Ignore:
Timestamp:
02/01/06 19:29:59 (18 years ago)
Author:
mattausch
Message:

implemented variance
started implementing merge history

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/VUT/GtpVisibilityPreprocessor/src/VspBspTree.cpp

    r579 r580  
    2525const float VspBspTree::sLeastRaySplitsTable[] = {0, 0, 1, 1, 0}; 
    2626/** Evaluates split plane classification with respect to the plane's 
    27         contribution for balanced rays. 
     27        contribution for  balanced rays. 
    2828*/ 
    2929const float VspBspTree::sBalancedRaysTable[] = {1, -1, 0, 0, 0}; 
    3030 
    31 ViewCellsManager *BspMergeCandidate::sViewCellsManager = NULL; 
    32 //int BspMergeCandidate::sMaxPvsSize = 0; 
    33 //int BspMergeCandidate::sMinPvsSize = 0; 
    3431 
    3532int VspBspTree::sFrontId = 0; 
     
    3734int VspBspTree::sFrontAndBackId = 0; 
    3835 
    39 float BspMergeCandidate::sOverallCost = 0; 
    40 float BspMergeCandidate::sExpectedCost = 0; 
    41 float BspMergeCandidate::sVariance = 0; 
    42 float BspMergeCandidate::sRenderCostWeight = 0.5f; 
    43 bool BspMergeCandidate::sUseArea = false; 
    44 int BspMergeCandidate::sNumViewCells = 0; 
    45  
    46 //int upperPvsLimit = 120; 
    47 //int lowerPvsLimit = 5; 
    4836 
    4937 
     
    6452 
    6553 
    66 // penalty for pvs durint merge 
    67 inline float EvalPvsPenaltyForMerge(const int pvs,  
    68                                                                         const int lower, 
    69                                                                         const int upper) 
    70 { 
    71         // clamp to minmax values 
    72         if (pvs < lower) 
    73                 return (float)lower; 
    74         if (pvs > upper) 
    75                 return (float)upper; 
    76  
    77         return (float)pvs; 
    78 } 
    7954 
    8055 
     
    9065mViewCellsManager(NULL), 
    9166mOutOfBoundsCell(NULL), 
    92 mStoreRays(false) 
     67mStoreRays(false), 
     68mRenderCostWeight(0.5) 
    9369{ 
    9470        bool randomize = false; 
     
    126102        // if only the driving axis is used for axis aligned split 
    127103        environment->GetBoolValue("VspBspTree.splitUseOnlyDrivingAxis", mOnlyDrivingAxis); 
    128  
    129         //-- merge options 
    130         environment->GetIntValue("VspBspTree.PostProcess.minViewCells", mMergeMinViewCells); 
    131         environment->GetFloatValue("VspBspTree.PostProcess.maxCostRatio", mMergeMaxCostRatio); 
    132         environment->GetBoolValue("VspBspTree.PostProcess.useRaysForMerge", mUseRaysForMerge); 
    133  
    134  
     104         
    135105        //-- termination criteria for axis aligned split 
    136106        environment->GetFloatValue("VspBspTree.Termination.AxisAligned.maxRayContribution",  
     
    142112        environment->GetFloatValue("VspBspTree.maxStaticMemory", mMaxMemory); 
    143113 
    144         environment->GetBoolValue("VspBspTree.Visualization.exportMergedViewCells", mExportMergedViewCells); 
    145         environment->GetBoolValue("VspBspTree.PostProcess.exportMergeStats", mExportMergeStats); 
    146          
    147  
    148         mStats.open("bspStats.log"); 
     114        environment->GetFloatValue("VspBspTree.Construction.renderCostWeight", mRenderCostWeight); 
     115 
     116 
     117 
    149118 
    150119        //-- debug output 
     120 
    151121        Debug << "******* VSP BSP options ******** " << endl; 
    152122    Debug << "max depth: " << mTermMaxDepth << endl; 
     
    162132        Debug << "max plane candidates: " << mMaxRayCandidates << endl; 
    163133        Debug << "randomize: " << randomize << endl; 
    164         Debug << "minimum view cells: " << mMergeMinViewCells << endl; 
     134//      Debug << "minimum view cells: " << mMergeMinViewCells << endl; 
    165135        Debug << "using area for pvs: " << mUseAreaForPvs << endl; 
     136        Debug << "render cost weight: " << mRenderCostWeight << endl; 
    166137        Debug << "Split plane strategy: "; 
    167138 
     
    195166        Debug << endl; 
    196167} 
     168 
    197169 
    198170BspViewCell *VspBspTree::GetOutOfBoundsCell() 
     
    249221        return (int)mesh->mFaces.size(); 
    250222} 
     223 
    251224 
    252225int VspBspTree::AddToPolygonSoup(const ViewCellContainer &viewCells, 
     
    273246        return polysSize; 
    274247} 
     248 
    275249 
    276250int VspBspTree::AddToPolygonSoup(const ObjectContainer &objects, 
     
    310284} 
    311285 
     286 
    312287void VspBspTree::Construct(const VssRayContainer &sampleRays, 
    313288                                                   AxisAlignedBox3 *forcedBoundingBox) 
     
    366341         
    367342        Debug << "maximal pvs (i.e., pvs still considered as valid) : " << mViewCellsManager->GetMaxPvsSize() << endl; 
     343 
    368344        //-- store rays 
    369345        for (rit = sampleRays.begin(); rit != rit_end; ++ rit) 
     
    572548                } 
    573549                 
    574         viewCell->mLeaves.push_back(leaf); 
     550        viewCell->mLeaf = leaf; 
    575551 
    576552                if (mUseAreaForPvs) 
     
    589565        return newNode; 
    590566} 
    591  
    592  
    593567 
    594568 
     
    752726} 
    753727 
     728 
    754729void VspBspTree::SortSplitCandidates(const RayInfoContainer &rays, const int axis) 
    755730{ 
     
    780755        stable_sort(mSplitCandidates->begin(), mSplitCandidates->end()); 
    781756} 
     757 
    782758 
    783759float VspBspTree::BestCostRatioHeuristics(const RayInfoContainer &rays, 
     
    10351011 
    10361012 
     1013bool VspBspTree::SelectPlane(Plane3 &bestPlane, 
     1014                                                         BspLeaf *leaf, 
     1015                                                         VspBspTraversalData &data, 
     1016                                                         VspBspTraversalData &frontData, 
     1017                                                         VspBspTraversalData &backData) 
     1018{ 
     1019        // simplest strategy: just take next polygon 
     1020        if (mSplitPlaneStrategy & RANDOM_POLYGON) 
     1021        { 
     1022        if (!data.mPolygons->empty()) 
     1023                { 
     1024                        const int randIdx =  
     1025                                (int)RandomValue(0, (Real)((int)data.mPolygons->size() - 1)); 
     1026                        Polygon3 *nextPoly = (*data.mPolygons)[randIdx]; 
     1027 
     1028                        bestPlane = nextPoly->GetSupportingPlane(); 
     1029                        return true; 
     1030                } 
     1031        } 
     1032 
     1033        //-- use heuristics to find appropriate plane 
     1034 
     1035        // intermediate plane 
     1036        Plane3 plane; 
     1037        float lowestCost = MAX_FLOAT; 
     1038         
     1039        // decides if the first few splits should be only axisAligned 
     1040        const bool onlyAxisAligned  =  
     1041                (mSplitPlaneStrategy & AXIS_ALIGNED) && 
     1042                ((int)data.mRays->size() > mTermMinRaysForAxisAligned) && 
     1043                ((int)data.GetAvgRayContribution() < mTermMaxRayContriForAxisAligned); 
     1044         
     1045        const int limit = onlyAxisAligned ? 0 :  
     1046                Min((int)data.mPolygons->size(), mMaxPolyCandidates); 
     1047 
     1048        float candidateCost; 
     1049 
     1050        int maxIdx = (int)data.mPolygons->size(); 
     1051 
     1052        for (int i = 0; i < limit; ++ i) 
     1053        { 
     1054                // the already taken candidates are stored behind maxIdx 
     1055                // => assure that no index is taken twice 
     1056                const int candidateIdx = (int)RandomValue(0, (Real)(-- maxIdx)); 
     1057                Polygon3 *poly = (*data.mPolygons)[candidateIdx]; 
     1058 
     1059                // swap candidate to the end to avoid testing same plane 
     1060                std::swap((*data.mPolygons)[maxIdx], (*data.mPolygons)[candidateIdx]); 
     1061                //Polygon3 *poly = (*data.mPolygons)[(int)RandomValue(0, (int)polys.size() - 1)]; 
     1062 
     1063                // evaluate current candidate 
     1064                BspNodeGeometry fGeom, bGeom; 
     1065                float fArea, bArea; 
     1066                plane = poly->GetSupportingPlane(); 
     1067                candidateCost = EvalSplitPlaneCost(plane, data, fGeom, bGeom, fArea, bArea); 
     1068                 
     1069                if (candidateCost < lowestCost) 
     1070                { 
     1071                        bestPlane = plane; 
     1072                        lowestCost = candidateCost; 
     1073                } 
     1074        } 
     1075 
     1076        //-- evaluate axis aligned splits 
     1077        int axis; 
     1078        BspNodeGeometry *fGeom, *bGeom; 
     1079        float pFront, pBack; 
     1080 
     1081        candidateCost = SelectAxisAlignedPlane(plane, data, axis, 
     1082                                                                                   &fGeom, &bGeom,  
     1083                                                                                   pFront, pBack, 
     1084                                                                                   data.mIsKdNode);       
     1085 
     1086        bool isAxisAlignedSplit = false; 
     1087 
     1088        if (candidateCost < lowestCost) 
     1089        {        
     1090                bestPlane = plane; 
     1091                lowestCost = candidateCost; 
     1092 
     1093                // assign already computed values 
     1094                // we can do this because we always save the 
     1095                // computed values from the axis aligned splits          
     1096                frontData.mGeometry = fGeom; 
     1097                backData.mGeometry = bGeom; 
     1098         
     1099                frontData.mProbability = pFront; 
     1100                backData.mProbability = pBack; 
     1101                 
     1102                //! error also computed if cost ratio is missed 
     1103                ++ mBspStats.splits[axis]; 
     1104                isAxisAlignedSplit = true; 
     1105        } 
     1106        else 
     1107        { 
     1108                DEL_PTR(fGeom); 
     1109                DEL_PTR(bGeom); 
     1110        } 
     1111 
     1112        frontData.mIsKdNode = backData.mIsKdNode = (data.mIsKdNode && isAxisAlignedSplit); 
     1113 
     1114#ifdef _DEBUG 
     1115        Debug << "plane lowest cost: " << lowestCost << endl; 
     1116#endif 
     1117 
     1118        // cost ratio miss 
     1119        if (lowestCost > mTermMaxCostRatio) 
     1120                return false; 
     1121 
     1122        return true; 
     1123} 
     1124 
     1125 
     1126Plane3 VspBspTree::ChooseCandidatePlane(const RayInfoContainer &rays) const 
     1127{ 
     1128        const int candidateIdx = (int)RandomValue(0, (Real)((int)rays.size() - 1)); 
     1129 
     1130        const Vector3 minPt = rays[candidateIdx].ExtrapOrigin(); 
     1131        const Vector3 maxPt = rays[candidateIdx].ExtrapTermination(); 
     1132 
     1133        const Vector3 pt = (maxPt + minPt) * 0.5; 
     1134        const Vector3 normal = Normalize(rays[candidateIdx].mRay->GetDir()); 
     1135 
     1136        return Plane3(normal, pt); 
     1137} 
     1138 
     1139 
     1140Plane3 VspBspTree::ChooseCandidatePlane2(const RayInfoContainer &rays) const 
     1141{ 
     1142        Vector3 pt[3]; 
     1143 
     1144        int idx[3]; 
     1145        int cmaxT = 0; 
     1146        int cminT = 0; 
     1147        bool chooseMin = false; 
     1148 
     1149        for (int j = 0; j < 3; ++ j) 
     1150        { 
     1151                idx[j] = (int)RandomValue(0, (Real)((int)rays.size() * 2 - 1)); 
     1152 
     1153                if (idx[j] >= (int)rays.size()) 
     1154                { 
     1155                        idx[j] -= (int)rays.size(); 
     1156 
     1157                        chooseMin = (cminT < 2); 
     1158                } 
     1159                else 
     1160                        chooseMin = (cmaxT < 2); 
     1161 
     1162                RayInfo rayInf = rays[idx[j]]; 
     1163                pt[j] = chooseMin ? rayInf.ExtrapOrigin() : rayInf.ExtrapTermination(); 
     1164        } 
     1165 
     1166        return Plane3(pt[0], pt[1], pt[2]); 
     1167} 
     1168 
     1169 
     1170Plane3 VspBspTree::ChooseCandidatePlane3(const RayInfoContainer &rays) const 
     1171{ 
     1172        Vector3 pt[3]; 
     1173 
     1174        int idx1 = (int)RandomValue(0, (Real)((int)rays.size() - 1)); 
     1175        int idx2 = (int)RandomValue(0, (Real)((int)rays.size() - 1)); 
     1176 
     1177        // check if rays different 
     1178        if (idx1 == idx2) 
     1179                idx2 = (idx2 + 1) % (int)rays.size(); 
     1180 
     1181        const RayInfo ray1 = rays[idx1]; 
     1182        const RayInfo ray2 = rays[idx2]; 
     1183 
     1184        // normal vector of the plane parallel to both lines 
     1185        const Vector3 norm = Normalize(CrossProd(ray1.mRay->GetDir(), ray2.mRay->GetDir())); 
     1186 
     1187        // vector from line 1 to line 2 
     1188        const Vector3 vd = ray2.ExtrapOrigin() - ray1.ExtrapOrigin(); 
     1189 
     1190        // project vector on normal to get distance 
     1191        const float dist = DotProd(vd, norm); 
     1192 
     1193        // point on plane lies halfway between the two planes 
     1194        const Vector3 planePt = ray1.ExtrapOrigin() + norm * dist * 0.5; 
     1195 
     1196        return Plane3(norm, planePt); 
     1197} 
     1198 
     1199 
     1200inline void VspBspTree::GenerateUniqueIdsForPvs() 
     1201{ 
     1202        Intersectable::NewMail(); sBackId = Intersectable::sMailId; 
     1203        Intersectable::NewMail(); sFrontId = Intersectable::sMailId; 
     1204        Intersectable::NewMail(); sFrontAndBackId = Intersectable::sMailId; 
     1205} 
     1206 
     1207 
     1208float VspBspTree::EvalSplitPlaneCost(const Plane3 &candidatePlane, 
     1209                                                                         const VspBspTraversalData &data, 
     1210                                                                         BspNodeGeometry &geomFront, 
     1211                                                                         BspNodeGeometry &geomBack, 
     1212                                                                         float &pFront, 
     1213                                                                         float &pBack) const 
     1214{ 
     1215        float cost = 0; 
     1216 
     1217        float sumBalancedRays = 0; 
     1218        float sumRaySplits = 0; 
     1219 
     1220        int pvsFront = 0; 
     1221        int pvsBack = 0; 
     1222 
     1223        // probability that view point lies in back / front node 
     1224        float pOverall = 0; 
     1225        pFront = 0; 
     1226        pBack = 0; 
     1227 
     1228        int raysFront = 0; 
     1229        int raysBack = 0; 
     1230        int totalPvs = 0; 
     1231 
     1232        int limit; 
     1233        bool useRand; 
     1234 
     1235        // choose test rays randomly if too much 
     1236        if ((int)data.mRays->size() > mMaxTests) 
     1237        { 
     1238                useRand = true; 
     1239                limit = mMaxTests; 
     1240        } 
     1241        else 
     1242        { 
     1243                useRand = false; 
     1244                limit = (int)data.mRays->size(); 
     1245        } 
     1246         
     1247        for (int i = 0; i < limit; ++ i) 
     1248        { 
     1249                const int testIdx = useRand ?  
     1250                        (int)RandomValue(0, (Real)((int)data.mRays->size() - 1)) : i; 
     1251                RayInfo rayInf = (*data.mRays)[testIdx]; 
     1252 
     1253                float t; 
     1254                VssRay *ray = rayInf.mRay; 
     1255                const int cf = rayInf.ComputeRayIntersection(candidatePlane, t); 
     1256 
     1257        if (0) 
     1258                { 
     1259                        if (cf >= 0) 
     1260                                ++ raysFront; 
     1261                        if (cf <= 0) 
     1262                                ++ raysBack; 
     1263                } 
     1264 
     1265                if (mSplitPlaneStrategy & LEAST_RAY_SPLITS) 
     1266                { 
     1267                        sumBalancedRays += cf; 
     1268                } 
     1269 
     1270                if (mSplitPlaneStrategy & BALANCED_RAYS) 
     1271                { 
     1272                        if (cf == 0) 
     1273                                ++ sumRaySplits; 
     1274                } 
     1275 
     1276                if (mSplitPlaneStrategy & PVS) 
     1277                { 
     1278                        // find front and back pvs for origing and termination object 
     1279                        AddObjToPvs(ray->mTerminationObject, cf, pvsFront, pvsBack, totalPvs); 
     1280                        AddObjToPvs(ray->mOriginObject, cf, pvsFront, pvsBack, totalPvs); 
     1281                } 
     1282        } 
     1283 
     1284        const float raysSize = (float)data.mRays->size() + Limits::Small; 
     1285 
     1286        if (mSplitPlaneStrategy & PVS) 
     1287        { 
     1288                // create unique ids for pvs heuristics 
     1289                GenerateUniqueIdsForPvs(); 
     1290 
     1291                // construct child geometry with regard to the candidate split plane 
     1292                data.mGeometry->SplitGeometry(geomFront, 
     1293                                                                          geomBack, 
     1294                                                                          candidatePlane, 
     1295                                                                          mBox, 
     1296                                                                          mEpsilon); 
     1297 
     1298                pOverall = data.mProbability; 
     1299 
     1300                if (!mUseAreaForPvs) // use front and back cell areas to approximate volume 
     1301                { 
     1302                        pFront = geomFront.GetVolume(); 
     1303                        pBack = pOverall - geomFront.GetVolume(); 
     1304                } 
     1305                else 
     1306                { 
     1307                        pFront = geomFront.GetArea(); 
     1308                        pBack = geomBack.GetArea(); 
     1309                } 
     1310        } 
     1311 
     1312 
     1313        if (mSplitPlaneStrategy & LEAST_RAY_SPLITS) 
     1314                cost += mLeastRaySplitsFactor * sumRaySplits / raysSize; 
     1315 
     1316        if (mSplitPlaneStrategy & BALANCED_RAYS) 
     1317                cost += mBalancedRaysFactor * fabs(sumBalancedRays) / raysSize; 
     1318 
     1319        // -- pvs rendering heuristics 
     1320        if (mSplitPlaneStrategy & PVS) 
     1321        { 
     1322                const int lowerPvsLimit = mViewCellsManager->GetMinPvsSize(); 
     1323                const int upperPvsLimit = mViewCellsManager->GetMaxPvsSize(); 
     1324 
     1325                // only render cost heuristics or combined with standard deviation 
     1326                if (1) 
     1327                { 
     1328                        const float penaltyOld = EvalPvsPenalty(totalPvs, lowerPvsLimit, upperPvsLimit); 
     1329                const float penaltyFront = EvalPvsPenalty(pvsFront, lowerPvsLimit, upperPvsLimit); 
     1330                        const float penaltyBack = EvalPvsPenalty(pvsBack, lowerPvsLimit, upperPvsLimit); 
     1331                         
     1332                        const float oldRenderCost = pOverall * (float)penaltyOld + Limits::Small; 
     1333                        const float newRenderCost = penaltyFront * pFront + penaltyBack * pBack; 
     1334 
     1335                        float oldCost, newCost; 
     1336 
     1337                        if (1) 
     1338                        { 
     1339                                oldCost = oldRenderCost; 
     1340                                newCost = newRenderCost; 
     1341                        } 
     1342                        else 
     1343                        { 
     1344                                // standard deviation is difference of back and front pvs 
     1345                                const float expectedCost = 0.5f * (penaltyFront + penaltyBack); 
     1346 
     1347                                const float newDeviation = 0.5f *  
     1348                                        fabs(penaltyFront - expectedCost) + fabs(penaltyBack - expectedCost); 
     1349 
     1350                const float oldDeviation = penaltyOld + Limits::Small; 
     1351 
     1352                                newCost = mRenderCostWeight * newRenderCost + (1.0f - mRenderCostWeight) * newDeviation; 
     1353                                oldCost = mRenderCostWeight * oldRenderCost + (1.0f - mRenderCostWeight) * oldDeviation; 
     1354                        } 
     1355 
     1356                        cost += mPvsFactor * newCost / oldCost; 
     1357                } 
     1358                else 
     1359                { 
     1360                        //-- compute weighted sum of expected render cost and standard deviation 
     1361                         
     1362                        //-- first compute expected render cost          
     1363                        const float penaltyOld = EvalPvsPenalty(totalPvs, lowerPvsLimit, upperPvsLimit); 
     1364                const float penaltyFront = EvalPvsPenalty(pvsFront, lowerPvsLimit, upperPvsLimit); 
     1365                        const float penaltyBack = EvalPvsPenalty(pvsBack, lowerPvsLimit, upperPvsLimit); 
     1366                         
     1367                        const float renderCostFront = penaltyFront * pFront; 
     1368                        const float renderCostBack = penaltyBack * pBack; 
     1369 
     1370                        const float oldRenderCost = pOverall * (float)penaltyOld + Limits::Small; 
     1371                        const float newRenderCost = renderCostFront + renderCostBack; 
     1372 
     1373 
     1374                        //-- compute standard deviation 
     1375                        const float expectedCost = 0.5f * (renderCostBack + renderCostFront); 
     1376 
     1377                        const float devFront = fabs(renderCostFront - expectedCost); 
     1378                         
     1379                        const float devBack = fabs(renderCostBack - expectedCost); 
     1380 
     1381                        const float newDev = 0.5f * (devFront + devBack); 
     1382                        const float oldDev = oldRenderCost * oldRenderCost; 
     1383 
     1384                        const float newCost = newRenderCost * mRenderCostWeight + newDev * (1.0f - mRenderCostWeight); 
     1385                        const float oldCost = oldRenderCost * mRenderCostWeight + oldDev * (1.0f - mRenderCostWeight); 
     1386 
     1387                        cost += mPvsFactor * newCost / oldCost; 
     1388 
     1389                        // also try to equalize render differences between front and back pvs 
     1390                        //const float oldCost = pOverall + Limits::Small; 
     1391                        //float newCost = (float)abs(pvsFront - pvsBack); 
     1392                         
     1393                } 
     1394        } 
     1395 
     1396#ifdef _DEBUG 
     1397        Debug << "totalpvs: " << data.mPvs << " ptotal: " << pOverall 
     1398                  << " frontpvs: " << pvsFront << " pFront: " << pFront 
     1399                  << " backpvs: " << pvsBack << " pBack: " << pBack << endl << endl; 
     1400#endif 
     1401 
     1402        // normalize cost by sum of linear factors 
     1403        if(0) 
     1404                return cost / (float)mCostNormalizer; 
     1405        else 
     1406                return cost; 
     1407} 
     1408 
     1409 
    10371410float VspBspTree::EvalAxisAlignedSplitCost(const VspBspTraversalData &data, 
    10381411                                                                                   const AxisAlignedBox3 &box, 
     
    11101483 
    11111484        return  (mCtDivCi + newCost) / oldCost; 
    1112 } 
    1113  
    1114  
    1115  
    1116 bool VspBspTree::SelectPlane(Plane3 &bestPlane, 
    1117                                                          BspLeaf *leaf, 
    1118                                                          VspBspTraversalData &data, 
    1119                                                          VspBspTraversalData &frontData, 
    1120                                                          VspBspTraversalData &backData) 
    1121 { 
    1122         // simplest strategy: just take next polygon 
    1123         if (mSplitPlaneStrategy & RANDOM_POLYGON) 
    1124         { 
    1125         if (!data.mPolygons->empty()) 
    1126                 { 
    1127                         const int randIdx =  
    1128                                 (int)RandomValue(0, (Real)((int)data.mPolygons->size() - 1)); 
    1129                         Polygon3 *nextPoly = (*data.mPolygons)[randIdx]; 
    1130  
    1131                         bestPlane = nextPoly->GetSupportingPlane(); 
    1132                         return true; 
    1133                 } 
    1134         } 
    1135  
    1136         //-- use heuristics to find appropriate plane 
    1137  
    1138         // intermediate plane 
    1139         Plane3 plane; 
    1140         float lowestCost = MAX_FLOAT; 
    1141          
    1142         // decides if the first few splits should be only axisAligned 
    1143         const bool onlyAxisAligned  =  
    1144                 (mSplitPlaneStrategy & AXIS_ALIGNED) && 
    1145                 ((int)data.mRays->size() > mTermMinRaysForAxisAligned) && 
    1146                 ((int)data.GetAvgRayContribution() < mTermMaxRayContriForAxisAligned); 
    1147          
    1148         const int limit = onlyAxisAligned ? 0 :  
    1149                 Min((int)data.mPolygons->size(), mMaxPolyCandidates); 
    1150  
    1151         float candidateCost; 
    1152  
    1153         int maxIdx = (int)data.mPolygons->size(); 
    1154  
    1155         for (int i = 0; i < limit; ++ i) 
    1156         { 
    1157                 // the already taken candidates are stored behind maxIdx 
    1158                 // => assure that no index is taken twice 
    1159                 const int candidateIdx = (int)RandomValue(0, (Real)(-- maxIdx)); 
    1160                 Polygon3 *poly = (*data.mPolygons)[candidateIdx]; 
    1161  
    1162                 // swap candidate to the end to avoid testing same plane 
    1163                 std::swap((*data.mPolygons)[maxIdx], (*data.mPolygons)[candidateIdx]); 
    1164                 //Polygon3 *poly = (*data.mPolygons)[(int)RandomValue(0, (int)polys.size() - 1)]; 
    1165  
    1166                 // evaluate current candidate 
    1167                 BspNodeGeometry fGeom, bGeom; 
    1168                 float fArea, bArea; 
    1169                 plane = poly->GetSupportingPlane(); 
    1170                 candidateCost = EvalSplitPlaneCost(plane, data, fGeom, bGeom, fArea, bArea); 
    1171                  
    1172                 if (candidateCost < lowestCost) 
    1173                 { 
    1174                         bestPlane = plane; 
    1175                         lowestCost = candidateCost; 
    1176                 } 
    1177         } 
    1178  
    1179         //-- evaluate axis aligned splits 
    1180         int axis; 
    1181         BspNodeGeometry *fGeom, *bGeom; 
    1182         float pFront, pBack; 
    1183  
    1184         candidateCost = SelectAxisAlignedPlane(plane, data, axis, 
    1185                                                                                    &fGeom, &bGeom,  
    1186                                                                                    pFront, pBack, 
    1187                                                                                    data.mIsKdNode);       
    1188  
    1189         bool isAxisAlignedSplit = false; 
    1190  
    1191         if (candidateCost < lowestCost) 
    1192         {        
    1193                 bestPlane = plane; 
    1194                 lowestCost = candidateCost; 
    1195  
    1196                 // assign already computed values 
    1197                 // we can do this because we always save the 
    1198                 // computed values from the axis aligned splits          
    1199                 frontData.mGeometry = fGeom; 
    1200                 backData.mGeometry = bGeom; 
    1201          
    1202                 frontData.mProbability = pFront; 
    1203                 backData.mProbability = pBack; 
    1204                  
    1205                 //! error also computed if cost ratio is missed 
    1206                 ++ mBspStats.splits[axis]; 
    1207                 isAxisAlignedSplit = true; 
    1208         } 
    1209         else 
    1210         { 
    1211                 DEL_PTR(fGeom); 
    1212                 DEL_PTR(bGeom); 
    1213         } 
    1214  
    1215         frontData.mIsKdNode = backData.mIsKdNode = (data.mIsKdNode && isAxisAlignedSplit); 
    1216  
    1217 #ifdef _DEBUG 
    1218         Debug << "plane lowest cost: " << lowestCost << endl; 
    1219 #endif 
    1220  
    1221         // cost ratio miss 
    1222         if (lowestCost > mTermMaxCostRatio) 
    1223                 return false; 
    1224  
    1225         return true; 
    1226 } 
    1227  
    1228  
    1229 Plane3 VspBspTree::ChooseCandidatePlane(const RayInfoContainer &rays) const 
    1230 { 
    1231         const int candidateIdx = (int)RandomValue(0, (Real)((int)rays.size() - 1)); 
    1232  
    1233         const Vector3 minPt = rays[candidateIdx].ExtrapOrigin(); 
    1234         const Vector3 maxPt = rays[candidateIdx].ExtrapTermination(); 
    1235  
    1236         const Vector3 pt = (maxPt + minPt) * 0.5; 
    1237         const Vector3 normal = Normalize(rays[candidateIdx].mRay->GetDir()); 
    1238  
    1239         return Plane3(normal, pt); 
    1240 } 
    1241  
    1242  
    1243 Plane3 VspBspTree::ChooseCandidatePlane2(const RayInfoContainer &rays) const 
    1244 { 
    1245         Vector3 pt[3]; 
    1246  
    1247         int idx[3]; 
    1248         int cmaxT = 0; 
    1249         int cminT = 0; 
    1250         bool chooseMin = false; 
    1251  
    1252         for (int j = 0; j < 3; ++ j) 
    1253         { 
    1254                 idx[j] = (int)RandomValue(0, (Real)((int)rays.size() * 2 - 1)); 
    1255  
    1256                 if (idx[j] >= (int)rays.size()) 
    1257                 { 
    1258                         idx[j] -= (int)rays.size(); 
    1259  
    1260                         chooseMin = (cminT < 2); 
    1261                 } 
    1262                 else 
    1263                         chooseMin = (cmaxT < 2); 
    1264  
    1265                 RayInfo rayInf = rays[idx[j]]; 
    1266                 pt[j] = chooseMin ? rayInf.ExtrapOrigin() : rayInf.ExtrapTermination(); 
    1267         } 
    1268  
    1269         return Plane3(pt[0], pt[1], pt[2]); 
    1270 } 
    1271  
    1272 Plane3 VspBspTree::ChooseCandidatePlane3(const RayInfoContainer &rays) const 
    1273 { 
    1274         Vector3 pt[3]; 
    1275  
    1276         int idx1 = (int)RandomValue(0, (Real)((int)rays.size() - 1)); 
    1277         int idx2 = (int)RandomValue(0, (Real)((int)rays.size() - 1)); 
    1278  
    1279         // check if rays different 
    1280         if (idx1 == idx2) 
    1281                 idx2 = (idx2 + 1) % (int)rays.size(); 
    1282  
    1283         const RayInfo ray1 = rays[idx1]; 
    1284         const RayInfo ray2 = rays[idx2]; 
    1285  
    1286         // normal vector of the plane parallel to both lines 
    1287         const Vector3 norm = Normalize(CrossProd(ray1.mRay->GetDir(), ray2.mRay->GetDir())); 
    1288  
    1289         // vector from line 1 to line 2 
    1290         const Vector3 vd = ray2.ExtrapOrigin() - ray1.ExtrapOrigin(); 
    1291  
    1292         // project vector on normal to get distance 
    1293         const float dist = DotProd(vd, norm); 
    1294  
    1295         // point on plane lies halfway between the two planes 
    1296         const Vector3 planePt = ray1.ExtrapOrigin() + norm * dist * 0.5; 
    1297  
    1298         return Plane3(norm, planePt); 
    1299 } 
    1300  
    1301  
    1302 inline void VspBspTree::GenerateUniqueIdsForPvs() 
    1303 { 
    1304         Intersectable::NewMail(); sBackId = ViewCell::sMailId; 
    1305         Intersectable::NewMail(); sFrontId = ViewCell::sMailId; 
    1306         Intersectable::NewMail(); sFrontAndBackId = ViewCell::sMailId; 
    1307 } 
    1308  
    1309  
    1310 float VspBspTree::EvalSplitPlaneCost(const Plane3 &candidatePlane, 
    1311                                                                          const VspBspTraversalData &data, 
    1312                                                                          BspNodeGeometry &geomFront, 
    1313                                                                          BspNodeGeometry &geomBack, 
    1314                                                                          float &pFront, 
    1315                                                                          float &pBack) const 
    1316 { 
    1317         float cost = 0; 
    1318  
    1319         float sumBalancedRays = 0; 
    1320         float sumRaySplits = 0; 
    1321  
    1322         int pvsFront = 0; 
    1323         int pvsBack = 0; 
    1324  
    1325         // probability that view point lies in back / front node 
    1326         float pOverall = 0; 
    1327         pFront = 0; 
    1328         pBack = 0; 
    1329  
    1330         int raysFront = 0; 
    1331         int raysBack = 0; 
    1332         int totalPvs = 0; 
    1333  
    1334         int limit; 
    1335         bool useRand; 
    1336  
    1337         // choose test rays randomly if too much 
    1338         if ((int)data.mRays->size() > mMaxTests) 
    1339         { 
    1340                 useRand = true; 
    1341                 limit = mMaxTests; 
    1342         } 
    1343         else 
    1344         { 
    1345                 useRand = false; 
    1346                 limit = (int)data.mRays->size(); 
    1347         } 
    1348          
    1349         for (int i = 0; i < limit; ++ i) 
    1350         { 
    1351                 const int testIdx = useRand ?  
    1352                         (int)RandomValue(0, (Real)((int)data.mRays->size() - 1)) : i; 
    1353                 RayInfo rayInf = (*data.mRays)[testIdx]; 
    1354  
    1355                 float t; 
    1356                 VssRay *ray = rayInf.mRay; 
    1357                 const int cf = rayInf.ComputeRayIntersection(candidatePlane, t); 
    1358  
    1359         if (0) 
    1360                 { 
    1361                         if (cf >= 0) 
    1362                                 ++ raysFront; 
    1363                         if (cf <= 0) 
    1364                                 ++ raysBack; 
    1365                 } 
    1366  
    1367                 if (mSplitPlaneStrategy & LEAST_RAY_SPLITS) 
    1368                 { 
    1369                         sumBalancedRays += cf; 
    1370                 } 
    1371  
    1372                 if (mSplitPlaneStrategy & BALANCED_RAYS) 
    1373                 { 
    1374                         if (cf == 0) 
    1375                                 ++ sumRaySplits; 
    1376                 } 
    1377  
    1378                 if (mSplitPlaneStrategy & PVS) 
    1379                 { 
    1380                         // find front and back pvs for origing and termination object 
    1381                         AddObjToPvs(ray->mTerminationObject, cf, pvsFront, pvsBack, totalPvs); 
    1382                         AddObjToPvs(ray->mOriginObject, cf, pvsFront, pvsBack, totalPvs); 
    1383                 } 
    1384         } 
    1385  
    1386         const float raysSize = (float)data.mRays->size() + Limits::Small; 
    1387  
    1388         if (mSplitPlaneStrategy & PVS) 
    1389         { 
    1390                 // create unique ids for pvs heuristics 
    1391                 GenerateUniqueIdsForPvs(); 
    1392  
    1393                 // construct child geometry with regard to the candidate split plane 
    1394                 data.mGeometry->SplitGeometry(geomFront, 
    1395                                                                           geomBack, 
    1396                                                                           candidatePlane, 
    1397                                                                           mBox, 
    1398                                                                           mEpsilon); 
    1399  
    1400                 pOverall = data.mProbability; 
    1401  
    1402                 if (!mUseAreaForPvs) // use front and back cell areas to approximate volume 
    1403                 { 
    1404                         pFront = geomFront.GetVolume(); 
    1405                         pBack = pOverall - geomFront.GetVolume(); 
    1406                 } 
    1407                 else 
    1408                 { 
    1409                         pFront = geomFront.GetArea(); 
    1410                         pBack = geomBack.GetArea(); 
    1411                 } 
    1412         } 
    1413  
    1414  
    1415         if (mSplitPlaneStrategy & LEAST_RAY_SPLITS) 
    1416                 cost += mLeastRaySplitsFactor * sumRaySplits / raysSize; 
    1417  
    1418         if (mSplitPlaneStrategy & BALANCED_RAYS) 
    1419                 cost += mBalancedRaysFactor * fabs(sumBalancedRays) / raysSize; 
    1420  
    1421         // pvs criterium 
    1422         if (mSplitPlaneStrategy & PVS) 
    1423         { 
    1424                 if (1) 
    1425                 { 
    1426                         const int lowerPvsLimit = mViewCellsManager->GetMinPvsSize(); 
    1427                         const int upperPvsLimit = mViewCellsManager->GetMaxPvsSize(); 
    1428                          
    1429                         const float penaltyOld = EvalPvsPenalty(totalPvs, lowerPvsLimit, upperPvsLimit); 
    1430              
    1431                         const float penaltyFront = EvalPvsPenalty(pvsFront, lowerPvsLimit, upperPvsLimit); 
    1432                         const float penaltyBack = EvalPvsPenalty(pvsBack, lowerPvsLimit, upperPvsLimit); 
    1433                          
    1434                         const float oldCost = pOverall * (float)penaltyOld + Limits::Small; 
    1435                         cost += mPvsFactor * (penaltyFront * pFront + penaltyBack * pBack) / oldCost; 
    1436  
    1437                 } 
    1438                 else 
    1439                 { 
    1440                         // try to equalize render differences 
    1441                         //const float oldCost = pOverall * (float)totalPvs + Limits::Small; 
    1442                         //float newCost = fabs(pvsFront * pFront - pvsBack * pBack); 
    1443                         const float oldCost = pOverall + Limits::Small; 
    1444                         float newCost = (float)abs(pvsFront - pvsBack); 
    1445  
    1446                         cost += mPvsFactor * newCost / oldCost; 
    1447                 } 
    1448         } 
    1449  
    1450 #ifdef _DEBUG 
    1451         Debug << "totalpvs: " << data.mPvs << " ptotal: " << pOverall 
    1452                   << " frontpvs: " << pvsFront << " pFront: " << pFront 
    1453                   << " backpvs: " << pvsBack << " pBack: " << pBack << endl << endl; 
    1454 #endif 
    1455  
    1456         // normalize cost by sum of linear factors 
    1457         if(0) 
    1458                 return cost / (float)mCostNormalizer; 
    1459         else 
    1460                 return cost; 
    14611485} 
    14621486 
     
    17311755                        { 
    17321756                                BspViewCell *viewCell = dynamic_cast<BspLeaf *>(node)->GetViewCell(); 
    1733                          
    1734                                 vector<BspLeaf *>::const_iterator it, it_end = viewCell->mLeaves.end(); 
    1735                                 for (it = viewCell->mLeaves.begin();it != it_end; ++ it) 
     1757         
     1758                                ViewCellContainer leaves; 
     1759                                mViewCellsManager->GetViewCellsTree()->CollectLeaves(viewCell, leaves); 
     1760 
     1761                                ViewCellContainer::const_iterator it, it_end = leaves.end(); 
     1762 
     1763                                for (it = leaves.begin(); it != it_end; ++ it) 
    17361764                                { 
    1737                                         BspLeaf *l = *it; 
     1765                                        BspLeaf *l = dynamic_cast<BspViewCell *>(*it)->mLeaf; 
    17381766                                        l->SetViewCell(GetOrCreateOutOfBoundsCell()); 
    17391767                                        ++ mBspStats.invalidLeaves; 
     
    20242052                                                                   BspNodeGeometry &vcGeom) const 
    20252053{ 
    2026         vector<BspLeaf *> leaves = vc->mLeaves; 
    2027         vector<BspLeaf *>::const_iterator it, it_end = leaves.end(); 
     2054        ViewCellContainer leaves; 
     2055        mViewCellsManager->GetViewCellsTree()->CollectLeaves(vc, leaves); 
     2056 
     2057        ViewCellContainer::const_iterator it, it_end = leaves.end(); 
    20282058 
    20292059        for (it = leaves.begin(); it != it_end; ++ it) 
    2030                 ConstructGeometry(*it, vcGeom); 
     2060        { 
     2061                BspLeaf *l = dynamic_cast<BspViewCell *>(*it)->mLeaf; 
     2062                ConstructGeometry(l, vcGeom); 
     2063        } 
    20312064} 
    20322065 
     
    24562489} 
    24572490 
     2491 
    24582492BspNode *VspBspTree::CollapseTree(BspNode *node, int &collapsed) 
    24592493{ 
     
    24992533{ 
    25002534        int collapsed = 0; 
    2501          
     2535        //TODO 
     2536#if VC_HISTORY 
    25022537        (void)CollapseTree(mRoot, collapsed); 
    25032538 
    25042539        // revalidate leaves 
    25052540        RepairViewCellsLeafLists(); 
    2506  
     2541#endif 
    25072542        return collapsed; 
    25082543} 
     
    25272562 
    25282563                        BspViewCell *viewCell = leaf->GetViewCell(); 
    2529  
     2564        // TODO 
     2565#if VC_HISTORY 
    25302566                        if (!viewCell->Mailed()) 
    25312567                        { 
     
    25332569                                viewCell->Mail(); 
    25342570                        } 
    2535  
     2571         
    25362572                        viewCell->mLeaves.push_back(leaf); 
     2573// TODO 
     2574#endif 
    25372575                } 
    25382576                else 
     
    26312669 
    26322670 
    2633 bool VspBspTree::MergeViewCells(BspLeaf *l1, BspLeaf *l2) //const 
    2634 { 
    2635         //-- change pointer to view cells of all leaves associated 
    2636         //-- with the previous view cells 
    2637         BspViewCell *fVc = l1->GetViewCell(); 
    2638         BspViewCell *bVc = l2->GetViewCell(); 
    2639  
    2640         BspViewCell *vc = dynamic_cast<BspViewCell *>( 
    2641                 mViewCellsManager->MergeViewCells(*fVc, *bVc)); 
    2642  
    2643         // if merge was unsuccessful 
    2644         if (!vc) return false; 
    2645  
    2646         // set new size of view cell 
    2647         if (mUseAreaForPvs) 
    2648                 vc->SetArea(fVc->GetArea() + bVc->GetArea()); 
    2649         else 
    2650                 vc->SetVolume(fVc->GetVolume() + bVc->GetVolume()); 
    2651          
    2652         vector<BspLeaf *> fLeaves = fVc->mLeaves; 
    2653         vector<BspLeaf *> bLeaves = bVc->mLeaves; 
    2654  
    2655         vector<BspLeaf *>::const_iterator it; 
    2656  
    2657         //-- change view cells of all the other leaves the view cell belongs to 
    2658         for (it = fLeaves.begin(); it != fLeaves.end(); ++ it) 
    2659         { 
    2660                 (*it)->SetViewCell(vc); 
    2661                 vc->mLeaves.push_back(*it); 
    2662         } 
    2663  
    2664         for (it = bLeaves.begin(); it != bLeaves.end(); ++ it) 
    2665         { 
    2666                 (*it)->SetViewCell(vc); 
    2667                 vc->mLeaves.push_back(*it); 
    2668         } 
    2669  
    2670         // important so other merge candidates sharing this view cell 
    2671         // are notified that the merge cost must be updated!! 
    2672         vc->Mail(); 
    2673  
    2674         //-- clean up old view cells 
    2675         if (mExportMergedViewCells) 
    2676         { 
    2677                 DEL_PTR(fVc); 
    2678                 DEL_PTR(bVc); 
    2679         } 
    2680         else  
    2681         { 
    2682                 // old view cells container needed for visualization 
    2683                 //fVc->mMailbox = -1; 
    2684                 //bVc->mMailbox = -1; 
    2685                 fVc->SetId(-2); 
    2686                 bVc->SetId(-2); 
    2687  
    2688                 mOldViewCells.push_back(fVc); 
    2689                 mOldViewCells.push_back(bVc); 
    2690                  
    2691                 mNewViewCells.push_back(vc); 
    2692         } 
    2693  
    2694         return true; 
    2695 } 
    2696  
    2697  
    26982671void VspBspTree::SetViewCellsManager(ViewCellsManager *vcm) 
    26992672{ 
     
    27022675 
    27032676 
    2704 int VspBspTree::CollectMergeCandidates(const vector<BspLeaf *> leaves) 
     2677int VspBspTree::CollectMergeCandidates(const vector<BspLeaf *> leaves, 
     2678                                                                           vector<MergeCandidate> &candidates) 
    27052679{ 
    27062680        BspLeaf::NewMail(); 
     
    27082682        vector<BspLeaf *>::const_iterator it, it_end = leaves.end(); 
    27092683 
    2710         int candidates = 0; 
     2684        int numCandidates = 0; 
    27112685 
    27122686        // find merge candidates and push them into queue 
     
    27142688        { 
    27152689                BspLeaf *leaf = *it; 
    2716                  
    2717                 /// create leaf pvs (needed for post processing) 
    2718                 leaf->mPvs = new ObjectPvs(leaf->GetViewCell()->GetPvs()); 
    2719  
    2720                 //const float rc = leaf->mProbability * (float)leaf->mPvs->GetSize(); 
    2721                 //BspMergeCandidate::sOverallCost += rc; 
    27222690                 
    27232691                // the same leaves must not be part of two merge candidates 
     
    27332701                        if ((*nit)->GetViewCell() != leaf->GetViewCell()) 
    27342702                        { 
    2735                                 BspMergeCandidate mc(leaf, *nit); 
    2736                                 mc.EvalMergeCost(); 
    2737  
    2738                                 mMergeQueue.push(mc); 
    2739                                 ++ candidates; 
    2740                                 if ((candidates % 1000) == 0) 
     2703                                MergeCandidate mc(leaf->GetViewCell(), (*nit)->GetViewCell()); 
     2704                                candidates.push_back(mc); 
     2705 
     2706                                ++ numCandidates; 
     2707                                if ((numCandidates % 1000) == 0) 
    27412708                                { 
    2742                                         cout << "collected " << candidates << " merge candidates" << endl; 
     2709                                        cout << "collected " << numCandidates << " merge candidates" << endl; 
    27432710                                } 
    27442711                        } 
     
    27462713        } 
    27472714 
    2748         Debug << "mergequeue: " << (int)mMergeQueue.size() << endl; 
    2749         Debug << "leaves in queue: " << candidates << endl; 
    2750         Debug << "overall cost: " << BspMergeCandidate::sOverallCost << endl; 
    2751  
     2715        Debug << "merge queue: " << (int)candidates.size() << endl; 
     2716        Debug << "leaves in queue: " << numCandidates << endl; 
     2717         
    27522718 
    27532719        return (int)leaves.size(); 
     
    27552721 
    27562722 
    2757 int VspBspTree::CollectMergeCandidates(const VssRayContainer &rays) 
     2723int VspBspTree::CollectMergeCandidates(const VssRayContainer &rays,  
     2724                                                                           vector<MergeCandidate> &candidates) 
    27582725{ 
    27592726        ViewCell::NewMail(); 
     
    27752742                if (ray->mViewCells.size() < 2) 
    27762743                        continue; 
    2777            
     2744//TODO viewcellhierarchy 
    27782745                iit = ray->mViewCells.begin(); 
    27792746                BspViewCell *bspVc = dynamic_cast<BspViewCell *>(*(iit ++)); 
    2780                 BspLeaf *leaf = bspVc->mLeaves[0]; 
    2781                  
    2782                 // create leaf pvs (needed for post processing) 
    2783                 if (!leaf->mPvs) 
    2784                 { 
    2785                         leaf->mPvs =  
    2786                                 new ObjectPvs(leaf->GetViewCell()->GetPvs()); 
    2787  
    2788                         //BspMergeCandidate::sOverallCost +=  
    2789                         //      leaf->mProbability * leaf->mPvs->GetSize(); 
    2790                          
    2791                         ++ numLeaves; 
    2792                 } 
     2747                BspLeaf *leaf = bspVc->mLeaf; 
    27932748                 
    27942749                // traverse intersections  
     
    27992754                        BspLeaf *prevLeaf = leaf; 
    28002755                        bspVc = dynamic_cast<BspViewCell *>(*iit); 
    2801             leaf = bspVc->mLeaves[0]; 
     2756            leaf = bspVc->mLeaf; 
    28022757 
    28032758                        // view space not valid or same view cell 
     
    28062761                                continue; 
    28072762 
    2808             // create leaf pvs (needed for post processing) 
    2809                         if (!leaf->mPvs) 
    2810                         { 
    2811                                 leaf->mPvs =  
    2812                                         new ObjectPvs(leaf->GetViewCell()->GetPvs()); 
    2813                                  
    2814                                 //BspMergeCandidate::sOverallCost +=  
    2815                                 //      leaf->mProbability * leaf->mPvs->GetSize(); 
    2816  
    2817                                 ++ numLeaves; 
    2818                         } 
    2819                  
    2820                         vector<BspLeaf *> &neighbors = neighborMap[leaf]; 
     2763                vector<BspLeaf *> &neighbors = neighborMap[leaf]; 
    28212764                         
    28222765                        bool found = false; 
     
    28432786                                prevLeaf->Mail(); 
    28442787                 
    2845                                 BspMergeCandidate mc(leaf, prevLeaf); 
    2846                                 mc.EvalMergeCost(); 
    2847  
    2848                                 mMergeQueue.push(mc); 
    2849  
    2850                                 if (((int)mMergeQueue.size() % 1000) == 0) 
     2788                                MergeCandidate mc(leaf->GetViewCell(), prevLeaf->GetViewCell()); 
     2789                                 
     2790                                candidates.push_back(mc); 
     2791 
     2792                                if (((int)candidates.size() % 1000) == 0) 
    28512793                                { 
    2852                                         cout << "collected " << (int)mMergeQueue.size() << " merge candidates" << endl; 
     2794                                        cout << "collected " << (int)candidates.size() << " merge candidates" << endl; 
    28532795                                } 
    28542796                        } 
     
    28572799 
    28582800        Debug << "neighbormap size: " << (int)neighborMap.size() << endl; 
    2859         Debug << "mergequeue: " << (int)mMergeQueue.size() << endl; 
     2801        Debug << "merge queue: " << (int)candidates.size() << endl; 
    28602802        Debug << "leaves in queue: " << numLeaves << endl; 
    2861         Debug << "overall cost: " << BspMergeCandidate::sOverallCost << endl; 
     2803 
    28622804 
    28632805        //-- collect the leaves which haven't been found by ray casting 
     
    28682810                CollectLeaves(leaves, true); 
    28692811                Debug << "found " << (int)leaves.size() << " new leaves" << endl << endl; 
    2870                 CollectMergeCandidates(leaves); 
     2812                CollectMergeCandidates(leaves, candidates); 
    28712813        } 
    28722814 
     
    28752817 
    28762818 
    2877 void VspBspTree::ConstructBspRays(vector<BspRay *> &bspRays, 
    2878                                                                   const VssRayContainer &rays) 
    2879 { 
    2880         VssRayContainer::const_iterator it, it_end = rays.end(); 
    2881  
    2882         for (it = rays.begin(); it != rays.end(); ++ it) 
    2883         { 
    2884                 VssRay *vssRay = *it; 
    2885                 BspRay *ray = new BspRay(vssRay); 
    2886  
    2887                 ViewCellContainer viewCells; 
    2888  
    2889                 Ray hray(*vssRay); 
    2890                 float tmin = 0, tmax = 1.0; 
    2891                 // matt TODO: remove this!! 
    2892                 //hray.Init(ray.GetOrigin(), ray.GetDir(), Ray::LINE_SEGMENT); 
    2893                 if (!mBox.GetRaySegment(hray, tmin, tmax) || (tmin > tmax)) 
    2894                         continue; 
    2895  
    2896                 Vector3 origin = hray.Extrap(tmin); 
    2897                 Vector3 termination = hray.Extrap(tmax); 
    2898          
    2899                 // cast line segment to get intersections with bsp leaves 
    2900                 CastLineSegment(origin, termination, viewCells); 
    2901  
    2902                 ViewCellContainer::const_iterator vit, vit_end = viewCells.end(); 
    2903                 for (vit = viewCells.begin(); vit != vit_end; ++ vit) 
    2904                 { 
    2905                         BspViewCell *vc = dynamic_cast<BspViewCell *>(*vit); 
    2906                         vector<BspLeaf *>::const_iterator it, it_end = vc->mLeaves.end(); 
    2907                         //NOTE: not sorted! 
    2908                         for (it = vc->mLeaves.begin(); it != it_end; ++ it) 
    2909                         { 
    2910                                 ray->intersections.push_back(BspIntersection(0, *it)); 
    2911                         } 
    2912                 } 
    2913  
    2914                 bspRays.push_back(ray); 
    2915         } 
    2916 } 
    2917  
    2918  
    2919 #if 1 
    2920 int VspBspTree::MergeViewCells(const VssRayContainer &rays, const ObjectContainer &objects) 
    2921 { 
    2922         BspMergeCandidate::sViewCellsManager = mViewCellsManager; 
    2923         BspMergeCandidate::sUseArea = mUseAreaForPvs; 
    2924  
    2925  
    2926         //-- compute statistics values of initial view cells 
    2927         mViewCellsManager->EvaluateRenderStatistics(BspMergeCandidate::sOverallCost,  
    2928                                                                                                 BspMergeCandidate::sExpectedCost, 
    2929                                                                                                 BspMergeCandidate::sVariance); 
    2930  
    2931  
    2932         //BspMergeCandidate::sExpectedCost =  
    2933         //      BspMergeCandidate::sOverallCost / BspMergeCandidate::sNumViewCells; 
    2934  
    2935  
    2936         ViewCellsManager::PvsStatistics pvsStats; 
    2937         mViewCellsManager->GetPvsStatistics(pvsStats); 
    2938  
    2939         static float expectedValue = pvsStats.avgPvs; 
    2940          
    2941         // the current view cells are kept in this container 
    2942         ViewCellContainer viewCells; 
    2943         if (mExportMergedViewCells) 
    2944         { 
    2945                 ViewCell::NewMail(); 
    2946                 CollectViewCells(mRoot, true, viewCells, true); 
    2947         } 
    2948  
    2949  
    2950         ViewCell::NewMail(); 
    2951  
    2952         MergeStatistics mergeStats; 
    2953         mergeStats.Start(); 
    2954          
    2955         long startTime = GetTime(); 
    2956  
    2957         cout << "collecting merge candidates ... " << endl; 
    2958          
    2959         if (mUseRaysForMerge) 
    2960         { 
    2961                 mergeStats.nodes = CollectMergeCandidates(rays); 
    2962         } 
    2963         else 
    2964         { 
    2965                 vector<BspLeaf *> leaves; 
    2966                 CollectLeaves(leaves); 
    2967                 mergeStats.nodes = CollectMergeCandidates(leaves); 
    2968         } 
    2969          
    2970         cout << "fininshed collecting candidates" << endl; 
    2971  
    2972         mergeStats.collectTime = TimeDiff(startTime, GetTime()); 
    2973         mergeStats.candidates = (int)mMergeQueue.size(); 
    2974         startTime = GetTime(); 
    2975  
    2976         // frequency stats are updated 
    2977         const int statsOut = 100; 
    2978  
    2979         // number of view cells withouth the invalid ones 
    2980         BspMergeCandidate::sNumViewCells = mBspStats.Leaves() - mBspStats.invalidLeaves; 
    2981  
    2982         // passes are needed for statistics, because we don't want to record 
    2983         // every merge 
    2984         const int maxMergesPerPass = 100; 
    2985         int pass = 0; 
    2986  
    2987         // maximal ratio of old expected render cost to expected render 
    2988         // when the the render queue has to be reset. 
    2989         const float ercMaxRatio = 0.7f; 
    2990          
    2991         cout << "actual merge starts now ... " << endl; 
    2992  
    2993          
    2994          
    2995         //-- use priority queue to merge leaf pairs 
    2996  
    2997  
    2998         while (!mMergeQueue.empty() &&  
    2999                    (BspMergeCandidate::sNumViewCells > mMergeMinViewCells) && 
    3000                    (mMergeQueue.top().GetMergeCost() < mMergeMaxCostRatio * BspMergeCandidate::sOverallCost)) 
    3001         { 
    3002  
    3003                 int mergedPerPass = 0; 
    3004                 const float oldExpectedCost = BspMergeCandidate::sExpectedCost; 
    3005                  
    3006 //#ifdef _DEBUG 
    3007                 Debug << "abs mergecost: " << mMergeQueue.top().GetMergeCost() << " rel mergecost: " 
    3008                           << mMergeQueue.top().GetMergeCost() / BspMergeCandidate::sOverallCost  
    3009                           << " max ratio: " << mMergeMaxCostRatio << endl 
    3010                           << " expected value: " << oldExpectedCost << endl; 
    3011 //#endif 
    3012  
    3013                 while (!mMergeQueue.empty() &&  
    3014                            (BspMergeCandidate::sNumViewCells > mMergeMinViewCells) && 
    3015                            (ercMaxRatio > oldExpectedCost / BspMergeCandidate::sExpectedCost) && 
    3016                            (mMergeQueue.top().GetMergeCost() < mMergeMaxCostRatio * BspMergeCandidate::sOverallCost) && 
    3017                            (maxMergesPerPass < mergedPerPass)); 
    3018                 { 
    3019                                 Debug << "erc max ratio" << ercMaxRatio << endl; 
    3020  
    3021                                 BspMergeCandidate mc = mMergeQueue.top(); 
    3022                                 mMergeQueue.pop(); 
    3023  
    3024                                 // both view cells equal! 
    3025                                 if (mc.GetLeaf1()->GetViewCell() == mc.GetLeaf2()->GetViewCell()) 
    3026                                         continue; 
    3027  
    3028                                 if (mc.Valid()) 
    3029                                 { 
    3030                                         ViewCell::NewMail(); 
    3031                                         const float currentMergeCost = mc.GetMergeCost(); 
    3032  
    3033                                         MergeViewCells(mc.GetLeaf1(), mc.GetLeaf2()); 
    3034                                          
    3035                                         -- BspMergeCandidate::sNumViewCells; 
    3036                                         ++ mergeStats.merged; 
    3037                                         ++ mergedPerPass; 
    3038  
    3039                                         // increase absolute merge cost 
    3040                                         BspMergeCandidate::sOverallCost += mc.GetRenderCost(); 
    3041                                         BspMergeCandidate::sVariance = mc.GetVarianceIncr(); 
    3042  
    3043                                         BspMergeCandidate::sExpectedCost =  
    3044                                                 BspMergeCandidate::sOverallCost / (float)BspMergeCandidate::sNumViewCells; 
    3045  
    3046                                         // stats 
    3047                                         if (mc.GetLeaf1()->IsSibling(mc.GetLeaf2())) 
    3048                                                 ++ mergeStats.siblings; 
    3049  
    3050                                         if (0) 
    3051                                         { 
    3052                                                 const int dist =  
    3053                                                         TreeDistance(mc.GetLeaf1(), mc.GetLeaf2()); 
    3054                                                 if (dist > mergeStats.maxTreeDist) 
    3055                                                         mergeStats.maxTreeDist = dist; 
    3056                                                 mergeStats.accTreeDist += dist; 
    3057                                         } 
    3058  
    3059                                         if ((mergeStats.merged % statsOut) == 0) 
    3060                                         { 
    3061                                                 cout << "merged " << mergeStats.merged << " view cells" << endl; 
    3062  
    3063                                                 mStats  
    3064                                                         << "#Pass\n" << pass << endl 
    3065                                                         << "#Merged\n" << mergeStats.merged << endl  
    3066                                                         << "#Viewcells\n" << BspMergeCandidate::sNumViewCells << endl  
    3067                                                         << "#OverallCost\n" << BspMergeCandidate::sOverallCost << endl 
    3068                                                         << "#CurrentCost\n" << currentMergeCost << endl 
    3069                                                         << "#RelativeCost\n" << currentMergeCost / BspMergeCandidate::sOverallCost << endl 
    3070                                                         << "#CurrentPvs\n" << mc.GetLeaf1()->GetViewCell()->GetPvs().GetSize() << endl 
    3071                                                         << "#MergedSiblings\n" << mergeStats.siblings << endl 
    3072                                                         << "#AvgTreeDist\n" << mergeStats.AvgTreeDist() << endl 
    3073                                                         << "#ExpectedCost\n" << BspMergeCandidate::sExpectedCost << endl 
    3074                                                         << "#RatioExpectedCost\n" << oldExpectedCost / BspMergeCandidate::sExpectedCost << endl 
    3075                                                         << "#variance\n" << BspMergeCandidate::sVariance << endl; 
    3076  
    3077                                                 if (mExportMergedViewCells) 
    3078                                                         ExportMergedViewCells(viewCells, objects, BspMergeCandidate::sNumViewCells); 
    3079                                         } 
    3080                                 } 
    3081                                 else 
    3082                                 {  
    3083  
    3084                                         // merge candidate not valid, because one of the leaves was already 
    3085                                         // merged with another one => validate and reinsert into queue 
    3086                                         mc.SetValid(); 
    3087                                         mMergeQueue.push(mc); 
    3088                                 } 
    3089                 } 
    3090          
    3091  
    3092                 ++ pass; 
    3093         } 
    3094  
    3095         mergeStats.overallCost = BspMergeCandidate::sOverallCost; 
    3096  
    3097         mergeStats.mergeTime = TimeDiff(startTime, GetTime()); 
    3098         mergeStats.Stop(); 
    3099  
    3100         Debug << mergeStats << endl << endl; 
    3101          
    3102         // delete the view cells which were already merged 
    3103         CLEAR_CONTAINER(mOldViewCells); 
    3104          
    3105  
    3106         //TODO: should return sample contributions? 
    3107         return mergeStats.merged; 
    3108 } 
    3109  
    3110 #else 
    3111  
    3112 int VspBspTree::MergeViewCells(const VssRayContainer &rays, const ObjectContainer &objects) 
    3113 { 
    3114         BspMergeCandidate::sViewCellsManager = mViewCellsManager; 
    3115         BspMergeCandidate::sUseArea = mUseAreaForPvs; 
    3116  
    3117         ViewCellsManager::PvsStatistics pvsStats; 
    3118         mViewCellsManager->GetPvsStatistics(pvsStats); 
    3119  
    3120         static float expectedValue = pvsStats.avgPvs; 
    3121         // the current view cells are kept in this container 
    3122         ViewCellContainer viewCells; 
    3123         if (mExportMergedViewCells) 
    3124         { 
    3125                 ViewCell::NewMail(); 
    3126                 CollectViewCells(mRoot, true, viewCells, true); 
    3127         } 
    3128         ViewCell::NewMail(); 
    3129  
    3130         MergeStatistics mergeStats; 
    3131         mergeStats.Start(); 
    3132          
    3133         //BspMergeCandidate::sOverallCost = mBox.SurfaceArea() * mBspStats.maxPvs; 
    3134         long startTime = GetTime(); 
    3135  
    3136         cout << "collecting merge candidates ... " << endl; 
    3137          
    3138         if (mUseRaysForMerge) 
    3139         { 
    3140                 mergeStats.nodes = CollectMergeCandidates(rays); 
    3141         } 
    3142         else 
    3143         { 
    3144                 vector<BspLeaf *> leaves; 
    3145                 CollectLeaves(leaves); 
    3146                 mergeStats.nodes = CollectMergeCandidates(leaves); 
    3147         } 
    3148          
    3149         cout << "fininshed collecting candidates" << endl; 
    3150  
    3151         mergeStats.collectTime = TimeDiff(startTime, GetTime()); 
    3152         mergeStats.candidates = (int)mMergeQueue.size(); 
    3153         startTime = GetTime(); 
    3154  
    3155          
    3156         // number of view cells withouth the invalid ones 
    3157         int nViewCells = mBspStats.Leaves() - mBspStats.invalidLeaves; 
    3158         BspMergeCandidate::sExpectedCost = BspMergeCandidate::sOverallCost / (float)nViewCells; 
    3159  
    3160         // passes are needed for statistics, because we don't want to record 
    3161         // every merge 
    3162         const int mergesPerPass = 100; 
    3163          
    3164         int nextPass = 0; 
    3165     int pass = 0; 
    3166          
    3167          
    3168         Debug << "stats: " << nextStats << " " << statsIncr << endl; 
    3169         cout << "actual merge starts now ... " << endl; 
    3170  
    3171         //-- use priority queue to merge leaf pairs 
    3172         while (!mMergeQueue.empty() && (nViewCells > mMergeMinViewCells) && 
    3173                    (mMergeQueue.top().GetMergeCost() < 
    3174                     mMergeMaxCostRatio * BspMergeCandidate::sOverallCost)) 
    3175         { 
    3176 #ifdef _DEBUG 
    3177                 Debug << "abs mergecost: " << mMergeQueue.top().GetMergeCost() << " rel mergecost: " 
    3178                           << mMergeQueue.top().GetMergeCost() / BspMergeCandidate::sOverallCost  
    3179                           << " max ratio: " << mMergeMaxCostRatio << endl; 
    3180 #endif 
    3181  
    3182                 BspMergeCandidate mc = mMergeQueue.top(); 
    3183                 mMergeQueue.pop(); 
    3184  
    3185  
    3186                 // both view cells equal! 
    3187                 if (mc.GetLeaf1()->GetViewCell() == mc.GetLeaf2()->GetViewCell()) 
    3188                         continue; 
    3189  
    3190                 if (mc.Valid()) 
    3191                 { 
    3192                         ViewCell::NewMail(); 
    3193                         const float mergeCost = mc.GetMergeCost(); 
    3194  
    3195                         MergeViewCells(mc.GetLeaf1(), mc.GetLeaf2()); 
    3196                                          
    3197                         // increase absolute merge cost 
    3198                         BspMergeCandidate::sOverallCost += mc.GetMergeCost(); 
    3199                          
    3200  
    3201                         -- nViewCells; 
    3202                         ++ mergeStats.merged; 
    3203  
    3204                         if ((mergeStats.merged % 500) == 0) 
    3205                                 cout << "merged " << mergeStats.merged << " view cells" << endl; 
    3206  
    3207                         // stats and visualizations 
    3208                         if (mExportMergeStats) 
    3209                         { 
    3210                                 if (mc.GetLeaf1()->IsSibling(mc.GetLeaf2())) 
    3211                                         ++ mergeStats.siblings; 
    3212  
    3213                                 if (0) 
    3214                                 const int dist =  
    3215                                         TreeDistance(mc.GetLeaf1(), mc.GetLeaf2()); 
    3216                                 if (dist > mergeStats.maxTreeDist) 
    3217                                         mergeStats.maxTreeDist = dist; 
    3218                                 mergeStats.accTreeDist += dist; 
    3219  
    3220                                 if ((mergeStats.merged == nextPass) || (nViewCells == mMergeMinViewCells)) 
    3221                                 { 
    3222                                         nextPass += mergesPerPass; 
    3223  
    3224                                         mStats  
    3225                                                 << "#Pass\n" << pass ++ << endl 
    3226                                                 << "#Merged\n" << mergeStats.merged << endl  
    3227                                                 << "#Viewcells\n" << nViewCells << endl  
    3228                                                 << "#OverallCost\n" << BspMergeCandidate::sOverallCost << endl 
    3229                                                 << "#CurrentCost\n" << mergeCost << endl 
    3230                                                 << "#RelativeCost\n" << mergeCost / BspMergeCandidate::sOverallCost << endl 
    3231                                                 << "#CurrentPvs\n" << mc.GetLeaf1()->GetViewCell()->GetPvs().GetSize() << endl 
    3232                                                 << "#MergedSiblings\n" << mergeStats.siblings << endl 
    3233                                                 << "#AvgTreeDist\n" << mergeStats.AvgTreeDist() << endl; 
    3234  
    3235                                                 if (mExportMergedViewCells) 
    3236                                                         ExportMergedViewCells(viewCells, objects, nViewCells); 
    3237                                 } 
    3238                         } 
    3239                 } 
    3240                 // merge candidate not valid, because one of the leaves was already 
    3241                 // merged with another one => validate and reinsert into queue 
    3242                 else 
    3243                 {  
    3244                         mc.SetValid(); 
    3245                         mMergeQueue.push(mc); 
    3246                 } 
    3247         } 
    3248  
    3249         mergeStats.overallCost = BspMergeCandidate::sOverallCost; 
    3250  
    3251         mergeStats.mergeTime = TimeDiff(startTime, GetTime()); 
    3252         mergeStats.Stop(); 
    3253  
    3254         Debug << mergeStats << endl << endl; 
    3255          
    3256         // delete the view cells which were already merged 
    3257         CLEAR_CONTAINER(mOldViewCells); 
    3258          
    3259  
    3260         //TODO: should return sample contributions? 
    3261         return mergeStats.merged; 
    3262 } 
    3263 #endif 
    32642819 
    32652820 
     
    32972852 
    32982853 
    3299 void VspBspTree::ExportMergedViewCells(ViewCellContainer &viewCells,  
    3300                                                                            const ObjectContainer &objects, 
    3301                                                                            const int nViewCells) 
    3302 { 
    3303         ViewCellContainer::const_iterator vit, vit_end = viewCells.end(); 
    3304                                          
    3305         // find all already merged view cells and remove them from view cells 
    3306         int i = 0; 
    3307  
    3308         while (1) 
    3309         { 
    3310                 //while (!viewCells.empty() && (viewCells.back()->mMailbox == -1)) 
    3311                 while (!viewCells.empty() && (viewCells.back()->GetId() == -2)) 
    3312                 { 
    3313                         //DEL_PTR(viewCells.back()); 
    3314                         viewCells.pop_back(); 
    3315                 } 
    3316                 // all merged view cells have been found 
    3317                 if (i >= viewCells.size())  
    3318                         break; 
    3319  
    3320                 // already merged view cell, put it to end of vector 
    3321                 //if (viewCells[i]->mMailbox == -1) 
    3322                 if (viewCells[i]->GetId() == -2) 
    3323                         swap(viewCells[i], viewCells.back()); 
    3324                  
    3325                 ++ i; 
    3326         } 
    3327  
    3328         int newVcSize = 0; 
    3329         // add new view cells to container only if they don't have been  
    3330         // merged in the mean time 
    3331         while (!mNewViewCells.empty()) 
    3332         { 
    3333                 if (mNewViewCells.back()->GetId() != -2) 
    3334                 { 
    3335                         viewCells.push_back(mNewViewCells.back()); 
    3336                         ++ newVcSize; 
    3337                 } 
    3338  
    3339                 mNewViewCells.pop_back(); 
    3340         } 
    3341  
    3342         char s[64]; 
    3343         sprintf(s, "merged_viewcells%07d.x3d", nViewCells); 
    3344         Exporter *exporter = Exporter::GetExporter(s); 
    3345  
    3346         if (exporter) 
    3347         { 
    3348                 cout << "exporting " << nViewCells << " merged view cells ... "; 
    3349                 exporter->ExportGeometry(objects); 
    3350                 //Debug << "vc size " << (int)viewCells.size() << " merge queue size: " << (int)mMergeQueue.size() << endl; 
    3351                 ViewCellContainer::const_iterator it, it_end = viewCells.end(); 
    3352  
    3353                 int i = 0; 
    3354                 for (it = viewCells.begin(); it != it_end; ++ it) 
    3355                 { 
    3356                         Material m; 
    3357                         // assign special material to new view cells 
    3358                         // new view cells are on the back of container 
    3359                         if (i ++ >= (viewCells.size() - newVcSize)) 
    3360                         { 
    3361                                 //m = RandomMaterial(); 
    3362                                 m.mDiffuseColor.r = RandomValue(0.5f, 1.0f); 
    3363                                 m.mDiffuseColor.g = RandomValue(0.5f, 1.0f); 
    3364                                 m.mDiffuseColor.b = RandomValue(0.5f, 1.0f); 
    3365                         } 
    3366                         else 
    3367                         { 
    3368                                 float col = RandomValue(0.1f, 0.4f); 
    3369                                 m.mDiffuseColor.r = col; 
    3370                                 m.mDiffuseColor.g = col; 
    3371                                 m.mDiffuseColor.b = col; 
    3372                         } 
    3373  
    3374                         exporter->SetForcedMaterial(m); 
    3375                         mViewCellsManager->ExportVcGeometry(exporter, *it); 
    3376                 } 
    3377                 delete exporter; 
    3378                 cout << "finished" << endl; 
    3379         } 
    3380  
    3381         // delete the view cells which were merged 
    3382         CLEAR_CONTAINER(mOldViewCells); 
    3383         // remove the new view cells 
    3384         mNewViewCells.clear(); 
    3385 } 
    3386  
    3387  
    3388 int VspBspTree::RefineViewCells(const VssRayContainer &rays, const ObjectContainer &objects) 
    3389 { 
    3390         Debug << "refining " << (int)mMergeQueue.size() << " candidates " << endl; 
    3391          
    3392         BspLeaf::NewMail(); 
    3393  
    3394         // Use priority queue of remaining leaf pairs  
    3395         // The candidates either share the same view cells or 
    3396         // are border leaves which share a boundary. 
    3397         // We test if they can be shuffled, i.e., 
    3398         // either one leaf is made part of one view cell or the other 
    3399         // leaf is made part of the other view cell. It is tested if the 
    3400         // remaining view cells are "better" than the old ones. 
    3401         // 
    3402         // repeat the merging test numPasses times. For example, it could be 
    3403         // that a shuffle only makes sense if another pair was shuffled before. 
    3404         // Therefore we keep two queues and shift the merge candidates between 
    3405         // those two queues until numPasses is reached 
    3406          
    3407         queue<BspMergeCandidate> queue1; 
    3408         queue<BspMergeCandidate> queue2; 
    3409  
    3410         queue<BspMergeCandidate> *shuffleQueue = &queue1; 
    3411         queue<BspMergeCandidate> *backQueue = &queue2; 
    3412  
    3413         while (!mMergeQueue.empty()) 
    3414         { 
    3415                 BspMergeCandidate mc = mMergeQueue.top(); 
    3416                 shuffleQueue->push(mc); 
    3417                 mMergeQueue.pop(); 
    3418         } 
    3419  
    3420         const int numPasses = 5; 
    3421         int pass = 0; 
    3422         int passShuffled = 0; 
    3423         int shuffled = 0; 
    3424  
    3425         BspLeaf::NewMail(); 
    3426  
    3427         do 
    3428         { 
    3429                 passShuffled = 0; 
    3430                 while (!shuffleQueue->empty()) 
    3431                 { 
    3432                         BspMergeCandidate mc = shuffleQueue->front(); 
    3433                         shuffleQueue->pop(); 
    3434  
    3435                         // both view cells equal or already shuffled 
    3436                         if ((mc.GetLeaf1()->GetViewCell() == mc.GetLeaf2()->GetViewCell()))// || 
    3437                         //      (mc.GetLeaf1()->Mailed()) || (mc.GetLeaf2()->Mailed())) 
    3438                                 continue; 
    3439                  
    3440                         // candidate for shuffling 
    3441                         const bool wasShuffled =  
    3442                                 ShuffleLeaves(mc.GetLeaf1(), mc.GetLeaf2()); 
    3443                  
    3444                         if (wasShuffled) 
    3445                                 ++ passShuffled; 
    3446                         else 
    3447                                 backQueue->push(mc); 
    3448                 } 
    3449  
    3450                 // now the back queue is the current shuffle queue 
    3451                 swap(shuffleQueue, backQueue); 
    3452                 shuffled += passShuffled; 
    3453                 Debug << "shuffled in pass: " << passShuffled << endl; 
    3454         } 
    3455         while (((++ pass) < numPasses) && passShuffled); 
    3456  
    3457         while (!shuffleQueue->empty()) 
    3458         { 
    3459                 shuffleQueue->pop(); 
    3460         } 
    3461  
    3462         return shuffled; 
    3463 } 
    3464  
    3465  
    3466 inline int AddedPvsSize(ObjectPvs pvs1, const ObjectPvs &pvs2) 
    3467 { 
    3468         return pvs1.AddPvs(pvs2); 
    3469 } 
    3470  
    3471  
    3472 // recomputes pvs size minus pvs of leaf l 
    3473 #if 0 
    3474 inline int SubtractedPvsSize(BspViewCell *vc, BspLeaf *l, const ObjectPvs &pvs2) 
    3475 { 
    3476         ObjectPvs pvs; 
    3477         vector<BspLeaf *>::const_iterator it, it_end = vc->mLeaves.end(); 
    3478         for (it = vc->mLeaves.begin(); it != vc->mLeaves.end(); ++ it) 
    3479                 if (*it != l) 
    3480                         pvs.AddPvs(*(*it)->mPvs); 
    3481         return pvs.GetSize(); 
    3482 } 
    3483 #endif 
    3484  
    3485 // computes pvs1 minus pvs2 
    3486 inline int SubtractedPvsSize(ObjectPvs pvs1, const ObjectPvs &pvs2) 
    3487 { 
    3488         return pvs1.SubtractPvs(pvs2); 
    3489 } 
    3490  
    3491  
    3492 float VspBspTree::GetShuffledVcCost(BspLeaf *leaf, BspViewCell *vc1, BspViewCell *vc2) const 
    3493 { 
    3494         //const int pvs1 = SubtractedPvsSize(vc1, leaf, *leaf->mPvs); 
    3495         const int pvs1 = SubtractedPvsSize(vc1->GetPvs(), *leaf->mPvs); 
    3496         const int pvs2 = AddedPvsSize(vc2->GetPvs(), *leaf->mPvs); 
    3497  
    3498         // don't shuffle leaves with pvs > max 
    3499         if (pvs1 + pvs2 > mViewCellsManager->GetMaxPvsSize()) 
    3500                 return 1e15f; 
    3501  
    3502 #if 1 
    3503         float p1, p2; 
    3504  
    3505     if (mUseAreaForPvs) 
    3506         { 
    3507                 p1 = vc1->GetArea() - leaf->mProbability; 
    3508                 p2 = vc2->GetArea() + leaf->mProbability; 
    3509         } 
    3510         else 
    3511         { 
    3512                 p1 = vc1->GetVolume() - leaf->mProbability; 
    3513                 p2 = vc2->GetVolume() + leaf->mProbability; 
    3514         } 
    3515  
    3516         const float cost1 = pvs1 * p1; 
    3517         const float cost2 = pvs2 * p2; 
    3518 #else 
    3519         const float cost1 = pvs1; 
    3520         const float cost2 = pvs2; 
    3521 #endif 
    3522  
    3523         return cost1 + cost2; 
    3524 } 
    3525  
    3526  
    3527 void VspBspTree::ShuffleLeaf(BspLeaf *leaf,  
    3528                                                          BspViewCell *vc1,  
    3529                                                          BspViewCell *vc2) const 
    3530 { 
    3531         // compute new pvs and area 
    3532         vc1->GetPvs().SubtractPvs(*leaf->mPvs); 
    3533         vc2->GetPvs().AddPvs(*leaf->mPvs); 
    3534          
    3535         if (mUseAreaForPvs) 
    3536         { 
    3537                 vc1->SetArea(vc1->GetArea() - leaf->mProbability); 
    3538                 vc2->SetArea(vc2->GetArea() + leaf->mProbability); 
    3539         } 
    3540         else 
    3541         { 
    3542                 vc1->SetVolume(vc1->GetVolume() - leaf->mProbability); 
    3543                 vc2->SetVolume(vc2->GetVolume() + leaf->mProbability); 
    3544         } 
    3545  
    3546         /// add to second view cell 
    3547         vc2->mLeaves.push_back(leaf); 
    3548  
    3549         // erase leaf from old view cell 
    3550         vector<BspLeaf *>::iterator it = vc1->mLeaves.begin(); 
    3551  
    3552         for (; *it != leaf; ++ it); 
    3553         vc1->mLeaves.erase(it); 
    3554  
    3555         /*vc1->GetPvs().mEntries.clear(); 
    3556         for (; it != vc1->mLeaves.end(); ++ it) 
    3557         { 
    3558                 if (*it == leaf) 
    3559                         vc1->mLeaves.erase(it); 
    3560                 else 
    3561                         vc1->GetPvs().AddPvs(*(*it)->mPvs); 
    3562         }*/ 
    3563  
    3564         leaf->SetViewCell(vc2); // finally change view cell 
    3565 } 
    3566  
    3567  
    3568 bool VspBspTree::ShuffleLeaves(BspLeaf *leaf1, BspLeaf *leaf2) const 
    3569 { 
    3570         BspViewCell *vc1 = leaf1->GetViewCell(); 
    3571         BspViewCell *vc2 = leaf2->GetViewCell(); 
    3572  
    3573         float cost1, cost2; 
    3574  
    3575 #if 1 
    3576         if (mUseAreaForPvs) 
    3577         { 
    3578                 cost1 = vc1->GetPvs().GetSize() * vc1->GetArea(); 
    3579                 cost2 = vc2->GetPvs().GetSize() * vc2->GetArea(); 
    3580         } 
    3581         else 
    3582         { 
    3583                 cost1 = vc1->GetPvs().GetSize() * vc1->GetVolume(); 
    3584                 cost2 = vc2->GetPvs().GetSize() * vc2->GetVolume(); 
    3585         } 
    3586 #else 
    3587         cost1 = vc1->GetPvs().GetSize();  
    3588         cost2 = vc2->GetPvs().GetSize();  
    3589 #endif 
    3590  
    3591         const float oldCost = cost1 + cost2; 
    3592          
    3593         float shuffledCost1 = Limits::Infinity; 
    3594         float shuffledCost2 = Limits::Infinity; 
    3595  
    3596         // the view cell should not be empty after the shuffle 
    3597         if (vc1->mLeaves.size() > 1) 
    3598                 shuffledCost1 = GetShuffledVcCost(leaf1, vc1, vc2); 
    3599         if (vc2->mLeaves.size() > 1) 
    3600                 shuffledCost2 = GetShuffledVcCost(leaf2, vc2, vc1); 
    3601  
    3602         // shuffling unsuccessful 
    3603         if ((oldCost <= shuffledCost1) && (oldCost <= shuffledCost2)) 
    3604                 return false; 
    3605          
    3606         if (shuffledCost1 < shuffledCost2) 
    3607         { 
    3608                 ShuffleLeaf(leaf1, vc1, vc2); 
    3609                 leaf1->Mail(); 
    3610         } 
    3611         else 
    3612         { 
    3613                 ShuffleLeaf(leaf2, vc2, vc1); 
    3614                 leaf2->Mail(); 
    3615         } 
    3616  
    3617         return true; 
    3618 } 
    3619  
    3620  
    36212854bool VspBspTree::ViewPointValid(const Vector3 &viewPoint) const 
    36222855{ 
     
    37132946        } 
    37142947} 
    3715  
    3716  
    3717 /**************************************************************************/ 
    3718 /*                  BspMergeCandidate implementation                      */ 
    3719 /**************************************************************************/ 
    3720  
    3721  
    3722 BspMergeCandidate::BspMergeCandidate(BspLeaf *l1, BspLeaf *l2): 
    3723 mRenderCost(0), 
    3724 mVarianceIncr(0), 
    3725 mLeaf1(l1), 
    3726 mLeaf2(l2), 
    3727 mLeaf1Id(l1->GetViewCell()->mMailbox), 
    3728 mLeaf2Id(l2->GetViewCell()->mMailbox) 
    3729 { 
    3730         //EvalMergeCost(); 
    3731 } 
    3732  
    3733  
    3734 float BspMergeCandidate::GetRenderCost(ViewCell *vc) const 
    3735 { 
    3736         if (sUseArea) 
    3737                 return vc->GetPvs().GetSize() * vc->GetArea(); 
    3738  
    3739         return vc->GetPvs().GetSize() * vc->GetVolume(); 
    3740 } 
    3741  
    3742  
    3743 float BspMergeCandidate::GetLeaf1Cost() const 
    3744 { 
    3745         BspViewCell *vc = mLeaf1->GetViewCell(); 
    3746  
    3747         return GetRenderCost(vc); 
    3748 } 
    3749  
    3750  
    3751 float BspMergeCandidate::GetLeaf2Cost() const 
    3752 { 
    3753         BspViewCell *vc = mLeaf2->GetViewCell(); 
    3754  
    3755         return GetRenderCost(vc); 
    3756 } 
    3757  
    3758  
    3759 int ComputeMergedPvsSize(const ObjectPvs &pvs1, const ObjectPvs &pvs2) 
    3760 { 
    3761         int pvs = pvs1.GetSize(); 
    3762  
    3763         // compute new pvs size 
    3764         ObjectPvsMap::const_iterator it, it_end =  pvs1.mEntries.end(); 
    3765  
    3766         Intersectable::NewMail(); 
    3767  
    3768         for (it = pvs1.mEntries.begin(); it != it_end; ++ it) 
    3769         { 
    3770                 (*it).first->Mail(); 
    3771         } 
    3772  
    3773         it_end = pvs2.mEntries.end(); 
    3774  
    3775         for (it = pvs2.mEntries.begin(); it != it_end; ++ it) 
    3776         { 
    3777                 Intersectable *obj = (*it).first; 
    3778                 if (!obj->Mailed()) 
    3779                         ++ pvs; 
    3780         } 
    3781  
    3782         return pvs; 
    3783 } 
    3784  
    3785  
    3786  
    3787 void BspMergeCandidate::EvalMergeCost() 
    3788 { 
    3789         //-- compute pvs difference 
    3790         BspViewCell *vc1 = mLeaf1->GetViewCell(); 
    3791         BspViewCell *vc2 = mLeaf2->GetViewCell(); 
    3792  
    3793         const int newPvs = ComputeMergedPvsSize(vc1->GetPvs(), vc2->GetPvs()); 
    3794         const float newPenalty =  
    3795                 EvalPvsPenalty(newPvs,  
    3796                                            sViewCellsManager->GetMinPvsSize(), 
    3797                                            sViewCellsManager->GetMaxPvsSize()); 
    3798  
    3799         //-- compute ratio of old cost 
    3800         //   (i.e., added size of left and right view cell times pvs size) 
    3801         //   to new rendering cost (i.e, size of merged view cell times pvs size) 
    3802         const float oldCost = GetLeaf1Cost() + GetLeaf2Cost(); 
    3803  
    3804     const float newCost = sUseArea ?  
    3805                 (float)newPvs * (vc1->GetArea() + vc2->GetArea()) : 
    3806                 (float)newPvs * (vc1->GetVolume() + vc2->GetVolume()); 
    3807  
    3808  
    3809         if (newPvs > sViewCellsManager->GetMaxPvsSize()) // strong penalty if pvs size too large 
    3810         { 
    3811                 mRenderCost = 1e15; 
    3812         } 
    3813         else 
    3814         { 
    3815                 mRenderCost = newCost - oldCost; 
    3816         } 
    3817  
    3818         // merge cost also takes variance into account 
    3819  
    3820         const float oldVar1 = GetLeaf1Variance(); 
    3821         const float oldVar2 = GetLeaf2Variance(); 
    3822  
    3823         const float newVar = (sExpectedCost - mRenderCost) * (sExpectedCost - mRenderCost); 
    3824  
    3825         mVarianceIncr = (newVar - oldVar1 - oldVar2) / sNumViewCells; 
    3826         //mMergeCost = mRenderCost + fabs(newPenalty - BspMergeCandidate::sExpectedCost) ; 
    3827 } 
    3828  
    3829  
    3830 void BspMergeCandidate::SetLeaf1(BspLeaf *l) 
    3831 { 
    3832         mLeaf1 = l; 
    3833 } 
    3834  
    3835  
    3836 void BspMergeCandidate::SetLeaf2(BspLeaf *l) 
    3837 { 
    3838         mLeaf2 = l; 
    3839 } 
    3840  
    3841  
    3842 BspLeaf *BspMergeCandidate::GetLeaf1() const 
    3843 { 
    3844         return mLeaf1; 
    3845 } 
    3846  
    3847  
    3848 BspLeaf *BspMergeCandidate::GetLeaf2() const 
    3849 { 
    3850         return mLeaf2; 
    3851 } 
    3852  
    3853  
    3854 bool BspMergeCandidate::Valid() const 
    3855 { 
    3856         return 
    3857                 (mLeaf1->GetViewCell()->mMailbox == mLeaf1Id) && 
    3858                 (mLeaf2->GetViewCell()->mMailbox == mLeaf2Id); 
    3859 } 
    3860  
    3861  
    3862 float BspMergeCandidate::GetMergeCost() const 
    3863 { 
    3864         return mRenderCost * sRenderCostWeight + mVarianceIncr * (1.0f - sRenderCostWeight); 
    3865 } 
    3866  
    3867  
    3868 float BspMergeCandidate::GetRenderCost() const 
    3869 { 
    3870         return mRenderCost; 
    3871 } 
    3872  
    3873  
    3874 float BspMergeCandidate::GetVarianceIncr() const 
    3875 { 
    3876         return mVarianceIncr; 
    3877 } 
    3878  
    3879 float BspMergeCandidate::GetLeaf1Variance() const 
    3880 { 
    3881         const float leafCost = GetLeaf1Cost(); 
    3882          
    3883         return (sExpectedCost - leafCost) * (sExpectedCost - leafCost); 
    3884 } 
    3885  
    3886  
    3887 float BspMergeCandidate::GetLeaf2Variance() const 
    3888 { 
    3889         const float leafCost = GetLeaf2Cost(); 
    3890          
    3891         return (sExpectedCost - leafCost) * (sExpectedCost - leafCost); 
    3892 } 
    3893  
    3894  
    3895 void BspMergeCandidate::SetValid() 
    3896 { 
    3897         mLeaf1Id = mLeaf1->GetViewCell()->mMailbox; 
    3898         mLeaf2Id = mLeaf2->GetViewCell()->mMailbox; 
    3899  
    3900         EvalMergeCost(); 
    3901 } 
    3902  
    3903  
    3904 /************************************************************************/ 
    3905 /*                    MergeStatistics implementation                    */ 
    3906 /************************************************************************/ 
    3907  
    3908  
    3909 void MergeStatistics::Print(ostream &app) const 
    3910 { 
    3911         app << "===== Merge statistics ===============\n"; 
    3912  
    3913         app << setprecision(4); 
    3914  
    3915         app << "#N_CTIME ( Overall time [s] )\n" << Time() << " \n"; 
    3916  
    3917         app << "#N_CCTIME ( Collect candidates time [s] )\n" << collectTime * 1e-3f << " \n"; 
    3918  
    3919         app << "#N_MTIME ( Merge time [s] )\n" << mergeTime * 1e-3f << " \n"; 
    3920  
    3921         app << "#N_NODES ( Number of nodes before merge )\n" << nodes << "\n"; 
    3922  
    3923         app << "#N_CANDIDATES ( Number of merge candidates )\n" << candidates << "\n"; 
    3924  
    3925         app << "#N_MERGEDSIBLINGS ( Number of merged siblings )\n" << siblings << "\n"; 
    3926  
    3927         app << "#OVERALLCOST ( overall merge cost )\n" << overallCost << "\n"; 
    3928  
    3929         app << "#N_MERGEDNODES ( Number of merged nodes )\n" << merged << "\n"; 
    3930  
    3931         app << "#MAX_TREEDIST ( Maximal distance in tree of merged leaves )\n" << maxTreeDist << "\n"; 
    3932  
    3933         app << "#AVG_TREEDIST ( Average distance in tree of merged leaves )\n" << AvgTreeDist() << "\n"; 
    3934  
    3935         app << "===== END OF BspTree statistics ==========\n"; 
    3936 } 
Note: See TracChangeset for help on using the changeset viewer.