Changeset 508 for trunk/VUT/GtpVisibilityPreprocessor/src/VspBspTree.cpp
- Timestamp:
- 01/08/06 05:56:40 (19 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/VUT/GtpVisibilityPreprocessor/src/VspBspTree.cpp
r503 r508 19 19 20 20 //-- static members 21 21 22 /** Evaluates split plane classification with respect to the plane's 22 23 contribution for a minimum number of ray splits. … … 35 36 float BspMergeCandidate::sOverallCost = 0; 36 37 37 /**************************************************************** /38 /* class VspBspTree implementation */39 /**************************************************************** /38 /********************************************************************/ 39 /* class VspBspTree implementation */ 40 /********************************************************************/ 40 41 41 42 VspBspTree::VspBspTree(): … … 44 45 mCostNormalizer(Limits::Small), 45 46 mViewCellsManager(NULL), 46 mStoreRays(false),47 47 mOutOfBoundsCell(NULL), 48 mShowInvalidSpace(false) 48 mShowInvalidSpace(false), 49 mStoreRays(false) 49 50 { 50 51 bool randomize = false; … … 88 89 environment->GetIntValue("ViewCells.maxPvs", mMaxPvs); 89 90 91 //-- termination criteria for axis aligned split 92 environment->GetFloatValue("VspBspTree.Termination.AxisAligned.maxRayContribution", 93 mTermMaxRayContriForAxisAligned); 94 environment->GetIntValue("VspBspTree.Termination.AxisAligned.minRays", 95 mTermMinRaysForAxisAligned); 96 97 //environment->GetFloatValue("VspBspTree.maxTotalMemory", mMaxTotalMemory); 98 environment->GetFloatValue("VspBspTree.maxStaticMemory", mMaxMemory); 90 99 91 100 //-- debug output … … 135 144 } 136 145 146 BspViewCell *VspBspTree::GetOutOfBoundsCell() 147 { 148 return mOutOfBoundsCell; 149 } 150 137 151 138 152 BspViewCell *VspBspTree::GetOrCreateOutOfBoundsCell() 139 153 { 140 154 if (!mOutOfBoundsCell) 155 { 141 156 mOutOfBoundsCell = new BspViewCell(); 142 157 mOutOfBoundsCell->SetId(-1); 158 } 143 159 return mOutOfBoundsCell; 144 160 } … … 326 342 } 327 343 344 345 // return memory usage in MB 346 float VspBspTree::GetMemUsage() const 347 { 348 return 349 (sizeof(VspBspTree) + 350 mStat.Leaves() * sizeof(BspLeaf) + 351 mStat.Interior() * sizeof(BspInterior) + 352 mStat.accumRays * sizeof(RayInfo)) / (1024.0f * 1024.0f); 353 } 354 355 356 328 357 void VspBspTree::Construct(const PolygonContainer &polys, RayInfoContainer *rays) 329 358 { … … 350 379 351 380 long startTime = GetTime(); 381 382 bool mOutOfMemory = false; 352 383 353 384 while (!tStack.empty()) 354 385 { 355 386 tData = tStack.top(); 356 357 tStack.pop(); 387 tStack.pop(); 388 389 if (0 && !mOutOfMemory) 390 { 391 float mem = GetMemUsage(); 392 393 if (mem > mMaxMemory) 394 { 395 mOutOfMemory = true; 396 Debug << "memory limit reached: " << mem << endl; 397 } 398 } 358 399 359 400 // subdivide leaf node … … 365 406 } 366 407 408 Debug << "Used Memory: " << GetMemUsage() << " MB" << endl; 367 409 cout << "finished\n"; 368 410 369 411 mStat.Stop(); 370 412 } 413 371 414 372 415 bool VspBspTree::TerminationCriteriaMet(const VspBspTraversalData &data) const … … 377 420 (data.mArea <= mTermMinArea) || 378 421 (mStat.Leaves() >= mMaxViewCells) || 379 //(data.GetAvgRayContribution() >= mTermMaxRayContribution) ||422 (data.GetAvgRayContribution() >= mTermMaxRayContribution) || 380 423 (data.mDepth >= mTermMaxDepth)); 381 424 } 425 382 426 383 427 BspNode *VspBspTree::Subdivide(VspBspTraversalStack &tStack, … … 386 430 BspNode *newNode = tData.mNode; 387 431 388 if (! TerminationCriteriaMet(tData))432 if (!mOutOfMemory || !TerminationCriteriaMet(tData)) 389 433 { 390 434 PolygonContainer coincident; … … 423 467 } 424 468 else 425 { 426 // create new view cell for this leaf 469 { // create new view cell for this leaf 427 470 viewCell = new BspViewCell(); 428 471 } … … 465 508 { 466 509 BspLeaf *leaf = dynamic_cast<BspLeaf *>(tData.mNode); 467 468 int maxCostMisses = tData.mMaxCostMisses; 469 510 470 511 // select subdivision plane 471 512 Plane3 splitPlane; 472 if (!SelectPlane(splitPlane, leaf, tData)) 513 int maxCostMisses = tData.mMaxCostMisses; 514 bool success = SelectPlane(splitPlane, 515 leaf, 516 tData, 517 frontData, 518 backData); 519 if (!success) 473 520 { 474 521 ++ maxCostMisses; … … 492 539 493 540 //-- the front and back traversal data is filled with the new values 541 frontData.mDepth = tData.mDepth + 1; 494 542 frontData.mPolygons = new PolygonContainer(); 495 frontData.mDepth = tData.mDepth + 1;496 543 frontData.mRays = new RayInfoContainer(); 497 frontData.mGeometry = new BspNodeGeometry();498 544 545 backData.mDepth = tData.mDepth + 1; 499 546 backData.mPolygons = new PolygonContainer(); 500 backData.mDepth = tData.mDepth + 1;501 547 backData.mRays = new RayInfoContainer(); 502 backData.mGeometry = new BspNodeGeometry(); 503 548 504 549 // subdivide rays 505 550 SplitRays(interior->GetPlane(), … … 524 569 backData.mPvs = ComputePvsSize(*backData.mRays); 525 570 526 // split geometry and compute area 527 if (1) 528 { 529 tData.mGeometry->SplitGeometry(*frontData.mGeometry, 530 *backData.mGeometry, 531 interior->GetPlane(), 532 mBox, 533 mEpsilon); 534 535 frontData.mArea = frontData.mGeometry->GetArea(); 536 backData.mArea = backData.mGeometry->GetArea(); 537 } 538 539 // compute accumulated ray length 540 //frontData.mAccRayLength = AccumulatedRayLength(*frontData.mRays); 541 //backData.mAccRayLength = AccumulatedRayLength(*backData.mRays); 571 // split front and back node geometry and compute area 572 if (mPvsUseArea) 573 { 574 // if not already computed 575 if (!frontData.mGeometry && !backData.mGeometry) 576 { 577 frontData.mGeometry = new BspNodeGeometry(); 578 backData.mGeometry = new BspNodeGeometry(); 579 580 tData.mGeometry->SplitGeometry(*frontData.mGeometry, 581 *backData.mGeometry, 582 interior->GetPlane(), 583 mBox, 584 mEpsilon); 585 586 frontData.mArea = frontData.mGeometry->GetArea(); 587 backData.mArea = backData.mGeometry->GetArea(); 588 } 589 } 590 else 591 { 592 frontData.mArea = (float)frontData.mRays->size(); 593 backData.mArea = (float)backData.mRays->size(); 594 } 542 595 543 596 //-- create front and back leaf … … 565 618 return interior; 566 619 } 620 567 621 568 622 void VspBspTree::AddToPvs(BspLeaf *leaf, … … 757 811 const VspBspTraversalData &tData, 758 812 int &axis, 759 float &position, 760 int &raysBack, 761 int &raysFront, 762 int &pvsBack, 763 int &pvsFront) 764 { 765 AxisAlignedBox3 box; 766 box.Initialize(); 767 768 // create bounding box of region 769 RayInfoContainer::const_iterator ri, ri_end = tData.mRays->end(); 770 771 for(ri = tData.mRays->begin(); ri < ri_end; ++ ri) 772 box.Include((*ri).ExtrapTermination()); 773 813 BspNodeGeometry **frontGeom, 814 BspNodeGeometry **backGeom, 815 float &frontArea, 816 float &backArea) 817 { 774 818 const bool useCostHeuristics = false; 775 819 … … 777 821 float nPosition[3]; 778 822 float nCostRatio[3]; 823 float nFrontArea[3]; 824 float nBackArea[3]; 825 826 BspNodeGeometry *nFrontGeom[3]; 827 BspNodeGeometry *nBackGeom[3]; 828 779 829 int bestAxis = -1; 780 830 781 const int sAxis = box.Size().DrivingAxis(); 831 // create bounding box of node extent 832 AxisAlignedBox3 box; 833 box.Initialize(); 834 835 #if 0 836 RayInfoContainer::const_iterator ri, ri_end = tData.mRays->end(); 837 838 for(ri = tData.mRays->begin(); ri < ri_end; ++ ri) 839 box.Include((*ri).ExtrapTermination()); 840 #else 841 PolygonContainer::const_iterator it, it_end = tData.mGeometry->mPolys.end(); 842 843 for(it = tData.mGeometry->mPolys.begin(); it < it_end; ++ it) 844 box.Include(*(*it)); 845 846 #endif 847 int sAxis = box.Size().DrivingAxis(); 782 848 783 849 for (axis = 0; axis < 3; ++ axis) 784 850 { 851 nFrontGeom[axis] = new BspNodeGeometry(); 852 nBackGeom[axis] = new BspNodeGeometry(); 853 785 854 if (!mOnlyDrivingAxis || axis == sAxis) 786 855 { … … 789 858 nPosition[axis] = (box.Min()[axis] + box.Max()[axis]) * 0.5f; 790 859 Vector3 normal(0,0,0); normal[axis] = 1; 791 792 nCostRatio[axis] = SplitPlaneCost(Plane3(normal, nPosition[axis]), tData); 860 861 nCostRatio[axis] = SplitPlaneCost(Plane3(normal, nPosition[axis]), 862 tData, *nFrontGeom[axis], *nBackGeom[axis], 863 nFrontArea[axis], nBackArea[axis]); 793 864 } 794 865 else … … 809 880 else if (nCostRatio[axis] < nCostRatio[bestAxis]) 810 881 { 811 /*Debug << "pvs front " << nPvsBack[axis]812 << " pvs back " << nPvsFront[axis]813 << " overall pvs " << leaf->GetPvsSize() << endl;*/814 882 bestAxis = axis; 815 883 } … … 820 888 //-- assign values 821 889 axis = bestAxis; 822 position = nPosition[bestAxis]; 823 824 raysBack = 0;//nRaysBack[bestAxis]; 825 raysFront = 0;//nRaysFront[bestAxis]; 826 827 pvsBack = 0;//nPvsBack[bestAxis]; 828 pvsFront = 0;//nPvsFront[bestAxis]; 829 830 Vector3 normal(0,0,0); normal[bestAxis] = 1; 890 frontArea = nFrontArea[bestAxis]; 891 backArea = nBackArea[bestAxis]; 892 893 // assign best split nodes geometry 894 *frontGeom = nFrontGeom[bestAxis]; 895 *backGeom = nBackGeom[bestAxis]; 896 // and delete other geometry 897 delete nFrontGeom[(bestAxis + 1) % 3]; 898 delete nBackGeom[(bestAxis + 2) % 3]; 899 900 //-- split plane 901 Vector3 normal(0,0,0); normal[bestAxis] = 1; 831 902 plane = Plane3(normal, nPosition[bestAxis]); 832 903 833 904 return nCostRatio[bestAxis]; 834 905 } 835 906 836 907 837 /* 838 float VspBspTree::EvalCostRatio(const VspBspTraversalData &tData, 839 const AxisAlignedBox3 &box, 840 const int axis, 841 const float position, 842 int &raysBack, 843 int &raysFront, 844 int &pvsBack, 845 int &pvsFront) 846 { 847 raysBack = 0; 848 raysFront = 0; 849 pvsFront = 0; 850 pvsBack = 0; 851 852 Intersectable::NewMail(3); 853 854 // eval pvs size 855 const int pvsSize = tData.mPvs; 856 857 // create unique ids for pvs heuristics 858 GenerateUniqueIdsForPvs(); 859 860 // this is the main ray classification loop! 861 for(RayInfoContainer::iterator ri = tData.mRays->begin(); 862 ri != tData.mRays->end(); ++ ri) 863 { 864 if (!(*ri).mRay->IsActive()) 865 continue; 866 867 // determine the side of this ray with respect to the plane 868 float t; 869 int side = (*ri).ComputeRayIntersection(axis, position, t); 870 871 if (side <= 0) 872 ++ raysBack; 873 874 if (side >= 0) 875 ++ raysFront; 876 877 AddObjToPvs((*ri).mRay->mTerminationObject, side, pvsBack, pvsFront); 878 } 879 880 //-- only one of these options should be one 881 882 if (0) //-- only pvs 883 { 884 const float sum = float(pvsBack + pvsFront); 885 const float oldCost = (float)pvsSize; 886 887 return sum / oldCost; 888 } 889 890 //-- pvs + probability heuristics 891 float pBack, pFront, pOverall; 892 893 if (0) 894 { 895 // box length substitute for probability 896 const float minBox = box.Min(axis); 897 const float maxBox = box.Max(axis); 898 899 pBack = position - minBox; 900 pFront = maxBox - position; 901 pOverall = maxBox - minBox; 902 } 903 904 if (1) //-- area substitute for probability 905 { 906 907 const bool useMidSplit = true; 908 //const bool useMidSplit = false; 909 910 pOverall = box.SurfaceArea(); 911 912 if (!useMidSplit) 913 { 914 Vector3 pos = box.Max(); pos[axis] = position; 915 pBack = AxisAlignedBox3(box.Min(), pos).SurfaceArea(); 916 917 pos = box.Min(); pos[axis] = position; 918 pFront = AxisAlignedBox3(pos, box.Max()).SurfaceArea(); 919 } 920 else 921 { 922 //-- simplified computation for mid split 923 const int axis2 = (axis + 1) % 3; 924 const int axis3 = (axis + 2) % 3; 925 926 const float faceArea = 927 (box.Max(axis2) - box.Min(axis2)) * 928 (box.Max(axis3) - box.Min(axis3)); 929 930 pBack = pFront = pOverall * 0.5f + faceArea; 931 } 932 } 933 934 //-- ray density substitute for probability 935 if (0) 936 { 937 pBack = (float)raysBack; 938 pFront = (float)raysFront; 939 pOverall = (float)tData.mRays->size(); 940 } 941 942 //Debug << axis << " " << pvsSize << " " << pvsBack << " " << pvsFront << endl; 943 //Debug << pFront << " " << pBack << " " << pOverall << endl; 944 945 // float sum = raysBack*(position - minBox) + raysFront*(maxBox - position); 946 const float newCost = pvsBack * pBack + pvsFront * pFront; 947 // float oldCost = leaf->mRays.size(); 948 const float oldCost = (float)pvsSize * pOverall; 949 950 return (mCtDivCi + newCost) / oldCost; 951 } 952 */ 953 954 955 bool VspBspTree::SelectPlane(Plane3 &plane, 908 bool VspBspTree::SelectPlane(Plane3 &bestPlane, 956 909 BspLeaf *leaf, 957 VspBspTraversalData &data) 910 VspBspTraversalData &data, 911 VspBspTraversalData &frontData, 912 VspBspTraversalData &backData) 958 913 { 959 914 // simplest strategy: just take next polygon … … 962 917 if (!data.mPolygons->empty()) 963 918 { 964 const int randIdx = (int)RandomValue(0, (Real)((int)data.mPolygons->size() - 1)); 919 const int randIdx = 920 (int)RandomValue(0, (Real)((int)data.mPolygons->size() - 1)); 965 921 Polygon3 *nextPoly = (*data.mPolygons)[randIdx]; 966 922 967 plane = nextPoly->GetSupportingPlane();923 bestPlane = nextPoly->GetSupportingPlane(); 968 924 return true; 969 925 } 970 926 } 971 927 972 // use heuristics to find appropriate plane 973 return SelectPlaneHeuristics(plane, leaf, data); 928 //-- use heuristics to find appropriate plane 929 930 // intermediate plane 931 Plane3 plane; 932 float lowestCost = MAX_FLOAT; 933 934 const bool onlyAxisAligned = 935 (mSplitPlaneStrategy & AXIS_ALIGNED) && 936 ((int)data.mRays->size() > mTermMinRaysForAxisAligned) && 937 ((int)data.GetAvgRayContribution() < mTermMaxRayContriForAxisAligned); 938 939 // split polygons if no axis aligned splits 940 const int limit = onlyAxisAligned ? 0 : 941 Min((int)data.mPolygons->size(), mMaxPolyCandidates); 942 943 float candidateCost; 944 945 int maxIdx = (int)data.mPolygons->size(); 946 947 for (int i = 0; i < limit; ++ i) 948 { 949 //-- assure that no index is taken twice 950 const int candidateIdx = (int)RandomValue(0, (Real)(-- maxIdx)); 951 Polygon3 *poly = (*data.mPolygons)[candidateIdx]; 952 953 // swap candidate to the end to avoid testing same plane 954 std::swap((*data.mPolygons)[maxIdx], (*data.mPolygons)[candidateIdx]); 955 //Polygon3 *poly = (*data.mPolygons)[(int)RandomValue(0, (int)polys.size() - 1)]; 956 957 // evaluate current candidate 958 BspNodeGeometry fGeom, bGeom; 959 float fArea, bArea; 960 plane = poly->GetSupportingPlane(); 961 candidateCost = SplitPlaneCost(plane, data, fGeom, bGeom, fArea, bArea); 962 963 if (candidateCost < lowestCost) 964 { 965 bestPlane = plane; 966 lowestCost = candidateCost; 967 } 968 } 969 970 //-- evaluate axis aligned splits 971 int axis; 972 BspNodeGeometry *fGeom, *bGeom; 973 float fArea, bArea; 974 975 candidateCost = SelectAxisAlignedPlane(plane, data, axis, 976 &fGeom, &bGeom, 977 fArea, bArea); 978 979 if (candidateCost < lowestCost) 980 { 981 bestPlane = plane; 982 lowestCost = candidateCost; 983 984 //-- assign already computed values 985 frontData.mGeometry = fGeom; 986 backData.mGeometry = bGeom; 987 frontData.mArea = fArea; 988 backData.mArea = bArea; 989 990 //! error also computed if cost ratio is missed 991 ++ mStat.splits[axis]; 992 } 993 else 994 { 995 DEL_PTR(fGeom); 996 DEL_PTR(bGeom); 997 } 998 999 #ifdef _DEBUG 1000 Debug << "plane lowest cost: " << lowestCost << endl; 1001 #endif 1002 1003 // cost ratio miss 1004 if (lowestCost > mTermMaxCostRatio) 1005 return false; 1006 1007 return true; 974 1008 } 975 1009 … … 1048 1082 1049 1083 1050 bool VspBspTree::SelectPlaneHeuristics(Plane3 &bestPlane,1051 BspLeaf *leaf,1052 VspBspTraversalData &data)1053 {1054 float lowestCost = MAX_FLOAT;1055 // intermediate plane1056 Plane3 plane;1057 bool useAxisAlignedPlane = false;1058 1059 const int limit = Min((int)data.mPolygons->size(), mMaxPolyCandidates);1060 int maxIdx = (int)data.mPolygons->size();1061 1062 float candidateCost;1063 1064 for (int i = 0; i < limit; ++ i)1065 {1066 //-- assure that no index is taken twice1067 const int candidateIdx = (int)RandomValue(0, (Real)(-- maxIdx));1068 Polygon3 *poly = (*data.mPolygons)[candidateIdx];1069 1070 // swap candidate to the end to avoid testing same plane1071 std::swap((*data.mPolygons)[maxIdx], (*data.mPolygons)[candidateIdx]);1072 1073 //Polygon3 *poly = (*data.mPolygons)[(int)RandomValue(0, (int)polys.size() - 1)];1074 1075 // evaluate current candidate1076 candidateCost = SplitPlaneCost(poly->GetSupportingPlane(), data);1077 1078 if (candidateCost < lowestCost)1079 {1080 bestPlane = poly->GetSupportingPlane();1081 lowestCost = candidateCost;1082 }1083 }1084 1085 //-- axis aligned splits1086 int axis;1087 float position;1088 int raysBack;1089 int raysFront;1090 int pvsFront;1091 int pvsBack;1092 1093 candidateCost = SelectAxisAlignedPlane(plane,1094 data,1095 axis,1096 position,1097 raysBack,1098 raysFront,1099 pvsFront,1100 pvsBack);1101 1102 if (candidateCost < lowestCost)1103 {1104 if (!useAxisAlignedPlane)1105 {1106 useAxisAlignedPlane = true;1107 //if (data.mPolygons->size() > 0)1108 // Debug << "haha" << endl;1109 //! error also computed if cost ratio is missed1110 ++ mStat.splits[axis];1111 }1112 1113 bestPlane = plane;1114 lowestCost = candidateCost;1115 }1116 1117 #ifdef _DEBUG1118 Debug << "plane lowest cost: " << lowestCost << endl;1119 #endif1120 1121 // cost ratio miss1122 if (lowestCost > mTermMaxCostRatio)1123 return false;1124 1125 return true;1126 }1127 1128 1129 1084 inline void VspBspTree::GenerateUniqueIdsForPvs() 1130 1085 { … … 1136 1091 1137 1092 float VspBspTree::SplitPlaneCost(const Plane3 &candidatePlane, 1138 const VspBspTraversalData &data) const 1093 const VspBspTraversalData &data, 1094 BspNodeGeometry &geomFront, 1095 BspNodeGeometry &geomBack, 1096 float &areaFront, 1097 float &areaBack) const 1139 1098 { 1140 1099 float cost = 0; … … 1143 1102 float sumRaySplits = 0; 1144 1103 1145 int frontPvs= 0;1146 int backPvs= 0;1147 1148 // probability that view point lies in child1104 int pvsFront = 0; 1105 int pvsBack = 0; 1106 1107 // probability that view point lies in back / front node 1149 1108 float pOverall = 0; 1150 1109 float pFront = 0; 1151 1110 float pBack = 0; 1152 1111 1112 int raysFront = 0; 1113 int raysBack = 0; 1114 int totalPvs = 0; 1115 1153 1116 if (mSplitPlaneStrategy & PVS) 1154 1117 { … … 1159 1122 { 1160 1123 // construct child geometry with regard to the candidate split plane 1161 BspNodeGeometry frontCell; 1162 BspNodeGeometry backCell; 1163 1164 data.mGeometry->SplitGeometry(frontCell, 1165 backCell, 1124 data.mGeometry->SplitGeometry(geomFront, 1125 geomBack, 1166 1126 candidatePlane, 1167 1127 mBox, 1168 1128 mEpsilon); 1169 1129 1170 pFront = frontCell.GetArea(); 1171 pBack = backCell.GetArea(); 1172 1130 areaFront = geomFront.GetArea(); 1131 areaBack = geomBack.GetArea(); 1132 1133 pBack = areaBack; 1134 pFront = areaFront; 1173 1135 pOverall = data.mArea; 1136 } 1137 else // use number of rays to approximate volume 1138 { 1139 pOverall = (float)data.mRays->size(); 1140 pFront = (float)raysFront; 1141 pBack = (float)raysBack; 1174 1142 } 1175 1143 } … … 1189 1157 limit = (int)data.mRays->size(); 1190 1158 } 1191 1159 1192 1160 for (int i = 0; i < limit; ++ i) 1193 1161 { 1194 const int testIdx = useRand ? (int)RandomValue(0, (Real)(limit - 1)) : i; 1162 const int testIdx = useRand ? 1163 (int)RandomValue(0, (Real)((int)data.mRays->size() - 1)) : i; 1195 1164 RayInfo rayInf = (*data.mRays)[testIdx]; 1196 1165 1166 float t; 1197 1167 VssRay *ray = rayInf.mRay; 1198 float t;1199 1168 const int cf = rayInf.ComputeRayIntersection(candidatePlane, t); 1169 1170 if (cf >= 0) 1171 ++ raysFront; 1172 if (cf <= 0) 1173 ++ raysBack; 1200 1174 1201 1175 if (mSplitPlaneStrategy & LEAST_RAY_SPLITS) … … 1212 1186 if (mSplitPlaneStrategy & PVS) 1213 1187 { 1214 // in case the ray intersects an object 1215 // assure that we only count the object 1216 // once for the front and once for the back side of the plane 1217 AddObjToPvs(ray->mTerminationObject, cf, frontPvs, backPvs); 1218 AddObjToPvs(ray->mOriginObject, cf, frontPvs, backPvs); 1219 1220 // use number of rays to approximate volume 1221 if (!mPvsUseArea) 1222 { 1223 pOverall = (float)data.mRays->size(); 1224 1225 if (cf >= 0) 1226 ++ pFront; 1227 if (cf <= 0) 1228 ++ pBack; 1229 } 1188 // find front and back pvs for origing and termination object 1189 AddObjToPvs(ray->mTerminationObject, cf, pvsFront, pvsBack, totalPvs); 1190 AddObjToPvs(ray->mOriginObject, cf, pvsFront, pvsBack, totalPvs); 1230 1191 } 1231 1192 } … … 1242 1203 if (mSplitPlaneStrategy & PVS) 1243 1204 { 1244 const float oldCost = pOverall * (float)data.mPvs + Limits::Small; 1245 cost += mPvsFactor * (frontPvs * pFront + backPvs * pBack) / oldCost; 1246 1247 //cost += mPvsFactor * 0.5 * (frontPvs * pFront + backPvs * pBack) / oldCost; 1248 //Debug << "new cost: " << cost << " over" << frontPvs * pFront + backPvs * pBack << " old cost " << oldCost << endl; 1249 1250 if (0) // give penalty to unbalanced split 1251 if (((pFront * 0.2 + Limits::Small) > pBack) || 1252 (pFront < (pBack * 0.2 + Limits::Small))) 1253 cost += 0.5; 1205 const float oldCost = pOverall * (float)totalPvs + Limits::Small; 1206 cost += mPvsFactor * (pvsFront * pFront + pvsBack * pBack) / oldCost; 1254 1207 } 1255 1208 1256 1209 #ifdef _DEBUG 1257 1210 Debug << "totalpvs: " << data.mPvs << " ptotal: " << pOverall 1258 << " frontpvs: " << frontPvs<< " pFront: " << pFront1259 << " backpvs: " << backPvs<< " pBack: " << pBack << endl << endl;1211 << " frontpvs: " << pvsFront << " pFront: " << pFront 1212 << " backpvs: " << pvsBack << " pBack: " << pBack << endl << endl; 1260 1213 #endif 1261 1214 … … 1263 1216 return cost / (float)mCostNormalizer; 1264 1217 } 1218 1265 1219 1266 1220 void VspBspTree::AddObjToPvs(Intersectable *obj, 1267 1221 const int cf, 1268 1222 int &frontPvs, 1269 int &backPvs) const 1223 int &backPvs, 1224 int &totalPvs) const 1270 1225 { 1271 1226 if (!obj) 1272 1227 return; 1228 1229 if ((obj->mMailbox != sFrontId) && 1230 (obj->mMailbox != sBackId) && 1231 (obj->mMailbox != sFrontAndBackId)) 1232 { 1233 ++ totalPvs; 1234 } 1235 1273 1236 // TODO: does this really belong to no pvs? 1274 1237 //if (cf == Ray::COINCIDENT) return; … … 1281 1244 { 1282 1245 ++ frontPvs; 1283 1246 1284 1247 if (obj->mMailbox == sBackId) 1285 1248 obj->mMailbox = sFrontAndBackId; … … 1295 1258 { 1296 1259 ++ backPvs; 1297 1260 1298 1261 if (obj->mMailbox == sFrontId) 1299 1262 obj->mMailbox = sFrontAndBackId; … … 1322 1285 BspLeaf *leaf = dynamic_cast<BspLeaf *>(node); 1323 1286 if (leaf->TreeValid() && 1324 (!onlyUnmailed || leaf->Mailed()) &&1287 (!onlyUnmailed || !leaf->Mailed()) && 1325 1288 ((maxPvsSize < 0) || (leaf->GetViewCell()->GetPvs().GetSize() <= maxPvsSize))) 1326 1289 { … … 1351 1314 1352 1315 1353 BspViewCell *VspBspTree::GetOutOfBoundsCell() const1354 {1355 return mOutOfBoundsCell;1356 }1357 1358 1359 1316 void VspBspTree::EvaluateLeafStats(const VspBspTraversalData &data) 1360 1317 { … … 1368 1325 if (data.mPvs > mStat.maxPvs) 1369 1326 mStat.maxPvs = data.mPvs; 1327 1370 1328 if (data.mDepth < mStat.minDepth) 1371 1329 mStat.minDepth = data.mDepth; 1330 1372 1331 if (data.mDepth >= mTermMaxDepth) 1373 1332 ++ mStat.maxDepthNodes; 1333 // accumulate rays to compute rays / leaf 1334 mStat.accumRays += (int)data.mRays->size(); 1374 1335 1375 1336 if (data.mPvs < mTermMinPvs) … … 1383 1344 1384 1345 if (data.mArea <= mTermMinArea) 1385 {1386 //Debug << "area: " << data.mArea / mBox.SurfaceArea() << " min area: " << mTermMinArea / mBox.SurfaceArea() << endl;1387 1346 ++ mStat.minAreaNodes; 1388 }1347 1389 1348 // accumulate depth to compute average depth 1390 1349 mStat.accumDepth += data.mDepth; … … 1498 1457 } 1499 1458 1500 bool VspBspTree::Export(const string filename)1501 {1502 Exporter *exporter = Exporter::GetExporter(filename);1503 1504 if (exporter)1505 {1506 //exporter->ExportVspBspTree(*this);1507 return true;1508 }1509 1510 return false;1511 }1512 1513 1459 void VspBspTree::CollectViewCells(ViewCellContainer &viewCells) const 1514 1460 { … … 1516 1462 1517 1463 if (!mRoot) 1518 return;1464 return; 1519 1465 1520 1466 nodeStack.push(mRoot); … … 1543 1489 { 1544 1490 BspInterior *interior = dynamic_cast<BspInterior *>(node); 1545 1491 1546 1492 nodeStack.push(interior->GetFront()); 1547 1493 nodeStack.push(interior->GetBack()); … … 2245 2191 { 2246 2192 BspLeaf::NewMail(); 2247 2193 2248 2194 vector<BspLeaf *>::const_iterator it, it_end = leaves.end(); 2249 2195 2196 Debug << "mergequeue size: " << mMergeQueue.size() << endl; 2250 2197 // find merge candidates and push them into queue 2251 2198 for (it = leaves.begin(); it != it_end; ++ it) … … 2268 2215 // TODO: test if at least one ray goes from one leaf to the other 2269 2216 for (nit = neighbors.begin(); nit != nit_end; ++ nit) 2270 { 2271 mMergeQueue.push(BspMergeCandidate(leaf, *nit)); 2272 } 2273 } 2217 { 2218 if ((*nit)->GetViewCell() != leaf->GetViewCell()) 2219 mMergeQueue.push(BspMergeCandidate(leaf, *nit)); 2220 } 2221 } 2222 2223 Debug << "new mergequeue size: " << mMergeQueue.size() << endl; 2274 2224 2275 2225 return (int)leaves.size(); … … 2283 2233 long startTime = GetTime(); 2284 2234 ConstructBspRays(bspRays, rays); 2285 Debug << (int)bspRays.size() << " bsp rays constructed in " << TimeDiff(startTime, GetTime()) * 1e-3f << " secs" << endl; 2235 Debug << (int)bspRays.size() << " bsp rays constructed in " 2236 << TimeDiff(startTime, GetTime()) * 1e-3f << " secs" << endl; 2286 2237 2287 2238 map<BspLeaf *, vector<BspLeaf*> > neighborMap; … … 2324 2275 leaf = (*iit).mLeaf; 2325 2276 2326 // view space not valid 2327 if (!leaf->TreeValid() || !prevLeaf->TreeValid()) 2277 // view space not valid or same view cell 2278 if (!leaf->TreeValid() || !prevLeaf->TreeValid() || 2279 (leaf->GetViewCell() == prevLeaf->GetViewCell())) 2328 2280 continue; 2329 2281 … … 2379 2331 vector<BspLeaf *> leaves; 2380 2332 CollectLeaves(leaves, true, mMaxPvs); 2381 Debug << "found " << (int)leaves.size() << " new leaves" << endl; 2382 //CollectMergeCandidates(leaves); 2333 Debug << "found " << (int)leaves.size() << " new leaves" << endl << endl; 2334 // TODO 2335 CollectMergeCandidates(leaves); 2383 2336 2384 2337 return numLeaves; … … 2508 2461 2509 2462 2510 ViewCell * 2511 VspBspTree::GetViewCell(const Vector3 &point) 2463 ViewCell *VspBspTree::GetViewCell(const Vector3 &point) 2512 2464 { 2513 2465 if (mRoot == NULL) … … 2737 2689 } 2738 2690 2739 #define USE_ASCII 0 2740 bool VspBspTree::WriteVspBspTree() 2741 { 2742 char fileName[100]; 2743 environment->GetStringValue("VspBspTree.viewCellsFilename", fileName); 2691 2692 bool VspBspTree::Export(ofstream &stream) 2693 { 2694 ExportNode(mRoot, stream); 2695 2696 return true; 2697 } 2698 2699 2700 void VspBspTree::ExportNode(BspNode *node, ofstream &stream) 2701 { 2702 if (node->IsLeaf()) 2703 { 2704 BspLeaf *leaf = dynamic_cast<BspLeaf *>(node); 2705 2706 int id = -1; 2707 if (leaf->GetViewCell() != mOutOfBoundsCell) 2708 id = leaf->GetViewCell()->GetId(); 2709 2710 stream << "<Leaf viewCellId=\"" << id << "\" />" << endl; 2711 } 2712 else 2713 { 2714 BspInterior *interior = dynamic_cast<BspInterior *>(node); 2744 2715 2745 /*VssRayContainer::const_iterator it, it_end = samples.end(); 2746 2747 #if USE_ASCII 2748 ofstream samplesOut(fileName); 2749 if (!samplesOut.is_open()) 2750 return false; 2751 2752 for (it = samples.begin(); it != it_end; ++ it) 2753 { 2754 VssRay *ray = *it; 2755 int sourceid = ray->mOriginObject ? ray->mOriginObject->mId : -1; 2756 int termid = ray->mTerminationObject ? ray->mTerminationObject->mId : -1; 2757 2758 samplesOut << ray->GetOrigin().x << " " << ray->GetOrigin().y << " " << ray->GetOrigin().z << " " 2759 << ray->GetTermination().x << " " << ray->GetTermination().y << " " << ray->GetTermination().z << " " 2760 << sourceid << " " << termid << "\n"; 2761 } 2762 #else 2763 ofstream samplesOut(fileName, ios::binary); 2764 if (!samplesOut.is_open()) 2765 return false; 2766 2767 for (it = samples.begin(); it != it_end; ++ it) 2768 { 2769 VssRay *ray = *it; 2770 Vector3 origin(ray->GetOrigin()); 2771 Vector3 termination(ray->GetTermination()); 2772 2773 int sourceid = ray->mOriginObject ? ray->mOriginObject->mId : -1; 2774 int termid = ray->mTerminationObject ? ray->mTerminationObject->mId : -1; 2775 2776 samplesOut.write(reinterpret_cast<char *>(&origin), sizeof(Vector3)); 2777 samplesOut.write(reinterpret_cast<char *>(&termination), sizeof(Vector3)); 2778 samplesOut.write(reinterpret_cast<char *>(&sourceid), sizeof(int)); 2779 samplesOut.write(reinterpret_cast<char *>(&termid), sizeof(int)); 2780 } 2781 #endif 2782 2783 samplesOut.close(); 2784 */ 2785 return true; 2786 } 2787 2788 bool VspBspTree::LoadVspBspTree() 2789 { 2790 /*std::stable_sort(objects.begin(), objects.end(), ilt); 2791 char fileName[100]; 2792 environment->GetStringValue("Preprocessor.samplesFilename", fileName); 2793 2794 Vector3 origin, termination; 2795 // HACK: needed only for lower_bound algorithm to find the 2796 // intersected objects 2797 MeshInstance sObj(NULL); 2798 MeshInstance tObj(NULL); 2799 2800 #if USE_ASCII 2801 ifstream samplesIn(fileName, ios::binary); 2802 if (!samplesIn.is_open()) 2803 return false; 2804 2805 string buf; 2806 while (!(getline(samplesIn, buf)).eof()) 2807 { 2808 sscanf(buf.c_str(), "%f %f %f %f %f %f %d %d", 2809 &origin.x, &origin.y, &origin.z, 2810 &termination.x, &termination.y, &termination.z, 2811 &(sObj.mId), &(tObj.mId)); 2812 2813 Intersectable *sourceObj = NULL; 2814 Intersectable *termObj = NULL; 2815 2816 if (sObj.mId >= 0) 2817 { 2818 ObjectContainer::iterator oit = 2819 lower_bound(objects.begin(), objects.end(), &sObj, ilt); 2820 sourceObj = *oit; 2821 } 2822 2823 if (tObj.mId >= 0) 2824 { 2825 ObjectContainer::iterator oit = 2826 lower_bound(objects.begin(), objects.end(), &tObj, ilt); 2827 termObj = *oit; 2828 } 2829 2830 samples.push_back(new VssRay(origin, termination, sourceObj, termObj)); 2831 } 2832 #else 2833 ifstream samplesIn(fileName, ios::binary); 2834 if (!samplesIn.is_open()) 2835 return false; 2836 2837 while (1) 2838 { 2839 samplesIn.read(reinterpret_cast<char *>(&origin), sizeof(Vector3)); 2840 samplesIn.read(reinterpret_cast<char *>(&termination), sizeof(Vector3)); 2841 samplesIn.read(reinterpret_cast<char *>(&(sObj.mId)), sizeof(int)); 2842 samplesIn.read(reinterpret_cast<char *>(&(tObj.mId)), sizeof(int)); 2843 2844 if (samplesIn.eof()) 2845 break; 2846 2847 Intersectable *sourceObj = NULL; 2848 Intersectable *termObj = NULL; 2849 2850 if (sObj.mId >= 0) 2851 { 2852 ObjectContainer::iterator oit = 2853 lower_bound(objects.begin(), objects.end(), &sObj, ilt); 2854 sourceObj = *oit; 2855 } 2856 2857 if (tObj.mId >= 0) 2858 { 2859 ObjectContainer::iterator oit = 2860 lower_bound(objects.begin(), objects.end(), &tObj, ilt); 2861 termObj = *oit; 2862 } 2863 2864 samples.push_back(new VssRay(origin, termination, sourceObj, termObj)); 2865 } 2866 2867 #endif 2868 samplesIn.close(); 2869 */ 2870 return true; 2871 } 2872 2716 Plane3 plane = interior->GetPlane(); 2717 stream << "<Interior plane=\"" << plane.mNormal.x << " " 2718 << plane.mNormal.y << " " << plane.mNormal.z << " " 2719 << plane.mD << "\">" << endl; 2720 2721 ExportNode(interior->GetBack(), stream); 2722 ExportNode(interior->GetFront(), stream); 2723 2724 stream << "</Interior>" << endl; 2725 } 2726 } 2873 2727 2874 2728 /************************************************************************/
Note: See TracChangeset
for help on using the changeset viewer.