本文整理汇总了C++中ArrayT::PushBackEmpty方法的典型用法代码示例。如果您正苦于以下问题:C++ ArrayT::PushBackEmpty方法的具体用法?C++ ArrayT::PushBackEmpty怎么用?C++ ArrayT::PushBackEmpty使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类ArrayT
的用法示例。
在下文中一共展示了ArrayT::PushBackEmpty方法的10个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: GetFrameBuffer
uint32_t* SingleOpenGLWindowImplT::GetFrameBuffer(unsigned int& Width_, unsigned int& Height_)
{
static ArrayT<uint32_t> FrameBuffer;
FrameBuffer.Overwrite();
FrameBuffer.PushBackEmpty(Width*Height);
// Pixel vom BackBuffer in den FrameBuffer lesen.
// Beachte: Die ersten beiden Parameter (0, 0) spezifizieren die linke UNTERE Ecke des gewünschten Bereichs!
glReadPixels(0, 0, Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, &FrameBuffer[0]);
Width_ =Width;
Height_=Height;
// Wie oben schon erwähnt, steht der 'FrameBuffer' leider auf dem Kopf.
// Vertausche daher alle Zeilen (vertikale Spiegelung).
for (unsigned int y=0; y<Height_/2; y++)
{
uint32_t* UpperRow=&FrameBuffer[0]+ y *Width_;
uint32_t* LowerRow=&FrameBuffer[0]+(Height_-y-1)*Width_;
for (unsigned int x=0; x<Width_; x++)
{
const uint32_t Swap=*UpperRow;
*UpperRow=*LowerRow;
*LowerRow=Swap;
UpperRow++;
LowerRow++;
}
}
return &FrameBuffer[0];
}
示例2: if
template<class T> ArrayT< Polygon3T<T> > Polygon3T<T>::GetSplits(const Plane3T<T>& SplitPlane, const T HalfPlaneThickness) const
{
const unsigned long FRONT=0;
const unsigned long BACK =1;
ArrayT< Polygon3T<T> > Result;
Result.PushBackEmpty(2);
Result[FRONT].Plane=this->Plane;
Result[BACK ].Plane=this->Plane;
if (!Vertices.Size()) return Result;
Vector3T<T> LastVertex=Vertices[Vertices.Size()-1];
double LastDist =SplitPlane.GetDistance(LastVertex);
for (unsigned long VertexNr=0; VertexNr<Vertices.Size(); VertexNr++)
{
const Vector3T<T>& ThisVertex=Vertices[VertexNr];
const double ThisDist =SplitPlane.GetDistance(ThisVertex);
if (ThisDist>HalfPlaneThickness)
{
if (LastDist<-HalfPlaneThickness)
{
Vector3T<T> Intersection=SplitPlane.GetIntersection(LastVertex, ThisVertex, 0);
Result[BACK ].Vertices.PushBack(Intersection);
Result[FRONT].Vertices.PushBack(Intersection);
}
else if (LastDist<=HalfPlaneThickness) Result[FRONT].Vertices.PushBack(LastVertex);
Result[FRONT].Vertices.PushBack(ThisVertex);
}
else if (ThisDist<-HalfPlaneThickness)
{
if (LastDist>HalfPlaneThickness)
{
Vector3T<T> Intersection=SplitPlane.GetIntersection(LastVertex, ThisVertex, 0);
Result[FRONT].Vertices.PushBack(Intersection);
Result[BACK ].Vertices.PushBack(Intersection);
}
else if (LastDist>=-HalfPlaneThickness) Result[BACK].Vertices.PushBack(LastVertex);
Result[BACK].Vertices.PushBack(ThisVertex);
}
else
{
if (LastDist> HalfPlaneThickness) Result[FRONT].Vertices.PushBack(ThisVertex);
else if (LastDist<-HalfPlaneThickness) Result[BACK ].Vertices.PushBack(ThisVertex);
}
LastVertex=ThisVertex;
LastDist =ThisDist;
}
return Result;
}
示例3: CreateLeafPortals
void BspTreeBuilderT::CreateLeafPortals(unsigned long LeafNr, const ArrayT< Plane3T<double> >& NodeList)
{
ArrayT<cf::SceneGraph::BspTreeNodeT::LeafT>& Leaves=BspTree->Leaves;
Console->Print(cf::va("%5.1f%%\r", (double)LeafNr/Leaves.Size()*100.0));
// fflush(stdout); // The stdout console auto-flushes the output.
const BoundingBox3T<double> LeafBB=Leaves[LeafNr].BB.GetEpsilonBox(MapT::RoundEpsilon);
ArrayT< Polygon3T<double> > NewPortals;
for (unsigned long Nr=0; Nr<NodeList.Size(); Nr++)
if (LeafBB.WhatSide(NodeList[Nr])==BoundingBox3T<double>::Both)
{
NewPortals.PushBackEmpty();
NewPortals[NewPortals.Size()-1].Plane=NodeList[Nr];
}
// Hier ist auch denkbar, daß Portals mit 0 Vertices zurückkommen (outer leaves)!
// (Auch ganz normale gültige Portale in outer leaves sind denkbar!)
Polygon3T<double>::Complete(NewPortals, MapT::RoundEpsilon);
for (unsigned long PortalNr=0; PortalNr<NewPortals.Size(); PortalNr++)
{
const Polygon3T<double>& Portal=NewPortals[PortalNr];
// In degenerierten Grenzfällen (in Gegenwart von Splittern) können auch andere ungültige Polygone entstehen
// (z.B. mehrere Vertices quasi auf einer Edge), sodaß wir explizit die Gültigkeit prüfen.
// if (Portal.Vertices.Size()<3) continue; // Ist in .IsValid() enthalten!
if (!Portal.IsValid(MapT::RoundEpsilon, MapT::MinVertexDist)) continue;
// Another very serious problem is the fact that we sometimes self-create leaks,
// because nearly all operations in this program suffer from rounding errors.
// I have *NO* idea how to best combat them (except the introduction of exact arithmetic, which I'm seriously considering).
// But for now, lets try something simpler - enforce a "minimum area" for portals.
// Portals that are smaller than this minimum are considered degenerate, despite they were classified as valid above.
// Note that the same is enforced below, where portals are split along the leafs faces.
// UPDATE: As the new Polygon3T<double>::IsValid() method now enforces the MapT::MinVertexDist,
// I believe the problem is solved the the polygon area check not longer required.
if (Portal.GetArea()<=100.0 /* 1 cm^2 */) continue;
// Note that rejecting portals here (i.e. adding additional test criteria) is a dangerous idea,
// because any omitted portal might stop the subsequent flood-fill early.
// This in turn might easily tear big holes into the world.
// Consider my Tech-Archive notes from 2005-11-15 for a sketch that shows a problematic (but valid!) leaf
// whose entry portal must not be omitted so that it can be entered during the flood-fill,
// or else the left wall will be erroneously removed by the fill.
// Okay, the portal seems to be good, so add it to the leaf.
Leaves[LeafNr].Portals.PushBack(Portal.GetMirror());
}
}
示例4: ReduceSamplesTo
void CaptureStreamT::ReduceSamplesTo(unsigned int NumLeft)
{
const unsigned int NumNow=GetNumCaptureSamples();
if (NumNow>NumLeft)
{
ArrayT<unsigned char> Discard;
Discard.PushBackEmpty((NumNow-NumLeft)*BytesPerSample(m_FORMAT));
alcCaptureSamples(m_CaptureDevice, &Discard[0], NumNow-NumLeft);
}
}
示例5: ComputeSuperLeavesBBs
// This function computes for each SuperLeaf the bounding box over its 'SubPortals'.
// Such bounding boxes are useful when a SuperLeaf is considered in its role as a "target" SuperLeaf.
// The results are stored in the 'SuperLeavesBBs', which is assumed to be empty before this function is called.
// SuperLeaves that have no (sub-)portals (and thus, no neighbours), get the default bounding box assigned.
void ComputeSuperLeavesBBs()
{
for (unsigned long SL=0; SL<SuperLeaves.Size(); SL++)
{
SuperLeavesBBs.PushBackEmpty();
if (SuperLeaves[SL].Neighbours.Size()==0) continue;
SuperLeavesBBs[SL]=BoundingBox3T<double>(SuperLeaves[SL].Neighbours[0].SubPortal.Vertices);
for (unsigned long NeighbourNr=1; NeighbourNr<SuperLeaves[SL].Neighbours.Size(); NeighbourNr++)
SuperLeavesBBs[SL].Insert(SuperLeaves[SL].Neighbours[NeighbourNr].SubPortal.Vertices);
}
printf("SLs Bounding Boxes : done\n");
}
示例6: CanSeeFromAToB
// This functions determines if we can see from 'MasterSL' to 'TargetSL', that is, if 'TargetSL' is visible from 'MasterSL'.
// ATTENTION 1: IT IS ASSUMED THAT THE PVS FOR ALL SUPERLEAVES IN RANGE '0..MasterSL-1' HAS ALREADY BEEN ESTABLISHED!
// ATTENTION 2: THIS FUNCTION DOES NOT WORK IF 'MasterSL==TargetSL', OR 'TargetSL' IS AN IMMEDIATE NEIGHBOUR OF 'MasterSL'!
// If mutual visibility could be established, the result is recorded in 'SuperLeavesPVS', for both "from A to B" and "from B to A".
bool CanSeeFromAToB(unsigned long MasterSL, unsigned long TargetSL)
{
ArrayT<unsigned long> AncestorSLs;
AncestorSLs.PushBackEmpty(2);
// Für den alten Algorithmus war hier vermerkt, daß "outer leaves" keine Neighbours/Portals haben,
// wegen der Eigenschaften von Portalize() und FillInside() des CaBSP Programms.
// Der neue Algorithmus verwendet SuperLeaves, bei denen überhaupt nicht zwischen "inner" und "outer" unterschieden wird.
// Alles was zählt, sind die Portale. Deshalb setzen sich SuperLeaves korrekt aus beliebigen Leaves eines Sub-Trees zusammen.
for (unsigned long NeighbourNr=0; NeighbourNr<SuperLeaves[MasterSL].Neighbours.Size(); NeighbourNr++)
{
const unsigned long NeighbourSL =SuperLeaves[MasterSL].Neighbours[NeighbourNr].SuperLeafNr;
const Polygon3T<double>& MasterPortal=SuperLeaves[MasterSL].Neighbours[NeighbourNr].SubPortal;
// Wenn für das 'NeighbourSL' schon festgestellt wurde, daß das 'TargetSL' von dort aus nicht zu sehen ist,
// sparen wir uns die Mühe, es trotzdem zu versuchen, und machen direkt weiter.
if (NeighbourSL<MasterSL && !IsVisible(NeighbourSL, TargetSL)) continue;
AncestorSLs[0]=MasterSL;
AncestorSLs[1]=NeighbourSL;
for (unsigned long NNNr=0; NNNr<SuperLeaves[NeighbourSL].Neighbours.Size(); NNNr++)
{
const unsigned long NeighboursNeighbourSL=SuperLeaves[NeighbourSL].Neighbours[NNNr].SuperLeafNr;
const Polygon3T<double>& EnteringPortal =SuperLeaves[NeighbourSL].Neighbours[NNNr].SubPortal;
if (NeighboursNeighbourSL==MasterSL) continue;
const Polygon3T<double>::SideT Side=MasterPortal.WhatSide(EnteringPortal.Plane, MapT::RoundEpsilon);
if (Side==Polygon3T<double>::InIdentical || Side==Polygon3T<double>::InMirrored) continue;
// Wenn für das 'NeighboursNeighbourSL' schon festgestellt wurde, daß das 'TargetSL' von dort aus nicht zu sehen ist,
// sparen wir uns die Mühe, es trotzdem zu versuchen, und machen direkt weiter.
if (NeighboursNeighbourSL<MasterSL && !IsVisible(NeighboursNeighbourSL, TargetSL)) continue;
// Das TOLLE: Sobald wir festgestellt haben, daß "irgendeine" Sichtbarkeit von 'MasterSL' nach 'TargetSL' existiert,
// können wir sofort AUFHÖREN(!!!) und mit dem nächsten SuperLeaves-Paar weitermachen!
if (DetermineVisibility(NeighboursNeighbourSL, EnteringPortal, AncestorSLs, MasterPortal, TargetSL, SuperLeavesBBs[TargetSL])) return true;
}
}
return false;
}
示例7: SortFacesIntoTexNameOrder
// Diese Funktion sortiert die Faces anhand ihres Texture-Namens in aufsteigender Reihenfolge.
// Dank Z-Buffering kann die Engine damit die Faces in dieser Reihenfolge mit einem Minimum von State-Changes rendern.
// Da außerdem die LightMaps der Faces in dieser Reihenfolge in die größeren LightMaps einsortiert werden
// (CreateFullBrightLightMaps()), erhalten wir den selben positiven Effekt auch für die LightMaps!
void BspTreeBuilderT::SortFacesIntoTexNameOrder()
{
if (FaceChildren.Size()==0) return;
Console->Print(cf::va("\n%-50s %s\n", "*** Sort Faces ***", GetTimeSinceProgramStart()));
FaceNrs.Clear();
for (unsigned long FaceNr=0; FaceNr<FaceChildren.Size(); FaceNr++) FaceNrs.PushBack(FaceNr);
// QuickSort Faces according to their texture name.
ToDoRanges.Clear();
ToDoRanges.PushBack(0);
ToDoRanges.PushBack(FaceChildren.Size()-1);
QuickSortFacesIntoTexNameOrder();
// Verify sorting.
for (unsigned long FaceNr=0; FaceNr+1<FaceChildren.Size(); FaceNr++)
if (_stricmp(FaceChildren[FaceNr]->Material->Name.c_str(), FaceChildren[FaceNr+1]->Material->Name.c_str())>0) Error("Bad sorting!");
// Wir wissen nun, daß an Stelle der Face i nun die Face FaceNrs[i] steht, wollen aber wissen, an welcher
// Stelle nun die i-te Face steht. Führe dazu das RevFaceNrs-Array ein und fülle es entsprechend aus.
ArrayT<unsigned long> RevFaceNrs;
RevFaceNrs.PushBackEmpty(FaceChildren.Size());
for (unsigned long FaceNr=0; FaceNr<FaceChildren.Size(); FaceNr++) RevFaceNrs[FaceNrs[FaceNr]]=FaceNr;
// Korrigiere damit die FaceSets der Leaves.
ArrayT<cf::SceneGraph::BspTreeNodeT::LeafT>& Leaves=BspTree->Leaves;
for (unsigned long LeafNr=0; LeafNr<Leaves.Size(); LeafNr++)
for (unsigned long FaceNr=0; FaceNr<Leaves[LeafNr].FaceChildrenSet.Size(); FaceNr++)
Leaves[LeafNr].FaceChildrenSet[FaceNr]=RevFaceNrs[Leaves[LeafNr].FaceChildrenSet[FaceNr]];
Console->Print("done\n");
}
示例8: main
//.........这里部分代码省略.........
printf("Unknown option '%s'.\n", ArgV[ArgNr]);
Usage();
}
}
std::string GameDirectory=ArgV[1];
// Determine the game directory, cleverly assuming that the destination file is in "Worlds".
{
// Strip the file name and extention off.
size_t i=GameDirectory.find_last_of("/\\");
GameDirectory=GameDirectory.substr(0, i==std::string::npos ? 0 : i)+"/..";
}
// Setup the global MaterialManager pointer.
static MaterialManagerImplT MatManImpl;
MaterialManager=&MatManImpl;
if (MaterialManager->RegisterMaterialScriptsInDir(GameDirectory+"/Materials", GameDirectory+"/").Size()==0)
{
printf("\nNo materials found in scripts in \"%s/Materials\".\n", GameDirectory.c_str());
printf("No materials found.\n\n");
Usage();
}
try
{
// General note: Robustness against the 'sharp wedge' problem is granted:
// DetermineAdjacencyGraph() is the only place where PolygonOverlap() is called, but only once on *input* portals.
// Everywhere else (especially in BuildPVS() and its sub-functions), only PolygonSplit() and PolygonWhatSide() are called.
printf("*** Load World %s ***\n", ArgV[1]);
// 1. Load the 'CaPVSWorld'.
ModelManagerT ModelMan;
CaPVSWorldT* CaPVSWorld=new CaPVSWorldT(ArgV[1], ModelMan, MaxRecDepthSL, MinAreaSL);
// 2. Create the 'SuperLeaves'.
CaPVSWorld->CreateSuperLeaves(SuperLeaves);
if (OnlySuperLeaves) return 0;
// 3. Determine the adjacency graph.
// This completely fills-in the remaining components of the 'SuperLeaves'.
printf("\n%-50s %s\n", "*** Initialize ***", GetTimeSinceProgramStart());
DetermineAdjacencyGraph();
// 4. Compute for each SuperLeaf the bounding box over its (sub-)portals.
ComputeSuperLeavesBBs();
// 5. Create and initialize the 'SuperLeavesPVS' (reset to complete blindness (all 0s)).
SuperLeavesPVS.PushBackEmpty((SuperLeaves.Size()*SuperLeaves.Size()+31)/32);
for (unsigned long Vis=0; Vis<SuperLeavesPVS.Size(); Vis++) SuperLeavesPVS[Vis]=0;
// 6. For each SuperLeaf, flag itself and the immediate neighbours as visible.
DetermineTrivialVisibility();
// 7. Do some simple ray tests in order to quickly obtain a good estimation of the actual PVS.
// Note that calling this function is ENTIRELY OPTIONAL, and the call can be omitted without danger!
// (The latter might e.g. be useful for debugging.)
DetermineRayPresampledVisibility(CaPVSWorld);
// 8. Finally calculate the 'SuperLeavesPVS' using analytical methods.
printf("\n%-50s %s\n", "*** Potentially Visibility Set ***", GetTimeSinceProgramStart());
BuildPVS();
// 9. Carry the information in 'SuperLeavesPVS' into the PVS of the 'CaPVSWorld'.
CaPVSWorld->StorePVS(SuperLeaves, SuperLeavesPVS);
// 10. Print some statistics and obtain a checksum.
unsigned long CheckSum=CaPVSWorld->GetChecksumAndPrintStats();
// 11. Save the 'CaPVSWorld' back to disk.
printf("\n%-50s %s\n", "*** Save World ***", GetTimeSinceProgramStart());
printf("%s\n", ArgV[1]);
CaPVSWorld->SaveToDisk(ArgV[1]);
// 12. Clean-up and write log file entry.
delete CaPVSWorld;
WriteLogFileEntry(ArgV[1], CheckSum);
printf("\n%-50s %s\n", "COMPLETED.", GetTimeSinceProgramStart());
}
catch (const WorldT::LoadErrorT& E)
{
printf("\nFATAL ERROR: %s\n", E.Msg);
printf("Program aborted.\n\n");
exit(1);
}
catch (const WorldT::SaveErrorT& E)
{
printf("\nFATAL ERROR: %s\n", E.Msg);
printf("Program aborted.\n\n");
exit(1);
}
return 0;
}
示例9: DetermineRayPresampledVisibility
// Determines a simple pre-PVS by sampling "random" rays (and stores it in 'SuperLeavesPVS').
// The result is a subset of the analytically determined, conservative, "exact" PVS.
// This function does not handle the fact that SuperLeaves can see themselves.
// Thus, calling 'DetermineTrivialVisibility()' before (or after) calling this function is required.
void DetermineRayPresampledVisibility(const CaPVSWorldT* CaPVSWorld)
{
ArrayT< ArrayT<VectorT> > SuperLeavesCenters;
ArrayT< ArrayT<bool > > SuperLeavesCenterIsValid;
for (unsigned long SL=0; SL<SuperLeaves.Size(); SL++)
{
SuperLeavesCenters .PushBackEmpty();
SuperLeavesCenterIsValid.PushBackEmpty();
for (unsigned long NbNr=0; NbNr<SuperLeaves[SL].Neighbours.Size(); NbNr++)
{
const Polygon3T<double>& SubPortal=SuperLeaves[SL].Neighbours[NbNr].SubPortal;
VectorT Center =SubPortal.Vertices[0];
for (unsigned long VertexNr=1; VertexNr<SubPortal.Vertices.Size(); VertexNr++) Center=Center+SubPortal.Vertices[VertexNr];
Center=scale(Center, 1.0/double(SubPortal.Vertices.Size()))+scale(SubPortal.Plane.Normal, 0.2);
// Not really necessary, but add a little check to see if everything is in order.
// (Or, more precisely, assert that the 'Center' is really "inside" the SuperLeaf.)
const unsigned long LeafNr=CaPVSWorld->WhatLeaf(Center);
unsigned long LeafSetNr;
for (LeafSetNr=0; LeafSetNr<SuperLeaves[SL].LeafSet.Size(); LeafSetNr++)
if (LeafNr==SuperLeaves[SL].LeafSet[LeafSetNr]) break;
SuperLeavesCenters [SL].PushBack(Center);
SuperLeavesCenterIsValid[SL].PushBack(LeafSetNr<SuperLeaves[SL].LeafSet.Size());
// if (LeafSetNr>=SuperLeaves[SL1].LeafSet.Size()) printf("WARNING: Center not in its SuperLeaf. TODO: Print more extensive diagnostics.\n");
}
}
for (unsigned long SL1=0; SL1+1<SuperLeaves.Size(); SL1++)
{
printf("%5.1f%%\r", (double)SL1/SuperLeaves.Size()*100.0);
fflush(stdout);
for (unsigned long SL2=SL1+1; SL2<SuperLeaves.Size(); SL2++)
{
if (IsVisible(SL1, SL2)) continue;
for (unsigned long Nb1Nr=0; Nb1Nr<SuperLeaves[SL1].Neighbours.Size(); Nb1Nr++)
{
if (!SuperLeavesCenterIsValid[SL1][Nb1Nr]) continue;
for (unsigned long Nb2Nr=0; Nb2Nr<SuperLeaves[SL2].Neighbours.Size(); Nb2Nr++)
{
if (!SuperLeavesCenterIsValid[SL2][Nb2Nr]) continue;
const VectorT& Center1=SuperLeavesCenters[SL1][Nb1Nr];
const VectorT& Center2=SuperLeavesCenters[SL2][Nb2Nr];
// This ClipLine() only considers faces, but not BPs, terrains, etc.
if (CaPVSWorld->ClipLine(Center1, Center2-Center1)==1.0)
{
FlagVisible(SL1, SL2);
FlagVisible(SL2, SL1);
goto DoneWithSL2;
}
}
}
DoneWithSL2:;
}
}
printf("Estimated PVS : %10.5f\n", GetAverageVisibility());
}
示例10: CreatePatchMeshes
void FaceNodeT::CreatePatchMeshes(ArrayT<cf::PatchMeshT>& PatchMeshes, ArrayT< ArrayT< ArrayT<Vector3dT> > >& SampleCoords) const
{
if (LightMapInfo.SizeS==0) return;
if (LightMapInfo.SizeT==0) return;
if (Polygon.Vertices.Size()<3) return;
// A FaceNodeT creates excatly one patch mesh - namely the one that covers it.
PatchMeshes.PushBackEmpty();
SampleCoords.PushBackEmpty();
PatchMeshT& PatchMesh=PatchMeshes[PatchMeshes.Size()-1];
// Fill-in basic data.
PatchMesh.Width =LightMapInfo.SizeS;
PatchMesh.Height=LightMapInfo.SizeT;
PatchMesh.Patches.PushBackEmpty(PatchMesh.Width*PatchMesh.Height);
PatchMesh.WrapsHorz=false;
PatchMesh.WrapsVert=false;
PatchMesh.Node =this;
PatchMesh.Material=Material;
SampleCoords[0].PushBackEmpty(PatchMesh.Width*PatchMesh.Height);
// Compute the details for each patch.
// Dieser Code ist sehr ähnlich zu dem Code in CaLights PostProcessBorders() Funktion!
// Änderungen hier könnten Änderungen in dieser Funktion erforderlich machen!
// Bestimme die Spannvektoren.
VectorT U;
VectorT V;
Polygon.Plane.GetSpanVectors(U, V);
// Finde SmallestU und SmallestV.
double SmallestU=dot(Polygon.Vertices[0], U);
double SmallestV=dot(Polygon.Vertices[0], V);
for (unsigned long VertexNr=1; VertexNr<Polygon.Vertices.Size(); VertexNr++)
{
double u=dot(Polygon.Vertices[VertexNr], U);
double v=dot(Polygon.Vertices[VertexNr], V);
if (u<SmallestU) SmallestU=u;
if (v<SmallestV) SmallestV=v;
}
// Bereite folgende Schleife vor.
const VectorT UV_Origin=scale(Polygon.Plane.Normal, Polygon.Plane.Dist);
const VectorT Safety =scale(Polygon.Plane.Normal, 0.1);
Polygon3T<double> PatchPoly;
PatchPoly.Plane=dot(Polygon.Plane.Normal, cross(U, V))<0 ? Polygon.Plane : Polygon.Plane.GetMirror();
// Nun betrachte alle Patches.
for (unsigned long t=0; t<PatchMesh.Height; t++)
for (unsigned long s=0; s<PatchMesh.Width; s++)
{
const double PATCH_SIZE=cf::SceneGraph::FaceNodeT::LightMapInfoT::PatchSize;
cf::PatchT& Patch =PatchMesh.Patches[t*PatchMesh.Width+s];
Patch.Coord =VectorT(0, 0, 0);
Patch.Normal =Polygon.Plane.Normal;
Patch.Area =PATCH_SIZE*PATCH_SIZE;
Patch.InsideFace=false;
// Also assign an initial, non-zero "Where comes the energy from?"-direction.
// The value (==length) has been chosen entirely arbitrary with the accumulative nature of the computations in CaLight
// in mind, and in the hope to pick a reasonable value.
// (However, tests seem to indicate the smaller values are better. I tried 0.3 first, then 0.05.)
Patch.EnergyFromDir=Patch.Normal*0.02;
const double s_=s;
const double t_=t;
PatchPoly.Vertices.Clear();
PatchPoly.Vertices.PushBack(UV_Origin+scale(U, SmallestU+(s_-1.0)*PATCH_SIZE)+scale(V, SmallestV+(t_-1.0)*PATCH_SIZE));
PatchPoly.Vertices.PushBack(UV_Origin+scale(U, SmallestU+ s_ *PATCH_SIZE)+scale(V, SmallestV+(t_-1.0)*PATCH_SIZE));
PatchPoly.Vertices.PushBack(UV_Origin+scale(U, SmallestU+ s_ *PATCH_SIZE)+scale(V, SmallestV+ t_ *PATCH_SIZE));
PatchPoly.Vertices.PushBack(UV_Origin+scale(U, SmallestU+(s_-1.0)*PATCH_SIZE)+scale(V, SmallestV+ t_ *PATCH_SIZE));
assert(fabs(PatchPoly.GetArea()-Patch.Area)<1.0); // This is just to make sure there is no logic error in area computation.
if (!Polygon.Overlaps(PatchPoly, false, ROUND_EPSILON)) continue;
if (!Polygon.Encloses(PatchPoly, true, ROUND_EPSILON))
{
ArrayT< Polygon3T<double> > NewPolygons;
PatchPoly.GetChoppedUpAlong(Polygon, ROUND_EPSILON, NewPolygons);
if (NewPolygons.Size()>0 && NewPolygons[NewPolygons.Size()-1].Vertices.Size()>0)
{
PatchPoly=NewPolygons[NewPolygons.Size()-1];
}
else
{
//.........这里部分代码省略.........