Changeset 448 for trunk/VUT/GtpVisibilityPreprocessor
- Timestamp:
- 12/05/05 04:42:54 (19 years ago)
- Location:
- trunk/VUT/GtpVisibilityPreprocessor
- Files:
-
- 30 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/VUT/GtpVisibilityPreprocessor/scripts/Preprocessor.vcproj
r439 r448 255 255 </File> 256 256 <File 257 RelativePath="..\src\RssPreprocessor.cpp"> 258 </File> 259 <File 260 RelativePath="..\src\RssPreprocessor.h"> 261 </File> 262 <File 263 RelativePath="..\src\RssTree.cpp"> 264 </File> 265 <File 266 RelativePath="..\src\RssTree.h"> 267 </File> 268 <File 257 269 RelativePath="..\src\SamplingPreprocessor.cpp"> 258 270 </File> -
trunk/VUT/GtpVisibilityPreprocessor/scripts/default.env
r445 r448 19 19 20 20 Preprocessor { 21 type sampling22 #type vss21 # type sampling 22 type vss 23 23 } 24 24 … … 94 94 95 95 Sampling { 96 totalSamples 60000096 totalSamples 300000 97 97 samplesPerPass 3 98 98 } … … 101 101 loadFromFile false 102 102 #type kdTree 103 #type vspTree103 type vspKdTree 104 104 #type bspTree 105 type vspBspTree105 #type vspBspTree 106 106 107 107 #type sceneDependent … … 131 131 BspTree { 132 132 Construction { 133 samples 200000134 sideTolerance0.005133 samples 50000 134 epsilon 0.005 135 135 } 136 136 … … 193 193 minRays 200 194 194 minPolygons -1 195 maxDepth 50195 maxDepth 40 196 196 minPvs 100 197 197 minArea 0.01 … … 256 256 257 257 Construction { 258 samples 500000258 samples 100000 259 259 } 260 260 … … 278 278 VspBspTree { 279 279 Construction { 280 samples 200000281 sideTolerance0.005280 samples 100000 281 epsilon 0.005 282 282 } 283 283 … … 309 309 minRays 200 310 310 minPolygons -1 311 maxDepth 50311 maxDepth 40 312 312 minPvs 100 313 313 minArea 0.01 -
trunk/VUT/GtpVisibilityPreprocessor/src/AxisAlignedBox3.cpp
r372 r448 1662 1662 1663 1663 // TODO: use a table to avoid normal and distance computations 1664 Polygon3 *AxisAlignedBox3::CrossSection(const Plane3 &plane) 1664 Polygon3 *AxisAlignedBox3::CrossSection(const Plane3 &plane) const 1665 1665 { 1666 1666 Polygon3 *planePoly = new Polygon3(); … … 1746 1746 return planePoly; 1747 1747 } 1748 1749 bool AxisAlignedBox3::GetRaySegment(const Ray &ray, 1750 float &minT, 1751 float &maxT) const 1752 { 1753 maxT = 1e6; 1754 minT = 0; 1755 1756 // test with bounding box 1757 if (!GetMinMaxT(ray, &minT, &maxT)) 1758 return false; 1759 1760 if (minT < 0) // start ray from origin 1761 minT = 0; 1762 1763 // bound ray or line segment 1764 if (//(ray.GetType() == Ray::LOCAL_RAY) && 1765 !ray.intersections.empty() && 1766 (ray.intersections[0].mT <= maxT)) 1767 { 1768 maxT = ray.intersections[0].mT; 1769 } 1770 1771 return true; 1772 } -
trunk/VUT/GtpVisibilityPreprocessor/src/AxisAlignedBox3.h
r387 r448 312 312 @returns the cross section 313 313 */ 314 Polygon3 *CrossSection(const Plane3 &plane); 314 Polygon3 *CrossSection(const Plane3 &plane) const; 315 316 /** Computes minimal and maximal t of ray, including the object intersections. 317 @returns true if ray hits the bounding box. 318 */ 319 bool GetRaySegment(const Ray &ray, 320 float &minT, 321 float &maxT) const; 315 322 316 323 #define __EXTENT_HACK -
trunk/VUT/GtpVisibilityPreprocessor/src/Environment.cpp
r446 r448 1269 1269 "100000"); 1270 1270 1271 RegisterOption("BspTree.Construction. sideTolerance",1271 RegisterOption("BspTree.Construction.epsilon", 1272 1272 optFloat, 1273 1273 "-bsp_construction_side_tolerance=", … … 1732 1732 "false"); 1733 1733 1734 RegisterOption("VspBspTree.Factor.leastRaySplits", optFloat, "-vsp_bsp_factor_least_ray_splits=", "1.0"); 1735 RegisterOption("VspBspTree.Factor.balancedRays", optFloat, "-vsp_bsp_factor_balanced_rays=", "1.0"); 1736 RegisterOption("VspBspTree.Factor.pvs", optFloat, "-vsp_bsp_factor_pvs=", "1.0"); 1734 RegisterOption("VspBspTree.Construction.samples", 1735 optInt, 1736 "-bsp_construction_samples=", 1737 "100000"); 1738 1739 RegisterOption("VspBspTree.Construction.epsilon", 1740 optFloat, 1741 "-vsp_bsp_construction_side_tolerance=", 1742 "0.002"); 1743 1744 RegisterOption("VspBspTree.Factor.leastRaySplits", optFloat, "-vsp_bsp_factor_least_ray_splits=", "1.0"); 1745 RegisterOption("VspBspTree.Factor.balancedRays", optFloat, "-vsp_bsp_factor_balanced_rays=", "1.0"); 1746 RegisterOption("VspBspTree.Factor.pvs", optFloat, "-vsp_bsp_factor_pvs=", "1.0"); 1737 1747 1738 1748 ////////////////////////////////////////////////////////////////////////////////// -
trunk/VUT/GtpVisibilityPreprocessor/src/Exporter.h
r446 r448 20 20 class Polygon3; 21 21 class VssTree; 22 class VspBspTree; 22 23 class RssTree; 23 24 … … 44 45 virtual bool ExportScene(SceneGraphNode *node) = 0; 45 46 46 47 47 virtual bool 48 48 ExportBox(const AxisAlignedBox3 &box) = 0; … … 56 56 virtual bool 57 57 ExportVssTree2(const VssTree &tree, 58 const Vector3 direction59 ) = 0;60 61 virtual bool62 ExportRssTree2(const RssTree &tree,63 58 const Vector3 direction 64 59 ) = 0; … … 98 93 virtual void 99 94 ExportBspSplits(const BspTree &tree, const bool exportDepth = false) = 0; 95 100 96 virtual void 101 97 ExportLeavesGeometry(const BspTree &tree, const vector<BspLeaf *> &leaves) = 0; 102 98 99 virtual void 100 ExportBspSplits(const VspBspTree &tree, const bool exportDepth = false) = 0; 101 102 virtual void 103 ExportBspViewCellPartition(const VspBspTree &tree, const int maxPvs = 0) = 0; 104 103 105 virtual void 104 106 ExportPolygons(const PolygonContainer &polys) = 0; … … 112 114 virtual void 113 115 ExportGeometry(const ObjectContainer &objects) = 0; 116 117 virtual bool 118 ExportRssTree2(const RssTree &tree, 119 const Vector3 direction) = 0; 114 120 115 121 void SetExportRayDensity(const bool d) { mExportRayDensity = d; } -
trunk/VUT/GtpVisibilityPreprocessor/src/Plane3.h
r437 r448 51 51 */ 52 52 Vector3 FindIntersection(const Vector3 &a, 53 const Vector3 &b, 54 float *t = NULL, 55 bool *coplanar = NULL 56 ) const 53 const Vector3 &b, 54 float *t = NULL, 55 bool *coplanar = NULL) const 57 56 { 58 57 const Vector3 v = b - a; // line from A to B -
trunk/VUT/GtpVisibilityPreprocessor/src/Polygon3.cpp
r436 r448 42 42 void Polygon3::Split(const Plane3 &partition, 43 43 Polygon3 &front, 44 Polygon3 &back) 44 Polygon3 &back, 45 const float epsilon) 45 46 { 46 47 Vector3 ptA = mVertices.back(); 47 48 48 int sideA = partition.Side(ptA, Vector3::sDistTolerance);49 int sideA = partition.Side(ptA, epsilon); 49 50 50 51 VertexContainer::const_iterator it; … … 53 54 54 55 bool foundSplit = false; 55 // find line - plane intersections 56 57 //-- find line - plane intersections 56 58 for (it = mVertices.begin(); it != mVertices.end(); ++ it) 57 59 { 58 60 Vector3 ptB = *it; 59 int sideB = partition.Side(ptB, Vector3::sDistTolerance);61 int sideB = partition.Side(ptB, epsilon); 60 62 61 63 // vertices on different sides => split … … 68 70 69 71 // test if split point not too close to previous split point 70 if (!foundSplit || 71 (SqrDistance(splitPt, lastSplit) > Vector3::sDistToleranceSqrt)) 72 if (!foundSplit || (!EpsilonEqualV3(splitPt, lastSplit, epsilon))) 72 73 { 73 74 // add vertex to both polygons … … 89 90 // test if split point not too close to other split point 90 91 // test if split point not too close to previous split point 91 if (!foundSplit || 92 (SqrDistance(splitPt, lastSplit) > Vector3::sDistToleranceSqrt)) 92 if (!foundSplit || (!EpsilonEqualV3(splitPt, lastSplit, epsilon))) 93 93 { 94 94 // add vertex to both polygons … … 125 125 } 126 126 127 int Polygon3::Side(const Plane3 &plane) const 128 { 129 int classification = ClassifyPlane(plane); 127 int Polygon3::Side(const Plane3 &plane, 128 const float epsilon) const 129 { 130 int classification = ClassifyPlane(plane, epsilon); 130 131 131 132 if (classification == BACK_SIDE) … … 137 138 } 138 139 139 int Polygon3::ClassifyPlane(const Plane3 &plane, const float tolerance) const 140 int Polygon3::ClassifyPlane(const Plane3 &plane, 141 const float epsilon) const 140 142 { 141 143 VertexContainer::const_iterator it; … … 148 150 for (it = mVertices.begin(); it != mVertices.end(); ++ it) 149 151 { 150 const int side = plane.Side(*it, tolerance);152 const int side = plane.Side(*it, epsilon); 151 153 152 154 if (side > 0) … … 179 181 } 180 182 181 int Polygon3::ClassifyPlane(const Plane3 &plane) const182 { 183 return ClassifyPlane(plane, Vector3::sDistTolerance);184 } 183 /*int Polygon3::ClassifyPlane(const Plane3 &plane) const 184 { 185 return ClassifyPlane(plane, Limits::Small); 186 }*/ 185 187 186 188 … … 207 209 } 208 210 209 bool Polygon3::Valid( ) const211 bool Polygon3::Valid(const float epsilon) const 210 212 { 211 213 if (mVertices.size() < 3) … … 225 227 for (it = mVertices.begin(); it != it_end; ++it) 226 228 { 227 if (!( SqrDistance(vtx, *it) > sDistToleranceSqrt))228 { 229 Debug << "Malformed vertices:\n" << *this << endl;229 if (!(EpsilonEqual(vtx, *it))) 230 { 231 //Debug << "Malformed vertices:\n" << *this << endl; 230 232 return false; 231 233 } … … 385 387 } 386 388 387 int Polygon3::ClassifyPlane(const PolygonContainer &polys, const Plane3 &plane) 389 int Polygon3::ClassifyPlane(const PolygonContainer &polys, 390 const Plane3 &plane, 391 const float epsilon) 388 392 { 389 393 PolygonContainer::const_iterator it; … … 395 399 for (it = polys.begin(); it != polys.end(); ++ it) 396 400 { 397 const int cf = (*it)->ClassifyPlane(plane );401 const int cf = (*it)->ClassifyPlane(plane, epsilon); 398 402 399 403 if (cf == FRONT_SIDE) … … 445 449 446 450 for (pit = cell.begin(); pit != cell.end(); ++ pit) 451 { 452 if ((*pit)->mVertices.size() < 3) 453 Debug << "ERROR" << endl; 454 447 455 area += (*pit)->GetArea(); 456 } 448 457 449 458 return area; -
trunk/VUT/GtpVisibilityPreprocessor/src/Polygon3.h
r436 r448 50 50 @param front returns the front the front polygon 51 51 @param back returns the back polygon 52 @param epsilon epsilon where two points are considered equal 52 53 */ 53 54 void Split(const Plane3 &partition, 54 55 Polygon3 &front, 55 Polygon3 &back); 56 Polygon3 &back, 57 const float epsilon);// = Limits::Small); 56 58 57 59 /** Returns the area of this polygon. … … 62 64 @returns one of BACK_SIDE, FRONT_SIDE, SPLIT, COINCIDENT 63 65 */ 64 int ClassifyPlane(const Plane3 &plane) const; 65 66 //int ClassifyPlane(const Plane3 &plane) const; 66 67 67 68 /** Classify polygon with respect to the plane. 68 @returns one of BACK_SIDE, FRONT_SIDE, SPLIT, COINCIDENT 69 @param epsilon tolerance value 70 @returns one of BACK_SIDE, FRONT_SIDE, SPLIT, COINCIDENT 71 69 72 */ 70 int ClassifyPlane(const Plane3 &plane, const float tolerance) const;73 int ClassifyPlane(const Plane3 &plane, const float epsilon) const; 71 74 72 75 /** Side of the polygon with respect to the plane. 73 76 @returns 1 if on front side, -1 if on back side, 0 else. 74 77 */ 75 int Side(const Plane3 &plane ) const;78 int Side(const Plane3 &plane, const float epsilon) const; 76 79 77 80 /** Scales the polygon about its center … … 85 88 @returns true if polygon is valid. 86 89 */ 87 bool Valid( ) const;90 bool Valid(const float epsilon) const; 88 91 89 92 /** Returns the surface normal. … … 127 130 @returns one of BACK_SIDE, FRONT_SIDE, SPLIT, COINCIDENT 128 131 */ 129 static int ClassifyPlane(const PolygonContainer &polys, const Plane3 &plane); 132 static int ClassifyPlane(const PolygonContainer &polys, 133 const Plane3 &plane, 134 const float epsilon); 130 135 131 136 -
trunk/VUT/GtpVisibilityPreprocessor/src/Preprocessor.cpp
r445 r448 178 178 mViewCellsManager = new KdViewCellsManager(mKdTree); 179 179 } 180 if (strcmp(viewCellsStr, "bspTree") == 0)180 else if (strcmp(viewCellsStr, "bspTree") == 0) 181 181 { 182 182 mBspTree = new BspTree(); 183 184 Debug << "view cell type: Bsp" << endl; 183 185 184 186 environment->GetIntValue("BspTree.Construction.samples", constructionSamples); 185 187 mViewCellsManager = new BspViewCellsManager(mBspTree, constructionSamples); 186 188 } 187 if (strcmp(viewCellsStr, "vspBspTree") == 0)189 else if (strcmp(viewCellsStr, "vspBspTree") == 0) 188 190 { 189 191 mVspBspTree = new VspBspTree(); 192 193 Debug << "view cell type: VspBsp" << endl; 190 194 191 195 environment->GetIntValue("VspBspTree.Construction.samples", constructionSamples); … … 204 208 mBspTree = new BspTree(); 205 209 210 Debug << "view cell type: Bsp" << endl; 206 211 environment->GetIntValue("BspTree.Construction.samples", constructionSamples); 207 212 mViewCellsManager = new BspViewCellsManager(mBspTree, constructionSamples); -
trunk/VUT/GtpVisibilityPreprocessor/src/Ray.cpp
r444 r448 225 225 mType(LOCAL_RAY) 226 226 { 227 const float dist = Distance(vssRay.mTermination, vssRay.mOrigin); 228 229 if (dist) 230 dir = vssRay.GetDir() / dist; 227 float len = vssRay.Length(); 228 229 if (!len) 230 len = Limits::Small; 231 232 dir = vssRay.GetDir() / len; 231 233 232 234 if (vssRay.mTerminationObject) 233 intersections.push_back(Intersection( dist, vssRay.mTerminationObject, 0));235 intersections.push_back(Intersection(len, vssRay.mTerminationObject, 0)); 234 236 235 237 Precompute(); -
trunk/VUT/GtpVisibilityPreprocessor/src/Ray.h
r428 r448 15 15 class VssRay; 16 16 17 17 18 // ------------------------------------------------------------------- 18 19 // CRay class. A ray is defined by a location and a direction. … … 48 49 49 50 bool operator<( 50 const Intersection &b) const { 51 const Intersection &b) const { 52 51 53 return 52 54 mT -
trunk/VUT/GtpVisibilityPreprocessor/src/RayInfo.cpp
r437 r448 45 45 float RayInfo::ExtrapOrigin(const int axis) const 46 46 { 47 return mRay->GetOrigin(axis) + GetMinT() *mRay->GetDir(axis);47 return mRay->GetOrigin(axis) + GetMinT() * mRay->GetDir(axis); 48 48 } 49 49 50 50 float RayInfo::ExtrapTermination(const int axis) const 51 51 { 52 return mRay->GetOrigin(axis) + GetMaxT() *mRay->GetDir(axis);52 return mRay->GetOrigin(axis) + GetMaxT() * mRay->GetDir(axis); 53 53 } 54 54 55 55 Vector3 RayInfo::ExtrapOrigin() const 56 56 { 57 return mRay->GetOrigin() * mRay->GetDir();57 return mRay->GetOrigin() + GetMinT() * mRay->GetDir(); 58 58 } 59 59 … … 134 134 t = splitPlane.FindT(mRay->GetOrigin(), mRay->GetTermination()); 135 135 136 // Debug << "t: " << t << " mint " << GetMinT() << " maxt " << GetMaxT() << " orig: " << mRay->GetOrigin() << 137 // " term " << mRay->GetTermination() << endl; 136 138 if ((t < GetMinT()) || (t > GetMaxT())) 137 139 return splitPlane.Side(ExtrapOrigin()); -
trunk/VUT/GtpVisibilityPreprocessor/src/RenderSimulator.cpp
r440 r448 3 3 #include "ViewCellBsp.h" 4 4 #include "ViewCell.h" 5 #include "VspBspTree.h" 6 5 7 6 8 void SimulationStatistics::Print(ostream &app) const … … 53 55 /* class BspRenderSimulator implementation */ 54 56 /********************************************************/ 57 58 55 59 BspRenderSimulator::BspRenderSimulator(BspTree *bspTree): 56 60 mBspTree(bspTree) … … 139 143 140 144 Real BspRenderSimulator::RenderPvs(ViewCell &viewCell, 141 145 float objRenderTime) const 142 146 { 143 147 return viewCell.GetPvs().GetSize() * objRenderTime; … … 234 238 return leaf->mKdPvs.GetSize() * objRenderTime; 235 239 } 240 241 /********************************************************/ 242 /* class BspRenderSimulator implementation */ 243 /********************************************************/ 244 VspBspRenderSimulator::VspBspRenderSimulator(VspBspTree *vspBspTree): 245 mVspBspTree(vspBspTree) 246 { 247 } 248 249 VspBspRenderSimulator::VspBspRenderSimulator(float objRenderCost, 250 float vcOverhead, 251 float moveSpeed, 252 VspBspTree *vspBspTree): 253 RenderSimulator(objRenderCost, vcOverhead, moveSpeed), 254 mVspBspTree(vspBspTree) 255 { 256 } 257 258 SimulationStatistics VspBspRenderSimulator::SimulateRendering() 259 { 260 SimulationStatistics simStat; 261 262 simStat.Reset(); 263 simStat.Start(); 264 265 Real renderTime = 0; 266 267 // overhead for loading the PVS of the view cells 268 float loadPvsOverhead = 0; 269 // probability that view point lies in a view cell 270 float pInVcTotal = 0; 271 272 // total probability that a view cell border is crossed 273 const float pCrossVcTotal = mVspBspTree->GetBoundingBox().SurfaceArea(); 274 275 // collect all view cells 276 ViewCellContainer viewCells; 277 mVspBspTree->CollectViewCells(viewCells); 278 279 ViewCellContainer::const_iterator it, it_end = viewCells.end(); 280 281 // surface area substitute for probability 282 PolygonContainer geom; 283 float overallarea = 0; 284 for (it = viewCells.begin(); it != it_end; ++ it) 285 { 286 // compute view cell area 287 mVspBspTree->ConstructGeometry(dynamic_cast<BspViewCell *>(*it), geom); 288 289 const float area = Polygon3::GetArea(geom); 290 if (area < 0.0001) 291 Debug << "warning, area: " << area << endl; 292 CLEAR_CONTAINER(geom); 293 294 // area substitute for view point probability 295 float pInVc = area; 296 297 // compute render time of PVS times probability that view point is in view cell 298 float vcCost = pInVc * RenderPvs(*(*it), mObjRenderCost); 299 //Debug << "p: " << pInVc << " rendercost: " << RenderPvs(*(*it), mObjRenderCost) << endl; 300 renderTime += vcCost; 301 302 if (vcCost > simStat.maxCost) 303 simStat.maxCost = vcCost; 304 else if (vcCost < simStat.minCost) 305 simStat.minCost = vcCost; 306 307 // probability that a view cell border is crossed 308 float pCrossVc = area * mMoveSpeed; 309 310 // crossing the border of a view cell is also depending on the move speed 311 loadPvsOverhead += pCrossVc * mVcOverhead; 312 overallarea += area; 313 pInVcTotal += pInVc; 314 } 315 Debug << "overall area: " << overallarea << endl; 316 317 renderTime /= pInVcTotal; 318 loadPvsOverhead /= pCrossVcTotal; 319 320 simStat.avgRtWithoutOverhead = renderTime; 321 simStat.avgRenderTime = renderTime + loadPvsOverhead; 322 323 simStat.maxCost /= pInVcTotal; 324 simStat.minCost /= pInVcTotal; 325 326 simStat.Stop(); 327 328 return simStat; 329 } 330 331 Real VspBspRenderSimulator::RenderPvs(ViewCell &viewCell, 332 float objRenderTime) const 333 { 334 return viewCell.GetPvs().GetSize() * objRenderTime; 335 } -
trunk/VUT/GtpVisibilityPreprocessor/src/RenderSimulator.h
r441 r448 9 9 class ViewCell; 10 10 class KdLeaf; 11 class VspBspTree; 11 12 12 13 class SimulationStatistics: public StatisticsBase … … 105 106 Real RenderPvs(ViewCell &viewCell, const float objRenderTime) const; 106 107 108 private: 107 109 BspTree *mBspTree; 110 }; 111 112 class VspBspRenderSimulator: public RenderSimulator 113 { 114 public: 115 VspBspRenderSimulator(VspBspTree *vspBspTree); 116 117 VspBspRenderSimulator(float objRenderCost, 118 float vcOverhead, 119 float moveSpeed, 120 VspBspTree *vspBspTree); 121 122 SimulationStatistics SimulateRendering(); 123 124 protected: 125 /** Simulates rendering of the pvs of one view cell, with given rendering time for an object. 126 @param viewCell the view cell holding the Pvs 127 @param objRenderTime estimated render time for one object of the Pvs 128 */ 129 Real RenderPvs(ViewCell &viewCell, const float objRenderTime) const; 130 131 private: 132 VspBspTree *mVspBspTree; 108 133 }; 109 134 -
trunk/VUT/GtpVisibilityPreprocessor/src/RssPreprocessor.cpp
r447 r448 9 9 #include "VssRay.h" 10 10 #include "RssTree.h" 11 11 #include "ViewCellBsp.h" 12 12 13 13 static bool useViewSpaceBox = true;//true; … … 474 474 } 475 475 476 //-- construct BSP view cells477 if (ViewCell::sHierarchy == ViewCell::BSP)478 {479 const int bspSamples = min((int)mVssRays.size(), mBspConstructionSamples);480 481 Debug << "bpssamples: " << bspSamples << endl;482 for (int i = 0; i < bspSamples; ++ i)483 bspRays.push_back(new Ray(*mVssRays[i]));484 485 //-- construct BSP tree using the samples486 mBspTree = new BspTree(&mUnbounded);487 488 ObjectContainer objects;489 mSceneGraph->CollectObjects(&objects);490 mBspTree->Construct(objects, bspRays);491 }492 493 476 rssTree = new RssTree; 494 477 // viewcells = Construct(mVssRays); … … 567 550 } 568 551 569 // cast rays into BSP tree570 if (ViewCell::sHierarchy == ViewCell::BSP)571 {572 for (int i = 0; i < (int)vssRays.size(); ++ i)573 {574 CastRay(*mBspTree, *vssRays[i]);575 }576 }577 578 552 samples+=num; 579 553 float pvs = rssTree->GetAvgPvsSize(); … … 598 572 delete rssTree; 599 573 600 if (ViewCell::sHierarchy == ViewCell::BSP)601 {602 Debug << mBspTree->GetStatistics();603 604 ObjectContainer objects;605 ExportSplits(objects, bspRays, 10000);606 ExportBspPvs(objects, bspRays, 10000);607 608 BspViewCellsStatistics stat;609 mBspTree->EvaluateViewCellsStats(stat);610 Debug << "original view cell partition:\n" << stat << endl;611 612 // clear BSP samples613 CLEAR_CONTAINER(bspRays);614 }615 574 616 575 return true; … … 646 605 BspLeaf *leaf = ray.bspIntersections[j].mLeaf; 647 606 // if ray not in unbounded space 648 if (leaf->GetViewCell() != &mUnbounded)607 /* if (leaf->GetViewCell() != &mUnbounded) 649 608 contributingSamples += 650 leaf->GetViewCell()->GetPvs().AddSample(obj); 609 leaf->GetViewCell()->GetPvs().AddSample(obj);*/ 651 610 } 652 611 … … 657 616 BspLeaf *leaf = ray.bspIntersections[j].mLeaf; 658 617 659 if (leaf->GetViewCell() != &mUnbounded)618 /* if (leaf->GetViewCell() != &mUnbounded) 660 619 leaf->GetViewCell()-> 661 AddPassingRay(ray, contributingSamples ? 1 : 0); 620 AddPassingRay(ray, contributingSamples ? 1 : 0);*/ 662 621 } 663 622 -
trunk/VUT/GtpVisibilityPreprocessor/src/SamplingPreprocessor.cpp
r444 r448 75 75 76 76 mViewCellsManager->ComputeSampleContributions(rays, 77 castRaysToViewCells,78 77 sampleContributions, 79 contributingSamples); 78 contributingSamples, 79 castRaysToViewCells); 80 80 } 81 81 … … 397 397 //-- several visualizations and statistics 398 398 399 //-- render simulation 400 cout << "\nevaluating bsp view cells render time beforemerge ... ";399 //-- render simulation after merge 400 cout << "\nevaluating bsp view cells render time after merge ... "; 401 401 402 402 const SimulationStatistics ss = mViewCellsManager->SimulateRendering(); … … 405 405 cout << ss << endl; 406 406 Debug << ss << endl; 407 407 408 408 409 mViewCellsManager->Visualize(objects, mSampleRays); 409 410 … … 424 425 RayContainer::const_iterator it, it_end = newRays.end(); 425 426 426 if ((int)mVssSampleRays.size() < mViewCellsManager->GetConstructionSamples()) 427 if ((int)mVssSampleRays.size() < 428 mViewCellsManager->GetConstructionSamples()) 427 429 { 428 430 for (it = newRays.begin(); it != it_end; ++ it) … … 433 435 else 434 436 { 435 // construct view cells using the collected samples 436 cout << "building view cells from " << (int)mVssSampleRays.size() << " samples " << endl; 437 437 // construct view cells 438 438 mViewCellsManager->Construct(objects, mVssSampleRays); 439 439 440 440 // throw away samples 441 CLEAR_CONTAINER(mVssSampleRays);442 } 443 } 444 // Need (ordered) raysfor post processing => collect new rays441 //CLEAR_CONTAINER(mVssSampleRays); 442 } 443 } 444 // Need rays (with ordered intersections) for post processing => collect new rays 445 445 else if (((int)mSampleRays.size() < mViewCellsManager->GetPostProcessSamples()) || 446 446 ((int)mSampleRays.size() < mViewCellsManager->GetVisualizationSamples())) -
trunk/VUT/GtpVisibilityPreprocessor/src/Vector3.cpp
r372 r448 2 2 #include "Vector3.h" 3 3 #include "Halton.h" 4 5 float Vector3::sDistTolerance = 0.002f;6 float Vector3::sDistToleranceSqrt = 0.000004f;7 4 8 5 // Given min a vector to minimize and a candidate vector, replace -
trunk/VUT/GtpVisibilityPreprocessor/src/Vector3.h
r372 r448 36 36 Vector3(float X) { x = y = z = X; } 37 37 Vector3(const Vector3 &v) { x = v.x; y = v.y; z = v.z; } 38 39 /// the distance where two points are still considered equal40 static float sDistTolerance;41 static float sDistToleranceSqrt;42 38 43 39 // Functions to get at the vector components … … 480 476 EpsilonEqualV3(const Vector3 &v1, const Vector3 &v2) 481 477 { 482 return EpsilonEqualV3(v1, v2,Limits::Small);478 return EpsilonEqualV3(v1, v2, Limits::Small); 483 479 } 484 480 -
trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellBsp.cpp
r445 r448 98 98 } 99 99 100 Plane3 *BspInterior::GetPlane()101 { 102 return &mPlane;100 Plane3 BspInterior::GetPlane() const 101 { 102 return mPlane; 103 103 } 104 104 … … 117 117 } 118 118 119 int BspInterior::SplitPolygons(PolygonContainer &polys,120 PolygonContainer &frontPolys,121 PolygonContainer &backPolys,122 PolygonContainer &coincident)123 {124 int splits = 0;125 126 #ifdef _Debug127 Debug << "splitting polygons of node " << this << " with plane " << mPlane << endl;128 #endif129 while (!polys.empty())130 {131 Polygon3 *poly = polys.back();132 polys.pop_back();133 134 //Debug << "New polygon with plane: " << poly->GetSupportingPlane() << "\n";135 136 // classify polygon137 const int cf = poly->ClassifyPlane(mPlane);138 139 switch (cf)140 {141 case Polygon3::COINCIDENT:142 coincident.push_back(poly);143 break;144 case Polygon3::FRONT_SIDE:145 frontPolys.push_back(poly);146 break;147 case Polygon3::BACK_SIDE:148 backPolys.push_back(poly);149 break;150 case Polygon3::SPLIT:151 {152 Polygon3 *front_piece = new Polygon3(poly->mParent);153 Polygon3 *back_piece = new Polygon3(poly->mParent);154 155 //-- split polygon into front and back part156 poly->Split(mPlane, *front_piece, *back_piece);157 158 ++ splits; // increase number of splits159 160 //-- inherit rays from parent polygon for blocked ray criterium161 poly->InheritRays(*front_piece, *back_piece);162 //Debug << "p: " << poly->mPiercingRays.size() << " f: " << front_piece->mPiercingRays.size() << " b: " << back_piece->mPiercingRays.size() << endl;163 164 // check if polygons still valid165 if (front_piece->Valid())166 frontPolys.push_back(front_piece);167 else168 DEL_PTR(front_piece);169 170 if (back_piece->Valid())171 backPolys.push_back(back_piece);172 else173 DEL_PTR(back_piece);174 175 #ifdef _DEBUG176 Debug << "split " << *poly << endl << *front_piece << endl << *back_piece << endl;177 #endif178 DEL_PTR(poly);179 }180 break;181 default:182 Debug << "SHOULD NEVER COME HERE\n";183 break;184 }185 }186 187 return splits;188 }189 190 119 /****************************************************************/ 191 120 /* class BspLeaf implementation */ 192 121 /****************************************************************/ 122 123 193 124 BspLeaf::BspLeaf(): mViewCell(NULL) 194 125 { 195 126 } 127 196 128 197 129 BspLeaf::BspLeaf(BspViewCell *viewCell): … … 199 131 { 200 132 } 133 201 134 202 135 BspLeaf::BspLeaf(BspInterior *parent): … … 204 137 {} 205 138 139 140 206 141 BspLeaf::BspLeaf(BspInterior *parent, BspViewCell *viewCell): 207 142 BspNode(parent), mViewCell(viewCell) … … 222 157 { 223 158 return true; 224 }225 226 void BspLeaf::AddToPvs(const BoundedRayContainer &rays,227 int &sampleContributions,228 int &contributingSamples)229 {230 sampleContributions = 0;231 contributingSamples = 0;232 233 BoundedRayContainer::const_iterator it, it_end = rays.end();234 235 // add contributions from samples to the PVS236 for (it = rays.begin(); it != it_end; ++ it)237 {238 int contribution = 0;239 Ray *ray = (*it)->mRay;240 241 if (!ray->intersections.empty())242 contribution += mViewCell->GetPvs().AddSample(ray->intersections[0].mObject);243 244 if (ray->sourceObject.mObject)245 contribution += mViewCell->GetPvs().AddSample(ray->sourceObject.mObject);246 247 if (contribution)248 {249 sampleContributions += contribution;250 ++ contributingSamples;251 }252 253 //if (ray->mFlags & Ray::STORE_BSP_INTERSECTIONS)254 ray->bspIntersections.push_back(Ray::BspIntersection((*it)->mMinT, this));255 }256 159 } 257 160 … … 308 211 environment->GetIntValue("BspTree.maxTests", mMaxTests); 309 212 310 environment->GetFloatValue("BspTree.Construction.sideTolerance", Vector3::sDistTolerance); 311 Vector3::sDistToleranceSqrt = Vector3::sDistTolerance * Vector3::sDistTolerance; 312 313 213 environment->GetFloatValue("BspTree.Construction.epsilon", mEpsilon); 214 314 215 Debug << "BSP max depth: " << mTermMaxDepth << endl; 315 216 Debug << "BSP min PVS: " << mTermMinPvs << endl; … … 347 248 } 348 249 250 349 251 const BspTreeStatistics &BspTree::GetStatistics() const 350 252 { 351 253 return mStat; 352 254 } 255 256 257 int BspTree::SplitPolygons(const Plane3 &plane, 258 PolygonContainer &polys, 259 PolygonContainer &frontPolys, 260 PolygonContainer &backPolys, 261 PolygonContainer &coincident) const 262 { 263 int splits = 0; 264 265 #ifdef _Debug 266 Debug << "splitting polygons of node " << this << " with plane " << mPlane << endl; 267 #endif 268 while (!polys.empty()) 269 { 270 Polygon3 *poly = polys.back(); 271 polys.pop_back(); 272 273 //Debug << "New polygon with plane: " << poly->GetSupportingPlane() << "\n"; 274 275 // classify polygon 276 const int cf = poly->ClassifyPlane(plane, mEpsilon); 277 278 switch (cf) 279 { 280 case Polygon3::COINCIDENT: 281 coincident.push_back(poly); 282 break; 283 case Polygon3::FRONT_SIDE: 284 frontPolys.push_back(poly); 285 break; 286 case Polygon3::BACK_SIDE: 287 backPolys.push_back(poly); 288 break; 289 case Polygon3::SPLIT: 290 { 291 Polygon3 *front_piece = new Polygon3(poly->mParent); 292 Polygon3 *back_piece = new Polygon3(poly->mParent); 293 294 //-- split polygon into front and back part 295 poly->Split(plane, 296 *front_piece, 297 *back_piece, 298 mEpsilon); 299 300 ++ splits; // increase number of splits 301 302 //-- inherit rays from parent polygon for blocked ray criterium 303 poly->InheritRays(*front_piece, *back_piece); 304 305 // check if polygons still valid 306 if (front_piece->Valid(mEpsilon)) 307 frontPolys.push_back(front_piece); 308 else 309 DEL_PTR(front_piece); 310 311 if (back_piece->Valid(mEpsilon)) 312 backPolys.push_back(back_piece); 313 else 314 DEL_PTR(back_piece); 315 316 #ifdef _DEBUG 317 Debug << "split " << *poly << endl << *front_piece << endl << *back_piece << endl; 318 #endif 319 DEL_PTR(poly); 320 } 321 break; 322 default: 323 Debug << "SHOULD NEVER COME HERE\n"; 324 break; 325 } 326 } 327 328 return splits; 329 } 330 353 331 354 332 void BspTreeStatistics::Print(ostream &app) const … … 458 436 459 437 // split viewcell polygons with respect to split plane 460 splits += interior->SplitPolygons(*tData.mPolygons, 461 *frontPolys, 462 *backPolys, 463 coincident); 438 splits += SplitPolygons(interior->GetPlane(), 439 *tData.mPolygons, 440 *frontPolys, 441 *backPolys, 442 coincident); 464 443 465 444 // extract view cells associated with the split polygons … … 505 484 // cleanup 506 485 DEL_PTR(tData.mPolygons); 486 DEL_PTR(tData.mRays); 507 487 } 508 488 else … … 514 494 } 515 495 516 int BspTree::AddMeshToPolygons(Mesh *mesh, PolygonContainer &polys, MeshInstance *parent) 496 int BspTree::AddMeshToPolygons(Mesh *mesh, 497 PolygonContainer &polys, 498 MeshInstance *parent) 517 499 { 518 500 FaceContainer::const_iterator fi; … … 523 505 Polygon3 *poly = new Polygon3((*fi), mesh); 524 506 525 if (poly->Valid( ))507 if (poly->Valid(mEpsilon)) 526 508 { 527 509 poly->mParent = parent; // set parent intersectable … … 684 666 685 667 float minT, maxT; 686 if ( BoundRay(*ray, minT, maxT))668 if (mBox.GetRaySegment(*ray, minT, maxT)) 687 669 rays->push_back(new BoundedRay(ray, minT, maxT)); 688 670 } … … 719 701 720 702 float minT, maxT; 721 if ( BoundRay(*ray, minT, maxT))703 if (mBox.GetRaySegment(*ray, minT, maxT)) 722 704 rays->push_back(new BoundedRay(ray, minT, maxT)); 723 705 } … … 801 783 { 802 784 int conSamp = 0, sampCon = 0; 803 leaf->AddToPvs(*tData.mRays, conSamp, sampCon);785 AddToPvs(leaf, *tData.mRays, conSamp, sampCon); 804 786 805 787 mStat.contributingSamples += conSamp; … … 818 800 DEL_PTR(tData.mPolygons); 819 801 DEL_PTR(tData.mRays); 820 802 DEL_PTR(tData.mGeometry); 803 821 804 return leaf; 822 805 } … … 860 843 // cleanup 861 844 DEL_PTR(tData.mNode); 845 862 846 DEL_PTR(tData.mPolygons); 863 847 DEL_PTR(tData.mRays); … … 916 900 917 901 918 Debug << "number of rays: " << tData.mRays->size() << endl;919 Debug << "number of polys: " << tData.mPolygons->size() << endl;902 Debug << "number of rays: " << (int)tData.mRays->size() << endl; 903 Debug << "number of polys: " << (int)tData.mPolygons->size() << endl; 920 904 921 905 startTime = GetTime(); … … 928 912 startTime = GetTime(); 929 913 // subdivide polygons with plane 930 mStat.splits += interior->SplitPolygons(*tData.mPolygons, 931 *frontData.mPolygons, 932 *backData.mPolygons, 933 coincident); 914 mStat.splits += SplitPolygons(interior->GetPlane(), 915 *tData.mPolygons, 916 *frontData.mPolygons, 917 *backData.mPolygons, 918 coincident); 934 919 935 920 Debug << "time used for polygon splitting: " << TimeDiff(startTime, GetTime())*1e-3 << "s" << endl; … … 944 929 tData.mGeometry->SplitGeometry(*frontData.mGeometry, 945 930 *backData.mGeometry, 946 *this, 947 interior->mPlane); 931 interior->mPlane, 932 mBox, 933 mEpsilon); 948 934 949 935 … … 974 960 interior->SetupChildLinks(new BspLeaf(interior), new BspLeaf(interior)); 975 961 976 frontData.mNode = interior-> mFront;977 backData.mNode = interior-> mBack;962 frontData.mNode = interior->GetFront(); 963 backData.mNode = interior->GetBack(); 978 964 979 965 //DEL_PTR(leaf); … … 1269 1255 1270 1256 BoundedRay *bRay = (*rays)[idx[j]]; 1271 pt[j] = chooseMin ? bRay->mRay->Extrap(bRay->mMinT) : bRay->mRay->Extrap(bRay->mMaxT); 1257 pt[j] = chooseMin ? bRay->mRay->Extrap(bRay->mMinT) : 1258 bRay->mRay->Extrap(bRay->mMaxT); 1272 1259 } 1273 1260 … … 1347 1334 Polygon3 *poly = polys[testIdx]; 1348 1335 1349 const int classification = poly->ClassifyPlane(candidatePlane); 1336 const int classification = 1337 poly->ClassifyPlane(candidatePlane, mEpsilon); 1350 1338 1351 1339 if (mSplitPlaneStrategy & BALANCED_POLYS) … … 1437 1425 } 1438 1426 1439 bool BspTree::BoundRay(const Ray &ray, float &minT, float &maxT) const1440 {1441 maxT = 1e6;1442 minT = 0;1443 1444 // test with tree bounding box1445 if (!mBox.GetMinMaxT(ray, &minT, &maxT))1446 return false;1447 1448 if (minT < 0) // start ray from origin1449 minT = 0;1450 1451 // bound ray or line segment1452 if (//(ray.GetType() == Ray::LOCAL_RAY) &&1453 !ray.intersections.empty() &&1454 (ray.intersections[0].mT <= maxT))1455 {1456 maxT = ray.intersections[0].mT;1457 }1458 1459 return true;1460 }1461 1427 1462 1428 inline void BspTree::GenerateUniqueIdsForPvs() … … 1499 1465 BspNodeGeometry backCell; 1500 1466 1501 cell.SplitGeometry(frontCell, backCell, *this, candidatePlane); 1467 cell.SplitGeometry(frontCell, 1468 backCell, 1469 candidatePlane, 1470 mBox, 1471 mEpsilon); 1502 1472 1503 1473 pFront = frontCell.GetArea(); … … 1803 1773 float maxt, mint; 1804 1774 1805 if (! BoundRay(ray, mint, maxt))1775 if (!mBox.GetRaySegment(ray, mint, maxt)) 1806 1776 return 0; 1807 1777 … … 1818 1788 if (!node->IsLeaf()) 1819 1789 { 1820 BspInterior *in = (BspInterior *) node;1790 BspInterior *in = dynamic_cast<BspInterior *>(node); 1821 1791 1822 Plane3 *splitPlane = in->GetPlane(); 1823 1824 int entSide = splitPlane->Side(entp); 1825 int extSide = splitPlane->Side(extp); 1826 1827 Vector3 intersection; 1792 Plane3 splitPlane = in->GetPlane(); 1793 const int entSide = splitPlane.Side(entp); 1794 const int extSide = splitPlane.Side(extp); 1828 1795 1829 1796 if (entSide < 0) … … 1858 1825 // find intersection of ray segment with plane 1859 1826 float t; 1860 extp = splitPlane ->FindIntersection(ray.GetLoc(), extp, &t);1827 extp = splitPlane.FindIntersection(ray.GetLoc(), extp, &t); 1861 1828 maxt *= t; 1862 1829 … … 1934 1901 BspInterior *interior = dynamic_cast<BspInterior *>(node); 1935 1902 1936 nodeStack.push(interior-> mFront);1937 nodeStack.push(interior-> mBack);1903 nodeStack.push(interior->GetFront()); 1904 nodeStack.push(interior->GetBack()); 1938 1905 } 1939 1906 } … … 1989 1956 BspInterior *interior = dynamic_cast<BspInterior *>(node); 1990 1957 1991 nodeStack.push(interior-> mFront);1992 nodeStack.push(interior-> mBack);1958 nodeStack.push(interior->GetFront()); 1959 nodeStack.push(interior->GetBack()); 1993 1960 } 1994 1961 } … … 2101 2068 { 2102 2069 BspInterior *interior = dynamic_cast<BspInterior *>(n); 2103 Plane3 halfSpace = *dynamic_cast<BspInterior *>(interior)->GetPlane();2104 2105 if (interior-> mFront!= lastNode)2070 Plane3 halfSpace = dynamic_cast<BspInterior *>(interior)->GetPlane(); 2071 2072 if (interior->GetFront() != lastNode) 2106 2073 halfSpace.ReverseOrientation(); 2107 2074 … … 2135 2102 ExtractHalfSpaces(n, halfSpaces); 2136 2103 2137 PolygonContainer candidate Polys;2104 PolygonContainer candidates; 2138 2105 2139 2106 // bounded planes are added to the polygons (reverse polygons … … 2143 2110 Polygon3 *p = GetBoundingBox().CrossSection(halfSpaces[i]); 2144 2111 2145 if (p->Valid( ))2146 { 2147 candidate Polys.push_back(p->CreateReversePolygon());2112 if (p->Valid(mEpsilon)) 2113 { 2114 candidates.push_back(p->CreateReversePolygon()); 2148 2115 DEL_PTR(p); 2149 2116 } … … 2158 2125 vertices.push_back(mBox.GetFace(i).mVertices[j]); 2159 2126 2160 candidate Polys.push_back(new Polygon3(vertices));2161 } 2162 2163 for (int i = 0; i < (int)candidate Polys.size(); ++ i)2127 candidates.push_back(new Polygon3(vertices)); 2128 } 2129 2130 for (int i = 0; i < (int)candidates.size(); ++ i) 2164 2131 { 2165 2132 // polygon is split by all other planes 2166 for (int j = 0; (j < (int)halfSpaces.size()) && candidate Polys[i]; ++ j)2133 for (int j = 0; (j < (int)halfSpaces.size()) && candidates[i]; ++ j) 2167 2134 { 2168 2135 if (i == j) // polygon and plane are coincident … … 2172 2139 Polygon3 *frontPoly, *backPoly; 2173 2140 2174 const int cf = candidatePolys[i]->ClassifyPlane(halfSpaces[j]); 2141 const int cf = candidates[i]-> 2142 ClassifyPlane(halfSpaces[j], mEpsilon); 2175 2143 2176 2144 switch (cf) … … 2180 2148 backPoly = new Polygon3(); 2181 2149 2182 candidatePolys[i]->Split(halfSpaces[j], 2183 *frontPoly, 2184 *backPoly); 2185 2186 DEL_PTR(candidatePolys[i]); 2187 2188 if (frontPoly->Valid()) 2189 candidatePolys[i] = frontPoly; 2150 candidates[i]->Split(halfSpaces[j], 2151 *frontPoly, 2152 *backPoly, 2153 mEpsilon); 2154 2155 DEL_PTR(candidates[i]); 2156 2157 if (frontPoly->Valid(mEpsilon)) 2158 candidates[i] = frontPoly; 2190 2159 else 2191 2160 DEL_PTR(frontPoly); … … 2194 2163 break; 2195 2164 case Polygon3::BACK_SIDE: 2196 DEL_PTR(candidate Polys[i]);2165 DEL_PTR(candidates[i]); 2197 2166 break; 2198 2167 // just take polygon as it is … … 2204 2173 } 2205 2174 2206 if (candidate Polys[i])2207 cell.push_back(candidate Polys[i]);2175 if (candidates[i]) 2176 cell.push_back(candidates[i]); 2208 2177 } 2209 2178 } … … 2242 2211 { 2243 2212 const int cf = 2244 Polygon3::ClassifyPlane(neighborCandidate, halfSpaces[i]); 2213 Polygon3::ClassifyPlane(neighborCandidate, 2214 halfSpaces[i], 2215 mEpsilon); 2245 2216 2246 2217 if (cf == Polygon3::BACK_SIDE) … … 2258 2229 BspInterior *interior = dynamic_cast<BspInterior *>(node); 2259 2230 2260 const int cf = Polygon3::ClassifyPlane(cell, interior->mPlane); 2231 const int cf = Polygon3::ClassifyPlane(cell, 2232 interior->mPlane, 2233 mEpsilon); 2261 2234 2262 2235 if (cf == Polygon3::FRONT_SIDE) 2263 nodeStack.push(interior-> mFront);2236 nodeStack.push(interior->GetFront()); 2264 2237 else 2265 2238 if (cf == Polygon3::BACK_SIDE) 2266 nodeStack.push(interior-> mBack);2239 nodeStack.push(interior->GetBack()); 2267 2240 else 2268 2241 { 2269 2242 // random decision 2270 nodeStack.push(interior-> mBack);2271 nodeStack.push(interior-> mFront);2243 nodeStack.push(interior->GetBack()); 2244 nodeStack.push(interior->GetFront()); 2272 2245 } 2273 2246 } … … 2305 2278 ConstructGeometry(interior, cell); 2306 2279 2307 const int cf = Polygon3::ClassifyPlane(cell, halfspace); 2280 const int cf = Polygon3::ClassifyPlane(cell, 2281 halfspace, 2282 mEpsilon); 2308 2283 2309 2284 if (cf == Polygon3::BACK_SIDE) 2310 next = interior-> mFront;2285 next = interior->GetFront(); 2311 2286 else 2312 2287 if (cf == Polygon3::FRONT_SIDE) 2313 next = interior-> mFront;2288 next = interior->GetFront(); 2314 2289 else 2315 2290 { 2316 2291 // random decision 2317 2292 if (mask & 1) 2318 next = interior-> mBack;2293 next = interior->GetBack(); 2319 2294 else 2320 next = interior-> mFront;2295 next = interior->GetFront(); 2321 2296 mask = mask >> 1; 2322 2297 } … … 2353 2328 // random decision 2354 2329 if (mask & 1) 2355 nodeStack.push(interior-> mBack);2330 nodeStack.push(interior->GetBack()); 2356 2331 else 2357 nodeStack.push(interior-> mFront);2332 nodeStack.push(interior->GetFront()); 2358 2333 2359 2334 mask = mask >> 1; … … 2362 2337 2363 2338 return NULL; 2339 } 2340 2341 void BspTree::AddToPvs(BspLeaf *leaf, 2342 const BoundedRayContainer &rays, 2343 int &sampleContributions, 2344 int &contributingSamples) 2345 { 2346 sampleContributions = 0; 2347 contributingSamples = 0; 2348 2349 BoundedRayContainer::const_iterator it, it_end = rays.end(); 2350 2351 ViewCell *vc = leaf->GetViewCell(); 2352 2353 // add contributions from samples to the PVS 2354 for (it = rays.begin(); it != it_end; ++ it) 2355 { 2356 int contribution = 0; 2357 Ray *ray = (*it)->mRay; 2358 2359 if (!ray->intersections.empty()) 2360 contribution += vc->GetPvs().AddSample(ray->intersections[0].mObject); 2361 2362 if (ray->sourceObject.mObject) 2363 contribution += vc->GetPvs().AddSample(ray->sourceObject.mObject); 2364 2365 if (contribution) 2366 { 2367 sampleContributions += contribution; 2368 ++ contributingSamples; 2369 } 2370 2371 //if (ray->mFlags & Ray::STORE_BSP_INTERSECTIONS) 2372 // ray->bspIntersections.push_back(Ray::BspIntersection((*it)->mMinT, this)); 2373 } 2364 2374 } 2365 2375 … … 2397 2407 } 2398 2408 2399 /************************************************************* 2400 * BspNodeGeometry Implementation * 2401 *************************************************************/ 2409 float BspTree::GetEpsilon() const 2410 { 2411 return mEpsilon; 2412 } 2413 2414 void BspViewCellsStatistics::Print(ostream &app) const 2415 { 2416 app << "===== BspViewCells statistics ===============\n"; 2417 2418 app << setprecision(4); 2419 2420 //app << "#N_CTIME ( Construction time [s] )\n" << Time() << " \n"; 2421 2422 app << "#N_OVERALLPVS ( objects in PVS )\n" << pvs << endl; 2423 2424 app << "#N_PMAXPVS ( largest PVS )\n" << maxPvs << endl; 2425 2426 app << "#N_PMINPVS ( smallest PVS )\n" << minPvs << endl; 2427 2428 app << "#N_PAVGPVS ( average PVS )\n" << AvgPvs() << endl; 2429 2430 app << "#N_PEMPTYPVS ( view cells with PVS smaller 2 )\n" << emptyPvs << endl; 2431 2432 app << "#N_VIEWCELLS ( number of view cells)\n" << viewCells << endl; 2433 2434 app << "#N_AVGBSPLEAVES (average number of BSP leaves per view cell )\n" << AvgBspLeaves() << endl; 2435 2436 app << "#N_MAXBSPLEAVES ( maximal number of BSP leaves per view cell )\n" << maxBspLeaves << endl; 2437 2438 app << "===== END OF BspViewCells statistics ==========\n"; 2439 } 2440 2441 /*************************************************************/ 2442 /* BspNodeGeometry Implementation */ 2443 /*************************************************************/ 2402 2444 2403 2445 BspNodeGeometry::~BspNodeGeometry() … … 2413 2455 void BspNodeGeometry::SplitGeometry(BspNodeGeometry &front, 2414 2456 BspNodeGeometry &back, 2415 const BspTree &tree, 2416 const Plane3 &splitPlane) const 2457 const Plane3 &splitPlane, 2458 const AxisAlignedBox3 &box, 2459 const float epsilon) const 2417 2460 { 2418 2461 // get cross section of new polygon 2419 Polygon3 *planePoly = tree.GetBoundingBox().CrossSection(splitPlane); 2420 2421 planePoly = SplitPolygon(planePoly, tree); 2422 2423 //-- plane poly splits all other cell polygons 2462 Polygon3 *planePoly = box.CrossSection(splitPlane); 2463 2464 // split polygon with all other polygons 2465 planePoly = SplitPolygon(planePoly, epsilon); 2466 2467 //-- new polygon splits all other polygons 2424 2468 for (int i = 0; i < (int)mPolys.size(); ++ i) 2425 2469 { 2426 const int cf = mPolys[i]->ClassifyPlane(splitPlane, 0.00001f); 2470 /// don't use epsilon here to get exact split planes 2471 const int cf = 2472 mPolys[i]->ClassifyPlane(splitPlane, Limits::Small); 2427 2473 2428 // split new polygon with all previous planes2429 2474 switch (cf) 2430 2475 { … … 2436 2481 Polygon3 *backPoly = new Polygon3(); 2437 2482 2438 poly->Split(splitPlane, *frontPoly, *backPoly); 2483 poly->Split(splitPlane, 2484 *frontPoly, 2485 *backPoly, 2486 epsilon); 2439 2487 2440 2488 DEL_PTR(poly); 2441 2489 2442 if (frontPoly->Valid( ))2490 if (frontPoly->Valid(epsilon)) 2443 2491 front.mPolys.push_back(frontPoly); 2444 2492 else 2445 2493 DEL_PTR(frontPoly); 2446 2494 2447 if (backPoly->Valid( ))2495 if (backPoly->Valid(epsilon)) 2448 2496 back.mPolys.push_back(backPoly); 2449 2497 else … … 2467 2515 } 2468 2516 2469 //-- finally add the new polygon to the child cells2517 //-- finally add the new polygon to the child node geometries 2470 2518 if (planePoly) 2471 2519 { … … 2481 2529 2482 2530 Polygon3 *BspNodeGeometry::SplitPolygon(Polygon3 *planePoly, 2483 const BspTree &tree) const 2484 { 2531 const float epsilon) const 2532 { 2533 if (!planePoly->Valid(epsilon)) 2534 DEL_PTR(planePoly); 2535 2485 2536 // polygon is split by all other planes 2486 2537 for (int i = 0; (i < (int)mPolys.size()) && planePoly; ++ i) … … 2488 2539 Plane3 plane = mPolys[i]->GetSupportingPlane(); 2489 2540 2541 /// don't use epsilon here to get exact split planes 2490 2542 const int cf = 2491 planePoly->ClassifyPlane(plane, 0.00001f);2543 planePoly->ClassifyPlane(plane, Limits::Small); 2492 2544 2493 2545 // split new polygon with all previous planes … … 2499 2551 Polygon3 *backPoly = new Polygon3(); 2500 2552 2501 planePoly->Split(plane, *frontPoly, *backPoly); 2553 planePoly->Split(plane, 2554 *frontPoly, 2555 *backPoly, 2556 epsilon); 2502 2557 2503 2558 // don't need anymore … … 2506 2561 2507 2562 // back polygon is belonging to geometry 2508 if (backPoly->Valid( ))2563 if (backPoly->Valid(epsilon)) 2509 2564 planePoly = backPoly; 2510 2565 else … … 2525 2580 return planePoly; 2526 2581 } 2527 2528 void BspViewCellsStatistics::Print(ostream &app) const2529 {2530 app << "===== BspViewCells statistics ===============\n";2531 2532 app << setprecision(4);2533 2534 //app << "#N_CTIME ( Construction time [s] )\n" << Time() << " \n";2535 2536 app << "#N_OVERALLPVS ( objects in PVS )\n" << pvs << endl;2537 2538 app << "#N_PMAXPVS ( largest PVS )\n" << maxPvs << endl;2539 2540 app << "#N_PMINPVS ( smallest PVS )\n" << minPvs << endl;2541 2542 app << "#N_PAVGPVS ( average PVS )\n" << AvgPvs() << endl;2543 2544 app << "#N_PEMPTYPVS ( view cells with PVS smaller 2 )\n" << emptyPvs << endl;2545 2546 app << "#N_VIEWCELLS ( number of view cells)\n" << viewCells << endl;2547 2548 app << "#N_AVGBSPLEAVES (average number of BSP leaves per view cell )\n" << AvgBspLeaves() << endl;2549 2550 app << "#N_MAXBSPLEAVES ( maximal number of BSP leaves per view cell )\n" << maxBspLeaves << endl;2551 2552 app << "===== END OF BspViewCells statistics ==========\n";2553 } -
trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellBsp.h
r444 r448 7 7 #include <stack> 8 8 #include "Statistics.h" 9 #include "VssRay.h" 10 9 11 10 12 class ViewCell; … … 27 29 float GetArea() const; 28 30 29 /** Computes new cell based on the old cell definition and a new split plane30 @param side indicates which side of the halfspace31 */ 32 void SplitGeometry(BspNodeGeometry &front, 31 /** Computes new front and back geometry based on the old cell 32 geometry and a new split plane 33 */ 34 void SplitGeometry(BspNodeGeometry &front, 33 35 BspNodeGeometry &back, 34 const BspTree &tree, 35 const Plane3 &splitPlane) const; 36 37 Polygon3 *SplitPolygon(Polygon3 *poly, const BspTree &tree) const; 36 const Plane3 &splitPlane, 37 const AxisAlignedBox3 &box, 38 const float epsilon) const; 39 40 Polygon3 *SplitPolygon(Polygon3 *poly, const float epsilon) const; 38 41 39 42 PolygonContainer mPolys; … … 270 273 BspNode *GetFront(); 271 274 272 Plane3 *GetPlane(); 273 275 /** Returns split plane. 276 */ 277 Plane3 GetPlane() const; 278 279 /** Replace front or back child with new child. 280 */ 274 281 void ReplaceChildLink(BspNode *oldChild, BspNode *newChild); 282 /** Replace front and back child. 283 */ 275 284 void SetupChildLinks(BspNode *b, BspNode *f); 276 277 /** Splits polygons with respect to the split plane.278 @param polys the polygons to be split. the polygons are consumed and279 distributed to the containers frontPolys, backPolys, coincident.280 @param frontPolys returns the polygons in the front of the split plane281 @param backPolys returns the polygons in the back of the split plane282 @param coincident returns the polygons coincident to the split plane283 284 @returns the number of splits285 */286 int SplitPolygons(PolygonContainer &polys,287 PolygonContainer &frontPolys,288 PolygonContainer &backPolys,289 PolygonContainer &coincident);290 285 291 286 friend ostream &operator<<(ostream &s, const BspInterior &A) … … 298 293 /// Splitting plane corresponding to this node 299 294 Plane3 mPlane; 295 300 296 /// back node 301 297 BspNode *mBack; … … 328 324 void SetViewCell(BspViewCell *viewCell); 329 325 330 /** Adds ray sample contributions to the PVS. 331 @param sampleContributions the number contributions of the samples 332 @param contributingSampels the number of contributing rays 333 334 */ 335 void AddToPvs(const BoundedRayContainer &rays, 336 int &sampleContributions, 337 int &contributingSamples); 326 VssRayContainer mVssRays; 338 327 339 328 protected: … … 516 505 BspViewCell *GetRootCell() const; 517 506 518 /** Parses the environment and stores the global BSP tree parameters 519 */ 520 static void ParseEnvironment(); 521 507 /** Returns epsilon of this tree. 508 */ 509 float GetEpsilon() const; 522 510 523 511 protected: … … 722 710 bool SelectAxisAlignedPlane(Plane3 &plane, const PolygonContainer &polys) const; 723 711 724 /** Bounds ray and returns minT and maxT.725 @returns true if ray hits BSP tree bounding box726 */727 bool BoundRay(const Ray &ray, float &minT, float &maxT) const;728 729 712 /** Subdivides the rays into front and back rays according to the split plane. 730 713 … … 768 751 */ 769 752 float AccumulatedRayLength(BoundedRayContainer &rays) const; 753 754 /** Splits polygons with respect to the split plane. 755 @param polys the polygons to be split. the polygons are consumed and 756 distributed to the containers frontPolys, backPolys, coincident. 757 @param frontPolys returns the polygons in the front of the split plane 758 @param backPolys returns the polygons in the back of the split plane 759 @param coincident returns the polygons coincident to the split plane 760 761 @returns the number of splits 762 */ 763 int SplitPolygons(const Plane3 &plane, 764 PolygonContainer &polys, 765 PolygonContainer &frontPolys, 766 PolygonContainer &backPolys, 767 PolygonContainer &coincident) const; 768 769 /** Adds ray sample contributions to the PVS. 770 @param sampleContributions the number contributions of the samples 771 @param contributingSampels the number of contributing rays 772 773 */ 774 void AddToPvs(BspLeaf *leaf, 775 const BoundedRayContainer &rays, 776 int &sampleContributions, 777 int &contributingSamples); 770 778 771 779 /// Pointer to the root of the tree. … … 852 860 bool mPvsUseArea; 853 861 862 /// epsilon where two points are still considered equal 863 float mEpsilon; 864 854 865 private: 855 866 -
trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellsManager.cpp
r444 r448 68 68 69 69 void ViewCellsManager::ComputeSampleContributions(const RayContainer &rays, 70 const bool castRays,71 70 int &sampleContributions, 72 int &contributingSamples) 71 int &contributingSamples, 72 const bool castRays) 73 73 { 74 74 // view cells not yet constructed … … 168 168 SimulationStatistics ViewCellsManager::SimulateRendering() const 169 169 { 170 if (!ViewCellsConstructed() )170 if (!ViewCellsConstructed() || !mRenderSimulator) 171 171 return SimulationStatistics(); 172 172 … … 240 240 return 0; 241 241 242 Debug << "Constructing bsp view cells" << endl;243 244 242 int sampleContributions = 0; 245 243 … … 247 245 248 246 int limit = min (mConstructionSamples, (int)rays.size()); 247 248 // construct view cells using the collected samples 249 Debug << "construcing bsp view cells from " 250 << limit << " samples " << endl; 249 251 250 252 for (int i = 0; i < limit; ++ i) … … 332 334 int pvsSize = 0; 333 335 334 BspViewCellsStatistics stat;335 mBspTree->EvaluateViewCellsStats( stat);336 Debug << "original view cell partition:\n" << stat<< endl;337 338 if (1) // export view cells 336 BspViewCellsStatistics vcStats; 337 mBspTree->EvaluateViewCellsStats(vcStats); 338 Debug << "original view cell partition:\n" << vcStats << endl; 339 340 if (1) // export view cells before merge 339 341 { 340 342 cout << "exporting initial view cells (=leaves) ... "; … … 344 346 { 345 347 exporter->SetWireframe(); 346 exporter->ExportBspLeaves(*mBspTree, stat.maxPvs);348 exporter->ExportBspLeaves(*mBspTree, vcStats.maxPvs); 347 349 //exporter->ExportBspViewCellPartition(*mBspTree, 0); 348 350 … … 360 362 } 361 363 cout << "finished" << endl; 362 } 364 365 //-- render simulation 366 cout << "\nevaluating bsp view cells render time before merge ... "; 367 368 const SimulationStatistics ss = SimulateRendering(); 369 370 cout << " finished" << endl; 371 cout << ss << endl; 372 Debug << ss << endl; 373 } 374 363 375 364 376 cout << "starting post processing using " << mPostProcessSamples << " samples ... "; 365 377 366 378 long startTime = GetTime(); 367 368 379 369 380 //-- merge or subdivide view cells … … 408 419 cout << "merged " << merged << " view cells in " 409 420 << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl; 421 422 // statistics after post process 423 vcStats.Reset(); 424 mBspTree->EvaluateViewCellsStats(vcStats); 425 Debug << "post processed view cell partition:\n" << vcStats << endl; 410 426 411 427 return merged; … … 956 972 mVspKdTree(vspKdTree) 957 973 { 958 mRenderSimulator = NULL; // TODO:new VspKdRenderSimulator(vspKdTree);974 mRenderSimulator = NULL;//new VspKdRenderSimulator(vspKdTree); 959 975 InitRenderSimulator(); 960 976 } … … 983 999 return 0; 984 1000 985 //if (castRay) // TODO 1001 //if (castRay) 1002 //mVspKdTree->CastRay(ray); 986 1003 987 1004 int sampleContributions = 0; 988 1005 989 /*990 for (int i = 0; i < (int)rays.size(); ++ i)991 {992 Ray *ray = rays[i];993 994 mBspTree->CastRay(*ray);995 996 Intersectable *term =997 !ray->intersections.empty() ? ray->intersections[0].mObject : NULL998 ;999 sampleContributions +=1000 AddSampleContributions(*ray, ray->sourceObject.mObject, term);1001 1002 }1003 */1004 1006 return sampleContributions; 1005 1007 } … … 1121 1123 mVspBspTree(vspBspTree) 1122 1124 { 1123 mRenderSimulator = NULL;// TODO new VspBspRenderSimulator(bspTree);1124 //InitRenderSimulator();1125 mRenderSimulator = new VspBspRenderSimulator(vspBspTree); 1126 InitRenderSimulator(); 1125 1127 } 1126 1128 … … 1182 1184 for (int j = 0; j < (int)ray.bspIntersections.size(); ++ j) 1183 1185 { 1184 VspBspLeaf *leaf = NULL; //TODOray.bspIntersections[j].mLeaf;1186 BspLeaf *leaf = ray.bspIntersections[j].mLeaf; 1185 1187 1186 1188 // if ray not in unbounded space … … 1206 1208 for (int j = 1; j < ((int)ray.bspIntersections.size() - 1); ++ j) 1207 1209 { 1208 VspBspLeaf *leaf = NULL;// TODO= ray.bspIntersections[j].mLeaf;1210 BspLeaf *leaf = ray.bspIntersections[j].mLeaf; 1209 1211 1210 1212 if (leaf->GetViewCell() != mVspBspTree->GetRootCell()) … … 1219 1221 const RayContainer &rays) 1220 1222 { 1221 return 0;// TODO1222 1223 if (!ViewCellsConstructed()) 1223 1224 { … … 1231 1232 int pvsSize = 0; 1232 1233 1233 VspBspViewCellsStatistics vcStats;1234 BspViewCellsStatistics vcStats; 1234 1235 mVspBspTree->EvaluateViewCellsStats(vcStats); 1235 1236 Debug << "original view cell partition:\n" << vcStats << endl; … … 1243 1244 { 1244 1245 exporter->SetWireframe(); 1245 //exporter->ExportBspLeaves(*mVspBspTree, stat.maxPvs);1246 exporter->ExportBspViewCellPartition(*mVspBspTree, vcStats.maxPvs); 1246 1247 1247 1248 if (0) … … 1284 1285 iit = ray->bspIntersections.begin(); 1285 1286 1286 VspBspLeaf *previousLeaf = NULL;//TODO(*iit).mLeaf;1287 BspLeaf *previousLeaf = (*iit).mLeaf; 1287 1288 ++ iit; 1288 1289 1289 1290 for (; iit != ray->bspIntersections.end(); ++ iit) 1290 1291 { 1291 VspBspLeaf *leaf = NULL;//TODO(*iit).mLeaf;1292 BspLeaf *leaf = (*iit).mLeaf; 1292 1293 1293 1294 if (ShouldMerge(leaf, previousLeaf)) … … 1307 1308 << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl; 1308 1309 1310 // statistics after post process 1311 vcStats.Reset(); 1312 mVspBspTree->EvaluateViewCellsStats(vcStats); 1313 Debug << "post processed view cell partition:\n" << vcStats << endl; 1314 1309 1315 return merged; 1310 1316 } … … 1319 1325 const RayContainer &sampleRays) 1320 1326 { 1321 return; // TODO1322 1327 if (!ViewCellsConstructed()) 1323 1328 return; 1324 1329 1325 1330 //-- recount pvs 1326 VspBspViewCellsStatistics vcStats;1331 BspViewCellsStatistics vcStats; 1327 1332 mVspBspTree->EvaluateViewCellsStats(vcStats); 1328 1333 … … 1330 1335 { 1331 1336 cout << "exporting view cells after merge ... "; 1332 /*Exporter *exporter = Exporter::GetExporter("merged_view_cells.x3d");1337 Exporter *exporter = Exporter::GetExporter("merged_view_cells.x3d"); 1333 1338 1334 1339 if (exporter) … … 1337 1342 delete exporter; 1338 1343 } 1339 */1344 1340 1345 cout << "finished" << endl; 1341 1346 } … … 1343 1348 //-- visualization of the BSP splits 1344 1349 bool exportSplits = false; 1345 1350 environment->GetBoolValue("BspTree.Visualization.exportSplits", exportSplits); 1346 1351 1347 1352 if (exportSplits) … … 1352 1357 } 1353 1358 1354 //TODO ExportVspBspPvs(objects, sampleRays);1359 ExportBspPvs(objects, sampleRays); 1355 1360 } 1356 1361 … … 1367 1372 exporter->SetForcedMaterial(m); 1368 1373 exporter->SetWireframe(); 1369 // TODO1370 //exporter->ExportBspSplits(*mVspBspTree, true);1374 1375 exporter->ExportBspSplits(*mVspBspTree, true); 1371 1376 1372 1377 // take forced material, else big scenes cannot be viewed … … 1412 1417 const int raysOut = min((int)sampleRays.size(), mVisualizationSamples); 1413 1418 cout << "visualization using " << mVisualizationSamples << " samples" << endl; 1414 vector<Ray *> vcRays[leafOut]; 1415 1416 if (0) 1419 1420 if (1) 1417 1421 { 1418 1422 //-- some random view cells and rays for output 1419 vector< VspBspLeaf *> vspBspLeaves;1423 vector<BspLeaf *> vspBspLeaves; 1420 1424 1421 1425 for (int i = 0; i < leafOut; ++ i) … … 1424 1428 for (int i = 0; i < (int)vspBspLeaves.size(); ++ i) 1425 1429 { 1430 RayContainer vcRays; 1426 1431 cout << "creating output for view cell " << i << " ... "; 1427 1432 // check whether we can add the current ray to the output rays 1428 for (int k = 0; k < raysOut; ++ k)1433 /*for (int k = 0; k < raysOut; ++ k) 1429 1434 { 1430 1435 Ray *ray = sampleRays[k]; … … 1436 1441 if (vspBspLeaves[i]->GetViewCell() == leaf->GetViewCell()) 1437 1442 { 1438 vcRays [i].push_back(ray);1443 vcRays.push_back(ray); 1439 1444 } 1440 1445 } 1441 1446 } 1447 */ 1442 1448 1443 1449 Intersectable::NewMail(); … … 1474 1480 1475 1481 Debug << i << ": pvs size=" << (int)vc->GetPvs().GetSize() 1476 << ", piercing rays=" << (int)vcRays [i].size() << endl;1482 << ", piercing rays=" << (int)vcRays.size() << endl; 1477 1483 1478 1484 // export rays piercing this view cell 1479 exporter->ExportRays(vcRays[i], 1000, RgbColor(0, 1, 0)); 1480 1481 m.mDiffuseColor = RgbColor(1, 0, 0); 1485 exporter->ExportRays(vcRays, 1000, RgbColor(1, 0, 0)); 1486 exporter->ExportRays(vspBspLeaves[i]->mVssRays, RgbColor(1, 1, 1)); 1487 1488 m.mDiffuseColor = RgbColor(0, 1, 1); 1482 1489 exporter->SetForcedMaterial(m); 1483 1490 1484 //exporter->SetWireframe();1485 exporter->SetFilled();1491 exporter->SetWireframe(); 1492 //exporter->SetFilled(); 1486 1493 1487 1494 // output PVS of view cell … … 1527 1534 { 1528 1535 cout << "creating output for view cell " << i << " ... "; 1529 1536 RayContainer vcRays; 1530 1537 Intersectable::NewMail(); 1531 1538 BspViewCell *vc = dynamic_cast<BspViewCell *>(viewCells[i]); … … 1539 1546 for (int j = 0; j < (int)ray->bspIntersections.size(); ++ j) 1540 1547 { 1541 VspBspLeaf *leaf = NULL; // TODO= ray->bspIntersections[j].mLeaf;1548 BspLeaf *leaf = ray->bspIntersections[j].mLeaf; 1542 1549 1543 1550 if (vc == leaf->GetViewCell()) 1544 1551 { 1545 vcRays [i].push_back(ray);1552 vcRays.push_back(ray); 1546 1553 } 1547 1554 } … … 1572 1579 1573 1580 Debug << i << ": pvs size=" << (int)vc->GetPvs().GetSize() 1574 << ", piercing rays=" << (int)vcRays [i].size() << endl;1581 << ", piercing rays=" << (int)vcRays.size() << endl; 1575 1582 1576 1583 1577 1584 // export rays piercing this view cell 1578 exporter->ExportRays(vcRays [i], 1000, RgbColor(0, 1, 0));1585 exporter->ExportRays(vcRays, 1000, RgbColor(0, 1, 0)); 1579 1586 1580 1587 m.mDiffuseColor = RgbColor(1, 0, 0); … … 1607 1614 1608 1615 1609 bool VspBspViewCellsManager::MergeVspBspLeafViewCells( VspBspLeaf *front,1610 VspBspLeaf *back) const1616 bool VspBspViewCellsManager::MergeVspBspLeafViewCells(BspLeaf *front, 1617 BspLeaf *back) const 1611 1618 { 1612 1619 BspViewCell *viewCell = … … 1623 1630 BspViewCell *bVc = back->GetViewCell(); 1624 1631 1625 // TODO 1626 /*vector<VspBspLeaf *> fLeaves = fVc->mBspLeaves; 1627 vector<VspBspLeaf *> bLeaves = bVc->mBspLeaves; 1628 1629 vector<VspBspLeaf *>::const_iterator it; 1632 vector<BspLeaf *> fLeaves = fVc->mBspLeaves; 1633 vector<BspLeaf *> bLeaves = bVc->mBspLeaves; 1634 1635 vector<BspLeaf *>::const_iterator it; 1630 1636 1631 1637 for (it = fLeaves.begin(); it != fLeaves.end(); ++ it) … … 1642 1648 DEL_PTR(fVc); 1643 1649 DEL_PTR(bVc); 1644 */ 1650 1645 1651 return true; 1646 1652 } 1647 1653 1648 bool VspBspViewCellsManager::ShouldMerge( VspBspLeaf *front, VspBspLeaf *back) const1654 bool VspBspViewCellsManager::ShouldMerge(BspLeaf *front, BspLeaf *back) const 1649 1655 { 1650 1656 ViewCell *fvc = front->GetViewCell(); -
trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellsManager.h
r444 r448 20 20 class VspKdTree; 21 21 class AxisAlignedBox3; 22 class VspBspLeaf;22 class BspLeaf; 23 23 24 24 /** … … 57 57 */ 58 58 void ComputeSampleContributions(const RayContainer &rays, 59 const bool castRays,60 59 int &sampleContributions, 61 int &contributingSamples); 60 int &contributingSamples, 61 const bool castRays = true); 62 62 63 63 … … 350 350 /** Merges view cells front and back leaf view cell. 351 351 */ 352 bool MergeVspBspLeafViewCells( VspBspLeaf *front, VspBspLeaf *back) const;352 bool MergeVspBspLeafViewCells(BspLeaf *front, BspLeaf *back) const; 353 353 354 354 /** Returns true if front and back leaf should be merged. 355 355 */ 356 bool ShouldMerge( VspBspLeaf *front, VspBspLeaf *back) const;356 bool ShouldMerge(BspLeaf *front, BspLeaf *back) const; 357 357 358 358 /// the view space partition BSP tree. -
trunk/VUT/GtpVisibilityPreprocessor/src/VspBspTree.cpp
r445 r448 13 13 #include "Exporter.h" 14 14 #include "Plane3.h" 15 #include "ViewCellBsp.h" 15 16 16 17 //-- static members … … 24 25 const float VspBspTree::sBalancedRaysTable[] = {1, -1, 0, 0, 0}; 25 26 26 int VspBspNode::sMailId = 1;27 27 28 28 int VspBspTree::sFrontId = 0; … … 30 30 int VspBspTree::sFrontAndBackId = 0; 31 31 32 32 33 /****************************************************************/ 33 /* class VspBsp Node implementation*/34 /* class VspBspTree implementation */ 34 35 /****************************************************************/ 35 36 36 VspBspNode::VspBspNode(): 37 mParent(NULL) 38 {} 39 40 VspBspNode::VspBspNode(VspBspInterior *parent): 41 mParent(parent) 42 {} 43 44 45 bool VspBspNode::IsRoot() const 46 { 47 return mParent == NULL; 48 } 49 50 VspBspInterior *VspBspNode::GetParent() 51 { 52 return mParent; 53 } 54 55 void VspBspNode::SetParent(VspBspInterior *parent) 56 { 57 mParent = parent; 58 } 59 60 /****************************************************************/ 61 /* class VspBspInterior implementation */ 62 /****************************************************************/ 63 64 65 VspBspInterior::VspBspInterior(const Plane3 &plane): 66 mPlane(plane), mFront(NULL), mBack(NULL) 67 {} 68 69 VspBspInterior::~VspBspInterior() 70 { 71 DEL_PTR(mFront); 72 DEL_PTR(mBack); 73 } 74 75 bool VspBspInterior::IsLeaf() const 76 { 77 return false; 78 } 79 80 VspBspNode *VspBspInterior::GetBack() 81 { 82 return mBack; 83 } 84 85 VspBspNode *VspBspInterior::GetFront() 86 { 87 return mFront; 88 } 89 90 Plane3 *VspBspInterior::GetPlane() 91 { 92 return &mPlane; 93 } 94 95 void VspBspInterior::ReplaceChildLink(VspBspNode *oldChild, VspBspNode *newChild) 96 { 97 if (mBack == oldChild) 98 mBack = newChild; 37 VspBspTree::VspBspTree(): 38 mRoot(NULL), 39 mPvsUseArea(true) 40 { 41 mRootCell = new BspViewCell(); 42 43 Randomize(); // initialise random generator for heuristics 44 45 //-- termination criteria for autopartition 46 environment->GetIntValue("VspBspTree.Termination.maxDepth", mTermMaxDepth); 47 environment->GetIntValue("VspBspTree.Termination.minPvs", mTermMinPvs); 48 environment->GetIntValue("VspBspTree.Termination.minRays", mTermMinRays); 49 environment->GetFloatValue("VspBspTree.Termination.minArea", mTermMinArea); 50 environment->GetFloatValue("VspBspTree.Termination.maxRayContribution", mTermMaxRayContribution); 51 environment->GetFloatValue("VspBspTree.Termination.minAccRayLenght", mTermMinAccRayLength); 52 53 //-- factors for bsp tree split plane heuristics 54 environment->GetFloatValue("VspBspTree.Factor.balancedRays", mBalancedRaysFactor); 55 environment->GetFloatValue("VspBspTree.Factor.pvs", mPvsFactor); 56 environment->GetFloatValue("VspBspTree.Termination.ct_div_ci", mCtDivCi); 57 58 //-- termination criteria for axis aligned split 59 environment->GetFloatValue("VspBspTree.Termination.AxisAligned.ct_div_ci", mAaCtDivCi); 60 environment->GetFloatValue("VspBspTree.Termination.AxisAligned.maxCostRatio", mMaxCostRatio); 61 62 environment->GetIntValue("VspBspTree.Termination.AxisAligned.minRays", 63 mTermMinRaysForAxisAligned); 64 65 //-- partition criteria 66 environment->GetIntValue("VspBspTree.maxPolyCandidates", mMaxPolyCandidates); 67 environment->GetIntValue("VspBspTree.maxRayCandidates", mMaxRayCandidates); 68 environment->GetIntValue("VspBspTree.splitPlaneStrategy", mSplitPlaneStrategy); 69 environment->GetFloatValue("VspBspTree.AxisAligned.splitBorder", mSplitBorder); 70 71 environment->GetFloatValue("VspBspTree.Construction.epsilon", mEpsilon); 72 environment->GetIntValue("VspBspTree.maxTests", mMaxTests); 73 74 Debug << "BSP max depth: " << mTermMaxDepth << endl; 75 Debug << "BSP min PVS: " << mTermMinPvs << endl; 76 Debug << "BSP min area: " << mTermMinArea << endl; 77 Debug << "BSP min rays: " << mTermMinRays << endl; 78 Debug << "BSP max polygon candidates: " << mMaxPolyCandidates << endl; 79 Debug << "BSP max plane candidates: " << mMaxRayCandidates << endl; 80 81 Debug << "Split plane strategy: "; 82 if (mSplitPlaneStrategy & RANDOM_POLYGON) 83 Debug << "random polygon "; 84 if (mSplitPlaneStrategy & AXIS_ALIGNED) 85 Debug << "axis aligned "; 86 if (mSplitPlaneStrategy & LEAST_RAY_SPLITS) 87 Debug << "least ray splits "; 88 if (mSplitPlaneStrategy & BALANCED_RAYS) 89 Debug << "balanced rays "; 90 if (mSplitPlaneStrategy & PVS) 91 Debug << "pvs"; 92 93 Debug << endl; 94 } 95 96 97 const BspTreeStatistics &VspBspTree::GetStatistics() const 98 { 99 return mStat; 100 } 101 102 103 VspBspTree::~VspBspTree() 104 { 105 DEL_PTR(mRoot); 106 DEL_PTR(mRootCell); 107 } 108 109 int VspBspTree::AddMeshToPolygons(Mesh *mesh, 110 PolygonContainer &polys, 111 MeshInstance *parent) 112 { 113 FaceContainer::const_iterator fi; 114 115 // copy the face data to polygons 116 for (fi = mesh->mFaces.begin(); fi != mesh->mFaces.end(); ++ fi) 117 { 118 Polygon3 *poly = new Polygon3((*fi), mesh); 119 120 if (poly->Valid(mEpsilon)) 121 { 122 poly->mParent = parent; // set parent intersectable 123 polys.push_back(poly); 124 } 125 else 126 DEL_PTR(poly); 127 } 128 return (int)mesh->mFaces.size(); 129 } 130 131 int VspBspTree::AddToPolygonSoup(const ViewCellContainer &viewCells, 132 PolygonContainer &polys, 133 int maxObjects) 134 { 135 int limit = (maxObjects > 0) ? 136 Min((int)viewCells.size(), maxObjects) : (int)viewCells.size(); 137 138 int polysSize = 0; 139 140 for (int i = 0; i < limit; ++ i) 141 { 142 if (viewCells[i]->GetMesh()) // copy the mesh data to polygons 143 { 144 mBox.Include(viewCells[i]->GetBox()); // add to BSP tree aabb 145 polysSize += 146 AddMeshToPolygons(viewCells[i]->GetMesh(), 147 polys, 148 viewCells[i]); 149 } 150 } 151 152 return polysSize; 153 } 154 155 int VspBspTree::AddToPolygonSoup(const ObjectContainer &objects, 156 PolygonContainer &polys, 157 int maxObjects) 158 { 159 int limit = (maxObjects > 0) ? 160 Min((int)objects.size(), maxObjects) : (int)objects.size(); 161 162 for (int i = 0; i < limit; ++i) 163 { 164 Intersectable *object = objects[i];//*it; 165 Mesh *mesh = NULL; 166 167 switch (object->Type()) // extract the meshes 168 { 169 case Intersectable::MESH_INSTANCE: 170 mesh = dynamic_cast<MeshInstance *>(object)->GetMesh(); 171 break; 172 case Intersectable::VIEW_CELL: 173 mesh = dynamic_cast<ViewCell *>(object)->GetMesh(); 174 break; 175 // TODO: handle transformed mesh instances 176 default: 177 Debug << "intersectable type not supported" << endl; 178 break; 179 } 180 181 if (mesh) // copy the mesh data to polygons 182 { 183 mBox.Include(object->GetBox()); // add to BSP tree aabb 184 AddMeshToPolygons(mesh, polys, mRootCell); 185 } 186 } 187 188 return (int)polys.size(); 189 } 190 191 void VspBspTree::Construct(const VssRayContainer &sampleRays) 192 { 193 mStat.nodes = 1; 194 mBox.Initialize(); // initialise BSP tree bounding box 195 196 PolygonContainer polys; 197 RayInfoContainer *rays = new RayInfoContainer(); 198 199 VssRayContainer::const_iterator rit, rit_end = sampleRays.end(); 200 201 long startTime = GetTime(); 202 203 Debug << "**** Extracting polygons from rays ****\n"; 204 205 Intersectable::NewMail(); 206 207 //-- extract polygons intersected by the rays 208 for (rit = sampleRays.begin(); rit != rit_end; ++ rit) 209 { 210 VssRay *ray = *rit; 211 212 if (ray->mTerminationObject && !ray->mTerminationObject->Mailed()) 213 { 214 ray->mTerminationObject->Mail(); 215 MeshInstance *obj = dynamic_cast<MeshInstance *>(ray->mTerminationObject); 216 AddMeshToPolygons(obj->GetMesh(), polys, obj); 217 } 218 219 if (ray->mOriginObject && !ray->mOriginObject->Mailed()) 220 { 221 ray->mOriginObject->Mail(); 222 MeshInstance *obj = dynamic_cast<MeshInstance *>(ray->mOriginObject); 223 AddMeshToPolygons(obj->GetMesh(), polys, obj); 224 } 225 } 226 227 // compute bounding box 228 Polygon3::IncludeInBox(polys, mBox); 229 230 //-- store rays 231 for (rit = sampleRays.begin(); rit != rit_end; ++ rit) 232 { 233 VssRay *ray = *rit; 234 235 float minT, maxT; 236 237 // TODO: not very efficient to implictly cast between rays types ... 238 if (mBox.GetRaySegment(*ray, minT, maxT)) 239 { 240 float len = ray->Length(); 241 242 if (!len) 243 len = Limits::Small; 244 245 rays->push_back(RayInfo(ray, minT / len, maxT / len)); 246 } 247 } 248 249 mStat.polys = (int)polys.size(); 250 251 Debug << "**** Finished polygon extraction ****" << endl; 252 Debug << (int)polys.size() << " polys extracted from " << (int)sampleRays.size() << " rays" << endl; 253 Debug << "extraction time: " << TimeDiff(startTime, GetTime())*1e-3 << "s" << endl; 254 255 Construct(polys, rays); 256 257 // clean up polygons 258 CLEAR_CONTAINER(polys); 259 } 260 261 void VspBspTree::Construct(const PolygonContainer &polys, RayInfoContainer *rays) 262 { 263 std::stack<VspBspTraversalData> tStack; 264 265 mRoot = new BspLeaf(); 266 267 // constrruct root node geometry 268 BspNodeGeometry *geom = new BspNodeGeometry(); 269 ConstructGeometry(mRoot, *geom); 270 271 VspBspTraversalData tData(mRoot, 272 new PolygonContainer(polys), 273 0, 274 rays, 275 ComputePvsSize(*rays), 276 geom->GetArea(), 277 geom); 278 279 tStack.push(tData); 280 281 mStat.Start(); 282 cout << "Contructing vsp bsp tree ... "; 283 284 long startTime = GetTime(); 285 286 while (!tStack.empty()) 287 { 288 tData = tStack.top(); 289 290 tStack.pop(); 291 292 // subdivide leaf node 293 BspNode *r = Subdivide(tStack, tData); 294 295 if (r == mRoot) 296 Debug << "BSP tree construction time spent at root: " 297 << TimeDiff(startTime, GetTime())*1e-3 << "s" << endl; 298 } 299 300 cout << "finished\n"; 301 302 mStat.Stop(); 303 } 304 305 bool VspBspTree::TerminationCriteriaMet(const VspBspTraversalData &data) const 306 { 307 return 308 (((int)data.mRays->size() <= mTermMinRays) || 309 (data.mPvs <= mTermMinPvs) || 310 (data.mArea <= mTermMinArea) || 311 // (data.GetAvgRayContribution() >= mTermMaxRayContribution) || 312 (data.mDepth >= mTermMaxDepth)); 313 } 314 315 BspNode *VspBspTree::Subdivide(VspBspTraversalStack &tStack, 316 VspBspTraversalData &tData) 317 { 318 //-- terminate traversal 319 if (TerminationCriteriaMet(tData)) 320 { 321 BspLeaf *leaf = dynamic_cast<BspLeaf *>(tData.mNode); 322 323 BspViewCell *viewCell = new BspViewCell(); 324 325 leaf->SetViewCell(viewCell); 326 viewCell->mBspLeaves.push_back(leaf); 327 328 //-- add pvs 329 if (viewCell != mRootCell) 330 { 331 int conSamp = 0, sampCon = 0; 332 AddToPvs(leaf, *tData.mRays, conSamp, sampCon); 333 334 mStat.contributingSamples += conSamp; 335 mStat.sampleContributions += sampCon; 336 } 337 338 EvaluateLeafStats(tData); 339 340 //-- clean up 341 342 DEL_PTR(tData.mPolygons); 343 DEL_PTR(tData.mRays); 344 DEL_PTR(tData.mGeometry); 345 346 return leaf; 347 } 348 349 //-- continue subdivision 350 PolygonContainer coincident; 351 352 VspBspTraversalData tFrontData(new PolygonContainer(), 353 tData.mDepth + 1, 354 new RayInfoContainer(), 355 new BspNodeGeometry()); 356 357 VspBspTraversalData tBackData(new PolygonContainer(), 358 tData.mDepth + 1, 359 new RayInfoContainer(), 360 new BspNodeGeometry()); 361 362 // create new interior node and two leaf nodes 363 BspInterior *interior = 364 SubdivideNode(tData, tFrontData, tBackData, coincident); 365 366 #ifdef _DEBUG 367 if (frontPolys->empty() && backPolys->empty() && (coincident.size() > 2)) 368 { for (PolygonContainer::iterator it = coincident.begin(); it != coincident.end(); ++it) 369 Debug << (*it) << " " << (*it)->GetArea() << " " << (*it)->mParent << endl ; 370 Debug << endl;} 371 #endif 372 373 // push the children on the stack 374 tStack.push(tFrontData); 375 tStack.push(tBackData); 376 377 // cleanup 378 DEL_PTR(tData.mNode); 379 380 DEL_PTR(tData.mPolygons); 381 DEL_PTR(tData.mRays); 382 DEL_PTR(tData.mGeometry); 383 384 return interior; 385 } 386 387 BspInterior *VspBspTree::SubdivideNode(VspBspTraversalData &tData, 388 VspBspTraversalData &frontData, 389 VspBspTraversalData &backData, 390 PolygonContainer &coincident) 391 { 392 mStat.nodes += 2; 393 394 BspLeaf *leaf = dynamic_cast<BspLeaf *>(tData.mNode); 395 396 // select subdivision plane 397 BspInterior *interior = new BspInterior(SelectPlane(leaf, tData)); 398 399 #ifdef _DEBUG 400 Debug << interior << endl; 401 #endif 402 403 // subdivide rays into front and back rays 404 SplitRays(interior->GetPlane(), 405 *tData.mRays, 406 *frontData.mRays, 407 *backData.mRays); 408 409 // subdivide polygons with plane 410 mStat.splits += SplitPolygons(interior->GetPlane(), 411 *tData.mPolygons, 412 *frontData.mPolygons, 413 *backData.mPolygons, 414 coincident); 415 416 // compute pvs 417 frontData.mPvs = ComputePvsSize(*frontData.mRays); 418 backData.mPvs = ComputePvsSize(*backData.mRays); 419 420 // split geometry and compute area 421 if (1) 422 { 423 tData.mGeometry->SplitGeometry(*frontData.mGeometry, 424 *backData.mGeometry, 425 interior->GetPlane(), 426 mBox, 427 mEpsilon); 428 429 430 frontData.mArea = frontData.mGeometry->GetArea(); 431 backData.mArea = backData.mGeometry->GetArea(); 432 } 433 434 // compute accumulated ray length 435 //frontData.mAccRayLength = AccumulatedRayLength(*frontData.mRays); 436 //backData.mAccRayLength = AccumulatedRayLength(*backData.mRays); 437 438 //-- create front and back leaf 439 440 BspInterior *parent = leaf->GetParent(); 441 442 // replace a link from node's parent 443 if (!leaf->IsRoot()) 444 { 445 parent->ReplaceChildLink(leaf, interior); 446 interior->SetParent(parent); 447 } 448 else // new root 449 { 450 mRoot = interior; 451 } 452 453 // and setup child links 454 interior->SetupChildLinks(new BspLeaf(interior), new BspLeaf(interior)); 455 456 frontData.mNode = interior->GetFront(); 457 backData.mNode = interior->GetBack(); 458 459 //DEL_PTR(leaf); 460 return interior; 461 } 462 463 void VspBspTree::AddToPvs(BspLeaf *leaf, 464 const RayInfoContainer &rays, 465 int &sampleContributions, 466 int &contributingSamples) 467 { 468 sampleContributions = 0; 469 contributingSamples = 0; 470 471 RayInfoContainer::const_iterator it, it_end = rays.end(); 472 473 ViewCell *vc = leaf->GetViewCell(); 474 475 // add contributions from samples to the PVS 476 for (it = rays.begin(); it != it_end; ++ it) 477 { 478 int contribution = 0; 479 VssRay *ray = (*it).mRay; 480 481 if (ray->mTerminationObject) 482 contribution += vc->GetPvs().AddSample(ray->mTerminationObject); 483 484 if (ray->mOriginObject) 485 contribution += vc->GetPvs().AddSample(ray->mOriginObject); 486 487 if (contribution) 488 { 489 sampleContributions += contribution; 490 ++ contributingSamples; 491 } 492 //leaf->mVssRays.push_back(ray); 493 } 494 } 495 496 void VspBspTree::SortSplitCandidates(const PolygonContainer &polys, 497 const int axis, 498 vector<SortableEntry> &splitCandidates) const 499 { 500 splitCandidates.clear(); 501 502 int requestedSize = 2 * (int)polys.size(); 503 // creates a sorted split candidates array 504 splitCandidates.reserve(requestedSize); 505 506 PolygonContainer::const_iterator it, it_end = polys.end(); 507 508 AxisAlignedBox3 box; 509 510 // insert all queries 511 for(it = polys.begin(); it != it_end; ++ it) 512 { 513 box.Initialize(); 514 box.Include(*(*it)); 515 516 splitCandidates.push_back(SortableEntry(SortableEntry::POLY_MIN, box.Min(axis), *it)); 517 splitCandidates.push_back(SortableEntry(SortableEntry::POLY_MAX, box.Max(axis), *it)); 518 } 519 520 stable_sort(splitCandidates.begin(), splitCandidates.end()); 521 } 522 523 524 float VspBspTree::BestCostRatio(const PolygonContainer &polys, 525 const AxisAlignedBox3 &box, 526 const int axis, 527 float &position, 528 int &objectsBack, 529 int &objectsFront) const 530 { 531 vector<SortableEntry> splitCandidates; 532 533 SortSplitCandidates(polys, axis, splitCandidates); 534 535 // go through the lists, count the number of objects left and right 536 // and evaluate the following cost funcion: 537 // C = ct_div_ci + (ol + or)/queries 538 539 int objectsLeft = 0, objectsRight = (int)polys.size(); 540 541 float minBox = box.Min(axis); 542 float maxBox = box.Max(axis); 543 float boxArea = box.SurfaceArea(); 544 545 float minBand = minBox + mSplitBorder * (maxBox - minBox); 546 float maxBand = minBox + (1.0f - mSplitBorder) * (maxBox - minBox); 547 548 float minSum = 1e20f; 549 vector<SortableEntry>::const_iterator ci, ci_end = splitCandidates.end(); 550 551 for(ci = splitCandidates.begin(); ci != ci_end; ++ ci) 552 { 553 switch ((*ci).type) 554 { 555 case SortableEntry::POLY_MIN: 556 ++ objectsLeft; 557 break; 558 case SortableEntry::POLY_MAX: 559 -- objectsRight; 560 break; 561 default: 562 break; 563 } 564 565 if ((*ci).value > minBand && (*ci).value < maxBand) 566 { 567 AxisAlignedBox3 lbox = box; 568 AxisAlignedBox3 rbox = box; 569 lbox.SetMax(axis, (*ci).value); 570 rbox.SetMin(axis, (*ci).value); 571 572 float sum = objectsLeft * lbox.SurfaceArea() + 573 objectsRight * rbox.SurfaceArea(); 574 575 if (sum < minSum) 576 { 577 minSum = sum; 578 position = (*ci).value; 579 580 objectsBack = objectsLeft; 581 objectsFront = objectsRight; 582 } 583 } 584 } 585 586 float oldCost = (float)polys.size(); 587 float newCost = mAaCtDivCi + minSum / boxArea; 588 float ratio = newCost / oldCost; 589 590 591 #if 0 592 Debug << "====================" << endl; 593 Debug << "costRatio=" << ratio << " pos=" << position<<" t=" << (position - minBox)/(maxBox - minBox) 594 << "\t o=(" << objectsBack << "," << objectsFront << ")" << endl; 595 #endif 596 return ratio; 597 } 598 599 bool VspBspTree::SelectAxisAlignedPlane(Plane3 &plane, 600 const PolygonContainer &polys) const 601 { 602 AxisAlignedBox3 box; 603 box.Initialize(); 604 605 // create bounding box of region 606 Polygon3::IncludeInBox(polys, box); 607 608 int objectsBack = 0, objectsFront = 0; 609 int axis = 0; 610 float costRatio = MAX_FLOAT; 611 Vector3 position; 612 613 //-- area subdivision 614 for (int i = 0; i < 3; ++ i) 615 { 616 float p = 0; 617 float r = BestCostRatio(polys, box, i, p, objectsBack, objectsFront); 618 619 if (r < costRatio) 620 { 621 costRatio = r; 622 axis = i; 623 position = p; 624 } 625 } 626 627 if (costRatio >= mMaxCostRatio) 628 return false; 629 630 Vector3 norm(0,0,0); norm[axis] = 1.0f; 631 plane = Plane3(norm, position); 632 633 return true; 634 } 635 636 Plane3 VspBspTree::SelectPlane(BspLeaf *leaf, VspBspTraversalData &data) 637 { 638 if ((mSplitPlaneStrategy & AXIS_ALIGNED) && 639 ((int)data.mRays->size() > mTermMinRaysForAxisAligned)) 640 { 641 Plane3 plane; 642 if (SelectAxisAlignedPlane(plane, *data.mPolygons)) // TODO: should be rays 643 return plane; 644 } 645 646 // simplest strategy: just take next polygon 647 if (mSplitPlaneStrategy & RANDOM_POLYGON) 648 { 649 if (!data.mPolygons->empty()) 650 { 651 const int randIdx = Random((int)data.mPolygons->size()); 652 Polygon3 *nextPoly = (*data.mPolygons)[randIdx]; 653 return nextPoly->GetSupportingPlane(); 654 } 655 else 656 { 657 //-- choose plane on midpoint of a ray 658 const int candidateIdx = Random((int)data.mRays->size()); 659 660 const Vector3 minPt = (*data.mRays)[candidateIdx].ExtrapOrigin(); 661 const Vector3 maxPt = (*data.mRays)[candidateIdx].ExtrapTermination(); 662 663 const Vector3 pt = (maxPt + minPt) * 0.5; 664 665 const Vector3 normal = (*data.mRays)[candidateIdx].mRay->GetDir(); 666 667 return Plane3(normal, pt); 668 } 669 670 return Plane3(); 671 } 672 673 // use heuristics to find appropriate plane 674 return SelectPlaneHeuristics(leaf, data); 675 } 676 677 Plane3 VspBspTree::SelectPlaneHeuristics(BspLeaf *leaf, VspBspTraversalData &data) 678 { 679 float lowestCost = MAX_FLOAT; 680 Plane3 bestPlane; 681 Plane3 plane; 682 683 int limit = Min((int)data.mPolygons->size(), mMaxPolyCandidates); 684 685 int candidateIdx = limit; 686 687 for (int i = 0; i < limit; ++ i) 688 { 689 candidateIdx = GetNextCandidateIdx(candidateIdx, *data.mPolygons); 690 691 Polygon3 *poly = (*data.mPolygons)[candidateIdx]; 692 693 // evaluate current candidate 694 const float candidateCost = 695 SplitPlaneCost(poly->GetSupportingPlane(), data); 696 697 if (candidateCost < lowestCost) 698 { 699 bestPlane = poly->GetSupportingPlane(); 700 lowestCost = candidateCost; 701 } 702 } 703 704 //Debug << "lowest: " << lowestCost << endl; 705 706 //-- choose candidate planes extracted from rays 707 // we currently use different two methods chosen with 708 // equal probability 709 710 // take 3 ray endpoints, where two are minimum and one a maximum 711 // point or the other way round 712 for (int i = 0; i < mMaxRayCandidates / 2; ++ i) 713 { 714 candidateIdx = Random((int)data.mRays->size()); 715 716 RayInfo rayInf = (*data.mRays)[candidateIdx]; 717 718 const Vector3 minPt = rayInf.ExtrapOrigin(); 719 const Vector3 maxPt = rayInf.ExtrapTermination(); 720 721 const Vector3 pt = (maxPt + minPt) * 0.5; 722 const Vector3 normal = Normalize(rayInf.mRay->GetDir()); 723 724 plane = Plane3(normal, pt); 725 726 const float candidateCost = SplitPlaneCost(plane, data); 727 728 if (candidateCost < lowestCost) 729 { 730 bestPlane = plane; 731 lowestCost = candidateCost; 732 } 733 } 734 735 // take plane normal as plane normal and the midpoint of the ray. 736 // PROBLEM: does not resemble any point where visibility is likely to change 737 //Debug << "lowest2: " << lowestCost << endl; 738 for (int i = 0; i < mMaxRayCandidates / 2; ++ i) 739 { 740 Vector3 pt[3]; 741 int idx[3]; 742 int cmaxT = 0; 743 int cminT = 0; 744 bool chooseMin = false; 745 746 for (int j = 0; j < 3; j ++) 747 { 748 idx[j] = Random((int)data.mRays->size() * 2); 749 750 if (idx[j] >= (int)data.mRays->size()) 751 { 752 idx[j] -= (int)data.mRays->size(); 753 754 chooseMin = (cminT < 2); 755 } 756 else 757 chooseMin = (cmaxT < 2); 758 759 RayInfo rayInf = (*data.mRays)[idx[j]]; 760 pt[j] = chooseMin ? rayInf.ExtrapOrigin() : rayInf.ExtrapTermination(); 761 } 762 763 plane = Plane3(pt[0], pt[1], pt[2]); 764 765 const float candidateCost = SplitPlaneCost(plane, data); 766 767 if (candidateCost < lowestCost) 768 { 769 //Debug << "choose ray plane 2: " << candidateCost << endl; 770 bestPlane = plane; 771 772 lowestCost = candidateCost; 773 } 774 } 775 776 #ifdef _DEBUG 777 Debug << "plane lowest cost: " << lowestCost << endl; 778 #endif 779 return bestPlane; 780 } 781 782 int VspBspTree::GetNextCandidateIdx(int currentIdx, PolygonContainer &polys) 783 { 784 const int candidateIdx = Random(currentIdx --); 785 786 // swap candidates to avoid testing same plane 2 times 787 std::swap(polys[currentIdx], polys[candidateIdx]); 788 789 return currentIdx; 790 //return Random((int)polys.size()); 791 } 792 793 794 inline void VspBspTree::GenerateUniqueIdsForPvs() 795 { 796 Intersectable::NewMail(); sBackId = ViewCell::sMailId; 797 Intersectable::NewMail(); sFrontId = ViewCell::sMailId; 798 Intersectable::NewMail(); sFrontAndBackId = ViewCell::sMailId; 799 } 800 801 float VspBspTree::SplitPlaneCost(const Plane3 &candidatePlane, 802 const VspBspTraversalData &data) 803 { 804 float val = 0; 805 806 float sumBalancedRays = 0; 807 float sumRaySplits = 0; 808 809 int frontPvs = 0; 810 int backPvs = 0; 811 812 // probability that view point lies in child 813 float pOverall = 0; 814 float pFront = 0; 815 float pBack = 0; 816 817 const bool pvsUseLen = false; 818 819 if (mSplitPlaneStrategy & PVS) 820 { 821 // create unique ids for pvs heuristics 822 GenerateUniqueIdsForPvs(); 823 824 if (mPvsUseArea) // use front and back cell areas to approximate volume 825 { 826 // construct child geometry with regard to the candidate split plane 827 BspNodeGeometry frontCell; 828 BspNodeGeometry backCell; 829 830 data.mGeometry->SplitGeometry(frontCell, 831 backCell, 832 candidatePlane, 833 mBox, 834 mEpsilon); 835 836 pFront = frontCell.GetArea(); 837 pBack = backCell.GetArea(); 838 839 pOverall = data.mArea; 840 } 841 } 842 843 int limit; 844 bool useRand; 845 846 // choose test polyongs randomly if over threshold 847 if ((int)data.mRays->size() > mMaxTests) 848 { 849 useRand = true; 850 limit = mMaxTests; 851 } 99 852 else 100 mFront = newChild; 101 } 102 103 void VspBspInterior::SetupChildLinks(VspBspNode *b, VspBspNode *f) 104 { 105 mBack = b; 106 mFront = f; 107 } 108 109 int VspBspInterior::SplitPolygons(PolygonContainer &polys, 110 PolygonContainer &frontPolys, 111 PolygonContainer &backPolys, 112 PolygonContainer &coincident) 853 { 854 useRand = false; 855 limit = (int)data.mRays->size(); 856 } 857 858 for (int i = 0; i < limit; ++ i) 859 { 860 const int testIdx = useRand ? Random(limit) : i; 861 RayInfo rayInf = (*data.mRays)[testIdx]; 862 863 VssRay *ray = rayInf.mRay; 864 const int cf = rayInf.ComputeRayIntersection(candidatePlane, ray->mT); 865 866 if (mSplitPlaneStrategy & LEAST_RAY_SPLITS) 867 { 868 sumBalancedRays += cf; 869 } 870 871 if (mSplitPlaneStrategy & BALANCED_RAYS) 872 { 873 if (cf == 0) 874 ++ sumRaySplits; 875 } 876 877 if (mSplitPlaneStrategy & PVS) 878 { 879 // in case the ray intersects an object 880 // assure that we only count the object 881 // once for the front and once for the back side of the plane 882 883 // add the termination object 884 AddObjToPvs(ray->mTerminationObject, cf, frontPvs, backPvs); 885 886 // add the source object 887 AddObjToPvs(ray->mOriginObject, cf, frontPvs, backPvs); 888 889 // use number or length of rays to approximate volume 890 if (!mPvsUseArea) 891 { 892 float len = 1; 893 894 if (pvsUseLen) // use length of rays 895 len = rayInf.SqrSegmentLength(); 896 897 pOverall += len; 898 899 if (cf == 1) 900 pFront += len; 901 if (cf == -1) 902 pBack += len; 903 if (cf == 0) 904 { 905 // use length of rays to approximate volume 906 if (pvsUseLen) 907 { 908 float newLen = len * 909 (rayInf.GetMaxT() - rayInf.mRay->mT) / 910 (rayInf.GetMaxT() - rayInf.GetMinT()); 911 912 if (candidatePlane.Side(rayInf.ExtrapOrigin()) <= 0) 913 { 914 pBack += newLen; 915 pFront += len - newLen; 916 } 917 else 918 { 919 pFront += newLen; 920 pBack += len - newLen; 921 } 922 } 923 else 924 { 925 ++ pFront; 926 ++ pBack; 927 } 928 } 929 } 930 } 931 } 932 933 const float raysSize = (float)data.mRays->size() + Limits::Small; 934 935 if (mSplitPlaneStrategy & LEAST_RAY_SPLITS) 936 val += mLeastRaySplitsFactor * sumRaySplits / raysSize; 937 938 if (mSplitPlaneStrategy & BALANCED_RAYS) 939 val += mBalancedRaysFactor * fabs(sumBalancedRays) / raysSize; 940 941 const float denom = pOverall * (float)data.mPvs * 2.0f + Limits::Small; 942 943 if (mSplitPlaneStrategy & PVS) 944 { 945 val += mPvsFactor * (frontPvs * pFront + (backPvs * pBack)) / denom; 946 947 // give penalty to unbalanced split 948 if (1) 949 if (((pFront * 0.2 + Limits::Small) > pBack) || 950 (pFront < (pBack * 0.2 + Limits::Small))) 951 val += 0.5; 952 } 953 954 #ifdef _DEBUG 955 Debug << "totalpvs: " << pvs << " ptotal: " << pOverall 956 << " frontpvs: " << frontPvs << " pFront: " << pFront 957 << " backpvs: " << backPvs << " pBack: " << pBack << endl << endl; 958 #endif 959 return val; 960 } 961 962 void VspBspTree::AddObjToPvs(Intersectable *obj, 963 const int cf, 964 int &frontPvs, 965 int &backPvs) const 966 { 967 if (!obj) 968 return; 969 // TODO: does this really belong to no pvs? 970 //if (cf == Ray::COINCIDENT) return; 971 972 // object belongs to both PVS 973 if (cf >= 0) 974 { 975 if ((obj->mMailbox != sFrontId) && 976 (obj->mMailbox != sFrontAndBackId)) 977 { 978 ++ frontPvs; 979 980 if (obj->mMailbox == sBackId) 981 obj->mMailbox = sFrontAndBackId; 982 else 983 obj->mMailbox = sFrontId; 984 } 985 } 986 987 if (cf <= 0) 988 { 989 if ((obj->mMailbox != sBackId) && 990 (obj->mMailbox != sFrontAndBackId)) 991 { 992 ++ backPvs; 993 994 if (obj->mMailbox == sFrontId) 995 obj->mMailbox = sFrontAndBackId; 996 else 997 obj->mMailbox = sBackId; 998 } 999 } 1000 } 1001 1002 void VspBspTree::CollectLeaves(vector<BspLeaf *> &leaves) const 1003 { 1004 stack<BspNode *> nodeStack; 1005 nodeStack.push(mRoot); 1006 1007 while (!nodeStack.empty()) 1008 { 1009 BspNode *node = nodeStack.top(); 1010 1011 nodeStack.pop(); 1012 1013 if (node->IsLeaf()) 1014 { 1015 BspLeaf *leaf = (BspLeaf *)node; 1016 leaves.push_back(leaf); 1017 } 1018 else 1019 { 1020 BspInterior *interior = dynamic_cast<BspInterior *>(node); 1021 1022 nodeStack.push(interior->GetBack()); 1023 nodeStack.push(interior->GetFront()); 1024 } 1025 } 1026 } 1027 1028 AxisAlignedBox3 VspBspTree::GetBoundingBox() const 1029 { 1030 return mBox; 1031 } 1032 1033 BspNode *VspBspTree::GetRoot() const 1034 { 1035 return mRoot; 1036 } 1037 1038 void VspBspTree::EvaluateLeafStats(const VspBspTraversalData &data) 1039 { 1040 // the node became a leaf -> evaluate stats for leafs 1041 BspLeaf *leaf = dynamic_cast<BspLeaf *>(data.mNode); 1042 1043 // store maximal and minimal depth 1044 if (data.mDepth > mStat.maxDepth) 1045 mStat.maxDepth = data.mDepth; 1046 1047 if (data.mDepth < mStat.minDepth) 1048 mStat.minDepth = data.mDepth; 1049 1050 // accumulate depth to compute average depth 1051 mStat.accumDepth += data.mDepth; 1052 1053 1054 if (data.mDepth >= mTermMaxDepth) 1055 ++ mStat.maxDepthNodes; 1056 1057 if (data.mPvs < mTermMinPvs) 1058 ++ mStat.minPvsNodes; 1059 1060 if ((int)data.mRays->size() < mTermMinRays) 1061 ++ mStat.minRaysNodes; 1062 1063 if (data.GetAvgRayContribution() > mTermMaxRayContribution) 1064 ++ mStat.maxRayContribNodes; 1065 1066 if (data.mGeometry->GetArea() <= mTermMinArea) 1067 ++ mStat.minAreaNodes; 1068 1069 #ifdef _DEBUG 1070 Debug << "BSP stats: " 1071 << "Depth: " << data.mDepth << " (max: " << mTermMaxDepth << "), " 1072 << "PVS: " << data.mPvs << " (min: " << mTermMinPvs << "), " 1073 << "Area: " << data.mArea << " (min: " << mTermMinArea << "), " 1074 << "#rays: " << (int)data.mRays->size() << " (max: " << mTermMinRays << "), " 1075 << "#pvs: " << leaf->GetViewCell()->GetPvs().GetSize() << "=, " 1076 << "#avg ray contrib (pvs): " << (float)data.mPvs / (float)data.mRays->size() << endl; 1077 #endif 1078 } 1079 1080 int VspBspTree::CastRay(Ray &ray) 1081 { 1082 int hits = 0; 1083 1084 stack<BspRayTraversalData> tStack; 1085 1086 float maxt, mint; 1087 1088 if (!mBox.GetRaySegment(ray, mint, maxt)) 1089 return 0; 1090 1091 Intersectable::NewMail(); 1092 1093 Vector3 entp = ray.Extrap(mint); 1094 Vector3 extp = ray.Extrap(maxt); 1095 1096 BspNode *node = mRoot; 1097 BspNode *farChild = NULL; 1098 1099 while (1) 1100 { 1101 if (!node->IsLeaf()) 1102 { 1103 BspInterior *in = dynamic_cast<BspInterior *>(node); 1104 1105 Plane3 splitPlane = in->GetPlane(); 1106 const int entSide = splitPlane.Side(entp); 1107 const int extSide = splitPlane.Side(extp); 1108 1109 if (entSide < 0) 1110 { 1111 node = in->GetBack(); 1112 1113 if(extSide <= 0) // plane does not split ray => no far child 1114 continue; 1115 1116 farChild = in->GetFront(); // plane splits ray 1117 1118 } else if (entSide > 0) 1119 { 1120 node = in->GetFront(); 1121 1122 if (extSide >= 0) // plane does not split ray => no far child 1123 continue; 1124 1125 farChild = in->GetBack(); // plane splits ray 1126 } 1127 else // ray and plane are coincident 1128 { 1129 // WHAT TO DO IN THIS CASE ? 1130 //break; 1131 node = in->GetFront(); 1132 continue; 1133 } 1134 1135 // push data for far child 1136 tStack.push(BspRayTraversalData(farChild, extp, maxt)); 1137 1138 // find intersection of ray segment with plane 1139 float t; 1140 extp = splitPlane.FindIntersection(ray.GetLoc(), extp, &t); 1141 maxt *= t; 1142 1143 } else // reached leaf => intersection with view cell 1144 { 1145 BspLeaf *leaf = dynamic_cast<BspLeaf *>(node); 1146 1147 if (!leaf->GetViewCell()->Mailed()) 1148 { 1149 //ray.bspIntersections.push_back(Ray::VspBspIntersection(maxt, leaf)); 1150 leaf->GetViewCell()->Mail(); 1151 ++ hits; 1152 } 1153 1154 //-- fetch the next far child from the stack 1155 if (tStack.empty()) 1156 break; 1157 1158 entp = extp; 1159 mint = maxt; // NOTE: need this? 1160 1161 if (ray.GetType() == Ray::LINE_SEGMENT && mint > 1.0f) 1162 break; 1163 1164 BspRayTraversalData &s = tStack.top(); 1165 1166 node = s.mNode; 1167 extp = s.mExitPoint; 1168 maxt = s.mMaxT; 1169 1170 tStack.pop(); 1171 } 1172 } 1173 1174 return hits; 1175 } 1176 1177 bool VspBspTree::Export(const string filename) 1178 { 1179 Exporter *exporter = Exporter::GetExporter(filename); 1180 1181 if (exporter) 1182 { 1183 //exporter->ExportVspBspTree(*this); 1184 return true; 1185 } 1186 1187 return false; 1188 } 1189 1190 void VspBspTree::CollectViewCells(ViewCellContainer &viewCells) const 1191 { 1192 stack<BspNode *> nodeStack; 1193 nodeStack.push(mRoot); 1194 1195 ViewCell::NewMail(); 1196 1197 while (!nodeStack.empty()) 1198 { 1199 BspNode *node = nodeStack.top(); 1200 nodeStack.pop(); 1201 1202 if (node->IsLeaf()) 1203 { 1204 ViewCell *viewCell = dynamic_cast<BspLeaf *>(node)->GetViewCell(); 1205 1206 if (!viewCell->Mailed()) 1207 { 1208 viewCell->Mail(); 1209 viewCells.push_back(viewCell); 1210 } 1211 } 1212 else 1213 { 1214 BspInterior *interior = dynamic_cast<BspInterior *>(node); 1215 1216 nodeStack.push(interior->GetFront()); 1217 nodeStack.push(interior->GetBack()); 1218 } 1219 } 1220 } 1221 1222 void VspBspTree::EvaluateViewCellsStats(BspViewCellsStatistics &stat) const 1223 { 1224 stat.Reset(); 1225 1226 stack<BspNode *> nodeStack; 1227 nodeStack.push(mRoot); 1228 1229 ViewCell::NewMail(); 1230 1231 // exclude root cell 1232 mRootCell->Mail(); 1233 1234 while (!nodeStack.empty()) 1235 { 1236 BspNode *node = nodeStack.top(); 1237 nodeStack.pop(); 1238 1239 if (node->IsLeaf()) 1240 { 1241 ++ stat.bspLeaves; 1242 1243 BspViewCell *viewCell = dynamic_cast<BspLeaf *>(node)->GetViewCell(); 1244 1245 if (!viewCell->Mailed()) 1246 { 1247 viewCell->Mail(); 1248 1249 ++ stat.viewCells; 1250 const int pvsSize = viewCell->GetPvs().GetSize(); 1251 1252 stat.pvs += pvsSize; 1253 1254 if (pvsSize < 1) 1255 ++ stat.emptyPvs; 1256 1257 if (pvsSize > stat.maxPvs) 1258 stat.maxPvs = pvsSize; 1259 1260 if (pvsSize < stat.minPvs) 1261 stat.minPvs = pvsSize; 1262 1263 if ((int)viewCell->mBspLeaves.size() > stat.maxBspLeaves) 1264 stat.maxBspLeaves = (int)viewCell->mBspLeaves.size(); 1265 } 1266 } 1267 else 1268 { 1269 BspInterior *interior = dynamic_cast<BspInterior *>(node); 1270 1271 nodeStack.push(interior->GetFront()); 1272 nodeStack.push(interior->GetBack()); 1273 } 1274 } 1275 } 1276 1277 BspTreeStatistics &VspBspTree::GetStat() 1278 { 1279 return mStat; 1280 } 1281 1282 float VspBspTree::AccumulatedRayLength(const RayInfoContainer &rays) const 1283 { 1284 float len = 0; 1285 1286 RayInfoContainer::const_iterator it, it_end = rays.end(); 1287 1288 for (it = rays.begin(); it != it_end; ++ it) 1289 len += (*it).SegmentLength(); 1290 1291 return len; 1292 } 1293 1294 int VspBspTree::SplitRays(const Plane3 &plane, 1295 RayInfoContainer &rays, 1296 RayInfoContainer &frontRays, 1297 RayInfoContainer &backRays) 1298 { 1299 int splits = 0; 1300 1301 while (!rays.empty()) 1302 { 1303 RayInfo bRay = rays.back(); 1304 VssRay *ray = bRay.mRay; 1305 1306 rays.pop_back(); 1307 1308 // get classification and receive new t 1309 const int cf = bRay.ComputeRayIntersection(plane, ray->mT); 1310 1311 switch (cf) 1312 { 1313 case -1: 1314 backRays.push_back(bRay); 1315 break; 1316 case 1: 1317 frontRays.push_back(bRay); 1318 break; 1319 case 0: 1320 //-- split ray 1321 1322 // if start point behind plane 1323 if (plane.Side(bRay.ExtrapOrigin()) <= 0) 1324 { 1325 backRays.push_back(RayInfo(ray, bRay.GetMinT(), ray->mT)); 1326 frontRays.push_back(RayInfo(ray, ray->mT, bRay.GetMaxT())); 1327 } 1328 else 1329 { 1330 frontRays.push_back(RayInfo(ray, bRay.GetMinT(), ray->mT)); 1331 backRays.push_back(RayInfo(ray, ray->mT, bRay.GetMaxT())); 1332 } 1333 break; 1334 default: 1335 Debug << "Should not come here 4" << endl; 1336 break; 1337 } 1338 } 1339 1340 return splits; 1341 } 1342 1343 void VspBspTree::ExtractHalfSpaces(BspNode *n, vector<Plane3> &halfSpaces) const 1344 { 1345 BspNode *lastNode; 1346 1347 do 1348 { 1349 lastNode = n; 1350 1351 // want to get planes defining geometry of this node => don't take 1352 // split plane of node itself 1353 n = n->GetParent(); 1354 1355 if (n) 1356 { 1357 BspInterior *interior = dynamic_cast<BspInterior *>(n); 1358 Plane3 halfSpace = dynamic_cast<BspInterior *>(interior)->GetPlane(); 1359 1360 if (interior->GetFront() != lastNode) 1361 halfSpace.ReverseOrientation(); 1362 1363 halfSpaces.push_back(halfSpace); 1364 } 1365 } 1366 while (n); 1367 } 1368 1369 void VspBspTree::ConstructGeometry(BspNode *n, 1370 BspNodeGeometry &cell) const 1371 { 1372 PolygonContainer polys; 1373 ConstructGeometry(n, polys); 1374 cell.mPolys = polys; 1375 } 1376 1377 void VspBspTree::ConstructGeometry(BspNode *n, 1378 PolygonContainer &cell) const 1379 { 1380 vector<Plane3> halfSpaces; 1381 ExtractHalfSpaces(n, halfSpaces); 1382 1383 PolygonContainer candidatePolys; 1384 1385 // bounded planes are added to the polygons (reverse polygons 1386 // as they have to be outfacing 1387 for (int i = 0; i < (int)halfSpaces.size(); ++ i) 1388 { 1389 Polygon3 *p = GetBoundingBox().CrossSection(halfSpaces[i]); 1390 1391 if (p->Valid(mEpsilon)) 1392 { 1393 candidatePolys.push_back(p->CreateReversePolygon()); 1394 DEL_PTR(p); 1395 } 1396 } 1397 1398 // add faces of bounding box (also could be faces of the cell) 1399 for (int i = 0; i < 6; ++ i) 1400 { 1401 VertexContainer vertices; 1402 1403 for (int j = 0; j < 4; ++ j) 1404 vertices.push_back(mBox.GetFace(i).mVertices[j]); 1405 1406 candidatePolys.push_back(new Polygon3(vertices)); 1407 } 1408 1409 for (int i = 0; i < (int)candidatePolys.size(); ++ i) 1410 { 1411 // polygon is split by all other planes 1412 for (int j = 0; (j < (int)halfSpaces.size()) && candidatePolys[i]; ++ j) 1413 { 1414 if (i == j) // polygon and plane are coincident 1415 continue; 1416 1417 VertexContainer splitPts; 1418 Polygon3 *frontPoly, *backPoly; 1419 1420 const int cf = 1421 candidatePolys[i]->ClassifyPlane(halfSpaces[j], 1422 mEpsilon); 1423 1424 switch (cf) 1425 { 1426 case Polygon3::SPLIT: 1427 frontPoly = new Polygon3(); 1428 backPoly = new Polygon3(); 1429 1430 candidatePolys[i]->Split(halfSpaces[j], 1431 *frontPoly, 1432 *backPoly, 1433 mEpsilon); 1434 1435 DEL_PTR(candidatePolys[i]); 1436 1437 if (frontPoly->Valid(mEpsilon)) 1438 candidatePolys[i] = frontPoly; 1439 else 1440 DEL_PTR(frontPoly); 1441 1442 DEL_PTR(backPoly); 1443 break; 1444 case Polygon3::BACK_SIDE: 1445 DEL_PTR(candidatePolys[i]); 1446 break; 1447 // just take polygon as it is 1448 case Polygon3::FRONT_SIDE: 1449 case Polygon3::COINCIDENT: 1450 default: 1451 break; 1452 } 1453 } 1454 1455 if (candidatePolys[i]) 1456 cell.push_back(candidatePolys[i]); 1457 } 1458 } 1459 1460 void VspBspTree::ConstructGeometry(BspViewCell *vc, PolygonContainer &vcGeom) const 1461 { 1462 vector<BspLeaf *> leaves = vc->mBspLeaves; 1463 1464 vector<BspLeaf *>::const_iterator it, it_end = leaves.end(); 1465 1466 for (it = leaves.begin(); it != it_end; ++ it) 1467 ConstructGeometry(*it, vcGeom); 1468 } 1469 1470 int VspBspTree::FindNeighbors(BspNode *n, vector<BspLeaf *> &neighbors, 1471 const bool onlyUnmailed) const 1472 { 1473 PolygonContainer cell; 1474 1475 ConstructGeometry(n, cell); 1476 1477 stack<BspNode *> nodeStack; 1478 nodeStack.push(mRoot); 1479 1480 // planes needed to verify that we found neighbor leaf. 1481 vector<Plane3> halfSpaces; 1482 ExtractHalfSpaces(n, halfSpaces); 1483 1484 while (!nodeStack.empty()) 1485 { 1486 BspNode *node = nodeStack.top(); 1487 nodeStack.pop(); 1488 1489 if (node->IsLeaf()) 1490 { 1491 if (node != n && (!onlyUnmailed || !node->Mailed())) 1492 { 1493 // test all planes of current node if candidate really 1494 // is neighbour 1495 PolygonContainer neighborCandidate; 1496 ConstructGeometry(node, neighborCandidate); 1497 1498 bool isAdjacent = true; 1499 for (int i = 0; (i < halfSpaces.size()) && isAdjacent; ++ i) 1500 { 1501 const int cf = 1502 Polygon3::ClassifyPlane(neighborCandidate, 1503 halfSpaces[i], 1504 mEpsilon); 1505 1506 if (cf == Polygon3::BACK_SIDE) 1507 isAdjacent = false; 1508 } 1509 1510 if (isAdjacent) 1511 neighbors.push_back(dynamic_cast<BspLeaf *>(node)); 1512 1513 CLEAR_CONTAINER(neighborCandidate); 1514 } 1515 } 1516 else 1517 { 1518 BspInterior *interior = dynamic_cast<BspInterior *>(node); 1519 1520 const int cf = Polygon3::ClassifyPlane(cell, 1521 interior->GetPlane(), 1522 mEpsilon); 1523 1524 if (cf == Polygon3::FRONT_SIDE) 1525 nodeStack.push(interior->GetFront()); 1526 else 1527 if (cf == Polygon3::BACK_SIDE) 1528 nodeStack.push(interior->GetBack()); 1529 else 1530 { 1531 // random decision 1532 nodeStack.push(interior->GetBack()); 1533 nodeStack.push(interior->GetFront()); 1534 } 1535 } 1536 } 1537 1538 CLEAR_CONTAINER(cell); 1539 return (int)neighbors.size(); 1540 } 1541 1542 BspLeaf *VspBspTree::GetRandomLeaf(const Plane3 &halfspace) 1543 { 1544 stack<BspNode *> nodeStack; 1545 nodeStack.push(mRoot); 1546 1547 int mask = rand(); 1548 1549 while (!nodeStack.empty()) 1550 { 1551 BspNode *node = nodeStack.top(); 1552 nodeStack.pop(); 1553 1554 if (node->IsLeaf()) 1555 { 1556 return dynamic_cast<BspLeaf *>(node); 1557 } 1558 else 1559 { 1560 BspInterior *interior = dynamic_cast<BspInterior *>(node); 1561 1562 BspNode *next; 1563 1564 PolygonContainer cell; 1565 1566 // todo: not very efficient: constructs full cell everytime 1567 ConstructGeometry(interior, cell); 1568 1569 const int cf = Polygon3::ClassifyPlane(cell, halfspace, mEpsilon); 1570 1571 if (cf == Polygon3::BACK_SIDE) 1572 next = interior->GetFront(); 1573 else 1574 if (cf == Polygon3::FRONT_SIDE) 1575 next = interior->GetFront(); 1576 else 1577 { 1578 // random decision 1579 if (mask & 1) 1580 next = interior->GetBack(); 1581 else 1582 next = interior->GetFront(); 1583 mask = mask >> 1; 1584 } 1585 1586 nodeStack.push(next); 1587 } 1588 } 1589 1590 return NULL; 1591 } 1592 1593 BspLeaf *VspBspTree::GetRandomLeaf(const bool onlyUnmailed) 1594 { 1595 stack<BspNode *> nodeStack; 1596 1597 nodeStack.push(mRoot); 1598 1599 int mask = rand(); 1600 1601 while (!nodeStack.empty()) 1602 { 1603 BspNode *node = nodeStack.top(); 1604 nodeStack.pop(); 1605 1606 if (node->IsLeaf()) 1607 { 1608 if ( (!onlyUnmailed || !node->Mailed()) ) 1609 return dynamic_cast<BspLeaf *>(node); 1610 } 1611 else 1612 { 1613 BspInterior *interior = dynamic_cast<BspInterior *>(node); 1614 1615 // random decision 1616 if (mask & 1) 1617 nodeStack.push(interior->GetBack()); 1618 else 1619 nodeStack.push(interior->GetFront()); 1620 1621 mask = mask >> 1; 1622 } 1623 } 1624 1625 return NULL; 1626 } 1627 1628 int VspBspTree::ComputePvsSize(const RayInfoContainer &rays) const 1629 { 1630 int pvsSize = 0; 1631 1632 RayInfoContainer::const_iterator rit, rit_end = rays.end(); 1633 1634 Intersectable::NewMail(); 1635 1636 for (rit = rays.begin(); rit != rays.end(); ++ rit) 1637 { 1638 VssRay *ray = (*rit).mRay; 1639 1640 if (ray->mOriginObject) 1641 { 1642 if (!ray->mOriginObject->Mailed()) 1643 { 1644 ray->mOriginObject->Mail(); 1645 ++ pvsSize; 1646 } 1647 } 1648 if (ray->mTerminationObject) 1649 { 1650 if (!ray->mTerminationObject->Mailed()) 1651 { 1652 ray->mTerminationObject->Mail(); 1653 ++ pvsSize; 1654 } 1655 } 1656 } 1657 1658 return pvsSize; 1659 } 1660 1661 float VspBspTree::GetEpsilon() const 1662 { 1663 return mEpsilon; 1664 } 1665 1666 BspViewCell *VspBspTree::GetRootCell() const 1667 { 1668 return mRootCell; 1669 } 1670 1671 int VspBspTree::SplitPolygons(const Plane3 &plane, 1672 PolygonContainer &polys, 1673 PolygonContainer &frontPolys, 1674 PolygonContainer &backPolys, 1675 PolygonContainer &coincident) const 113 1676 { 114 1677 int splits = 0; … … 120 1683 121 1684 // classify polygon 122 const int cf = poly->ClassifyPlane( mPlane);1685 const int cf = poly->ClassifyPlane(plane, mEpsilon); 123 1686 124 1687 switch (cf) … … 146 1709 return splits; 147 1710 } 148 149 /****************************************************************/150 /* class VspBspLeaf implementation */151 /****************************************************************/152 VspBspLeaf::VspBspLeaf(): mViewCell(NULL)153 {154 }155 156 VspBspLeaf::VspBspLeaf(BspViewCell *viewCell):157 mViewCell(viewCell)158 {159 }160 161 VspBspLeaf::VspBspLeaf(VspBspInterior *parent):162 VspBspNode(parent), mViewCell(NULL)163 {}164 165 VspBspLeaf::VspBspLeaf(VspBspInterior *parent, BspViewCell *viewCell):166 VspBspNode(parent), mViewCell(viewCell)167 {168 }169 170 BspViewCell *VspBspLeaf::GetViewCell() const171 {172 return mViewCell;173 }174 175 void VspBspLeaf::SetViewCell(BspViewCell *viewCell)176 {177 mViewCell = viewCell;178 }179 180 bool VspBspLeaf::IsLeaf() const181 {182 return true;183 }184 185 void VspBspLeaf::AddToPvs(const RayInfoContainer &rays,186 int &sampleContributions,187 int &contributingSamples,188 bool storeLeavesWithRays)189 {190 sampleContributions = 0;191 contributingSamples = 0;192 193 RayInfoContainer::const_iterator it, it_end = rays.end();194 195 // add contributions from samples to the PVS196 for (it = rays.begin(); it != it_end; ++ it)197 {198 int contribution = 0;199 VssRay *ray = (*it).mRay;200 201 if (ray->mTerminationObject)202 contribution += mViewCell->GetPvs().AddSample(ray->mTerminationObject);203 204 if (ray->mOriginObject)205 contribution += mViewCell->GetPvs().AddSample(ray->mOriginObject);206 207 if (contribution > 0)208 {209 sampleContributions += contribution;210 ++ contributingSamples;211 }212 }213 }214 215 216 /****************************************************************/217 /* class VspBspTree implementation */218 /****************************************************************/219 220 VspBspTree::VspBspTree():221 mRoot(NULL),222 mPvsUseArea(true)223 {224 mRootCell = new BspViewCell();225 226 Randomize(); // initialise random generator for heuristics227 228 //-- termination criteria for autopartition229 environment->GetIntValue("VspBspTree.Termination.maxDepth", mTermMaxDepth);230 environment->GetIntValue("VspBspTree.Termination.minPvs", mTermMinPvs);231 environment->GetIntValue("VspBspTree.Termination.minRays", mTermMinRays);232 environment->GetFloatValue("VspBspTree.Termination.minArea", mTermMinArea);233 environment->GetFloatValue("VspBspTree.Termination.maxRayContribution", mTermMaxRayContribution);234 environment->GetFloatValue("VspBspTree.Termination.minAccRayLenght", mTermMinAccRayLength);235 236 //-- factors for bsp tree split plane heuristics237 environment->GetFloatValue("VspBspTree.Factor.balancedRays", mBalancedRaysFactor);238 environment->GetFloatValue("VspBspTree.Factor.pvs", mPvsFactor);239 environment->GetFloatValue("VspBspTree.Termination.ct_div_ci", mCtDivCi);240 241 //-- termination criteria for axis aligned split242 environment->GetFloatValue("VspBspTree.Termination.AxisAligned.ct_div_ci", mAaCtDivCi);243 environment->GetFloatValue("VspBspTree.Termination.AxisAligned.maxCostRatio", mMaxCostRatio);244 245 environment->GetIntValue("VspBspTree.Termination.AxisAligned.minRays",246 mTermMinRaysForAxisAligned);247 248 //-- partition criteria249 environment->GetIntValue("VspBspTree.maxPolyCandidates", mMaxPolyCandidates);250 environment->GetIntValue("VspBspTree.maxRayCandidates", mMaxRayCandidates);251 environment->GetIntValue("VspBspTree.splitPlaneStrategy", mSplitPlaneStrategy);252 environment->GetFloatValue("VspBspTree.AxisAligned.splitBorder", mSplitBorder);253 254 environment->GetFloatValue("VspBspTree.Construction.sideTolerance", Vector3::sDistTolerance);255 Vector3::sDistToleranceSqrt = Vector3::sDistTolerance * Vector3::sDistTolerance;256 257 Debug << "BSP max depth: " << mTermMaxDepth << endl;258 Debug << "BSP min PVS: " << mTermMinPvs << endl;259 Debug << "BSP min area: " << mTermMinArea << endl;260 Debug << "BSP min rays: " << mTermMinRays << endl;261 Debug << "BSP max polygon candidates: " << mMaxPolyCandidates << endl;262 Debug << "BSP max plane candidates: " << mMaxRayCandidates << endl;263 264 Debug << "Split plane strategy: ";265 if (mSplitPlaneStrategy & RANDOM_POLYGON)266 Debug << "random polygon ";267 if (mSplitPlaneStrategy & AXIS_ALIGNED)268 Debug << "axis aligned ";269 if (mSplitPlaneStrategy & LEAST_RAY_SPLITS)270 Debug << "least ray splits ";271 if (mSplitPlaneStrategy & BALANCED_RAYS)272 Debug << "balanced rays ";273 if (mSplitPlaneStrategy & PVS)274 Debug << "pvs";275 276 Debug << endl;277 }278 279 280 const VspBspTreeStatistics &VspBspTree::GetStatistics() const281 {282 return mStat;283 }284 285 void VspBspTreeStatistics::Print(ostream &app) const286 {287 app << "===== VspBspTree statistics ===============\n";288 289 app << setprecision(4);290 291 app << "#N_CTIME ( Construction time [s] )\n" << Time() << " \n";292 293 app << "#N_NODES ( Number of nodes )\n" << nodes << "\n";294 295 app << "#N_INTERIORS ( Number of interior nodes )\n" << Interior() << "\n";296 297 app << "#N_LEAVES ( Number of leaves )\n" << Leaves() << "\n";298 299 app << "#N_SPLITS ( Number of splits )\n" << splits << "\n";300 301 app << "#N_PMAXDEPTHLEAVES ( Percentage of leaves at maximum depth )\n"302 << maxDepthNodes * 100 / (double)Leaves() << endl;303 304 app << "#N_PMAXDEPTHLEAVES ( Percentage of leaves at maximum depth )\n"305 << maxDepthNodes * 100 / (double)Leaves() << endl;306 307 app << "#N_PMINPVSLEAVES ( Percentage of leaves with mininimal PVS )\n"308 << minPvsNodes * 100 / (double)Leaves() << endl;309 310 app << "#N_PMINRAYSLEAVES ( Percentage of leaves with minimal number of rays)\n"311 << minRaysNodes * 100 / (double)Leaves() << endl;312 313 app << "#N_PMINAREALEAVES ( Percentage of leaves with mininum area )\n"314 << minAreaNodes * 100 / (double)Leaves() << endl;315 316 app << "#N_PMAXRAYCONTRIBLEAVES ( Percentage of leaves with maximal ray contribution )\n"317 << maxRayContribNodes * 100 / (double)Leaves() << endl;318 319 app << "#N_PMAXDEPTH ( Maximal reached depth )\n" << maxDepth << endl;320 321 app << "#N_PMINDEPTH ( Minimal reached depth )\n" << minDepth << endl;322 323 app << "#AVGDEPTH ( average depth )\n" << AvgDepth() << endl;324 325 app << "#N_INPUT_POLYGONS (number of input polygons )\n" << polys << endl;326 327 //app << "#N_PVS: " << pvs << endl;328 329 app << "#N_ROUTPUT_INPUT_POLYGONS ( ratio polygons after subdivision / input polygons )\n" <<330 (polys + splits) / (double)polys << endl;331 332 app << "===== END OF VspBspTree statistics ==========\n";333 }334 335 336 VspBspTree::~VspBspTree()337 {338 DEL_PTR(mRoot);339 DEL_PTR(mRootCell);340 }341 342 int VspBspTree::AddMeshToPolygons(Mesh *mesh, PolygonContainer &polys, MeshInstance *parent)343 {344 FaceContainer::const_iterator fi;345 346 // copy the face data to polygons347 for (fi = mesh->mFaces.begin(); fi != mesh->mFaces.end(); ++ fi)348 {349 Polygon3 *poly = new Polygon3((*fi), mesh);350 351 if (poly->Valid())352 {353 poly->mParent = parent; // set parent intersectable354 polys.push_back(poly);355 }356 else357 DEL_PTR(poly);358 }359 return (int)mesh->mFaces.size();360 }361 362 int VspBspTree::AddToPolygonSoup(const ViewCellContainer &viewCells,363 PolygonContainer &polys,364 int maxObjects)365 {366 int limit = (maxObjects > 0) ?367 Min((int)viewCells.size(), maxObjects) : (int)viewCells.size();368 369 int polysSize = 0;370 371 for (int i = 0; i < limit; ++ i)372 {373 if (viewCells[i]->GetMesh()) // copy the mesh data to polygons374 {375 mBox.Include(viewCells[i]->GetBox()); // add to BSP tree aabb376 polysSize += AddMeshToPolygons(viewCells[i]->GetMesh(), polys, viewCells[i]);377 }378 }379 380 return polysSize;381 }382 383 int VspBspTree::AddToPolygonSoup(const ObjectContainer &objects, PolygonContainer &polys, int maxObjects)384 {385 int limit = (maxObjects > 0) ? Min((int)objects.size(), maxObjects) : (int)objects.size();386 387 for (int i = 0; i < limit; ++i)388 {389 Intersectable *object = objects[i];//*it;390 Mesh *mesh = NULL;391 392 switch (object->Type()) // extract the meshes393 {394 case Intersectable::MESH_INSTANCE:395 mesh = dynamic_cast<MeshInstance *>(object)->GetMesh();396 break;397 case Intersectable::VIEW_CELL:398 mesh = dynamic_cast<ViewCell *>(object)->GetMesh();399 break;400 // TODO: handle transformed mesh instances401 default:402 Debug << "intersectable type not supported" << endl;403 break;404 }405 406 if (mesh) // copy the mesh data to polygons407 {408 mBox.Include(object->GetBox()); // add to BSP tree aabb409 AddMeshToPolygons(mesh, polys, mRootCell);410 }411 }412 413 return (int)polys.size();414 }415 416 void VspBspTree::Construct(const VssRayContainer &sampleRays)417 {418 mStat.nodes = 1;419 mBox.Initialize(); // initialise BSP tree bounding box420 421 PolygonContainer polys;422 RayInfoContainer *rays = new RayInfoContainer();423 424 VssRayContainer::const_iterator rit, rit_end = sampleRays.end();425 426 long startTime = GetTime();427 428 Debug << "**** Extracting polygons from rays ****\n";429 430 //-- extract polygons intersected by the rays431 for (rit = sampleRays.begin(); rit != rit_end; ++ rit)432 {433 VssRay *ray = *rit;434 435 if (ray->mTerminationObject)436 {437 MeshInstance *obj = dynamic_cast<MeshInstance *>(ray->mTerminationObject);438 AddMeshToPolygons(obj->GetMesh(), polys, obj);439 }440 441 if (ray->mOriginObject)442 {443 MeshInstance *obj = dynamic_cast<MeshInstance *>(ray->mOriginObject);444 AddMeshToPolygons(obj->GetMesh(), polys, obj);445 }446 }447 448 //-- store rays449 for (rit = sampleRays.begin(); rit != rit_end; ++ rit)450 {451 rays->push_back(RayInfo(*rit));452 }453 454 mStat.polys = (int)polys.size();455 456 Debug << "**** Finished polygon extraction ****" << endl;457 Debug << (int)polys.size() << " polys extracted from " << (int)sampleRays.size() << " rays" << endl;458 Debug << "extraction time: " << TimeDiff(startTime, GetTime())*1e-3 << "s" << endl;459 460 Construct(new PolygonContainer(polys), rays);461 462 // clean up polygons because they are not deleted in the tree463 CLEAR_CONTAINER(polys);464 }465 466 void VspBspTree::Construct(PolygonContainer *polys, RayInfoContainer *rays)467 {468 std::stack<VspBspTraversalData> tStack;469 470 mRoot = new VspBspLeaf();471 472 VspBspNodeGeometry *cell = new VspBspNodeGeometry();473 ConstructGeometry(mRoot, *cell);474 475 VspBspTraversalData tData(mRoot, polys, 0, mRootCell, rays,476 ComputePvsSize(*rays), cell->GetArea(), cell);477 478 tStack.push(tData);479 480 mStat.Start();481 cout << "Contructing bsp tree ... ";482 long startTime = GetTime();483 while (!tStack.empty())484 {485 tData = tStack.top();486 487 tStack.pop();488 489 // subdivide leaf node490 VspBspNode *r = Subdivide(tStack, tData);491 492 if (r == mRoot)493 Debug << "BSP tree construction time spent at root: " << TimeDiff(startTime, GetTime())*1e-3 << "s" << endl;494 }495 496 cout << "finished\n";497 498 mStat.Stop();499 }500 501 bool VspBspTree::TerminationCriteriaMet(const VspBspTraversalData &data) const502 {503 return504 (((int)data.mRays->size() <= mTermMinRays) ||505 (data.mPvs <= mTermMinPvs) ||506 (data.mArea <= mTermMinArea) ||507 (data.GetAvgRayContribution() >= mTermMaxRayContribution) ||508 (data.mDepth >= mTermMaxDepth));509 }510 511 VspBspNode *VspBspTree::Subdivide(VspBspTraversalStack &tStack, VspBspTraversalData &tData)512 {513 //-- terminate traversal514 if (TerminationCriteriaMet(tData))515 {516 VspBspLeaf *leaf = dynamic_cast<VspBspLeaf *>(tData.mNode);517 518 BspViewCell *viewCell = new BspViewCell();519 520 leaf->SetViewCell(viewCell);521 //TODO viewCell->mVspBspLeaves.push_back(leaf);522 523 //-- add pvs524 if (viewCell != mRootCell)525 {526 int conSamp = 0, sampCon = 0;527 leaf->AddToPvs(*tData.mRays, conSamp, sampCon);528 529 mStat.contributingSamples += conSamp;530 mStat.sampleContributions += sampCon;531 }532 533 EvaluateLeafStats(tData);534 535 //-- clean up536 537 DEL_PTR(tData.mPolygons);538 DEL_PTR(tData.mRays);539 DEL_PTR(tData.mGeometry);540 541 return leaf;542 }543 544 //-- continue subdivision545 PolygonContainer coincident;546 547 VspBspTraversalData tFrontData(NULL, new PolygonContainer(), tData.mDepth + 1, mRootCell,548 new RayInfoContainer(), 0, 0, new VspBspNodeGeometry());549 VspBspTraversalData tBackData(NULL, new PolygonContainer(), tData.mDepth + 1, mRootCell,550 new RayInfoContainer(), 0, 0, new VspBspNodeGeometry());551 552 // create new interior node and two leaf nodes553 VspBspInterior *interior =554 SubdivideNode(tData, tFrontData, tBackData, coincident);555 556 #ifdef _DEBUG557 if (frontPolys->empty() && backPolys->empty() && (coincident.size() > 2))558 { for (PolygonContainer::iterator it = coincident.begin(); it != coincident.end(); ++it)559 Debug << (*it) << " " << (*it)->GetArea() << " " << (*it)->mParent << endl ;560 Debug << endl;}561 #endif562 563 // don't need coincident polygons anymory564 CLEAR_CONTAINER(coincident);565 566 // push the children on the stack567 tStack.push(tFrontData);568 tStack.push(tBackData);569 570 // cleanup571 DEL_PTR(tData.mNode);572 DEL_PTR(tData.mPolygons);573 DEL_PTR(tData.mRays);574 DEL_PTR(tData.mGeometry);575 576 return interior;577 }578 579 VspBspInterior *VspBspTree::SubdivideNode(VspBspTraversalData &tData,580 VspBspTraversalData &frontData,581 VspBspTraversalData &backData,582 PolygonContainer &coincident)583 {584 mStat.nodes += 2;585 586 VspBspLeaf *leaf = dynamic_cast<VspBspLeaf *>(tData.mNode);587 // select subdivision plane588 VspBspInterior *interior =589 new VspBspInterior(SelectPlane(leaf, tData));590 591 #ifdef _DEBUG592 Debug << interior << endl;593 #endif594 595 // subdivide rays into front and back rays596 SplitRays(interior->mPlane, *tData.mRays, *frontData.mRays, *backData.mRays);597 598 // subdivide polygons with plane599 mStat.splits += interior->SplitPolygons(*tData.mPolygons,600 *frontData.mPolygons,601 *backData.mPolygons,602 coincident);603 604 // compute pvs605 frontData.mPvs = ComputePvsSize(*frontData.mRays);606 backData.mPvs = ComputePvsSize(*backData.mRays);607 608 // split geometry and compute area609 if (1)610 {611 tData.mGeometry->SplitGeometry(*frontData.mGeometry,612 *backData.mGeometry,613 *this,614 interior->mPlane);615 616 617 frontData.mArea = frontData.mGeometry->GetArea();618 backData.mArea = backData.mGeometry->GetArea();619 }620 621 // compute accumulated ray length622 //frontData.mAccRayLength = AccumulatedRayLength(*frontData.mRays);623 //backData.mAccRayLength = AccumulatedRayLength(*backData.mRays);624 625 //-- create front and back leaf626 627 VspBspInterior *parent = leaf->GetParent();628 629 // replace a link from node's parent630 if (!leaf->IsRoot())631 {632 parent->ReplaceChildLink(leaf, interior);633 interior->SetParent(parent);634 }635 else // new root636 {637 mRoot = interior;638 }639 640 // and setup child links641 interior->SetupChildLinks(new VspBspLeaf(interior), new VspBspLeaf(interior));642 643 frontData.mNode = interior->mFront;644 backData.mNode = interior->mBack;645 646 //DEL_PTR(leaf);647 return interior;648 }649 650 void VspBspTree::SortSplitCandidates(const PolygonContainer &polys,651 const int axis,652 vector<SortableEntry> &splitCandidates) const653 {654 splitCandidates.clear();655 656 int requestedSize = 2 * (int)polys.size();657 // creates a sorted split candidates array658 splitCandidates.reserve(requestedSize);659 660 PolygonContainer::const_iterator it, it_end = polys.end();661 662 AxisAlignedBox3 box;663 664 // insert all queries665 for(it = polys.begin(); it != it_end; ++ it)666 {667 box.Initialize();668 box.Include(*(*it));669 670 splitCandidates.push_back(SortableEntry(SortableEntry::POLY_MIN, box.Min(axis), *it));671 splitCandidates.push_back(SortableEntry(SortableEntry::POLY_MAX, box.Max(axis), *it));672 }673 674 stable_sort(splitCandidates.begin(), splitCandidates.end());675 }676 677 678 float VspBspTree::BestCostRatio(const PolygonContainer &polys,679 const AxisAlignedBox3 &box,680 const int axis,681 float &position,682 int &objectsBack,683 int &objectsFront) const684 {685 vector<SortableEntry> splitCandidates;686 687 SortSplitCandidates(polys, axis, splitCandidates);688 689 // go through the lists, count the number of objects left and right690 // and evaluate the following cost funcion:691 // C = ct_div_ci + (ol + or)/queries692 693 int objectsLeft = 0, objectsRight = (int)polys.size();694 695 float minBox = box.Min(axis);696 float maxBox = box.Max(axis);697 float boxArea = box.SurfaceArea();698 699 float minBand = minBox + mSplitBorder * (maxBox - minBox);700 float maxBand = minBox + (1.0f - mSplitBorder) * (maxBox - minBox);701 702 float minSum = 1e20f;703 vector<SortableEntry>::const_iterator ci, ci_end = splitCandidates.end();704 705 for(ci = splitCandidates.begin(); ci != ci_end; ++ ci)706 {707 switch ((*ci).type)708 {709 case SortableEntry::POLY_MIN:710 ++ objectsLeft;711 break;712 case SortableEntry::POLY_MAX:713 -- objectsRight;714 break;715 default:716 break;717 }718 719 if ((*ci).value > minBand && (*ci).value < maxBand)720 {721 AxisAlignedBox3 lbox = box;722 AxisAlignedBox3 rbox = box;723 lbox.SetMax(axis, (*ci).value);724 rbox.SetMin(axis, (*ci).value);725 726 float sum = objectsLeft * lbox.SurfaceArea() +727 objectsRight * rbox.SurfaceArea();728 729 if (sum < minSum)730 {731 minSum = sum;732 position = (*ci).value;733 734 objectsBack = objectsLeft;735 objectsFront = objectsRight;736 }737 }738 }739 740 float oldCost = (float)polys.size();741 float newCost = mAaCtDivCi + minSum / boxArea;742 float ratio = newCost / oldCost;743 744 745 #if 0746 Debug << "====================" << endl;747 Debug << "costRatio=" << ratio << " pos=" << position<<" t=" << (position - minBox)/(maxBox - minBox)748 << "\t o=(" << objectsBack << "," << objectsFront << ")" << endl;749 #endif750 return ratio;751 }752 753 bool VspBspTree::SelectAxisAlignedPlane(Plane3 &plane,754 const PolygonContainer &polys) const755 {756 AxisAlignedBox3 box;757 box.Initialize();758 759 // create bounding box of region760 Polygon3::IncludeInBox(polys, box);761 762 int objectsBack = 0, objectsFront = 0;763 int axis = 0;764 float costRatio = MAX_FLOAT;765 Vector3 position;766 767 //-- area subdivision768 for (int i = 0; i < 3; ++ i)769 {770 float p = 0;771 float r = BestCostRatio(polys, box, i, p, objectsBack, objectsFront);772 773 if (r < costRatio)774 {775 costRatio = r;776 axis = i;777 position = p;778 }779 }780 781 if (costRatio >= mMaxCostRatio)782 return false;783 784 Vector3 norm(0,0,0); norm[axis] = 1.0f;785 plane = Plane3(norm, position);786 787 return true;788 }789 790 Plane3 VspBspTree::SelectPlane(VspBspLeaf *leaf, VspBspTraversalData &data)791 {792 if ((mSplitPlaneStrategy & AXIS_ALIGNED) &&793 ((int)data.mRays->size() > mTermMinRaysForAxisAligned))794 {795 Plane3 plane;796 if (SelectAxisAlignedPlane(plane, *data.mPolygons)) // TODO: should be rays797 return plane;798 }799 800 // simplest strategy: just take next polygon801 if (mSplitPlaneStrategy & RANDOM_POLYGON)802 {803 if (!data.mPolygons->empty())804 {805 Polygon3 *nextPoly = (*data.mPolygons)[Random((int)data.mPolygons->size())];806 return nextPoly->GetSupportingPlane();807 }808 else809 {810 //-- choose plane on midpoint of a ray811 const int candidateIdx = Random((int)data.mRays->size());812 813 const Vector3 minPt = (*data.mRays)[candidateIdx].ExtrapOrigin();814 const Vector3 maxPt = (*data.mRays)[candidateIdx].ExtrapTermination();815 816 const Vector3 pt = (maxPt + minPt) * 0.5;817 818 const Vector3 normal = (*data.mRays)[candidateIdx].mRay->GetDir();819 820 return Plane3(normal, pt);821 }822 823 return Plane3();824 }825 826 // use heuristics to find appropriate plane827 return SelectPlaneHeuristics(leaf, data);828 }829 830 Plane3 VspBspTree::SelectPlaneHeuristics(VspBspLeaf *leaf, VspBspTraversalData &data)831 {832 float lowestCost = MAX_FLOAT;833 Plane3 bestPlane;834 Plane3 plane;835 836 int limit = Min((int)data.mPolygons->size(), mMaxPolyCandidates);837 838 int candidateIdx = limit;839 840 for (int i = 0; i < limit; ++ i)841 {842 candidateIdx = GetNextCandidateIdx(candidateIdx, *data.mPolygons);843 844 Polygon3 *poly = (*data.mPolygons)[candidateIdx];845 // evaluate current candidate846 const float candidateCost =847 SplitPlaneCost(poly->GetSupportingPlane(), data);848 849 if (candidateCost < lowestCost)850 {851 bestPlane = poly->GetSupportingPlane();852 lowestCost = candidateCost;853 }854 }855 856 //Debug << "lowest: " << lowestCost << endl;857 858 //-- choose candidate planes extracted from rays859 // we currently use different two methods chosen with860 // equal probability861 862 RayInfoContainer *rays = data.mRays;863 // take 3 ray endpoints, where two are minimum and one a maximum864 // point or the other way round865 for (int i = 0; i < mMaxRayCandidates / 2; ++ i)866 {867 candidateIdx = Random((int)rays->size());868 869 RayInfo rayInf = (*rays)[candidateIdx];870 const Vector3 minPt = rayInf.ExtrapOrigin();871 const Vector3 maxPt = rayInf.ExtrapTermination();872 873 const Vector3 pt = (maxPt + minPt) * 0.5;874 const Vector3 normal = Normalize(rayInf.mRay->GetDir());875 876 plane = Plane3(normal, pt);877 878 const float candidateCost = SplitPlaneCost(plane, data);879 880 if (candidateCost < lowestCost)881 {882 bestPlane = plane;883 lowestCost = candidateCost;884 }885 }886 887 // take plane normal as plane normal and the midpoint of the ray.888 // PROBLEM: does not resemble any point where visibility is likely to change889 //Debug << "lowest: " << lowestCost << endl;890 for (int i = 0; i < mMaxRayCandidates / 2; ++ i)891 {892 Vector3 pt[3];893 int idx[3];894 int cmaxT = 0;895 int cminT = 0;896 bool chooseMin = false;897 898 for (int j = 0; j < 3; j ++)899 {900 idx[j] = Random((int)rays->size() * 2);901 902 if (idx[j] >= (int)rays->size())903 {904 idx[j] -= (int)rays->size();905 906 chooseMin = (cminT < 2);907 }908 else909 chooseMin = (cmaxT < 2);910 911 RayInfo rayInf = (*rays)[idx[j]];912 pt[j] = chooseMin ? rayInf.ExtrapOrigin() : rayInf.ExtrapTermination();913 }914 915 plane = Plane3(pt[0], pt[1], pt[2]);916 917 const float candidateCost = SplitPlaneCost(plane, data);918 919 if (candidateCost < lowestCost)920 {921 //Debug << "choose ray plane 2: " << candidateCost << endl;922 bestPlane = plane;923 924 lowestCost = candidateCost;925 }926 }927 928 #ifdef _DEBUG929 Debug << "plane lowest cost: " << lowestCost << endl;930 #endif931 return bestPlane;932 }933 934 int VspBspTree::GetNextCandidateIdx(int currentIdx, PolygonContainer &polys)935 {936 const int candidateIdx = Random(currentIdx --);937 938 // swap candidates to avoid testing same plane 2 times939 std::swap(polys[currentIdx], polys[candidateIdx]);940 941 return currentIdx;942 //return Random((int)polys.size());943 }944 945 946 bool VspBspTree::BoundRay(const Ray &ray, float &minT, float &maxT) const947 {948 maxT = 1e6;949 minT = 0;950 951 // test with tree bounding box952 if (!mBox.GetMinMaxT(ray, &minT, &maxT))953 return false;954 955 if (minT < 0) // start ray from origin956 minT = 0;957 958 // bound ray or line segment959 if ((ray.GetType() == Ray::LOCAL_RAY) &&960 !ray.intersections.empty() &&961 (ray.intersections[0].mT <= maxT))962 {963 maxT = ray.intersections[0].mT;964 }965 966 return true;967 }968 969 inline void VspBspTree::GenerateUniqueIdsForPvs()970 {971 Intersectable::NewMail(); sBackId = ViewCell::sMailId;972 Intersectable::NewMail(); sFrontId = ViewCell::sMailId;973 Intersectable::NewMail(); sFrontAndBackId = ViewCell::sMailId;974 }975 976 float VspBspTree::SplitPlaneCost(const Plane3 &candidatePlane,977 const VspBspTraversalData &data)978 {979 float val = 0;980 981 float sumBalancedRays = 0;982 float sumRaySplits = 0;983 984 int backId = 0;985 int frontId = 0;986 int frontAndBackId = 0;987 988 int frontPvs = 0;989 int backPvs = 0;990 991 // probability that view point lies in child992 float pOverall = 0;993 float pFront = 0;994 float pBack = 0;995 996 const bool pvsUseLen = false;997 998 if (mSplitPlaneStrategy & PVS)999 {1000 // create unique ids for pvs heuristics1001 GenerateUniqueIdsForPvs();1002 1003 if (mPvsUseArea) // use front and back cell areas to approximate volume1004 {1005 // construct child geometry with regard to the candidate split plane1006 VspBspNodeGeometry frontCell;1007 VspBspNodeGeometry backCell;1008 1009 data.mGeometry->SplitGeometry(frontCell, backCell, *this, candidatePlane);1010 1011 pFront = frontCell.GetArea();1012 pBack = backCell.GetArea();1013 1014 pOverall = data.mArea;1015 }1016 }1017 1018 RayInfoContainer::const_iterator rit, rit_end = data.mRays->end();1019 1020 for (rit = data.mRays->begin(); rit != data.mRays->end(); ++ rit)1021 {1022 VssRay *ray = (*rit).mRay;1023 const int cf = (*rit).ComputeRayIntersection(candidatePlane, (*rit).mRay->mT);1024 1025 if (mSplitPlaneStrategy & LEAST_RAY_SPLITS)1026 {1027 sumBalancedRays += cf;1028 }1029 1030 if (mSplitPlaneStrategy & BALANCED_RAYS)1031 {1032 if (cf == 0)1033 ++ sumRaySplits;1034 }1035 1036 if (mSplitPlaneStrategy & PVS)1037 {1038 // in case the ray intersects an object1039 // assure that we only count the object1040 // once for the front and once for the back side of the plane1041 1042 // add the termination object1043 AddObjToPvs(ray->mTerminationObject, cf, frontPvs, backPvs);1044 1045 // add the source object1046 AddObjToPvs(ray->mOriginObject, cf, frontPvs, backPvs);1047 1048 // use number or length of rays to approximate volume1049 if (!mPvsUseArea)1050 {1051 float len = 1;1052 1053 if (pvsUseLen) // use length of rays1054 len = (*rit).SqrSegmentLength();1055 1056 pOverall += len;1057 1058 if (cf == 1)1059 pFront += len;1060 if (cf == -1)1061 pBack += len;1062 if (cf == 0)1063 {1064 // use length of rays to approximate volume1065 if (pvsUseLen)1066 {1067 float newLen = len *1068 ((*rit).GetMaxT() - (*rit).mRay->mT) /1069 ((*rit).GetMaxT() - (*rit).GetMinT());1070 1071 if (candidatePlane.Side((*rit).ExtrapOrigin()) <= 0)1072 {1073 pBack += newLen;1074 pFront += len - newLen;1075 }1076 else1077 {1078 pFront += newLen;1079 pBack += len - newLen;1080 }1081 }1082 else1083 {1084 ++ pFront;1085 ++ pBack;1086 }1087 }1088 }1089 }1090 }1091 1092 const float raysSize = (float)data.mRays->size() + Limits::Small;1093 1094 if (mSplitPlaneStrategy & LEAST_RAY_SPLITS)1095 val += mLeastRaySplitsFactor * sumRaySplits / raysSize;1096 1097 if (mSplitPlaneStrategy & BALANCED_RAYS)1098 val += mBalancedRaysFactor * fabs(sumBalancedRays) / raysSize;1099 1100 const float denom = pOverall * (float)data.mPvs * 2.0f + Limits::Small;1101 1102 if (mSplitPlaneStrategy & PVS)1103 {1104 val += mPvsFactor * (frontPvs * pFront + (backPvs * pBack)) / denom;1105 1106 // give penalty to unbalanced split1107 if (0)1108 if (((pFront * 0.2 + Limits::Small) > pBack) ||1109 (pFront < (pBack * 0.2 + Limits::Small)))1110 val += 0.5;1111 }1112 1113 #ifdef _DEBUG1114 Debug << "totalpvs: " << pvs << " ptotal: " << pOverall1115 << " frontpvs: " << frontPvs << " pFront: " << pFront1116 << " backpvs: " << backPvs << " pBack: " << pBack << endl << endl;1117 #endif1118 return val;1119 }1120 1121 void VspBspTree::AddObjToPvs(Intersectable *obj,1122 const int cf,1123 int &frontPvs,1124 int &backPvs) const1125 {1126 if (!obj)1127 return;1128 // TODO: does this really belong to no pvs?1129 //if (cf == Ray::COINCIDENT) return;1130 1131 // object belongs to both PVS1132 if (cf >= 0)1133 {1134 if ((obj->mMailbox != sFrontId) &&1135 (obj->mMailbox != sFrontAndBackId))1136 {1137 ++ frontPvs;1138 1139 if (obj->mMailbox == sBackId)1140 obj->mMailbox = sFrontAndBackId;1141 else1142 obj->mMailbox = sFrontId;1143 }1144 }1145 1146 if (cf <= 0)1147 {1148 if ((obj->mMailbox != sBackId) &&1149 (obj->mMailbox != sFrontAndBackId))1150 {1151 ++ backPvs;1152 1153 if (obj->mMailbox == sFrontId)1154 obj->mMailbox = sFrontAndBackId;1155 else1156 obj->mMailbox = sBackId;1157 }1158 }1159 }1160 1161 void VspBspTree::CollectLeaves(vector<VspBspLeaf *> &leaves) const1162 {1163 stack<VspBspNode *> nodeStack;1164 nodeStack.push(mRoot);1165 1166 while (!nodeStack.empty())1167 {1168 VspBspNode *node = nodeStack.top();1169 1170 nodeStack.pop();1171 1172 if (node->IsLeaf())1173 {1174 VspBspLeaf *leaf = (VspBspLeaf *)node;1175 leaves.push_back(leaf);1176 }1177 else1178 {1179 VspBspInterior *interior = dynamic_cast<VspBspInterior *>(node);1180 1181 nodeStack.push(interior->GetBack());1182 nodeStack.push(interior->GetFront());1183 }1184 }1185 }1186 1187 AxisAlignedBox3 VspBspTree::GetBoundingBox() const1188 {1189 return mBox;1190 }1191 1192 VspBspNode *VspBspTree::GetRoot() const1193 {1194 return mRoot;1195 }1196 1197 void VspBspTree::EvaluateLeafStats(const VspBspTraversalData &data)1198 {1199 // the node became a leaf -> evaluate stats for leafs1200 VspBspLeaf *leaf = dynamic_cast<VspBspLeaf *>(data.mNode);1201 1202 // store maximal and minimal depth1203 if (data.mDepth > mStat.maxDepth)1204 mStat.maxDepth = data.mDepth;1205 1206 if (data.mDepth < mStat.minDepth)1207 mStat.minDepth = data.mDepth;1208 1209 // accumulate depth to compute average depth1210 mStat.accumDepth += data.mDepth;1211 1212 1213 if (data.mDepth >= mTermMaxDepth)1214 ++ mStat.maxDepthNodes;1215 1216 if (data.mPvs < mTermMinPvs)1217 ++ mStat.minPvsNodes;1218 1219 if ((int)data.mRays->size() < mTermMinRays)1220 ++ mStat.minRaysNodes;1221 1222 if (data.GetAvgRayContribution() > mTermMaxRayContribution)1223 ++ mStat.maxRayContribNodes;1224 1225 if (data.mGeometry->GetArea() <= mTermMinArea)1226 ++ mStat.minAreaNodes;1227 1228 #ifdef _DEBUG1229 Debug << "BSP stats: "1230 << "Depth: " << data.mDepth << " (max: " << mTermMaxDepth << "), "1231 << "PVS: " << data.mPvs << " (min: " << mTermMinPvs << "), "1232 << "Area: " << data.mArea << " (min: " << mTermMinArea << "), "1233 << "#polygons: " << (int)data.mPolygons->size() << " (max: " << mTermMinPolys << "), "1234 << "#rays: " << (int)data.mRays->size() << " (max: " << mTermMinRays << "), "1235 << "#pvs: " << leaf->GetViewCell()->GetPvs().GetSize() << "=, "1236 << "#avg ray contrib (pvs): " << (float)data.mPvs / (float)data.mRays->size() << endl;1237 #endif1238 }1239 1240 int VspBspTree::CastRay(Ray &ray)1241 {1242 int hits = 0;1243 1244 stack<VspBspRayTraversalData> tStack;1245 1246 float maxt, mint;1247 1248 if (!BoundRay(ray, mint, maxt))1249 return 0;1250 1251 Intersectable::NewMail();1252 1253 Vector3 entp = ray.Extrap(mint);1254 Vector3 extp = ray.Extrap(maxt);1255 1256 VspBspNode *node = mRoot;1257 VspBspNode *farChild = NULL;1258 1259 while (1)1260 {1261 if (!node->IsLeaf())1262 {1263 VspBspInterior *in = (VspBspInterior *) node;1264 1265 Plane3 *splitPlane = in->GetPlane();1266 1267 int entSide = splitPlane->Side(entp);1268 int extSide = splitPlane->Side(extp);1269 1270 Vector3 intersection;1271 1272 if (entSide < 0)1273 {1274 node = in->GetBack();1275 1276 if(extSide <= 0) // plane does not split ray => no far child1277 continue;1278 1279 farChild = in->GetFront(); // plane splits ray1280 1281 } else if (entSide > 0)1282 {1283 node = in->GetFront();1284 1285 if (extSide >= 0) // plane does not split ray => no far child1286 continue;1287 1288 farChild = in->GetBack(); // plane splits ray1289 }1290 else // ray and plane are coincident1291 {1292 // WHAT TO DO IN THIS CASE ?1293 //break;1294 node = in->GetFront();1295 continue;1296 }1297 1298 // push data for far child1299 tStack.push(VspBspRayTraversalData(farChild, extp, maxt));1300 1301 // find intersection of ray segment with plane1302 float t;1303 extp = splitPlane->FindIntersection(ray.GetLoc(), extp, &t);1304 maxt *= t;1305 1306 } else // reached leaf => intersection with view cell1307 {1308 VspBspLeaf *leaf = dynamic_cast<VspBspLeaf *>(node);1309 1310 if (!leaf->mViewCell->Mailed())1311 {1312 //ray.bspIntersections.push_back(Ray::VspBspIntersection(maxt, leaf));1313 leaf->mViewCell->Mail();1314 ++ hits;1315 }1316 1317 //-- fetch the next far child from the stack1318 if (tStack.empty())1319 break;1320 1321 entp = extp;1322 mint = maxt; // NOTE: need this?1323 1324 if (ray.GetType() == Ray::LINE_SEGMENT && mint > 1.0f)1325 break;1326 1327 VspBspRayTraversalData &s = tStack.top();1328 1329 node = s.mNode;1330 extp = s.mExitPoint;1331 maxt = s.mMaxT;1332 1333 tStack.pop();1334 }1335 }1336 1337 return hits;1338 }1339 1340 bool VspBspTree::Export(const string filename)1341 {1342 Exporter *exporter = Exporter::GetExporter(filename);1343 1344 if (exporter)1345 {1346 //exporter->ExportVspBspTree(*this);1347 return true;1348 }1349 1350 return false;1351 }1352 1353 void VspBspTree::CollectViewCells(ViewCellContainer &viewCells) const1354 {1355 stack<VspBspNode *> nodeStack;1356 nodeStack.push(mRoot);1357 1358 ViewCell::NewMail();1359 1360 while (!nodeStack.empty())1361 {1362 VspBspNode *node = nodeStack.top();1363 nodeStack.pop();1364 1365 if (node->IsLeaf())1366 {1367 ViewCell *viewCell = dynamic_cast<VspBspLeaf *>(node)->mViewCell;1368 1369 if (!viewCell->Mailed())1370 {1371 viewCell->Mail();1372 viewCells.push_back(viewCell);1373 }1374 }1375 else1376 {1377 VspBspInterior *interior = dynamic_cast<VspBspInterior *>(node);1378 1379 nodeStack.push(interior->mFront);1380 nodeStack.push(interior->mBack);1381 }1382 }1383 }1384 1385 void VspBspTree::EvaluateViewCellsStats(VspBspViewCellsStatistics &stat) const1386 {1387 stat.Reset();1388 1389 stack<VspBspNode *> nodeStack;1390 nodeStack.push(mRoot);1391 1392 ViewCell::NewMail();1393 1394 // exclude root cell1395 mRootCell->Mail();1396 1397 while (!nodeStack.empty())1398 {1399 VspBspNode *node = nodeStack.top();1400 nodeStack.pop();1401 1402 if (node->IsLeaf())1403 {1404 ++ stat.bspLeaves;1405 1406 BspViewCell *viewCell = dynamic_cast<VspBspLeaf *>(node)->mViewCell;1407 1408 if (!viewCell->Mailed())1409 {1410 viewCell->Mail();1411 1412 ++ stat.viewCells;1413 const int pvsSize = viewCell->GetPvs().GetSize();1414 1415 stat.pvs += pvsSize;1416 1417 if (pvsSize < 1)1418 ++ stat.emptyPvs;1419 1420 if (pvsSize > stat.maxPvs)1421 stat.maxPvs = pvsSize;1422 1423 if (pvsSize < stat.minPvs)1424 stat.minPvs = pvsSize;1425 1426 //TODO1427 //if ((int)viewCell->mVspBspLeaves.size() > stat.maxVspBspLeaves)1428 // stat.maxVspBspLeaves = (int)viewCell->mVspBspLeaves.size();1429 }1430 }1431 else1432 {1433 VspBspInterior *interior = dynamic_cast<VspBspInterior *>(node);1434 1435 nodeStack.push(interior->mFront);1436 nodeStack.push(interior->mBack);1437 }1438 }1439 }1440 1441 VspBspTreeStatistics &VspBspTree::GetStat()1442 {1443 return mStat;1444 }1445 1446 float VspBspTree::AccumulatedRayLength(const RayInfoContainer &rays) const1447 {1448 float len = 0;1449 1450 RayInfoContainer::const_iterator it, it_end = rays.end();1451 1452 for (it = rays.begin(); it != it_end; ++ it)1453 len += (*it).SegmentLength();1454 1455 return len;1456 }1457 1458 int VspBspTree::SplitRays(const Plane3 &plane,1459 RayInfoContainer &rays,1460 RayInfoContainer &frontRays,1461 RayInfoContainer &backRays)1462 {1463 int splits = 0;1464 1465 while (!rays.empty())1466 {1467 RayInfo bRay = rays.back();1468 VssRay *ray = bRay.mRay;1469 1470 rays.pop_back();1471 1472 // get classification and receive new t1473 const int cf = bRay.ComputeRayIntersection(plane, ray->mT);1474 1475 switch(cf)1476 {1477 case -1:1478 backRays.push_back(bRay);1479 break;1480 case 1:1481 break;1482 frontRays.push_back(bRay);1483 case 0:1484 //-- split ray1485 1486 // if start point behind plane1487 if (plane.Side(bRay.ExtrapOrigin()) <= 0)1488 {1489 backRays.push_back(RayInfo(ray, bRay.GetMinT(), ray->mT));1490 frontRays.push_back(RayInfo(ray, ray->mT, bRay.GetMaxT()));1491 }1492 else1493 {1494 frontRays.push_back(RayInfo(ray, bRay.GetMinT(), ray->mT));1495 backRays.push_back(RayInfo(ray, ray->mT, bRay.GetMaxT()));1496 }1497 break;1498 default:1499 Debug << "Should not come here 4" << endl;1500 break;1501 }1502 }1503 1504 return splits;1505 }1506 1507 void VspBspTree::ExtractHalfSpaces(VspBspNode *n, vector<Plane3> &halfSpaces) const1508 {1509 VspBspNode *lastNode;1510 do1511 {1512 lastNode = n;1513 1514 // want to get planes defining geometry of this node => don't take1515 // split plane of node itself1516 n = n->GetParent();1517 1518 if (n)1519 {1520 VspBspInterior *interior = dynamic_cast<VspBspInterior *>(n);1521 Plane3 halfSpace = *dynamic_cast<VspBspInterior *>(interior)->GetPlane();1522 1523 if (interior->mFront != lastNode)1524 halfSpace.ReverseOrientation();1525 1526 halfSpaces.push_back(halfSpace);1527 }1528 }1529 while (n);1530 }1531 1532 void VspBspTree::ConstructGeometry(VspBspNode *n, VspBspNodeGeometry &cell) const1533 {1534 PolygonContainer polys;1535 ConstructGeometry(n, polys);1536 cell.mPolys = polys;1537 }1538 1539 void VspBspTree::ConstructGeometry(VspBspNode *n, PolygonContainer &cell) const1540 {1541 vector<Plane3> halfSpaces;1542 ExtractHalfSpaces(n, halfSpaces);1543 1544 PolygonContainer candidatePolys;1545 1546 // bounded planes are added to the polygons (reverse polygons1547 // as they have to be outfacing1548 for (int i = 0; i < (int)halfSpaces.size(); ++ i)1549 {1550 Polygon3 *p = GetBoundingBox().CrossSection(halfSpaces[i]);1551 1552 if (p->Valid())1553 {1554 candidatePolys.push_back(p->CreateReversePolygon());1555 DEL_PTR(p);1556 }1557 }1558 1559 // add faces of bounding box (also could be faces of the cell)1560 for (int i = 0; i < 6; ++ i)1561 {1562 VertexContainer vertices;1563 1564 for (int j = 0; j < 4; ++ j)1565 vertices.push_back(mBox.GetFace(i).mVertices[j]);1566 1567 candidatePolys.push_back(new Polygon3(vertices));1568 }1569 1570 for (int i = 0; i < (int)candidatePolys.size(); ++ i)1571 {1572 // polygon is split by all other planes1573 for (int j = 0; (j < (int)halfSpaces.size()) && candidatePolys[i]; ++ j)1574 {1575 if (i == j) // polygon and plane are coincident1576 continue;1577 1578 VertexContainer splitPts;1579 Polygon3 *frontPoly, *backPoly;1580 1581 const int cf = candidatePolys[i]->ClassifyPlane(halfSpaces[j]);1582 1583 switch (cf)1584 {1585 case Polygon3::SPLIT:1586 frontPoly = new Polygon3();1587 backPoly = new Polygon3();1588 1589 candidatePolys[i]->Split(halfSpaces[j],1590 *frontPoly,1591 *backPoly);1592 1593 DEL_PTR(candidatePolys[i]);1594 1595 if (frontPoly->Valid())1596 candidatePolys[i] = frontPoly;1597 else1598 DEL_PTR(frontPoly);1599 1600 DEL_PTR(backPoly);1601 break;1602 case Polygon3::BACK_SIDE:1603 DEL_PTR(candidatePolys[i]);1604 break;1605 // just take polygon as it is1606 case Polygon3::FRONT_SIDE:1607 case Polygon3::COINCIDENT:1608 default:1609 break;1610 }1611 }1612 1613 if (candidatePolys[i])1614 cell.push_back(candidatePolys[i]);1615 }1616 }1617 1618 void VspBspTree::ConstructGeometry(BspViewCell *vc, PolygonContainer &cell) const1619 {1620 /*1621 TODO1622 vector<VspBspLeaf *> leaves = vc->mBspLeaves;1623 1624 vector<VspBspLeaf *>::const_iterator it, it_end = leaves.end();1625 1626 for (it = leaves.begin(); it != it_end; ++ it)1627 ConstructGeometry(*it, vcGeom);*/1628 }1629 1630 int VspBspTree::FindNeighbors(VspBspNode *n, vector<VspBspLeaf *> &neighbors,1631 const bool onlyUnmailed) const1632 {1633 PolygonContainer cell;1634 1635 ConstructGeometry(n, cell);1636 1637 stack<VspBspNode *> nodeStack;1638 nodeStack.push(mRoot);1639 1640 // planes needed to verify that we found neighbor leaf.1641 vector<Plane3> halfSpaces;1642 ExtractHalfSpaces(n, halfSpaces);1643 1644 while (!nodeStack.empty())1645 {1646 VspBspNode *node = nodeStack.top();1647 nodeStack.pop();1648 1649 if (node->IsLeaf())1650 {1651 if (node != n && (!onlyUnmailed || !node->Mailed()))1652 {1653 // test all planes of current node if candidate really1654 // is neighbour1655 PolygonContainer neighborCandidate;1656 ConstructGeometry(node, neighborCandidate);1657 1658 bool isAdjacent = true;1659 for (int i = 0; (i < halfSpaces.size()) && isAdjacent; ++ i)1660 {1661 const int cf =1662 Polygon3::ClassifyPlane(neighborCandidate, halfSpaces[i]);1663 1664 if (cf == Polygon3::BACK_SIDE)1665 isAdjacent = false;1666 }1667 1668 if (isAdjacent)1669 neighbors.push_back(dynamic_cast<VspBspLeaf *>(node));1670 1671 CLEAR_CONTAINER(neighborCandidate);1672 }1673 }1674 else1675 {1676 VspBspInterior *interior = dynamic_cast<VspBspInterior *>(node);1677 1678 const int cf = Polygon3::ClassifyPlane(cell, interior->mPlane);1679 1680 if (cf == Polygon3::FRONT_SIDE)1681 nodeStack.push(interior->mFront);1682 else1683 if (cf == Polygon3::BACK_SIDE)1684 nodeStack.push(interior->mBack);1685 else1686 {1687 // random decision1688 nodeStack.push(interior->mBack);1689 nodeStack.push(interior->mFront);1690 }1691 }1692 }1693 1694 CLEAR_CONTAINER(cell);1695 return (int)neighbors.size();1696 }1697 1698 VspBspLeaf *VspBspTree::GetRandomLeaf(const Plane3 &halfspace)1699 {1700 stack<VspBspNode *> nodeStack;1701 nodeStack.push(mRoot);1702 1703 int mask = rand();1704 1705 while (!nodeStack.empty())1706 {1707 VspBspNode *node = nodeStack.top();1708 nodeStack.pop();1709 1710 if (node->IsLeaf())1711 {1712 return dynamic_cast<VspBspLeaf *>(node);1713 }1714 else1715 {1716 VspBspInterior *interior = dynamic_cast<VspBspInterior *>(node);1717 1718 VspBspNode *next;1719 1720 PolygonContainer cell;1721 1722 // todo: not very efficient: constructs full cell everytime1723 ConstructGeometry(interior, cell);1724 1725 const int cf = Polygon3::ClassifyPlane(cell, halfspace);1726 1727 if (cf == Polygon3::BACK_SIDE)1728 next = interior->mFront;1729 else1730 if (cf == Polygon3::FRONT_SIDE)1731 next = interior->mFront;1732 else1733 {1734 // random decision1735 if (mask & 1)1736 next = interior->mBack;1737 else1738 next = interior->mFront;1739 mask = mask >> 1;1740 }1741 1742 nodeStack.push(next);1743 }1744 }1745 1746 return NULL;1747 }1748 1749 VspBspLeaf *VspBspTree::GetRandomLeaf(const bool onlyUnmailed)1750 {1751 stack<VspBspNode *> nodeStack;1752 1753 nodeStack.push(mRoot);1754 1755 int mask = rand();1756 1757 while (!nodeStack.empty())1758 {1759 VspBspNode *node = nodeStack.top();1760 nodeStack.pop();1761 1762 if (node->IsLeaf())1763 {1764 if ( (!onlyUnmailed || !node->Mailed()) )1765 return dynamic_cast<VspBspLeaf *>(node);1766 }1767 else1768 {1769 VspBspInterior *interior = dynamic_cast<VspBspInterior *>(node);1770 1771 // random decision1772 if (mask & 1)1773 nodeStack.push(interior->mBack);1774 else1775 nodeStack.push(interior->mFront);1776 1777 mask = mask >> 1;1778 }1779 }1780 1781 return NULL;1782 }1783 1784 int VspBspTree::ComputePvsSize(const RayInfoContainer &rays) const1785 {1786 int pvsSize = 0;1787 1788 RayInfoContainer::const_iterator rit, rit_end = rays.end();1789 1790 Intersectable::NewMail();1791 1792 for (rit = rays.begin(); rit != rays.end(); ++ rit)1793 {1794 VssRay *ray = (*rit).mRay;1795 1796 if (ray->mOriginObject)1797 {1798 if (!ray->mOriginObject->Mailed())1799 {1800 ray->mOriginObject->Mail();1801 ++ pvsSize;1802 }1803 }1804 if (ray->mTerminationObject)1805 {1806 if (!ray->mTerminationObject->Mailed())1807 {1808 ray->mTerminationObject->Mail();1809 ++ pvsSize;1810 }1811 }1812 }1813 1814 return pvsSize;1815 }1816 1817 /*************************************************************1818 * VspBspNodeGeometry Implementation *1819 *************************************************************/1820 1821 VspBspNodeGeometry::~VspBspNodeGeometry()1822 {1823 CLEAR_CONTAINER(mPolys);1824 }1825 1826 float VspBspNodeGeometry::GetArea() const1827 {1828 return Polygon3::GetArea(mPolys);1829 }1830 1831 void VspBspNodeGeometry::SplitGeometry(VspBspNodeGeometry &front,1832 VspBspNodeGeometry &back,1833 const VspBspTree &tree,1834 const Plane3 &splitPlane) const1835 {1836 // get cross section of new polygon1837 Polygon3 *planePoly = tree.GetBoundingBox().CrossSection(splitPlane);1838 1839 planePoly = SplitPolygon(planePoly, tree);1840 1841 //-- plane poly splits all other cell polygons1842 for (int i = 0; i < (int)mPolys.size(); ++ i)1843 {1844 const int cf = mPolys[i]->ClassifyPlane(splitPlane, 0.00001f);1845 1846 // split new polygon with all previous planes1847 switch (cf)1848 {1849 case Polygon3::SPLIT:1850 {1851 Polygon3 *poly = new Polygon3(mPolys[i]->mVertices);1852 1853 Polygon3 *frontPoly = new Polygon3();1854 Polygon3 *backPoly = new Polygon3();1855 1856 poly->Split(splitPlane, *frontPoly, *backPoly);1857 1858 DEL_PTR(poly);1859 1860 if (frontPoly->Valid())1861 front.mPolys.push_back(frontPoly);1862 if (backPoly->Valid())1863 back.mPolys.push_back(backPoly);1864 }1865 1866 break;1867 case Polygon3::BACK_SIDE:1868 back.mPolys.push_back(new Polygon3(mPolys[i]->mVertices));1869 break;1870 case Polygon3::FRONT_SIDE:1871 front.mPolys.push_back(new Polygon3(mPolys[i]->mVertices));1872 break;1873 case Polygon3::COINCIDENT:1874 //front.mPolys.push_back(CreateReversePolygon(mPolys[i]));1875 back.mPolys.push_back(new Polygon3(mPolys[i]->mVertices));1876 break;1877 default:1878 break;1879 }1880 }1881 1882 //-- finally add the new polygon to the child cells1883 if (planePoly)1884 {1885 // add polygon with normal pointing into positive half space to back cell1886 back.mPolys.push_back(planePoly);1887 // add polygon with reverse orientation to front cell1888 front.mPolys.push_back(planePoly->CreateReversePolygon());1889 }1890 1891 //Debug << "returning new geometry " << mPolys.size() << " f: " << front.mPolys.size() << " b: " << back.mPolys.size() << endl;1892 //Debug << "old area " << GetArea() << " f: " << front.GetArea() << " b: " << back.GetArea() << endl;1893 }1894 1895 Polygon3 *VspBspNodeGeometry::SplitPolygon(Polygon3 *planePoly,1896 const VspBspTree &tree) const1897 {1898 // polygon is split by all other planes1899 for (int i = 0; (i < (int)mPolys.size()) && planePoly; ++ i)1900 {1901 Plane3 plane = mPolys[i]->GetSupportingPlane();1902 1903 const int cf =1904 planePoly->ClassifyPlane(plane, 0.00001f);1905 1906 // split new polygon with all previous planes1907 switch (cf)1908 {1909 case Polygon3::SPLIT:1910 {1911 Polygon3 *frontPoly = new Polygon3();1912 Polygon3 *backPoly = new Polygon3();1913 1914 planePoly->Split(plane, *frontPoly, *backPoly);1915 DEL_PTR(planePoly);1916 1917 if (backPoly->Valid())1918 planePoly = backPoly;1919 else1920 DEL_PTR(backPoly);1921 }1922 break;1923 case Polygon3::FRONT_SIDE:1924 DEL_PTR(planePoly);1925 break;1926 // polygon is taken as it is1927 case Polygon3::BACK_SIDE:1928 case Polygon3::COINCIDENT:1929 default:1930 break;1931 }1932 }1933 1934 return planePoly;1935 }1936 1937 void VspBspViewCellsStatistics::Print(ostream &app) const1938 {1939 app << "===== VspBspViewCells statistics ===============\n";1940 1941 app << setprecision(4);1942 1943 //app << "#N_CTIME ( Construction time [s] )\n" << Time() << " \n";1944 1945 app << "#N_OVERALLPVS ( objects in PVS )\n" << pvs << endl;1946 1947 app << "#N_PMAXPVS ( largest PVS )\n" << maxPvs << endl;1948 1949 app << "#N_PMINPVS ( smallest PVS )\n" << minPvs << endl;1950 1951 app << "#N_PAVGPVS ( average PVS )\n" << AvgPvs() << endl;1952 1953 app << "#N_PEMPTYPVS ( view cells with PVS smaller 2 )\n" << emptyPvs << endl;1954 1955 app << "#N_VIEWCELLS ( number of view cells)\n" << viewCells << endl;1956 1957 app << "#N_AVGBSPLEAVES (average number of BSP leaves per view cell )\n" << AvgVspBspLeaves() << endl;1958 1959 app << "#N_MAXBSPLEAVES ( maximal number of BSP leaves per view cell )\n" << maxVspBspLeaves << endl;1960 1961 app << "===== END OF VspBspViewCells statistics ==========\n";1962 }1963 1964 BspViewCell *VspBspTree::GetRootCell() const1965 {1966 return mRootCell;1967 } -
trunk/VUT/GtpVisibilityPreprocessor/src/VspBspTree.h
r445 r448 9 9 #include "VssRay.h" 10 10 #include "RayInfo.h" 11 #include "ViewCellBsp.h" 11 12 12 13 class ViewCell; … … 14 15 class Plane3; 15 16 class VspBspTree; 16 class VspBspInterior;17 class VspBspNode;17 class BspInterior; 18 class BspNode; 18 19 class AxisAlignedBox3; 19 20 class Ray; 20 21 21 class VspBspNodeGeometry 22 { 23 public: 24 VspBspNodeGeometry() 25 {}; 26 27 ~VspBspNodeGeometry(); 28 29 float GetArea() const; 30 31 /** Computes new cell based on the old cell definition and a new split plane 32 @param side indicates which side of the halfspace 33 */ 34 void SplitGeometry(VspBspNodeGeometry &front, 35 VspBspNodeGeometry &back, 36 const VspBspTree &tree, 37 const Plane3 &splitPlane) const; 38 39 Polygon3 *SplitPolygon(Polygon3 *poly, const VspBspTree &tree) const; 40 41 PolygonContainer mPolys; 42 }; 43 44 /** Data structure used for optimized ray casting. 22 /*class BspNodeGeometry; 23 class BspTreeStatistics; 24 class BspViewCellsStatistics; 25 class BspNode; 26 class BspLeaf; 27 class BspInterior; 45 28 */ 46 struct VspBspRayTraversalData47 {48 VspBspNode *mNode;49 Vector3 mExitPoint;50 float mMaxT;51 52 VspBspRayTraversalData() {}53 54 VspBspRayTraversalData(VspBspNode *n, const Vector3 &extp, const float maxt):55 mNode(n), mExitPoint(extp), mMaxT(maxt)56 {}57 };58 59 class VspBspTreeStatistics: public StatisticsBase60 {61 public:62 // total number of nodes63 int nodes;64 // number of splits65 int splits;66 // totals number of rays67 int rays;68 // maximal reached depth69 int maxDepth;70 // minimal depth71 int minDepth;72 73 // max depth nodes74 int maxDepthNodes;75 // minimum depth nodes76 int minDepthNodes;77 // max depth nodes78 int minPvsNodes;79 // nodes with minimum PVS80 int minRaysNodes;81 // max ray contribution nodes82 int maxRayContribNodes;83 // minimum area nodes84 int minAreaNodes;85 86 // max number of rays per node87 int maxObjectRefs;88 // accumulated depth (used to compute average)89 int accumDepth;90 // number of initial polygons91 int polys;92 /// samples contributing to pvs93 int contributingSamples;94 /// sample contributions to pvs95 int sampleContributions;96 /// largest pvs97 int largestPvs;98 99 // Constructor100 VspBspTreeStatistics()101 {102 Reset();103 }104 105 int Nodes() const {return nodes;}106 int Interior() const { return nodes / 2; }107 int Leaves() const { return (nodes / 2) + 1; }108 109 // TODO: computation wrong110 double AvgDepth() const { return accumDepth / (double)Leaves();};111 112 void Reset()113 {114 nodes = 0;115 splits = 0;116 117 maxDepth = 0;118 minDepth = 99999;119 polys = 0;120 accumDepth = 0;121 122 maxDepthNodes = 0;123 minPvsNodes = 0;124 minRaysNodes = 0;125 maxRayContribNodes = 0;126 minAreaNodes = 0;127 128 contributingSamples = 0;129 sampleContributions = 0;130 }131 132 void Print(ostream &app) const;133 134 friend ostream &operator<<(ostream &s, const VspBspTreeStatistics &stat)135 {136 stat.Print(s);137 return s;138 }139 };140 141 class VspBspViewCellsStatistics: public StatisticsBase142 {143 public:144 145 /// number of view cells146 int viewCells;147 148 /// size of the PVS149 int pvs;150 151 /// largest PVS of all view cells152 int maxPvs;153 154 /// smallest PVS of all view cells155 int minPvs;156 157 /// view cells with empty PVS158 int emptyPvs;159 160 /// number of bsp leaves covering the view space161 int bspLeaves;162 163 /// largest number of leaves covered by one view cell164 int maxVspBspLeaves;165 166 // Constructor167 VspBspViewCellsStatistics()168 {169 Reset();170 }171 172 double AvgVspBspLeaves() const {return (double)bspLeaves / (double)viewCells;};173 double AvgPvs() const {return (double)pvs / (double)viewCells;};174 175 void Reset()176 {177 viewCells = 0;178 pvs = 0;179 maxPvs = 0;180 181 minPvs = 999999;182 emptyPvs = 0;183 bspLeaves = 0;184 maxVspBspLeaves = 0;185 }186 187 void Print(ostream &app) const;188 189 friend ostream &operator<<(ostream &s, const VspBspViewCellsStatistics &stat)190 {191 stat.Print(s);192 return s;193 }194 };195 196 /**197 VspBspNode abstract class serving for interior and leaf node implementation198 */199 class VspBspNode200 {201 friend class VspBspTree;202 203 public:204 VspBspNode();205 virtual ~VspBspNode(){};206 VspBspNode(VspBspInterior *parent);207 208 /** Determines whether this node is a leaf or not209 @return true if leaf210 */211 virtual bool IsLeaf() const = 0;212 213 /** Determines whether this node is a root214 @return true if root215 */216 virtual bool IsRoot() const;217 218 /** Returns parent node.219 */220 VspBspInterior *GetParent();221 222 /** Sets parent node.223 */224 void SetParent(VspBspInterior *parent);225 226 227 static int sMailId;228 int mMailbox;229 230 void Mail() { mMailbox = sMailId; }231 static void NewMail() { ++ sMailId; }232 bool Mailed() const { return mMailbox == sMailId; }233 234 protected:235 236 /// parent of this node237 VspBspInterior *mParent;238 };239 240 /** BSP interior node implementation241 */242 class VspBspInterior : public VspBspNode243 {244 friend class VspBspTree;245 public:246 /** Standard contructor taking split plane as argument.247 */248 VspBspInterior(const Plane3 &plane);249 ~VspBspInterior();250 /** @return false since it is an interior node251 */252 bool IsLeaf() const;253 254 VspBspNode *GetBack();255 VspBspNode *GetFront();256 257 Plane3 *GetPlane();258 259 void ReplaceChildLink(VspBspNode *oldChild, VspBspNode *newChild);260 void SetupChildLinks(VspBspNode *b, VspBspNode *f);261 262 /** Splits polygons with respect to the split plane.263 @param polys the polygons to be split. the polygons are consumed and264 distributed to the containers frontPolys, backPolys, coincident.265 @param frontPolys returns the polygons in the front of the split plane266 @param backPolys returns the polygons in the back of the split plane267 @param coincident returns the polygons coincident to the split plane268 269 @returns the number of splits270 */271 int SplitPolygons(PolygonContainer &polys,272 PolygonContainer &frontPolys,273 PolygonContainer &backPolys,274 PolygonContainer &coincident);275 276 friend ostream &operator<<(ostream &s, const VspBspInterior &A)277 {278 return s << A.mPlane;279 }280 281 protected:282 283 /// Splitting plane corresponding to this node284 Plane3 mPlane;285 /// back node286 VspBspNode *mBack;287 /// front node288 VspBspNode *mFront;289 };290 291 /** BSP leaf node implementation.292 */293 class VspBspLeaf : public VspBspNode294 {295 friend class VspBspTree;296 297 public:298 VspBspLeaf();299 VspBspLeaf(BspViewCell *viewCell);300 VspBspLeaf(VspBspInterior *parent);301 VspBspLeaf(VspBspInterior *parent, BspViewCell *viewCell);302 303 /** @return true since it is an interior node304 */305 bool IsLeaf() const;306 307 /** Returns pointer of view cell.308 */309 BspViewCell *GetViewCell() const;310 311 /** Sets pointer to view cell.312 */313 void SetViewCell(BspViewCell *viewCell);314 315 /** Adds ray sample contributions to the PVS.316 @param sampleContributions the number contributions of the samples317 @param contributingSampels the number of contributing rays318 319 */320 void AddToPvs(const RayInfoContainer &rays,321 int &sampleContributions,322 int &contributingSamples,323 bool storeLeavesWithRays = false);324 325 protected:326 327 /// if NULL this does not correspond to feasible viewcell328 BspViewCell *mViewCell;329 };330 29 331 30 /** … … 345 44 { 346 45 /// the current node 347 VspBspNode *mNode;46 BspNode *mNode; 348 47 /// polygonal data for splitting 349 48 PolygonContainer *mPolygons; 350 49 /// current depth 351 50 int mDepth; 352 /// the view cell associated with this subdivsion 353 ViewCell *mViewCell; 51 354 52 /// rays piercing this node 355 53 RayInfoContainer *mRays; 356 54 /// area of current node 357 55 float mArea; 358 /// geometry of current node induced by splitplanes359 VspBspNodeGeometry *mGeometry;360 56 /// geometry of node as induced by planes 57 BspNodeGeometry *mGeometry; 58 361 59 /// pvs size 362 60 int mPvs; … … 374 72 mPolygons(NULL), 375 73 mDepth(0), 376 mViewCell(NULL),377 74 mRays(NULL), 378 75 mPvs(0), … … 381 78 {} 382 79 383 VspBspTraversalData( VspBspNode *node,80 VspBspTraversalData(BspNode *node, 384 81 PolygonContainer *polys, 385 82 const int depth, 386 ViewCell *viewCell,387 83 RayInfoContainer *rays, 388 84 int pvs, 389 85 float area, 390 VspBspNodeGeometry *cell):86 BspNodeGeometry *geom): 391 87 mNode(node), 392 88 mPolygons(polys), 393 89 mDepth(depth), 394 mViewCell(viewCell),395 90 mRays(rays), 396 91 mPvs(pvs), 397 92 mArea(area), 398 mGeometry(cell) 93 mGeometry(geom) 94 {} 95 96 VspBspTraversalData(PolygonContainer *polys, 97 const int depth, 98 RayInfoContainer *rays, 99 BspNodeGeometry *geom): 100 mNode(NULL), 101 mPolygons(polys), 102 mDepth(depth), 103 mRays(rays), 104 mPvs(0), 105 mArea(0), 106 mGeometry(geom) 399 107 {} 400 108 }; … … 406 114 VspBspTree(); 407 115 116 /** Default destructor. 117 */ 408 118 ~VspBspTree(); 409 119 410 const VspBspTreeStatistics &GetStatistics() const; 120 /** Returns BSP Tree statistics. 121 */ 122 const BspTreeStatistics &GetStatistics() const; 411 123 412 124 … … 420 132 /** Returns list of BSP leaves. 421 133 */ 422 void CollectLeaves(vector< VspBspLeaf *> &leaves) const;134 void CollectLeaves(vector<BspLeaf *> &leaves) const; 423 135 424 136 /** Returns box which bounds the whole tree. … … 428 140 /** Returns root of BSP tree. 429 141 */ 430 VspBspNode *GetRoot() const;142 BspNode *GetRoot() const; 431 143 432 144 /** Exports VspBsp tree to file. … … 450 162 /** Returns statistics. 451 163 */ 452 VspBspTreeStatistics &GetStat();164 BspTreeStatistics &GetStat(); 453 165 454 166 /** finds neighbouring leaves of this tree node. 455 167 */ 456 int FindNeighbors(VspBspNode *n, vector<VspBspLeaf *> &neighbors, 168 int FindNeighbors(BspNode *n, 169 vector<BspLeaf *> &neighbors, 457 170 const bool onlyUnmailed) const; 458 171 … … 460 173 leading to this node. 461 174 */ 462 void ConstructGeometry( VspBspNode *n, PolygonContainer &cell) const;175 void ConstructGeometry(BspNode *n, PolygonContainer &cell) const; 463 176 464 177 /** Constructs geometry associated with the half space intersections … … 469 182 /** Construct geometry and stores it in a geometry node container. 470 183 */ 471 void ConstructGeometry( VspBspNode *n, VspBspNodeGeometry &cell) const;184 void ConstructGeometry(BspNode *n, BspNodeGeometry &cell) const; 472 185 473 186 /** Returns random leaf of BSP tree. 474 187 @param halfspace defines the halfspace from which the leaf is taken. 475 188 */ 476 VspBspLeaf *GetRandomLeaf(const Plane3 &halfspace);189 BspLeaf *GetRandomLeaf(const Plane3 &halfspace); 477 190 478 191 /** Returns random leaf of BSP tree. 479 192 @param onlyUnmailed if only unmailed leaves should be returned. 480 193 */ 481 VspBspLeaf *GetRandomLeaf(const bool onlyUnmailed = false);194 BspLeaf *GetRandomLeaf(const bool onlyUnmailed = false); 482 195 483 196 /** Traverses tree and counts all view cells as well as their PVS size. 484 197 */ 485 void EvaluateViewCellsStats( VspBspViewCellsStatistics &stat) const;198 void EvaluateViewCellsStats(BspViewCellsStatistics &stat) const; 486 199 487 200 … … 489 202 */ 490 203 BspViewCell *GetRootCell() const; 204 205 /** Returns epsilon of this tree. 206 */ 207 float GetEpsilon() const; 491 208 492 209 protected: … … 521 238 @returns new root of the subtree 522 239 */ 523 VspBspNode *Subdivide(VspBspTraversalStack &tStack, VspBspTraversalData &tData); 524 525 /** Constructs the tree from the given list of polygons and rays. 240 BspNode *Subdivide(VspBspTraversalStack &tStack, 241 VspBspTraversalData &tData); 242 243 /** Constructs the tree from the given traversal data. 526 244 @param polys stores set of polygons on which subdivision may be based 527 245 @param rays storesset of rays on which subdivision may be based 528 246 */ 529 void Construct( PolygonContainer *polys, RayInfoContainer *rays);247 void Construct(const PolygonContainer &polys, RayInfoContainer *rays); 530 248 531 249 /** Selects the best possible splitting plane. … … 536 254 @returns the split plane 537 255 */ 538 Plane3 SelectPlane( VspBspLeaf *leaf,256 Plane3 SelectPlane(BspLeaf *leaf, 539 257 VspBspTraversalData &data); 540 258 … … 564 282 */ 565 283 566 VspBspInterior *SubdivideNode(VspBspTraversalData &tData,284 BspInterior *SubdivideNode(VspBspTraversalData &tData, 567 285 VspBspTraversalData &frontData, 568 286 VspBspTraversalData &backData, … … 575 293 @param rays bundle of rays on which the split can be based 576 294 */ 577 Plane3 SelectPlaneHeuristics( VspBspLeaf *leaf,295 Plane3 SelectPlaneHeuristics(BspLeaf *leaf, 578 296 VspBspTraversalData &data); 579 297 … … 639 357 bool SelectAxisAlignedPlane(Plane3 &plane, const PolygonContainer &polys) const; 640 358 641 /** Bounds ray and returns minT and maxT.642 @returns true if ray hits BSP tree bounding box643 */644 bool BoundRay(const Ray &ray, float &minT, float &maxT) const;645 646 359 /** Subdivides the rays into front and back rays according to the split plane. 647 360 … … 662 375 /** Extracts the split planes representing the space bounded by node n. 663 376 */ 664 void ExtractHalfSpaces( VspBspNode *n, vector<Plane3> &halfSpaces) const;377 void ExtractHalfSpaces(BspNode *n, vector<Plane3> &halfSpaces) const; 665 378 666 379 /** Adds the object to the pvs of the front and back leaf with a given classification. … … 686 399 float AccumulatedRayLength(const RayInfoContainer &rays) const; 687 400 688 401 /** Splits polygons with respect to the split plane. 402 403 @param plane the split plane 404 @param polys the polygons to be split. the polygons are consumed and 405 distributed to the containers frontPolys, backPolys, coincident. 406 @param frontPolys returns the polygons in the front of the split plane 407 @param backPolys returns the polygons in the back of the split plane 408 @param coincident returns the polygons coincident to the split plane 409 410 @returns the number of splits 411 */ 412 int SplitPolygons(const Plane3 &plane, 413 PolygonContainer &polys, 414 PolygonContainer &frontPolys, 415 PolygonContainer &backPolys, 416 PolygonContainer &coincident) const; 417 418 /** Adds ray sample contributions to the PVS. 419 @param sampleContributions the number contributions of the samples 420 @param contributingSampels the number of contributing rays 421 422 */ 423 void AddToPvs(BspLeaf *leaf, 424 const RayInfoContainer &rays, 425 int &sampleContributions, 426 int &contributingSamples); 689 427 690 428 /// Pointer to the root of the tree 691 VspBspNode *mRoot;692 693 VspBspTreeStatistics mStat;429 BspNode *mRoot; 430 431 BspTreeStatistics mStat; 694 432 695 433 /// Strategies for choosing next split plane. … … 749 487 bool mPvsUseArea; 750 488 489 float mEpsilon; 490 491 int mMaxTests; 492 751 493 private: 752 494 -
trunk/VUT/GtpVisibilityPreprocessor/src/VspKdTree.cpp
r440 r448 459 459 460 460 mStat.nodes = 1; 461 462 mBox.Initialize(); 463 464 for (VssRayContainer::const_iterator ri = rays.begin(); ri != rays.end(); ++ ri) 465 { 466 leaf->AddRay(RayInfo(*ri)); 467 468 mBox.Include((*ri)->GetOrigin()); 469 mBox.Include((*ri)->GetTermination()); 470 } 471 461 mBox.Initialize(); 462 463 //-- compute bounding box 472 464 if (forcedBoundingBox) 473 465 mBox = *forcedBoundingBox; 466 else 467 for (VssRayContainer::const_iterator ri = rays.begin(); ri != rays.end(); ++ ri) 468 { 469 mBox.Include((*ri)->GetOrigin()); 470 mBox.Include((*ri)->GetTermination()); 471 } 474 472 475 473 Debug << "bbox = " << mBox << endl; 474 475 for (VssRayContainer::const_iterator ri = rays.begin(); ri != rays.end(); ++ ri) 476 { 477 //leaf->AddRay(RayInfo(*ri)); 478 VssRay *ray = *ri; 479 480 float minT, maxT; 481 482 // TODO: not very efficient to implictly cast between rays types ... 483 if (mBox.GetRaySegment(*ray, minT, maxT)) 484 { 485 float len = ray->Length(); 486 487 if (!len) 488 len = Limits::Small; 489 490 leaf->AddRay(RayInfo(ray, minT / len, maxT / len)); 491 } 492 } 476 493 477 494 mStat.rays = (int)leaf->mRays.size(); … … 1317 1334 stack<RayTraversalData> &tstack) 1318 1335 { 1319 VspKdTreeInterior *in = (VspKdTreeInterior *) data.mNode;1336 VspKdTreeInterior *in = dynamic_cast<VspKdTreeInterior *>(data.mNode); 1320 1337 1321 1338 if (in->mAxis <= VspKdTreeNode::SPLIT_Z) … … 1688 1705 1689 1706 AxisAlignedBox3 box(node->mParent->mBox); 1690 if (node->mParent-> mFront== node)1707 if (node->mParent->GetFront() == node) 1691 1708 box.SetMin(node->mParent->mAxis, node->mParent->mPosition); 1692 1709 else … … 1763 1780 VspKdTreeInterior *interior = dynamic_cast<VspKdTreeInterior *>(node); 1764 1781 1765 nodeStack.push(interior-> mBack);1766 nodeStack.push(interior-> mFront);1767 } 1768 } 1769 } 1782 nodeStack.push(interior->GetBack()); 1783 nodeStack.push(interior->GetFront()); 1784 } 1785 } 1786 } -
trunk/VUT/GtpVisibilityPreprocessor/src/VssPreprocessor.cpp
r446 r448 384 384 VssTree *vssTree = NULL; 385 385 386 RayContainer bspRays;387 388 386 while (totalSamples < mInitialSamples) { 389 387 int passContributingSamples = 0; … … 454 452 mSceneGraph->CollectObjects(&objects); 455 453 456 //mViewCellsManager->Construct(mVssRays, objects); 454 // construct view cells 455 mViewCellsManager->Construct(objects, mVssRays, mViewSpaceBox); 457 456 458 457 vssTree = new VssTree; … … 489 488 int samples = 0; 490 489 int pass = 0; 490 491 /// Rays used for post processing and visualizations. 492 RayContainer storedRays; 493 // cast view cell samples 491 494 while (1) { 492 495 int num = mVssSamplesPerPass; … … 503 506 num = GenerateImportanceRays(vssTree, num, rays); 504 507 } 505 506 508 507 509 for (int i=0; i < rays.size(); i++) 508 510 CastRay(rays[i].mOrigin, rays[i].mDirection, vssRays); … … 528 530 } 529 531 530 // cast rays into BSP tree 531 /*if (ViewCell::sHierarchy == ViewCell::BSP) 532 { 533 for (int i = 0; i < (int)vssRays.size(); ++ i) 534 { 535 CastRay(*mBspTree, *vssRays[i]); 536 } 537 } 538 */ 532 //-- prepare traversal rays for view cell intersections 533 RayContainer passRays; 534 535 VssRayContainer::const_iterator it, it_end = vssRays.end(); 536 537 for (it = vssRays.begin(); it != it_end; ++ it) 538 passRays.push_back(new Ray(*(*it))); 539 540 int sampleContributions = 0; 541 int contributingSamples = 0; 542 543 /// compute view cell contribution of rays 544 mViewCellsManager->ComputeSampleContributions(passRays, 545 sampleContributions, 546 contributingSamples); 547 548 //-- save rays for post processing 549 if (((int)storedRays.size() < mViewCellsManager->GetPostProcessSamples()) || 550 ((int)storedRays.size() < mViewCellsManager->GetVisualizationSamples())) 551 { 552 RayContainer::const_iterator it, it_end = passRays.end(); 553 554 for (it = passRays.begin(); it != it_end; ++ it) 555 storedRays.push_back(new Ray(*(*it))); 556 } 557 else 558 { 559 CLEAR_CONTAINER(passRays); 560 } 561 539 562 samples+=num; 540 563 float pvs = vssTree->GetAvgPvsSize(); … … 547 570 pass++; 548 571 } 549 572 573 //-- post process view cells 574 mViewCellsManager->PostProcess(objects, storedRays); 575 mViewCellsManager->Visualize(objects, storedRays); 576 577 CLEAR_CONTAINER(storedRays); 578 550 579 delete vssTree; 551 580 -
trunk/VUT/GtpVisibilityPreprocessor/src/VssRay.h
r446 r448 135 135 Vector3 GetNormalizedDir() const { return (mTermination - mOrigin)*mInvSize; } 136 136 137 float Length() const { return Distance(mOrigin, mTermination); } 138 137 139 Vector3 Extrap(const float t) const { 138 140 return GetOrigin() + t * GetDir(); -
trunk/VUT/GtpVisibilityPreprocessor/src/X3dExporter.h
r446 r448 19 19 class ViewCell; 20 20 class BspTree; 21 class VspBspTree; 22 class BspNode; 21 23 22 24 class X3dExporter : public Exporter … … 92 94 ExportGeometry(const ObjectContainer &objects); 93 95 96 bool 97 ExportRays(const RayContainer &rays, 98 const float length=1000, 99 const RgbColor &color = RgbColor(1,1,1)); 100 bool 101 ExportRays(const VssRayContainer &rays, 102 const RgbColor &color = RgbColor(1,1,1)); 103 94 104 virtual void 95 105 ExportBspSplitPlanes(const BspTree &tree); … … 101 111 ExportLeavesGeometry(const BspTree &tree, const vector<BspLeaf *> &leaves); 102 112 103 bool104 ExportRays(const RayContainer &rays,105 const float length=1000,106 const RgbColor &color = RgbColor(1,1,1));107 108 bool109 ExportRays(const VssRayContainer &rays,110 const RgbColor &color = RgbColor(1,1,1));111 112 113 virtual void 113 114 ExportBspViewCellPartition(const BspTree &tree, const int maxPvs = 0); … … 116 117 ExportBspLeaves(const BspTree &tree, const int maxPvs = 0); 117 118 119 120 virtual void 121 ExportBspSplits(const VspBspTree &tree, const bool exportDepth); 122 123 virtual void 124 ExportBspViewCellPartition(const VspBspTree &tree, const int maxPvs = 0); 125 118 126 protected: 127 119 128 120 129 virtual void … … 126 135 bool 127 136 ExportBspTreeRayDensity(const BspTree &tree); 137 138 void 139 AddBoxToMesh(const AxisAlignedBox3 &box, 140 Mesh *mesh); 128 141 129 void 130 AddBoxToMesh(const AxisAlignedBox3 &box,131 Mesh *mesh);132 142 void ExportBspNodeSplits(BspNode *root, 143 const AxisAlignedBox3 &box, 144 const bool exportDepth, 145 const bool epsilon); 133 146 }; 134 147 -
trunk/VUT/GtpVisibilityPreprocessor/src/main.cpp
r446 r448 58 58 p->KdTreeStatistics(cout); 59 59 60 // parse view cell hierarchy options61 p->ParseViewCellsOptions();62 63 60 // parse view cells related options 64 61 p->PrepareViewCells();
Note: See TracChangeset
for help on using the changeset viewer.