00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #ifndef BVHStaticGeometryBuilder_hxx
00019 #define BVHStaticGeometryBuilder_hxx
00020
00021 #include <algorithm>
00022 #include <map>
00023 #include <set>
00024
00025 #include <simgear/structure/SGReferenced.hxx>
00026 #include <simgear/structure/SGSharedPtr.hxx>
00027
00028 #include "BVHVisitor.hxx"
00029 #include "BVHNode.hxx"
00030 #include "BVHGroup.hxx"
00031 #include "BVHTransform.hxx"
00032
00033 #include "BVHStaticData.hxx"
00034
00035 #include "BVHStaticNode.hxx"
00036 #include "BVHStaticLeaf.hxx"
00037 #include "BVHStaticTriangle.hxx"
00038 #include "BVHStaticBinary.hxx"
00039 #include "BVHStaticGeometry.hxx"
00040
00041 namespace simgear {
00042
00043 class BVHStaticGeometryBuilder : public SGReferenced {
00044 public:
00045 BVHStaticGeometryBuilder() :
00046 _staticData(new BVHStaticData),
00047 _currentMaterial(0),
00048 _currentMaterialIndex(~0u)
00049 { }
00050 virtual ~BVHStaticGeometryBuilder()
00051 { }
00052
00053 struct LeafRef {
00054 LeafRef(const BVHStaticLeaf* leaf, const BVHStaticData& data) :
00055 _leaf(leaf),
00056 _box(_leaf->computeBoundingBox(data)),
00057 _center(_leaf->computeCenter(data))
00058 { }
00059 SGSharedPtr<const BVHStaticLeaf> _leaf;
00060 SGBoxf _box;
00061 SGVec3f _center;
00062 };
00063 typedef std::list<LeafRef> LeafRefList;
00064
00065 struct LeafRefLess : public std::binary_function<LeafRef, LeafRef, bool> {
00066 LeafRefLess(unsigned sortAxis) : _sortAxis(sortAxis) {}
00067 bool operator()(const LeafRef& x, const LeafRef& y)
00068 { return x._center[_sortAxis] < y._center[_sortAxis]; }
00069 unsigned _sortAxis;
00070 };
00071
00072 SGSharedPtr<BVHStaticData> _staticData;
00073 LeafRefList _leafRefList;
00074
00075 typedef std::map<SGVec3f, unsigned> VertexMap;
00076 VertexMap _vertexMap;
00077
00078 typedef std::set<SGVec3<unsigned> > TriangleSet;
00079 TriangleSet _triangleSet;
00080
00081 void setCurrentMaterial(const SGMaterial* material)
00082 {
00083 _currentMaterial = material;
00084 _currentMaterialIndex = addMaterial(material);
00085 }
00086 const SGMaterial* getCurrentMaterial() const
00087 {
00088 return _currentMaterial;
00089 }
00090 unsigned addMaterial(const SGMaterial* material)
00091 {
00092 MaterialMap::const_iterator i = _materialMap.find(material);
00093 if (i != _materialMap.end())
00094 return i->second;
00095 unsigned index = _staticData->addMaterial(material);
00096 _materialMap[material] = index;
00097 return index;
00098 }
00099
00100 typedef std::map<const SGMaterial*, unsigned> MaterialMap;
00101 MaterialMap _materialMap;
00102 const SGMaterial* _currentMaterial;
00103 unsigned _currentMaterialIndex;
00104
00105 void addTriangle(const SGVec3f& v1, const SGVec3f& v2, const SGVec3f& v3)
00106 {
00107 unsigned indices[3] = { addVertex(v1), addVertex(v2), addVertex(v3) };
00108 std::sort(indices, indices + 3);
00109 SGVec3<unsigned> indexKey(indices);
00110 if (_triangleSet.find(indexKey) != _triangleSet.end())
00111 return;
00112 _triangleSet.insert(indexKey);
00113 BVHStaticTriangle* staticTriangle;
00114 staticTriangle = new BVHStaticTriangle(_currentMaterialIndex, indices);
00115 _leafRefList.push_back(LeafRef(staticTriangle, *_staticData));
00116 }
00117 unsigned addVertex(const SGVec3f& v)
00118 {
00119 VertexMap::const_iterator i = _vertexMap.find(v);
00120 if (i != _vertexMap.end())
00121 return i->second;
00122 unsigned index = _staticData->addVertex(v);
00123 _vertexMap[v] = index;
00124 return index;
00125 }
00126
00127 BVHStaticGeometry* buildTree()
00128 {
00129 const BVHStaticNode* tree = buildTreeRecursive(_leafRefList);
00130 if (!tree)
00131 return 0;
00132 _staticData->trim();
00133 return new BVHStaticGeometry(tree, _staticData);
00134 }
00135
00136 private:
00137 static void
00138 centerSplitLeafs(unsigned splitAxis, const double& splitValue,
00139 LeafRefList& leafs, LeafRefList split[2])
00140 {
00141 while (!leafs.empty()) {
00142 if (leafs.front()._center[splitAxis] < splitValue) {
00143 split[0].splice(split[0].begin(), leafs, leafs.begin());
00144 } else {
00145 split[1].splice(split[1].begin(), leafs, leafs.begin());
00146 }
00147 }
00148 }
00149
00150 static void
00151 equalSplitLeafs(unsigned splitAxis, LeafRefList& leafs,
00152 LeafRefList split[2])
00153 {
00154 leafs.sort(LeafRefLess(splitAxis));
00155 while (true) {
00156 if (leafs.empty())
00157 break;
00158 split[0].splice(split[0].begin(), leafs, leafs.begin());
00159
00160 if (leafs.empty())
00161 break;
00162 split[1].splice(split[1].begin(), leafs, --leafs.end());
00163 }
00164 }
00165
00166 static const BVHStaticNode* buildTreeRecursive(LeafRefList& leafs)
00167 {
00168
00169 if (leafs.empty())
00170 return 0;
00171
00172
00173 if (++leafs.begin() == leafs.end())
00174 return leafs.front()._leaf;
00175
00176 SGBoxf box;
00177 for (LeafRefList::const_iterator i = leafs.begin();
00178 i != leafs.end(); ++i)
00179 box.expandBy(i->_box);
00180
00181
00182
00183
00184
00185 if (box.empty())
00186 return 0;
00187
00188 unsigned splitAxis = box.getBroadestAxis();
00189 LeafRefList splitLeafs[2];
00190 double splitValue = box.getCenter()[splitAxis];
00191 centerSplitLeafs(splitAxis, splitValue, leafs, splitLeafs);
00192
00193 if (splitLeafs[0].empty() || splitLeafs[1].empty()) {
00194 for (unsigned i = 0; i < 3 ; ++i) {
00195 if (i == splitAxis)
00196 continue;
00197
00198 leafs.swap(splitLeafs[0]);
00199 leafs.splice(leafs.begin(), splitLeafs[1]);
00200 splitValue = box.getCenter()[i];
00201 centerSplitLeafs(i, splitValue, leafs, splitLeafs);
00202
00203 if (!splitLeafs[0].empty() && !splitLeafs[1].empty()) {
00204 splitAxis = i;
00205 break;
00206 }
00207 }
00208 }
00209 if (splitLeafs[0].empty() || splitLeafs[1].empty()) {
00210 leafs.swap(splitLeafs[0]);
00211 leafs.splice(leafs.begin(), splitLeafs[1]);
00212 equalSplitLeafs(splitAxis, leafs, splitLeafs);
00213 }
00214
00215 const BVHStaticNode* child0 = buildTreeRecursive(splitLeafs[0]);
00216 const BVHStaticNode* child1 = buildTreeRecursive(splitLeafs[1]);
00217 if (!child0)
00218 return child1;
00219 if (!child1)
00220 return child0;
00221
00222 return new BVHStaticBinary(splitAxis, child0, child1, box);
00223 }
00224 };
00225
00226 }
00227
00228 #endif