[440] | 1 | #include "ViewCellsManager.h"
|
---|
| 2 | #include "RenderSimulator.h"
|
---|
| 3 | #include "Mesh.h"
|
---|
| 4 | #include "Triangle3.h"
|
---|
| 5 | #include "ViewCell.h"
|
---|
| 6 | #include "Environment.h"
|
---|
| 7 | #include "X3dParser.h"
|
---|
| 8 | #include "ViewCellBsp.h"
|
---|
| 9 | #include "KdTree.h"
|
---|
[1233] | 10 | #include "HierarchyManager.h"
|
---|
[440] | 11 | #include "Exporter.h"
|
---|
[442] | 12 | #include "VspBspTree.h"
|
---|
[508] | 13 | #include "ViewCellsParser.h"
|
---|
[532] | 14 | #include "Beam.h"
|
---|
[540] | 15 | #include "VssPreprocessor.h"
|
---|
| 16 | #include "RssPreprocessor.h"
|
---|
[931] | 17 | #include "BoundingBoxConverter.h"
|
---|
[979] | 18 | #include "GlRenderer.h"
|
---|
[1001] | 19 | #include "ResourceManager.h"
|
---|
[1315] | 20 | #include "IntersectableWrapper.h"
|
---|
[1233] | 21 | #include "VspTree.h"
|
---|
| 22 | #include "OspTree.h"
|
---|
[1259] | 23 | #include "BvHierarchy.h"
|
---|
[1520] | 24 | #include "SamplingStrategy.h"
|
---|
[1545] | 25 | #include "SceneGraph.h"
|
---|
[440] | 26 |
|
---|
[1278] | 27 |
|
---|
[1594] | 28 | // $$JB HACK
|
---|
[1771] | 29 | #define KD_PVS_AREA (1e-5f)
|
---|
[1486] | 30 |
|
---|
[1900] | 31 | #define USE_RAY_LENGTH_AS_CONTRIBUTION 0
|
---|
[1931] | 32 | #define DIST_WEIGHTED_CONTRIBUTION 0
|
---|
[1942] | 33 | #define SUM_RAY_CONTRIBUTIONS 1
|
---|
| 34 | #define AVG_RAY_CONTRIBUTIONS 0
|
---|
| 35 | #define CONTRIBUTION_RELATIVE_TO_PVS_SIZE 0
|
---|
[1932] | 36 | #define PVS_ADD_DIRTY 1
|
---|
[1900] | 37 |
|
---|
[863] | 38 | namespace GtpVisibilityPreprocessor {
|
---|
[860] | 39 |
|
---|
| 40 |
|
---|
[712] | 41 | // HACK
|
---|
| 42 | const static bool SAMPLE_AFTER_SUBDIVISION = true;
|
---|
[1764] | 43 | //const static bool CLAMP_TO_BOX = false;
|
---|
| 44 | const static bool CLAMP_TO_BOX = true;
|
---|
[517] | 45 |
|
---|
[1705] | 46 |
|
---|
[1703] | 47 | int ViewCellsManager::sRenderCostEvaluationType = 0;
|
---|
| 48 |
|
---|
| 49 |
|
---|
[697] | 50 | template <typename T> class myless
|
---|
| 51 | {
|
---|
| 52 | public:
|
---|
| 53 | //bool operator() (HierarchyNode *v1, HierarchyNode *v2) const
|
---|
| 54 | bool operator() (T v1, T v2) const
|
---|
| 55 | {
|
---|
| 56 | return (v1->GetMergeCost() < v2->GetMergeCost());
|
---|
| 57 | }
|
---|
| 58 | };
|
---|
| 59 |
|
---|
| 60 |
|
---|
[1264] | 61 | ViewCellsManager::ViewCellsManager(ViewCellsTree *viewCellsTree):
|
---|
[480] | 62 | mRenderer(NULL),
|
---|
[574] | 63 | mInitialSamples(0),
|
---|
[440] | 64 | mConstructionSamples(0),
|
---|
| 65 | mPostProcessSamples(0),
|
---|
[470] | 66 | mVisualizationSamples(0),
|
---|
| 67 | mTotalAreaValid(false),
|
---|
[517] | 68 | mTotalArea(0.0f),
|
---|
[547] | 69 | mViewCellsFinished(false),
|
---|
[562] | 70 | mMaxPvsSize(9999999),
|
---|
[1686] | 71 | mMinPvsSize(0),
|
---|
[719] | 72 | mMaxPvsRatio(1.0),
|
---|
[1145] | 73 | mViewCellPvsIsUpdated(false),
|
---|
[1264] | 74 | mPreprocessor(NULL),
|
---|
[1545] | 75 | mViewCellsTree(viewCellsTree),
|
---|
| 76 | mUsePredefinedViewCells(false)
|
---|
[440] | 77 | {
|
---|
[542] | 78 | mViewSpaceBox.Initialize();
|
---|
[482] | 79 | ParseEnvironment();
|
---|
[580] | 80 |
|
---|
[1264] | 81 | mViewCellsTree->SetViewCellsManager(this);
|
---|
[440] | 82 | }
|
---|
| 83 |
|
---|
[517] | 84 |
|
---|
[1932] | 85 | int ViewCellsManager::CastPassSamples2(const int samplesPerPass,
|
---|
| 86 | VssRayContainer &passSamples) const
|
---|
[1903] | 87 | {
|
---|
| 88 | long startTime = GetTime();
|
---|
| 89 |
|
---|
| 90 | SimpleRayContainer simpleRays;
|
---|
| 91 |
|
---|
| 92 | simpleRays.reserve(samplesPerPass);
|
---|
| 93 | passSamples.reserve(samplesPerPass * 2); // always creates double rays
|
---|
| 94 |
|
---|
| 95 | // create one third of each type
|
---|
| 96 | int castRays = 0;
|
---|
| 97 |
|
---|
| 98 | mMixtureDistribution->GenerateSamples(mSamplesPerPass, simpleRays);
|
---|
| 99 |
|
---|
[1949] | 100 | cout << "generated " << (int)simpleRays.size() << " samples in "
|
---|
[1903] | 101 | << TimeDiff(startTime, GetTime()) * 1e-3 << " secs" << endl;
|
---|
| 102 |
|
---|
| 103 | startTime = GetTime();
|
---|
| 104 |
|
---|
| 105 | // shoot simple ray and add it to importance samples
|
---|
| 106 | mPreprocessor->CastRays(simpleRays, passSamples, true);
|
---|
| 107 |
|
---|
| 108 | cout << "cast " << samplesPerPass << " samples in "
|
---|
| 109 | << TimeDiff(startTime, GetTime()) * 1e-3 << " secs" << endl;
|
---|
| 110 |
|
---|
| 111 | mMixtureDistribution->ComputeContributions(passSamples);
|
---|
| 112 |
|
---|
| 113 | return (int)passSamples.size();
|
---|
| 114 | }
|
---|
| 115 |
|
---|
| 116 |
|
---|
[482] | 117 | void ViewCellsManager::ParseEnvironment()
|
---|
| 118 | {
|
---|
[503] | 119 | // visualization stuff
|
---|
[1761] | 120 | Environment::GetSingleton()->GetBoolValue("ViewCells.Visualization.exportRays", mExportRays);
|
---|
[1004] | 121 | Environment::GetSingleton()->GetBoolValue("ViewCells.Visualization.exportGeometry", mExportGeometry);
|
---|
| 122 | Environment::GetSingleton()->GetFloatValue("ViewCells.maxPvsRatio", mMaxPvsRatio);
|
---|
[664] | 123 |
|
---|
[1004] | 124 | Environment::GetSingleton()->GetBoolValue("ViewCells.processOnlyValidViewCells", mOnlyValidViewCells);
|
---|
[485] | 125 |
|
---|
[1004] | 126 | Environment::GetSingleton()->GetIntValue("ViewCells.Construction.samples", mConstructionSamples);
|
---|
| 127 | Environment::GetSingleton()->GetIntValue("ViewCells.PostProcess.samples", mPostProcessSamples);
|
---|
| 128 | Environment::GetSingleton()->GetBoolValue("ViewCells.PostProcess.useRaysForMerge", mUseRaysForMerge);
|
---|
[595] | 129 |
|
---|
[1004] | 130 | Environment::GetSingleton()->GetIntValue("ViewCells.Visualization.samples", mVisualizationSamples);
|
---|
[574] | 131 |
|
---|
[1004] | 132 | Environment::GetSingleton()->GetIntValue("ViewCells.Construction.samplesPerPass", mSamplesPerPass);
|
---|
| 133 | Environment::GetSingleton()->GetBoolValue("ViewCells.exportToFile", mExportViewCells);
|
---|
[581] | 134 |
|
---|
[1004] | 135 | Environment::GetSingleton()->GetIntValue("ViewCells.active", mNumActiveViewCells);
|
---|
| 136 | Environment::GetSingleton()->GetBoolValue("ViewCells.PostProcess.compress", mCompressViewCells);
|
---|
| 137 | Environment::GetSingleton()->GetBoolValue("ViewCells.Visualization.useClipPlane", mUseClipPlaneForViz);
|
---|
| 138 | Environment::GetSingleton()->GetBoolValue("ViewCells.PostProcess.merge", mMergeViewCells);
|
---|
| 139 | Environment::GetSingleton()->GetBoolValue("ViewCells.evaluateViewCells", mEvaluateViewCells);
|
---|
| 140 | Environment::GetSingleton()->GetBoolValue("ViewCells.showVisualization", mShowVisualization);
|
---|
| 141 | Environment::GetSingleton()->GetIntValue("ViewCells.Filter.maxSize", mMaxFilterSize);
|
---|
| 142 | Environment::GetSingleton()->GetFloatValue("ViewCells.Filter.width", mFilterWidth);
|
---|
[1703] | 143 | Environment::GetSingleton()->GetIntValue("ViewCells.renderCostEvaluationType", sRenderCostEvaluationType);
|
---|
[710] | 144 |
|
---|
[1004] | 145 | Environment::GetSingleton()->GetBoolValue("ViewCells.exportBboxesForPvs", mExportBboxesForPvs);
|
---|
| 146 | Environment::GetSingleton()->GetBoolValue("ViewCells.exportPvs", mExportPvs);
|
---|
[1902] | 147 |
|
---|
| 148 | Environment::GetSingleton()->GetBoolValue("ViewCells.useKdPvs", mUseKdPvs);
|
---|
| 149 |
|
---|
[664] | 150 | char buf[100];
|
---|
[1004] | 151 | Environment::GetSingleton()->GetStringValue("ViewCells.samplingType", buf);
|
---|
[664] | 152 |
|
---|
[1773] | 153 | // mix of sampling strategies
|
---|
[1919] | 154 | if (0)
|
---|
| 155 | {
|
---|
| 156 | mStrategies.push_back(SamplingStrategy::OBJECT_DIRECTION_BASED_DISTRIBUTION);
|
---|
| 157 | }
|
---|
| 158 | else
|
---|
| 159 | {
|
---|
| 160 | /*mStrategies.push_back(SamplingStrategy::OBJECT_BASED_DISTRIBUTION);
|
---|
| 161 | mStrategies.push_back(SamplingStrategy::REVERSE_VIEWSPACE_BORDER_BASED_DISTRIBUTION);
|
---|
| 162 | mStrategies.push_back(SamplingStrategy::REVERSE_OBJECT_BASED_DISTRIBUTION);
|
---|
| 163 | */
|
---|
| 164 |
|
---|
| 165 | mStrategies.push_back(SamplingStrategy::SPATIAL_BOX_BASED_DISTRIBUTION);
|
---|
| 166 | }
|
---|
[1910] | 167 |
|
---|
[1826] | 168 | Debug << "casting strategies: ";
|
---|
| 169 | for (int i = 0; i < (int)mStrategies.size(); ++ i)
|
---|
| 170 | Debug << mStrategies[i] << " ";
|
---|
| 171 | Debug << endl;
|
---|
| 172 |
|
---|
[1903] | 173 | // now decode distribution string
|
---|
| 174 | char buff[1024];
|
---|
| 175 | Environment::GetSingleton()->GetStringValue("RssPreprocessor.distributions", buff);
|
---|
| 176 |
|
---|
| 177 | mMixtureDistribution = new MixtureDistribution(*mPreprocessor);
|
---|
| 178 | mMixtureDistribution->Construct(buff);
|
---|
| 179 |
|
---|
| 180 |
|
---|
[1020] | 181 | // sampling type for view cells construction samples
|
---|
[1695] | 182 | if (strcmp(buf, "object") == 0)
|
---|
[722] | 183 | {
|
---|
[1695] | 184 | mSamplingType = SamplingStrategy::OBJECT_BASED_DISTRIBUTION;
|
---|
| 185 | }
|
---|
| 186 | else if (strcmp(buf, "box") == 0)
|
---|
| 187 | {
|
---|
[1520] | 188 | mSamplingType = SamplingStrategy::SPATIAL_BOX_BASED_DISTRIBUTION;
|
---|
[722] | 189 | }
|
---|
[664] | 190 | else if (strcmp(buf, "directional") == 0)
|
---|
[722] | 191 | {
|
---|
[1520] | 192 | mSamplingType = SamplingStrategy::DIRECTION_BASED_DISTRIBUTION;
|
---|
[722] | 193 | }
|
---|
[1020] | 194 | else if (strcmp(buf, "object_directional") == 0)
|
---|
| 195 | {
|
---|
[1520] | 196 | mSamplingType = SamplingStrategy::OBJECT_DIRECTION_BASED_DISTRIBUTION;
|
---|
[1020] | 197 | }
|
---|
[1695] | 198 | else if (strcmp(buf, "reverse_object") == 0)
|
---|
| 199 | {
|
---|
| 200 | mSamplingType = SamplingStrategy::REVERSE_OBJECT_BASED_DISTRIBUTION;
|
---|
| 201 | }
|
---|
[1022] | 202 | /*else if (strcmp(buf, "interior") == 0)
|
---|
| 203 | {
|
---|
| 204 | mSamplingType = Preprocessor::OBJECTS_INTERIOR_DISTRIBUTION;
|
---|
| 205 | }*/
|
---|
[1020] | 206 | else
|
---|
| 207 | {
|
---|
[666] | 208 | Debug << "error! wrong sampling type" << endl;
|
---|
| 209 | exit(0);
|
---|
| 210 | }
|
---|
[660] | 211 |
|
---|
[1020] | 212 | // sampling type for evaluation samples
|
---|
[1004] | 213 | Environment::GetSingleton()->GetStringValue("ViewCells.Evaluation.samplingType", buf);
|
---|
[722] | 214 |
|
---|
[1695] | 215 | if (strcmp(buf, "object") == 0)
|
---|
[722] | 216 | {
|
---|
[1695] | 217 | mEvaluationSamplingType = SamplingStrategy::OBJECT_BASED_DISTRIBUTION;
|
---|
| 218 | }
|
---|
| 219 | else if (strcmp(buf, "box") == 0)
|
---|
| 220 | {
|
---|
[1520] | 221 | mEvaluationSamplingType = SamplingStrategy::SPATIAL_BOX_BASED_DISTRIBUTION;
|
---|
[722] | 222 | }
|
---|
| 223 | else if (strcmp(buf, "directional") == 0)
|
---|
| 224 | {
|
---|
[1520] | 225 | mEvaluationSamplingType = SamplingStrategy::DIRECTION_BASED_DISTRIBUTION;
|
---|
[722] | 226 | }
|
---|
[1020] | 227 | else if (strcmp(buf, "object_directional") == 0)
|
---|
[722] | 228 | {
|
---|
[1520] | 229 | mEvaluationSamplingType = SamplingStrategy::OBJECT_DIRECTION_BASED_DISTRIBUTION;
|
---|
[1020] | 230 | }
|
---|
[1695] | 231 | else if (strcmp(buf, "reverse_object") == 0)
|
---|
| 232 | {
|
---|
| 233 | mEvaluationSamplingType = SamplingStrategy::REVERSE_OBJECT_BASED_DISTRIBUTION;
|
---|
| 234 | }
|
---|
[1022] | 235 | /*else if (strcmp(buf, "interior") == 0)
|
---|
[1020] | 236 | {
|
---|
[1520] | 237 | mEvaluationSamplingType = SamplingStrategy::OBJECTS_INTERIOR_DISTRIBUTION;
|
---|
[1022] | 238 | }*/
|
---|
[1020] | 239 | else
|
---|
| 240 | {
|
---|
[1695] | 241 | mEvaluationSamplingType = -1;
|
---|
[722] | 242 | Debug << "error! wrong sampling type" << endl;
|
---|
| 243 | exit(0);
|
---|
| 244 | }
|
---|
[503] | 245 |
|
---|
[1004] | 246 | Environment::GetSingleton()->GetStringValue("ViewCells.renderCostEvaluationType", buf);
|
---|
[728] | 247 |
|
---|
[734] | 248 | if (strcmp(buf, "perobject") == 0)
|
---|
[728] | 249 | {
|
---|
[1703] | 250 | sRenderCostEvaluationType = ViewCellsManager::PER_OBJECT;
|
---|
[728] | 251 | }
|
---|
[1703] | 252 | else if (strcmp(buf, "pertriangle") == 0)
|
---|
[728] | 253 | {
|
---|
[1703] | 254 | sRenderCostEvaluationType = ViewCellsManager::PER_TRIANGLE;
|
---|
[728] | 255 | }
|
---|
| 256 | else
|
---|
| 257 | {
|
---|
| 258 | Debug << "error! wrong sampling type" << endl;
|
---|
| 259 | exit(0);
|
---|
| 260 | }
|
---|
| 261 |
|
---|
[1004] | 262 | Environment::GetSingleton()->GetStringValue("ViewCells.Visualization.colorCode", buf);
|
---|
[722] | 263 |
|
---|
[482] | 264 | if (strcmp(buf, "PVS") == 0)
|
---|
| 265 | mColorCode = 1;
|
---|
| 266 | else if (strcmp(buf, "MergedLeaves") == 0)
|
---|
| 267 | mColorCode = 2;
|
---|
| 268 | else if (strcmp(buf, "MergedTreeDiff") == 0)
|
---|
| 269 | mColorCode = 3;
|
---|
| 270 | else
|
---|
| 271 | mColorCode = 0;
|
---|
| 272 |
|
---|
[664] | 273 |
|
---|
[1418] | 274 | Debug << "************ View Cells Manager options ***************" << endl;
|
---|
[664] | 275 | Debug << "color code: " << mColorCode << endl;
|
---|
| 276 |
|
---|
| 277 | Debug << "export rays: " << mExportRays << endl;
|
---|
| 278 | Debug << "export geometry: " << mExportGeometry << endl;
|
---|
| 279 | Debug << "max pvs ratio: " << mMaxPvsRatio << endl;
|
---|
| 280 |
|
---|
| 281 | Debug << "process only valid view cells: " << mOnlyValidViewCells << endl;
|
---|
| 282 | Debug << "construction samples: " << mConstructionSamples << endl;
|
---|
| 283 | Debug << "post process samples: " << mPostProcessSamples << endl;
|
---|
| 284 | Debug << "post process use rays for merge: " << mUseRaysForMerge << endl;
|
---|
| 285 | Debug << "visualization samples: " << mVisualizationSamples << endl;
|
---|
| 286 | Debug << "construction samples per pass: " << mSamplesPerPass << endl;
|
---|
| 287 | Debug << "export to file: " << mExportViewCells << endl;
|
---|
| 288 |
|
---|
[801] | 289 | Debug << "active view cells: " << mNumActiveViewCells << endl;
|
---|
[664] | 290 | Debug << "post process compress: " << mCompressViewCells << endl;
|
---|
| 291 | Debug << "visualization use clipPlane: " << mUseClipPlaneForViz << endl;
|
---|
| 292 | Debug << "post process merge: " << mMergeViewCells << endl;
|
---|
| 293 | Debug << "evaluate view cells: " << mEvaluateViewCells << endl;
|
---|
| 294 | Debug << "sampling type: " << mSamplingType << endl;
|
---|
[1703] | 295 | Debug << "render cost evaluation type: " << sRenderCostEvaluationType << endl;
|
---|
[728] | 296 | Debug << "evaluation sampling type: " << mEvaluationSamplingType << endl;
|
---|
[666] | 297 | Debug << "show visualization: " << mShowVisualization << endl;
|
---|
[697] | 298 | Debug << "filter width: " << mFilterWidth << endl;
|
---|
[710] | 299 | Debug << "sample after subdivision: " << SAMPLE_AFTER_SUBDIVISION << endl;
|
---|
[850] | 300 |
|
---|
| 301 | Debug << "export bounding boxes: " << mExportBboxesForPvs << endl;
|
---|
| 302 | Debug << "export pvs for view cells: " << mExportPvs << endl;
|
---|
[1902] | 303 | Debug << "use kd pvs " << mUseKdPvs << endl;
|
---|
[664] | 304 | Debug << endl;
|
---|
[440] | 305 | }
|
---|
| 306 |
|
---|
[485] | 307 |
|
---|
[440] | 308 | ViewCellsManager::~ViewCellsManager()
|
---|
| 309 | {
|
---|
[1020] | 310 | // HACK: if view cells tree does not
|
---|
[1264] | 311 | // handle view cells, we have to do it here
|
---|
[1020] | 312 | // question: rather create view cells resource manager?
|
---|
[598] | 313 | if (!ViewCellsTreeConstructed())
|
---|
[1141] | 314 | {
|
---|
[598] | 315 | CLEAR_CONTAINER(mViewCells);
|
---|
[1141] | 316 | }
|
---|
[1696] | 317 | else
|
---|
| 318 | {
|
---|
| 319 | DEL_PTR(mViewCellsTree);
|
---|
| 320 | }
|
---|
[1903] | 321 |
|
---|
| 322 | DEL_PTR(mMixtureDistribution);
|
---|
[440] | 323 | }
|
---|
| 324 |
|
---|
[1903] | 325 |
|
---|
[1743] | 326 | Intersectable *
|
---|
| 327 | ViewCellsManager::GetIntersectable(const VssRay &ray, const bool isTermination) const
|
---|
| 328 | {
|
---|
[1902] | 329 | if (mUseKdPvs)
|
---|
| 330 | {
|
---|
| 331 | float area = GetPreprocessor()->mKdTree->GetBox().SurfaceArea()*KD_PVS_AREA;
|
---|
| 332 | KdNode *node = GetPreprocessor()->mKdTree->GetNode(isTermination ?
|
---|
| 333 | ray.mTermination : ray.mOrigin,
|
---|
| 334 | area);
|
---|
| 335 | return GetPreprocessor()->mKdTree->GetOrCreateKdIntersectable(node);
|
---|
| 336 | }
|
---|
| 337 | else
|
---|
| 338 | {
|
---|
| 339 | return isTermination ? ray.mTerminationObject : ray.mOriginObject;
|
---|
| 340 | }
|
---|
[1743] | 341 | }
|
---|
[1221] | 342 |
|
---|
[1902] | 343 |
|
---|
[1737] | 344 | void
|
---|
| 345 | ViewCellsManager::CollectObjects(const AxisAlignedBox3 &box, ObjectContainer &objects)
|
---|
| 346 | {
|
---|
| 347 | GetPreprocessor()->mKdTree->CollectObjects(box, objects);
|
---|
| 348 | }
|
---|
[1613] | 349 |
|
---|
[1221] | 350 | AxisAlignedBox3 ViewCellsManager::GetViewCellBox(ViewCell *vc)
|
---|
[859] | 351 | {
|
---|
| 352 | Mesh *m = vc->GetMesh();
|
---|
| 353 |
|
---|
[1563] | 354 | if (m)
|
---|
| 355 | {
|
---|
| 356 | m->ComputeBoundingBox();
|
---|
| 357 | return m->mBox;
|
---|
[859] | 358 | }
|
---|
[485] | 359 |
|
---|
[859] | 360 | AxisAlignedBox3 box;
|
---|
| 361 | box.Initialize();
|
---|
| 362 |
|
---|
| 363 | if (!vc->IsLeaf()) {
|
---|
| 364 | ViewCellInterior *vci = (ViewCellInterior *) vc;
|
---|
| 365 |
|
---|
| 366 | ViewCellContainer::iterator it = vci->mChildren.begin();
|
---|
| 367 | for (; it != vci->mChildren.end(); ++it) {
|
---|
| 368 | box.Include(GetViewCellBox(*it));
|
---|
| 369 | }
|
---|
| 370 | }
|
---|
| 371 |
|
---|
| 372 | return box;
|
---|
| 373 | }
|
---|
| 374 |
|
---|
[693] | 375 |
|
---|
[574] | 376 | int ViewCellsManager::CastPassSamples(const int samplesPerPass,
|
---|
[1768] | 377 | const vector<int> &strategies,
|
---|
| 378 | VssRayContainer &passSamples
|
---|
| 379 | ) const
|
---|
[527] | 380 | {
|
---|
[1633] | 381 | long startTime = GetTime();
|
---|
[564] | 382 |
|
---|
[1784] | 383 | SimpleRayContainer simpleRays;
|
---|
| 384 |
|
---|
| 385 | simpleRays.reserve(samplesPerPass);
|
---|
| 386 | passSamples.reserve(samplesPerPass * 2); // always creates double rays
|
---|
| 387 |
|
---|
[1701] | 388 | // create one third of each type
|
---|
[1765] | 389 | int castRays = 0;
|
---|
[1701] | 390 |
|
---|
[1765] | 391 | const int numRaysPerPass = samplesPerPass / (int)strategies.size();
|
---|
| 392 | vector<int>::const_iterator iit, iit_end = strategies.end();
|
---|
| 393 |
|
---|
| 394 | for (iit = strategies.begin(); iit != iit_end; ++ iit)
|
---|
| 395 | {
|
---|
[1772] | 396 | const int stype = *iit;
|
---|
[1765] | 397 | const int newRays =
|
---|
| 398 | mPreprocessor->GenerateRays(numRaysPerPass, stype, simpleRays);
|
---|
[1772] | 399 |
|
---|
[1765] | 400 | cout << "cast " << newRays << " rays of strategy " << stype << endl;
|
---|
| 401 | castRays += newRays;
|
---|
[1709] | 402 | }
|
---|
[1701] | 403 |
|
---|
[1784] | 404 | cout << "generated " << samplesPerPass << " samples in "
|
---|
| 405 | << TimeDiff(startTime, GetTime()) * 1e-3 << " secs" << endl;
|
---|
[1221] | 406 |
|
---|
[1633] | 407 | startTime = GetTime();
|
---|
[1784] | 408 |
|
---|
[573] | 409 | // shoot simple ray and add it to importance samples
|
---|
[1520] | 410 | mPreprocessor->CastRays(simpleRays, passSamples, true);
|
---|
[1784] | 411 | cout << "cast " << samplesPerPass << " samples in "
|
---|
| 412 | << TimeDiff(startTime, GetTime()) * 1e-3 << " secs" << endl;
|
---|
[570] | 413 |
|
---|
[574] | 414 | return (int)passSamples.size();
|
---|
| 415 | }
|
---|
[570] | 416 |
|
---|
[574] | 417 |
|
---|
| 418 | /// helper function which destroys rays or copies them into the output ray container
|
---|
[639] | 419 | inline void disposeRays(VssRayContainer &rays, VssRayContainer *outRays)
|
---|
[574] | 420 | {
|
---|
| 421 | cout << "disposing samples ... ";
|
---|
[582] | 422 | long startTime = GetTime();
|
---|
| 423 | int n = (int)rays.size();
|
---|
| 424 |
|
---|
[573] | 425 | if (outRays)
|
---|
[542] | 426 | {
|
---|
[574] | 427 | VssRayContainer::const_iterator it, it_end = rays.end();
|
---|
| 428 | for (it = rays.begin(); it != it_end; ++ it)
|
---|
| 429 | {
|
---|
| 430 | outRays->push_back(*it);
|
---|
| 431 | }
|
---|
[573] | 432 | }
|
---|
| 433 | else
|
---|
| 434 | {
|
---|
[639] | 435 | VssRayContainer::const_iterator it, it_end = rays.end();
|
---|
| 436 | for (it = rays.begin(); it != it_end; ++ it)
|
---|
| 437 | {
|
---|
| 438 | if (!(*it)->IsActive())
|
---|
| 439 | delete (*it);
|
---|
| 440 | }
|
---|
[573] | 441 | }
|
---|
[639] | 442 |
|
---|
[574] | 443 | cout << "finished" << endl;
|
---|
[582] | 444 | Debug << "disposed " << n << " samples in " << TimeDiff(startTime, GetTime()) * 1e-3 << " secs" << endl;
|
---|
[573] | 445 | }
|
---|
[570] | 446 |
|
---|
| 447 |
|
---|
[573] | 448 | int ViewCellsManager::Construct(Preprocessor *preprocessor, VssRayContainer *outRays)
|
---|
| 449 | {
|
---|
| 450 | int numSamples = 0;
|
---|
[1077] | 451 |
|
---|
[573] | 452 | SimpleRayContainer simpleRays;
|
---|
[574] | 453 | VssRayContainer initialSamples;
|
---|
[540] | 454 |
|
---|
[1381] | 455 | // store pointer to preprocessor for further use during construction
|
---|
| 456 | mPreprocessor = preprocessor;
|
---|
| 457 |
|
---|
[1563] | 458 |
|
---|
[1381] | 459 | ///////////////////////////////////////////////////////
|
---|
| 460 | //-- Initial sampling for the construction of the view cell hierarchy.
|
---|
| 461 | //-- We use uniform sampling / box based sampling.
|
---|
| 462 |
|
---|
[752] | 463 | long startTime = GetTime();
|
---|
[1633] | 464 | cout << "view cell construction: casting " << mInitialSamples << " initial samples ... " << endl;
|
---|
[1414] | 465 |
|
---|
[1381] | 466 | // cast initial samples
|
---|
[1778] | 467 |
|
---|
| 468 | // mix of sampling strategies
|
---|
| 469 | vector<int>dummy;
|
---|
| 470 | //dummy.push_back(SamplingStrategy::OBJECT_BASED_DISTRIBUTION);
|
---|
| 471 | //dummy.push_back(SamplingStrategy::SPATIAL_BOX_BASED_DISTRIBUTION);
|
---|
| 472 | //dummy.push_back(SamplingStrategy::REVERSE_OBJECT_BASED_DISTRIBUTION);
|
---|
| 473 |
|
---|
[1773] | 474 | CastPassSamples(mInitialSamples, mStrategies, initialSamples);
|
---|
[1278] | 475 |
|
---|
[1221] | 476 | cout << "finished in " << TimeDiff(startTime, GetTime()) * 1e-3 << " secs" << endl;
|
---|
[574] | 477 |
|
---|
[573] | 478 | // construct view cells
|
---|
[752] | 479 | ConstructSubdivision(preprocessor->mObjects, initialSamples);
|
---|
[540] | 480 |
|
---|
[727] | 481 | // initial samples count for overall samples ...
|
---|
[752] | 482 | numSamples += mInitialSamples;
|
---|
[542] | 483 |
|
---|
[574] | 484 | // rays can be passed or deleted
|
---|
[639] | 485 | disposeRays(initialSamples, outRays);
|
---|
[752] | 486 |
|
---|
| 487 | cout << "time needed for initial construction: "
|
---|
| 488 | << TimeDiff(startTime, GetTime()) * 1e-3 << " secs" << endl;
|
---|
| 489 |
|
---|
| 490 | Debug << "time needed for initial construction: "
|
---|
| 491 | << TimeDiff(startTime, GetTime()) * 1e-3 << " secs" << endl;
|
---|
| 492 |
|
---|
[1444] | 493 | // collect view cells and compute statistics
|
---|
| 494 | ResetViewCells();
|
---|
[752] | 495 |
|
---|
[1444] | 496 |
|
---|
| 497 | ///////////////////
|
---|
| 498 | //-- Initial hierarchy construction finished.
|
---|
[1381] | 499 | //-- We can do some stats and visualization
|
---|
| 500 |
|
---|
[1444] | 501 | if (0)
|
---|
[660] | 502 | {
|
---|
[1444] | 503 | //-- export initial view cell partition
|
---|
[1563] | 504 | Debug << "\nView cells after initial sampling:\n" << mCurrentViewCellsStats << endl;
|
---|
[1416] | 505 |
|
---|
[1414] | 506 | const string filename("viewcells.wrl");
|
---|
| 507 | Exporter *exporter = Exporter::GetExporter(filename.c_str());
|
---|
[712] | 508 |
|
---|
[660] | 509 | if (exporter)
|
---|
| 510 | {
|
---|
[1414] | 511 | cout << "exporting initial view cells (=leaves) to " << filename.c_str() << " ... ";
|
---|
| 512 |
|
---|
[660] | 513 | if (mExportGeometry)
|
---|
[712] | 514 | {
|
---|
[660] | 515 | exporter->ExportGeometry(preprocessor->mObjects);
|
---|
[712] | 516 | }
|
---|
[660] | 517 |
|
---|
[750] | 518 | exporter->SetWireframe();
|
---|
[1760] | 519 | ExportViewCellsForViz(exporter, NULL, mColorCode, GetClipPlane());
|
---|
[660] | 520 |
|
---|
| 521 | delete exporter;
|
---|
[712] | 522 | cout << "finished" << endl;
|
---|
[660] | 523 | }
|
---|
| 524 | }
|
---|
| 525 |
|
---|
[1381] | 526 |
|
---|
[1419] | 527 | //////////////////////
|
---|
[1381] | 528 | //-- Cast some more sampling after initial construction.
|
---|
| 529 | //-- The additional rays can be used to gain
|
---|
| 530 | //-- some more information before the bottom-up merge
|
---|
| 531 | //-- note: guided rays could be used for this task
|
---|
| 532 |
|
---|
[1414] | 533 | // time spent after construction of the initial partition
|
---|
[1381] | 534 | startTime = GetTime();
|
---|
[574] | 535 | const int n = mConstructionSamples; //+initialSamples;
|
---|
[573] | 536 |
|
---|
| 537 | while (numSamples < n)
|
---|
| 538 | {
|
---|
[596] | 539 | cout << "casting " << mSamplesPerPass << " samples of " << n << " ... ";
|
---|
[727] | 540 | Debug << "casting " << mSamplesPerPass << " samples of " << n << " ... ";
|
---|
| 541 |
|
---|
[574] | 542 | VssRayContainer constructionSamples;
|
---|
| 543 |
|
---|
[727] | 544 | // cast new samples
|
---|
[574] | 545 | numSamples += CastPassSamples(mSamplesPerPass,
|
---|
[1773] | 546 | mStrategies,
|
---|
[574] | 547 | constructionSamples);
|
---|
| 548 |
|
---|
| 549 | cout << "finished" << endl;
|
---|
| 550 | cout << "computing sample contribution for " << (int)constructionSamples.size() << " samples ... ";
|
---|
| 551 |
|
---|
[727] | 552 | // computes sample contribution of cast rays TODO: leak?
|
---|
| 553 | if (SAMPLE_AFTER_SUBDIVISION)
|
---|
[605] | 554 | ComputeSampleContributions(constructionSamples, true, false);
|
---|
[712] | 555 |
|
---|
[574] | 556 | cout << "finished" << endl;
|
---|
| 557 |
|
---|
[639] | 558 | disposeRays(constructionSamples, outRays);
|
---|
[574] | 559 | cout << "total samples: " << numSamples << endl;
|
---|
[542] | 560 | }
|
---|
[752] | 561 |
|
---|
[1563] | 562 | if (0)
|
---|
| 563 | {
|
---|
| 564 | ///////////////
|
---|
| 565 | //-- Get stats after the additional sampling step
|
---|
| 566 | //-- and before the bottom-up merge step
|
---|
[570] | 567 |
|
---|
[1563] | 568 | EvaluateViewCellsStats();
|
---|
| 569 | Debug << "\noriginal view cell partition before post process:\n"
|
---|
| 570 | << mCurrentViewCellsStats << endl;
|
---|
| 571 |
|
---|
| 572 | mRenderer->RenderScene();
|
---|
| 573 | SimulationStatistics ss;
|
---|
| 574 | dynamic_cast<RenderSimulator *>(mRenderer)->GetStatistics(ss);
|
---|
[660] | 575 |
|
---|
[1563] | 576 | Debug << ss << endl;
|
---|
| 577 | }
|
---|
[660] | 578 |
|
---|
[1416] | 579 | ////////////////////
|
---|
[1381] | 580 | //-- post processing of the initial construction
|
---|
| 581 | //-- We can bottom-up merge the view cells in this step
|
---|
[1444] | 582 | //-- We can additionally cast some post processing sample rays.
|
---|
| 583 | //-- These rays can be used to store the view cells with the rays
|
---|
[1381] | 584 |
|
---|
| 585 | VssRayContainer postProcessSamples;
|
---|
| 586 | cout << "casting " << mPostProcessSamples << " post processing samples ... ";
|
---|
| 587 |
|
---|
[1773] | 588 | CastPassSamples(mPostProcessSamples, mStrategies, postProcessSamples);
|
---|
[1381] | 589 |
|
---|
| 590 | cout << "finished" << endl;
|
---|
[574] | 591 | cout << "starting post processing and visualization" << endl;
|
---|
| 592 |
|
---|
[1444] | 593 | // store view cells with rays for post processing?
|
---|
[574] | 594 | const bool storeViewCells = true;
|
---|
[605] | 595 |
|
---|
| 596 | if (SAMPLE_AFTER_SUBDIVISION)
|
---|
| 597 | ComputeSampleContributions(postProcessSamples, true, storeViewCells);
|
---|
[663] | 598 |
|
---|
[1381] | 599 | PostProcess(preprocessor->mObjects, postProcessSamples);
|
---|
[570] | 600 |
|
---|
[1414] | 601 | const float secs = TimeDiff(startTime, GetTime()) * 1e-3f;
|
---|
| 602 | cout << "post processing (=merge) finished in " << secs << " secs" << endl;
|
---|
[752] | 603 |
|
---|
[1414] | 604 | Debug << "post processing time: " << secs << endl;
|
---|
[1002] | 605 | disposeRays(postProcessSamples, outRays);
|
---|
| 606 |
|
---|
[1749] | 607 |
|
---|
[1416] | 608 | ////////////////
|
---|
[1381] | 609 | //-- Evaluation of the resulting view cell partition.
|
---|
| 610 | //-- We cast a number of new samples and measure the render cost
|
---|
| 611 |
|
---|
[801] | 612 | if (mEvaluateViewCells)
|
---|
| 613 | {
|
---|
[1145] | 614 | EvalViewCellPartition();
|
---|
[801] | 615 | }
|
---|
[1749] | 616 |
|
---|
[1416] | 617 | /////////////////
|
---|
[1769] | 618 | //-- Show some visualizations
|
---|
[1381] | 619 |
|
---|
[666] | 620 | if (mShowVisualization)
|
---|
| 621 | {
|
---|
[1769] | 622 | if (0)
|
---|
| 623 | {
|
---|
[1773] | 624 | mStrategies.clear();
|
---|
| 625 | mStrategies.push_back(SamplingStrategy::VIEWCELL_BORDER_BASED_DISTRIBUTION);
|
---|
[1769] | 626 | }
|
---|
| 627 |
|
---|
[1633] | 628 | ///////////////
|
---|
[1381] | 629 | //-- visualization rays, e.g., to show some samples in the scene
|
---|
[1633] | 630 |
|
---|
| 631 | VssRayContainer visSamples;
|
---|
| 632 | int numSamples = CastPassSamples(mVisualizationSamples,
|
---|
[1773] | 633 | mStrategies,
|
---|
[1633] | 634 | visSamples);
|
---|
[574] | 635 |
|
---|
[666] | 636 | if (SAMPLE_AFTER_SUBDIVISION)
|
---|
[1633] | 637 | ComputeSampleContributions(visSamples, true, storeViewCells);
|
---|
[574] | 638 |
|
---|
[1444] | 639 | // various visualizations
|
---|
[1633] | 640 | Visualize(preprocessor->mObjects, visSamples);
|
---|
[574] | 641 |
|
---|
[1633] | 642 | disposeRays(visSamples, outRays);
|
---|
[666] | 643 | }
|
---|
[574] | 644 |
|
---|
[1444] | 645 | // recalculate view cells
|
---|
| 646 | EvaluateViewCellsStats();
|
---|
| 647 |
|
---|
[1843] | 648 | if (1) CompressViewCells();
|
---|
| 649 |
|
---|
| 650 | // write view cells to disc
|
---|
| 651 | if (mExportViewCells)
|
---|
| 652 | {
|
---|
| 653 | char filename[100];
|
---|
[1924] | 654 |
|
---|
[1843] | 655 | Environment::GetSingleton()->GetStringValue("ViewCells.filename", filename);
|
---|
| 656 | ExportViewCells(filename, mExportPvs, mPreprocessor->mObjects);
|
---|
| 657 | }
|
---|
| 658 |
|
---|
[573] | 659 | return numSamples;
|
---|
[527] | 660 | }
|
---|
| 661 |
|
---|
[547] | 662 |
|
---|
[1418] | 663 | AxisAlignedPlane *ViewCellsManager::GetClipPlane()
|
---|
[1416] | 664 | {
|
---|
| 665 | return mUseClipPlaneForViz ? &mClipPlaneForViz : NULL;
|
---|
| 666 | }
|
---|
| 667 |
|
---|
| 668 |
|
---|
[752] | 669 | void ViewCellsManager::EvalViewCellHistogram(const string filename,
|
---|
| 670 | const int nViewCells)
|
---|
[728] | 671 | {
|
---|
| 672 | std::ofstream outstream;
|
---|
| 673 | outstream.open(filename.c_str());
|
---|
| 674 |
|
---|
| 675 | ViewCellContainer viewCells;
|
---|
[1771] | 676 | // $$ JB hack - the collect best viewcells does not work?
|
---|
| 677 | #if 1
|
---|
[735] | 678 | mViewCellsTree->CollectBestViewCellSet(viewCells, nViewCells);
|
---|
[1771] | 679 | #else
|
---|
| 680 | viewCells = mViewCells;
|
---|
| 681 | #endif
|
---|
[728] | 682 |
|
---|
| 683 | float maxRenderCost, minRenderCost;
|
---|
[734] | 684 |
|
---|
| 685 | // sort by render cost
|
---|
| 686 | sort(viewCells.begin(), viewCells.end(), ViewCell::SmallerRenderCost);
|
---|
| 687 |
|
---|
| 688 | minRenderCost = viewCells.front()->GetRenderCost();
|
---|
| 689 | maxRenderCost = viewCells.back()->GetRenderCost();
|
---|
| 690 |
|
---|
[991] | 691 | Debug << "histogram min rc: " << minRenderCost << " max rc: " << maxRenderCost << endl;
|
---|
[736] | 692 |
|
---|
[997] | 693 | int histoIntervals;
|
---|
[1004] | 694 | Environment::GetSingleton()->GetIntValue("Preprocessor.histogram.intervals", histoIntervals);
|
---|
[997] | 695 | const int intervals = min(histoIntervals, (int)viewCells.size());
|
---|
[735] | 696 |
|
---|
[997] | 697 | int histoMaxVal;
|
---|
[1004] | 698 | Environment::GetSingleton()->GetIntValue("Preprocessor.histogram.maxValue", histoMaxVal);
|
---|
[1145] | 699 | maxRenderCost = max((float)histoMaxVal, maxRenderCost);
|
---|
[991] | 700 |
|
---|
[997] | 701 |
|
---|
[728] | 702 | const float range = maxRenderCost - minRenderCost;
|
---|
[735] | 703 | const float stepSize = range / (float)intervals;
|
---|
[728] | 704 |
|
---|
[735] | 705 | float currentRenderCost = minRenderCost;//(int)ceil(minRenderCost);
|
---|
| 706 |
|
---|
| 707 | const float totalRenderCost = mViewCellsTree->GetRoot()->GetRenderCost();
|
---|
| 708 | const float totalVol = GetViewSpaceBox().GetVolume();
|
---|
[736] | 709 | //const float totalVol = mViewCellsTree->GetRoot()->GetVolume();
|
---|
[735] | 710 |
|
---|
[736] | 711 | int j = 0;
|
---|
[735] | 712 | int i = 0;
|
---|
| 713 |
|
---|
[734] | 714 | ViewCellContainer::const_iterator it = viewCells.begin(), it_end = viewCells.end();
|
---|
| 715 |
|
---|
[744] | 716 | // count for integral
|
---|
| 717 | float volSum = 0;
|
---|
| 718 | int smallerCostSum = 0;
|
---|
[735] | 719 |
|
---|
[1917] | 720 | // note can skip computations for view cells already
|
---|
| 721 | // evaluated and delete them from vector ...
|
---|
[734] | 722 | while (1)
|
---|
| 723 | {
|
---|
[744] | 724 | // count for histogram value
|
---|
| 725 | float volDif = 0;
|
---|
| 726 | int smallerCostDif = 0;
|
---|
[736] | 727 |
|
---|
[734] | 728 | while ((i < (int)viewCells.size()) && (viewCells[i]->GetRenderCost() < currentRenderCost))
|
---|
| 729 | {
|
---|
[744] | 730 | volSum += viewCells[i]->GetVolume();
|
---|
| 731 | volDif += viewCells[i]->GetVolume();
|
---|
| 732 |
|
---|
[734] | 733 | ++ i;
|
---|
[744] | 734 | ++ smallerCostSum;
|
---|
| 735 | ++ smallerCostDif;
|
---|
[734] | 736 | }
|
---|
[736] | 737 |
|
---|
[744] | 738 | if ((i >= (int)viewCells.size()) || (currentRenderCost >= maxRenderCost))
|
---|
[735] | 739 | break;
|
---|
[736] | 740 |
|
---|
[744] | 741 | const float rcRatio = currentRenderCost / maxRenderCost;
|
---|
| 742 | const float volRatioSum = volSum / totalVol;
|
---|
| 743 | const float volRatioDif = volDif / totalVol;
|
---|
[735] | 744 |
|
---|
[991] | 745 | outstream << "#Pass\n" << j ++ << endl;
|
---|
[736] | 746 | outstream << "#RenderCostRatio\n" << rcRatio << endl;
|
---|
| 747 | outstream << "#WeightedCost\n" << currentRenderCost / totalVol << endl;
|
---|
[744] | 748 | outstream << "#ViewCellsDif\n" << smallerCostDif << endl;
|
---|
| 749 | outstream << "#ViewCellsSum\n" << smallerCostSum << endl;
|
---|
| 750 | outstream << "#VolumeDif\n" << volRatioDif << endl << endl;
|
---|
| 751 | outstream << "#VolumeSum\n" << volRatioSum << endl << endl;
|
---|
[735] | 752 |
|
---|
| 753 | // increase current render cost
|
---|
[734] | 754 | currentRenderCost += stepSize;
|
---|
| 755 | }
|
---|
[735] | 756 |
|
---|
[734] | 757 | outstream.close();
|
---|
| 758 | }
|
---|
| 759 |
|
---|
[735] | 760 |
|
---|
[979] | 761 | ViewCellsManager *ViewCellsManager::LoadViewCells(const string &filename,
|
---|
| 762 | ObjectContainer *objects,
|
---|
[1676] | 763 | bool finalizeViewCells,
|
---|
[979] | 764 | BoundingBoxConverter *bconverter)
|
---|
| 765 |
|
---|
| 766 | {
|
---|
| 767 | ViewCellsParser parser;
|
---|
| 768 | ViewCellsManager *vm = NULL;
|
---|
| 769 |
|
---|
[1616] | 770 | const long startTime = GetTime();
|
---|
| 771 | bool success = parser.ParseViewCellsFile(filename, &vm, objects, bconverter);
|
---|
| 772 |
|
---|
[1715] | 773 | cout<<"viewcells parsed "<<endl<<flush;
|
---|
| 774 |
|
---|
[1616] | 775 | if (success)
|
---|
[979] | 776 | {
|
---|
[1621] | 777 | //vm->ResetViewCells();
|
---|
[1679] | 778 | //hack
|
---|
| 779 | vm->mViewCells.clear();
|
---|
| 780 | ViewCellContainer leaves;
|
---|
| 781 | vm->mViewCellsTree->CollectLeaves(vm->mViewCellsTree->GetRoot(), leaves);
|
---|
[979] | 782 |
|
---|
[1679] | 783 | ViewCellContainer::const_iterator it, it_end = leaves.end();
|
---|
[1621] | 784 |
|
---|
[1679] | 785 | for (it = leaves.begin(); it != it_end; ++ it)
|
---|
| 786 | {
|
---|
| 787 | vm->mViewCells.push_back(*it);
|
---|
| 788 | }
|
---|
[979] | 789 | vm->mViewCellsFinished = true;
|
---|
| 790 | vm->mMaxPvsSize = (int)objects->size();
|
---|
| 791 |
|
---|
| 792 | if (finalizeViewCells)
|
---|
| 793 | {
|
---|
[1444] | 794 | // create the meshes and compute volumes
|
---|
[979] | 795 | vm->FinalizeViewCells(true);
|
---|
[1616] | 796 | // vm->mViewCellsTree->AssignRandomColors();
|
---|
[979] | 797 | }
|
---|
| 798 |
|
---|
| 799 | Debug << (int)vm->mViewCells.size() << " view cells loaded in "
|
---|
| 800 | << TimeDiff(startTime, GetTime()) * 1e-3 << " secs" << endl;
|
---|
| 801 | }
|
---|
| 802 | else
|
---|
| 803 | {
|
---|
| 804 | Debug << "Error: loading view cells failed!" << endl;
|
---|
| 805 | DEL_PTR(vm);
|
---|
| 806 | }
|
---|
| 807 |
|
---|
| 808 | return vm;
|
---|
| 809 | }
|
---|
| 810 |
|
---|
| 811 |
|
---|
| 812 | bool VspBspViewCellsManager::ExportViewCells(const string filename,
|
---|
| 813 | const bool exportPvs,
|
---|
| 814 | const ObjectContainer &objects)
|
---|
| 815 | {
|
---|
[1002] | 816 | if (!ViewCellsConstructed() || !ViewCellsTreeConstructed())
|
---|
[1545] | 817 | {
|
---|
[997] | 818 | return false;
|
---|
[1545] | 819 | }
|
---|
[997] | 820 |
|
---|
[979] | 821 | cout << "exporting view cells to xml ... ";
|
---|
[1264] | 822 |
|
---|
[1201] | 823 | OUT_STREAM stream(filename.c_str());
|
---|
[979] | 824 |
|
---|
| 825 | // for output we need unique ids for each view cell
|
---|
| 826 | CreateUniqueViewCellIds();
|
---|
| 827 |
|
---|
| 828 | stream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"<<endl;
|
---|
| 829 | stream << "<VisibilitySolution>" << endl;
|
---|
| 830 |
|
---|
[1262] | 831 | if (exportPvs)
|
---|
| 832 | {
|
---|
| 833 | //-- export bounding boxes
|
---|
| 834 | stream << "<BoundingBoxes>" << endl;
|
---|
[979] | 835 |
|
---|
[1902] | 836 | if (mUseKdPvs)
|
---|
[1614] | 837 | {
|
---|
[1902] | 838 | vector<KdIntersectable *>::iterator kit, kit_end = GetPreprocessor()->mKdTree->mKdIntersectables.end();
|
---|
| 839 |
|
---|
| 840 | int id = 0;
|
---|
| 841 | for (kit = GetPreprocessor()->mKdTree->mKdIntersectables.begin(); kit != kit_end; ++ kit, ++ id)
|
---|
| 842 | {
|
---|
| 843 | Intersectable *obj = *kit;
|
---|
| 844 | const AxisAlignedBox3 box = obj->GetBox();
|
---|
[1761] | 845 |
|
---|
[1902] | 846 | obj->SetId(id);
|
---|
| 847 |
|
---|
| 848 | stream << "<BoundingBox" << " id=\"" << id << "\""
|
---|
| 849 | << " min=\"" << box.Min().x << " " << box.Min().y << " " << box.Min().z << "\""
|
---|
| 850 | << " max=\"" << box.Max().x << " " << box.Max().y << " " << box.Max().z << "\" />" << endl;
|
---|
| 851 | }
|
---|
[1614] | 852 | }
|
---|
[1902] | 853 | else
|
---|
| 854 | {
|
---|
| 855 | ObjectContainer::const_iterator oit, oit_end = objects.end();
|
---|
[1761] | 856 |
|
---|
[1902] | 857 | for (oit = objects.begin(); oit != oit_end; ++ oit)
|
---|
| 858 | {
|
---|
| 859 | const AxisAlignedBox3 box = (*oit)->GetBox();
|
---|
[979] | 860 |
|
---|
[1902] | 861 | ////////////
|
---|
| 862 | //-- the bounding boxes
|
---|
| 863 |
|
---|
| 864 | stream << "<BoundingBox" << " id=\"" << (*oit)->GetId() << "\""
|
---|
| 865 | << " min=\"" << box.Min().x << " " << box.Min().y << " " << box.Min().z << "\""
|
---|
| 866 | << " max=\"" << box.Max().x << " " << box.Max().y << " " << box.Max().z << "\" />" << endl;
|
---|
| 867 | }
|
---|
[1262] | 868 | }
|
---|
[1902] | 869 |
|
---|
[1262] | 870 | stream << "</BoundingBoxes>" << endl;
|
---|
[1112] | 871 | }
|
---|
[979] | 872 |
|
---|
[1264] | 873 |
|
---|
[1551] | 874 | /////////////
|
---|
[979] | 875 | //-- export the view cells and the pvs
|
---|
| 876 |
|
---|
| 877 | const int numViewCells = mCurrentViewCellsStats.viewCells;
|
---|
| 878 | stream << "<ViewCells number=\"" << numViewCells << "\" >" << endl;
|
---|
[1551] | 879 |
|
---|
[979] | 880 | mViewCellsTree->Export(stream, exportPvs);
|
---|
| 881 |
|
---|
| 882 | stream << "</ViewCells>" << endl;
|
---|
| 883 |
|
---|
| 884 |
|
---|
[1551] | 885 | //////////
|
---|
[1262] | 886 | //-- export the view space hierarchy
|
---|
[979] | 887 |
|
---|
[1262] | 888 | stream << "<ViewSpaceHierarchy type=\"bsp\""
|
---|
| 889 | << " min=\"" << mViewSpaceBox.Min().x << " " << mViewSpaceBox.Min().y << " " << mViewSpaceBox.Min().z << "\""
|
---|
[1264] | 890 | << " max=\"" << mViewSpaceBox.Max().x << " " << mViewSpaceBox.Max().y << " " << mViewSpaceBox.Max().z << "\">" << endl;
|
---|
[1262] | 891 |
|
---|
[979] | 892 | mVspBspTree->Export(stream);
|
---|
[1286] | 893 | stream << "</ViewSpaceHierarchy>" << endl;
|
---|
[979] | 894 |
|
---|
| 895 | stream << "</VisibilitySolution>" << endl;
|
---|
| 896 |
|
---|
| 897 | stream.close();
|
---|
| 898 | cout << "finished" << endl;
|
---|
| 899 |
|
---|
| 900 | return true;
|
---|
| 901 | }
|
---|
| 902 |
|
---|
| 903 |
|
---|
[735] | 904 | void ViewCellsManager::EvalViewCellHistogramForPvsSize(const string filename,
|
---|
| 905 | const int nViewCells)
|
---|
[734] | 906 | {
|
---|
| 907 | std::ofstream outstream;
|
---|
| 908 | outstream.open(filename.c_str());
|
---|
| 909 |
|
---|
| 910 | ViewCellContainer viewCells;
|
---|
[1771] | 911 |
|
---|
| 912 | // $$ JB hack - the collect best viewcells does not work?
|
---|
| 913 | #if 0
|
---|
[735] | 914 | mViewCellsTree->CollectBestViewCellSet(viewCells, nViewCells);
|
---|
[1771] | 915 | #else
|
---|
| 916 | viewCells = mViewCells;
|
---|
| 917 | #endif
|
---|
[1917] | 918 | ViewCellContainer::iterator it = viewCells.begin(), it_end = viewCells.end();
|
---|
| 919 | for (; it != it_end; ++it)
|
---|
| 920 | {
|
---|
| 921 | if (1)
|
---|
| 922 | (*it)->UpdatePvsCost();
|
---|
| 923 | else
|
---|
| 924 | (*it)->SetPvsCost((float)(*it)->GetFilteredPvsSize());
|
---|
[1771] | 925 | }
|
---|
[734] | 926 |
|
---|
[1709] | 927 | float maxPvs, maxVal, minVal;
|
---|
[1771] | 928 |
|
---|
[997] | 929 | // sort by pvs size
|
---|
[735] | 930 | sort(viewCells.begin(), viewCells.end(), ViewCell::SmallerPvs);
|
---|
| 931 |
|
---|
[1771] | 932 | maxPvs = viewCells.back()->GetPvsCost();
|
---|
[997] | 933 | minVal = 0;
|
---|
| 934 |
|
---|
[991] | 935 | // hack: normalize pvs size
|
---|
[997] | 936 | int histoMaxVal;
|
---|
[1917] | 937 | Environment::GetSingleton()->GetIntValue("Preprocessor.histogram.maxValue", histoMaxVal);
|
---|
[1709] | 938 | maxVal = max((float)histoMaxVal, maxPvs);
|
---|
[997] | 939 |
|
---|
[1121] | 940 | Debug << "histogram minpvssize: " << minVal << " maxpvssize: " << maxVal
|
---|
| 941 | << " real maxpvs " << maxPvs << endl;
|
---|
[752] | 942 |
|
---|
[997] | 943 | int histoIntervals;
|
---|
[1004] | 944 | Environment::GetSingleton()->GetIntValue("Preprocessor.histogram.intervals", histoIntervals);
|
---|
[997] | 945 | const int intervals = min(histoIntervals, (int)viewCells.size());
|
---|
[735] | 946 |
|
---|
[1709] | 947 | const float range = maxVal - minVal;
|
---|
| 948 | int stepSize = (int)(range / intervals);
|
---|
[735] | 949 |
|
---|
[997] | 950 | // set step size to avoid endless loop
|
---|
[735] | 951 | if (!stepSize) stepSize = 1;
|
---|
[979] | 952 |
|
---|
[1917] | 953 | Debug << "intervals " << histoIntervals << endl;
|
---|
[979] | 954 | Debug << "stepsize: " << stepSize << endl;
|
---|
[1917] | 955 | cout << "intervals " << histoIntervals << endl;
|
---|
| 956 | cout << "stepsize: " << stepSize << endl;
|
---|
| 957 |
|
---|
[735] | 958 | const float totalRenderCost = mViewCellsTree->GetRoot()->GetRenderCost();
|
---|
| 959 | const float totalVol = GetViewSpaceBox().GetVolume();
|
---|
| 960 |
|
---|
[1709] | 961 | float currentPvs = minVal;
|
---|
[997] | 962 |
|
---|
[735] | 963 | int i = 0;
|
---|
| 964 | int j = 0;
|
---|
[744] | 965 | float volSum = 0;
|
---|
| 966 | int smallerSum = 0;
|
---|
| 967 |
|
---|
[1771] | 968 | it = viewCells.begin();
|
---|
[735] | 969 |
|
---|
[997] | 970 | for (int j = 0; j < intervals; ++ j)
|
---|
[728] | 971 | {
|
---|
[744] | 972 | float volDif = 0;
|
---|
| 973 | int smallerDif = 0;
|
---|
[736] | 974 |
|
---|
[997] | 975 | while ((i < (int)viewCells.size()) &&
|
---|
[1771] | 976 | (viewCells[i]->GetPvsCost() < currentPvs))
|
---|
[735] | 977 | {
|
---|
[744] | 978 | volDif += viewCells[i]->GetVolume();
|
---|
| 979 | volSum += viewCells[i]->GetVolume();
|
---|
[997] | 980 |
|
---|
[735] | 981 | ++ i;
|
---|
[744] | 982 | ++ smallerDif;
|
---|
| 983 | ++ smallerSum;
|
---|
[735] | 984 | }
|
---|
[736] | 985 |
|
---|
[1771] | 986 | // if (0 && (i < (int)viewCells.size()))
|
---|
| 987 | // Debug << "new pvs cost increase: " << mViewCellsTree->GetPvsCost(viewCells[i])
|
---|
| 988 | // << " " << currentPvs << endl;
|
---|
| 989 |
|
---|
[744] | 990 | const float volRatioDif = volDif / totalVol;
|
---|
| 991 | const float volRatioSum = volSum / totalVol;
|
---|
[728] | 992 |
|
---|
[997] | 993 | outstream << "#Pass\n" << j << endl;
|
---|
| 994 | outstream << "#Pvs\n" << currentPvs << endl;
|
---|
[744] | 995 | outstream << "#ViewCellsDif\n" << smallerDif << endl;
|
---|
| 996 | outstream << "#ViewCellsSum\n" << smallerSum << endl;
|
---|
| 997 | outstream << "#VolumeDif\n" << volRatioDif << endl << endl;
|
---|
| 998 | outstream << "#VolumeSum\n" << volRatioSum << endl << endl;
|
---|
[997] | 999 |
|
---|
| 1000 | //-- increase current pvs size to define next interval
|
---|
| 1001 | currentPvs += stepSize;
|
---|
[728] | 1002 | }
|
---|
[991] | 1003 |
|
---|
[735] | 1004 | outstream.close();
|
---|
[728] | 1005 | }
|
---|
| 1006 |
|
---|
[735] | 1007 |
|
---|
[1919] | 1008 | void ViewCellsManager::EvalViewCellHistogramForPvsSize(const string filename,
|
---|
| 1009 | ViewCellContainer &viewCells)
|
---|
| 1010 | {
|
---|
| 1011 | std::ofstream outstream;
|
---|
| 1012 | outstream.open(filename.c_str());
|
---|
| 1013 |
|
---|
| 1014 | float maxPvs, maxVal, minVal;
|
---|
| 1015 |
|
---|
| 1016 | // sort by pvs size
|
---|
| 1017 | sort(viewCells.begin(), viewCells.end(), ViewCell::SmallerPvs);
|
---|
| 1018 |
|
---|
| 1019 | maxPvs = viewCells.back()->GetPvsCost();
|
---|
| 1020 | minVal = 0;
|
---|
| 1021 |
|
---|
| 1022 | // hack: normalize pvs size
|
---|
| 1023 | int histoMaxVal;
|
---|
| 1024 | Environment::GetSingleton()->GetIntValue("Preprocessor.histogram.maxValue", histoMaxVal);
|
---|
| 1025 | maxVal = max((float)histoMaxVal, maxPvs);
|
---|
| 1026 |
|
---|
| 1027 | Debug << "histogram minpvssize: " << minVal << " maxpvssize: " << maxVal
|
---|
| 1028 | << " real maxpvs " << maxPvs << endl;
|
---|
| 1029 |
|
---|
| 1030 | int histoIntervals;
|
---|
| 1031 | Environment::GetSingleton()->GetIntValue("Preprocessor.histogram.intervals", histoIntervals);
|
---|
| 1032 | const int intervals = min(histoIntervals, (int)viewCells.size());
|
---|
| 1033 |
|
---|
| 1034 | const float range = maxVal - minVal;
|
---|
| 1035 | int stepSize = (int)(range / intervals);
|
---|
| 1036 |
|
---|
| 1037 | // set step size to avoid endless loop
|
---|
| 1038 | if (!stepSize) stepSize = 1;
|
---|
| 1039 |
|
---|
| 1040 | Debug << "intervals " << histoIntervals << endl;
|
---|
| 1041 | Debug << "stepsize: " << stepSize << endl;
|
---|
| 1042 | cout << "intervals " << histoIntervals << endl;
|
---|
| 1043 | cout << "stepsize: " << stepSize << endl;
|
---|
| 1044 |
|
---|
| 1045 | const float totalRenderCost = mViewCellsTree->GetRoot()->GetRenderCost();
|
---|
| 1046 | const float totalVol = GetViewSpaceBox().GetVolume();
|
---|
| 1047 |
|
---|
| 1048 | float currentPvs = minVal;
|
---|
| 1049 |
|
---|
| 1050 | int i = 0;
|
---|
| 1051 | int j = 0;
|
---|
| 1052 | float volSum = 0;
|
---|
| 1053 | int smallerSum = 0;
|
---|
| 1054 |
|
---|
| 1055 | //ViewCellContainer::const_iterator it = viewCells.begin(), it_end = viewCells.end();
|
---|
| 1056 |
|
---|
| 1057 | for (int j = 0; j < intervals; ++ j)
|
---|
| 1058 | {
|
---|
| 1059 | float volDif = 0;
|
---|
| 1060 | int smallerDif = 0;
|
---|
| 1061 |
|
---|
| 1062 | while ((i < (int)viewCells.size()) &&
|
---|
| 1063 | (viewCells[i]->GetPvsCost() < currentPvs))
|
---|
| 1064 | {
|
---|
| 1065 | volDif += viewCells[i]->GetVolume();
|
---|
| 1066 | volSum += viewCells[i]->GetVolume();
|
---|
| 1067 |
|
---|
| 1068 | ++ i;
|
---|
| 1069 | ++ smallerDif;
|
---|
| 1070 | ++ smallerSum;
|
---|
| 1071 | }
|
---|
| 1072 |
|
---|
| 1073 | // if (0 && (i < (int)viewCells.size()))
|
---|
| 1074 | // Debug << "new pvs cost increase: " << mViewCellsTree->GetPvsCost(viewCells[i])
|
---|
| 1075 | // << " " << currentPvs << endl;
|
---|
| 1076 |
|
---|
| 1077 | const float volRatioDif = volDif / totalVol;
|
---|
| 1078 | const float volRatioSum = volSum / totalVol;
|
---|
| 1079 |
|
---|
| 1080 | outstream << "#Pass\n" << j << endl;
|
---|
| 1081 | outstream << "#Pvs\n" << currentPvs << endl;
|
---|
| 1082 | outstream << "#ViewCellsDif\n" << smallerDif << endl;
|
---|
| 1083 | outstream << "#ViewCellsSum\n" << smallerSum << endl;
|
---|
| 1084 | outstream << "#VolumeDif\n" << volRatioDif << endl << endl;
|
---|
| 1085 | outstream << "#VolumeSum\n" << volRatioSum << endl << endl;
|
---|
| 1086 |
|
---|
| 1087 | //-- increase current pvs size to define next interval
|
---|
| 1088 | currentPvs += stepSize;
|
---|
| 1089 | }
|
---|
| 1090 |
|
---|
| 1091 | outstream.close();
|
---|
| 1092 | }
|
---|
| 1093 |
|
---|
| 1094 |
|
---|
[1002] | 1095 | bool ViewCellsManager::GetExportPvs() const
|
---|
| 1096 | {
|
---|
| 1097 | return mExportPvs;
|
---|
| 1098 | }
|
---|
| 1099 |
|
---|
| 1100 |
|
---|
[1580] | 1101 | void ViewCellsManager::ResetPvs()
|
---|
| 1102 | {
|
---|
| 1103 | if (ViewCellsTreeConstructed())
|
---|
| 1104 | {
|
---|
| 1105 | mViewCellsTree->ResetPvs();
|
---|
| 1106 | }
|
---|
| 1107 | else
|
---|
| 1108 | {
|
---|
| 1109 | cout << "view cells tree not constructed" << endl;
|
---|
| 1110 | }
|
---|
| 1111 | }
|
---|
| 1112 |
|
---|
| 1113 |
|
---|
[1679] | 1114 | void ViewCellsManager::ExportStats(const string &fileName)
|
---|
| 1115 | {
|
---|
| 1116 | mViewCellsTree->ExportStats(fileName);
|
---|
| 1117 | }
|
---|
| 1118 |
|
---|
| 1119 |
|
---|
[1145] | 1120 | void ViewCellsManager::EvalViewCellPartition()
|
---|
[660] | 1121 | {
|
---|
| 1122 | int samplesPerPass;
|
---|
| 1123 | int numSamples;
|
---|
| 1124 | int castSamples = 0;
|
---|
[1570] | 1125 | char str[64];
|
---|
[1695] | 1126 | int oldSamples = 0;
|
---|
[660] | 1127 |
|
---|
[1695] | 1128 | int samplesForStats;
|
---|
| 1129 |
|
---|
[1004] | 1130 | Environment::GetSingleton()->GetIntValue("ViewCells.Evaluation.samplesPerPass", samplesPerPass);
|
---|
[1695] | 1131 | Environment::GetSingleton()->GetIntValue("ViewCells.Evaluation.samplesForStats", samplesForStats);
|
---|
[1004] | 1132 | Environment::GetSingleton()->GetIntValue("ViewCells.Evaluation.samples", numSamples);
|
---|
[660] | 1133 |
|
---|
[664] | 1134 | char statsPrefix[100];
|
---|
[1004] | 1135 | Environment::GetSingleton()->GetStringValue("ViewCells.Evaluation.statsPrefix", statsPrefix);
|
---|
[663] | 1136 |
|
---|
[664] | 1137 | Debug << "view cell evaluation samples per pass: " << samplesPerPass << endl;
|
---|
| 1138 | Debug << "view cell evaluation samples: " << numSamples << endl;
|
---|
| 1139 | Debug << "view cell stats prefix: " << statsPrefix << endl;
|
---|
| 1140 |
|
---|
[801] | 1141 | cout << "reseting pvs ... ";
|
---|
| 1142 |
|
---|
[1145] | 1143 | const bool startFromZero = true;
|
---|
[801] | 1144 |
|
---|
[666] | 1145 | // reset pvs and start over from zero
|
---|
| 1146 | if (startFromZero)
|
---|
| 1147 | {
|
---|
| 1148 | mViewCellsTree->ResetPvs();
|
---|
| 1149 | }
|
---|
[1145] | 1150 | else // start from current sampless
|
---|
[666] | 1151 | {
|
---|
[1145] | 1152 | // statistics before casting more samples
|
---|
[666] | 1153 | cout << "compute new statistics ... ";
|
---|
[1570] | 1154 | sprintf(str, "-%09d-eval.log", castSamples);
|
---|
| 1155 | string fName = string(statsPrefix) + string(str);
|
---|
[666] | 1156 |
|
---|
| 1157 | mViewCellsTree->ExportStats(fName);
|
---|
| 1158 | cout << "finished" << endl;
|
---|
| 1159 | }
|
---|
[1570] | 1160 |
|
---|
[744] | 1161 | cout << "finished" << endl;
|
---|
[1178] | 1162 | cout << "Evaluating view cell partition ... " << endl;
|
---|
[744] | 1163 |
|
---|
[660] | 1164 | while (castSamples < numSamples)
|
---|
[1686] | 1165 | {
|
---|
| 1166 | ///////////////
|
---|
| 1167 | //-- we have to use uniform sampling strategy for construction rays
|
---|
| 1168 |
|
---|
[664] | 1169 | VssRayContainer evaluationSamples;
|
---|
[1686] | 1170 | const int samplingType = mEvaluationSamplingType;
|
---|
[663] | 1171 |
|
---|
[1004] | 1172 | long startTime = GetTime();
|
---|
| 1173 |
|
---|
| 1174 | cout << "casting " << samplesPerPass << " samples ... ";
|
---|
| 1175 | Debug << "casting " << samplesPerPass << " samples ... ";
|
---|
| 1176 |
|
---|
[1773] | 1177 | CastPassSamples(samplesPerPass, mStrategies, evaluationSamples);
|
---|
[664] | 1178 |
|
---|
| 1179 | castSamples += samplesPerPass;
|
---|
| 1180 |
|
---|
[1004] | 1181 | Real timeDiff = TimeDiff(startTime, GetTime());
|
---|
[1695] | 1182 |
|
---|
| 1183 | cout << "finished in " << timeDiff * 1e-3f << " secs" << endl;
|
---|
[1004] | 1184 | cout << "computing sample contributions of " << (int)evaluationSamples.size() << " samples ... ";
|
---|
[1695] | 1185 |
|
---|
| 1186 | Debug << "finished in " << timeDiff * 1e-3f << " secs" << endl;
|
---|
[1004] | 1187 | Debug << "computing sample contributions of " << (int)evaluationSamples.size() << " samples ... ";
|
---|
| 1188 |
|
---|
| 1189 | startTime = GetTime();
|
---|
| 1190 |
|
---|
[664] | 1191 | ComputeSampleContributions(evaluationSamples, true, false);
|
---|
| 1192 |
|
---|
[1004] | 1193 | timeDiff = TimeDiff(startTime, GetTime());
|
---|
| 1194 | cout << "finished in " << timeDiff * 1e-3 << " secs" << endl;
|
---|
| 1195 | Debug << "finished in " << timeDiff * 1e-3 << " secs" << endl;
|
---|
[664] | 1196 |
|
---|
[1695] | 1197 | if ((castSamples >= samplesForStats + oldSamples) || (castSamples >= numSamples))
|
---|
| 1198 | {
|
---|
| 1199 | oldSamples += samplesForStats;
|
---|
[1686] | 1200 |
|
---|
[1695] | 1201 | ///////////
|
---|
| 1202 | //-- output stats
|
---|
[1686] | 1203 |
|
---|
[1695] | 1204 | sprintf(str, "-%09d-eval.log", castSamples);
|
---|
| 1205 | string fileName = string(statsPrefix) + string(str);
|
---|
[1686] | 1206 |
|
---|
[1695] | 1207 | ///////////////
|
---|
| 1208 | //-- propagate pvs or pvs size information
|
---|
[1586] | 1209 |
|
---|
[1695] | 1210 | startTime = GetTime();
|
---|
| 1211 | ObjectPvs pvs;
|
---|
[664] | 1212 |
|
---|
[1709] | 1213 | cout << "updating pvs for evaluation ... " << endl;
|
---|
[664] | 1214 |
|
---|
[1695] | 1215 | UpdatePvsForEvaluation(mViewCellsTree->GetRoot(), pvs);
|
---|
| 1216 |
|
---|
| 1217 | timeDiff = TimeDiff(startTime, GetTime());
|
---|
| 1218 | cout << "finished updating the pvs in " << timeDiff * 1e-3 << " secs" << endl;
|
---|
| 1219 | Debug << "pvs evaluated in " << timeDiff * 1e-3 << " secs" << endl;
|
---|
| 1220 |
|
---|
| 1221 | startTime = GetTime();
|
---|
| 1222 | cout << "compute new statistics ... " << endl;
|
---|
| 1223 |
|
---|
| 1224 | ExportStats(fileName);
|
---|
| 1225 |
|
---|
| 1226 | timeDiff = TimeDiff(startTime, GetTime());
|
---|
| 1227 | cout << "finished in " << timeDiff * 1e-3 << " secs" << endl;
|
---|
| 1228 | Debug << "statistis computed in " << timeDiff * 1e-3 << " secs" << endl;
|
---|
| 1229 | }
|
---|
| 1230 |
|
---|
[664] | 1231 | disposeRays(evaluationSamples, NULL);
|
---|
[660] | 1232 | }
|
---|
[728] | 1233 |
|
---|
[997] | 1234 |
|
---|
[1570] | 1235 | ////////////
|
---|
[997] | 1236 | //-- histogram
|
---|
| 1237 |
|
---|
[1695] | 1238 | const int numLeaves = mViewCellsTree->GetNumInitialViewCells(mViewCellsTree->GetRoot());
|
---|
[735] | 1239 | bool useHisto;
|
---|
[997] | 1240 | int histoStepSize;
|
---|
[693] | 1241 |
|
---|
[1004] | 1242 | Environment::GetSingleton()->GetBoolValue("ViewCells.Evaluation.histogram", useHisto);
|
---|
| 1243 | Environment::GetSingleton()->GetIntValue("ViewCells.Evaluation.histoStepSize", histoStepSize);
|
---|
[728] | 1244 |
|
---|
[735] | 1245 | if (useHisto)
|
---|
[734] | 1246 | {
|
---|
[735] | 1247 | // evaluate view cells in a histogram
|
---|
| 1248 | char s[64];
|
---|
| 1249 |
|
---|
[997] | 1250 | for (int pass = histoStepSize; pass <= numLeaves; pass += histoStepSize)
|
---|
[744] | 1251 | {
|
---|
[997] | 1252 | string filename;
|
---|
[744] | 1253 |
|
---|
[997] | 1254 | cout << "computing histogram for " << pass << " view cells" << endl;
|
---|
| 1255 | #if 0
|
---|
[744] | 1256 | //-- evaluate histogram for render cost
|
---|
| 1257 | sprintf(s, "-%09d-histo.log", pass);
|
---|
[997] | 1258 | filename = string(statsPrefix) + string(s);
|
---|
[744] | 1259 |
|
---|
| 1260 | EvalViewCellHistogram(filename, pass);
|
---|
| 1261 |
|
---|
[997] | 1262 | #endif
|
---|
[744] | 1263 | //////////////////////////////////////////
|
---|
[752] | 1264 | //-- evaluate histogram for pvs size
|
---|
[744] | 1265 |
|
---|
| 1266 | cout << "computing pvs histogram for " << pass << " view cells" << endl;
|
---|
| 1267 |
|
---|
| 1268 | sprintf(s, "-%09d-histo-pvs.log", pass);
|
---|
| 1269 | filename = string(statsPrefix) + string(s);
|
---|
| 1270 |
|
---|
| 1271 | EvalViewCellHistogramForPvsSize(filename, pass);
|
---|
| 1272 | }
|
---|
[734] | 1273 | }
|
---|
[660] | 1274 | }
|
---|
| 1275 |
|
---|
[704] | 1276 |
|
---|
| 1277 | inline float EvalMergeCost(ViewCell *root, ViewCell *candidate)
|
---|
[703] | 1278 | {
|
---|
[704] | 1279 | return root->GetPvs().GetPvsHomogenity(candidate->GetPvs());
|
---|
| 1280 | }
|
---|
[660] | 1281 |
|
---|
[703] | 1282 |
|
---|
[1145] | 1283 | /// Returns index of the best view cells of the neighborhood
|
---|
[1707] | 1284 | static int GetBestViewCellIdx(ViewCell *root, const ViewCellContainer &neighborhood)
|
---|
[704] | 1285 | {
|
---|
[705] | 1286 | int bestViewCellIdx = 0;
|
---|
[703] | 1287 |
|
---|
[704] | 1288 | float mergeCost = Limits::Infinity;
|
---|
| 1289 | int i = 0;
|
---|
[703] | 1290 |
|
---|
[734] | 1291 | ViewCellContainer::const_iterator vit, vit_end = neighborhood.end();
|
---|
[703] | 1292 |
|
---|
[734] | 1293 | for (vit = neighborhood.begin(); vit != vit_end; ++ vit, ++ i)
|
---|
[703] | 1294 | {
|
---|
[734] | 1295 | const float mc = EvalMergeCost(root, *vit);
|
---|
[705] | 1296 |
|
---|
| 1297 | if (mc < mergeCost)
|
---|
[704] | 1298 | {
|
---|
| 1299 | mergeCost = mc;
|
---|
| 1300 | bestViewCellIdx = i;
|
---|
[703] | 1301 | }
|
---|
[704] | 1302 | }
|
---|
[703] | 1303 |
|
---|
[704] | 1304 | return bestViewCellIdx;
|
---|
| 1305 | }
|
---|
[703] | 1306 |
|
---|
| 1307 |
|
---|
[728] | 1308 | void ViewCellsManager::SetMaxFilterSize(const int size)
|
---|
| 1309 | {
|
---|
| 1310 | mMaxFilterSize = size;
|
---|
| 1311 | }
|
---|
| 1312 |
|
---|
| 1313 |
|
---|
[1703] | 1314 | float ViewCellsManager::EvalRenderCost(Intersectable *obj) //const
|
---|
[728] | 1315 | {
|
---|
[1703] | 1316 | switch (sRenderCostEvaluationType)
|
---|
[728] | 1317 | {
|
---|
| 1318 | case PER_OBJECT:
|
---|
[752] | 1319 | return 1.0f;
|
---|
[728] | 1320 |
|
---|
| 1321 | case PER_TRIANGLE:
|
---|
[1703] | 1322 | {
|
---|
[1701] | 1323 | return (float)obj->NumberOfFaces();
|
---|
[728] | 1324 | }
|
---|
| 1325 | default:
|
---|
[752] | 1326 | cout << "default" << endl;
|
---|
| 1327 | return 1.0f;
|
---|
[728] | 1328 | }
|
---|
| 1329 |
|
---|
| 1330 | // should not come here
|
---|
[752] | 1331 | return 0.0f;
|
---|
[728] | 1332 | }
|
---|
| 1333 |
|
---|
| 1334 |
|
---|
[704] | 1335 | ViewCell *ViewCellsManager::ConstructLocalMergeTree(ViewCell *currentViewCell,
|
---|
| 1336 | const ViewCellContainer &viewCells)
|
---|
| 1337 | {
|
---|
| 1338 | ViewCell *root = currentViewCell;
|
---|
| 1339 | ViewCellContainer neighborhood = viewCells;
|
---|
[703] | 1340 |
|
---|
[704] | 1341 | ViewCellContainer::const_iterator it, it_end = neighborhood.end();
|
---|
[703] | 1342 |
|
---|
[704] | 1343 | const int n = min(mMaxFilterSize, (int)neighborhood.size());
|
---|
[1545] | 1344 |
|
---|
| 1345 | /////////////////
|
---|
[704] | 1346 | //-- use priority queue to merge leaf pairs
|
---|
[1545] | 1347 |
|
---|
[704] | 1348 | for (int nMergedViewCells = 0; nMergedViewCells < n; ++ nMergedViewCells)
|
---|
[703] | 1349 | {
|
---|
[704] | 1350 | const int bestViewCellIdx = GetBestViewCellIdx(root, neighborhood);
|
---|
[703] | 1351 |
|
---|
[704] | 1352 | ViewCell *bestViewCell = neighborhood[bestViewCellIdx];
|
---|
[706] | 1353 |
|
---|
[704] | 1354 | // remove from vector
|
---|
| 1355 | swap(neighborhood[bestViewCellIdx], neighborhood.back());
|
---|
| 1356 | neighborhood.pop_back();
|
---|
[705] | 1357 |
|
---|
[704] | 1358 | if (!bestViewCell || !root)
|
---|
[1545] | 1359 | cout << "warning!!" << endl;
|
---|
[705] | 1360 |
|
---|
[704] | 1361 | // create new root of the hierarchy
|
---|
| 1362 | root = MergeViewCells(root, bestViewCell);
|
---|
[703] | 1363 | }
|
---|
| 1364 |
|
---|
[704] | 1365 | return root;
|
---|
[703] | 1366 | }
|
---|
| 1367 |
|
---|
[704] | 1368 |
|
---|
[713] | 1369 | struct SortableViewCellEntry {
|
---|
| 1370 |
|
---|
[1174] | 1371 | SortableViewCellEntry() {}
|
---|
| 1372 | SortableViewCellEntry(const float v, ViewCell *cell):mValue(v), mViewCell(cell) {}
|
---|
[713] | 1373 |
|
---|
[1174] | 1374 | float mValue;
|
---|
| 1375 | ViewCell *mViewCell;
|
---|
| 1376 |
|
---|
| 1377 | friend bool operator<(const SortableViewCellEntry &a, const SortableViewCellEntry &b) {
|
---|
| 1378 | return a.mValue < b.mValue;
|
---|
| 1379 | }
|
---|
[713] | 1380 | };
|
---|
| 1381 |
|
---|
[1174] | 1382 |
|
---|
| 1383 | ViewCell * ViewCellsManager::ConstructLocalMergeTree2(ViewCell *currentViewCell,
|
---|
| 1384 | const ViewCellContainer &viewCells)
|
---|
[713] | 1385 | {
|
---|
| 1386 |
|
---|
| 1387 | vector<SortableViewCellEntry> neighborhood(viewCells.size());
|
---|
| 1388 | int i, j;
|
---|
| 1389 | for (i = 0, j = 0; i < viewCells.size(); i++) {
|
---|
| 1390 | if (viewCells[i] != currentViewCell)
|
---|
| 1391 | neighborhood[j++] = SortableViewCellEntry(
|
---|
| 1392 | EvalMergeCost(currentViewCell, viewCells[i]),
|
---|
| 1393 | viewCells[i]);
|
---|
| 1394 | }
|
---|
| 1395 | neighborhood.resize(j);
|
---|
| 1396 |
|
---|
| 1397 | sort(neighborhood.begin(), neighborhood.end());
|
---|
| 1398 |
|
---|
| 1399 | ViewCell *root = currentViewCell;
|
---|
| 1400 |
|
---|
| 1401 | vector<SortableViewCellEntry>::const_iterator it, it_end = neighborhood.end();
|
---|
| 1402 |
|
---|
| 1403 | const int n = min(mMaxFilterSize, (int)neighborhood.size());
|
---|
| 1404 | //-- use priority queue to merge leaf pairs
|
---|
| 1405 |
|
---|
| 1406 | //cout << "neighborhood: " << neighborhood.size() << endl;
|
---|
| 1407 | for (int nMergedViewCells = 0; nMergedViewCells < n; ++ nMergedViewCells)
|
---|
[728] | 1408 | {
|
---|
[713] | 1409 | ViewCell *bestViewCell = neighborhood[nMergedViewCells].mViewCell;
|
---|
| 1410 | //cout <<nMergedViewCells<<":"<<"homogenity=" <<neighborhood[nMergedViewCells].mValue<<endl;
|
---|
| 1411 | // create new root of the hierarchy
|
---|
| 1412 | root = MergeViewCells(root, bestViewCell);
|
---|
| 1413 | // set negative cost so that this view cell gets deleted
|
---|
| 1414 | root->SetMergeCost(-1.0f);
|
---|
[728] | 1415 | }
|
---|
[713] | 1416 |
|
---|
| 1417 | return root;
|
---|
| 1418 | }
|
---|
| 1419 |
|
---|
| 1420 | void
|
---|
| 1421 | ViewCellsManager::DeleteLocalMergeTree(ViewCell *vc
|
---|
| 1422 | ) const
|
---|
| 1423 | {
|
---|
[1586] | 1424 | if (!vc->IsLeaf() && vc->GetMergeCost() < 0.0f)
|
---|
| 1425 | {
|
---|
| 1426 | ViewCellInterior *vci = (ViewCellInterior *) vc;
|
---|
| 1427 | ViewCellContainer::const_iterator it, it_end = vci->mChildren.end();
|
---|
| 1428 |
|
---|
| 1429 | for (it = vci->mChildren.begin(); it != it_end; ++ it)
|
---|
| 1430 | DeleteLocalMergeTree(*it);
|
---|
| 1431 |
|
---|
| 1432 | vci->mChildren.clear();
|
---|
| 1433 |
|
---|
| 1434 | delete vci;
|
---|
[713] | 1435 | }
|
---|
| 1436 | }
|
---|
| 1437 |
|
---|
[1021] | 1438 |
|
---|
[564] | 1439 | bool ViewCellsManager::CheckValidity(ViewCell *vc,
|
---|
| 1440 | int minPvsSize,
|
---|
[562] | 1441 | int maxPvsSize) const
|
---|
[547] | 1442 | {
|
---|
[569] | 1443 |
|
---|
[1707] | 1444 | if ((vc->GetPvs().EvalPvsCost() > maxPvsSize) ||
|
---|
| 1445 | (vc->GetPvs().EvalPvsCost() < minPvsSize))
|
---|
[564] | 1446 | {
|
---|
[710] | 1447 | return false;
|
---|
[561] | 1448 | }
|
---|
[570] | 1449 |
|
---|
[710] | 1450 | return true;
|
---|
[547] | 1451 | }
|
---|
| 1452 |
|
---|
| 1453 |
|
---|
[710] | 1454 | int ViewCellsManager::ComputeBoxIntersections(const AxisAlignedBox3 &box,
|
---|
| 1455 | ViewCellContainer &viewCells) const
|
---|
| 1456 | {
|
---|
| 1457 | return 0;
|
---|
| 1458 | };
|
---|
| 1459 |
|
---|
[1021] | 1460 |
|
---|
[697] | 1461 | AxisAlignedBox3 ViewCellsManager::GetFilterBBox(const Vector3 &viewPoint,
|
---|
| 1462 | const float width) const
|
---|
| 1463 | {
|
---|
[746] | 1464 | float w = Magnitude(mViewSpaceBox.Size())*width;
|
---|
| 1465 | Vector3 min = viewPoint - w * 0.5f;
|
---|
| 1466 | Vector3 max = viewPoint + w * 0.5f;
|
---|
| 1467 |
|
---|
| 1468 | return AxisAlignedBox3(min, max);
|
---|
[697] | 1469 | }
|
---|
| 1470 |
|
---|
| 1471 |
|
---|
[904] | 1472 | void ViewCellsManager::GetPrVS(const Vector3 &viewPoint,
|
---|
| 1473 | PrVs &prvs,
|
---|
| 1474 | const float filterWidth)
|
---|
[697] | 1475 | {
|
---|
[1594] | 1476 | ViewCell *currentViewCell = GetViewCell(viewPoint);
|
---|
[1112] | 1477 |
|
---|
[1594] | 1478 | if (mMaxFilterSize < 1) {
|
---|
| 1479 | prvs.mViewCell = currentViewCell;
|
---|
| 1480 | return;
|
---|
| 1481 | }
|
---|
| 1482 |
|
---|
| 1483 | const AxisAlignedBox3 box = GetFilterBBox(viewPoint, filterWidth);
|
---|
| 1484 |
|
---|
| 1485 | if (currentViewCell)
|
---|
[1545] | 1486 | {
|
---|
[1594] | 1487 | ViewCellContainer viewCells;
|
---|
| 1488 | ComputeBoxIntersections(box, viewCells);
|
---|
| 1489 |
|
---|
| 1490 | ViewCell *root = ConstructLocalMergeTree2(currentViewCell, viewCells);
|
---|
| 1491 | prvs.mViewCell = root;
|
---|
| 1492 |
|
---|
[1545] | 1493 | }
|
---|
[1594] | 1494 | else
|
---|
[1545] | 1495 | {
|
---|
[1594] | 1496 | prvs.mViewCell = NULL;
|
---|
| 1497 | //prvs.mPvs = root->GetPvs();
|
---|
[1545] | 1498 | }
|
---|
[697] | 1499 | }
|
---|
| 1500 |
|
---|
| 1501 |
|
---|
[581] | 1502 | bool ViewCellsManager::ViewCellsTreeConstructed() const
|
---|
| 1503 | {
|
---|
[1002] | 1504 | return (mViewCellsTree && mViewCellsTree->GetRoot());
|
---|
[581] | 1505 | }
|
---|
| 1506 |
|
---|
| 1507 |
|
---|
[564] | 1508 | void ViewCellsManager::SetValidity(ViewCell *vc,
|
---|
| 1509 | int minPvs,
|
---|
[562] | 1510 | int maxPvs) const
|
---|
| 1511 | {
|
---|
| 1512 | vc->SetValid(CheckValidity(vc, minPvs, maxPvs));
|
---|
| 1513 | }
|
---|
| 1514 |
|
---|
[577] | 1515 |
|
---|
[569] | 1516 | void
|
---|
| 1517 | ViewCellsManager::SetValidity(
|
---|
[570] | 1518 | int minPvsSize,
|
---|
[569] | 1519 | int maxPvsSize) const
|
---|
| 1520 | {
|
---|
[991] | 1521 | ViewCellContainer::const_iterator it, it_end = mViewCells.end();
|
---|
[570] | 1522 |
|
---|
[991] | 1523 |
|
---|
| 1524 | for (it = mViewCells.begin(); it != it_end; ++ it)
|
---|
| 1525 | {
|
---|
| 1526 | SetValidity(*it, minPvsSize, maxPvsSize);
|
---|
| 1527 | }
|
---|
[569] | 1528 | }
|
---|
[562] | 1529 |
|
---|
[569] | 1530 | void
|
---|
| 1531 | ViewCellsManager::SetValidityPercentage(
|
---|
| 1532 | const float minValid,
|
---|
| 1533 | const float maxValid
|
---|
| 1534 | )
|
---|
| 1535 | {
|
---|
[1761] | 1536 | ObjectPvs dummyPvs;
|
---|
| 1537 | // update pvs sizes
|
---|
| 1538 | for (int i = 0; i < (int)mViewCells.size(); ++ i) {
|
---|
| 1539 | UpdatePvsForEvaluation(mViewCells[i], dummyPvs);
|
---|
| 1540 | }
|
---|
| 1541 |
|
---|
| 1542 | sort(mViewCells.begin(), mViewCells.end(), ViewCell::SmallerPvs);
|
---|
| 1543 |
|
---|
| 1544 | int start = (int)(mViewCells.size() * minValid);
|
---|
| 1545 | int end = (int)(mViewCells.size() * maxValid);
|
---|
| 1546 |
|
---|
| 1547 | for (int i = 0; i < (int)mViewCells.size(); ++ i)
|
---|
[997] | 1548 | {
|
---|
[1761] | 1549 | // cout<<"pvs:"<<mViewCells[i]->GetCachedPvsCost()<<endl;
|
---|
| 1550 | mViewCells[i]->SetValid(i >= start && i <= end);
|
---|
[997] | 1551 | }
|
---|
[569] | 1552 | }
|
---|
| 1553 |
|
---|
[1148] | 1554 |
|
---|
[991] | 1555 | int ViewCellsManager::CountValidViewcells() const
|
---|
[569] | 1556 | {
|
---|
[991] | 1557 | ViewCellContainer::const_iterator it, it_end = mViewCells.end();
|
---|
| 1558 | int valid = 0;
|
---|
| 1559 |
|
---|
| 1560 | for (it = mViewCells.begin(); it != it_end; ++ it)
|
---|
| 1561 | {
|
---|
| 1562 | if ((*it)->GetValid())
|
---|
| 1563 | ++ valid;
|
---|
| 1564 | }
|
---|
| 1565 |
|
---|
| 1566 | return valid;
|
---|
[569] | 1567 | }
|
---|
| 1568 |
|
---|
[577] | 1569 |
|
---|
[1545] | 1570 | bool ViewCellsManager::LoadViewCellsGeometry(const string filename,
|
---|
| 1571 | const bool extrudeBaseTriangles)
|
---|
[440] | 1572 | {
|
---|
[1545] | 1573 | /// we use predefined view cells from now on
|
---|
| 1574 | mUsePredefinedViewCells = true;
|
---|
[440] | 1575 | X3dParser parser;
|
---|
[1545] | 1576 |
|
---|
| 1577 | if (extrudeBaseTriangles)
|
---|
| 1578 | {
|
---|
| 1579 | Environment::GetSingleton()->GetFloatValue("ViewCells.height", parser.mViewCellHeight);
|
---|
[1563] | 1580 | const bool success = parser.ParseFile(filename, *this);
|
---|
| 1581 |
|
---|
| 1582 | if (!success)
|
---|
| 1583 | return false;
|
---|
[1545] | 1584 | }
|
---|
| 1585 | else
|
---|
| 1586 | {
|
---|
| 1587 | // hack: use standard mesh loading
|
---|
| 1588 | // create temporary scene graph for loading the view cells geometry
|
---|
[1563] | 1589 | // note: delete the meshes as they are created two times for transformed mesh instances.
|
---|
[1545] | 1590 | SceneGraphNode *root = new SceneGraphNode();
|
---|
[1563] | 1591 | const bool success = parser.ParseFile(filename, root, true);
|
---|
| 1592 |
|
---|
| 1593 | if (!success)
|
---|
[1545] | 1594 | {
|
---|
[1563] | 1595 | DEL_PTR(root);
|
---|
| 1596 | return false;
|
---|
| 1597 | }
|
---|
| 1598 |
|
---|
| 1599 | ObjectContainer::const_iterator oit, oit_end = root->mGeometry.end();
|
---|
| 1600 |
|
---|
| 1601 | for (oit = root->mGeometry.begin(); oit != oit_end; ++ oit)
|
---|
| 1602 | {
|
---|
| 1603 | Mesh *mesh;
|
---|
| 1604 | if ((*oit)->Type() == Intersectable::TRANSFORMED_MESH_INSTANCE)
|
---|
[1545] | 1605 | {
|
---|
[1563] | 1606 | TransformedMeshInstance *mit = dynamic_cast<TransformedMeshInstance *>(*oit);
|
---|
| 1607 | mesh = MeshManager::GetSingleton()->CreateResource();
|
---|
| 1608 | mit->GetTransformedMesh(*mesh);
|
---|
[1545] | 1609 | }
|
---|
[1563] | 1610 | else if ((*oit)->Type() == Intersectable::MESH_INSTANCE)
|
---|
| 1611 | {
|
---|
| 1612 | MeshInstance *mit = dynamic_cast<MeshInstance *>(*oit);
|
---|
| 1613 | mesh = mit->GetMesh();
|
---|
| 1614 | }
|
---|
| 1615 | mesh->ComputeBoundingBox();
|
---|
| 1616 | mViewCells.push_back(GenerateViewCell(mesh));
|
---|
[1545] | 1617 | }
|
---|
[1563] | 1618 |
|
---|
[1545] | 1619 | DEL_PTR(root);
|
---|
| 1620 | }
|
---|
[503] | 1621 |
|
---|
[1563] | 1622 | // set view space box to bounding box of the view cells
|
---|
| 1623 | AxisAlignedBox3 bbox;
|
---|
| 1624 | bbox.Initialize();
|
---|
| 1625 | ViewCellContainer::iterator it = mViewCells.begin(), it_end = mViewCells.end();
|
---|
| 1626 |
|
---|
| 1627 | for (; it != it_end; ++ it)
|
---|
[1545] | 1628 | {
|
---|
[1563] | 1629 | bbox.Include((*it)->GetMesh()->mBox);
|
---|
[1545] | 1630 | }
|
---|
[503] | 1631 |
|
---|
[1563] | 1632 | SetViewSpaceBox(bbox);
|
---|
| 1633 | cout << "view space box: " << bbox << endl;
|
---|
| 1634 | cout << "generated " << (int)mViewCells.size() << " view cells using the geometry " << filename << endl;
|
---|
| 1635 |
|
---|
| 1636 | return true;
|
---|
[440] | 1637 | }
|
---|
| 1638 |
|
---|
[485] | 1639 |
|
---|
[487] | 1640 | bool ViewCellsManager::GetViewPoint(Vector3 &viewPoint) const
|
---|
| 1641 | {
|
---|
[1867] | 1642 | viewPoint = mViewSpaceBox.GetRandomPoint();
|
---|
| 1643 | return true;
|
---|
[487] | 1644 | }
|
---|
| 1645 |
|
---|
[1867] | 1646 | bool ViewCellsManager::GetViewPoint(Vector3 &viewPoint, const Vector3 ¶ms) const
|
---|
| 1647 | {
|
---|
| 1648 | viewPoint = mViewSpaceBox.GetRandomPoint(params);
|
---|
| 1649 | return true;
|
---|
| 1650 | }
|
---|
[487] | 1651 |
|
---|
[1867] | 1652 |
|
---|
[557] | 1653 | float ViewCellsManager::GetViewSpaceVolume()
|
---|
| 1654 | {
|
---|
[610] | 1655 | return mViewSpaceBox.GetVolume() * (2.0f * sqr((float)M_PI));
|
---|
[557] | 1656 | }
|
---|
| 1657 |
|
---|
| 1658 |
|
---|
[490] | 1659 | bool ViewCellsManager::ViewPointValid(const Vector3 &viewPoint) const
|
---|
| 1660 | {
|
---|
[1444] | 1661 | if (!ViewCellsConstructed())
|
---|
| 1662 | {
|
---|
| 1663 | return mViewSpaceBox.IsInside(viewPoint);
|
---|
| 1664 | }
|
---|
| 1665 | else
|
---|
| 1666 | {
|
---|
| 1667 | if (!mViewSpaceBox.IsInside(viewPoint))
|
---|
| 1668 | return false;
|
---|
[837] | 1669 |
|
---|
[1444] | 1670 | ViewCell *viewcell = GetViewCell(viewPoint);
|
---|
| 1671 |
|
---|
| 1672 | if (!viewcell || !viewcell->GetValid())
|
---|
| 1673 | return false;
|
---|
| 1674 | }
|
---|
| 1675 |
|
---|
| 1676 | return true;
|
---|
[490] | 1677 | }
|
---|
| 1678 |
|
---|
[501] | 1679 |
|
---|
[1867] | 1680 | float
|
---|
| 1681 | ViewCellsManager::ComputeSampleContributions(const VssRayContainer &rays,
|
---|
| 1682 | const bool addRays,
|
---|
| 1683 | const bool storeViewCells)
|
---|
[440] | 1684 | {
|
---|
[1867] | 1685 | float sum = 0.0f;
|
---|
[1900] | 1686 |
|
---|
[1867] | 1687 | VssRayContainer::const_iterator it, it_end = rays.end();
|
---|
| 1688 |
|
---|
| 1689 | for (it = rays.begin(); it != it_end; ++ it)
|
---|
[1444] | 1690 | {
|
---|
[1900] | 1691 | if (!ViewCellsConstructed()) {
|
---|
| 1692 | // view cells not yet constructed
|
---|
| 1693 | // just take the lenghts of the rays as contributions
|
---|
| 1694 | if ((*it)->mTerminationObject)
|
---|
| 1695 | sum += (*it)->Length();
|
---|
| 1696 | } else {
|
---|
| 1697 | sum += ComputeSampleContribution(*(*it), addRays, storeViewCells);
|
---|
| 1698 | }
|
---|
[1444] | 1699 | }
|
---|
[1931] | 1700 |
|
---|
[1867] | 1701 | return sum;
|
---|
[440] | 1702 | }
|
---|
| 1703 |
|
---|
[485] | 1704 |
|
---|
[479] | 1705 | void ViewCellsManager::EvaluateViewCellsStats()
|
---|
| 1706 | {
|
---|
[660] | 1707 | mCurrentViewCellsStats.Reset();
|
---|
[479] | 1708 | ViewCellContainer::const_iterator it, it_end = mViewCells.end();
|
---|
| 1709 |
|
---|
| 1710 | for (it = mViewCells.begin(); it != it_end; ++ it)
|
---|
[487] | 1711 | {
|
---|
[660] | 1712 | mViewCellsTree->UpdateViewCellsStats(*it, mCurrentViewCellsStats);
|
---|
[487] | 1713 | }
|
---|
[479] | 1714 | }
|
---|
| 1715 |
|
---|
[485] | 1716 |
|
---|
[580] | 1717 | void ViewCellsManager::EvaluateRenderStatistics(float &totalRenderCost,
|
---|
[579] | 1718 | float &expectedRenderCost,
|
---|
[580] | 1719 | float &deviation,
|
---|
| 1720 | float &variance,
|
---|
[1709] | 1721 | float &totalCost,
|
---|
[580] | 1722 | float &avgRenderCost)
|
---|
[579] | 1723 | {
|
---|
[1444] | 1724 | ////////////
|
---|
| 1725 | //-- compute expected value
|
---|
[579] | 1726 |
|
---|
| 1727 | totalRenderCost = 0;
|
---|
[1709] | 1728 | totalCost = 0;
|
---|
[579] | 1729 |
|
---|
[1444] | 1730 | ViewCellContainer::const_iterator it, it_end = mViewCells.end();
|
---|
| 1731 |
|
---|
[579] | 1732 | for (it = mViewCells.begin(); it != it_end; ++ it)
|
---|
| 1733 | {
|
---|
| 1734 | ViewCell *vc = *it;
|
---|
[1707] | 1735 | totalRenderCost += vc->GetPvs().EvalPvsCost() * vc->GetVolume();
|
---|
[1709] | 1736 | totalCost += (int)vc->GetPvs().EvalPvsCost();
|
---|
[579] | 1737 | }
|
---|
| 1738 |
|
---|
[580] | 1739 | // normalize with view space box
|
---|
| 1740 | totalRenderCost /= mViewSpaceBox.GetVolume();
|
---|
[579] | 1741 | expectedRenderCost = totalRenderCost / (float)mViewCells.size();
|
---|
[1709] | 1742 | avgRenderCost = totalCost / (float)mViewCells.size();
|
---|
[579] | 1743 |
|
---|
| 1744 |
|
---|
[1444] | 1745 | ///////////
|
---|
[580] | 1746 | //-- compute standard defiation
|
---|
[1444] | 1747 |
|
---|
[579] | 1748 | variance = 0;
|
---|
[580] | 1749 | deviation = 0;
|
---|
[579] | 1750 |
|
---|
| 1751 | for (it = mViewCells.begin(); it != it_end; ++ it)
|
---|
| 1752 | {
|
---|
| 1753 | ViewCell *vc = *it;
|
---|
| 1754 |
|
---|
[1707] | 1755 | float renderCost = vc->GetPvs().EvalPvsCost() * vc->GetVolume();
|
---|
[580] | 1756 | float dev;
|
---|
[579] | 1757 |
|
---|
[580] | 1758 | if (1)
|
---|
[1707] | 1759 | dev = fabs(avgRenderCost - (float)vc->GetPvs().EvalPvsCost());
|
---|
[580] | 1760 | else
|
---|
| 1761 | dev = fabs(expectedRenderCost - renderCost);
|
---|
[579] | 1762 |
|
---|
[580] | 1763 | deviation += dev;
|
---|
| 1764 | variance += dev * dev;
|
---|
[579] | 1765 | }
|
---|
[580] | 1766 |
|
---|
[579] | 1767 | variance /= (float)mViewCells.size();
|
---|
[580] | 1768 | deviation /= (float)mViewCells.size();
|
---|
[579] | 1769 | }
|
---|
| 1770 |
|
---|
| 1771 |
|
---|
[478] | 1772 | float ViewCellsManager::GetArea(ViewCell *viewCell) const
|
---|
| 1773 | {
|
---|
| 1774 | return viewCell->GetArea();
|
---|
| 1775 | }
|
---|
| 1776 |
|
---|
| 1777 |
|
---|
| 1778 | float ViewCellsManager::GetVolume(ViewCell *viewCell) const
|
---|
| 1779 | {
|
---|
| 1780 | return viewCell->GetVolume();
|
---|
| 1781 | }
|
---|
| 1782 |
|
---|
[485] | 1783 |
|
---|
[1843] | 1784 | void ViewCellsManager::CompressViewCells()
|
---|
| 1785 | {
|
---|
[1889] | 1786 | if (!(ViewCellsTreeConstructed() && mCompressViewCells))
|
---|
| 1787 | return;
|
---|
| 1788 |
|
---|
[1843] | 1789 | ////////////
|
---|
| 1790 | //-- compression
|
---|
[1889] | 1791 |
|
---|
| 1792 | int pvsEntries = mViewCellsTree->CountStoredPvsEntries(mViewCellsTree->GetRoot());
|
---|
[1843] | 1793 |
|
---|
[1889] | 1794 | cout << "number of entries before compress: " << pvsEntries << endl;
|
---|
| 1795 | Debug << "number of entries before compress: " << pvsEntries << endl;
|
---|
[1843] | 1796 |
|
---|
[1889] | 1797 | mViewCellsTree->SetViewCellsStorage(ViewCellsTree::COMPRESSED);
|
---|
[1843] | 1798 |
|
---|
[1889] | 1799 | pvsEntries = mViewCellsTree->CountStoredPvsEntries(mViewCellsTree->GetRoot());
|
---|
| 1800 |
|
---|
| 1801 | Debug << "number of entries after compress: " << pvsEntries << endl;
|
---|
| 1802 | cout << "number of entries after compress: " << pvsEntries << endl;
|
---|
[1843] | 1803 | }
|
---|
| 1804 |
|
---|
| 1805 |
|
---|
[503] | 1806 | ViewCell *ViewCellsManager::ExtrudeViewCell(const Triangle3 &baseTri,
|
---|
[440] | 1807 | const float height) const
|
---|
| 1808 | {
|
---|
| 1809 | // one mesh per view cell
|
---|
[1001] | 1810 | Mesh *mesh = MeshManager::GetSingleton()->CreateResource();
|
---|
[503] | 1811 |
|
---|
[1545] | 1812 | ////////////
|
---|
[440] | 1813 | //-- construct prism
|
---|
| 1814 |
|
---|
[503] | 1815 | // bottom
|
---|
[440] | 1816 | mesh->mFaces.push_back(new Face(2,1,0));
|
---|
| 1817 | // top
|
---|
| 1818 | mesh->mFaces.push_back(new Face(3,4,5));
|
---|
| 1819 | // sides
|
---|
| 1820 | mesh->mFaces.push_back(new Face(1, 4, 3, 0));
|
---|
| 1821 | mesh->mFaces.push_back(new Face(2, 5, 4, 1));
|
---|
| 1822 | mesh->mFaces.push_back(new Face(3, 5, 2, 0));
|
---|
| 1823 |
|
---|
[1545] | 1824 |
|
---|
| 1825 | /////////////
|
---|
| 1826 | //-- extrude new vertices for top of prism
|
---|
| 1827 |
|
---|
[1586] | 1828 | const Vector3 triNorm = baseTri.GetNormal();
|
---|
[503] | 1829 | Triangle3 topTri;
|
---|
[440] | 1830 |
|
---|
| 1831 | // add base vertices and calculate top vertices
|
---|
| 1832 | for (int i = 0; i < 3; ++ i)
|
---|
[1545] | 1833 | {
|
---|
[440] | 1834 | mesh->mVertices.push_back(baseTri.mVertices[i]);
|
---|
[1545] | 1835 | }
|
---|
[503] | 1836 |
|
---|
| 1837 | // add top vertices
|
---|
[440] | 1838 | for (int i = 0; i < 3; ++ i)
|
---|
[1545] | 1839 | {
|
---|
[440] | 1840 | mesh->mVertices.push_back(baseTri.mVertices[i] + height * triNorm);
|
---|
[1545] | 1841 | }
|
---|
[503] | 1842 |
|
---|
[1545] | 1843 | // do we have to preprocess this mesh (we don't want to trace view cells!)?
|
---|
| 1844 | mesh->ComputeBoundingBox();
|
---|
| 1845 |
|
---|
[440] | 1846 | return GenerateViewCell(mesh);
|
---|
| 1847 | }
|
---|
| 1848 |
|
---|
[485] | 1849 |
|
---|
[551] | 1850 | void ViewCellsManager::FinalizeViewCells(const bool createMesh)
|
---|
| 1851 | {
|
---|
| 1852 | ViewCellContainer::const_iterator it, it_end = mViewCells.end();
|
---|
[693] | 1853 |
|
---|
[1768] | 1854 | // volume and area of the view cells are recomputed
|
---|
| 1855 | // a view cell mesh is created
|
---|
[551] | 1856 | for (it = mViewCells.begin(); it != it_end; ++ it)
|
---|
| 1857 | {
|
---|
| 1858 | Finalize(*it, createMesh);
|
---|
| 1859 | }
|
---|
[555] | 1860 |
|
---|
[1584] | 1861 | mViewCellsTree->AssignRandomColors();
|
---|
| 1862 |
|
---|
[555] | 1863 | mTotalAreaValid = false;
|
---|
[551] | 1864 | }
|
---|
| 1865 |
|
---|
| 1866 |
|
---|
| 1867 | void ViewCellsManager::Finalize(ViewCell *viewCell, const bool createMesh)
|
---|
| 1868 | {
|
---|
| 1869 | // implemented in subclasses
|
---|
| 1870 | }
|
---|
| 1871 |
|
---|
[1001] | 1872 |
|
---|
[1168] | 1873 | /** fast way of merging 2 view cells.
|
---|
| 1874 | */
|
---|
[582] | 1875 | ViewCellInterior *ViewCellsManager::MergeViewCells(ViewCell *left, ViewCell *right) const
|
---|
[440] | 1876 | {
|
---|
[580] | 1877 | // generate parent view cell
|
---|
[752] | 1878 | ViewCellInterior *vc = new ViewCellInterior();
|
---|
[710] | 1879 |
|
---|
[752] | 1880 | vc->GetPvs().Clear();
|
---|
[1740] | 1881 | ObjectPvs::Merge(vc->GetPvs(), left->GetPvs(), right->GetPvs());
|
---|
[752] | 1882 |
|
---|
[710] | 1883 | // set only links to child (not from child to parent, maybe not wished!!)
|
---|
| 1884 | vc->mChildren.push_back(left);
|
---|
| 1885 | vc->mChildren.push_back(right);
|
---|
| 1886 |
|
---|
[752] | 1887 | // update pvs size
|
---|
[1707] | 1888 | UpdateScalarPvsSize(vc, vc->GetPvs().EvalPvsCost(), vc->GetPvs().GetSize());
|
---|
[752] | 1889 |
|
---|
[440] | 1890 | return vc;
|
---|
| 1891 | }
|
---|
| 1892 |
|
---|
[485] | 1893 |
|
---|
[582] | 1894 | ViewCellInterior *ViewCellsManager::MergeViewCells(ViewCellContainer &children) const
|
---|
| 1895 | {
|
---|
[752] | 1896 | ViewCellInterior *vc = new ViewCellInterior();
|
---|
[582] | 1897 | ViewCellContainer::const_iterator it, it_end = children.end();
|
---|
| 1898 |
|
---|
| 1899 | for (it = children.begin(); it != it_end; ++ it)
|
---|
| 1900 | {
|
---|
[1740] | 1901 | vc->GetPvs().MergeInPlace((*it)->GetPvs());
|
---|
| 1902 |
|
---|
[710] | 1903 | vc->mChildren.push_back(*it);
|
---|
[582] | 1904 | }
|
---|
| 1905 |
|
---|
| 1906 | return vc;
|
---|
| 1907 | }
|
---|
| 1908 |
|
---|
| 1909 |
|
---|
[480] | 1910 | void ViewCellsManager::SetRenderer(Renderer *renderer)
|
---|
| 1911 | {
|
---|
| 1912 | mRenderer = renderer;
|
---|
| 1913 | }
|
---|
[441] | 1914 |
|
---|
[485] | 1915 |
|
---|
[580] | 1916 | ViewCellsTree *ViewCellsManager::GetViewCellsTree()
|
---|
[440] | 1917 | {
|
---|
[580] | 1918 | return mViewCellsTree;
|
---|
[440] | 1919 | }
|
---|
| 1920 |
|
---|
| 1921 |
|
---|
| 1922 | void ViewCellsManager::SetVisualizationSamples(const int visSamples)
|
---|
| 1923 | {
|
---|
[444] | 1924 | mVisualizationSamples = visSamples;
|
---|
[440] | 1925 | }
|
---|
| 1926 |
|
---|
[485] | 1927 |
|
---|
[440] | 1928 | void ViewCellsManager::SetConstructionSamples(const int constructionSamples)
|
---|
| 1929 | {
|
---|
| 1930 | mConstructionSamples = constructionSamples;
|
---|
| 1931 | }
|
---|
| 1932 |
|
---|
[485] | 1933 |
|
---|
[574] | 1934 | void ViewCellsManager::SetInitialSamples(const int initialSamples)
|
---|
| 1935 | {
|
---|
| 1936 | mInitialSamples = initialSamples;
|
---|
| 1937 | }
|
---|
| 1938 |
|
---|
| 1939 |
|
---|
[440] | 1940 | void ViewCellsManager::SetPostProcessSamples(const int postProcessSamples)
|
---|
| 1941 | {
|
---|
| 1942 | mPostProcessSamples = postProcessSamples;
|
---|
| 1943 | }
|
---|
| 1944 |
|
---|
[485] | 1945 |
|
---|
[440] | 1946 | int ViewCellsManager::GetVisualizationSamples() const
|
---|
| 1947 | {
|
---|
| 1948 | return mVisualizationSamples;
|
---|
| 1949 | }
|
---|
| 1950 |
|
---|
[485] | 1951 |
|
---|
[440] | 1952 | int ViewCellsManager::GetConstructionSamples() const
|
---|
| 1953 | {
|
---|
| 1954 | return mConstructionSamples;
|
---|
| 1955 | }
|
---|
| 1956 |
|
---|
[485] | 1957 |
|
---|
[440] | 1958 | int ViewCellsManager::GetPostProcessSamples() const
|
---|
| 1959 | {
|
---|
| 1960 | return mPostProcessSamples;
|
---|
| 1961 | }
|
---|
| 1962 |
|
---|
[485] | 1963 |
|
---|
[719] | 1964 | void ViewCellsManager::UpdatePvs()
|
---|
| 1965 | {
|
---|
[1737] | 1966 | if (mViewCellPvsIsUpdated || !ViewCellsTreeConstructed())
|
---|
| 1967 | return;
|
---|
| 1968 |
|
---|
| 1969 | mViewCellPvsIsUpdated = true;
|
---|
| 1970 |
|
---|
| 1971 | ViewCellContainer leaves;
|
---|
| 1972 | mViewCellsTree->CollectLeaves(mViewCellsTree->GetRoot(), leaves);
|
---|
| 1973 |
|
---|
| 1974 | ViewCellContainer::const_iterator it, it_end = leaves.end();
|
---|
| 1975 |
|
---|
| 1976 | for (it = leaves.begin(); it != it_end; ++ it)
|
---|
[719] | 1977 | {
|
---|
[1737] | 1978 | mViewCellsTree->PropagatePvs(*it);
|
---|
[719] | 1979 | }
|
---|
| 1980 | }
|
---|
| 1981 |
|
---|
| 1982 |
|
---|
[485] | 1983 | void ViewCellsManager::GetPvsStatistics(PvsStatistics &stat)
|
---|
[467] | 1984 | {
|
---|
[1737] | 1985 | // update pvs of view cells tree if necessary
|
---|
| 1986 | UpdatePvs();
|
---|
| 1987 |
|
---|
| 1988 | ViewCellContainer::const_iterator it = mViewCells.begin();
|
---|
| 1989 |
|
---|
| 1990 | stat.viewcells = 0;
|
---|
| 1991 | stat.minPvs = 100000000;
|
---|
| 1992 | stat.maxPvs = 0;
|
---|
| 1993 | stat.avgPvs = 0.0f;
|
---|
| 1994 | stat.avgFilteredPvs = 0.0f;
|
---|
| 1995 | stat.avgFilterContribution = 0.0f;
|
---|
[1761] | 1996 | stat.avgFilterRadius = 0;
|
---|
| 1997 | stat.avgFilterRatio = 0;
|
---|
[1942] | 1998 | stat.avgRelPvsIncrease = 0.0f;
|
---|
| 1999 | stat.devRelPvsIncrease = 0.0f;
|
---|
[1737] | 2000 |
|
---|
[1942] | 2001 | if (mPerViewCellStat.size() != mViewCells.size()) {
|
---|
| 2002 | // reset the pvs size array after the first call to this routine
|
---|
| 2003 | mPerViewCellStat.resize(mViewCells.size());
|
---|
| 2004 | for (int i=0; i < mPerViewCellStat.size(); i++) {
|
---|
| 2005 | mPerViewCellStat[i].pvsSize = 0.0f;
|
---|
| 2006 | mPerViewCellStat[i].relPvsIncrease = 0.0f;
|
---|
| 2007 | }
|
---|
| 2008 | }
|
---|
| 2009 | int i;
|
---|
| 2010 | bool evaluateFilter;
|
---|
| 2011 | Environment::GetSingleton()->GetBoolValue("Preprocessor.evaluateFilter", evaluateFilter);
|
---|
| 2012 |
|
---|
| 2013 | for (i=0; it != mViewCells.end(); ++ it, i++)
|
---|
[719] | 2014 | {
|
---|
[1737] | 2015 | ViewCell *viewcell = *it;
|
---|
[1761] | 2016 | if (viewcell->GetValid()) {
|
---|
| 2017 | const float pvsCost = mViewCellsTree->GetPvsCost(viewcell);
|
---|
| 2018 |
|
---|
| 2019 | if (pvsCost < stat.minPvs)
|
---|
| 2020 | stat.minPvs = pvsCost;
|
---|
| 2021 | if (pvsCost > stat.maxPvs)
|
---|
| 2022 | stat.maxPvs = pvsCost;
|
---|
| 2023 |
|
---|
| 2024 | stat.avgPvs += pvsCost;
|
---|
[1785] | 2025 |
|
---|
[1942] | 2026 |
|
---|
| 2027 | if (mPerViewCellStat[i].pvsSize > 0.0f)
|
---|
| 2028 | mPerViewCellStat[i].relPvsIncrease = (pvsCost - mPerViewCellStat[i].pvsSize)/mPerViewCellStat[i].pvsSize;
|
---|
[1761] | 2029 |
|
---|
[1942] | 2030 | stat.avgRelPvsIncrease += mPerViewCellStat[i].relPvsIncrease;
|
---|
[1761] | 2031 |
|
---|
[1942] | 2032 | // update the pvs size
|
---|
| 2033 | mPerViewCellStat[i].pvsSize = pvsCost;
|
---|
| 2034 |
|
---|
| 2035 |
|
---|
| 2036 |
|
---|
[1761] | 2037 | if (evaluateFilter) {
|
---|
[1877] | 2038 | ObjectPvs filteredPvs;
|
---|
[1824] | 2039 | PvsFilterStatistics fstat = ApplyFilter2(viewcell,
|
---|
[1877] | 2040 | false,
|
---|
[1952] | 2041 | 4.0f,
|
---|
[1877] | 2042 | filteredPvs);
|
---|
[1761] | 2043 |
|
---|
| 2044 | float filteredCost = filteredPvs.EvalPvsCost();
|
---|
| 2045 | stat.avgFilteredPvs += filteredCost;
|
---|
| 2046 | stat.avgFilterContribution += filteredCost - pvsCost;
|
---|
[1877] | 2047 |
|
---|
[1761] | 2048 | stat.avgFilterRadius += fstat.mAvgFilterRadius;
|
---|
[1771] | 2049 | int sum = fstat.mGlobalFilterCount + fstat.mLocalFilterCount;
|
---|
| 2050 | if (sum) {
|
---|
| 2051 | stat.avgFilterRatio += fstat.mLocalFilterCount /
|
---|
| 2052 | (float) sum;
|
---|
| 2053 | }
|
---|
[1761] | 2054 |
|
---|
| 2055 | } else {
|
---|
| 2056 | stat.avgFilteredPvs += pvsCost;
|
---|
| 2057 | stat.avgFilterContribution += 0;
|
---|
| 2058 | }
|
---|
| 2059 |
|
---|
| 2060 | ++ stat.viewcells;
|
---|
[1737] | 2061 | }
|
---|
[719] | 2062 | }
|
---|
[1942] | 2063 |
|
---|
[1737] | 2064 |
|
---|
[1942] | 2065 |
|
---|
[1737] | 2066 | if (stat.viewcells) {
|
---|
| 2067 | stat.avgPvs/=stat.viewcells;
|
---|
| 2068 | stat.avgFilteredPvs/=stat.viewcells;
|
---|
| 2069 | stat.avgFilterContribution/=stat.viewcells;
|
---|
[1761] | 2070 | stat.avgFilterRadius/=stat.viewcells;
|
---|
[1942] | 2071 | stat.avgFilterRatio/=stat.viewcells;
|
---|
| 2072 | stat.avgRelPvsIncrease/=stat.viewcells;
|
---|
| 2073 |
|
---|
| 2074 | // evaluate std deviation of relPvsIncrease
|
---|
| 2075 | float sum=0.0f;
|
---|
| 2076 | for (i=0; i < stat.viewcells; i++) {
|
---|
| 2077 | sum += sqr(mPerViewCellStat[i].relPvsIncrease - stat.avgRelPvsIncrease);
|
---|
| 2078 | }
|
---|
| 2079 | stat.devRelPvsIncrease = sqrt(sum/stat.viewcells);
|
---|
[1737] | 2080 | }
|
---|
[1942] | 2081 |
|
---|
[467] | 2082 | }
|
---|
| 2083 |
|
---|
[485] | 2084 |
|
---|
[480] | 2085 | void ViewCellsManager::PrintPvsStatistics(ostream &s)
|
---|
[467] | 2086 | {
|
---|
| 2087 | s<<"############# Viewcell PVS STAT ##################\n";
|
---|
| 2088 | PvsStatistics pvsStat;
|
---|
| 2089 | GetPvsStatistics(pvsStat);
|
---|
| 2090 | s<<"#AVG_PVS\n"<<pvsStat.avgPvs<<endl;
|
---|
[1737] | 2091 | s<<"#AVG_FILTERED_PVS\n"<<pvsStat.avgFilteredPvs<<endl;
|
---|
| 2092 | s<<"#AVG_FILTER_CONTRIBUTION\n"<<pvsStat.avgFilterContribution<<endl;
|
---|
[1761] | 2093 | s<<"#AVG_FILTER_RADIUS\n"<<pvsStat.avgFilterRadius<<endl;
|
---|
| 2094 | s<<"#AVG_FILTER_RATIO\n"<<pvsStat.avgFilterRatio<<endl;
|
---|
[467] | 2095 | s<<"#MAX_PVS\n"<<pvsStat.maxPvs<<endl;
|
---|
| 2096 | s<<"#MIN_PVS\n"<<pvsStat.minPvs<<endl;
|
---|
[1942] | 2097 | s<<"#AVG_REL_PVS_INCREASE\n"<<pvsStat.avgRelPvsIncrease<<endl;
|
---|
| 2098 | s<<"#DEV_REL_PVS_INCREASE\n"<<pvsStat.devRelPvsIncrease<<endl;
|
---|
[467] | 2099 | }
|
---|
| 2100 |
|
---|
[485] | 2101 |
|
---|
[532] | 2102 | int ViewCellsManager::CastBeam(Beam &beam)
|
---|
| 2103 | {
|
---|
| 2104 | return 0;
|
---|
| 2105 | }
|
---|
| 2106 |
|
---|
[547] | 2107 |
|
---|
[468] | 2108 | ViewCellContainer &ViewCellsManager::GetViewCells()
|
---|
| 2109 | {
|
---|
| 2110 | return mViewCells;
|
---|
| 2111 | }
|
---|
| 2112 |
|
---|
[485] | 2113 |
|
---|
[487] | 2114 | void ViewCellsManager::SetViewSpaceBox(const AxisAlignedBox3 &box)
|
---|
| 2115 | {
|
---|
[542] | 2116 | mViewSpaceBox = box;
|
---|
[1074] | 2117 |
|
---|
[1027] | 2118 | // hack: create clip plane relative to new view space box
|
---|
[660] | 2119 | CreateClipPlane();
|
---|
[1027] | 2120 | // the total area of the view space has changed
|
---|
[577] | 2121 | mTotalAreaValid = false;
|
---|
[487] | 2122 | }
|
---|
| 2123 |
|
---|
| 2124 |
|
---|
[660] | 2125 | void ViewCellsManager::CreateClipPlane()
|
---|
[591] | 2126 | {
|
---|
| 2127 | int axis = 0;
|
---|
[667] | 2128 | float pos;
|
---|
[1418] | 2129 | bool orientation;
|
---|
| 2130 | Vector3 absPos;
|
---|
[591] | 2131 |
|
---|
[1004] | 2132 | Environment::GetSingleton()->GetFloatValue("ViewCells.Visualization.clipPlanePos", pos);
|
---|
[1416] | 2133 | Environment::GetSingleton()->GetIntValue("ViewCells.Visualization.clipPlaneAxis", axis);
|
---|
[591] | 2134 |
|
---|
[1418] | 2135 | if (axis < 0)
|
---|
| 2136 | {
|
---|
| 2137 | axis = -axis;
|
---|
| 2138 | orientation = false;
|
---|
| 2139 | absPos = mViewSpaceBox.Max() - mViewSpaceBox.Size() * pos;
|
---|
| 2140 | }
|
---|
| 2141 | else
|
---|
| 2142 | {
|
---|
| 2143 | orientation = true;
|
---|
| 2144 | absPos = mViewSpaceBox.Min() + mViewSpaceBox.Size() * pos;
|
---|
| 2145 | }
|
---|
| 2146 |
|
---|
[1416] | 2147 | mClipPlaneForViz = AxisAlignedPlane(axis, absPos[axis]);
|
---|
[1418] | 2148 | mClipPlaneForViz.mOrientation = orientation;
|
---|
[591] | 2149 | }
|
---|
| 2150 |
|
---|
| 2151 |
|
---|
[519] | 2152 | AxisAlignedBox3 ViewCellsManager::GetViewSpaceBox() const
|
---|
| 2153 | {
|
---|
[542] | 2154 | return mViewSpaceBox;
|
---|
[519] | 2155 | }
|
---|
| 2156 |
|
---|
| 2157 |
|
---|
[480] | 2158 | void ViewCellsManager::ResetViewCells()
|
---|
| 2159 | {
|
---|
[720] | 2160 | // recollect view cells
|
---|
[480] | 2161 | mViewCells.clear();
|
---|
| 2162 | CollectViewCells();
|
---|
[590] | 2163 |
|
---|
[720] | 2164 | // stats are computed once more
|
---|
[480] | 2165 | EvaluateViewCellsStats();
|
---|
[590] | 2166 |
|
---|
[520] | 2167 | // has to be recomputed
|
---|
[480] | 2168 | mTotalAreaValid = false;
|
---|
| 2169 | }
|
---|
| 2170 |
|
---|
[485] | 2171 |
|
---|
[547] | 2172 | int ViewCellsManager::GetMaxPvsSize() const
|
---|
| 2173 | {
|
---|
| 2174 | return mMaxPvsSize;
|
---|
| 2175 | }
|
---|
| 2176 |
|
---|
[564] | 2177 |
|
---|
[562] | 2178 | int ViewCellsManager::GetMinPvsSize() const
|
---|
| 2179 | {
|
---|
| 2180 | return mMinPvsSize;
|
---|
| 2181 | }
|
---|
| 2182 |
|
---|
| 2183 |
|
---|
| 2184 |
|
---|
[561] | 2185 | float ViewCellsManager::GetMaxPvsRatio() const
|
---|
| 2186 | {
|
---|
| 2187 | return mMaxPvsRatio;
|
---|
| 2188 | }
|
---|
| 2189 |
|
---|
[1594] | 2190 |
|
---|
[1932] | 2191 | inline static void AddSampleToPvs(ObjectPvs &pvs,
|
---|
| 2192 | Intersectable *obj,
|
---|
| 2193 | const float pdf)
|
---|
| 2194 | {
|
---|
| 2195 | #if PVS_ADD_DIRTY
|
---|
| 2196 | pvs.AddSampleDirtyCheck(obj, pdf);
|
---|
[1877] | 2197 |
|
---|
[1932] | 2198 | if (pvs.RequiresResort())
|
---|
| 2199 | {
|
---|
| 2200 | pvs.SimpleSort();
|
---|
| 2201 | }
|
---|
| 2202 | #else
|
---|
| 2203 | pvs.AddSample(obj, pdf);
|
---|
| 2204 | #endif
|
---|
| 2205 | }
|
---|
[1877] | 2206 |
|
---|
[1932] | 2207 |
|
---|
| 2208 | void ViewCellsManager::ComputeViewCellContribution(ViewCell *viewCell,
|
---|
| 2209 | VssRay &ray,
|
---|
| 2210 | Intersectable *obj,
|
---|
| 2211 | const Vector3 &pt,
|
---|
| 2212 | const bool addRays)
|
---|
| 2213 | {
|
---|
[1942] | 2214 | // check if we are outside of view space
|
---|
[1932] | 2215 | if (!obj || !viewCell->GetValid())
|
---|
| 2216 | return;
|
---|
[1942] | 2217 |
|
---|
[1932] | 2218 | // if ray not outside of view space
|
---|
| 2219 | float relContribution = 0.0f;
|
---|
| 2220 | float absContribution = 0.0f;
|
---|
| 2221 |
|
---|
[1942] | 2222 | if (obj)
|
---|
| 2223 | {
|
---|
| 2224 | // todo: maybe not correct for kd node pvs
|
---|
| 2225 | if (addRays) {
|
---|
| 2226 | float pdf = viewCell->GetPvs().AddSampleDirtyCheck(obj, ray.mPdf);
|
---|
| 2227 | if (pdf == ray.mPdf) {
|
---|
| 2228 | absContribution = 1.0f;
|
---|
| 2229 | if (viewCell->GetPvs().RequiresResort())
|
---|
| 2230 | viewCell->GetPvs().SimpleSort();
|
---|
| 2231 | }
|
---|
| 2232 | } else {
|
---|
| 2233 | if (viewCell->GetPvs().GetSampleContribution(
|
---|
| 2234 | obj,
|
---|
| 2235 | ray.mPdf,
|
---|
| 2236 | relContribution))
|
---|
| 2237 | absContribution = 1.0f;
|
---|
| 2238 | }
|
---|
| 2239 | // $$ clear the relative contribution as it is currently not correct anyway
|
---|
| 2240 | relContribution = 0.0f;
|
---|
| 2241 |
|
---|
| 2242 | if (absContribution == 1.0f) {
|
---|
| 2243 | ++ ray.mPvsContribution;
|
---|
| 2244 | relContribution = 1.0f;
|
---|
| 2245 |
|
---|
| 2246 |
|
---|
| 2247 | #if CONTRIBUTION_RELATIVE_TO_PVS_SIZE
|
---|
| 2248 | relContribution /= viewcell->GetPvs().GetSize();
|
---|
| 2249 | #endif
|
---|
| 2250 |
|
---|
[1932] | 2251 | #if DIST_WEIGHTED_CONTRIBUTION
|
---|
[1942] | 2252 | // recalculate the contribution - weight the 1.0f contribution by the sqr distance to the
|
---|
| 2253 | // object-> a new contribution in the proximity of the viewcell has a larger weight!
|
---|
| 2254 | relContribution /= SqrDistance(GetViewCellBox(viewcell).Center(),
|
---|
| 2255 | ray.mTermination);
|
---|
| 2256 |
|
---|
[1932] | 2257 | #endif
|
---|
[1942] | 2258 | }
|
---|
| 2259 |
|
---|
[1932] | 2260 | #if SUM_RAY_CONTRIBUTIONS || AVG_RAY_CONTRIBUTIONS
|
---|
[1942] | 2261 | ray.mRelativePvsContribution += relContribution;
|
---|
[1932] | 2262 | #else
|
---|
[1942] | 2263 | // recalculate relative contribution - use max of Rel Contribution
|
---|
| 2264 | if (ray.mRelativePvsContribution < relContribution)
|
---|
| 2265 | ray.mRelativePvsContribution = relContribution;
|
---|
[1932] | 2266 | #endif
|
---|
[1942] | 2267 | }
|
---|
| 2268 |
|
---|
[1932] | 2269 | }
|
---|
| 2270 |
|
---|
| 2271 |
|
---|
[1877] | 2272 | float
|
---|
| 2273 | ViewCellsManager::ComputeSampleContribution(VssRay &ray,
|
---|
[1900] | 2274 | const bool addRays,
|
---|
| 2275 | const bool storeViewCells)
|
---|
[1790] | 2276 | {
|
---|
[1903] | 2277 | ray.mPvsContribution = 0;
|
---|
| 2278 | ray.mRelativePvsContribution = 0.0f;
|
---|
[1877] | 2279 |
|
---|
[1932] | 2280 | if (!ray.mTerminationObject)
|
---|
[1903] | 2281 | return 0.0f;
|
---|
| 2282 |
|
---|
[1932] | 2283 | ViewCellContainer viewCells;
|
---|
[1903] | 2284 |
|
---|
| 2285 | static Ray hray;
|
---|
| 2286 | hray.Init(ray);
|
---|
| 2287 |
|
---|
| 2288 | float tmin = 0, tmax = 1.0;
|
---|
| 2289 |
|
---|
[1942] | 2290 | if (!GetViewSpaceBox().GetRaySegment(hray, tmin, tmax) || (tmin > tmax)) {
|
---|
| 2291 | // cerr<<"ray outside view space box\n";
|
---|
| 2292 | return 0;
|
---|
| 2293 | }
|
---|
[1903] | 2294 |
|
---|
| 2295 | Vector3 origin = hray.Extrap(tmin);
|
---|
| 2296 | Vector3 termination = hray.Extrap(tmax);
|
---|
| 2297 |
|
---|
| 2298 | ViewCell::NewMail();
|
---|
| 2299 |
|
---|
| 2300 | // traverse the view space subdivision
|
---|
[1932] | 2301 | CastLineSegment(origin, termination, viewCells);
|
---|
[1903] | 2302 |
|
---|
[1942] | 2303 |
|
---|
[1903] | 2304 | if (storeViewCells)
|
---|
[1877] | 2305 | {
|
---|
[1942] | 2306 | // copy viewcells memory efficiently
|
---|
| 2307 | ray.mViewCells.reserve(viewCells.size());
|
---|
| 2308 | ray.mViewCells = viewCells;
|
---|
[570] | 2309 | }
|
---|
[1903] | 2310 |
|
---|
[1932] | 2311 | // optain pvs entry (can be different from hit object)
|
---|
[1903] | 2312 | Intersectable *terminationObj = GetIntersectable(ray, true);
|
---|
| 2313 |
|
---|
[1932] | 2314 | ViewCellContainer::const_iterator it = viewCells.begin();
|
---|
| 2315 |
|
---|
| 2316 | for (; it != viewCells.end(); ++ it)
|
---|
[664] | 2317 | {
|
---|
[1932] | 2318 | ComputeViewCellContribution(*it,
|
---|
| 2319 | ray,
|
---|
| 2320 | terminationObj,
|
---|
| 2321 | ray.mTermination,
|
---|
| 2322 | addRays);
|
---|
[563] | 2323 | }
|
---|
[1900] | 2324 |
|
---|
[1931] | 2325 | #if AVG_RAY_CONTRIBUTIONS
|
---|
[1932] | 2326 | ray.mRelativePvsContribution /= (float)viewCells.size();
|
---|
[1931] | 2327 | #endif
|
---|
[1946] | 2328 |
|
---|
[1900] | 2329 | #if USE_RAY_LENGTH_AS_CONTRIBUTION
|
---|
[1932] | 2330 | float c = 0.0f;
|
---|
[1942] | 2331 | if (terminationObj)
|
---|
| 2332 | c = ray.Length();
|
---|
[1932] | 2333 | ray.mRelativePvsContribution = ray.mPvsContribution = c;
|
---|
| 2334 | return c;
|
---|
[1900] | 2335 | #else
|
---|
[1942] | 2336 | return ABS_CONTRIBUTION_WEIGHT*ray.mPvsContribution +
|
---|
| 2337 | (1.0f - ABS_CONTRIBUTION_WEIGHT)*ray.mRelativePvsContribution;
|
---|
[1900] | 2338 | #endif
|
---|
[468] | 2339 | }
|
---|
| 2340 |
|
---|
| 2341 |
|
---|
[469] | 2342 | void ViewCellsManager::GetRaySets(const VssRayContainer &sourceRays,
|
---|
[485] | 2343 | const int maxSize,
|
---|
[503] | 2344 | VssRayContainer &usedRays,
|
---|
[485] | 2345 | VssRayContainer *savedRays) const
|
---|
[469] | 2346 | {
|
---|
[485] | 2347 | const int limit = min(maxSize, (int)sourceRays.size());
|
---|
[473] | 2348 | const float prop = (float)limit / ((float)sourceRays.size() + Limits::Small);
|
---|
[469] | 2349 |
|
---|
[485] | 2350 | VssRayContainer::const_iterator it, it_end = sourceRays.end();
|
---|
[469] | 2351 | for (it = sourceRays.begin(); it != it_end; ++ it)
|
---|
| 2352 | {
|
---|
[473] | 2353 | if (Random(1.0f) < prop)
|
---|
[485] | 2354 | usedRays.push_back(*it);
|
---|
| 2355 | else if (savedRays)
|
---|
| 2356 | savedRays->push_back(*it);
|
---|
[469] | 2357 | }
|
---|
| 2358 | }
|
---|
| 2359 |
|
---|
[477] | 2360 |
|
---|
[728] | 2361 | float ViewCellsManager::GetRendercost(ViewCell *viewCell) const
|
---|
[605] | 2362 | {
|
---|
[1709] | 2363 | return (float)mViewCellsTree->GetPvsCost(viewCell);
|
---|
[605] | 2364 | }
|
---|
| 2365 |
|
---|
| 2366 |
|
---|
[477] | 2367 | float ViewCellsManager::GetAccVcArea()
|
---|
[470] | 2368 | {
|
---|
| 2369 | // if already computed
|
---|
| 2370 | if (mTotalAreaValid)
|
---|
[728] | 2371 | {
|
---|
[470] | 2372 | return mTotalArea;
|
---|
[728] | 2373 | }
|
---|
[470] | 2374 |
|
---|
| 2375 | mTotalArea = 0;
|
---|
| 2376 | ViewCellContainer::const_iterator it, it_end = mViewCells.end();
|
---|
| 2377 |
|
---|
| 2378 | for (it = mViewCells.begin(); it != it_end; ++ it)
|
---|
[480] | 2379 | {
|
---|
| 2380 | //Debug << "area: " << GetArea(*it);
|
---|
[470] | 2381 | mTotalArea += GetArea(*it);
|
---|
[480] | 2382 | }
|
---|
| 2383 |
|
---|
[470] | 2384 | mTotalAreaValid = true;
|
---|
| 2385 |
|
---|
| 2386 | return mTotalArea;
|
---|
| 2387 | }
|
---|
| 2388 |
|
---|
[482] | 2389 |
|
---|
[475] | 2390 | void ViewCellsManager::PrintStatistics(ostream &s) const
|
---|
| 2391 | {
|
---|
[660] | 2392 | s << mCurrentViewCellsStats << endl;
|
---|
[475] | 2393 | }
|
---|
| 2394 |
|
---|
[477] | 2395 |
|
---|
[508] | 2396 | void ViewCellsManager::CreateUniqueViewCellIds()
|
---|
[482] | 2397 | {
|
---|
[651] | 2398 | if (ViewCellsTreeConstructed())
|
---|
[1284] | 2399 | {
|
---|
[651] | 2400 | mViewCellsTree->CreateUniqueViewCellsIds();
|
---|
[1284] | 2401 | }
|
---|
| 2402 | else // no view cells tree, handle view cells "myself"
|
---|
| 2403 | {
|
---|
[1551] | 2404 | int i = 0;
|
---|
| 2405 | ViewCellContainer::const_iterator vit, vit_end = mViewCells.end();
|
---|
| 2406 | for (vit = mViewCells.begin(); vit != vit_end; ++ vit)
|
---|
[1284] | 2407 | {
|
---|
[1557] | 2408 | if ((*vit)->GetId() != OUT_OF_BOUNDS_ID)
|
---|
| 2409 | {
|
---|
[1551] | 2410 | mViewCells[i]->SetId(i ++);
|
---|
[1557] | 2411 | }
|
---|
[1284] | 2412 | }
|
---|
| 2413 | }
|
---|
[508] | 2414 | }
|
---|
| 2415 |
|
---|
[1416] | 2416 |
|
---|
| 2417 | void ViewCellsManager::ExportViewCellsForViz(Exporter *exporter,
|
---|
| 2418 | const AxisAlignedBox3 *sceneBox,
|
---|
[1760] | 2419 | const bool colorCode,
|
---|
| 2420 | const AxisAlignedPlane *clipPlane
|
---|
[1416] | 2421 | ) const
|
---|
[508] | 2422 | {
|
---|
[482] | 2423 | ViewCellContainer::const_iterator it, it_end = mViewCells.end();
|
---|
[1763] | 2424 |
|
---|
[482] | 2425 | for (it = mViewCells.begin(); it != it_end; ++ it)
|
---|
[1763] | 2426 | {
|
---|
[574] | 2427 | if (!mOnlyValidViewCells || (*it)->GetValid())
|
---|
[1763] | 2428 | {
|
---|
[1571] | 2429 | ExportColor(exporter, *it, colorCode);
|
---|
[1416] | 2430 | ExportViewCellGeometry(exporter, *it, sceneBox, clipPlane);
|
---|
[574] | 2431 | }
|
---|
[482] | 2432 | }
|
---|
| 2433 | }
|
---|
| 2434 |
|
---|
| 2435 |
|
---|
[517] | 2436 | void ViewCellsManager::CreateViewCellMeshes()
|
---|
[503] | 2437 | {
|
---|
| 2438 | // convert to meshes
|
---|
| 2439 | ViewCellContainer::const_iterator it, it_end = mViewCells.end();
|
---|
| 2440 |
|
---|
| 2441 | for (it = mViewCells.begin(); it != it_end; ++ it)
|
---|
| 2442 | {
|
---|
[517] | 2443 | if (!(*it)->GetMesh())
|
---|
[1001] | 2444 | {
|
---|
[517] | 2445 | CreateMesh(*it);
|
---|
[1001] | 2446 | }
|
---|
[503] | 2447 | }
|
---|
| 2448 | }
|
---|
| 2449 |
|
---|
[508] | 2450 |
|
---|
[944] | 2451 | bool ViewCellsManager::ExportViewCells(const string filename,
|
---|
| 2452 | const bool exportPvs,
|
---|
| 2453 | const ObjectContainer &objects)
|
---|
[564] | 2454 | {
|
---|
[508] | 2455 | return false;
|
---|
| 2456 | }
|
---|
| 2457 |
|
---|
| 2458 |
|
---|
[610] | 2459 | void ViewCellsManager::CollectViewCells(const int n)
|
---|
[508] | 2460 | {
|
---|
[610] | 2461 | mNumActiveViewCells = n;
|
---|
| 2462 | mViewCells.clear();
|
---|
[1545] | 2463 | // implemented in subclasses
|
---|
[610] | 2464 | CollectViewCells();
|
---|
| 2465 | }
|
---|
[508] | 2466 |
|
---|
| 2467 |
|
---|
[1707] | 2468 | void ViewCellsManager::SetViewCellActive(ViewCell *vc) const
|
---|
| 2469 | {
|
---|
| 2470 | ViewCellContainer leaves;
|
---|
| 2471 | // sets the pointers to the currently active view cells
|
---|
| 2472 | mViewCellsTree->CollectLeaves(vc, leaves);
|
---|
| 2473 |
|
---|
| 2474 | ViewCellContainer::const_iterator lit, lit_end = leaves.end();
|
---|
| 2475 | for (lit = leaves.begin(); lit != lit_end; ++ lit)
|
---|
| 2476 | {
|
---|
| 2477 | dynamic_cast<ViewCellLeaf *>(*lit)->SetActiveViewCell(vc);
|
---|
| 2478 | }
|
---|
| 2479 | }
|
---|
| 2480 |
|
---|
| 2481 |
|
---|
[660] | 2482 | void ViewCellsManager::SetViewCellsActive()
|
---|
| 2483 | {
|
---|
[1707] | 2484 | // collect leaf view cells and set the pointers to
|
---|
| 2485 | // the currently active view cells
|
---|
[660] | 2486 | ViewCellContainer::const_iterator it, it_end = mViewCells.end();
|
---|
[944] | 2487 |
|
---|
[660] | 2488 | for (it = mViewCells.begin(); it != it_end; ++ it)
|
---|
| 2489 | {
|
---|
[1707] | 2490 | SetViewCellActive(*it);
|
---|
[660] | 2491 | }
|
---|
| 2492 | }
|
---|
[508] | 2493 |
|
---|
[840] | 2494 |
|
---|
| 2495 | int ViewCellsManager::GetMaxFilterSize() const
|
---|
| 2496 | {
|
---|
| 2497 | return mMaxFilterSize;
|
---|
| 2498 | }
|
---|
| 2499 |
|
---|
[1001] | 2500 |
|
---|
[840] | 2501 | static const bool USE_ASCII = true;
|
---|
| 2502 |
|
---|
[1001] | 2503 |
|
---|
[840] | 2504 | bool ViewCellsManager::ExportBoundingBoxes(const string filename,
|
---|
| 2505 | const ObjectContainer &objects) const
|
---|
| 2506 | {
|
---|
| 2507 | ObjectContainer::const_iterator it, it_end = objects.end();
|
---|
| 2508 |
|
---|
| 2509 | if (USE_ASCII)
|
---|
| 2510 | {
|
---|
| 2511 | ofstream boxesOut(filename.c_str());
|
---|
| 2512 | if (!boxesOut.is_open())
|
---|
| 2513 | return false;
|
---|
| 2514 |
|
---|
| 2515 | for (it = objects.begin(); it != it_end; ++ it)
|
---|
| 2516 | {
|
---|
| 2517 | MeshInstance *mi = dynamic_cast<MeshInstance *>(*it);
|
---|
| 2518 | const AxisAlignedBox3 box = mi->GetBox();
|
---|
| 2519 |
|
---|
| 2520 | boxesOut << mi->GetId() << " "
|
---|
| 2521 | << box.Min().x << " "
|
---|
| 2522 | << box.Min().y << " "
|
---|
| 2523 | << box.Min().z << " "
|
---|
| 2524 | << box.Max().x << " "
|
---|
| 2525 | << box.Max().y << " "
|
---|
| 2526 | << box.Max().z << endl;
|
---|
| 2527 | }
|
---|
| 2528 |
|
---|
| 2529 | boxesOut.close();
|
---|
| 2530 | }
|
---|
| 2531 | else
|
---|
| 2532 | {
|
---|
| 2533 | ofstream boxesOut(filename.c_str(), ios::binary);
|
---|
| 2534 |
|
---|
| 2535 | if (!boxesOut.is_open())
|
---|
| 2536 | return false;
|
---|
| 2537 |
|
---|
| 2538 | for (it = objects.begin(); it != it_end; ++ it)
|
---|
| 2539 | {
|
---|
| 2540 | MeshInstance *mi = dynamic_cast<MeshInstance *>(*it);
|
---|
| 2541 | const AxisAlignedBox3 box = mi->GetBox();
|
---|
| 2542 | Vector3 bmin = box.Min();
|
---|
| 2543 | Vector3 bmax = box.Max();
|
---|
[850] | 2544 | int id = mi->GetId();
|
---|
[840] | 2545 |
|
---|
[850] | 2546 | boxesOut.write(reinterpret_cast<char *>(&id), sizeof(int));
|
---|
[840] | 2547 | boxesOut.write(reinterpret_cast<char *>(&bmin), sizeof(Vector3));
|
---|
| 2548 | boxesOut.write(reinterpret_cast<char *>(&bmax), sizeof(Vector3));
|
---|
| 2549 | }
|
---|
| 2550 |
|
---|
| 2551 | boxesOut.close();
|
---|
| 2552 | }
|
---|
| 2553 |
|
---|
| 2554 | return true;
|
---|
| 2555 | }
|
---|
| 2556 |
|
---|
| 2557 |
|
---|
[850] | 2558 | bool ViewCellsManager::LoadBoundingBoxes(const string filename,
|
---|
| 2559 | IndexedBoundingBoxContainer &boxes) const
|
---|
[840] | 2560 | {
|
---|
[850] | 2561 | Vector3 bmin, bmax;
|
---|
| 2562 | int id;
|
---|
[840] | 2563 |
|
---|
[850] | 2564 | if (USE_ASCII)
|
---|
[840] | 2565 | {
|
---|
[850] | 2566 | ifstream boxesIn(filename.c_str());
|
---|
[840] | 2567 |
|
---|
[850] | 2568 | if (!boxesIn.is_open())
|
---|
[840] | 2569 | {
|
---|
[850] | 2570 | cout << "failed to open file " << filename << endl;
|
---|
| 2571 | return false;
|
---|
[840] | 2572 | }
|
---|
[850] | 2573 |
|
---|
| 2574 | string buf;
|
---|
| 2575 | while (!(getline(boxesIn, buf)).eof())
|
---|
[840] | 2576 | {
|
---|
[850] | 2577 | sscanf(buf.c_str(), "%d %f %f %f %f %f %f",
|
---|
| 2578 | &id, &bmin.x, &bmin.y, &bmin.z,
|
---|
| 2579 | &bmax.x, &bmax.y, &bmax.z);
|
---|
| 2580 |
|
---|
| 2581 | AxisAlignedBox3 box(bmin, bmax);
|
---|
| 2582 | // MeshInstance *mi = new MeshInstance();
|
---|
| 2583 | // HACK: set bounding box to new box
|
---|
| 2584 | //mi->mBox = box;
|
---|
| 2585 |
|
---|
| 2586 | boxes.push_back(IndexedBoundingBox(id, box));
|
---|
[840] | 2587 | }
|
---|
| 2588 |
|
---|
[850] | 2589 | boxesIn.close();
|
---|
[840] | 2590 | }
|
---|
[850] | 2591 | else
|
---|
[840] | 2592 | {
|
---|
[850] | 2593 | ifstream boxesIn(filename.c_str(), ios::binary);
|
---|
[840] | 2594 |
|
---|
[850] | 2595 | if (!boxesIn.is_open())
|
---|
| 2596 | return false;
|
---|
| 2597 |
|
---|
| 2598 | while (1)
|
---|
[840] | 2599 | {
|
---|
[850] | 2600 | boxesIn.read(reinterpret_cast<char *>(&id), sizeof(Vector3));
|
---|
| 2601 | boxesIn.read(reinterpret_cast<char *>(&bmin), sizeof(Vector3));
|
---|
| 2602 | boxesIn.read(reinterpret_cast<char *>(&bmax), sizeof(Vector3));
|
---|
| 2603 |
|
---|
| 2604 | if (boxesIn.eof())
|
---|
| 2605 | break;
|
---|
| 2606 |
|
---|
| 2607 |
|
---|
| 2608 | AxisAlignedBox3 box(bmin, bmax);
|
---|
| 2609 | MeshInstance *mi = new MeshInstance(NULL);
|
---|
| 2610 |
|
---|
| 2611 | // HACK: set bounding box to new box
|
---|
| 2612 | //mi->mBox = box;
|
---|
| 2613 | //boxes.push_back(mi);
|
---|
| 2614 | boxes.push_back(IndexedBoundingBox(id, box));
|
---|
[840] | 2615 | }
|
---|
| 2616 |
|
---|
[850] | 2617 | boxesIn.close();
|
---|
[840] | 2618 | }
|
---|
| 2619 |
|
---|
| 2620 | return true;
|
---|
[850] | 2621 | }
|
---|
[840] | 2622 |
|
---|
[931] | 2623 |
|
---|
| 2624 | float ViewCellsManager::GetFilterWidth()
|
---|
| 2625 | {
|
---|
| 2626 | return mFilterWidth;
|
---|
| 2627 | }
|
---|
| 2628 |
|
---|
| 2629 |
|
---|
| 2630 | float ViewCellsManager::GetAbsFilterWidth()
|
---|
| 2631 | {
|
---|
| 2632 | return Magnitude(mViewSpaceBox.Size()) * mFilterWidth;
|
---|
| 2633 | }
|
---|
| 2634 |
|
---|
| 2635 |
|
---|
[1168] | 2636 | void ViewCellsManager::UpdateScalarPvsSize(ViewCell *vc,
|
---|
[1709] | 2637 | const float pvsCost,
|
---|
[1168] | 2638 | const int entriesInPvs) const
|
---|
[1002] | 2639 | {
|
---|
[1709] | 2640 | vc->mPvsCost = pvsCost;
|
---|
[1160] | 2641 | vc->mEntriesInPvs = entriesInPvs;
|
---|
| 2642 |
|
---|
[1002] | 2643 | vc->mPvsSizeValid = true;
|
---|
| 2644 | }
|
---|
| 2645 |
|
---|
| 2646 |
|
---|
[1021] | 2647 | void
|
---|
| 2648 | ViewCellsManager::ApplyFilter(ViewCell *viewCell,
|
---|
| 2649 | KdTree *kdTree,
|
---|
| 2650 | const float viewSpaceFilterSize,
|
---|
| 2651 | const float spatialFilterSize,
|
---|
| 2652 | ObjectPvs &pvs
|
---|
| 2653 | )
|
---|
| 2654 | {
|
---|
| 2655 | // extend the pvs of the viewcell by pvs of its neighbors
|
---|
| 2656 | // and apply spatial filter by including all neighbors of the objects
|
---|
| 2657 | // in the pvs
|
---|
| 2658 |
|
---|
| 2659 | // get all viewcells intersecting the viewSpaceFilterBox
|
---|
| 2660 | // and compute the pvs union
|
---|
| 2661 |
|
---|
| 2662 | //Vector3 center = viewCell->GetBox().Center();
|
---|
| 2663 | // Vector3 center = m->mBox.Center();
|
---|
[1679] | 2664 |
|
---|
| 2665 | // AxisAlignedBox3 box(center - Vector3(viewSpaceFilterSize/2),
|
---|
| 2666 | // center + Vector3(viewSpaceFilterSize/2));
|
---|
[1021] | 2667 | if (!ViewCellsConstructed())
|
---|
| 2668 | return;
|
---|
| 2669 |
|
---|
[1679] | 2670 | if (viewSpaceFilterSize >= 0.0f) {
|
---|
[1021] | 2671 |
|
---|
[1679] | 2672 | const bool usePrVS = false;
|
---|
[1021] | 2673 |
|
---|
[1679] | 2674 | if (!usePrVS) {
|
---|
| 2675 | AxisAlignedBox3 box = GetViewCellBox(viewCell);
|
---|
| 2676 | box.Enlarge(Vector3(viewSpaceFilterSize/2));
|
---|
[1021] | 2677 |
|
---|
[1679] | 2678 | ViewCellContainer viewCells;
|
---|
| 2679 | ComputeBoxIntersections(box, viewCells);
|
---|
| 2680 |
|
---|
| 2681 | // cout<<"box="<<box<<endl;
|
---|
| 2682 | ViewCellContainer::const_iterator it = viewCells.begin(), it_end = viewCells.end();
|
---|
| 2683 |
|
---|
[1740] | 2684 | for (; it != it_end; ++ it)
|
---|
| 2685 | {
|
---|
| 2686 | ObjectPvs interPvs;
|
---|
[1679] | 2687 | //cout<<"v"<<i<<" pvs="<<(*it)->GetPvs().mEntries.size()<<endl;
|
---|
[1740] | 2688 | ObjectPvs::Merge(interPvs, pvs, (*it)->GetPvs());
|
---|
| 2689 |
|
---|
| 2690 | pvs = interPvs;
|
---|
[1679] | 2691 | }
|
---|
[1740] | 2692 | } else
|
---|
| 2693 | {
|
---|
[1679] | 2694 | PrVs prvs;
|
---|
| 2695 | AxisAlignedBox3 box = GetViewCellBox(viewCell);
|
---|
| 2696 |
|
---|
| 2697 | // mViewCellsManager->SetMaxFilterSize(1);
|
---|
| 2698 | GetPrVS(box.Center(), prvs, viewSpaceFilterSize);
|
---|
| 2699 | pvs = prvs.mViewCell->GetPvs();
|
---|
| 2700 | DeleteLocalMergeTree(prvs.mViewCell);
|
---|
| 2701 | }
|
---|
[1740] | 2702 | }
|
---|
| 2703 | else
|
---|
| 2704 | {
|
---|
[1679] | 2705 | pvs = viewCell->GetPvs();
|
---|
[1740] | 2706 | }
|
---|
[1679] | 2707 |
|
---|
| 2708 | if (spatialFilterSize >=0.0f)
|
---|
| 2709 | ApplySpatialFilter(kdTree, spatialFilterSize, pvs);
|
---|
| 2710 |
|
---|
[1021] | 2711 | }
|
---|
| 2712 |
|
---|
| 2713 |
|
---|
| 2714 |
|
---|
| 2715 | void
|
---|
| 2716 | ViewCellsManager::ApplyFilter(KdTree *kdTree,
|
---|
| 2717 | const float relViewSpaceFilterSize,
|
---|
| 2718 | const float relSpatialFilterSize
|
---|
| 2719 | )
|
---|
| 2720 | {
|
---|
| 2721 |
|
---|
| 2722 | if (!ViewCellsConstructed())
|
---|
| 2723 | return;
|
---|
| 2724 |
|
---|
[1679] | 2725 | ViewCellContainer::const_iterator it, it_end = mViewCells.end();
|
---|
[1021] | 2726 |
|
---|
[1679] | 2727 | ObjectPvs *newPvs;
|
---|
| 2728 | newPvs = new ObjectPvs[mViewCells.size()];
|
---|
[1021] | 2729 |
|
---|
[1679] | 2730 | float viewSpaceFilterSize = Magnitude(mViewSpaceBox.Size())*relViewSpaceFilterSize;
|
---|
| 2731 | float spatialFilterSize = Magnitude(kdTree->GetBox().Size())*relSpatialFilterSize;
|
---|
[1715] | 2732 |
|
---|
[1679] | 2733 | int i;
|
---|
| 2734 | for (i=0, it = mViewCells.begin(); it != it_end; ++ it, ++ i) {
|
---|
[1715] | 2735 | ApplyFilter(*it,
|
---|
| 2736 | kdTree,
|
---|
| 2737 | viewSpaceFilterSize,
|
---|
| 2738 | spatialFilterSize,
|
---|
| 2739 | newPvs[i]
|
---|
| 2740 | );
|
---|
[1679] | 2741 | }
|
---|
[1715] | 2742 |
|
---|
[1679] | 2743 | // now replace all pvss
|
---|
| 2744 | for (i = 0, it = mViewCells.begin(); it != it_end; ++ it, ++ i) {
|
---|
[1715] | 2745 |
|
---|
| 2746 | ObjectPvs &pvs = (*it)->GetPvs();
|
---|
| 2747 | pvs.Clear();
|
---|
| 2748 | pvs = newPvs[i];
|
---|
| 2749 | newPvs[i].Clear();
|
---|
[1679] | 2750 | }
|
---|
[1021] | 2751 |
|
---|
[1679] | 2752 | delete [] newPvs;
|
---|
| 2753 | }
|
---|
[1021] | 2754 |
|
---|
[1679] | 2755 |
|
---|
[1021] | 2756 | void
|
---|
| 2757 | ViewCellsManager::ApplySpatialFilter(
|
---|
| 2758 | KdTree *kdTree,
|
---|
| 2759 | const float spatialFilterSize,
|
---|
| 2760 | ObjectPvs &pvs
|
---|
| 2761 | )
|
---|
| 2762 | {
|
---|
[1716] | 2763 | // now compute a new Pvs by including also objects intersecting the
|
---|
| 2764 | // extended boxes of visible objects
|
---|
| 2765 | Intersectable::NewMail();
|
---|
[1742] | 2766 |
|
---|
| 2767 | ObjectPvsIterator pit = pvs.GetIterator();
|
---|
| 2768 |
|
---|
| 2769 | while (pit.HasMoreEntries())
|
---|
| 2770 | {
|
---|
| 2771 | ObjectPvsEntry entry = pit.Next();
|
---|
[1716] | 2772 |
|
---|
[1742] | 2773 | Intersectable *object = entry.mObject;
|
---|
[1189] | 2774 | object->Mail();
|
---|
[1742] | 2775 | }
|
---|
[1021] | 2776 |
|
---|
| 2777 | ObjectPvs nPvs;
|
---|
[1189] | 2778 | int nPvsSize = 0;
|
---|
[1742] | 2779 |
|
---|
| 2780 | ObjectPvsIterator pit2 = pvs.GetIterator();
|
---|
[1021] | 2781 |
|
---|
[1742] | 2782 | while (pit2.HasMoreEntries())
|
---|
| 2783 | {
|
---|
| 2784 | // now go through the pvs again
|
---|
| 2785 | ObjectPvsEntry entry = pit2.Next();
|
---|
| 2786 | Intersectable *object = entry.mObject;
|
---|
[1021] | 2787 |
|
---|
[1742] | 2788 | // Vector3 center = object->GetBox().Center();
|
---|
| 2789 | // AxisAlignedBox3 box(center - Vector3(spatialFilterSize/2),
|
---|
| 2790 | // center + Vector3(spatialFilterSize/2));
|
---|
| 2791 |
|
---|
| 2792 | AxisAlignedBox3 box = object->GetBox();
|
---|
| 2793 | box.Enlarge(Vector3(spatialFilterSize/2));
|
---|
| 2794 |
|
---|
| 2795 | ObjectContainer objects;
|
---|
| 2796 |
|
---|
| 2797 | // $$ warning collect objects takes only unmailed ones!
|
---|
| 2798 | kdTree->CollectObjects(box, objects);
|
---|
| 2799 | // cout<<"collected objects="<<objects.size()<<endl;
|
---|
| 2800 | ObjectContainer::const_iterator noi = objects.begin();
|
---|
| 2801 | for (; noi != objects.end(); ++ noi)
|
---|
| 2802 | {
|
---|
| 2803 | Intersectable *o = *noi;
|
---|
[1764] | 2804 |
|
---|
[1742] | 2805 | // $$ JB warning: pdfs are not correct at this point!
|
---|
| 2806 | nPvs.AddSample(o, Limits::Small);
|
---|
| 2807 | nPvsSize ++;
|
---|
| 2808 | }
|
---|
[1021] | 2809 | }
|
---|
[1740] | 2810 |
|
---|
[1764] | 2811 | // cout<<"nPvs size = "<<nPvsSize<<endl;
|
---|
[1740] | 2812 | pvs.MergeInPlace(nPvs);
|
---|
[1021] | 2813 | }
|
---|
| 2814 |
|
---|
| 2815 |
|
---|
[1787] | 2816 | void ViewCellsManager::MergeViewCellsRecursivly(ObjectPvs &pvs,
|
---|
| 2817 | const ViewCellContainer &viewCells) const
|
---|
[1786] | 2818 | {
|
---|
[1787] | 2819 | MergeViewCellsRecursivly(pvs, viewCells, 0, (int)viewCells.size() - 1);
|
---|
[1786] | 2820 | }
|
---|
| 2821 |
|
---|
[1787] | 2822 |
|
---|
| 2823 | void ViewCellsManager::MergeViewCellsRecursivly(ObjectPvs &pvs,
|
---|
| 2824 | const ViewCellContainer &viewCells,
|
---|
| 2825 | const int leftIdx,
|
---|
| 2826 | const int rightIdx) const
|
---|
| 2827 | {
|
---|
| 2828 | if (leftIdx == rightIdx)
|
---|
| 2829 | {
|
---|
| 2830 | pvs = viewCells[leftIdx]->GetPvs();
|
---|
| 2831 | }
|
---|
| 2832 | else
|
---|
| 2833 | {
|
---|
| 2834 | const int midSplit = (leftIdx + rightIdx) / 2;
|
---|
| 2835 |
|
---|
| 2836 | ObjectPvs leftPvs, rightPvs;
|
---|
| 2837 | MergeViewCellsRecursivly(leftPvs, viewCells, leftIdx, midSplit);
|
---|
| 2838 | MergeViewCellsRecursivly(rightPvs, viewCells, midSplit, rightIdx);
|
---|
| 2839 |
|
---|
| 2840 | ObjectPvs::Merge(pvs, leftPvs, rightPvs);
|
---|
| 2841 | }
|
---|
| 2842 | }
|
---|
| 2843 |
|
---|
| 2844 |
|
---|
[1761] | 2845 | PvsFilterStatistics
|
---|
[1715] | 2846 | ViewCellsManager::ApplyFilter2(ViewCell *viewCell,
|
---|
[1877] | 2847 | const bool useViewSpaceFilter,
|
---|
| 2848 | const float filterSize,
|
---|
| 2849 | ObjectPvs &pvs,
|
---|
| 2850 | vector<AxisAlignedBox3> *filteredBoxes
|
---|
| 2851 | )
|
---|
[1715] | 2852 | {
|
---|
[1877] | 2853 | //cout<<"y";
|
---|
[1761] | 2854 | PvsFilterStatistics stats;
|
---|
| 2855 |
|
---|
[1737] | 2856 | AxisAlignedBox3 vbox = GetViewCellBox(viewCell);
|
---|
| 2857 | Vector3 center = vbox.Center();
|
---|
[1786] | 2858 | // copy the PVS
|
---|
[1757] | 2859 | Intersectable::NewMail();
|
---|
[1877] | 2860 | ObjectPvs basePvs = viewCell->GetPvs();
|
---|
[1757] | 2861 | ObjectPvsIterator pit = basePvs.GetIterator();
|
---|
[1742] | 2862 |
|
---|
[1877] | 2863 | pvs.Reserve(viewCell->GetFilteredPvsSize());
|
---|
| 2864 |
|
---|
[1902] | 2865 | if (!mUseKdPvs)
|
---|
| 2866 | {
|
---|
| 2867 | // first mark all objects from this pvs
|
---|
| 2868 | while (pit.HasMoreEntries())
|
---|
| 2869 | {
|
---|
| 2870 | ObjectPvsEntry entry = pit.Next();
|
---|
| 2871 | Intersectable *object = entry.mObject;
|
---|
| 2872 | object->Mail();
|
---|
| 2873 | }
|
---|
[1716] | 2874 | }
|
---|
[1877] | 2875 |
|
---|
[1716] | 2876 | int pvsSize = 0;
|
---|
| 2877 | int nPvsSize = 0;
|
---|
[1761] | 2878 | float samples = (float)basePvs.GetSamples();
|
---|
| 2879 |
|
---|
[1787] | 2880 | Debug<<"f #s="<<samples<<" pvs size = "<<basePvs.GetSize();
|
---|
[1737] | 2881 | // cout<<"Filter size = "<<filterSize<<endl;
|
---|
| 2882 | // cout<<"vbox = "<<vbox<<endl;
|
---|
| 2883 | // cout<<"center = "<<center<<endl;
|
---|
[1716] | 2884 |
|
---|
[1737] | 2885 |
|
---|
[1757] | 2886 | // Minimal number of local samples to take into account
|
---|
| 2887 | // the local sampling density.
|
---|
| 2888 | // The size of the filter is a minimum of the conservative
|
---|
| 2889 | // local sampling density estimate (#rays intersecting teh viewcell and
|
---|
| 2890 | // the object)
|
---|
| 2891 | // and gobal estimate for the view cell
|
---|
| 2892 | // (total #rays intersecting the viewcell)
|
---|
[1824] | 2893 | int minLocalSamples = 2;
|
---|
| 2894 |
|
---|
[1737] | 2895 | float viewCellRadius = 0.5f*Magnitude(vbox.Diagonal());
|
---|
| 2896 |
|
---|
| 2897 | // now compute the filter box around the current viewCell
|
---|
[1757] | 2898 |
|
---|
[1737] | 2899 | if (useViewSpaceFilter) {
|
---|
[1877] | 2900 | // float radius = Max(viewCellRadius/100.0f, avgRadius - viewCellRadius);
|
---|
| 2901 | float radius = viewCellRadius/100.0f;
|
---|
| 2902 | vbox.Enlarge(radius);
|
---|
| 2903 | cout<<"vbox = "<<vbox<<endl;
|
---|
| 2904 | ViewCellContainer viewCells;
|
---|
| 2905 | ComputeBoxIntersections(vbox, viewCells);
|
---|
[1737] | 2906 |
|
---|
[1877] | 2907 | ViewCellContainer::const_iterator it = viewCells.begin(),
|
---|
| 2908 | it_end = viewCells.end();
|
---|
| 2909 | int i = 0;
|
---|
| 2910 | for (i=0; it != it_end; ++ it, ++ i)
|
---|
| 2911 | if ((*it) != viewCell) {
|
---|
| 2912 | //cout<<"v"<<i<<" pvs="<<(*it)->GetPvs().mEntries.size()<<endl;
|
---|
| 2913 | basePvs.MergeInPlace((*it)->GetPvs());
|
---|
| 2914 | }
|
---|
| 2915 |
|
---|
| 2916 | // update samples and globalC
|
---|
| 2917 | samples = (float)pvs.GetSamples();
|
---|
| 2918 | // cout<<"neighboring viewcells = "<<i-1<<endl;
|
---|
| 2919 | // cout<<"Samples' = "<<samples<<endl;
|
---|
| 2920 | }
|
---|
| 2921 |
|
---|
[1824] | 2922 | // Minimal number of samples so that filtering takes place
|
---|
| 2923 | #define MIN_SAMPLES 50
|
---|
[1877] | 2924 |
|
---|
[1761] | 2925 | if (samples > MIN_SAMPLES) {
|
---|
[1877] | 2926 | float globalC = 2.0f*filterSize/sqrt(samples);
|
---|
| 2927 |
|
---|
| 2928 | pit = basePvs.GetIterator();
|
---|
| 2929 |
|
---|
| 2930 | ObjectContainer objects;
|
---|
| 2931 |
|
---|
| 2932 | while (pit.HasMoreEntries()) {
|
---|
| 2933 | ObjectPvsEntry entry = pit.Next();
|
---|
| 2934 |
|
---|
| 2935 | Intersectable *object = entry.mObject;
|
---|
| 2936 | // compute filter size based on the distance and the numebr of samples
|
---|
| 2937 | AxisAlignedBox3 box = object->GetBox();
|
---|
| 2938 |
|
---|
| 2939 | float distance = Distance(center, box.Center());
|
---|
| 2940 | float globalRadius = distance*globalC;
|
---|
| 2941 |
|
---|
| 2942 | int objectSamples = (int)entry.mData.mSumPdf;
|
---|
| 2943 | float localRadius = MAX_FLOAT;
|
---|
| 2944 |
|
---|
| 2945 | localRadius = filterSize*0.5f*Magnitude(box.Diagonal())/
|
---|
| 2946 | sqrt((float)objectSamples);
|
---|
| 2947 |
|
---|
[1942] | 2948 | // cout<<"os="<<objectSamples<<" lr="<<localRadius<<" gr="<<globalRadius<<endl;
|
---|
[1877] | 2949 |
|
---|
| 2950 | // now compute the filter size
|
---|
| 2951 | float radius;
|
---|
| 2952 |
|
---|
[1824] | 2953 | #if 0
|
---|
[1877] | 2954 | if (objectSamples <= 1) {
|
---|
| 2955 | if (localRadius > globalRadius) {
|
---|
| 2956 | radius = 0.5flRadius;
|
---|
| 2957 | stats.mLocalFilterCount++;
|
---|
| 2958 | } else {
|
---|
| 2959 | radius = globalRadius;
|
---|
| 2960 | stats.mGlobalFilterCount++;
|
---|
| 2961 | }
|
---|
| 2962 | } else {
|
---|
| 2963 | radius = localRadius;
|
---|
| 2964 | stats.mLocalFilterCount++;
|
---|
| 2965 | }
|
---|
[1824] | 2966 | #else
|
---|
[1877] | 2967 | radius = 0.5f*globalRadius + 0.5f*localRadius;
|
---|
| 2968 | stats.mLocalFilterCount++;
|
---|
| 2969 | stats.mGlobalFilterCount++;
|
---|
[1824] | 2970 | #endif
|
---|
[1877] | 2971 |
|
---|
| 2972 | stats.mAvgFilterRadius += radius;
|
---|
| 2973 |
|
---|
| 2974 | // cout<<"box = "<<box<<endl;
|
---|
| 2975 | // cout<<"distance = "<<distance<<endl;
|
---|
| 2976 | // cout<<"radiues = "<<radius<<endl;
|
---|
| 2977 |
|
---|
| 2978 | box.Enlarge(Vector3(radius));
|
---|
| 2979 |
|
---|
| 2980 | if (filteredBoxes)
|
---|
| 2981 | filteredBoxes->push_back(box);
|
---|
| 2982 |
|
---|
| 2983 | objects.clear();
|
---|
| 2984 | // $$ warning collect objects takes only unmailed ones!
|
---|
| 2985 | CollectObjects(box, objects);
|
---|
| 2986 | // cout<<"collected objects="<<objects.size()<<endl;
|
---|
| 2987 | ObjectContainer::const_iterator noi = objects.begin();
|
---|
| 2988 | for (; noi != objects.end(); ++ noi) {
|
---|
| 2989 | Intersectable *o = *noi;
|
---|
| 2990 | // $$ JB warning: pdfs are not correct at this point!
|
---|
| 2991 | pvs.AddSampleDirty(o, Limits::Small);
|
---|
| 2992 | }
|
---|
| 2993 | }
|
---|
| 2994 | stats.mAvgFilterRadius /= (stats.mLocalFilterCount + stats.mGlobalFilterCount);
|
---|
[1757] | 2995 | }
|
---|
[1761] | 2996 |
|
---|
[1771] | 2997 | Debug<<" nPvs size = "<<pvs.GetSize()<<endl;
|
---|
[1877] | 2998 |
|
---|
[1902] | 2999 | if (!mUseKdPvs)
|
---|
| 3000 | {
|
---|
| 3001 | // copy the base pvs to the new pvs
|
---|
| 3002 | pit = basePvs.GetIterator();
|
---|
| 3003 | while (pit.HasMoreEntries())
|
---|
| 3004 | {
|
---|
| 3005 | ObjectPvsEntry entry = pit.Next();
|
---|
| 3006 | pvs.AddSampleDirty(entry.mObject, entry.mData.mSumPdf);
|
---|
| 3007 | }
|
---|
[1716] | 3008 | }
|
---|
[1877] | 3009 |
|
---|
| 3010 | pvs.SimpleSort();
|
---|
[1771] | 3011 | viewCell->SetFilteredPvsSize(pvs.GetSize());
|
---|
[1740] | 3012 |
|
---|
[1737] | 3013 | Intersectable::NewMail();
|
---|
[1761] | 3014 | return stats;
|
---|
[1715] | 3015 | }
|
---|
[1786] | 3016 |
|
---|
| 3017 |
|
---|
| 3018 |
|
---|
[1571] | 3019 | void ViewCellsManager::ExportColor(Exporter *exporter,
|
---|
| 3020 | ViewCell *vc,
|
---|
| 3021 | bool colorCode) const
|
---|
[1021] | 3022 | {
|
---|
| 3023 | const bool vcValid = CheckValidity(vc, mMinPvsSize, mMaxPvsSize);
|
---|
| 3024 |
|
---|
| 3025 | float importance = 0;
|
---|
| 3026 | static Material m;
|
---|
[1760] | 3027 | //cout << "color code: " << colorCode << endl;
|
---|
[1021] | 3028 | switch (mColorCode)
|
---|
| 3029 | {
|
---|
| 3030 | case 0: // Random
|
---|
| 3031 | {
|
---|
| 3032 | if (vcValid)
|
---|
| 3033 | {
|
---|
[1765] | 3034 | m.mDiffuseColor.r = 0.2f + RandomValue(0.0f, 0.8f);
|
---|
| 3035 | m.mDiffuseColor.g = 0.2f + RandomValue(0.0f, 0.8f);
|
---|
| 3036 | m.mDiffuseColor.b = 0.2f + RandomValue(0.0f, 0.8f);
|
---|
[1021] | 3037 | }
|
---|
| 3038 | else
|
---|
| 3039 | {
|
---|
| 3040 | m.mDiffuseColor.r = 0.0f;
|
---|
| 3041 | m.mDiffuseColor.g = 1.0f;
|
---|
| 3042 | m.mDiffuseColor.b = 0.0f;
|
---|
| 3043 | }
|
---|
| 3044 |
|
---|
| 3045 | exporter->SetForcedMaterial(m);
|
---|
| 3046 | return;
|
---|
| 3047 | }
|
---|
| 3048 |
|
---|
| 3049 | case 1: // pvs
|
---|
[1763] | 3050 | {
|
---|
[1021] | 3051 | if (mCurrentViewCellsStats.maxPvs)
|
---|
[1121] | 3052 | {
|
---|
[1763] | 3053 | importance = (float)mViewCellsTree->GetPvsCost(vc) /
|
---|
| 3054 | (float)mCurrentViewCellsStats.maxPvs;
|
---|
[1121] | 3055 | }
|
---|
[1021] | 3056 | }
|
---|
| 3057 | break;
|
---|
| 3058 | case 2: // merges
|
---|
| 3059 | {
|
---|
| 3060 | const int lSize = mViewCellsTree->GetNumInitialViewCells(vc);
|
---|
| 3061 | importance = (float)lSize / (float)mCurrentViewCellsStats.maxLeaves;
|
---|
| 3062 | }
|
---|
| 3063 | break;
|
---|
| 3064 | #if 0
|
---|
| 3065 | case 3: // merge tree differene
|
---|
| 3066 | {
|
---|
| 3067 | importance = (float)GetMaxTreeDiff(vc) /
|
---|
| 3068 | (float)(mVspBspTree->GetStatistics().maxDepth * 2);
|
---|
| 3069 |
|
---|
| 3070 | }
|
---|
| 3071 | break;
|
---|
| 3072 | #endif
|
---|
| 3073 | default:
|
---|
| 3074 | break;
|
---|
| 3075 | }
|
---|
| 3076 |
|
---|
| 3077 | // special color code for invalid view cells
|
---|
| 3078 | m.mDiffuseColor.r = importance;
|
---|
[1920] | 3079 | m.mDiffuseColor.b = 1.0f;//vcValid ? 0.0f : 1.0f;
|
---|
| 3080 | m.mDiffuseColor.g = 1.0f - importance;
|
---|
[1021] | 3081 |
|
---|
| 3082 | //Debug << "importance: " << importance << endl;
|
---|
| 3083 | exporter->SetForcedMaterial(m);
|
---|
| 3084 | }
|
---|
| 3085 |
|
---|
| 3086 |
|
---|
[1022] | 3087 | void ViewCellsManager::CollectMergeCandidates(const VssRayContainer &rays,
|
---|
| 3088 | vector<MergeCandidate> &candidates)
|
---|
| 3089 | {
|
---|
| 3090 | // implemented in subclasses
|
---|
| 3091 | }
|
---|
| 3092 |
|
---|
[1047] | 3093 |
|
---|
[1718] | 3094 | void ViewCellsManager::UpdatePvsForEvaluation()
|
---|
[1608] | 3095 | {
|
---|
[1718] | 3096 | ObjectPvs objPvs;
|
---|
| 3097 | UpdatePvsForEvaluation(mViewCellsTree->GetRoot(), objPvs);
|
---|
[1608] | 3098 | }
|
---|
| 3099 |
|
---|
[1168] | 3100 | void ViewCellsManager::UpdatePvsForEvaluation(ViewCell *root, ObjectPvs &pvs)
|
---|
| 3101 | {
|
---|
| 3102 | // terminate traversal
|
---|
| 3103 | if (root->IsLeaf())
|
---|
| 3104 | {
|
---|
[1709] | 3105 | //cout << "updating leaf" << endl;
|
---|
[1168] | 3106 | // we assume that pvs is explicitly stored in leaves
|
---|
| 3107 | pvs = root->GetPvs();
|
---|
[1707] | 3108 | UpdateScalarPvsSize(root, pvs.EvalPvsCost(), pvs.GetSize());
|
---|
[1168] | 3109 | return;
|
---|
| 3110 | }
|
---|
[1709] | 3111 |
|
---|
[1586] | 3112 | ////////////////
|
---|
| 3113 | //-- interior node => propagate pvs up the tree
|
---|
| 3114 |
|
---|
[1168] | 3115 | ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(root);
|
---|
[1606] | 3116 |
|
---|
| 3117 | // reset interior pvs
|
---|
[1168] | 3118 | interior->GetPvs().Clear();
|
---|
[1606] | 3119 | // reset recursive pvs
|
---|
[1168] | 3120 | pvs.Clear();
|
---|
[1695] | 3121 |
|
---|
| 3122 | // pvss of child nodes
|
---|
[1168] | 3123 | vector<ObjectPvs> pvsList;
|
---|
[1709] | 3124 | pvsList.resize((int)interior->mChildren.size());
|
---|
[1168] | 3125 |
|
---|
| 3126 | ViewCellContainer::const_iterator vit, vit_end = interior->mChildren.end();
|
---|
[1709] | 3127 |
|
---|
[1695] | 3128 | int i = 0;
|
---|
[1709] | 3129 |
|
---|
[1695] | 3130 | for (vit = interior->mChildren.begin(); vit != vit_end; ++ vit, ++ i)
|
---|
[1168] | 3131 | {
|
---|
[1586] | 3132 | //////////////////
|
---|
[1168] | 3133 | //-- recursivly compute child pvss
|
---|
[1695] | 3134 | UpdatePvsForEvaluation(*vit, pvsList[i]/*objPvs*/);
|
---|
[1168] | 3135 | }
|
---|
| 3136 |
|
---|
| 3137 | #if 1
|
---|
| 3138 | Intersectable::NewMail();
|
---|
| 3139 |
|
---|
| 3140 | //-- faster way of computing pvs:
|
---|
[1586] | 3141 | //-- construct merged pvs by adding
|
---|
| 3142 | //-- and only those of the next pvs which were not mailed.
|
---|
| 3143 | //-- note: sumpdf is not correct!!
|
---|
| 3144 |
|
---|
[1168] | 3145 | vector<ObjectPvs>::iterator oit = pvsList.begin();
|
---|
| 3146 |
|
---|
| 3147 | for (vit = interior->mChildren.begin(); vit != vit_end; ++ vit, ++ oit)
|
---|
| 3148 | {
|
---|
[1742] | 3149 | ObjectPvsIterator pit = (*oit).GetIterator();
|
---|
| 3150 |
|
---|
| 3151 | // first mark all object from this pvs
|
---|
| 3152 | while (pit.HasMoreEntries())
|
---|
| 3153 | {
|
---|
| 3154 | ObjectPvsEntry entry = pit.Next();
|
---|
[1168] | 3155 |
|
---|
[1742] | 3156 | Intersectable *intersect = entry.mObject;
|
---|
| 3157 |
|
---|
[1168] | 3158 | if (!intersect->Mailed())
|
---|
[1764] | 3159 | {
|
---|
[1742] | 3160 | pvs.AddSample(intersect, entry.mData.mSumPdf);
|
---|
[1168] | 3161 | intersect->Mail();
|
---|
| 3162 | }
|
---|
| 3163 | }
|
---|
| 3164 | }
|
---|
| 3165 |
|
---|
| 3166 | // store pvs in this node
|
---|
| 3167 | if (mViewCellsTree->ViewCellsStorage() == ViewCellsTree::PVS_IN_INTERIORS)
|
---|
| 3168 | {
|
---|
| 3169 | interior->SetPvs(pvs);
|
---|
| 3170 | }
|
---|
| 3171 |
|
---|
| 3172 | // set new pvs size
|
---|
[1707] | 3173 | UpdateScalarPvsSize(interior, pvs.EvalPvsCost(), pvs.GetSize());
|
---|
[1168] | 3174 |
|
---|
[1586] | 3175 | #else
|
---|
| 3176 | // really merge cells: slow put sumPdf is correct
|
---|
[1168] | 3177 | viewCellInterior->GetPvs().Merge(backVc->GetPvs());
|
---|
| 3178 | viewCellInterior->GetPvs().Merge(frontVc->GetPvs());
|
---|
| 3179 | #endif
|
---|
| 3180 | }
|
---|
| 3181 |
|
---|
[1174] | 3182 |
|
---|
| 3183 |
|
---|
[1145] | 3184 | /*******************************************************************/
|
---|
| 3185 | /* BspViewCellsManager implementation */
|
---|
| 3186 | /*******************************************************************/
|
---|
[440] | 3187 |
|
---|
[482] | 3188 |
|
---|
[1264] | 3189 | BspViewCellsManager::BspViewCellsManager(ViewCellsTree *vcTree, BspTree *bspTree):
|
---|
| 3190 | ViewCellsManager(vcTree), mBspTree(bspTree)
|
---|
[440] | 3191 | {
|
---|
[1004] | 3192 | Environment::GetSingleton()->GetIntValue("BspTree.Construction.samples", mInitialSamples);
|
---|
[1640] | 3193 |
|
---|
[587] | 3194 | mBspTree->SetViewCellsManager(this);
|
---|
[1545] | 3195 | mBspTree->SetViewCellsTree(mViewCellsTree);
|
---|
[440] | 3196 | }
|
---|
| 3197 |
|
---|
[462] | 3198 |
|
---|
[440] | 3199 | bool BspViewCellsManager::ViewCellsConstructed() const
|
---|
| 3200 | {
|
---|
| 3201 | return mBspTree->GetRoot() != NULL;
|
---|
| 3202 | }
|
---|
| 3203 |
|
---|
[480] | 3204 |
|
---|
[440] | 3205 | ViewCell *BspViewCellsManager::GenerateViewCell(Mesh *mesh) const
|
---|
| 3206 | {
|
---|
| 3207 | return new BspViewCell(mesh);
|
---|
| 3208 | }
|
---|
| 3209 |
|
---|
[480] | 3210 |
|
---|
[574] | 3211 | int BspViewCellsManager::ConstructSubdivision(const ObjectContainer &objects,
|
---|
| 3212 | const VssRayContainer &rays)
|
---|
[440] | 3213 | {
|
---|
[1545] | 3214 | // if view cells were already constructed, we can finish
|
---|
[440] | 3215 | if (ViewCellsConstructed())
|
---|
| 3216 | return 0;
|
---|
| 3217 |
|
---|
| 3218 | int sampleContributions = 0;
|
---|
[503] | 3219 |
|
---|
[469] | 3220 | // construct view cells using the collected samples
|
---|
| 3221 | RayContainer constructionRays;
|
---|
| 3222 | VssRayContainer savedRays;
|
---|
[440] | 3223 |
|
---|
[1563] | 3224 | // choose a a number of rays based on the ratio of cast rays / requested rays
|
---|
[574] | 3225 | const int limit = min(mInitialSamples, (int)rays.size());
|
---|
[469] | 3226 | VssRayContainer::const_iterator it, it_end = rays.end();
|
---|
[448] | 3227 |
|
---|
[473] | 3228 | const float prop = (float)limit / ((float)rays.size() + Limits::Small);
|
---|
[1586] | 3229 |
|
---|
[469] | 3230 | for (it = rays.begin(); it != it_end; ++ it)
|
---|
| 3231 | {
|
---|
[473] | 3232 | if (Random(1.0f) < prop)
|
---|
[469] | 3233 | constructionRays.push_back(new Ray(*(*it)));
|
---|
| 3234 | else
|
---|
| 3235 | savedRays.push_back(*it);
|
---|
| 3236 | }
|
---|
[440] | 3237 |
|
---|
[1545] | 3238 | if (!mUsePredefinedViewCells)
|
---|
[503] | 3239 | {
|
---|
| 3240 | // no view cells loaded
|
---|
[587] | 3241 | mBspTree->Construct(objects, constructionRays, &mViewSpaceBox);
|
---|
[469] | 3242 | // collect final view cells
|
---|
| 3243 | mBspTree->CollectViewCells(mViewCells);
|
---|
[503] | 3244 | }
|
---|
[469] | 3245 | else
|
---|
[1551] | 3246 | {
|
---|
[1545] | 3247 | // use predefined view cells geometry =>
|
---|
| 3248 | // contruct bsp hierarchy over them
|
---|
[469] | 3249 | mBspTree->Construct(mViewCells);
|
---|
| 3250 | }
|
---|
| 3251 |
|
---|
| 3252 | // destroy rays created only for construction
|
---|
| 3253 | CLEAR_CONTAINER(constructionRays);
|
---|
| 3254 |
|
---|
[440] | 3255 | Debug << mBspTree->GetStatistics() << endl;
|
---|
[660] | 3256 | Debug << "\nView cells after construction:\n" << mCurrentViewCellsStats << endl;
|
---|
[480] | 3257 |
|
---|
[469] | 3258 | // recast rest of the rays
|
---|
[649] | 3259 | if (SAMPLE_AFTER_SUBDIVISION)
|
---|
| 3260 | ComputeSampleContributions(savedRays, true, false);
|
---|
[469] | 3261 |
|
---|
[719] | 3262 | // real meshes are contructed at this stage
|
---|
| 3263 | if (0)
|
---|
| 3264 | {
|
---|
| 3265 | cout << "finalizing view cells ... ";
|
---|
| 3266 | FinalizeViewCells(true);
|
---|
| 3267 | cout << "finished" << endl;
|
---|
| 3268 | }
|
---|
| 3269 |
|
---|
[440] | 3270 | return sampleContributions;
|
---|
| 3271 | }
|
---|
| 3272 |
|
---|
[503] | 3273 |
|
---|
[480] | 3274 | void BspViewCellsManager::CollectViewCells()
|
---|
[1545] | 3275 | {
|
---|
[587] | 3276 | if (!ViewCellsTreeConstructed())
|
---|
[1545] | 3277 | { // view cells tree constructed
|
---|
[587] | 3278 | mBspTree->CollectViewCells(mViewCells);
|
---|
| 3279 | }
|
---|
| 3280 | else
|
---|
[1545] | 3281 | { // we can use the view cells tree hierarchy to get the right set
|
---|
| 3282 | mViewCellsTree->CollectBestViewCellSet(mViewCells, mNumActiveViewCells);
|
---|
[587] | 3283 | }
|
---|
[480] | 3284 | }
|
---|
[468] | 3285 |
|
---|
[503] | 3286 |
|
---|
[471] | 3287 | float BspViewCellsManager::GetProbability(ViewCell *viewCell)
|
---|
[440] | 3288 | {
|
---|
[591] | 3289 | if (1)
|
---|
| 3290 | return GetVolume(viewCell) / GetViewSpaceBox().GetVolume();
|
---|
| 3291 | else
|
---|
[1545] | 3292 | // compute view cell area as subsititute for probability
|
---|
[591] | 3293 | return GetArea(viewCell) / GetAccVcArea();
|
---|
[466] | 3294 | }
|
---|
[440] | 3295 |
|
---|
[503] | 3296 |
|
---|
[440] | 3297 |
|
---|
[468] | 3298 | int BspViewCellsManager::CastLineSegment(const Vector3 &origin,
|
---|
| 3299 | const Vector3 &termination,
|
---|
| 3300 | ViewCellContainer &viewcells)
|
---|
[440] | 3301 | {
|
---|
[468] | 3302 | return mBspTree->CastLineSegment(origin, termination, viewcells);
|
---|
| 3303 | }
|
---|
| 3304 |
|
---|
| 3305 |
|
---|
[1551] | 3306 | void ViewCellsManager::ExportMergedViewCells(const ObjectContainer &objects)
|
---|
[1545] | 3307 | {
|
---|
| 3308 | // save color code
|
---|
| 3309 | const int savedColorCode = mColorCode;
|
---|
| 3310 |
|
---|
[1763] | 3311 | Exporter *exporter;
|
---|
| 3312 |
|
---|
| 3313 | #if 0
|
---|
[1545] | 3314 | // export merged view cells
|
---|
| 3315 | mColorCode = 0; // use random colors
|
---|
| 3316 |
|
---|
[1763] | 3317 | exporter = Exporter::GetExporter("merged_view_cells.wrl");
|
---|
[1545] | 3318 |
|
---|
| 3319 | cout << "exporting view cells after merge ... ";
|
---|
| 3320 |
|
---|
| 3321 | if (exporter)
|
---|
| 3322 | {
|
---|
| 3323 | if (mExportGeometry)
|
---|
| 3324 | {
|
---|
| 3325 | exporter->ExportGeometry(objects);
|
---|
| 3326 | }
|
---|
| 3327 |
|
---|
| 3328 | exporter->SetFilled();
|
---|
[1760] | 3329 | ExportViewCellsForViz(exporter, NULL, mColorCode, GetClipPlane());
|
---|
[1545] | 3330 |
|
---|
| 3331 | delete exporter;
|
---|
| 3332 | }
|
---|
| 3333 | cout << "finished" << endl;
|
---|
[1763] | 3334 | #endif
|
---|
[1545] | 3335 |
|
---|
| 3336 | // export merged view cells using pvs color coding
|
---|
| 3337 | exporter = Exporter::GetExporter("merged_view_cells_pvs.wrl");
|
---|
| 3338 | cout << "exporting view cells after merge (pvs size) ... ";
|
---|
| 3339 |
|
---|
| 3340 | if (exporter)
|
---|
| 3341 | {
|
---|
| 3342 | if (mExportGeometry)
|
---|
| 3343 | {
|
---|
| 3344 | exporter->ExportGeometry(objects);
|
---|
| 3345 | }
|
---|
| 3346 |
|
---|
| 3347 | exporter->SetFilled();
|
---|
[1760] | 3348 | mColorCode = 1;
|
---|
[1763] | 3349 |
|
---|
[1760] | 3350 | ExportViewCellsForViz(exporter, NULL, mColorCode, GetClipPlane());
|
---|
[1545] | 3351 |
|
---|
| 3352 | delete exporter;
|
---|
| 3353 | }
|
---|
| 3354 | cout << "finished" << endl;
|
---|
| 3355 |
|
---|
| 3356 | mColorCode = savedColorCode;
|
---|
| 3357 | }
|
---|
| 3358 |
|
---|
| 3359 |
|
---|
[503] | 3360 | int BspViewCellsManager::PostProcess(const ObjectContainer &objects,
|
---|
[468] | 3361 | const VssRayContainer &rays)
|
---|
| 3362 | {
|
---|
[469] | 3363 | if (!ViewCellsConstructed())
|
---|
[441] | 3364 | {
|
---|
| 3365 | Debug << "view cells not constructed" << endl;
|
---|
| 3366 | return 0;
|
---|
| 3367 | }
|
---|
[590] | 3368 |
|
---|
[1414] | 3369 | // view cells already finished before post processing step,
|
---|
| 3370 | // i.e., because they were loaded from disc
|
---|
[590] | 3371 | if (mViewCellsFinished)
|
---|
| 3372 | {
|
---|
| 3373 | FinalizeViewCells(true);
|
---|
| 3374 | EvaluateViewCellsStats();
|
---|
| 3375 |
|
---|
| 3376 | return 0;
|
---|
| 3377 | }
|
---|
| 3378 |
|
---|
[1444] | 3379 | //////////////////
|
---|
[1414] | 3380 | //-- merge leaves of the view cell hierarchy
|
---|
| 3381 |
|
---|
[649] | 3382 | cout << "starting post processing using " << mPostProcessSamples << " samples ... ";
|
---|
| 3383 | long startTime = GetTime();
|
---|
| 3384 |
|
---|
| 3385 | VssRayContainer postProcessRays;
|
---|
| 3386 | GetRaySets(rays, mPostProcessSamples, postProcessRays);
|
---|
| 3387 |
|
---|
[592] | 3388 | if (mMergeViewCells)
|
---|
[591] | 3389 | {
|
---|
[660] | 3390 | cout << "constructing visibility based merge tree" << endl;
|
---|
[650] | 3391 | mViewCellsTree->ConstructMergeTree(rays, objects);
|
---|
[649] | 3392 | }
|
---|
| 3393 | else
|
---|
| 3394 | {
|
---|
[660] | 3395 | cout << "constructing spatial merge tree" << endl;
|
---|
[1545] | 3396 | ViewCell *root;
|
---|
| 3397 | // the spatial merge tree is difficult to build for
|
---|
| 3398 | // this type of construction, as view cells cover several
|
---|
| 3399 | // leaves => create dummy tree which is only 2 levels deep
|
---|
| 3400 | if (mUsePredefinedViewCells)
|
---|
| 3401 | {
|
---|
| 3402 | root = ConstructDummyMergeTree(mBspTree->GetRoot());
|
---|
| 3403 | }
|
---|
| 3404 | else
|
---|
| 3405 | {
|
---|
| 3406 | // create spatial merge hierarchy
|
---|
| 3407 | root = ConstructSpatialMergeTree(mBspTree->GetRoot());
|
---|
| 3408 | }
|
---|
| 3409 |
|
---|
[752] | 3410 | mViewCellsTree->SetRoot(root);
|
---|
| 3411 |
|
---|
[1415] | 3412 | // recompute pvs in the whole hierarchy
|
---|
[752] | 3413 | ObjectPvs pvs;
|
---|
| 3414 | UpdatePvsForEvaluation(root, pvs);
|
---|
[649] | 3415 | }
|
---|
[440] | 3416 |
|
---|
[1415] | 3417 | cout << "finished" << endl;
|
---|
| 3418 | cout << "merged view cells in "
|
---|
| 3419 | << TimeDiff(startTime, GetTime()) * 1e-3 << " secs" << endl;
|
---|
| 3420 |
|
---|
| 3421 | Debug << "Postprocessing: Merged view cells in "
|
---|
| 3422 | << TimeDiff(startTime, GetTime()) * 1e-3 << " secs" << endl << endl;
|
---|
| 3423 |
|
---|
| 3424 |
|
---|
[1418] | 3425 | ////////////////////////
|
---|
[1444] | 3426 | //-- visualization and statistics after merge
|
---|
[1415] | 3427 |
|
---|
[666] | 3428 | if (1)
|
---|
| 3429 | {
|
---|
| 3430 | char mstats[100];
|
---|
[1004] | 3431 | Environment::GetSingleton()->GetStringValue("ViewCells.mergeStats", mstats);
|
---|
[666] | 3432 | mViewCellsTree->ExportStats(mstats);
|
---|
| 3433 | }
|
---|
[650] | 3434 |
|
---|
[1551] | 3435 | // recompute view cells and stats
|
---|
| 3436 | ResetViewCells();
|
---|
[660] | 3437 | Debug << "\nView cells after merge:\n" << mCurrentViewCellsStats << endl;
|
---|
[600] | 3438 |
|
---|
[1551] | 3439 | // visualization of the view cells
|
---|
[1763] | 3440 | if (1) ExportMergedViewCells(objects);
|
---|
[600] | 3441 |
|
---|
[719] | 3442 | // compute final meshes and volume / area
|
---|
| 3443 | if (1) FinalizeViewCells(true);
|
---|
[840] | 3444 |
|
---|
[650] | 3445 | return 0;
|
---|
[440] | 3446 | }
|
---|
| 3447 |
|
---|
[477] | 3448 |
|
---|
| 3449 | BspViewCellsManager::~BspViewCellsManager()
|
---|
| 3450 | {
|
---|
| 3451 | }
|
---|
| 3452 |
|
---|
| 3453 |
|
---|
[440] | 3454 | int BspViewCellsManager::GetType() const
|
---|
| 3455 | {
|
---|
| 3456 | return BSP;
|
---|
| 3457 | }
|
---|
| 3458 |
|
---|
| 3459 |
|
---|
| 3460 | void BspViewCellsManager::Visualize(const ObjectContainer &objects,
|
---|
[466] | 3461 | const VssRayContainer &sampleRays)
|
---|
[440] | 3462 | {
|
---|
[469] | 3463 | if (!ViewCellsConstructed())
|
---|
| 3464 | return;
|
---|
[574] | 3465 |
|
---|
[1563] | 3466 | const int savedColorCode = mColorCode;
|
---|
[1551] | 3467 |
|
---|
[600] | 3468 | if (1) // export final view cells
|
---|
[440] | 3469 | {
|
---|
[1020] | 3470 | mColorCode = 1; // hack color code
|
---|
[1415] | 3471 | Exporter *exporter = Exporter::GetExporter("final_view_cells.wrl");
|
---|
[600] | 3472 |
|
---|
| 3473 | cout << "exporting view cells after merge (pvs size) ... ";
|
---|
[587] | 3474 |
|
---|
[469] | 3475 | if (exporter)
|
---|
[440] | 3476 | {
|
---|
[600] | 3477 | if (mExportGeometry)
|
---|
[1416] | 3478 | {
|
---|
[600] | 3479 | exporter->ExportGeometry(objects);
|
---|
[1416] | 3480 | }
|
---|
[590] | 3481 |
|
---|
[1760] | 3482 | ExportViewCellsForViz(exporter, NULL, mColorCode, GetClipPlane());
|
---|
[469] | 3483 | delete exporter;
|
---|
[440] | 3484 | }
|
---|
[469] | 3485 | cout << "finished" << endl;
|
---|
[503] | 3486 | }
|
---|
[1551] | 3487 |
|
---|
[1545] | 3488 | // reset color code
|
---|
[600] | 3489 | mColorCode = savedColorCode;
|
---|
| 3490 |
|
---|
[1416] | 3491 |
|
---|
| 3492 | //////////////////
|
---|
[469] | 3493 | //-- visualization of the BSP splits
|
---|
[1416] | 3494 |
|
---|
[469] | 3495 | bool exportSplits = false;
|
---|
[1004] | 3496 | Environment::GetSingleton()->GetBoolValue("BspTree.Visualization.exportSplits", exportSplits);
|
---|
[503] | 3497 |
|
---|
[469] | 3498 | if (exportSplits)
|
---|
[440] | 3499 | {
|
---|
[469] | 3500 | cout << "exporting splits ... ";
|
---|
[477] | 3501 | ExportSplits(objects);
|
---|
[469] | 3502 | cout << "finished" << endl;
|
---|
[440] | 3503 | }
|
---|
[477] | 3504 |
|
---|
[1570] | 3505 | int leafOut;
|
---|
| 3506 | Environment::GetSingleton()->GetIntValue("ViewCells.Visualization.maxOutput", leafOut);
|
---|
| 3507 | const int raysOut = 100;
|
---|
| 3508 | ExportSingleViewCells(objects, leafOut, false, true, false, raysOut, "");
|
---|
[440] | 3509 | }
|
---|
| 3510 |
|
---|
| 3511 |
|
---|
[477] | 3512 | void BspViewCellsManager::ExportSplits(const ObjectContainer &objects)
|
---|
[440] | 3513 | {
|
---|
| 3514 | Exporter *exporter = Exporter::GetExporter("bsp_splits.x3d");
|
---|
| 3515 |
|
---|
[503] | 3516 | if (exporter)
|
---|
| 3517 | {
|
---|
[598] | 3518 | //exporter->SetFilled();
|
---|
| 3519 | if (mExportGeometry)
|
---|
[1545] | 3520 | {
|
---|
[598] | 3521 | exporter->ExportGeometry(objects);
|
---|
[1545] | 3522 | }
|
---|
[598] | 3523 |
|
---|
[503] | 3524 | Material m;
|
---|
[440] | 3525 | m.mDiffuseColor = RgbColor(1, 0, 0);
|
---|
| 3526 | exporter->SetForcedMaterial(m);
|
---|
| 3527 | exporter->SetWireframe();
|
---|
[503] | 3528 |
|
---|
[440] | 3529 | exporter->ExportBspSplits(*mBspTree, true);
|
---|
| 3530 |
|
---|
[1545] | 3531 | // NOTE: take forced material, else big scenes cannot be viewed
|
---|
[440] | 3532 | m.mDiffuseColor = RgbColor(0, 1, 0);
|
---|
| 3533 | exporter->SetForcedMaterial(m);
|
---|
[482] | 3534 | //exporter->ResetForcedMaterial();
|
---|
| 3535 |
|
---|
[440] | 3536 | delete exporter;
|
---|
| 3537 | }
|
---|
| 3538 | }
|
---|
| 3539 |
|
---|
[477] | 3540 |
|
---|
[1570] | 3541 | void BspViewCellsManager::ExportSingleViewCells(const ObjectContainer &objects,
|
---|
| 3542 | const int maxViewCells,
|
---|
| 3543 | const bool sortViewCells,
|
---|
| 3544 | const bool exportPvs,
|
---|
| 3545 | const bool exportRays,
|
---|
| 3546 | const int maxRays,
|
---|
| 3547 | const string prefix,
|
---|
| 3548 | VssRayContainer *visRays)
|
---|
[440] | 3549 | {
|
---|
[1570] | 3550 | if (sortViewCells)
|
---|
| 3551 | { // sort view cells to visualize the largest view cells
|
---|
[1789] | 3552 | sort(mViewCells.begin(), mViewCells.end(), ViewCell::LargerRenderCost);
|
---|
[1570] | 3553 | }
|
---|
[440] | 3554 |
|
---|
[1545] | 3555 | //////////
|
---|
[1570] | 3556 | //-- some view cells for output
|
---|
[503] | 3557 |
|
---|
[1570] | 3558 | ViewCell::NewMail();
|
---|
| 3559 | const int limit = min(maxViewCells, (int)mViewCells.size());
|
---|
| 3560 |
|
---|
| 3561 | for (int i = 0; i < limit; ++ i)
|
---|
| 3562 | {
|
---|
| 3563 | const int idx = sortViewCells ? (int)RandomValue(0, (float)mViewCells.size() - 0.5f) : i;
|
---|
| 3564 | ViewCell *vc = mViewCells[idx];
|
---|
[503] | 3565 |
|
---|
[1570] | 3566 | if (vc->Mailed() || vc->GetId() == OUT_OF_BOUNDS_ID)
|
---|
| 3567 | continue;
|
---|
[587] | 3568 |
|
---|
[1570] | 3569 | vc->Mail();
|
---|
[503] | 3570 |
|
---|
[1570] | 3571 | ObjectPvs pvs;
|
---|
| 3572 | mViewCellsTree->GetPvs(vc, pvs);
|
---|
[582] | 3573 |
|
---|
[1571] | 3574 | char s[64]; sprintf(s, "%sviewcell-%04d.wrl", prefix.c_str(), i);
|
---|
[1570] | 3575 | Exporter *exporter = Exporter::GetExporter(s);
|
---|
| 3576 |
|
---|
[1709] | 3577 | cout << "view cell " << idx << ": pvs cost=" << (int)mViewCellsTree->GetPvsCost(vc) << endl;
|
---|
[582] | 3578 |
|
---|
[1570] | 3579 | if (exportRays)
|
---|
| 3580 | {
|
---|
| 3581 | ////////////
|
---|
| 3582 | //-- export rays piercing this view cell
|
---|
[469] | 3583 |
|
---|
[1571] | 3584 | // use rays stored with the view cells
|
---|
| 3585 | VssRayContainer vcRays, vcRays2, vcRays3;
|
---|
[1570] | 3586 | VssRayContainer collectRays;
|
---|
| 3587 |
|
---|
| 3588 | // collect initial view cells
|
---|
| 3589 | ViewCellContainer leaves;
|
---|
| 3590 | mViewCellsTree->CollectLeaves(vc, leaves);
|
---|
| 3591 |
|
---|
| 3592 | ViewCellContainer::const_iterator vit, vit_end = leaves.end();
|
---|
| 3593 | for (vit = leaves.begin(); vit != vit_end; ++ vit)
|
---|
| 3594 | {
|
---|
[1571] | 3595 | // prepare some rays for output
|
---|
[1696] | 3596 | VssRayContainer::const_iterator rit, rit_end = (*vit)->GetOrCreateRays()->end();
|
---|
| 3597 | for (rit = (*vit)->GetOrCreateRays()->begin(); rit != rit_end; ++ rit)
|
---|
[1570] | 3598 | {
|
---|
| 3599 | collectRays.push_back(*rit);
|
---|
| 3600 | }
|
---|
| 3601 | }
|
---|
| 3602 |
|
---|
| 3603 | const int raysOut = min((int)collectRays.size(), maxRays);
|
---|
[1571] | 3604 |
|
---|
[1570] | 3605 | // prepare some rays for output
|
---|
| 3606 | VssRayContainer::const_iterator rit, rit_end = collectRays.end();
|
---|
| 3607 | for (rit = collectRays.begin(); rit != rit_end; ++ rit)
|
---|
[477] | 3608 | {
|
---|
[1570] | 3609 | const float p = RandomValue(0.0f, (float)collectRays.size());
|
---|
| 3610 | if (p < raysOut)
|
---|
[587] | 3611 | {
|
---|
[1935] | 3612 | if ((*rit)->mFlags & VssRay::BorderSample)
|
---|
[1580] | 3613 | {
|
---|
[1571] | 3614 | vcRays.push_back(*rit);
|
---|
[1580] | 3615 | }
|
---|
[1571] | 3616 | else if ((*rit)->mFlags & VssRay::ReverseSample)
|
---|
[1928] | 3617 | {
|
---|
[1571] | 3618 | vcRays2.push_back(*rit);
|
---|
[1928] | 3619 | }
|
---|
[1935] | 3620 | else
|
---|
[1928] | 3621 | {
|
---|
[1571] | 3622 | vcRays3.push_back(*rit);
|
---|
[1928] | 3623 | }
|
---|
[587] | 3624 | }
|
---|
[477] | 3625 | }
|
---|
[1571] | 3626 |
|
---|
| 3627 | exporter->ExportRays(vcRays, RgbColor(1, 0, 0));
|
---|
| 3628 | exporter->ExportRays(vcRays2, RgbColor(0, 1, 0));
|
---|
| 3629 | exporter->ExportRays(vcRays3, RgbColor(1, 1, 1));
|
---|
[477] | 3630 | }
|
---|
[1570] | 3631 |
|
---|
| 3632 | ////////////////
|
---|
| 3633 | //-- export view cell geometry
|
---|
[587] | 3634 |
|
---|
[478] | 3635 | exporter->SetWireframe();
|
---|
[477] | 3636 |
|
---|
[478] | 3637 | Material m;//= RandomMaterial();
|
---|
| 3638 | m.mDiffuseColor = RgbColor(0, 1, 0);
|
---|
| 3639 | exporter->SetForcedMaterial(m);
|
---|
[477] | 3640 |
|
---|
[1416] | 3641 | ExportViewCellGeometry(exporter, vc, NULL, NULL);
|
---|
[478] | 3642 | exporter->SetFilled();
|
---|
[469] | 3643 |
|
---|
[1570] | 3644 | if (exportPvs)
|
---|
[478] | 3645 | {
|
---|
[1570] | 3646 | Intersectable::NewMail();
|
---|
[1742] | 3647 | ObjectPvsIterator pit = pvs.GetIterator();
|
---|
| 3648 |
|
---|
| 3649 | while (pit.HasMoreEntries())
|
---|
[1570] | 3650 | {
|
---|
[1742] | 3651 | ObjectPvsEntry entry = pit.Next();
|
---|
| 3652 |
|
---|
| 3653 | // output PVS of view cell
|
---|
| 3654 | Intersectable *intersect = entry.mObject;
|
---|
[1570] | 3655 |
|
---|
| 3656 | if (!intersect->Mailed())
|
---|
| 3657 | {
|
---|
| 3658 | intersect->Mail();
|
---|
[1571] | 3659 |
|
---|
[1570] | 3660 | m = RandomMaterial();
|
---|
| 3661 | exporter->SetForcedMaterial(m);
|
---|
| 3662 | exporter->ExportIntersectable(intersect);
|
---|
| 3663 | }
|
---|
[503] | 3664 | }
|
---|
[1570] | 3665 | cout << endl;
|
---|
[477] | 3666 | }
|
---|
[1570] | 3667 |
|
---|
[478] | 3668 | DEL_PTR(exporter);
|
---|
| 3669 | cout << "finished" << endl;
|
---|
[477] | 3670 | }
|
---|
[440] | 3671 | }
|
---|
| 3672 |
|
---|
[441] | 3673 |
|
---|
[693] | 3674 | void BspViewCellsManager::TestSubdivision()
|
---|
| 3675 | {
|
---|
| 3676 | ViewCellContainer leaves;
|
---|
| 3677 | mViewCellsTree->CollectLeaves(mViewCellsTree->GetRoot(), leaves);
|
---|
| 3678 |
|
---|
| 3679 | ViewCellContainer::const_iterator it, it_end = leaves.end();
|
---|
| 3680 |
|
---|
| 3681 | const float vol = mViewSpaceBox.GetVolume();
|
---|
| 3682 | float subdivVol = 0;
|
---|
| 3683 | float newVol = 0;
|
---|
| 3684 |
|
---|
| 3685 | for (it = leaves.begin(); it != it_end; ++ it)
|
---|
| 3686 | {
|
---|
| 3687 | BspNodeGeometry geom;
|
---|
[1551] | 3688 | mBspTree->ConstructGeometry(*it, geom);
|
---|
[693] | 3689 |
|
---|
| 3690 | const float lVol = geom.GetVolume();
|
---|
| 3691 | newVol += lVol;
|
---|
| 3692 | subdivVol += (*it)->GetVolume();
|
---|
[694] | 3693 |
|
---|
[1551] | 3694 | const float thres = 0.9f;
|
---|
[694] | 3695 | if ((lVol < ((*it)->GetVolume() * thres)) ||
|
---|
| 3696 | (lVol * thres > ((*it)->GetVolume())))
|
---|
| 3697 | Debug << "warning: " << lVol << " " << (*it)->GetVolume() << endl;
|
---|
[693] | 3698 | }
|
---|
| 3699 |
|
---|
| 3700 | Debug << "exact volume: " << vol << endl;
|
---|
| 3701 | Debug << "subdivision volume: " << subdivVol << endl;
|
---|
| 3702 | Debug << "new volume: " << newVol << endl;
|
---|
| 3703 | }
|
---|
| 3704 |
|
---|
| 3705 |
|
---|
[580] | 3706 | void BspViewCellsManager::ExportViewCellGeometry(Exporter *exporter,
|
---|
[591] | 3707 | ViewCell *vc,
|
---|
[1416] | 3708 | const AxisAlignedBox3 *sceneBox,
|
---|
| 3709 | const AxisAlignedPlane *clipPlane
|
---|
[1570] | 3710 | ) const
|
---|
[1557] | 3711 | {
|
---|
[660] | 3712 | if (clipPlane)
|
---|
[591] | 3713 | {
|
---|
[1047] | 3714 | const Plane3 plane = clipPlane->GetPlane();
|
---|
| 3715 |
|
---|
[726] | 3716 | ViewCellContainer leaves;
|
---|
| 3717 | mViewCellsTree->CollectLeaves(vc, leaves);
|
---|
| 3718 | ViewCellContainer::const_iterator it, it_end = leaves.end();
|
---|
[591] | 3719 |
|
---|
[726] | 3720 | for (it = leaves.begin(); it != it_end; ++ it)
|
---|
[681] | 3721 | {
|
---|
[726] | 3722 | BspNodeGeometry geom;
|
---|
[681] | 3723 | BspNodeGeometry front;
|
---|
| 3724 | BspNodeGeometry back;
|
---|
[591] | 3725 |
|
---|
[1551] | 3726 | mBspTree->ConstructGeometry(*it, geom);
|
---|
[681] | 3727 |
|
---|
[1563] | 3728 | const float eps = 0.0001f;
|
---|
[1047] | 3729 | const int cf = geom.Side(plane, eps);
|
---|
[726] | 3730 |
|
---|
| 3731 | if (cf == -1)
|
---|
| 3732 | {
|
---|
| 3733 | exporter->ExportPolygons(geom.GetPolys());
|
---|
| 3734 | }
|
---|
| 3735 | else if (cf == 0)
|
---|
| 3736 | {
|
---|
| 3737 | geom.SplitGeometry(front,
|
---|
| 3738 | back,
|
---|
[1047] | 3739 | plane,
|
---|
[726] | 3740 | mViewSpaceBox,
|
---|
| 3741 | eps);
|
---|
[1563] | 3742 |
|
---|
[726] | 3743 | if (back.Valid())
|
---|
[1563] | 3744 | {
|
---|
[726] | 3745 | exporter->ExportPolygons(back.GetPolys());
|
---|
| 3746 | }
|
---|
| 3747 | }
|
---|
[681] | 3748 | }
|
---|
[591] | 3749 | }
|
---|
| 3750 | else
|
---|
| 3751 | {
|
---|
[1563] | 3752 | // export mesh if available
|
---|
| 3753 | // TODO: some bug here?
|
---|
| 3754 | if (1 && vc->GetMesh())
|
---|
| 3755 | {
|
---|
| 3756 | exporter->ExportMesh(vc->GetMesh());
|
---|
| 3757 | }
|
---|
| 3758 | else
|
---|
| 3759 | {
|
---|
| 3760 | BspNodeGeometry geom;
|
---|
| 3761 | mBspTree->ConstructGeometry(vc, geom);
|
---|
| 3762 | exporter->ExportPolygons(geom.GetPolys());
|
---|
| 3763 | }
|
---|
[591] | 3764 | }
|
---|
[482] | 3765 | }
|
---|
| 3766 |
|
---|
[503] | 3767 |
|
---|
| 3768 | void BspViewCellsManager::CreateMesh(ViewCell *vc)
|
---|
| 3769 | {
|
---|
[1551] | 3770 | // note: should previous mesh be deleted (via mesh manager?)
|
---|
[587] | 3771 | BspNodeGeometry geom;
|
---|
| 3772 | mBspTree->ConstructGeometry(vc, geom);
|
---|
| 3773 |
|
---|
[1001] | 3774 | Mesh *mesh = MeshManager::GetSingleton()->CreateResource();
|
---|
[726] | 3775 |
|
---|
[840] | 3776 | IncludeNodeGeomInMesh(geom, *mesh);
|
---|
[587] | 3777 | vc->SetMesh(mesh);
|
---|
[503] | 3778 | }
|
---|
| 3779 |
|
---|
[551] | 3780 |
|
---|
[587] | 3781 | void BspViewCellsManager::Finalize(ViewCell *viewCell,
|
---|
| 3782 | const bool createMesh)
|
---|
[502] | 3783 | {
|
---|
[587] | 3784 | float area = 0;
|
---|
| 3785 | float volume = 0;
|
---|
[572] | 3786 |
|
---|
[587] | 3787 | ViewCellContainer leaves;
|
---|
| 3788 | mViewCellsTree->CollectLeaves(viewCell, leaves);
|
---|
| 3789 |
|
---|
| 3790 | ViewCellContainer::const_iterator it, it_end = leaves.end();
|
---|
| 3791 |
|
---|
[693] | 3792 | for (it = leaves.begin(); it != it_end; ++ it)
|
---|
[587] | 3793 | {
|
---|
| 3794 | BspNodeGeometry geom;
|
---|
| 3795 |
|
---|
[1551] | 3796 | mBspTree->ConstructGeometry(*it, geom);
|
---|
| 3797 |
|
---|
[719] | 3798 | const float lVol = geom.GetVolume();
|
---|
| 3799 | const float lArea = geom.GetArea();
|
---|
[693] | 3800 |
|
---|
| 3801 | area += lArea;
|
---|
| 3802 | volume += lVol;
|
---|
[1551] | 3803 |
|
---|
| 3804 | CreateMesh(*it);
|
---|
[587] | 3805 | }
|
---|
| 3806 |
|
---|
| 3807 | viewCell->SetVolume(volume);
|
---|
| 3808 | viewCell->SetArea(area);
|
---|
[502] | 3809 | }
|
---|
| 3810 |
|
---|
[580] | 3811 |
|
---|
[879] | 3812 | ViewCell *BspViewCellsManager::GetViewCell(const Vector3 &point, const bool active) const
|
---|
[580] | 3813 | {
|
---|
[1021] | 3814 | if (!ViewCellsConstructed())
|
---|
[1545] | 3815 | {
|
---|
[587] | 3816 | return NULL;
|
---|
[1545] | 3817 | }
|
---|
[587] | 3818 | if (!mViewSpaceBox.IsInside(point))
|
---|
[1545] | 3819 | {
|
---|
[587] | 3820 | return NULL;
|
---|
[1545] | 3821 | }
|
---|
[587] | 3822 | return mBspTree->GetViewCell(point);
|
---|
[580] | 3823 | }
|
---|
| 3824 |
|
---|
| 3825 |
|
---|
[587] | 3826 | void BspViewCellsManager::CollectMergeCandidates(const VssRayContainer &rays,
|
---|
| 3827 | vector<MergeCandidate> &candidates)
|
---|
| 3828 | {
|
---|
| 3829 | cout << "collecting merge candidates ... " << endl;
|
---|
| 3830 |
|
---|
| 3831 | if (mUseRaysForMerge)
|
---|
| 3832 | {
|
---|
| 3833 | mBspTree->CollectMergeCandidates(rays, candidates);
|
---|
| 3834 | }
|
---|
| 3835 | else
|
---|
| 3836 | {
|
---|
| 3837 | vector<BspLeaf *> leaves;
|
---|
| 3838 | mBspTree->CollectLeaves(leaves);
|
---|
| 3839 | mBspTree->CollectMergeCandidates(leaves, candidates);
|
---|
| 3840 | }
|
---|
| 3841 |
|
---|
| 3842 | cout << "fininshed collecting candidates" << endl;
|
---|
| 3843 | }
|
---|
| 3844 |
|
---|
| 3845 |
|
---|
[440] | 3846 |
|
---|
[1047] | 3847 | bool BspViewCellsManager::ExportViewCells(const string filename,
|
---|
| 3848 | const bool exportPvs,
|
---|
| 3849 | const ObjectContainer &objects)
|
---|
[590] | 3850 | {
|
---|
[1551] | 3851 | if (!ViewCellsConstructed() || !ViewCellsTreeConstructed())
|
---|
| 3852 | {
|
---|
| 3853 | return false;
|
---|
| 3854 | }
|
---|
| 3855 |
|
---|
[590] | 3856 | cout << "exporting view cells to xml ... ";
|
---|
[503] | 3857 |
|
---|
[1551] | 3858 | OUT_STREAM stream(filename.c_str());
|
---|
| 3859 |
|
---|
[590] | 3860 | // for output we need unique ids for each view cell
|
---|
| 3861 | CreateUniqueViewCellIds();
|
---|
[503] | 3862 |
|
---|
[590] | 3863 | stream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"<<endl;
|
---|
[975] | 3864 | stream << "<VisibilitySolution>" << endl;
|
---|
[590] | 3865 |
|
---|
[1551] | 3866 | if (exportPvs)
|
---|
| 3867 | {
|
---|
| 3868 | //////////
|
---|
| 3869 | //-- export bounding boxes: they are used to identify the objects from the pvs and
|
---|
| 3870 | //-- assign them to the entities in the rendering engine
|
---|
[590] | 3871 |
|
---|
[1551] | 3872 | stream << "<BoundingBoxes>" << endl;
|
---|
| 3873 | ObjectContainer::const_iterator oit, oit_end = objects.end();
|
---|
[610] | 3874 |
|
---|
[1551] | 3875 | for (oit = objects.begin(); oit != oit_end; ++ oit)
|
---|
| 3876 | {
|
---|
[1563] | 3877 | const AxisAlignedBox3 box = (*oit)->GetBox();
|
---|
[1551] | 3878 |
|
---|
[1563] | 3879 | stream << "<BoundingBox" << " id=\"" << (*oit)->GetId() << "\""
|
---|
[1551] | 3880 | << " min=\"" << box.Min().x << " " << box.Min().y << " " << box.Min().z << "\""
|
---|
| 3881 | << " max=\"" << box.Max().x << " " << box.Max().y << " " << box.Max().z << "\" />" << endl;
|
---|
| 3882 | }
|
---|
[590] | 3883 |
|
---|
[1551] | 3884 | stream << "</BoundingBoxes>" << endl;
|
---|
| 3885 | }
|
---|
| 3886 |
|
---|
| 3887 | ///////////
|
---|
| 3888 | //-- export the view cells and the pvs
|
---|
| 3889 |
|
---|
| 3890 | const int numViewCells = mCurrentViewCellsStats.viewCells;
|
---|
| 3891 | stream << "<ViewCells number=\"" << numViewCells << "\" >" << endl;
|
---|
| 3892 |
|
---|
| 3893 | mViewCellsTree->Export(stream, exportPvs);
|
---|
| 3894 |
|
---|
[590] | 3895 | stream << "</ViewCells>" << endl;
|
---|
| 3896 |
|
---|
[1551] | 3897 | /////////////
|
---|
| 3898 | //-- export the view space hierarchy
|
---|
| 3899 | stream << "<ViewSpaceHierarchy type=\"bsp\""
|
---|
| 3900 | << " min=\"" << mViewSpaceBox.Min().x << " " << mViewSpaceBox.Min().y << " " << mViewSpaceBox.Min().z << "\""
|
---|
| 3901 | << " max=\"" << mViewSpaceBox.Max().x << " " << mViewSpaceBox.Max().y << " " << mViewSpaceBox.Max().z << "\">" << endl;
|
---|
| 3902 |
|
---|
[590] | 3903 | mBspTree->Export(stream);
|
---|
| 3904 |
|
---|
[1551] | 3905 | // end tags
|
---|
| 3906 | stream << "</ViewSpaceHierarchy>" << endl;
|
---|
[975] | 3907 | stream << "</VisibilitySolution>" << endl;
|
---|
[590] | 3908 |
|
---|
[1551] | 3909 | stream.close();
|
---|
[590] | 3910 | cout << "finished" << endl;
|
---|
[1551] | 3911 |
|
---|
[590] | 3912 | return true;
|
---|
| 3913 | }
|
---|
| 3914 |
|
---|
| 3915 |
|
---|
[1545] | 3916 | ViewCell *BspViewCellsManager::ConstructDummyMergeTree(BspNode *root)
|
---|
| 3917 | {
|
---|
| 3918 | ViewCellInterior *vcRoot = new ViewCellInterior();
|
---|
| 3919 |
|
---|
| 3920 | // evaluate merge cost for priority traversal
|
---|
[1713] | 3921 | const float mergeCost = -(float)root->mTimeStamp;
|
---|
[1545] | 3922 | vcRoot->SetMergeCost(mergeCost);
|
---|
| 3923 |
|
---|
| 3924 | float volume = 0;
|
---|
| 3925 | vector<BspLeaf *> leaves;
|
---|
| 3926 | mBspTree->CollectLeaves(leaves);
|
---|
| 3927 | vector<BspLeaf *>::const_iterator lit, lit_end = leaves.end();
|
---|
[1548] | 3928 | ViewCell::NewMail();
|
---|
| 3929 |
|
---|
[1545] | 3930 | for (lit = leaves.begin(); lit != lit_end; ++ lit)
|
---|
| 3931 | {
|
---|
| 3932 | BspLeaf *leaf = *lit;
|
---|
| 3933 | ViewCell *vc = leaf->GetViewCell();
|
---|
| 3934 |
|
---|
[1548] | 3935 | if (!vc->Mailed())
|
---|
| 3936 | {
|
---|
| 3937 | vc->Mail();
|
---|
| 3938 | vc->SetMergeCost(0.0f);
|
---|
| 3939 | vcRoot->SetupChildLink(vc);
|
---|
[1545] | 3940 |
|
---|
[1548] | 3941 | volume += vc->GetVolume();
|
---|
| 3942 | volume += vc->GetVolume();
|
---|
| 3943 | vcRoot->SetVolume(volume);
|
---|
| 3944 | }
|
---|
[1545] | 3945 | }
|
---|
| 3946 |
|
---|
| 3947 | return vcRoot;
|
---|
| 3948 | }
|
---|
| 3949 |
|
---|
| 3950 |
|
---|
[650] | 3951 | ViewCell *BspViewCellsManager::ConstructSpatialMergeTree(BspNode *root)
|
---|
[610] | 3952 | {
|
---|
[752] | 3953 | // terminate recursion
|
---|
[650] | 3954 | if (root->IsLeaf())
|
---|
| 3955 | {
|
---|
[752] | 3956 | BspLeaf *leaf = dynamic_cast<BspLeaf *>(root);
|
---|
| 3957 | leaf->GetViewCell()->SetMergeCost(0.0f);
|
---|
| 3958 | return leaf->GetViewCell();
|
---|
[650] | 3959 | }
|
---|
| 3960 |
|
---|
| 3961 | BspInterior *interior = dynamic_cast<BspInterior *>(root);
|
---|
| 3962 | ViewCellInterior *viewCellInterior = new ViewCellInterior();
|
---|
| 3963 |
|
---|
[752] | 3964 | // evaluate merge cost for priority traversal
|
---|
[1713] | 3965 | const float mergeCost = -(float)root->mTimeStamp;
|
---|
[650] | 3966 | viewCellInterior->SetMergeCost(mergeCost);
|
---|
[649] | 3967 |
|
---|
[650] | 3968 | float volume = 0;
|
---|
[649] | 3969 |
|
---|
[650] | 3970 | BspNode *front = interior->GetFront();
|
---|
| 3971 | BspNode *back = interior->GetBack();
|
---|
[649] | 3972 |
|
---|
[752] | 3973 |
|
---|
[1545] | 3974 | ////////////
|
---|
[752] | 3975 | //-- recursivly compute child hierarchies
|
---|
[1545] | 3976 |
|
---|
[650] | 3977 | ViewCell *backVc = ConstructSpatialMergeTree(back);
|
---|
| 3978 | ViewCell *frontVc = ConstructSpatialMergeTree(front);
|
---|
[610] | 3979 |
|
---|
[752] | 3980 | viewCellInterior->SetupChildLink(backVc);
|
---|
[650] | 3981 | viewCellInterior->SetupChildLink(frontVc);
|
---|
[610] | 3982 |
|
---|
[650] | 3983 | volume += backVc->GetVolume();
|
---|
| 3984 | volume += frontVc->GetVolume();
|
---|
[649] | 3985 |
|
---|
[650] | 3986 | viewCellInterior->SetVolume(volume);
|
---|
[649] | 3987 |
|
---|
[650] | 3988 | return viewCellInterior;
|
---|
[610] | 3989 | }
|
---|
| 3990 |
|
---|
[650] | 3991 |
|
---|
[590] | 3992 | /************************************************************************/
|
---|
| 3993 | /* KdViewCellsManager implementation */
|
---|
| 3994 | /************************************************************************/
|
---|
| 3995 |
|
---|
| 3996 |
|
---|
| 3997 |
|
---|
[1264] | 3998 | KdViewCellsManager::KdViewCellsManager(ViewCellsTree *vcTree, KdTree *kdTree):
|
---|
| 3999 | ViewCellsManager(vcTree), mKdTree(kdTree), mKdPvsDepth(100)
|
---|
[440] | 4000 | {
|
---|
| 4001 | }
|
---|
| 4002 |
|
---|
[605] | 4003 |
|
---|
[471] | 4004 | float KdViewCellsManager::GetProbability(ViewCell *viewCell)
|
---|
[468] | 4005 | {
|
---|
[479] | 4006 | // compute view cell area / volume as subsititute for probability
|
---|
[605] | 4007 | if (0)
|
---|
| 4008 | return GetArea(viewCell) / GetViewSpaceBox().SurfaceArea();
|
---|
| 4009 | else
|
---|
| 4010 | return GetVolume(viewCell) / GetViewSpaceBox().GetVolume();
|
---|
[468] | 4011 | }
|
---|
| 4012 |
|
---|
| 4013 |
|
---|
| 4014 |
|
---|
[479] | 4015 |
|
---|
[480] | 4016 | void KdViewCellsManager::CollectViewCells()
|
---|
| 4017 | {
|
---|
| 4018 | //mKdTree->CollectViewCells(mViewCells); TODO
|
---|
| 4019 | }
|
---|
[479] | 4020 |
|
---|
[519] | 4021 |
|
---|
[574] | 4022 | int KdViewCellsManager::ConstructSubdivision(const ObjectContainer &objects,
|
---|
[487] | 4023 | const VssRayContainer &rays)
|
---|
[440] | 4024 | {
|
---|
[441] | 4025 | // if view cells already constructed
|
---|
[440] | 4026 | if (ViewCellsConstructed())
|
---|
| 4027 | return 0;
|
---|
[441] | 4028 |
|
---|
[440] | 4029 | mKdTree->Construct();
|
---|
| 4030 |
|
---|
[480] | 4031 | mTotalAreaValid = false;
|
---|
[469] | 4032 | // create the view cells
|
---|
| 4033 | mKdTree->CreateAndCollectViewCells(mViewCells);
|
---|
[480] | 4034 | // cast rays
|
---|
[574] | 4035 | ComputeSampleContributions(rays, true, false);
|
---|
[480] | 4036 |
|
---|
[479] | 4037 | EvaluateViewCellsStats();
|
---|
[660] | 4038 | Debug << "\nView cells after construction:\n" << mCurrentViewCellsStats << endl;
|
---|
[469] | 4039 |
|
---|
[440] | 4040 | return 0;
|
---|
| 4041 | }
|
---|
| 4042 |
|
---|
[587] | 4043 |
|
---|
[440] | 4044 | bool KdViewCellsManager::ViewCellsConstructed() const
|
---|
| 4045 | {
|
---|
| 4046 | return mKdTree->GetRoot() != NULL;
|
---|
| 4047 | }
|
---|
| 4048 |
|
---|
[1020] | 4049 |
|
---|
[503] | 4050 | int KdViewCellsManager::PostProcess(const ObjectContainer &objects,
|
---|
[466] | 4051 | const VssRayContainer &rays)
|
---|
[440] | 4052 | {
|
---|
| 4053 | return 0;
|
---|
| 4054 | }
|
---|
| 4055 |
|
---|
[1020] | 4056 |
|
---|
[1570] | 4057 | void KdViewCellsManager::ExportSingleViewCells(const ObjectContainer &objects,
|
---|
| 4058 | const int maxViewCells,
|
---|
| 4059 | const bool sortViewCells,
|
---|
| 4060 | const bool exportPvs,
|
---|
| 4061 | const bool exportRays,
|
---|
| 4062 | const int maxRays,
|
---|
| 4063 | const string prefix,
|
---|
| 4064 | VssRayContainer *visRays)
|
---|
| 4065 | {
|
---|
| 4066 | // TODO
|
---|
| 4067 | }
|
---|
| 4068 |
|
---|
| 4069 |
|
---|
[440] | 4070 | void KdViewCellsManager::Visualize(const ObjectContainer &objects,
|
---|
[466] | 4071 | const VssRayContainer &sampleRays)
|
---|
[440] | 4072 | {
|
---|
[441] | 4073 | if (!ViewCellsConstructed())
|
---|
| 4074 | return;
|
---|
| 4075 |
|
---|
[469] | 4076 | // using view cells instead of the kd PVS of objects
|
---|
| 4077 | const bool useViewCells = true;
|
---|
| 4078 | bool exportRays = false;
|
---|
[440] | 4079 |
|
---|
| 4080 | int limit = min(mVisualizationSamples, (int)sampleRays.size());
|
---|
[469] | 4081 | const int pvsOut = min((int)objects.size(), 10);
|
---|
[466] | 4082 | VssRayContainer *rays = new VssRayContainer[pvsOut];
|
---|
[440] | 4083 |
|
---|
[469] | 4084 | if (useViewCells)
|
---|
[440] | 4085 | {
|
---|
[469] | 4086 | const int leafOut = 10;
|
---|
[503] | 4087 |
|
---|
[469] | 4088 | ViewCell::NewMail();
|
---|
[503] | 4089 |
|
---|
[469] | 4090 | //-- some rays for output
|
---|
| 4091 | const int raysOut = min((int)sampleRays.size(), mVisualizationSamples);
|
---|
| 4092 | Debug << "visualization using " << raysOut << " samples" << endl;
|
---|
| 4093 |
|
---|
| 4094 | //-- some random view cells and rays for output
|
---|
| 4095 | vector<KdLeaf *> kdLeaves;
|
---|
[503] | 4096 |
|
---|
[469] | 4097 | for (int i = 0; i < leafOut; ++ i)
|
---|
| 4098 | kdLeaves.push_back(dynamic_cast<KdLeaf *>(mKdTree->GetRandomLeaf()));
|
---|
[503] | 4099 |
|
---|
[469] | 4100 | for (int i = 0; i < kdLeaves.size(); ++ i)
|
---|
[440] | 4101 | {
|
---|
[469] | 4102 | KdLeaf *leaf = kdLeaves[i];
|
---|
| 4103 | RayContainer vcRays;
|
---|
[503] | 4104 |
|
---|
[469] | 4105 | cout << "creating output for view cell " << i << " ... ";
|
---|
[503] | 4106 | #if 0
|
---|
[469] | 4107 | // check whether we can add the current ray to the output rays
|
---|
[503] | 4108 | for (int k = 0; k < raysOut; ++ k)
|
---|
[440] | 4109 | {
|
---|
[469] | 4110 | Ray *ray = sampleRays[k];
|
---|
[503] | 4111 |
|
---|
[469] | 4112 | for (int j = 0; j < (int)ray->bspIntersections.size(); ++ j)
|
---|
| 4113 | {
|
---|
| 4114 | BspLeaf *leaf2 = ray->bspIntersections[j].mLeaf;
|
---|
[503] | 4115 |
|
---|
| 4116 | if (leaf->GetViewCell() == leaf2->GetViewCell())
|
---|
[469] | 4117 | {
|
---|
| 4118 | vcRays.push_back(ray);
|
---|
| 4119 | }
|
---|
| 4120 | }
|
---|
[479] | 4121 | }
|
---|
[503] | 4122 | #endif
|
---|
[469] | 4123 | Intersectable::NewMail();
|
---|
[503] | 4124 |
|
---|
[469] | 4125 | ViewCell *vc = leaf->mViewCell;
|
---|
[1570] | 4126 | char str[64]; sprintf(str, "viewcell%04d.wrl", i);
|
---|
[503] | 4127 |
|
---|
[1570] | 4128 | Exporter *exporter = Exporter::GetExporter(str);
|
---|
[469] | 4129 | exporter->SetFilled();
|
---|
| 4130 |
|
---|
| 4131 | exporter->SetWireframe();
|
---|
| 4132 | //exporter->SetFilled();
|
---|
[503] | 4133 |
|
---|
[469] | 4134 | Material m;//= RandomMaterial();
|
---|
| 4135 | m.mDiffuseColor = RgbColor(1, 1, 0);
|
---|
| 4136 | exporter->SetForcedMaterial(m);
|
---|
[503] | 4137 |
|
---|
[469] | 4138 | AxisAlignedBox3 box = mKdTree->GetBox(leaf);
|
---|
| 4139 | exporter->ExportBox(box);
|
---|
| 4140 |
|
---|
| 4141 | // export rays piercing this view cell
|
---|
[503] | 4142 | exporter->ExportRays(vcRays, 1000, RgbColor(0, 1, 0));
|
---|
| 4143 |
|
---|
[469] | 4144 | m.mDiffuseColor = RgbColor(1, 0, 0);
|
---|
| 4145 | exporter->SetForcedMaterial(m);
|
---|
[503] | 4146 |
|
---|
[469] | 4147 | // exporter->SetWireframe();
|
---|
| 4148 | exporter->SetFilled();
|
---|
[503] | 4149 |
|
---|
[1742] | 4150 | ObjectPvsIterator pit = vc->GetPvs().GetIterator();
|
---|
| 4151 |
|
---|
| 4152 | while (pit.HasMoreEntries())
|
---|
| 4153 | {
|
---|
| 4154 | ObjectPvsEntry entry = pit.Next();
|
---|
| 4155 |
|
---|
| 4156 | //-- output PVS of view cell
|
---|
| 4157 | Intersectable *intersect = entry.mObject;
|
---|
[469] | 4158 | if (!intersect->Mailed())
|
---|
| 4159 | {
|
---|
| 4160 | exporter->ExportIntersectable(intersect);
|
---|
| 4161 | intersect->Mail();
|
---|
[503] | 4162 | }
|
---|
[440] | 4163 | }
|
---|
[503] | 4164 |
|
---|
[469] | 4165 | DEL_PTR(exporter);
|
---|
| 4166 | cout << "finished" << endl;
|
---|
[440] | 4167 | }
|
---|
[469] | 4168 |
|
---|
| 4169 | DEL_PTR(rays);
|
---|
[440] | 4170 | }
|
---|
[469] | 4171 | else // using kd PVS of objects
|
---|
| 4172 | {
|
---|
| 4173 | for (int i = 0; i < limit; ++ i)
|
---|
| 4174 | {
|
---|
| 4175 | VssRay *ray = sampleRays[i];
|
---|
[503] | 4176 |
|
---|
[469] | 4177 | // check whether we can add this to the rays
|
---|
[503] | 4178 | for (int j = 0; j < pvsOut; j++)
|
---|
[469] | 4179 | {
|
---|
| 4180 | if (objects[j] == ray->mTerminationObject)
|
---|
| 4181 | {
|
---|
| 4182 | rays[j].push_back(ray);
|
---|
| 4183 | }
|
---|
| 4184 | }
|
---|
| 4185 | }
|
---|
[440] | 4186 |
|
---|
[503] | 4187 | if (exportRays)
|
---|
[469] | 4188 | {
|
---|
| 4189 | Exporter *exporter = NULL;
|
---|
| 4190 | exporter = Exporter::GetExporter("sample-rays.x3d");
|
---|
| 4191 | exporter->SetWireframe();
|
---|
| 4192 | exporter->ExportKdTree(*mKdTree);
|
---|
[503] | 4193 |
|
---|
[1757] | 4194 | for (int i = 0; i < pvsOut; i++)
|
---|
[469] | 4195 | exporter->ExportRays(rays[i], RgbColor(1, 0, 0));
|
---|
| 4196 |
|
---|
| 4197 | exporter->SetFilled();
|
---|
| 4198 | delete exporter;
|
---|
| 4199 | }
|
---|
[440] | 4200 |
|
---|
[503] | 4201 | for (int k=0; k < pvsOut; k++)
|
---|
[469] | 4202 | {
|
---|
| 4203 | Intersectable *object = objects[k];
|
---|
[1757] | 4204 | char str[64]; sprintf(str, "viewcell%04d.wrl", k);
|
---|
[440] | 4205 |
|
---|
[1570] | 4206 | Exporter *exporter = Exporter::GetExporter(str);
|
---|
[469] | 4207 | exporter->SetWireframe();
|
---|
[503] | 4208 |
|
---|
[1736] | 4209 | // matt: no kd pvs
|
---|
| 4210 | /*
|
---|
[1233] | 4211 | KdPvsMap::iterator kit = object->mKdPvs.mEntries.begin();
|
---|
[469] | 4212 | Intersectable::NewMail();
|
---|
[503] | 4213 |
|
---|
[469] | 4214 | // avoid adding the object to the list
|
---|
| 4215 | object->Mail();
|
---|
| 4216 | ObjectContainer visibleObjects;
|
---|
[503] | 4217 |
|
---|
[1233] | 4218 | for (; kit != object->mKdPvs.mEntries.end(); i++)
|
---|
[469] | 4219 | {
|
---|
[1233] | 4220 | KdNode *node = (*kit).first;
|
---|
[469] | 4221 | exporter->ExportBox(mKdTree->GetBox(node));
|
---|
[503] | 4222 |
|
---|
[469] | 4223 | mKdTree->CollectObjects(node, visibleObjects);
|
---|
| 4224 | }
|
---|
[503] | 4225 |
|
---|
[469] | 4226 | exporter->ExportRays(rays[k], RgbColor(0, 1, 0));
|
---|
| 4227 | exporter->SetFilled();
|
---|
[503] | 4228 |
|
---|
[469] | 4229 | for (int j = 0; j < visibleObjects.size(); j++)
|
---|
| 4230 | exporter->ExportIntersectable(visibleObjects[j]);
|
---|
[503] | 4231 |
|
---|
[469] | 4232 | Material m;
|
---|
| 4233 | m.mDiffuseColor = RgbColor(1, 0, 0);
|
---|
| 4234 | exporter->SetForcedMaterial(m);
|
---|
| 4235 | exporter->ExportIntersectable(object);
|
---|
[1736] | 4236 | */
|
---|
[469] | 4237 | delete exporter;
|
---|
[440] | 4238 | }
|
---|
[503] | 4239 | }
|
---|
[440] | 4240 | }
|
---|
| 4241 |
|
---|
[469] | 4242 |
|
---|
[580] | 4243 | ViewCell *KdViewCellsManager::GenerateViewCell(Mesh *mesh) const
|
---|
| 4244 | {
|
---|
| 4245 | return new KdViewCell(mesh);
|
---|
| 4246 | }
|
---|
[482] | 4247 |
|
---|
[580] | 4248 |
|
---|
| 4249 | void KdViewCellsManager::ExportViewCellGeometry(Exporter *exporter,
|
---|
[591] | 4250 | ViewCell *vc,
|
---|
[1416] | 4251 | const AxisAlignedBox3 *sceneBox,
|
---|
| 4252 | const AxisAlignedPlane *clipPlane
|
---|
| 4253 | ) const
|
---|
[482] | 4254 | {
|
---|
[580] | 4255 | ViewCellContainer leaves;
|
---|
| 4256 | mViewCellsTree->CollectLeaves(vc, leaves);
|
---|
| 4257 | ViewCellContainer::const_iterator it, it_end = leaves.end();
|
---|
| 4258 |
|
---|
| 4259 | for (it = leaves.begin(); it != it_end; ++ it)
|
---|
| 4260 | {
|
---|
| 4261 | KdViewCell *kdVc = dynamic_cast<KdViewCell *>(*it);
|
---|
[1551] | 4262 | exporter->ExportBox(mKdTree->GetBox(kdVc->mLeaves[0]));
|
---|
[580] | 4263 | }
|
---|
[482] | 4264 | }
|
---|
| 4265 |
|
---|
| 4266 |
|
---|
[440] | 4267 | int KdViewCellsManager::GetType() const
|
---|
| 4268 | {
|
---|
| 4269 | return ViewCellsManager::KD;
|
---|
| 4270 | }
|
---|
| 4271 |
|
---|
| 4272 |
|
---|
[441] | 4273 |
|
---|
[440] | 4274 | KdNode *KdViewCellsManager::GetNodeForPvs(KdLeaf *leaf)
|
---|
| 4275 | {
|
---|
| 4276 | KdNode *node = leaf;
|
---|
| 4277 |
|
---|
| 4278 | while (node->mParent && node->mDepth > mKdPvsDepth)
|
---|
| 4279 | node = node->mParent;
|
---|
[1176] | 4280 |
|
---|
[440] | 4281 | return node;
|
---|
| 4282 | }
|
---|
| 4283 |
|
---|
[469] | 4284 | int KdViewCellsManager::CastLineSegment(const Vector3 &origin,
|
---|
| 4285 | const Vector3 &termination,
|
---|
| 4286 | ViewCellContainer &viewcells)
|
---|
[466] | 4287 | {
|
---|
[469] | 4288 | return mKdTree->CastLineSegment(origin, termination, viewcells);
|
---|
[466] | 4289 | }
|
---|
| 4290 |
|
---|
[469] | 4291 |
|
---|
[503] | 4292 | void KdViewCellsManager::CreateMesh(ViewCell *vc)
|
---|
| 4293 | {
|
---|
[551] | 4294 | // TODO
|
---|
[503] | 4295 | }
|
---|
| 4296 |
|
---|
[580] | 4297 |
|
---|
| 4298 |
|
---|
| 4299 | void KdViewCellsManager::CollectMergeCandidates(const VssRayContainer &rays,
|
---|
| 4300 | vector<MergeCandidate> &candidates)
|
---|
| 4301 | {
|
---|
| 4302 | // TODO
|
---|
| 4303 | }
|
---|
| 4304 |
|
---|
[1021] | 4305 |
|
---|
| 4306 |
|
---|
[503] | 4307 | /**************************************************************************/
|
---|
| 4308 | /* VspBspViewCellsManager implementation */
|
---|
| 4309 | /**************************************************************************/
|
---|
[482] | 4310 |
|
---|
[503] | 4311 |
|
---|
[1264] | 4312 | VspBspViewCellsManager::VspBspViewCellsManager(ViewCellsTree *vcTree, VspBspTree *vspBspTree):
|
---|
| 4313 | ViewCellsManager(vcTree), mVspBspTree(vspBspTree)
|
---|
[442] | 4314 | {
|
---|
[1004] | 4315 | Environment::GetSingleton()->GetIntValue("VspBspTree.Construction.samples", mInitialSamples);
|
---|
[478] | 4316 | mVspBspTree->SetViewCellsManager(this);
|
---|
[590] | 4317 | mVspBspTree->mViewCellsTree = mViewCellsTree;
|
---|
[442] | 4318 | }
|
---|
| 4319 |
|
---|
[477] | 4320 |
|
---|
[475] | 4321 | VspBspViewCellsManager::~VspBspViewCellsManager()
|
---|
| 4322 | {
|
---|
| 4323 | }
|
---|
| 4324 |
|
---|
[477] | 4325 |
|
---|
[471] | 4326 | float VspBspViewCellsManager::GetProbability(ViewCell *viewCell)
|
---|
[468] | 4327 | {
|
---|
[551] | 4328 | if (0 && mVspBspTree->mUseAreaForPvs)
|
---|
[547] | 4329 | return GetArea(viewCell) / GetAccVcArea();
|
---|
| 4330 | else
|
---|
| 4331 | return GetVolume(viewCell) / mViewSpaceBox.GetVolume();
|
---|
[468] | 4332 | }
|
---|
| 4333 |
|
---|
[477] | 4334 |
|
---|
[480] | 4335 | void VspBspViewCellsManager::CollectViewCells()
|
---|
| 4336 | {
|
---|
[1545] | 4337 | // view cells tree constructed?
|
---|
[581] | 4338 | if (!ViewCellsTreeConstructed())
|
---|
| 4339 | {
|
---|
[590] | 4340 | mVspBspTree->CollectViewCells(mViewCells, false);
|
---|
[581] | 4341 | }
|
---|
| 4342 | else
|
---|
[1264] | 4343 | {
|
---|
| 4344 | // we can use the view cells tree hierarchy to get the right set
|
---|
[600] | 4345 | mViewCellsTree->CollectBestViewCellSet(mViewCells, mNumActiveViewCells);
|
---|
[581] | 4346 | }
|
---|
[480] | 4347 | }
|
---|
| 4348 |
|
---|
| 4349 |
|
---|
[1021] | 4350 | void VspBspViewCellsManager::CollectMergeCandidates(const VssRayContainer &rays,
|
---|
| 4351 | vector<MergeCandidate> &candidates)
|
---|
| 4352 | {
|
---|
| 4353 | cout << "collecting merge candidates ... " << endl;
|
---|
| 4354 |
|
---|
| 4355 | if (mUseRaysForMerge)
|
---|
| 4356 | {
|
---|
| 4357 | mVspBspTree->CollectMergeCandidates(rays, candidates);
|
---|
| 4358 | }
|
---|
| 4359 | else
|
---|
| 4360 | {
|
---|
| 4361 | vector<BspLeaf *> leaves;
|
---|
| 4362 | mVspBspTree->CollectLeaves(leaves);
|
---|
| 4363 |
|
---|
| 4364 | mVspBspTree->CollectMergeCandidates(leaves, candidates);
|
---|
| 4365 | }
|
---|
| 4366 |
|
---|
| 4367 | cout << "fininshed collecting candidates" << endl;
|
---|
| 4368 | }
|
---|
| 4369 |
|
---|
| 4370 |
|
---|
[442] | 4371 | bool VspBspViewCellsManager::ViewCellsConstructed() const
|
---|
| 4372 | {
|
---|
| 4373 | return mVspBspTree->GetRoot() != NULL;
|
---|
| 4374 | }
|
---|
| 4375 |
|
---|
[462] | 4376 |
|
---|
[442] | 4377 | ViewCell *VspBspViewCellsManager::GenerateViewCell(Mesh *mesh) const
|
---|
| 4378 | {
|
---|
| 4379 | return new BspViewCell(mesh);
|
---|
| 4380 | }
|
---|
| 4381 |
|
---|
[569] | 4382 |
|
---|
[574] | 4383 | int VspBspViewCellsManager::ConstructSubdivision(const ObjectContainer &objects,
|
---|
[600] | 4384 | const VssRayContainer &rays)
|
---|
[442] | 4385 | {
|
---|
[710] | 4386 | mMaxPvsSize = (int)(mMaxPvsRatio * (float)objects.size());
|
---|
| 4387 |
|
---|
[503] | 4388 | // if view cells were already constructed
|
---|
| 4389 | if (ViewCellsConstructed())
|
---|
[1545] | 4390 | {
|
---|
[503] | 4391 | return 0;
|
---|
[1545] | 4392 | }
|
---|
[442] | 4393 |
|
---|
[503] | 4394 | int sampleContributions = 0;
|
---|
| 4395 | VssRayContainer sampleRays;
|
---|
| 4396 |
|
---|
[1545] | 4397 | const int limit = min(mInitialSamples, (int)rays.size());
|
---|
[503] | 4398 |
|
---|
[660] | 4399 | Debug << "samples used for vsp bsp subdivision: " << mInitialSamples
|
---|
[664] | 4400 | << ", actual rays: " << (int)rays.size() << endl;
|
---|
[587] | 4401 |
|
---|
[1545] | 4402 | VssRayContainer savedRays;
|
---|
[487] | 4403 |
|
---|
[1545] | 4404 | if (SAMPLE_AFTER_SUBDIVISION)
|
---|
| 4405 | {
|
---|
| 4406 | VssRayContainer constructionRays;
|
---|
| 4407 |
|
---|
| 4408 | GetRaySets(rays, mInitialSamples, constructionRays, &savedRays);
|
---|
[485] | 4409 |
|
---|
[1545] | 4410 | Debug << "rays used for initial construction: " << (int)constructionRays.size() << endl;
|
---|
| 4411 | Debug << "rays saved for later use: " << (int)savedRays.size() << endl;
|
---|
| 4412 |
|
---|
[667] | 4413 | mVspBspTree->Construct(constructionRays, &mViewSpaceBox);
|
---|
[1221] | 4414 | }
|
---|
[666] | 4415 | else
|
---|
[1221] | 4416 | {
|
---|
[1545] | 4417 | Debug << "rays used for initial construction: " << (int)rays.size() << endl;
|
---|
[667] | 4418 | mVspBspTree->Construct(rays, &mViewSpaceBox);
|
---|
[1221] | 4419 | }
|
---|
[667] | 4420 |
|
---|
[490] | 4421 | // collapse invalid regions
|
---|
[491] | 4422 | cout << "collapsing invalid tree regions ... ";
|
---|
[1545] | 4423 | long startTime = GetTime();
|
---|
| 4424 |
|
---|
[1002] | 4425 | const int collapsedLeaves = mVspBspTree->CollapseTree();
|
---|
[587] | 4426 | Debug << "collapsed in " << TimeDiff(startTime, GetTime()) * 1e-3
|
---|
| 4427 | << " seconds" << endl;
|
---|
| 4428 |
|
---|
[495] | 4429 | cout << "finished" << endl;
|
---|
[503] | 4430 |
|
---|
[1444] | 4431 | /////////////////
|
---|
[1221] | 4432 | //-- stats after construction
|
---|
| 4433 |
|
---|
[660] | 4434 | Debug << mVspBspTree->GetStatistics() << endl;
|
---|
| 4435 |
|
---|
[480] | 4436 | ResetViewCells();
|
---|
[660] | 4437 | Debug << "\nView cells after construction:\n" << mCurrentViewCellsStats << endl;
|
---|
[503] | 4438 |
|
---|
[491] | 4439 |
|
---|
[1444] | 4440 | //////////////////////
|
---|
[1545] | 4441 | //-- recast the rest of the rays
|
---|
[1570] | 4442 |
|
---|
[495] | 4443 | startTime = GetTime();
|
---|
[503] | 4444 |
|
---|
[491] | 4445 | cout << "Computing remaining ray contributions ... ";
|
---|
[605] | 4446 |
|
---|
| 4447 | if (SAMPLE_AFTER_SUBDIVISION)
|
---|
| 4448 | ComputeSampleContributions(savedRays, true, false);
|
---|
[752] | 4449 |
|
---|
[491] | 4450 | cout << "finished" << endl;
|
---|
| 4451 |
|
---|
[503] | 4452 | Debug << "Computed remaining ray contribution in " << TimeDiff(startTime, GetTime()) * 1e-3
|
---|
[485] | 4453 | << " secs" << endl;
|
---|
[442] | 4454 |
|
---|
[485] | 4455 | cout << "construction finished" << endl;
|
---|
[503] | 4456 |
|
---|
[719] | 4457 | if (0)
|
---|
[1545] | 4458 | { ////////
|
---|
[1077] | 4459 | //-- real meshes are contructed at this stage
|
---|
[1768] | 4460 |
|
---|
[719] | 4461 | cout << "finalizing view cells ... ";
|
---|
| 4462 | FinalizeViewCells(true);
|
---|
| 4463 | cout << "finished" << endl;
|
---|
| 4464 | }
|
---|
| 4465 |
|
---|
[442] | 4466 | return sampleContributions;
|
---|
| 4467 | }
|
---|
| 4468 |
|
---|
[489] | 4469 |
|
---|
[503] | 4470 | void VspBspViewCellsManager::MergeViewCells(const VssRayContainer &rays,
|
---|
| 4471 | const ObjectContainer &objects)
|
---|
[475] | 4472 | {
|
---|
[442] | 4473 | int vcSize = 0;
|
---|
| 4474 | int pvsSize = 0;
|
---|
| 4475 |
|
---|
[650] | 4476 | //-- merge view cells
|
---|
| 4477 | cout << "starting merge using " << mPostProcessSamples << " samples ... " << endl;
|
---|
| 4478 | long startTime = GetTime();
|
---|
| 4479 |
|
---|
| 4480 |
|
---|
[597] | 4481 | if (mMergeViewCells)
|
---|
| 4482 | {
|
---|
| 4483 | // TODO: should be done BEFORE the ray casting
|
---|
[710] | 4484 | // compute tree by merging the nodes based on cost heuristics
|
---|
[650] | 4485 | mViewCellsTree->ConstructMergeTree(rays, objects);
|
---|
| 4486 | }
|
---|
| 4487 | else
|
---|
| 4488 | {
|
---|
[710] | 4489 | // compute tree by merging the nodes of the spatial hierarchy
|
---|
| 4490 | ViewCell *root = ConstructSpatialMergeTree(mVspBspTree->GetRoot());
|
---|
| 4491 | mViewCellsTree->SetRoot(root);
|
---|
[752] | 4492 |
|
---|
| 4493 | // compute pvs
|
---|
| 4494 | ObjectPvs pvs;
|
---|
| 4495 | UpdatePvsForEvaluation(root, pvs);
|
---|
[650] | 4496 | }
|
---|
[442] | 4497 |
|
---|
[666] | 4498 | if (1)
|
---|
| 4499 | {
|
---|
| 4500 | char mstats[100];
|
---|
[752] | 4501 | ObjectPvs pvs;
|
---|
| 4502 |
|
---|
[1004] | 4503 | Environment::GetSingleton()->GetStringValue("ViewCells.mergeStats", mstats);
|
---|
[666] | 4504 | mViewCellsTree->ExportStats(mstats);
|
---|
| 4505 | }
|
---|
[485] | 4506 |
|
---|
[650] | 4507 | cout << "merged view cells in "
|
---|
| 4508 | << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl;
|
---|
[503] | 4509 |
|
---|
[650] | 4510 | Debug << "Postprocessing: Merged view cells in "
|
---|
| 4511 | << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl << endl;
|
---|
| 4512 |
|
---|
| 4513 |
|
---|
[1444] | 4514 | //////////////////
|
---|
| 4515 | //-- stats and visualizations
|
---|
| 4516 |
|
---|
[600] | 4517 | int savedColorCode = mColorCode;
|
---|
| 4518 |
|
---|
[660] | 4519 | // get currently active view cell set
|
---|
| 4520 | ResetViewCells();
|
---|
| 4521 | Debug << "\nView cells after merge:\n" << mCurrentViewCellsStats << endl;
|
---|
[1444] | 4522 |
|
---|
[1616] | 4523 | if (mShowVisualization) // export merged view cells
|
---|
[483] | 4524 | {
|
---|
[600] | 4525 | mColorCode = 0;
|
---|
[744] | 4526 | Exporter *exporter = Exporter::GetExporter("merged_view_cells.wrl");
|
---|
[660] | 4527 |
|
---|
[485] | 4528 | cout << "exporting view cells after merge ... ";
|
---|
| 4529 |
|
---|
| 4530 | if (exporter)
|
---|
[483] | 4531 | {
|
---|
[600] | 4532 | if (0)
|
---|
| 4533 | exporter->SetWireframe();
|
---|
| 4534 | else
|
---|
| 4535 | exporter->SetFilled();
|
---|
| 4536 |
|
---|
[1760] | 4537 | ExportViewCellsForViz(exporter, NULL, mColorCode, GetClipPlane());
|
---|
[600] | 4538 |
|
---|
[485] | 4539 | if (mExportGeometry)
|
---|
[483] | 4540 | {
|
---|
[485] | 4541 | Material m;
|
---|
| 4542 | m.mDiffuseColor = RgbColor(0, 1, 0);
|
---|
| 4543 | exporter->SetForcedMaterial(m);
|
---|
| 4544 | exporter->SetFilled();
|
---|
[442] | 4545 |
|
---|
[485] | 4546 | exporter->ExportGeometry(objects);
|
---|
[442] | 4547 | }
|
---|
[485] | 4548 |
|
---|
[600] | 4549 | delete exporter;
|
---|
| 4550 | }
|
---|
| 4551 | cout << "finished" << endl;
|
---|
| 4552 | }
|
---|
| 4553 |
|
---|
[1616] | 4554 | if (mShowVisualization)
|
---|
[600] | 4555 | {
|
---|
[1416] | 4556 | // use pvs size for color coding
|
---|
| 4557 | mColorCode = 1;
|
---|
[744] | 4558 | Exporter *exporter = Exporter::GetExporter("merged_view_cells_pvs.wrl");
|
---|
[1176] | 4559 |
|
---|
[600] | 4560 | cout << "exporting view cells after merge (pvs size) ... ";
|
---|
| 4561 |
|
---|
| 4562 | if (exporter)
|
---|
| 4563 | {
|
---|
[1416] | 4564 | exporter->SetFilled();
|
---|
[598] | 4565 |
|
---|
[1760] | 4566 | ExportViewCellsForViz(exporter, NULL, mColorCode, GetClipPlane());
|
---|
[598] | 4567 |
|
---|
[600] | 4568 | if (mExportGeometry)
|
---|
| 4569 | {
|
---|
| 4570 | Material m;
|
---|
| 4571 | m.mDiffuseColor = RgbColor(0, 1, 0);
|
---|
| 4572 | exporter->SetForcedMaterial(m);
|
---|
| 4573 | exporter->SetFilled();
|
---|
| 4574 |
|
---|
| 4575 | exporter->ExportGeometry(objects);
|
---|
| 4576 | }
|
---|
| 4577 |
|
---|
[485] | 4578 | delete exporter;
|
---|
[442] | 4579 | }
|
---|
[485] | 4580 | cout << "finished" << endl;
|
---|
[442] | 4581 | }
|
---|
[600] | 4582 |
|
---|
| 4583 | mColorCode = savedColorCode;
|
---|
[503] | 4584 | }
|
---|
[475] | 4585 |
|
---|
[503] | 4586 |
|
---|
[564] | 4587 | void VspBspViewCellsManager::RefineViewCells(const VssRayContainer &rays,
|
---|
| 4588 | const ObjectContainer &objects)
|
---|
[503] | 4589 | {
|
---|
[485] | 4590 | mRenderer->RenderScene();
|
---|
[1616] | 4591 |
|
---|
[503] | 4592 | SimulationStatistics ss;
|
---|
[485] | 4593 | dynamic_cast<RenderSimulator *>(mRenderer)->GetStatistics(ss);
|
---|
[1415] | 4594 | Debug << "render time before refine\n\n" << ss << endl;
|
---|
[485] | 4595 |
|
---|
[1414] | 4596 | const long startTime = GetTime();
|
---|
[489] | 4597 | cout << "Refining the merged view cells ... ";
|
---|
[485] | 4598 |
|
---|
| 4599 | // refining the merged view cells
|
---|
[580] | 4600 | const int refined = mViewCellsTree->RefineViewCells(rays, objects);
|
---|
[485] | 4601 |
|
---|
[442] | 4602 | //-- stats and visualizations
|
---|
| 4603 | cout << "finished" << endl;
|
---|
[485] | 4604 | cout << "refined " << refined << " view cells in "
|
---|
[442] | 4605 | << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl;
|
---|
| 4606 |
|
---|
[485] | 4607 | Debug << "Postprocessing: refined " << refined << " view cells in "
|
---|
[475] | 4608 | << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl << endl;
|
---|
[503] | 4609 | }
|
---|
[495] | 4610 |
|
---|
[517] | 4611 |
|
---|
[503] | 4612 | int VspBspViewCellsManager::PostProcess(const ObjectContainer &objects,
|
---|
| 4613 | const VssRayContainer &rays)
|
---|
[840] | 4614 | {
|
---|
[503] | 4615 | if (!ViewCellsConstructed())
|
---|
| 4616 | {
|
---|
[517] | 4617 | Debug << "postprocess error: no view cells constructed" << endl;
|
---|
[503] | 4618 | return 0;
|
---|
| 4619 | }
|
---|
[520] | 4620 |
|
---|
[609] | 4621 | // view cells already finished before post processing step
|
---|
| 4622 | // (i.e. because they were loaded)
|
---|
[520] | 4623 | if (mViewCellsFinished)
|
---|
[542] | 4624 | {
|
---|
[551] | 4625 | FinalizeViewCells(true);
|
---|
[542] | 4626 | EvaluateViewCellsStats();
|
---|
[577] | 4627 |
|
---|
[517] | 4628 | return 0;
|
---|
[542] | 4629 | }
|
---|
[448] | 4630 |
|
---|
[710] | 4631 | // check if new view cells turned invalid
|
---|
| 4632 | int minPvs, maxPvs;
|
---|
[564] | 4633 |
|
---|
[710] | 4634 | if (0)
|
---|
| 4635 | {
|
---|
| 4636 | minPvs = mMinPvsSize;
|
---|
| 4637 | maxPvs = mMaxPvsSize;
|
---|
| 4638 | }
|
---|
| 4639 | else
|
---|
| 4640 | {
|
---|
[1414] | 4641 | // problem matt: why did I start here from zero?
|
---|
| 4642 | minPvs = 0;
|
---|
[710] | 4643 | maxPvs = mMaxPvsSize;
|
---|
| 4644 | }
|
---|
[720] | 4645 |
|
---|
[710] | 4646 | Debug << "setting validity, min: " << minPvs << " max: " << maxPvs << endl;
|
---|
| 4647 | cout << "setting validity, min: " << minPvs << " max: " << maxPvs << endl;
|
---|
| 4648 |
|
---|
| 4649 | SetValidity(minPvs, maxPvs);
|
---|
| 4650 |
|
---|
[574] | 4651 | // update valid view space according to valid view cells
|
---|
[720] | 4652 | if (0) mVspBspTree->ValidateTree();
|
---|
[542] | 4653 |
|
---|
[720] | 4654 | // area has to be recomputed
|
---|
[574] | 4655 | mTotalAreaValid = false;
|
---|
[517] | 4656 | VssRayContainer postProcessRays;
|
---|
[605] | 4657 | GetRaySets(rays, mPostProcessSamples, postProcessRays);
|
---|
| 4658 |
|
---|
[517] | 4659 | Debug << "post processing using " << (int)postProcessRays.size() << " samples" << endl;
|
---|
[564] | 4660 |
|
---|
[1444] | 4661 | //////////
|
---|
[1768] | 4662 | //-- merge neighbouring view cells
|
---|
[597] | 4663 | MergeViewCells(postProcessRays, objects);
|
---|
[591] | 4664 |
|
---|
[1444] | 4665 | // refines the merged view cells
|
---|
[720] | 4666 | if (0) RefineViewCells(postProcessRays, objects);
|
---|
[568] | 4667 |
|
---|
[1444] | 4668 |
|
---|
| 4669 | ///////////
|
---|
[660] | 4670 | //-- render simulation after merge + refine
|
---|
[1414] | 4671 |
|
---|
[1415] | 4672 | cout << "\nview cells partition render time before compress" << endl << endl;;
|
---|
[605] | 4673 | dynamic_cast<RenderSimulator *>(mRenderer)->RenderScene();
|
---|
| 4674 | SimulationStatistics ss;
|
---|
| 4675 | dynamic_cast<RenderSimulator *>(mRenderer)->GetStatistics(ss);
|
---|
[1486] | 4676 | cout << ss << endl;
|
---|
[1414] | 4677 |
|
---|
[1843] | 4678 | if (0) CompressViewCells();
|
---|
| 4679 |
|
---|
[517] | 4680 | // collapse sibling leaves that share the same view cell
|
---|
[840] | 4681 | if (0) mVspBspTree->CollapseTree();
|
---|
[586] | 4682 |
|
---|
[574] | 4683 | // recompute view cell list and statistics
|
---|
[520] | 4684 | ResetViewCells();
|
---|
| 4685 |
|
---|
[719] | 4686 | // compute final meshes and volume / area
|
---|
| 4687 | if (1) FinalizeViewCells(true);
|
---|
[1444] | 4688 |
|
---|
[503] | 4689 | return 0;
|
---|
[442] | 4690 | }
|
---|
| 4691 |
|
---|
[490] | 4692 |
|
---|
[442] | 4693 | int VspBspViewCellsManager::GetType() const
|
---|
| 4694 | {
|
---|
| 4695 | return VSP_BSP;
|
---|
| 4696 | }
|
---|
| 4697 |
|
---|
| 4698 |
|
---|
[650] | 4699 | ViewCell *VspBspViewCellsManager::ConstructSpatialMergeTree(BspNode *root)
|
---|
[609] | 4700 | {
|
---|
[752] | 4701 | // terminate recursion
|
---|
[650] | 4702 | if (root->IsLeaf())
|
---|
| 4703 | {
|
---|
[752] | 4704 | BspLeaf *leaf = dynamic_cast<BspLeaf *>(root);
|
---|
| 4705 | leaf->GetViewCell()->SetMergeCost(0.0f);
|
---|
| 4706 | return leaf->GetViewCell();
|
---|
[650] | 4707 | }
|
---|
| 4708 |
|
---|
[752] | 4709 |
|
---|
[650] | 4710 | BspInterior *interior = dynamic_cast<BspInterior *>(root);
|
---|
| 4711 | ViewCellInterior *viewCellInterior = new ViewCellInterior();
|
---|
| 4712 |
|
---|
[752] | 4713 | // evaluate merge cost for priority traversal
|
---|
[650] | 4714 | float mergeCost = 1.0f / (float)root->mTimeStamp;
|
---|
| 4715 | viewCellInterior->SetMergeCost(mergeCost);
|
---|
[610] | 4716 |
|
---|
[650] | 4717 | float volume = 0;
|
---|
| 4718 |
|
---|
| 4719 | BspNode *front = interior->GetFront();
|
---|
| 4720 | BspNode *back = interior->GetBack();
|
---|
[649] | 4721 |
|
---|
[752] | 4722 |
|
---|
| 4723 | ObjectPvs frontPvs, backPvs;
|
---|
| 4724 |
|
---|
| 4725 | //-- recursivly compute child hierarchies
|
---|
[650] | 4726 | ViewCell *backVc = ConstructSpatialMergeTree(back);
|
---|
| 4727 | ViewCell *frontVc = ConstructSpatialMergeTree(front);
|
---|
[610] | 4728 |
|
---|
[752] | 4729 |
|
---|
| 4730 | viewCellInterior->SetupChildLink(backVc);
|
---|
[650] | 4731 | viewCellInterior->SetupChildLink(frontVc);
|
---|
| 4732 |
|
---|
| 4733 | volume += backVc->GetVolume();
|
---|
| 4734 | volume += frontVc->GetVolume();
|
---|
| 4735 |
|
---|
| 4736 | viewCellInterior->SetVolume(volume);
|
---|
| 4737 |
|
---|
| 4738 | return viewCellInterior;
|
---|
[609] | 4739 | }
|
---|
| 4740 |
|
---|
| 4741 |
|
---|
[490] | 4742 | bool VspBspViewCellsManager::GetViewPoint(Vector3 &viewPoint) const
|
---|
| 4743 | {
|
---|
| 4744 | if (!ViewCellsConstructed())
|
---|
| 4745 | return ViewCellsManager::GetViewPoint(viewPoint);
|
---|
| 4746 |
|
---|
| 4747 | // TODO: set reasonable limit
|
---|
| 4748 | const int limit = 20;
|
---|
| 4749 |
|
---|
| 4750 | for (int i = 0; i < limit; ++ i)
|
---|
| 4751 | {
|
---|
[542] | 4752 | viewPoint = mViewSpaceBox.GetRandomPoint();
|
---|
[490] | 4753 | if (mVspBspTree->ViewPointValid(viewPoint))
|
---|
| 4754 | {
|
---|
| 4755 | return true;
|
---|
| 4756 | }
|
---|
| 4757 | }
|
---|
[997] | 4758 |
|
---|
[490] | 4759 | Debug << "failed to find valid view point, taking " << viewPoint << endl;
|
---|
| 4760 | return false;
|
---|
| 4761 | }
|
---|
| 4762 |
|
---|
| 4763 |
|
---|
| 4764 | bool VspBspViewCellsManager::ViewPointValid(const Vector3 &viewPoint) const
|
---|
| 4765 | {
|
---|
[1551] | 4766 | // $$JB -> implemented in viewcellsmanager (slower, but allows dynamic
|
---|
| 4767 | // validy update in preprocessor for all managers)
|
---|
| 4768 | return ViewCellsManager::ViewPointValid(viewPoint);
|
---|
[570] | 4769 |
|
---|
[1551] | 4770 | // return mViewSpaceBox.IsInside(viewPoint) &&
|
---|
| 4771 | // mVspBspTree->ViewPointValid(viewPoint);
|
---|
[490] | 4772 | }
|
---|
| 4773 |
|
---|
| 4774 |
|
---|
[442] | 4775 | void VspBspViewCellsManager::Visualize(const ObjectContainer &objects,
|
---|
[466] | 4776 | const VssRayContainer &sampleRays)
|
---|
[442] | 4777 | {
|
---|
| 4778 | if (!ViewCellsConstructed())
|
---|
| 4779 | return;
|
---|
| 4780 |
|
---|
[485] | 4781 | VssRayContainer visRays;
|
---|
| 4782 | GetRaySets(sampleRays, mVisualizationSamples, visRays);
|
---|
[1416] | 4783 |
|
---|
[1551] | 4784 | if (1)
|
---|
[1047] | 4785 | {
|
---|
[1416] | 4786 | //////////////////
|
---|
| 4787 | //-- export final view cell partition
|
---|
| 4788 |
|
---|
[1020] | 4789 | Exporter *exporter = Exporter::GetExporter("final_view_cells.wrl");
|
---|
[600] | 4790 |
|
---|
[442] | 4791 | if (exporter)
|
---|
| 4792 | {
|
---|
[580] | 4793 | cout << "exporting view cells after post process ... ";
|
---|
[600] | 4794 | if (0)
|
---|
[1563] | 4795 | { // export view space box
|
---|
[542] | 4796 | exporter->SetWireframe();
|
---|
| 4797 | exporter->ExportBox(mViewSpaceBox);
|
---|
| 4798 | exporter->SetFilled();
|
---|
| 4799 | }
|
---|
| 4800 |
|
---|
[1052] | 4801 | Material m;
|
---|
| 4802 | m.mDiffuseColor.r = 0.0f;
|
---|
| 4803 | m.mDiffuseColor.g = 0.5f;
|
---|
| 4804 | m.mDiffuseColor.b = 0.5f;
|
---|
| 4805 |
|
---|
| 4806 | exporter->SetForcedMaterial(m);
|
---|
| 4807 |
|
---|
[1563] | 4808 | if (1 && mExportGeometry)
|
---|
[542] | 4809 | {
|
---|
[485] | 4810 | exporter->ExportGeometry(objects);
|
---|
[542] | 4811 | }
|
---|
[489] | 4812 |
|
---|
[1047] | 4813 | if (0 && mExportRays)
|
---|
[489] | 4814 | {
|
---|
[1052] | 4815 | exporter->ExportRays(visRays, RgbColor(1, 0, 0));
|
---|
[490] | 4816 | }
|
---|
[1760] | 4817 | ExportViewCellsForViz(exporter, NULL, mColorCode, GetClipPlane());
|
---|
[1020] | 4818 |
|
---|
[442] | 4819 | delete exporter;
|
---|
[580] | 4820 | cout << "finished" << endl;
|
---|
[442] | 4821 | }
|
---|
[557] | 4822 | }
|
---|
[503] | 4823 |
|
---|
[1551] | 4824 | ////////////////
|
---|
[442] | 4825 | //-- visualization of the BSP splits
|
---|
[1551] | 4826 |
|
---|
[442] | 4827 | bool exportSplits = false;
|
---|
[1004] | 4828 | Environment::GetSingleton()->GetBoolValue("VspBspTree.Visualization.exportSplits", exportSplits);
|
---|
[503] | 4829 |
|
---|
[442] | 4830 | if (exportSplits)
|
---|
| 4831 | {
|
---|
| 4832 | cout << "exporting splits ... ";
|
---|
[485] | 4833 | ExportSplits(objects, visRays);
|
---|
[442] | 4834 | cout << "finished" << endl;
|
---|
| 4835 | }
|
---|
| 4836 |
|
---|
[1551] | 4837 | ////////
|
---|
[542] | 4838 | //-- export single view cells
|
---|
[1570] | 4839 |
|
---|
| 4840 | int leafOut;
|
---|
| 4841 | Environment::GetSingleton()->GetIntValue("ViewCells.Visualization.maxOutput", leafOut);
|
---|
| 4842 | const int raysOut = 100;
|
---|
| 4843 |
|
---|
| 4844 | ExportSingleViewCells(objects, leafOut, false, true, false, raysOut, "");
|
---|
[442] | 4845 | }
|
---|
| 4846 |
|
---|
[503] | 4847 |
|
---|
[485] | 4848 | void VspBspViewCellsManager::ExportSplits(const ObjectContainer &objects,
|
---|
| 4849 | const VssRayContainer &rays)
|
---|
[442] | 4850 | {
|
---|
| 4851 | Exporter *exporter = Exporter::GetExporter("bsp_splits.x3d");
|
---|
| 4852 |
|
---|
[503] | 4853 | if (exporter)
|
---|
| 4854 | {
|
---|
| 4855 | Material m;
|
---|
[442] | 4856 | m.mDiffuseColor = RgbColor(1, 0, 0);
|
---|
| 4857 | exporter->SetForcedMaterial(m);
|
---|
| 4858 | exporter->SetWireframe();
|
---|
[503] | 4859 |
|
---|
[448] | 4860 | exporter->ExportBspSplits(*mVspBspTree, true);
|
---|
[442] | 4861 |
|
---|
| 4862 | // take forced material, else big scenes cannot be viewed
|
---|
| 4863 | m.mDiffuseColor = RgbColor(0, 1, 0);
|
---|
| 4864 | exporter->SetForcedMaterial(m);
|
---|
| 4865 | exporter->SetFilled();
|
---|
| 4866 |
|
---|
| 4867 | exporter->ResetForcedMaterial();
|
---|
[503] | 4868 |
|
---|
[442] | 4869 | // export rays
|
---|
[485] | 4870 | if (mExportRays)
|
---|
[1545] | 4871 | {
|
---|
[485] | 4872 | exporter->ExportRays(rays, RgbColor(1, 1, 0));
|
---|
[1545] | 4873 | }
|
---|
[503] | 4874 |
|
---|
[485] | 4875 | if (mExportGeometry)
|
---|
[1545] | 4876 | {
|
---|
[442] | 4877 | exporter->ExportGeometry(objects);
|
---|
[1545] | 4878 | }
|
---|
[442] | 4879 | delete exporter;
|
---|
| 4880 | }
|
---|
| 4881 | }
|
---|
| 4882 |
|
---|
[503] | 4883 |
|
---|
[1570] | 4884 | void VspBspViewCellsManager::ExportSingleViewCells(const ObjectContainer &objects,
|
---|
| 4885 | const int maxViewCells,
|
---|
| 4886 | const bool sortViewCells,
|
---|
| 4887 | const bool exportPvs,
|
---|
| 4888 | const bool exportRays,
|
---|
| 4889 | const int maxRays,
|
---|
| 4890 | const string prefix,
|
---|
| 4891 | VssRayContainer *visRays)
|
---|
| 4892 | {
|
---|
[694] | 4893 | if (sortViewCells)
|
---|
[801] | 4894 | {
|
---|
[1570] | 4895 | // sort view cells to visualize the largest view cells
|
---|
[1789] | 4896 | sort(mViewCells.begin(), mViewCells.end(), ViewCell::LargerRenderCost);
|
---|
[801] | 4897 | }
|
---|
| 4898 |
|
---|
[1566] | 4899 | //////////
|
---|
[1570] | 4900 | //-- some view cells for output
|
---|
[483] | 4901 |
|
---|
[1570] | 4902 | ViewCell::NewMail();
|
---|
| 4903 | const int limit = min(maxViewCells, (int)mViewCells.size());
|
---|
| 4904 |
|
---|
[478] | 4905 | for (int i = 0; i < limit; ++ i)
|
---|
[442] | 4906 | {
|
---|
[478] | 4907 | cout << "creating output for view cell " << i << " ... ";
|
---|
[503] | 4908 |
|
---|
[1570] | 4909 | ViewCell *vc = sortViewCells ? // largest view cell pvs first?
|
---|
| 4910 | mViewCells[(int)RandomValue(0, (float)mViewCells.size() - 0.5f)] : mViewCells[i];
|
---|
[442] | 4911 |
|
---|
[1570] | 4912 | if (vc->Mailed() || vc->GetId() == OUT_OF_BOUNDS_ID)
|
---|
| 4913 | continue;
|
---|
| 4914 |
|
---|
| 4915 | vc->Mail();
|
---|
| 4916 |
|
---|
[801] | 4917 | ObjectPvs pvs;
|
---|
| 4918 | mViewCellsTree->GetPvs(vc, pvs);
|
---|
| 4919 |
|
---|
[1570] | 4920 | char s[64]; sprintf(s, "%sviewcell%04d.wrl", prefix.c_str(), i);
|
---|
[639] | 4921 | Exporter *exporter = Exporter::GetExporter(s);
|
---|
| 4922 |
|
---|
[1709] | 4923 | const float pvsCost = mViewCellsTree->GetPvsCost(vc);
|
---|
| 4924 | cout << "view cell " << vc->GetId() << ": pvs cost=" << pvsCost << endl;
|
---|
[587] | 4925 |
|
---|
[1570] | 4926 | if (exportRays)
|
---|
[442] | 4927 | {
|
---|
[1566] | 4928 | ////////////
|
---|
| 4929 | //-- export rays piercing this view cell
|
---|
| 4930 |
|
---|
| 4931 | // take rays stored with the view cells during subdivision
|
---|
[1551] | 4932 | VssRayContainer vcRays;
|
---|
| 4933 | VssRayContainer collectRays;
|
---|
[639] | 4934 |
|
---|
[1566] | 4935 | // collect initial view cells
|
---|
[1551] | 4936 | ViewCellContainer leaves;
|
---|
| 4937 | mViewCellsTree->CollectLeaves(vc, leaves);
|
---|
[639] | 4938 |
|
---|
[1551] | 4939 | ViewCellContainer::const_iterator vit, vit_end = leaves.end();
|
---|
[1566] | 4940 | for (vit = leaves.begin(); vit != vit_end; ++ vit)
|
---|
[1570] | 4941 | {
|
---|
[1551] | 4942 | BspLeaf *vcLeaf = dynamic_cast<BspViewCell *>(*vit)->mLeaves[0];
|
---|
| 4943 | VssRayContainer::const_iterator rit, rit_end = vcLeaf->mVssRays.end();
|
---|
[587] | 4944 |
|
---|
[1551] | 4945 | for (rit = vcLeaf->mVssRays.begin(); rit != rit_end; ++ rit)
|
---|
[639] | 4946 | {
|
---|
[1551] | 4947 | collectRays.push_back(*rit);
|
---|
[639] | 4948 | }
|
---|
[1551] | 4949 | }
|
---|
[801] | 4950 |
|
---|
[1570] | 4951 | const int raysOut = min((int)collectRays.size(), maxRays);
|
---|
[1571] | 4952 |
|
---|
[1566] | 4953 | // prepare some rays for output
|
---|
[1551] | 4954 | VssRayContainer::const_iterator rit, rit_end = collectRays.end();
|
---|
| 4955 | for (rit = collectRays.begin(); rit != rit_end; ++ rit)
|
---|
[639] | 4956 | {
|
---|
[1566] | 4957 | const float p = RandomValue(0.0f, (float)collectRays.size());
|
---|
[1551] | 4958 |
|
---|
| 4959 | if (p < raysOut)
|
---|
[1566] | 4960 | {
|
---|
[1551] | 4961 | vcRays.push_back(*rit);
|
---|
[1566] | 4962 | }
|
---|
[639] | 4963 | }
|
---|
| 4964 |
|
---|
[1551] | 4965 | exporter->ExportRays(vcRays, RgbColor(1, 1, 1));
|
---|
[442] | 4966 | }
|
---|
[639] | 4967 |
|
---|
[1416] | 4968 | ////////////////
|
---|
[1020] | 4969 | //-- export view cell geometry
|
---|
[1416] | 4970 |
|
---|
[478] | 4971 | exporter->SetWireframe();
|
---|
[442] | 4972 |
|
---|
[478] | 4973 | Material m;//= RandomMaterial();
|
---|
| 4974 | m.mDiffuseColor = RgbColor(0, 1, 0);
|
---|
| 4975 | exporter->SetForcedMaterial(m);
|
---|
[442] | 4976 |
|
---|
[1416] | 4977 | ExportViewCellGeometry(exporter, vc, NULL, NULL);
|
---|
[639] | 4978 | exporter->SetFilled();
|
---|
[503] | 4979 |
|
---|
[1570] | 4980 | if (exportPvs)
|
---|
[574] | 4981 | {
|
---|
[801] | 4982 | Intersectable::NewMail();
|
---|
[1570] | 4983 |
|
---|
[1742] | 4984 | ObjectPvsIterator pit = pvs.GetIterator();
|
---|
| 4985 |
|
---|
[1570] | 4986 | cout << endl;
|
---|
[1742] | 4987 |
|
---|
[639] | 4988 | // output PVS of view cell
|
---|
[1742] | 4989 | while (pit.HasMoreEntries())
|
---|
| 4990 | {
|
---|
| 4991 | ObjectPvsEntry entry = pit.Next();
|
---|
| 4992 | Intersectable *intersect = entry.mObject;
|
---|
[1570] | 4993 |
|
---|
[639] | 4994 | if (!intersect->Mailed())
|
---|
| 4995 | {
|
---|
[1570] | 4996 | intersect->Mail();
|
---|
[1571] | 4997 |
|
---|
[643] | 4998 | m = RandomMaterial();
|
---|
| 4999 | exporter->SetForcedMaterial(m);
|
---|
[639] | 5000 | exporter->ExportIntersectable(intersect);
|
---|
| 5001 | }
|
---|
[503] | 5002 | }
|
---|
[1570] | 5003 | cout << endl;
|
---|
[442] | 5004 | }
|
---|
[801] | 5005 |
|
---|
[478] | 5006 | DEL_PTR(exporter);
|
---|
| 5007 | cout << "finished" << endl;
|
---|
[442] | 5008 | }
|
---|
| 5009 | }
|
---|
| 5010 |
|
---|
| 5011 |
|
---|
[1021] | 5012 | void VspBspViewCellsManager::TestFilter(const ObjectContainer &objects)
|
---|
[697] | 5013 | {
|
---|
[1021] | 5014 | Exporter *exporter = Exporter::GetExporter("filter.x3d");
|
---|
[697] | 5015 |
|
---|
[1021] | 5016 | Vector3 bsize = mViewSpaceBox.Size();
|
---|
| 5017 | const Vector3 viewPoint(mViewSpaceBox.Center());
|
---|
| 5018 | float w = Magnitude(mViewSpaceBox.Size()) * mFilterWidth;
|
---|
| 5019 | const Vector3 width = Vector3(w);
|
---|
| 5020 |
|
---|
| 5021 | PrVs testPrVs;
|
---|
| 5022 |
|
---|
| 5023 | if (exporter)
|
---|
| 5024 | {
|
---|
| 5025 | ViewCellContainer viewCells;
|
---|
| 5026 |
|
---|
| 5027 | const AxisAlignedBox3 tbox = GetFilterBBox(viewPoint, mFilterWidth);
|
---|
[697] | 5028 |
|
---|
[1021] | 5029 | GetPrVS(viewPoint, testPrVs, GetFilterWidth());
|
---|
[482] | 5030 |
|
---|
[1021] | 5031 | exporter->SetWireframe();
|
---|
[482] | 5032 |
|
---|
[1021] | 5033 | exporter->SetForcedMaterial(RgbColor(1,1,1));
|
---|
| 5034 | exporter->ExportBox(tbox);
|
---|
| 5035 |
|
---|
| 5036 | exporter->SetFilled();
|
---|
[503] | 5037 |
|
---|
[1021] | 5038 | exporter->SetForcedMaterial(RgbColor(0,1,0));
|
---|
[1416] | 5039 | ExportViewCellGeometry(exporter, GetViewCell(viewPoint), NULL, NULL);
|
---|
[564] | 5040 |
|
---|
[1021] | 5041 | //exporter->ResetForcedMaterial();
|
---|
| 5042 | exporter->SetForcedMaterial(RgbColor(0,0,1));
|
---|
[1416] | 5043 | ExportViewCellGeometry(exporter, testPrVs.mViewCell, NULL, NULL);
|
---|
[591] | 5044 |
|
---|
[1021] | 5045 | exporter->SetForcedMaterial(RgbColor(1,0,0));
|
---|
| 5046 | exporter->ExportGeometry(objects);
|
---|
[547] | 5047 |
|
---|
[1021] | 5048 | delete exporter;
|
---|
[482] | 5049 | }
|
---|
[1021] | 5050 | }
|
---|
[482] | 5051 |
|
---|
[547] | 5052 |
|
---|
[1021] | 5053 | int VspBspViewCellsManager::ComputeBoxIntersections(const AxisAlignedBox3 &box,
|
---|
| 5054 | ViewCellContainer &viewCells) const
|
---|
| 5055 | {
|
---|
| 5056 | return mVspBspTree->ComputeBoxIntersections(box, viewCells);
|
---|
[482] | 5057 | }
|
---|
| 5058 |
|
---|
| 5059 |
|
---|
[1021] | 5060 | int VspBspViewCellsManager::CastLineSegment(const Vector3 &origin,
|
---|
| 5061 | const Vector3 &termination,
|
---|
| 5062 | ViewCellContainer &viewcells)
|
---|
| 5063 | {
|
---|
| 5064 | return mVspBspTree->CastLineSegment(origin, termination, viewcells);
|
---|
| 5065 | }
|
---|
| 5066 |
|
---|
| 5067 |
|
---|
[979] | 5068 | void VspBspViewCellsManager::VisualizeWithFromPointQueries()
|
---|
| 5069 | {
|
---|
| 5070 | int numSamples;
|
---|
[1161] | 5071 |
|
---|
[1004] | 5072 | Environment::GetSingleton()->GetIntValue("RenderSampler.samples", numSamples);
|
---|
[979] | 5073 | cout << "samples" << numSamples << endl;
|
---|
| 5074 |
|
---|
| 5075 | vector<RenderCostSample> samples;
|
---|
| 5076 |
|
---|
[1145] | 5077 | if (!mPreprocessor->GetRenderer())
|
---|
[979] | 5078 | return;
|
---|
| 5079 |
|
---|
[1145] | 5080 | //start the view point queries
|
---|
[979] | 5081 | long startTime = GetTime();
|
---|
| 5082 | cout << "starting sampling of render cost ... ";
|
---|
| 5083 |
|
---|
[1145] | 5084 | mPreprocessor->GetRenderer()->SampleRenderCost(numSamples, samples, true);
|
---|
[979] | 5085 |
|
---|
| 5086 | cout << "finished in " << TimeDiff(startTime, GetTime()) * 1e-3 << " secs" << endl;
|
---|
| 5087 |
|
---|
| 5088 |
|
---|
[1161] | 5089 | // for each sample:
|
---|
| 5090 | // find view cells associated with the samples
|
---|
| 5091 | // store the sample pvs with the pvs associated with the view cell
|
---|
[1415] | 5092 | //
|
---|
[1161] | 5093 | // for each view cell:
|
---|
| 5094 | // compute difference point sampled pvs - view cell pvs
|
---|
| 5095 | // export geometry with color coded pvs difference
|
---|
| 5096 |
|
---|
| 5097 | std::map<ViewCell *, ObjectPvs> sampleMap;
|
---|
| 5098 |
|
---|
[979] | 5099 | vector<RenderCostSample>::const_iterator rit, rit_end = samples.end();
|
---|
| 5100 |
|
---|
[1161] | 5101 | for (rit = samples.begin(); rit != rit_end; ++ rit)
|
---|
| 5102 | {
|
---|
| 5103 | RenderCostSample sample = *rit;
|
---|
| 5104 |
|
---|
| 5105 | ViewCell *vc = GetViewCell(sample.mPosition);
|
---|
[991] | 5106 |
|
---|
[1161] | 5107 | std::map<ViewCell *, ObjectPvs>::iterator it = sampleMap.find(vc);
|
---|
| 5108 |
|
---|
| 5109 | if (it == sampleMap.end())
|
---|
| 5110 | {
|
---|
| 5111 | sampleMap[vc] = sample.mPvs;
|
---|
| 5112 | }
|
---|
| 5113 | else
|
---|
| 5114 | {
|
---|
[1740] | 5115 | (*it).second.MergeInPlace(sample.mPvs);
|
---|
[1161] | 5116 | }
|
---|
| 5117 | }
|
---|
| 5118 |
|
---|
| 5119 | // visualize the view cells
|
---|
| 5120 | std::map<ViewCell *, ObjectPvs>::const_iterator vit, vit_end = sampleMap.end();
|
---|
| 5121 |
|
---|
| 5122 | Material m;//= RandomMaterial();
|
---|
| 5123 |
|
---|
| 5124 | for (vit = sampleMap.begin(); vit != vit_end; ++ vit)
|
---|
| 5125 | {
|
---|
| 5126 | ViewCell *vc = (*vit).first;
|
---|
| 5127 |
|
---|
| 5128 | const int pvsVc = mViewCellsTree->GetPvsEntries(vc);
|
---|
[1168] | 5129 | const int pvsPtSamples = (*vit).second.GetSize();
|
---|
[1161] | 5130 |
|
---|
[1168] | 5131 | m.mDiffuseColor.r = (float) (pvsVc - pvsPtSamples);
|
---|
[1161] | 5132 | m.mDiffuseColor.b = 1.0f;
|
---|
| 5133 | //exporter->SetForcedMaterial(m);
|
---|
[1416] | 5134 | //ExportViewCellGeometry(exporter, vc, mClipPlaneForViz);
|
---|
[1161] | 5135 |
|
---|
[1415] | 5136 | /* // counting the pvss
|
---|
| 5137 | for (rit = samples.begin(); rit != rit_end; ++ rit)
|
---|
| 5138 | {
|
---|
| 5139 | RenderCostSample sample = *rit;
|
---|
| 5140 | ViewCell *vc = GetViewCell(sample.mPosition);
|
---|
[1161] | 5141 |
|
---|
[1415] | 5142 | AxisAlignedBox3 box(sample.mPosition - Vector3(1, 1, 1), sample.mPosition + Vector3(1, 1, 1));
|
---|
| 5143 | Mesh *hMesh = CreateMeshFromBox(box);
|
---|
[1001] | 5144 |
|
---|
[1415] | 5145 | DEL_PTR(hMesh);
|
---|
| 5146 | }
|
---|
| 5147 | */
|
---|
[979] | 5148 | }
|
---|
| 5149 | }
|
---|
| 5150 |
|
---|
| 5151 |
|
---|
[580] | 5152 | void VspBspViewCellsManager::ExportViewCellGeometry(Exporter *exporter,
|
---|
[1416] | 5153 | ViewCell *vc,
|
---|
| 5154 | const AxisAlignedBox3 *sceneBox,
|
---|
| 5155 | const AxisAlignedPlane *clipPlane
|
---|
| 5156 | ) const
|
---|
[482] | 5157 | {
|
---|
[660] | 5158 | if (clipPlane)
|
---|
[591] | 5159 | {
|
---|
[1047] | 5160 | const Plane3 plane = clipPlane->GetPlane();
|
---|
| 5161 |
|
---|
[591] | 5162 | ViewCellContainer leaves;
|
---|
| 5163 | mViewCellsTree->CollectLeaves(vc, leaves);
|
---|
| 5164 | ViewCellContainer::const_iterator it, it_end = leaves.end();
|
---|
| 5165 |
|
---|
| 5166 | for (it = leaves.begin(); it != it_end; ++ it)
|
---|
| 5167 | {
|
---|
| 5168 | BspNodeGeometry geom;
|
---|
| 5169 | BspNodeGeometry front;
|
---|
| 5170 | BspNodeGeometry back;
|
---|
| 5171 |
|
---|
[1551] | 5172 | mVspBspTree->ConstructGeometry(*it, geom);
|
---|
[591] | 5173 |
|
---|
[1052] | 5174 | const float eps = 0.0001f;
|
---|
[1047] | 5175 | const int cf = geom.Side(plane, eps);
|
---|
[682] | 5176 |
|
---|
[710] | 5177 | if (cf == -1)
|
---|
[682] | 5178 | {
|
---|
| 5179 | exporter->ExportPolygons(geom.GetPolys());
|
---|
| 5180 | }
|
---|
[710] | 5181 | else if (cf == 0)
|
---|
[684] | 5182 | {
|
---|
[682] | 5183 | geom.SplitGeometry(front,
|
---|
| 5184 | back,
|
---|
[1047] | 5185 | plane,
|
---|
[682] | 5186 | mViewSpaceBox,
|
---|
[710] | 5187 | eps);
|
---|
[801] | 5188 |
|
---|
[683] | 5189 | if (back.Valid())
|
---|
| 5190 | {
|
---|
[682] | 5191 | exporter->ExportPolygons(back.GetPolys());
|
---|
[708] | 5192 | }
|
---|
[684] | 5193 | }
|
---|
[591] | 5194 | }
|
---|
| 5195 | }
|
---|
| 5196 | else
|
---|
| 5197 | {
|
---|
[801] | 5198 | // export mesh if available
|
---|
[1001] | 5199 | // TODO: some bug here?
|
---|
[1563] | 5200 | if (1 && vc->GetMesh())
|
---|
[801] | 5201 | {
|
---|
| 5202 | exporter->ExportMesh(vc->GetMesh());
|
---|
| 5203 | }
|
---|
| 5204 | else
|
---|
[1001] | 5205 | {
|
---|
[801] | 5206 | BspNodeGeometry geom;
|
---|
| 5207 | mVspBspTree->ConstructGeometry(vc, geom);
|
---|
| 5208 | exporter->ExportPolygons(geom.GetPolys());
|
---|
[1001] | 5209 | }
|
---|
[591] | 5210 | }
|
---|
[482] | 5211 | }
|
---|
| 5212 |
|
---|
| 5213 |
|
---|
| 5214 | int VspBspViewCellsManager::GetMaxTreeDiff(ViewCell *vc) const
|
---|
| 5215 | {
|
---|
[580] | 5216 | ViewCellContainer leaves;
|
---|
| 5217 | mViewCellsTree->CollectLeaves(vc, leaves);
|
---|
[482] | 5218 |
|
---|
| 5219 | int maxDist = 0;
|
---|
[580] | 5220 |
|
---|
[482] | 5221 | // compute max height difference
|
---|
[580] | 5222 | for (int i = 0; i < (int)leaves.size(); ++ i)
|
---|
[1001] | 5223 | {
|
---|
[580] | 5224 | for (int j = 0; j < (int)leaves.size(); ++ j)
|
---|
[1001] | 5225 | {
|
---|
[1551] | 5226 | BspLeaf *leaf = dynamic_cast<BspViewCell *>(leaves[i])->mLeaves[0];
|
---|
[482] | 5227 |
|
---|
[1001] | 5228 | if (i != j)
|
---|
| 5229 | {
|
---|
[1551] | 5230 | BspLeaf *leaf2 =dynamic_cast<BspViewCell *>(leaves[j])->mLeaves[0];
|
---|
| 5231 | const int dist = mVspBspTree->TreeDistance(leaf, leaf2);
|
---|
[1001] | 5232 |
|
---|
| 5233 | if (dist > maxDist)
|
---|
| 5234 | maxDist = dist;
|
---|
| 5235 | }
|
---|
[482] | 5236 | }
|
---|
| 5237 | }
|
---|
[580] | 5238 |
|
---|
[492] | 5239 | return maxDist;
|
---|
| 5240 | }
|
---|
[482] | 5241 |
|
---|
[492] | 5242 |
|
---|
[879] | 5243 | ViewCell *VspBspViewCellsManager::GetViewCell(const Vector3 &point, const bool active) const
|
---|
[492] | 5244 | {
|
---|
[1021] | 5245 | if (!ViewCellsConstructed())
|
---|
[508] | 5246 | return NULL;
|
---|
[572] | 5247 |
|
---|
| 5248 | if (!mViewSpaceBox.IsInside(point))
|
---|
| 5249 | return NULL;
|
---|
| 5250 |
|
---|
[879] | 5251 | return mVspBspTree->GetViewCell(point, active);
|
---|
[492] | 5252 | }
|
---|
[503] | 5253 |
|
---|
| 5254 |
|
---|
| 5255 | void VspBspViewCellsManager::CreateMesh(ViewCell *vc)
|
---|
| 5256 | {
|
---|
| 5257 | BspNodeGeometry geom;
|
---|
[590] | 5258 | mVspBspTree->ConstructGeometry(vc, geom);
|
---|
[582] | 5259 |
|
---|
[1001] | 5260 | Mesh *mesh = MeshManager::GetSingleton()->CreateResource();
|
---|
[840] | 5261 | IncludeNodeGeomInMesh(geom, *mesh);
|
---|
| 5262 |
|
---|
[503] | 5263 | vc->SetMesh(mesh);
|
---|
| 5264 | }
|
---|
[508] | 5265 |
|
---|
| 5266 |
|
---|
[532] | 5267 | int VspBspViewCellsManager::CastBeam(Beam &beam)
|
---|
| 5268 | {
|
---|
[535] | 5269 | return mVspBspTree->CastBeam(beam);
|
---|
[532] | 5270 | }
|
---|
[551] | 5271 |
|
---|
| 5272 |
|
---|
[587] | 5273 | void VspBspViewCellsManager::Finalize(ViewCell *viewCell,
|
---|
| 5274 | const bool createMesh)
|
---|
[551] | 5275 | {
|
---|
| 5276 | float area = 0;
|
---|
| 5277 | float volume = 0;
|
---|
| 5278 |
|
---|
[580] | 5279 | ViewCellContainer leaves;
|
---|
[582] | 5280 | mViewCellsTree->CollectLeaves(viewCell, leaves);
|
---|
[580] | 5281 |
|
---|
| 5282 | ViewCellContainer::const_iterator it, it_end = leaves.end();
|
---|
| 5283 |
|
---|
[693] | 5284 | for (it = leaves.begin(); it != it_end; ++ it)
|
---|
[551] | 5285 | {
|
---|
| 5286 | BspNodeGeometry geom;
|
---|
[1551] | 5287 | mVspBspTree->ConstructGeometry(*it, geom);
|
---|
[551] | 5288 |
|
---|
[719] | 5289 | const float lVol = geom.GetVolume();
|
---|
| 5290 | const float lArea = geom.GetArea();
|
---|
[693] | 5291 |
|
---|
| 5292 | area += lArea;
|
---|
| 5293 | volume += lVol;
|
---|
| 5294 |
|
---|
[1616] | 5295 | if (createMesh)
|
---|
| 5296 | CreateMesh(*it);
|
---|
[551] | 5297 | }
|
---|
| 5298 |
|
---|
| 5299 | viewCell->SetVolume(volume);
|
---|
| 5300 | viewCell->SetArea(area);
|
---|
[563] | 5301 | }
|
---|
[575] | 5302 |
|
---|
| 5303 |
|
---|
[693] | 5304 | void VspBspViewCellsManager::TestSubdivision()
|
---|
| 5305 | {
|
---|
| 5306 | ViewCellContainer leaves;
|
---|
| 5307 | mViewCellsTree->CollectLeaves(mViewCellsTree->GetRoot(), leaves);
|
---|
| 5308 |
|
---|
| 5309 | ViewCellContainer::const_iterator it, it_end = leaves.end();
|
---|
| 5310 |
|
---|
| 5311 | const float vol = mViewSpaceBox.GetVolume();
|
---|
| 5312 | float subdivVol = 0;
|
---|
| 5313 | float newVol = 0;
|
---|
| 5314 |
|
---|
| 5315 | for (it = leaves.begin(); it != it_end; ++ it)
|
---|
| 5316 | {
|
---|
| 5317 | BspNodeGeometry geom;
|
---|
[1551] | 5318 | mVspBspTree->ConstructGeometry(*it, geom);
|
---|
[693] | 5319 |
|
---|
| 5320 | const float lVol = geom.GetVolume();
|
---|
| 5321 |
|
---|
| 5322 | newVol += lVol;
|
---|
| 5323 | subdivVol += (*it)->GetVolume();
|
---|
[697] | 5324 |
|
---|
[704] | 5325 | float thres = 0.9f;
|
---|
[697] | 5326 | if ((lVol < ((*it)->GetVolume() * thres)) || (lVol * thres > ((*it)->GetVolume())))
|
---|
| 5327 | Debug << "warning: " << lVol << " " << (*it)->GetVolume() << endl;
|
---|
[693] | 5328 | }
|
---|
| 5329 |
|
---|
| 5330 | Debug << "exact volume: " << vol << endl;
|
---|
| 5331 | Debug << "subdivision volume: " << subdivVol << endl;
|
---|
| 5332 | Debug << "new volume: " << newVol << endl;
|
---|
| 5333 | }
|
---|
| 5334 |
|
---|
| 5335 |
|
---|
[577] | 5336 | void VspBspViewCellsManager::PrepareLoadedViewCells()
|
---|
| 5337 | {
|
---|
| 5338 | // TODO: do I still need this here?
|
---|
[590] | 5339 | if (0)
|
---|
[693] | 5340 | mVspBspTree->RepairViewCellsLeafLists();
|
---|
[577] | 5341 | }
|
---|
[575] | 5342 |
|
---|
[1021] | 5343 |
|
---|
| 5344 |
|
---|
[1887] | 5345 | /************************************************************************/
|
---|
| 5346 | /* VspOspViewCellsManager implementation */
|
---|
| 5347 | /************************************************************************/
|
---|
[1021] | 5348 |
|
---|
| 5349 |
|
---|
[1789] | 5350 | VspOspViewCellsManager::VspOspViewCellsManager(ViewCellsTree *vcTree,
|
---|
| 5351 | const string &hierarchyType)
|
---|
[1740] | 5352 | : ViewCellsManager(vcTree)
|
---|
| 5353 | {
|
---|
| 5354 | Environment::GetSingleton()->GetIntValue("Hierarchy.Construction.samples", mInitialSamples);
|
---|
| 5355 |
|
---|
[1887] | 5356 | Environment::GetSingleton()->GetBoolValue("ViewCells.compressObjects", mCompressObjects);
|
---|
| 5357 |
|
---|
| 5358 | Debug << "compressing objects: " << mCompressObjects << endl;
|
---|
| 5359 | cout << "compressing objects: " << mCompressObjects << endl;
|
---|
| 5360 |
|
---|
[1740] | 5361 | mHierarchyManager = CreateHierarchyManager(hierarchyType);
|
---|
| 5362 | mHierarchyManager->SetViewCellsManager(this);
|
---|
| 5363 | mHierarchyManager->SetViewCellsTree(mViewCellsTree);
|
---|
| 5364 | }
|
---|
| 5365 |
|
---|
| 5366 |
|
---|
[1278] | 5367 | VspOspViewCellsManager::VspOspViewCellsManager(ViewCellsTree *vcTree, HierarchyManager *hm)
|
---|
| 5368 | : ViewCellsManager(vcTree), mHierarchyManager(hm)
|
---|
[859] | 5369 | {
|
---|
[1640] | 5370 | Environment::GetSingleton()->GetIntValue("Hierarchy.Construction.samples", mInitialSamples);
|
---|
[1887] | 5371 | Environment::GetSingleton()->GetBoolValue("ViewCells.compressObjects", mCompressObjects);
|
---|
[1106] | 5372 |
|
---|
[1887] | 5373 | Debug << "compressing objects: " << mCompressObjects << endl;
|
---|
| 5374 | cout << "compressing objects: " << mCompressObjects << endl;
|
---|
| 5375 |
|
---|
[1278] | 5376 | mHierarchyManager->SetViewCellsManager(this);
|
---|
| 5377 | mHierarchyManager->SetViewCellsTree(mViewCellsTree);
|
---|
[1021] | 5378 | }
|
---|
[859] | 5379 |
|
---|
[1789] | 5380 |
|
---|
[1743] | 5381 | Intersectable *
|
---|
| 5382 | VspOspViewCellsManager::GetIntersectable(const VssRay &ray, const bool isTermination) const
|
---|
| 5383 | {
|
---|
[1902] | 5384 | if (mUseKdPvs)
|
---|
| 5385 | {
|
---|
| 5386 | return ViewCellsManager::GetIntersectable(ray, isTermination);
|
---|
| 5387 | }
|
---|
| 5388 | else
|
---|
| 5389 | {
|
---|
| 5390 | return mHierarchyManager->GetIntersectable(ray, isTermination);
|
---|
| 5391 | }
|
---|
[1743] | 5392 | }
|
---|
[859] | 5393 |
|
---|
[1789] | 5394 |
|
---|
[1740] | 5395 | HierarchyManager *VspOspViewCellsManager::CreateHierarchyManager(const string &hierarchyType)
|
---|
| 5396 | {
|
---|
| 5397 | HierarchyManager *hierarchyManager;
|
---|
| 5398 |
|
---|
| 5399 | if (strcmp(hierarchyType.c_str(), "osp") == 0)
|
---|
| 5400 | {
|
---|
| 5401 | Debug << "hierarchy manager: osp" << endl;
|
---|
| 5402 | hierarchyManager = new HierarchyManager(HierarchyManager::KD_BASED_OBJ_SUBDIV);
|
---|
| 5403 | }
|
---|
| 5404 | else if (strcmp(hierarchyType.c_str(), "bvh") == 0)
|
---|
| 5405 | {
|
---|
| 5406 | Debug << "hierarchy manager: bvh" << endl;
|
---|
| 5407 | hierarchyManager = new HierarchyManager(HierarchyManager::BV_BASED_OBJ_SUBDIV);
|
---|
| 5408 | }
|
---|
| 5409 | else // only view space partition
|
---|
| 5410 | {
|
---|
| 5411 | Debug << "hierarchy manager: obj" << endl;
|
---|
| 5412 | hierarchyManager = new HierarchyManager(HierarchyManager::NO_OBJ_SUBDIV);
|
---|
| 5413 | }
|
---|
| 5414 |
|
---|
| 5415 | return hierarchyManager;
|
---|
| 5416 | }
|
---|
| 5417 |
|
---|
| 5418 |
|
---|
[1021] | 5419 | VspOspViewCellsManager::~VspOspViewCellsManager()
|
---|
| 5420 | {
|
---|
[1740] | 5421 | DEL_PTR(mHierarchyManager);
|
---|
[1021] | 5422 | }
|
---|
| 5423 |
|
---|
| 5424 |
|
---|
| 5425 | float VspOspViewCellsManager::GetProbability(ViewCell *viewCell)
|
---|
| 5426 | {
|
---|
| 5427 | return GetVolume(viewCell) / mViewSpaceBox.GetVolume();
|
---|
| 5428 | }
|
---|
| 5429 |
|
---|
| 5430 |
|
---|
| 5431 | void VspOspViewCellsManager::CollectViewCells()
|
---|
| 5432 | {
|
---|
| 5433 | // view cells tree constructed
|
---|
| 5434 | if (!ViewCellsTreeConstructed())
|
---|
| 5435 | {
|
---|
[1278] | 5436 | mHierarchyManager->GetVspTree()->CollectViewCells(mViewCells, false);
|
---|
[1021] | 5437 | }
|
---|
| 5438 | else
|
---|
| 5439 | { // we can use the view cells tree hierarchy to get the right set
|
---|
| 5440 | mViewCellsTree->CollectBestViewCellSet(mViewCells, mNumActiveViewCells);
|
---|
| 5441 | }
|
---|
| 5442 | }
|
---|
| 5443 |
|
---|
| 5444 |
|
---|
| 5445 | bool VspOspViewCellsManager::ViewCellsConstructed() const
|
---|
| 5446 | {
|
---|
[1278] | 5447 | return mHierarchyManager->GetVspTree()->GetRoot() != NULL;
|
---|
[1021] | 5448 | }
|
---|
| 5449 |
|
---|
| 5450 |
|
---|
| 5451 | ViewCell *VspOspViewCellsManager::GenerateViewCell(Mesh *mesh) const
|
---|
| 5452 | {
|
---|
| 5453 | return new VspViewCell(mesh);
|
---|
| 5454 | }
|
---|
| 5455 |
|
---|
| 5456 |
|
---|
| 5457 | int VspOspViewCellsManager::ConstructSubdivision(const ObjectContainer &objects,
|
---|
| 5458 | const VssRayContainer &rays)
|
---|
| 5459 | {
|
---|
| 5460 | mMaxPvsSize = (int)(mMaxPvsRatio * (float)objects.size());
|
---|
| 5461 |
|
---|
[1074] | 5462 | // skip rest if view cells were already constructed
|
---|
[1021] | 5463 | if (ViewCellsConstructed())
|
---|
| 5464 | return 0;
|
---|
| 5465 |
|
---|
| 5466 | int sampleContributions = 0;
|
---|
| 5467 | VssRayContainer sampleRays;
|
---|
| 5468 |
|
---|
| 5469 | int limit = min (mInitialSamples, (int)rays.size());
|
---|
| 5470 |
|
---|
| 5471 | VssRayContainer constructionRays;
|
---|
| 5472 | VssRayContainer savedRays;
|
---|
| 5473 |
|
---|
| 5474 | Debug << "samples used for vsp bsp subdivision: " << mInitialSamples
|
---|
| 5475 | << ", actual rays: " << (int)rays.size() << endl;
|
---|
| 5476 |
|
---|
| 5477 | GetRaySets(rays, mInitialSamples, constructionRays, &savedRays);
|
---|
| 5478 |
|
---|
[1421] | 5479 | Debug << "initial rays used for construction: " << (int)constructionRays.size() << endl;
|
---|
[1021] | 5480 | Debug << "saved rays: " << (int)savedRays.size() << endl;
|
---|
| 5481 |
|
---|
[1293] | 5482 | mHierarchyManager->Construct(constructionRays, objects, &mViewSpaceBox);
|
---|
[1142] | 5483 |
|
---|
[1576] | 5484 | #if TEST_EVALUATION
|
---|
| 5485 | VssRayContainer::const_iterator tit, tit_end = constructionRays.end();
|
---|
| 5486 | for (tit = constructionRays.begin(); tit != tit_end; ++ tit)
|
---|
| 5487 | {
|
---|
| 5488 | storedRays.push_back(new VssRay(*(*tit)));
|
---|
| 5489 | }
|
---|
| 5490 | #endif
|
---|
| 5491 |
|
---|
[1545] | 5492 | /////////////////////////
|
---|
[1444] | 5493 | //-- print satistics for subdivision and view cells
|
---|
| 5494 |
|
---|
[1421] | 5495 | Debug << endl << endl << *mHierarchyManager << endl;
|
---|
[1021] | 5496 |
|
---|
[1444] | 5497 | ResetViewCells();
|
---|
| 5498 | Debug << "\nView cells after construction:\n" << mCurrentViewCellsStats << endl;
|
---|
| 5499 |
|
---|
[1545] | 5500 | //////////////
|
---|
[1444] | 5501 | //-- recast rest of rays
|
---|
| 5502 |
|
---|
[1286] | 5503 | const long startTime = GetTime();
|
---|
[1021] | 5504 | cout << "Computing remaining ray contributions ... ";
|
---|
| 5505 |
|
---|
| 5506 | if (SAMPLE_AFTER_SUBDIVISION)
|
---|
| 5507 | ComputeSampleContributions(savedRays, true, false);
|
---|
| 5508 |
|
---|
[1415] | 5509 | Debug << "finished computing remaining ray contribution in " << TimeDiff(startTime, GetTime()) * 1e-3
|
---|
[1021] | 5510 | << " secs" << endl;
|
---|
| 5511 |
|
---|
| 5512 | if (0)
|
---|
[1932] | 5513 | {
|
---|
| 5514 | // real meshes are constructed at this stage
|
---|
[1021] | 5515 | cout << "finalizing view cells ... ";
|
---|
[1932] | 5516 | FinalizeViewCells(true);
|
---|
[1021] | 5517 | cout << "finished" << endl;
|
---|
| 5518 | }
|
---|
| 5519 |
|
---|
| 5520 | return sampleContributions;
|
---|
| 5521 | }
|
---|
| 5522 |
|
---|
| 5523 |
|
---|
| 5524 | int VspOspViewCellsManager::PostProcess(const ObjectContainer &objects,
|
---|
| 5525 | const VssRayContainer &rays)
|
---|
| 5526 | {
|
---|
| 5527 | if (!ViewCellsConstructed())
|
---|
| 5528 | {
|
---|
[1842] | 5529 | Debug << "post process error: no view cells constructed" << endl;
|
---|
[1021] | 5530 | return 0;
|
---|
| 5531 | }
|
---|
| 5532 |
|
---|
[1418] | 5533 | // if view cells were already constructed before post processing step
|
---|
| 5534 | // (e.g., because they were loaded), we are finished
|
---|
[1021] | 5535 | if (mViewCellsFinished)
|
---|
| 5536 | {
|
---|
| 5537 | FinalizeViewCells(true);
|
---|
| 5538 | EvaluateViewCellsStats();
|
---|
| 5539 |
|
---|
| 5540 | return 0;
|
---|
| 5541 | }
|
---|
| 5542 |
|
---|
| 5543 | // check if new view cells turned invalid
|
---|
| 5544 | int minPvs, maxPvs;
|
---|
| 5545 |
|
---|
| 5546 | if (0)
|
---|
| 5547 | {
|
---|
| 5548 | minPvs = mMinPvsSize;
|
---|
| 5549 | maxPvs = mMaxPvsSize;
|
---|
| 5550 | }
|
---|
| 5551 | else
|
---|
| 5552 | {
|
---|
[1414] | 5553 | // problem matt: why did I start here from zero?
|
---|
| 5554 | minPvs = 0;
|
---|
[1021] | 5555 | maxPvs = mMaxPvsSize;
|
---|
| 5556 | }
|
---|
| 5557 |
|
---|
| 5558 | Debug << "setting validity, min: " << minPvs << " max: " << maxPvs << endl;
|
---|
| 5559 | cout << "setting validity, min: " << minPvs << " max: " << maxPvs << endl;
|
---|
| 5560 |
|
---|
| 5561 | SetValidity(minPvs, maxPvs);
|
---|
| 5562 |
|
---|
| 5563 |
|
---|
[1414] | 5564 | // area is not up to date, has to be recomputed
|
---|
[1021] | 5565 | mTotalAreaValid = false;
|
---|
| 5566 | VssRayContainer postProcessRays;
|
---|
| 5567 | GetRaySets(rays, mPostProcessSamples, postProcessRays);
|
---|
| 5568 |
|
---|
| 5569 | Debug << "post processing using " << (int)postProcessRays.size() << " samples" << endl;
|
---|
| 5570 |
|
---|
| 5571 |
|
---|
| 5572 | // compute tree by merging the nodes of the spatial hierarchy
|
---|
[1278] | 5573 | ViewCell *root = ConstructSpatialMergeTree(mHierarchyManager->GetVspTree()->GetRoot());
|
---|
[1021] | 5574 | mViewCellsTree->SetRoot(root);
|
---|
| 5575 |
|
---|
[1696] | 5576 | //////////////////////////
|
---|
| 5577 | //-- update pvs up to the root of the hierarchy
|
---|
[1418] | 5578 |
|
---|
[1021] | 5579 | ObjectPvs pvs;
|
---|
| 5580 | UpdatePvsForEvaluation(root, pvs);
|
---|
| 5581 |
|
---|
[1414] | 5582 |
|
---|
[1418] | 5583 | //////////////////////
|
---|
[1021] | 5584 | //-- render simulation after merge + refine
|
---|
[1414] | 5585 |
|
---|
[1415] | 5586 | cout << "\nview cells partition render time before compress" << endl << endl;
|
---|
[1021] | 5587 | dynamic_cast<RenderSimulator *>(mRenderer)->RenderScene();
|
---|
| 5588 | SimulationStatistics ss;
|
---|
| 5589 | dynamic_cast<RenderSimulator *>(mRenderer)->GetStatistics(ss);
|
---|
| 5590 | cout << ss << endl;
|
---|
[1414] | 5591 |
|
---|
[1486] | 5592 |
|
---|
[1843] | 5593 | mHierarchyManager->CreateUniqueObjectIds();
|
---|
| 5594 |
|
---|
[1586] | 5595 | ///////////
|
---|
[1021] | 5596 | //-- compression
|
---|
[1262] | 5597 |
|
---|
[1843] | 5598 | if (0) CompressViewCells();
|
---|
[859] | 5599 |
|
---|
[1486] | 5600 | /////////////
|
---|
| 5601 | //-- some tasks still to do on the view cells:
|
---|
| 5602 | //-- Compute meshes from view cell geometry, evaluate volume and / or area
|
---|
[1696] | 5603 |
|
---|
[1021] | 5604 | if (1) FinalizeViewCells(true);
|
---|
| 5605 |
|
---|
| 5606 | return 0;
|
---|
[859] | 5607 | }
|
---|
| 5608 |
|
---|
[1021] | 5609 |
|
---|
| 5610 | int VspOspViewCellsManager::GetType() const
|
---|
[884] | 5611 | {
|
---|
[1021] | 5612 | return VSP_OSP;
|
---|
| 5613 | }
|
---|
[859] | 5614 |
|
---|
[1021] | 5615 |
|
---|
| 5616 | ViewCell *VspOspViewCellsManager::ConstructSpatialMergeTree(VspNode *root)
|
---|
| 5617 | {
|
---|
| 5618 | // terminate recursion
|
---|
| 5619 | if (root->IsLeaf())
|
---|
| 5620 | {
|
---|
| 5621 | VspLeaf *leaf = dynamic_cast<VspLeaf *>(root);
|
---|
| 5622 | leaf->GetViewCell()->SetMergeCost(0.0f);
|
---|
| 5623 | return leaf->GetViewCell();
|
---|
| 5624 | }
|
---|
| 5625 |
|
---|
| 5626 | VspInterior *interior = dynamic_cast<VspInterior *>(root);
|
---|
| 5627 | ViewCellInterior *viewCellInterior = new ViewCellInterior();
|
---|
| 5628 |
|
---|
| 5629 | // evaluate merge cost for priority traversal
|
---|
[1713] | 5630 | const float mergeCost = -(float)root->mTimeStamp;
|
---|
[1021] | 5631 | viewCellInterior->SetMergeCost(mergeCost);
|
---|
| 5632 |
|
---|
| 5633 | float volume = 0;
|
---|
| 5634 |
|
---|
| 5635 | VspNode *front = interior->GetFront();
|
---|
| 5636 | VspNode *back = interior->GetBack();
|
---|
| 5637 |
|
---|
| 5638 | ObjectPvs frontPvs, backPvs;
|
---|
| 5639 |
|
---|
[1545] | 5640 | /////////
|
---|
[1021] | 5641 | //-- recursivly compute child hierarchies
|
---|
[1545] | 5642 |
|
---|
[1021] | 5643 | ViewCell *backVc = ConstructSpatialMergeTree(back);
|
---|
| 5644 | ViewCell *frontVc = ConstructSpatialMergeTree(front);
|
---|
| 5645 |
|
---|
| 5646 | viewCellInterior->SetupChildLink(backVc);
|
---|
| 5647 | viewCellInterior->SetupChildLink(frontVc);
|
---|
| 5648 |
|
---|
| 5649 | volume += backVc->GetVolume();
|
---|
| 5650 | volume += frontVc->GetVolume();
|
---|
| 5651 |
|
---|
| 5652 | viewCellInterior->SetVolume(volume);
|
---|
| 5653 |
|
---|
| 5654 | return viewCellInterior;
|
---|
| 5655 | }
|
---|
| 5656 |
|
---|
| 5657 |
|
---|
| 5658 | bool VspOspViewCellsManager::GetViewPoint(Vector3 &viewPoint) const
|
---|
| 5659 | {
|
---|
| 5660 | if (!ViewCellsConstructed())
|
---|
| 5661 | return ViewCellsManager::GetViewPoint(viewPoint);
|
---|
| 5662 |
|
---|
| 5663 | // TODO: set reasonable limit
|
---|
| 5664 | const int limit = 20;
|
---|
| 5665 |
|
---|
| 5666 | for (int i = 0; i < limit; ++ i)
|
---|
| 5667 | {
|
---|
| 5668 | viewPoint = mViewSpaceBox.GetRandomPoint();
|
---|
[1047] | 5669 |
|
---|
[1278] | 5670 | if (mHierarchyManager->GetVspTree()->ViewPointValid(viewPoint))
|
---|
[1021] | 5671 | {
|
---|
| 5672 | return true;
|
---|
| 5673 | }
|
---|
[904] | 5674 | }
|
---|
[859] | 5675 |
|
---|
[1021] | 5676 | Debug << "failed to find valid view point, taking " << viewPoint << endl;
|
---|
| 5677 | return false;
|
---|
[884] | 5678 | }
|
---|
| 5679 |
|
---|
| 5680 |
|
---|
[1027] | 5681 | void VspOspViewCellsManager::ExportViewCellGeometry(Exporter *exporter,
|
---|
| 5682 | ViewCell *vc,
|
---|
[1416] | 5683 | const AxisAlignedBox3 *sceneBox,
|
---|
| 5684 | const AxisAlignedPlane *clipPlane
|
---|
| 5685 | ) const
|
---|
[1027] | 5686 | {
|
---|
| 5687 | ViewCellContainer leaves;
|
---|
| 5688 | mViewCellsTree->CollectLeaves(vc, leaves);
|
---|
| 5689 | ViewCellContainer::const_iterator it, it_end = leaves.end();
|
---|
| 5690 |
|
---|
[1047] | 5691 | Plane3 plane;
|
---|
| 5692 | if (clipPlane)
|
---|
[1418] | 5693 | {
|
---|
| 5694 | // arbitrary plane definition
|
---|
[1047] | 5695 | plane = clipPlane->GetPlane();
|
---|
[1418] | 5696 | }
|
---|
[1047] | 5697 |
|
---|
[1027] | 5698 | for (it = leaves.begin(); it != it_end; ++ it)
|
---|
| 5699 | {
|
---|
| 5700 | VspViewCell *vspVc = dynamic_cast<VspViewCell *>(*it);
|
---|
[1551] | 5701 | VspLeaf *l = vspVc->mLeaves[0];
|
---|
[1027] | 5702 |
|
---|
[1416] | 5703 | const AxisAlignedBox3 box =
|
---|
[1551] | 5704 | mHierarchyManager->GetVspTree()->GetBoundingBox(vspVc->mLeaves[0]);
|
---|
[1047] | 5705 |
|
---|
[1418] | 5706 | if (sceneBox && !Overlap(*sceneBox, box))
|
---|
[1415] | 5707 | continue;
|
---|
| 5708 |
|
---|
[1047] | 5709 | if (clipPlane)
|
---|
| 5710 | {
|
---|
| 5711 | if (box.Side(plane) == -1)
|
---|
[1144] | 5712 | {
|
---|
[1047] | 5713 | exporter->ExportBox(box);
|
---|
[1144] | 5714 | }
|
---|
[1047] | 5715 | else if (box.Side(plane) == 0)
|
---|
| 5716 | {
|
---|
[1418] | 5717 | // intersection
|
---|
[1047] | 5718 | AxisAlignedBox3 fbox, bbox;
|
---|
[1418] | 5719 | box.Split(clipPlane->mAxis, clipPlane->mPosition, fbox, bbox);
|
---|
[1047] | 5720 | exporter->ExportBox(bbox);
|
---|
| 5721 | }
|
---|
| 5722 | }
|
---|
| 5723 | else
|
---|
| 5724 | {
|
---|
[1027] | 5725 | exporter->ExportBox(box);
|
---|
[1047] | 5726 | }
|
---|
[1027] | 5727 | }
|
---|
| 5728 | }
|
---|
| 5729 |
|
---|
| 5730 |
|
---|
[1021] | 5731 | bool VspOspViewCellsManager::ViewPointValid(const Vector3 &viewPoint) const
|
---|
| 5732 | {
|
---|
| 5733 | // $$JB -> implemented in viewcellsmanager (slower, but allows dynamic
|
---|
| 5734 | // validy update in preprocessor for all managers)
|
---|
| 5735 | return ViewCellsManager::ViewPointValid(viewPoint);
|
---|
[884] | 5736 |
|
---|
[1021] | 5737 | // return mViewSpaceBox.IsInside(viewPoint) &&
|
---|
[1027] | 5738 | // mVspTree->ViewPointValid(viewPoint);
|
---|
[1021] | 5739 | }
|
---|
| 5740 |
|
---|
| 5741 |
|
---|
[1920] | 5742 | float VspOspViewCellsManager::UpdateObjectCosts()
|
---|
| 5743 | {
|
---|
| 5744 | float maxRenderCost = 0;
|
---|
| 5745 |
|
---|
| 5746 | cout << "updating object pvs cost ... ";
|
---|
| 5747 | const long startTime = GetTime();
|
---|
| 5748 |
|
---|
| 5749 | ViewCellContainer::const_iterator vit, vit_end = mViewCells.end();
|
---|
| 5750 |
|
---|
| 5751 | Intersectable::NewMail();
|
---|
| 5752 |
|
---|
| 5753 | const float invViewSpaceVol = 1.0f / GetViewSpaceBox().GetVolume();
|
---|
| 5754 |
|
---|
| 5755 | for (vit = mViewCells.begin(); vit != vit_end; ++ vit)
|
---|
| 5756 | {
|
---|
| 5757 | ViewCell *vc = *vit;
|
---|
| 5758 |
|
---|
| 5759 | ObjectPvsIterator pit = vc->GetPvs().GetIterator();
|
---|
| 5760 |
|
---|
| 5761 | // output PVS of view cell
|
---|
| 5762 | while (pit.HasMoreEntries())
|
---|
| 5763 | {
|
---|
| 5764 | ObjectPvsEntry entry = pit.Next();
|
---|
| 5765 |
|
---|
| 5766 | BvhNode *node = dynamic_cast<BvhNode *>(entry.mObject);
|
---|
| 5767 |
|
---|
| 5768 | // hack!!
|
---|
| 5769 | if (!node->IsLeaf())
|
---|
| 5770 | {
|
---|
| 5771 | cout << "error, can only do leaves" << endl;
|
---|
| 5772 | return 0;
|
---|
| 5773 | }
|
---|
| 5774 |
|
---|
| 5775 | if (!node->Mailed())
|
---|
| 5776 | {
|
---|
| 5777 | node->Mail();
|
---|
| 5778 | node->mRenderCost = 0;
|
---|
| 5779 | }
|
---|
| 5780 |
|
---|
| 5781 | const float rc = (float)((BvhLeaf *)node)->mObjects.size();
|
---|
| 5782 |
|
---|
| 5783 | node->mRenderCost += rc * vc->GetVolume() * invViewSpaceVol;
|
---|
| 5784 |
|
---|
| 5785 | if (node->mRenderCost > maxRenderCost)
|
---|
| 5786 | maxRenderCost = node->mRenderCost;
|
---|
| 5787 | }
|
---|
| 5788 | }
|
---|
| 5789 |
|
---|
| 5790 | cout << "finished in " << TimeDiff(startTime, GetTime()) * 1e-3f << " secs" << endl;
|
---|
| 5791 |
|
---|
| 5792 | return maxRenderCost;
|
---|
| 5793 | }
|
---|
| 5794 |
|
---|
| 5795 |
|
---|
[1021] | 5796 | void VspOspViewCellsManager::Visualize(const ObjectContainer &objects,
|
---|
| 5797 | const VssRayContainer &sampleRays)
|
---|
[859] | 5798 | {
|
---|
[997] | 5799 | if (!ViewCellsConstructed())
|
---|
| 5800 | return;
|
---|
[1027] | 5801 |
|
---|
[1021] | 5802 | VssRayContainer visRays;
|
---|
| 5803 | GetRaySets(sampleRays, mVisualizationSamples, visRays);
|
---|
[997] | 5804 |
|
---|
[1633] | 5805 | ////////////
|
---|
| 5806 | //-- export final view cells
|
---|
[1106] | 5807 |
|
---|
[1633] | 5808 | Exporter *exporter = Exporter::GetExporter("final_view_cells.wrl");
|
---|
| 5809 |
|
---|
[1920] | 5810 | //Vector3 scale(0.9f, 0.9f, 0.9f);
|
---|
| 5811 | Vector3 scale(1.0f, 1.0f, 1.0f);
|
---|
[1789] | 5812 |
|
---|
[1633] | 5813 | if (exporter)
|
---|
| 5814 | {
|
---|
[1764] | 5815 | if (CLAMP_TO_BOX)
|
---|
| 5816 | {
|
---|
| 5817 | exporter->mClampToBox = true;
|
---|
| 5818 | }
|
---|
| 5819 |
|
---|
[1763] | 5820 | EvaluateViewCellsStats();
|
---|
| 5821 |
|
---|
[1633] | 5822 | const long starttime = GetTime();
|
---|
| 5823 | cout << "exporting final view cells (after initial construction + post process) ... ";
|
---|
[1420] | 5824 |
|
---|
[1633] | 5825 | // matt: hack for clamping scene
|
---|
| 5826 | AxisAlignedBox3 bbox = mViewSpaceBox;
|
---|
[1763] | 5827 | bbox.Scale(scale);
|
---|
[1703] | 5828 |
|
---|
[1920] | 5829 | if (0 && mExportRays)
|
---|
[1633] | 5830 | {
|
---|
| 5831 | exporter->ExportRays(visRays, RgbColor(0, 1, 0));
|
---|
| 5832 | }
|
---|
| 5833 |
|
---|
[1920] | 5834 | // hack color code (show pvs size)
|
---|
| 5835 | const int savedColorCode = mColorCode;
|
---|
| 5836 |
|
---|
| 5837 | const float maxRenderCost = UpdateObjectCosts();
|
---|
| 5838 | cout << "maxRenderCost: " << maxRenderCost << endl;
|
---|
| 5839 | mColorCode = 0; // 0 = random, 1 = export pvs
|
---|
| 5840 |
|
---|
[1760] | 5841 | mHierarchyManager->ExportObjectSpaceHierarchy(exporter, objects,
|
---|
[1920] | 5842 | CLAMP_TO_BOX ? &bbox : NULL, maxRenderCost, false);
|
---|
[1763] | 5843 |
|
---|
[1920] | 5844 |
|
---|
| 5845 | //ExportViewCellsForViz(exporter, CLAMP_TO_BOX ? &bbox : NULL, mColorCode, GetClipPlane());
|
---|
| 5846 | ExportViewCellsForViz(exporter, NULL, mColorCode, GetClipPlane());
|
---|
| 5847 |
|
---|
| 5848 | delete exporter;
|
---|
| 5849 |
|
---|
| 5850 | cout << "finished in " << TimeDiff(starttime, GetTime()) * 1e-3f << " secs" << endl;
|
---|
| 5851 | mColorCode = savedColorCode;
|
---|
| 5852 | }
|
---|
| 5853 |
|
---|
| 5854 | exporter = Exporter::GetExporter("final_object_partition.wrl");
|
---|
| 5855 |
|
---|
| 5856 | if (exporter)
|
---|
| 5857 | {
|
---|
| 5858 | if (CLAMP_TO_BOX)
|
---|
| 5859 | {
|
---|
| 5860 | exporter->mClampToBox = true;
|
---|
| 5861 | }
|
---|
| 5862 |
|
---|
| 5863 | EvaluateViewCellsStats();
|
---|
| 5864 |
|
---|
| 5865 | const long starttime = GetTime();
|
---|
| 5866 | cout << "exporting final objects (after initial construction + post process) ... ";
|
---|
| 5867 |
|
---|
| 5868 | // matt: hack for clamping scene
|
---|
| 5869 | AxisAlignedBox3 bbox = mViewSpaceBox;
|
---|
| 5870 | bbox.Scale(scale);
|
---|
| 5871 |
|
---|
[1764] | 5872 | // hack color code (show pvs size)
|
---|
| 5873 | const int savedColorCode = mColorCode;
|
---|
| 5874 |
|
---|
[1920] | 5875 | mColorCode = 1; // 0 = random, 1 = export pvs
|
---|
| 5876 | const float maxRenderCost = -1;
|
---|
| 5877 |
|
---|
| 5878 | mHierarchyManager->ExportObjectSpaceHierarchy(exporter, objects,
|
---|
| 5879 | CLAMP_TO_BOX ? &bbox : NULL, maxRenderCost, false);
|
---|
| 5880 |
|
---|
| 5881 |
|
---|
[1763] | 5882 | //ExportViewCellsForViz(exporter, CLAMP_TO_BOX ? &bbox : NULL, mColorCode, GetClipPlane());
|
---|
| 5883 | ExportViewCellsForViz(exporter, NULL, mColorCode, GetClipPlane());
|
---|
[1633] | 5884 |
|
---|
| 5885 | delete exporter;
|
---|
[1760] | 5886 |
|
---|
[1633] | 5887 | cout << "finished in " << TimeDiff(starttime, GetTime()) * 1e-3f << " secs" << endl;
|
---|
[1021] | 5888 | mColorCode = savedColorCode;
|
---|
| 5889 | }
|
---|
| 5890 |
|
---|
[1920] | 5891 | #if 0
|
---|
[1633] | 5892 | // export final object partition
|
---|
| 5893 | exporter = Exporter::GetExporter("final_object_partition.wrl");
|
---|
| 5894 |
|
---|
| 5895 | if (exporter)
|
---|
[1287] | 5896 | {
|
---|
[1764] | 5897 | if (CLAMP_TO_BOX)
|
---|
| 5898 | {
|
---|
| 5899 | exporter->mClampToBox = true;
|
---|
| 5900 | }
|
---|
| 5901 |
|
---|
[1633] | 5902 | const long starttime = GetTime();
|
---|
[1287] | 5903 |
|
---|
[1633] | 5904 | // matt: hack for making visualization smaller in size
|
---|
| 5905 | AxisAlignedBox3 bbox = mHierarchyManager->GetObjectSpaceBox();
|
---|
[1763] | 5906 | bbox.Scale(scale);
|
---|
[1415] | 5907 |
|
---|
[1633] | 5908 | cout << "exporting object space hierarchy ... ";
|
---|
[1920] | 5909 | mHierarchyManager->ExportObjectSpaceHierarchy(exporter, objects, CLAMP_TO_BOX ? &bbox : NULL, -1);
|
---|
[1633] | 5910 |
|
---|
| 5911 | delete exporter;
|
---|
| 5912 | cout << "finished in " << TimeDiff(starttime, GetTime()) * 1e-3f << " secs" << endl;
|
---|
[1287] | 5913 | }
|
---|
[1920] | 5914 | #endif
|
---|
| 5915 |
|
---|
[1760] | 5916 | // visualization of the view cells
|
---|
[1763] | 5917 | if (0)
|
---|
[1760] | 5918 | {
|
---|
| 5919 | ExportMergedViewCells(objects);
|
---|
| 5920 | }
|
---|
| 5921 |
|
---|
[1841] | 5922 | // export some view cells
|
---|
[1021] | 5923 | int leafOut;
|
---|
| 5924 | Environment::GetSingleton()->GetIntValue("ViewCells.Visualization.maxOutput", leafOut);
|
---|
[1769] | 5925 |
|
---|
| 5926 | const bool sortViewCells = false;
|
---|
| 5927 | const bool exportPvs = true;
|
---|
| 5928 | const bool exportRays = true;
|
---|
[1570] | 5929 | const int raysOut = 100;
|
---|
[580] | 5930 |
|
---|
[1769] | 5931 | ExportSingleViewCells(objects,
|
---|
| 5932 | leafOut,
|
---|
| 5933 | sortViewCells,
|
---|
| 5934 | exportPvs,
|
---|
| 5935 | exportRays,
|
---|
| 5936 | raysOut,
|
---|
| 5937 | "");
|
---|
[1570] | 5938 | }
|
---|
[1021] | 5939 |
|
---|
| 5940 |
|
---|
[1570] | 5941 | void VspOspViewCellsManager::ExportSingleViewCells(const ObjectContainer &objects,
|
---|
| 5942 | const int maxViewCells,
|
---|
| 5943 | const bool sortViewCells,
|
---|
| 5944 | const bool exportPvs,
|
---|
| 5945 | const bool exportRays,
|
---|
| 5946 | const int maxRays,
|
---|
| 5947 | const string prefix,
|
---|
| 5948 | VssRayContainer *visRays)
|
---|
| 5949 | {
|
---|
| 5950 | if (sortViewCells)
|
---|
[697] | 5951 | {
|
---|
[1415] | 5952 | // sort view cells to visualize the view cells with highest render cost
|
---|
[1789] | 5953 | sort(mViewCells.begin(), mViewCells.end(), ViewCell::LargerRenderCost);
|
---|
[1021] | 5954 | }
|
---|
| 5955 |
|
---|
[1570] | 5956 | ViewCell::NewMail();
|
---|
| 5957 | const int limit = min(maxViewCells, (int)mViewCells.size());
|
---|
[1178] | 5958 |
|
---|
[1570] | 5959 | cout << "\nExporting " << limit << " single view cells: " << endl;
|
---|
| 5960 |
|
---|
[1021] | 5961 | for (int i = 0; i < limit; ++ i)
|
---|
| 5962 | {
|
---|
| 5963 | cout << "creating output for view cell " << i << " ... ";
|
---|
[1418] | 5964 |
|
---|
| 5965 | // largest view cell pvs first of random view cell
|
---|
[1570] | 5966 | ViewCell *vc = sortViewCells ?
|
---|
[1418] | 5967 | mViewCells[i] : mViewCells[(int)RandomValue(0, (float)mViewCells.size() - 1)];
|
---|
| 5968 |
|
---|
[1887] | 5969 | if (vc->Mailed()) // view cell already processed
|
---|
[1570] | 5970 | continue;
|
---|
| 5971 |
|
---|
| 5972 | vc->Mail();
|
---|
| 5973 |
|
---|
[1021] | 5974 | ObjectPvs pvs;
|
---|
| 5975 | mViewCellsTree->GetPvs(vc, pvs);
|
---|
[704] | 5976 |
|
---|
[1570] | 5977 | char s[64]; sprintf(s, "%sviewcell%04d.wrl", prefix.c_str(), i);
|
---|
[1021] | 5978 | Exporter *exporter = Exporter::GetExporter(s);
|
---|
| 5979 |
|
---|
[1709] | 5980 | cout << "view cell " << vc->GetId() << ": pvs cost=" << mViewCellsTree->GetPvsCost(vc) << endl;
|
---|
[1021] | 5981 |
|
---|
[1570] | 5982 | if (exportPvs)
|
---|
| 5983 | {
|
---|
| 5984 | Material m;
|
---|
[1418] | 5985 |
|
---|
[1570] | 5986 | Intersectable::NewMail();
|
---|
| 5987 |
|
---|
[1742] | 5988 | ObjectPvsIterator pit = pvs.GetIterator();
|
---|
| 5989 |
|
---|
[1570] | 5990 | // output PVS of view cell
|
---|
[1742] | 5991 | while (pit.HasMoreEntries())
|
---|
[1570] | 5992 | {
|
---|
[1742] | 5993 | ObjectPvsEntry entry = pit.Next();
|
---|
| 5994 |
|
---|
| 5995 | Intersectable *intersect = entry.mObject;
|
---|
| 5996 |
|
---|
[1570] | 5997 | if (!intersect->Mailed())
|
---|
| 5998 | {
|
---|
| 5999 | m = RandomMaterial();
|
---|
| 6000 | exporter->SetForcedMaterial(m);
|
---|
| 6001 |
|
---|
| 6002 | exporter->ExportIntersectable(intersect);
|
---|
| 6003 | intersect->Mail();
|
---|
| 6004 | }
|
---|
| 6005 | }
|
---|
| 6006 | }
|
---|
| 6007 |
|
---|
| 6008 | if (exportRays)
|
---|
[1021] | 6009 | {
|
---|
[1570] | 6010 | ////////////
|
---|
| 6011 | //-- export the sample rays
|
---|
| 6012 |
|
---|
[1021] | 6013 | // output rays stored with the view cells during subdivision
|
---|
[1570] | 6014 | VssRayContainer vcRays;
|
---|
| 6015 | VssRayContainer collectRays;
|
---|
[1021] | 6016 |
|
---|
[1570] | 6017 | // collect intial view cells
|
---|
| 6018 | ViewCellContainer leaves;
|
---|
| 6019 | mViewCellsTree->CollectLeaves(vc, leaves);
|
---|
[1021] | 6020 |
|
---|
[1570] | 6021 | ViewCellContainer::const_iterator vit, vit_end = leaves.end();
|
---|
[1021] | 6022 |
|
---|
[1570] | 6023 | for (vit = leaves.begin(); vit != vit_end; ++ vit)
|
---|
| 6024 | {
|
---|
| 6025 | VspLeaf *vcLeaf = dynamic_cast<VspViewCell *>(*vit)->mLeaves[0];
|
---|
| 6026 | VssRayContainer::const_iterator rit, rit_end = vcLeaf->mVssRays.end();
|
---|
| 6027 |
|
---|
| 6028 | for (rit = vcLeaf->mVssRays.begin(); rit != rit_end; ++ rit)
|
---|
[1021] | 6029 | {
|
---|
[1570] | 6030 | collectRays.push_back(*rit);
|
---|
[1021] | 6031 | }
|
---|
[1570] | 6032 | }
|
---|
[1021] | 6033 |
|
---|
[1570] | 6034 | const int raysOut = min((int)collectRays.size(), maxRays);
|
---|
[1021] | 6035 |
|
---|
[1570] | 6036 | VssRayContainer::const_iterator rit, rit_end = collectRays.end();
|
---|
[1021] | 6037 |
|
---|
[1570] | 6038 | for (rit = collectRays.begin(); rit != rit_end; ++ rit)
|
---|
| 6039 | {
|
---|
| 6040 | const float p = RandomValue(0.0f, (float)collectRays.size());
|
---|
| 6041 |
|
---|
| 6042 | if (p < raysOut)
|
---|
| 6043 | vcRays.push_back(*rit);
|
---|
[1021] | 6044 | }
|
---|
[1570] | 6045 |
|
---|
| 6046 | exporter->ExportRays(vcRays, RgbColor(1, 1, 1));
|
---|
[1021] | 6047 | }
|
---|
[1570] | 6048 |
|
---|
| 6049 |
|
---|
[1415] | 6050 | /////////////////
|
---|
[1021] | 6051 | //-- export view cell geometry
|
---|
[1121] | 6052 |
|
---|
[697] | 6053 | exporter->SetWireframe();
|
---|
| 6054 |
|
---|
[1416] | 6055 | Material m;
|
---|
[1021] | 6056 | m.mDiffuseColor = RgbColor(0, 1, 0);
|
---|
| 6057 | exporter->SetForcedMaterial(m);
|
---|
| 6058 |
|
---|
[1416] | 6059 | ExportViewCellGeometry(exporter, vc, NULL, NULL);
|
---|
[697] | 6060 | exporter->SetFilled();
|
---|
| 6061 |
|
---|
[1021] | 6062 | DEL_PTR(exporter);
|
---|
| 6063 | cout << "finished" << endl;
|
---|
[697] | 6064 | }
|
---|
[1021] | 6065 |
|
---|
[1570] | 6066 | cout << endl;
|
---|
[697] | 6067 | }
|
---|
| 6068 |
|
---|
| 6069 |
|
---|
[1021] | 6070 | int VspOspViewCellsManager::ComputeBoxIntersections(const AxisAlignedBox3 &box,
|
---|
| 6071 | ViewCellContainer &viewCells) const
|
---|
| 6072 | {
|
---|
[1278] | 6073 | return mHierarchyManager->GetVspTree()->ComputeBoxIntersections(box, viewCells);
|
---|
[1021] | 6074 | }
|
---|
[580] | 6075 |
|
---|
[1021] | 6076 |
|
---|
| 6077 | int VspOspViewCellsManager::CastLineSegment(const Vector3 &origin,
|
---|
| 6078 | const Vector3 &termination,
|
---|
| 6079 | ViewCellContainer &viewcells)
|
---|
| 6080 | {
|
---|
[1278] | 6081 | return mHierarchyManager->GetVspTree()->CastLineSegment(origin, termination, viewcells);
|
---|
[1021] | 6082 | }
|
---|
| 6083 |
|
---|
| 6084 |
|
---|
| 6085 | bool VspOspViewCellsManager::ExportViewCells(const string filename,
|
---|
| 6086 | const bool exportPvs,
|
---|
| 6087 | const ObjectContainer &objects)
|
---|
| 6088 | {
|
---|
| 6089 | if (!ViewCellsConstructed() || !ViewCellsTreeConstructed())
|
---|
| 6090 | return false;
|
---|
| 6091 |
|
---|
[1415] | 6092 | const long starttime = GetTime();
|
---|
[1021] | 6093 | cout << "exporting view cells to xml ... ";
|
---|
| 6094 |
|
---|
[1201] | 6095 | OUT_STREAM stream(filename.c_str());
|
---|
[1021] | 6096 |
|
---|
| 6097 | // for output we need unique ids for each view cell
|
---|
| 6098 | CreateUniqueViewCellIds();
|
---|
| 6099 |
|
---|
| 6100 | stream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"<<endl;
|
---|
| 6101 | stream << "<VisibilitySolution>" << endl;
|
---|
| 6102 |
|
---|
[1843] | 6103 | // §§ tmp matt: for storage cost
|
---|
| 6104 | if (0 && exportPvs)
|
---|
[1580] | 6105 | {
|
---|
| 6106 | ///////////////
|
---|
| 6107 | //-- export bounding boxes
|
---|
| 6108 | //-- The bounding boxes are used to identify
|
---|
| 6109 | //-- the objects in the rendering engine
|
---|
[1614] | 6110 | mHierarchyManager->ExportBoundingBoxes(stream, objects);
|
---|
[580] | 6111 | }
|
---|
[1021] | 6112 |
|
---|
[1415] | 6113 | //////////////////////////
|
---|
[1021] | 6114 | //-- export the view cells and the pvs
|
---|
| 6115 |
|
---|
| 6116 | const int numViewCells = mCurrentViewCellsStats.viewCells;
|
---|
| 6117 |
|
---|
| 6118 | stream << "<ViewCells number=\"" << numViewCells << "\" >" << endl;
|
---|
| 6119 | mViewCellsTree->Export(stream, exportPvs);
|
---|
| 6120 | stream << "</ViewCells>" << endl;
|
---|
| 6121 |
|
---|
[1415] | 6122 | //////////////////////
|
---|
[1201] | 6123 | //-- export the view space hierarchy
|
---|
[1021] | 6124 |
|
---|
[1262] | 6125 | stream << "<ViewSpaceHierarchy type=\"vsp\""
|
---|
| 6126 | << " min=\"" << mViewSpaceBox.Min().x << " " << mViewSpaceBox.Min().y << " " << mViewSpaceBox.Min().z << "\""
|
---|
[1286] | 6127 | << " max=\"" << mViewSpaceBox.Max().x << " " << mViewSpaceBox.Max().y << " " << mViewSpaceBox.Max().z << "\">" << endl;
|
---|
[1262] | 6128 |
|
---|
[1278] | 6129 | mHierarchyManager->GetVspTree()->Export(stream);
|
---|
[1286] | 6130 | stream << "</ViewSpaceHierarchy>" << endl;
|
---|
[1021] | 6131 |
|
---|
[1415] | 6132 | //////////////////////
|
---|
[1201] | 6133 | //-- export the object space partition
|
---|
| 6134 |
|
---|
[1278] | 6135 | mHierarchyManager->ExportObjectSpaceHierarchy(stream);
|
---|
| 6136 |
|
---|
[1201] | 6137 | stream << "</VisibilitySolution>" << endl;
|
---|
[1021] | 6138 | stream.close();
|
---|
[1201] | 6139 |
|
---|
[1415] | 6140 | cout << "finished in " << TimeDiff(starttime, GetTime()) * 1e-3 << " secs" << endl;
|
---|
[1021] | 6141 | return true;
|
---|
| 6142 | }
|
---|
| 6143 |
|
---|
| 6144 |
|
---|
| 6145 |
|
---|
[1027] | 6146 | ViewCell *VspOspViewCellsManager::GetViewCell(const Vector3 &point,
|
---|
| 6147 | const bool active) const
|
---|
[1021] | 6148 | {
|
---|
| 6149 | if (!ViewCellsConstructed())
|
---|
| 6150 | return NULL;
|
---|
[1588] | 6151 |
|
---|
[1021] | 6152 | if (!mViewSpaceBox.IsInside(point))
|
---|
[1418] | 6153 | return NULL;
|
---|
[1588] | 6154 |
|
---|
[1278] | 6155 | return mHierarchyManager->GetVspTree()->GetViewCell(point, active);
|
---|
[1021] | 6156 | }
|
---|
| 6157 |
|
---|
| 6158 |
|
---|
| 6159 | void VspOspViewCellsManager::CreateMesh(ViewCell *vc)
|
---|
| 6160 | {
|
---|
| 6161 | // matt: TODO
|
---|
| 6162 | Mesh *mesh = MeshManager::GetSingleton()->CreateResource();
|
---|
[1027] | 6163 |
|
---|
| 6164 | ViewCellContainer leaves;
|
---|
| 6165 | mViewCellsTree->CollectLeaves(vc, leaves);
|
---|
| 6166 |
|
---|
| 6167 | ViewCellContainer::const_iterator it, it_end = leaves.end();
|
---|
| 6168 |
|
---|
| 6169 | for (it = leaves.begin(); it != it_end; ++ it)
|
---|
| 6170 | {
|
---|
[1551] | 6171 | VspLeaf *leaf = dynamic_cast<VspViewCell *>(*it)->mLeaves[0];
|
---|
[1278] | 6172 | const AxisAlignedBox3 box = mHierarchyManager->GetVspTree()->GetBoundingBox(leaf);
|
---|
[1027] | 6173 | IncludeBoxInMesh(box, *mesh);
|
---|
| 6174 | }
|
---|
| 6175 |
|
---|
[1021] | 6176 | vc->SetMesh(mesh);
|
---|
| 6177 | }
|
---|
| 6178 |
|
---|
| 6179 |
|
---|
| 6180 | int VspOspViewCellsManager::CastBeam(Beam &beam)
|
---|
| 6181 | {
|
---|
| 6182 | // matt: TODO
|
---|
| 6183 | return 0;
|
---|
| 6184 | }
|
---|
| 6185 |
|
---|
| 6186 |
|
---|
[1667] | 6187 | void VspOspViewCellsManager::Finalize(ViewCell *viewCell, const bool createMesh)
|
---|
[1021] | 6188 | {
|
---|
| 6189 | float area = 0;
|
---|
| 6190 | float volume = 0;
|
---|
| 6191 |
|
---|
| 6192 | ViewCellContainer leaves;
|
---|
| 6193 | mViewCellsTree->CollectLeaves(viewCell, leaves);
|
---|
| 6194 |
|
---|
| 6195 | ViewCellContainer::const_iterator it, it_end = leaves.end();
|
---|
| 6196 |
|
---|
| 6197 | for (it = leaves.begin(); it != it_end; ++ it)
|
---|
[580] | 6198 | {
|
---|
[1551] | 6199 | VspLeaf *leaf = dynamic_cast<VspViewCell *>(*it)->mLeaves[0];
|
---|
[1027] | 6200 |
|
---|
[1278] | 6201 | const AxisAlignedBox3 box = mHierarchyManager->GetVspTree()->GetBoundingBox(leaf);
|
---|
[1021] | 6202 |
|
---|
[1027] | 6203 | const float lVol = box.GetVolume();
|
---|
| 6204 | const float lArea = box.SurfaceArea();
|
---|
[1021] | 6205 |
|
---|
| 6206 | area += lArea;
|
---|
| 6207 | volume += lVol;
|
---|
| 6208 |
|
---|
| 6209 | CreateMesh(*it);
|
---|
[580] | 6210 | }
|
---|
| 6211 |
|
---|
[1021] | 6212 | viewCell->SetVolume(volume);
|
---|
| 6213 | viewCell->SetArea(area);
|
---|
[580] | 6214 | }
|
---|
| 6215 |
|
---|
[1876] | 6216 |
|
---|
[1021] | 6217 | void VspOspViewCellsManager::PrepareLoadedViewCells()
|
---|
| 6218 | {
|
---|
| 6219 | // TODO
|
---|
| 6220 | }
|
---|
[580] | 6221 |
|
---|
[1201] | 6222 |
|
---|
[1889] | 6223 | static void PrintCompressionStats(HierarchyManager *hm, const int pvsEntries)
|
---|
| 6224 | {
|
---|
| 6225 | float mem = (float)pvsEntries * ObjectPvs::GetEntrySize();
|
---|
| 6226 |
|
---|
| 6227 | float fullmem = mem +
|
---|
| 6228 | (hm->GetVspTree()->GetStatistics().Leaves() * 16 +
|
---|
| 6229 | hm->mBvHierarchy->GetStatistics().Leaves() * 16) / float(1024 * 1024);
|
---|
| 6230 |
|
---|
| 6231 | cout << "entries: " << pvsEntries << ", mem=" << mem << ", fullmem=" << fullmem <<endl;
|
---|
| 6232 | Debug << "entries: " << pvsEntries << ", mem=" << mem << ", fullmem=" << fullmem <<endl;
|
---|
| 6233 | }
|
---|
| 6234 |
|
---|
| 6235 |
|
---|
[1845] | 6236 | void VspOspViewCellsManager::CompressViewCells()
|
---|
| 6237 | {
|
---|
[1889] | 6238 | if (!(ViewCellsTreeConstructed() && mCompressViewCells))
|
---|
[1887] | 6239 | return;
|
---|
| 6240 |
|
---|
[1845] | 6241 | ////////////
|
---|
| 6242 | //-- compression
|
---|
| 6243 |
|
---|
[1889] | 6244 | int pvsEntries = mViewCellsTree->CountStoredPvsEntries(mViewCellsTree->GetRoot());
|
---|
| 6245 |
|
---|
| 6246 | cout << "before compression: " << endl;
|
---|
| 6247 | Debug << "before compression: " << endl;
|
---|
| 6248 |
|
---|
| 6249 | PrintCompressionStats(mHierarchyManager, pvsEntries);
|
---|
| 6250 |
|
---|
| 6251 | if (mCompressObjects)
|
---|
[1845] | 6252 | {
|
---|
[1889] | 6253 | cout << "compressing in the objects: " << endl;
|
---|
| 6254 | Debug << "compressing in the objects: " << endl;
|
---|
[1845] | 6255 |
|
---|
| 6256 | pvsEntries = mHierarchyManager->CompressObjectSpace();
|
---|
[1889] | 6257 | }
|
---|
| 6258 | else
|
---|
| 6259 | {
|
---|
| 6260 | cout << "compressing in the view space: " << endl;
|
---|
| 6261 | Debug << "compressing in the view space: " << endl;
|
---|
[1846] | 6262 |
|
---|
[1889] | 6263 | mViewCellsTree->SetViewCellsStorage(ViewCellsTree::COMPRESSED);
|
---|
| 6264 | pvsEntries = mViewCellsTree->CountStoredPvsEntries(mViewCellsTree->GetRoot());
|
---|
[1845] | 6265 | }
|
---|
[1889] | 6266 |
|
---|
| 6267 | PrintCompressionStats(mHierarchyManager, pvsEntries);
|
---|
[1845] | 6268 | }
|
---|
| 6269 |
|
---|
| 6270 |
|
---|
[1201] | 6271 | ViewCellsManager *VspOspViewCellsManager::LoadViewCells(const string &filename,
|
---|
| 6272 | ObjectContainer *objects,
|
---|
| 6273 | const bool finalizeViewCells,
|
---|
| 6274 | BoundingBoxConverter *bconverter)
|
---|
| 6275 |
|
---|
| 6276 | {
|
---|
| 6277 | ViewCellsManager *vm =
|
---|
| 6278 | ViewCellsManager::LoadViewCells(filename, objects, finalizeViewCells, bconverter);
|
---|
[1278] | 6279 | #if 0
|
---|
| 6280 | // insert scene objects in tree
|
---|
[1201] | 6281 | mOspTree->InsertObjects(mOspTree->GetRoot(), *objects);
|
---|
[1278] | 6282 | #endif
|
---|
[1201] | 6283 | return vm;
|
---|
| 6284 | }
|
---|
| 6285 |
|
---|
[1889] | 6286 |
|
---|
[1737] | 6287 | void
|
---|
| 6288 | VspOspViewCellsManager::CollectObjects(const AxisAlignedBox3 &box, ObjectContainer &objects)
|
---|
| 6289 | {
|
---|
| 6290 | mHierarchyManager->CollectObjects(box, objects);
|
---|
| 6291 | }
|
---|
[1692] | 6292 |
|
---|
[1737] | 6293 |
|
---|
[1709] | 6294 | #if 1
|
---|
[1180] | 6295 |
|
---|
[1686] | 6296 | void VspOspViewCellsManager::EvalViewCellPartition()
|
---|
| 6297 | {
|
---|
| 6298 | int samplesPerPass;
|
---|
| 6299 | int numSamples;
|
---|
| 6300 | int castSamples = 0;
|
---|
[1718] | 6301 | int oldSamples = 0;
|
---|
| 6302 | int samplesForStats;
|
---|
| 6303 | char statsPrefix[100];
|
---|
| 6304 | char suffix[100];
|
---|
[1713] | 6305 | int splitsStepSize;
|
---|
[1686] | 6306 |
|
---|
| 6307 | Environment::GetSingleton()->GetIntValue("ViewCells.Evaluation.samplesPerPass", samplesPerPass);
|
---|
[1718] | 6308 | Environment::GetSingleton()->GetIntValue("ViewCells.Evaluation.samplesForStats", samplesForStats);
|
---|
[1686] | 6309 | Environment::GetSingleton()->GetIntValue("ViewCells.Evaluation.samples", numSamples);
|
---|
| 6310 | Environment::GetSingleton()->GetStringValue("ViewCells.Evaluation.statsPrefix", statsPrefix);
|
---|
[1718] | 6311 | Environment::GetSingleton()->GetIntValue("ViewCells.Evaluation.stepSize", splitsStepSize);
|
---|
| 6312 |
|
---|
[1919] | 6313 | bool useHisto;
|
---|
| 6314 | int histoMem;
|
---|
| 6315 |
|
---|
| 6316 | Environment::GetSingleton()->GetBoolValue("ViewCells.Evaluation.histogram", useHisto);
|
---|
| 6317 | Environment::GetSingleton()->GetIntValue("ViewCells.Evaluation.histoMem", histoMem);
|
---|
| 6318 |
|
---|
[1718] | 6319 | Debug << "step size: " << splitsStepSize << endl;
|
---|
[1686] | 6320 | Debug << "view cell evaluation samples per pass: " << samplesPerPass << endl;
|
---|
| 6321 | Debug << "view cell evaluation samples: " << numSamples << endl;
|
---|
| 6322 | Debug << "view cell stats prefix: " << statsPrefix << endl;
|
---|
| 6323 |
|
---|
[1773] | 6324 | cout << "reseting pvs ... ";
|
---|
[1686] | 6325 |
|
---|
| 6326 | // reset pvs and start over from zero
|
---|
[1718] | 6327 | mViewCellsTree->ResetPvs();
|
---|
| 6328 |
|
---|
[1686] | 6329 | cout << "finished" << endl;
|
---|
| 6330 | cout << "Evaluating view cell partition ... " << endl;
|
---|
| 6331 |
|
---|
[1811] | 6332 | vector<int> evalStrats;
|
---|
| 6333 |
|
---|
| 6334 | // mix of sampling strategies
|
---|
[1919] | 6335 | if (0)
|
---|
| 6336 | {
|
---|
| 6337 | evalStrats.push_back(SamplingStrategy::OBJECT_DIRECTION_BASED_DISTRIBUTION);
|
---|
| 6338 | }
|
---|
| 6339 | else
|
---|
| 6340 | {
|
---|
| 6341 | /*evalStrats.push_back(SamplingStrategy::OBJECT_BASED_DISTRIBUTION);
|
---|
| 6342 | evalStrats.push_back(SamplingStrategy::REVERSE_VIEWSPACE_BORDER_BASED_DISTRIBUTION);
|
---|
| 6343 | evalStrats.push_back(SamplingStrategy::REVERSE_OBJECT_BASED_DISTRIBUTION);
|
---|
| 6344 | */
|
---|
| 6345 | evalStrats.push_back(SamplingStrategy::SPATIAL_BOX_BASED_DISTRIBUTION);
|
---|
| 6346 | }
|
---|
[1910] | 6347 |
|
---|
[1826] | 6348 | Debug << "casting eval strategies: ";
|
---|
| 6349 | for (int i = 0; i < (int)evalStrats.size(); ++ i)
|
---|
| 6350 | Debug << evalStrats[i] << " ";
|
---|
| 6351 | Debug << endl;
|
---|
[1811] | 6352 |
|
---|
[1843] | 6353 | cout << "casting eval strategies: ";
|
---|
| 6354 | for (int i = 0; i < (int)evalStrats.size(); ++ i)
|
---|
| 6355 | cout << evalStrats[i] << " ";
|
---|
| 6356 | cout << endl;
|
---|
| 6357 |
|
---|
[1919] | 6358 | int pass = 0;
|
---|
| 6359 |
|
---|
[1686] | 6360 | while (castSamples < numSamples)
|
---|
| 6361 | {
|
---|
| 6362 | ///////////////
|
---|
| 6363 | //-- we have to use uniform sampling strategy for construction rays
|
---|
| 6364 |
|
---|
[1718] | 6365 | VssRayContainer evaluationSamples;
|
---|
[1686] | 6366 | const int samplingType = mEvaluationSamplingType;
|
---|
| 6367 |
|
---|
| 6368 | long startTime = GetTime();
|
---|
| 6369 |
|
---|
| 6370 | cout << "casting " << samplesPerPass << " samples ... ";
|
---|
| 6371 | Debug << "casting " << samplesPerPass << " samples ... ";
|
---|
[1778] | 6372 |
|
---|
[1903] | 6373 | if (1)
|
---|
| 6374 | {
|
---|
| 6375 | CastPassSamples(samplesPerPass, evalStrats, evaluationSamples);
|
---|
| 6376 | }
|
---|
| 6377 | else
|
---|
| 6378 | {
|
---|
| 6379 | // use mixed distributions
|
---|
| 6380 | CastPassSamples2(samplesPerPass, evaluationSamples);
|
---|
| 6381 | }
|
---|
| 6382 |
|
---|
[1686] | 6383 | castSamples += samplesPerPass;
|
---|
| 6384 |
|
---|
| 6385 | Real timeDiff = TimeDiff(startTime, GetTime());
|
---|
[1718] | 6386 |
|
---|
| 6387 | cout << "finished in " << timeDiff * 1e-3f << " secs" << endl;
|
---|
[1686] | 6388 | cout << "computing sample contributions of " << (int)evaluationSamples.size() << " samples ... ";
|
---|
[1718] | 6389 |
|
---|
| 6390 | Debug << "finished in " << timeDiff * 1e-3f << " secs" << endl;
|
---|
[1686] | 6391 | Debug << "computing sample contributions of " << (int)evaluationSamples.size() << " samples ... ";
|
---|
| 6392 |
|
---|
| 6393 | startTime = GetTime();
|
---|
| 6394 |
|
---|
| 6395 | ComputeSampleContributions(evaluationSamples, true, false);
|
---|
| 6396 |
|
---|
| 6397 | timeDiff = TimeDiff(startTime, GetTime());
|
---|
| 6398 | cout << "finished in " << timeDiff * 1e-3 << " secs" << endl;
|
---|
| 6399 | Debug << "finished in " << timeDiff * 1e-3 << " secs" << endl;
|
---|
| 6400 |
|
---|
[1758] | 6401 | if ((castSamples >= samplesForStats + oldSamples) ||
|
---|
| 6402 | (castSamples >= numSamples))
|
---|
[1718] | 6403 | {
|
---|
| 6404 | oldSamples += samplesForStats;
|
---|
[1686] | 6405 |
|
---|
[1718] | 6406 | ///////////
|
---|
| 6407 | //-- output stats
|
---|
[1686] | 6408 |
|
---|
[1718] | 6409 | sprintf(suffix, "-%09d-eval.log", castSamples);
|
---|
| 6410 | const string filename = string(statsPrefix) + string(suffix);
|
---|
[1710] | 6411 |
|
---|
[1718] | 6412 | startTime = GetTime();
|
---|
[1732] | 6413 |
|
---|
[1718] | 6414 | cout << "compute new statistics ... " << endl;
|
---|
[1710] | 6415 |
|
---|
[1718] | 6416 | ofstream ofstr(filename.c_str());
|
---|
[1919] | 6417 | mHierarchyManager->EvaluateSubdivision2(ofstr, splitsStepSize, false, useHisto, histoMem, pass);
|
---|
[1718] | 6418 |
|
---|
| 6419 | timeDiff = TimeDiff(startTime, GetTime());
|
---|
| 6420 | cout << "finished in " << timeDiff * 1e-3 << " secs" << endl;
|
---|
[1732] | 6421 | cout << "*************************************" << endl;
|
---|
| 6422 |
|
---|
[1718] | 6423 | Debug << "statistics computed in " << timeDiff * 1e-3 << " secs" << endl;
|
---|
| 6424 |
|
---|
[1750] | 6425 | #if 0
|
---|
[1787] | 6426 | //////////////
|
---|
[1745] | 6427 | // filtered stats
|
---|
[1790] | 6428 |
|
---|
[1745] | 6429 | sprintf(suffix, "-%09d-eval-filter.log", castSamples);
|
---|
| 6430 | const string filename2 = string(statsPrefix) + string(suffix);
|
---|
| 6431 |
|
---|
| 6432 | startTime = GetTime();
|
---|
| 6433 |
|
---|
| 6434 | cout << "compute new statistics for filtered pvs ... " << endl;
|
---|
| 6435 |
|
---|
| 6436 | ofstream ofstr2(filename2.c_str());
|
---|
| 6437 | mHierarchyManager->EvaluateSubdivision2(ofstr2, splitsStepSize, true);
|
---|
| 6438 |
|
---|
| 6439 | timeDiff = TimeDiff(startTime, GetTime());
|
---|
| 6440 | cout << "finished in " << timeDiff * 1e-3 << " secs" << endl;
|
---|
| 6441 | cout << "*************************************" << endl;
|
---|
[1787] | 6442 | Debug << "filtered statistics computed in " << timeDiff * 1e-3 << " secs" << endl;
|
---|
[1745] | 6443 | #endif
|
---|
| 6444 |
|
---|
[1718] | 6445 | // only for debugging purpose
|
---|
[1732] | 6446 | if (0)
|
---|
[1718] | 6447 | {
|
---|
| 6448 | ViewCellContainer viewCells;
|
---|
| 6449 | mViewCellsTree->CollectLeaves(mViewCellsTree->GetRoot(), viewCells);
|
---|
| 6450 |
|
---|
| 6451 | ViewCellContainer::const_iterator vit, vit_end = viewCells.end();
|
---|
| 6452 | int pvsSize = 0;
|
---|
| 6453 |
|
---|
| 6454 | for (vit = viewCells.begin(); vit != vit_end; ++ vit)
|
---|
| 6455 | {
|
---|
| 6456 | pvsSize += (*vit)->GetPvs().GetSize();
|
---|
| 6457 | }
|
---|
| 6458 |
|
---|
[1787] | 6459 | cout << "debug entries: " << pvsSize << ", memcost: "
|
---|
| 6460 | << (float)pvsSize * ObjectPvs::GetEntrySize() << endl;
|
---|
[1718] | 6461 | }
|
---|
[1919] | 6462 | ++ pass;
|
---|
[1718] | 6463 | }
|
---|
| 6464 |
|
---|
[1709] | 6465 | disposeRays(evaluationSamples, NULL);
|
---|
[1686] | 6466 | }
|
---|
[1917] | 6467 |
|
---|
| 6468 | ////////////
|
---|
| 6469 | //-- histogram
|
---|
[1919] | 6470 | #if 1
|
---|
[1917] | 6471 | const int numLeaves = mViewCellsTree->GetNumInitialViewCells(mViewCellsTree->GetRoot());
|
---|
| 6472 | int histoStepSize;
|
---|
| 6473 |
|
---|
| 6474 | Environment::GetSingleton()->GetBoolValue("ViewCells.Evaluation.histogram", useHisto);
|
---|
| 6475 | Environment::GetSingleton()->GetIntValue("ViewCells.Evaluation.histoStepSize", histoStepSize);
|
---|
| 6476 |
|
---|
| 6477 | if (useHisto)
|
---|
| 6478 | {
|
---|
| 6479 | // evaluate view cells in a histogram
|
---|
[1919] | 6480 | char str[64];
|
---|
[1917] | 6481 |
|
---|
| 6482 | // hack: just show final view cells
|
---|
| 6483 | int pass = (int)mViewCells.size();
|
---|
| 6484 | //for (int pass = histoStepSize; pass <= numLeaves; pass += histoStepSize)
|
---|
| 6485 | if (1)
|
---|
| 6486 | {
|
---|
| 6487 | string filename;
|
---|
| 6488 |
|
---|
| 6489 | cout << "computing histogram for " << pass << " view cells" << endl;
|
---|
| 6490 |
|
---|
| 6491 | //////////////////////////////////////////
|
---|
| 6492 | //-- evaluate histogram for pvs size
|
---|
| 6493 |
|
---|
| 6494 | cout << "computing pvs histogram for " << pass << " view cells" << endl;
|
---|
| 6495 |
|
---|
[1919] | 6496 | sprintf(str, "-%09d-histo-pvs2.log", pass);
|
---|
| 6497 | filename = string(statsPrefix) + string(str);
|
---|
[1917] | 6498 |
|
---|
| 6499 | EvalViewCellHistogramForPvsSize(filename, pass);
|
---|
| 6500 | }
|
---|
| 6501 | }
|
---|
[1919] | 6502 | #endif
|
---|
[1686] | 6503 | }
|
---|
[1917] | 6504 |
|
---|
[1551] | 6505 | #endif
|
---|
[1786] | 6506 |
|
---|
| 6507 |
|
---|
| 6508 |
|
---|
| 6509 | }
|
---|