Fix issue in Rocket.lua script.
[Cafu-Engine.git] / CaSHL / CaSHLWorld.cpp
blobbeef296033ab3eb3f4e64738f8dc590e9b387289
1 /*
2 Cafu Engine, http://www.cafu.de/
3 Copyright (c) Carsten Fuchs and other contributors.
4 This project is licensed under the terms of the MIT license.
5 */
7 /**************************/
8 /*** CaSHL World (Code) ***/
9 /**************************/
11 #include "CaSHLWorld.hpp"
12 #include "ClipSys/CollisionModel_static.hpp"
13 #include "ClipSys/TraceResult.hpp"
14 #include "ClipSys/TraceSolid.hpp"
15 #include "MaterialSystem/Material.hpp"
16 #include "SceneGraph/BspTreeNode.hpp"
17 #include "SceneGraph/FaceNode.hpp"
19 #include <stdio.h>
22 CaSHLWorldT::CaSHLWorldT(const char* FileName, ModelManagerT& ModelMan, cf::GuiSys::GuiResourcesT& GuiRes)
23 : m_World(FileName, ModelMan, GuiRes),
24 m_BspTree(m_World.m_StaticEntityData[0]->m_BspTree),
25 m_CollModel(m_World.m_StaticEntityData[0]->m_CollModel)
30 double CaSHLWorldT::TraceRay(const Vector3dT& Start, const Vector3dT& Ray) const
32 #if 1
33 const static cf::ClipSys::TracePointT Point;
34 cf::ClipSys::TraceResultT Result(1.0);
36 m_CollModel->TraceConvexSolid(Point, Start, Ray, MaterialT::Clip_Radiance, Result);
38 return Result.Fraction;
39 #else
40 return m_BspTree->TraceRay(Start, Ray, 0.0, 1.0, cf::SceneGraph::ConsiderAll, MaterialT::Clip_Radiance);
41 #endif
45 inline double GetSqrDist(const ArrayT<double>& A, const ArrayT<double>& B)
47 double Dist=0.0;
49 // if (A.Size()!=16) printf("A.Size()!=16 !!!!!!!!!!!!!!!!!!!!!!!!!\n");
50 // if (B.Size()!=16) printf("B.Size()!=16 !!!!!!!!!!!!!!!!!!!!!!!!!\n");
52 for (unsigned long i=0; i<A.Size(); i++)
54 const double d=B[i]-A[i];
56 Dist+=d*d;
59 // No need for sqrt().
60 return Dist;
64 void CaSHLWorldT::PatchesToSHLMaps(const ArrayT< ArrayT<PatchT> >& Patches)
66 const cf::SceneGraph::BspTreeNodeT& Map = *m_BspTree;
68 // Clear everything - the code below will fill in the new data.
69 for (unsigned long SHLMapNr = 0; SHLMapNr < m_World.SHLMapMan.SHLMaps.Size(); SHLMapNr++)
71 m_World.SHLMapMan.SHLMaps[SHLMapNr]->Coeffs .Clear();
72 m_World.SHLMapMan.SHLMaps[SHLMapNr]->Indices.Clear();
75 m_World.SHLMapMan.SHLCoeffsTable.Clear();
78 // Proceed depending on whether the data is to be stored compressed or not.
79 if (cf::SceneGraph::SHLMapManT::NrOfRepres>0)
81 // Compress the SHL coeffs by some representatives.
83 // Start by gathering all SHL vectors in one big list.
84 ArrayT< const ArrayT<double>* > AllVectors;
87 for (unsigned long FaceNr=0; FaceNr<Map.FaceChildren.Size(); FaceNr++)
89 const cf::SceneGraph::FaceNodeT::SHLMapInfoT& SMI=Map.FaceChildren[FaceNr]->SHLMapInfo;
91 for (unsigned long t=0; t<SMI.SizeT; t++)
92 for (unsigned long s=0; s<SMI.SizeS; s++)
93 AllVectors.PushBack(&(Patches[FaceNr][t*SMI.SizeS+s].SHCoeffs_TotalTransfer));
97 if (cf::SceneGraph::SHLMapManT::NrOfRepres>AllVectors.Size()) cf::SceneGraph::SHLMapManT::NrOfRepres=AllVectors.Size();
100 // Now pick an initial set of representatives from the complete list, approximately in an even distribution.
101 ArrayT< ArrayT<double> > Representatives;
104 for (unsigned long RepNr=0; RepNr<cf::SceneGraph::SHLMapManT::NrOfRepres; RepNr++)
105 Representatives.PushBack(*(AllVectors[RepNr*(AllVectors.Size()/cf::SceneGraph::SHLMapManT::NrOfRepres)]));
109 // Also maintain a list that states the best (nearest) representative for each vector.
110 ArrayT<unsigned long> BestRepForVector;
112 BestRepForVector.PushBackEmpty(AllVectors.Size());
115 // Iterate until the optimal solution is found.
116 double PrevLargestDist=1000.0;
117 char TriesLeft =3;
119 for (unsigned long IterationCounter=0; true; IterationCounter++)
121 // Create an array of clusters (one cluster for each representative),
122 // where each cluster is an array of (pointers to) vectors (those in AllVectors whose closest representative is this one).
123 ArrayT< ArrayT< const ArrayT<double>* > > RepClusters;
125 RepClusters.PushBackEmpty(Representatives.Size());
128 // For each vector in AllVectors, figure out the representative that it is closest to,
129 // and then assign this vector to (the cluster of) this representative.
130 double LargestDist=0.0;
132 for (unsigned long VectorNr=0; VectorNr<AllVectors.Size(); VectorNr++)
134 unsigned long ClosestRepNr =0;
135 double ClosestRepDist=GetSqrDist(*(AllVectors[VectorNr]), Representatives[0]);
137 for (unsigned long CurrentRepNr=1; CurrentRepNr<Representatives.Size(); CurrentRepNr++)
139 const double CurrentRepDist=GetSqrDist(*(AllVectors[VectorNr]), Representatives[CurrentRepNr]);
141 if (CurrentRepDist<ClosestRepDist)
143 ClosestRepNr =CurrentRepNr;
144 ClosestRepDist=CurrentRepDist;
148 RepClusters[ClosestRepNr].PushBack(AllVectors[VectorNr]);
149 BestRepForVector[VectorNr]=ClosestRepNr; // Also do the opposite assignment: Save for the current vector its closest representative.
151 if (LargestDist<ClosestRepDist) LargestDist=ClosestRepDist;
154 printf("%lu %.15f\r", IterationCounter, LargestDist);
155 fflush(stdout);
157 if (LargestDist>=PrevLargestDist)
159 TriesLeft--;
161 if (TriesLeft==0)
163 unsigned long UnusedCount=0;
165 for (unsigned long RepNr=0; RepNr<Representatives.Size(); RepNr++)
166 if (RepClusters[RepNr].Size()==0) UnusedCount++;
168 printf("Almost done. %lu of %lu representatives unused.\n", UnusedCount, Representatives.Size());
169 break;
172 else
174 PrevLargestDist=LargestDist;
175 TriesLeft=3;
179 // Finally re-determine each representative to become the average of its cluster contents.
180 for (unsigned long RepNr=0; RepNr<Representatives.Size(); RepNr++)
182 if (RepClusters[RepNr].Size()==0) continue;
184 // Clear the representative vector.
185 for (unsigned long CoeffNr=0; CoeffNr<Representatives[RepNr].Size(); CoeffNr++)
186 Representatives[RepNr][CoeffNr]=0.0;
188 // Sum up the vectors in the cluster.
189 for (unsigned long ClusterVecNr=0; ClusterVecNr<RepClusters[RepNr].Size(); ClusterVecNr++)
190 for (unsigned long CoeffNr=0; CoeffNr<Representatives[RepNr].Size(); CoeffNr++)
191 Representatives[RepNr][CoeffNr]+=(*(RepClusters[RepNr][ClusterVecNr]))[CoeffNr];
193 // Compute the average.
194 for (unsigned long CoeffNr=0; CoeffNr<Representatives[RepNr].Size(); CoeffNr++)
195 Representatives[RepNr][CoeffNr]/=double(RepClusters[RepNr].Size());
200 // Allocate space for the indices.
201 for (unsigned long SHLMapNr = 0; SHLMapNr < m_World.SHLMapMan.SHLMaps.Size(); SHLMapNr++)
203 // Make sure that all indices are initialized to zero.
204 while (m_World.SHLMapMan.SHLMaps[SHLMapNr]->Indices.Size() < (unsigned long)cf::SceneGraph::SHLMapManT::SIZE_S * cf::SceneGraph::SHLMapManT::SIZE_T)
205 m_World.SHLMapMan.SHLMaps[SHLMapNr]->Indices.PushBack(0);
209 // Fill in the indices to the best representatives for each vector.
210 unsigned long VectorNr=0;
212 for (unsigned long FaceNr=0; FaceNr<Map.FaceChildren.Size(); FaceNr++)
214 const cf::SceneGraph::FaceNodeT::SHLMapInfoT& SMI=Map.FaceChildren[FaceNr]->SHLMapInfo;
216 for (unsigned long t=0; t<SMI.SizeT; t++)
217 for (unsigned long s=0; s<SMI.SizeS; s++)
218 m_World.SHLMapMan.SHLMaps[SMI.SHLMapNr]->Indices[(SMI.PosT+t) * cf::SceneGraph::SHLMapManT::SIZE_S+SMI.PosS+s] = (unsigned short)BestRepForVector[VectorNr++];
222 // Finally, write the representatives into the SHLCoeffsTable.
223 for (unsigned long RepNr=0; RepNr<Representatives.Size(); RepNr++)
224 for (unsigned long CoeffNr=0; CoeffNr<Representatives[RepNr].Size(); CoeffNr++)
225 m_World.SHLMapMan.SHLCoeffsTable.PushBack(float(Representatives[RepNr][CoeffNr]));
227 else
229 // Store the SHL coeffs uncompressed.
230 const unsigned long NR_OF_SH_COEFFS=cf::SceneGraph::SHLMapManT::NrOfBands * cf::SceneGraph::SHLMapManT::NrOfBands;
232 for (unsigned long SHLMapNr = 0; SHLMapNr < m_World.SHLMapMan.SHLMaps.Size(); SHLMapNr++)
234 const unsigned long SHLMapCoeffSize = cf::SceneGraph::SHLMapManT::SIZE_S * cf::SceneGraph::SHLMapManT::SIZE_T * NR_OF_SH_COEFFS;
236 // Make sure that all coefficients are initialized with zeros.
237 while (m_World.SHLMapMan.SHLMaps[SHLMapNr]->Coeffs.Size() < SHLMapCoeffSize)
238 m_World.SHLMapMan.SHLMaps[SHLMapNr]->Coeffs.PushBack(0.0);
241 // Übertrage die Patches-Werte zurück in die SHLMaps.
242 for (unsigned long FaceNr=0; FaceNr<Map.FaceChildren.Size(); FaceNr++)
244 const cf::SceneGraph::FaceNodeT::SHLMapInfoT& SMI=Map.FaceChildren[FaceNr]->SHLMapInfo;
246 for (unsigned long t=0; t<SMI.SizeT; t++)
247 for (unsigned long s=0; s<SMI.SizeS; s++)
248 for (unsigned long CoeffNr=0; CoeffNr<NR_OF_SH_COEFFS; CoeffNr++)
249 m_World.SHLMapMan.SHLMaps[SMI.SHLMapNr]->Coeffs[((SMI.PosT+t)*cf::SceneGraph::SHLMapManT::SIZE_S + SMI.PosS + s) * NR_OF_SH_COEFFS + CoeffNr]
250 = float(Patches[FaceNr][t*SMI.SizeS + s].SHCoeffs_TotalTransfer[CoeffNr]);
256 void CaSHLWorldT::SaveToDisk(const char* FileName) const
258 m_World.SaveToDisk(FileName);