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.
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"
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
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
;
40 return m_BspTree
->TraceRay(Start
, Ray
, 0.0, 1.0, cf::SceneGraph::ConsiderAll
, MaterialT::Clip_Radiance
);
45 inline double GetSqrDist(const ArrayT
<double>& A
, const ArrayT
<double>& B
)
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
];
59 // No need for sqrt().
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;
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
);
157 if (LargestDist
>=PrevLargestDist
)
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());
174 PrevLargestDist
=LargestDist
;
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
]));
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
);