#include #include "common.h" #include "SceneGraph.h" #include "X3dExporter.h" #include "Mesh.h" #include "KdTree.h" #include "ViewCellBsp.h" #include "ViewCell.h" #include "Polygon3.h" #include "VssRay.h" #include "VspKdTree.h" #include "VssTree.h" #include "VspBspTree.h" #include "RssTree.h" #include "Beam.h" X3dExporter::X3dExporter(const string filename):Exporter(filename) { stream.open(mFilename.c_str()); stream<<""<"<"<"<"< &rays, // const float length, // const RgbColor &color) // { // vector::const_iterator ri = rays.begin(); // stream<<""<"<"<"<"<"<"<"<"<"<"<"<"<"<GetLoc(); Vector3 b; if (length < 0) b = (*ri)->GetLoc() - length*(*ri)->GetDir(); else if ((*ri)->intersections.size()==0) b = (*ri)->GetLoc() + length*(*ri)->GetDir(); else b = (*ri)->Extrap((*ri)->intersections[0].mT); stream<"<"<"<"<"<"<"<"<"<GetOrigin(); //const Vector3 b = (*ri)->mTerminationObject ? (*ri)->GetTermination() : a + 1000 * Normalize((*ri)->GetDir()); const Vector3 b = (*ri)->GetTermination(); // matt: change again!! stream<"<"<"<"<"<mChildren.begin(); for (; ni != node->mChildren.end(); ni++) ExportSceneNode(*ni); ObjectContainer::const_iterator mi = node->mGeometry.begin(); for (; mi != node->mGeometry.end(); mi++) { // export the transform... ExportIntersectable(*mi); } stream<<""<Type()) { case Intersectable::MESH_INSTANCE: case Intersectable::TRANSFORMED_MESH_INSTANCE: ExportMeshInstance((MeshInstance *)object); break; case Intersectable::VIEW_CELL: ExportViewCell((ViewCell *)object); break; default: cerr<<"Sorry the export for object not yet defined"<GetMesh()); } void X3dExporter::ExportViewCells(const ViewCellContainer &viewCells) { ViewCellContainer::const_iterator it, it_end = viewCells.end(); for (it = viewCells.begin(); it != it_end; ++ it) ExportViewCell(*it); } void X3dExporter::ExportBspLeaves(const BspTree &tree, const int maxPvs) { stack > tStack; ViewCell::NewMail(); BspNodeGeometry *geom = new BspNodeGeometry(); tree.ConstructGeometry(tree.GetRoot(), *geom); tStack.push(pair(tree.GetRoot(), geom)); if (maxPvs > 0) mUseForcedMaterial = true; while (!tStack.empty()) { BspNode *node = tStack.top().first; BspNodeGeometry *cell = tStack.top().second; tStack.pop(); if (!node->IsLeaf()) { BspInterior *interior = dynamic_cast(node); BspNodeGeometry *front = new BspNodeGeometry(); BspNodeGeometry *back = new BspNodeGeometry(); cell->SplitGeometry(*front, *back, interior->GetPlane(), tree.GetBoundingBox(), tree.GetEpsilon()); tStack.push(pair(interior->GetFront(), front)); tStack.push(pair(interior->GetBack(), back)); } else { if (maxPvs > 0) { BspLeaf *leaf = dynamic_cast(node); mForcedMaterial.mDiffuseColor.b = 1.0f; float importance = (float)leaf->GetViewCell()->GetPvs().GetSize() / (float)maxPvs; mForcedMaterial.mDiffuseColor.r = importance; mForcedMaterial.mDiffuseColor.g = 1.0f - mForcedMaterial.mDiffuseColor.r; } ExportPolygons(cell->mPolys); } DEL_PTR(cell); } } void X3dExporter::ExportViewCell(ViewCell *viewCell) { if (viewCell->GetMesh()) ExportMesh(viewCell->GetMesh()); } void X3dExporter::ExportMesh(Mesh *mesh) { stream<<""<"< random material float r, g, b; if (mUseForcedMaterial) { r = mForcedMaterial.mDiffuseColor.r; g = mForcedMaterial.mDiffuseColor.g; b = mForcedMaterial.mDiffuseColor.b; } else if (mesh->mMaterial) { r = mesh->mMaterial->mDiffuseColor.r; g = mesh->mMaterial->mDiffuseColor.g; b = mesh->mMaterial->mDiffuseColor.b; } else { r = RandomValue(0.5, 1.0); g = RandomValue(0.5, 1.0); b = RandomValue(0.5, 1.0); } stream<<""<"<mFaces.begin(); int index = 0; for (; fi != mesh->mFaces.end(); fi++) { Face *face = *fi; VertexIndexContainer::const_iterator vi = face->mVertexIndices.begin(); for (; vi != face->mVertexIndices.end(); vi++) stream<<*vi<<" "; if (mWireframe) // final line to finish polygon stream << (*face->mVertexIndices.begin()) << " "; stream<<"-1"<"<mVertices.begin(); for (; vi != mesh->mVertices.end(); vi++) { stream<<(*vi).x<<" "<<(*vi).y<<" "<<(*vi).z; stream<<","<"<"<"<"<"<" << endl; stream << "" << endl; // $$ tmp -> random material float r, g, b; if (mUseForcedMaterial) { r = mForcedMaterial.mDiffuseColor.r; g = mForcedMaterial.mDiffuseColor.g; b = mForcedMaterial.mDiffuseColor.b; } else if (poly->mMaterial) { r = poly->mMaterial->mDiffuseColor.r; g = poly->mMaterial->mDiffuseColor.g; b = poly->mMaterial->mDiffuseColor.b; } else { r = RandomValue(0.5, 1.0); g = RandomValue(0.5, 1.0); b = RandomValue(0.5, 1.0); } stream << "" << endl; stream << "" << endl; //-- create and write indices if (mWireframe) stream<<"mVertices.size(); ++ index) stream << index << " "; if (mWireframe) // final line to finish polygon stream << "0 "; stream << "-1" << endl; stream << "\" >" << endl; stream << "mVertices.begin(); vi != poly->mVertices.end(); ++vi) { stream << (*vi).x << " " << (*vi).y << " " << (*vi).z; stream << "," << endl; } stream << "\" >" << endl; stream << "" << endl; if (mWireframe) stream << "" << endl; else stream << "" << endl; stream << "" << endl; } void X3dExporter::ExportPolygons(const PolygonContainer &polys) { stream << "" << endl; stream << "" << endl; // $$ tmp -> random material float r, g, b; if (mUseForcedMaterial) { r = mForcedMaterial.mDiffuseColor.r; g = mForcedMaterial.mDiffuseColor.g; b = mForcedMaterial.mDiffuseColor.b; } else { r = RandomValue(0.5, 1.0); g = RandomValue(0.5, 1.0); b = RandomValue(0.5, 1.0); } stream << "" << endl; stream << "" << endl; //-- create and write indices if (mWireframe) stream<<"mVertices.begin(); vi != poly->mVertices.end(); ++vi) { stream << index ++ << " "; } stream << startIdx << " ";// finish line stream << "-1" << endl; } stream << "\" >" << endl; stream << "mVertices.begin(); vi != poly->mVertices.end(); ++vi) { stream << (*vi).x << " " << (*vi).y << " " << (*vi).z; stream << "," << endl; } } stream << "\" >" << endl; stream << "" << endl; if (mWireframe) stream << "" << endl; else stream << "" << endl; stream << "" << endl; } bool X3dExporter::ExportBox(const AxisAlignedBox3 &box) { Mesh *mesh = new Mesh; // add 8 vertices of the box int index = (int)mesh->mVertices.size(); for (int i=0; i < 8; i++) { Vector3 v; box.GetVertex(i, v); mesh->mVertices.push_back(v); } mesh->AddFace(new Face(index + 0, index + 1, index + 3, index + 2) ); mesh->AddFace(new Face(index + 0, index + 2, index + 6, index + 4) ); mesh->AddFace(new Face(index + 4, index + 6, index + 7, index + 5) ); mesh->AddFace(new Face(index + 3, index + 1, index + 5, index + 7) ); mesh->AddFace(new Face(index + 0, index + 4, index + 5, index + 1) ); mesh->AddFace(new Face(index + 2, index + 3, index + 7, index + 6) ); ExportMesh(mesh); delete mesh; return true; } bool X3dExporter::ExportBspTree(const BspTree &tree) { if (mExportRayDensity) { return ExportBspTreeRayDensity(tree); } bool savedWireframe = mWireframe; SetWireframe(); ExportBox(tree.GetBoundingBox()); if (!savedWireframe) SetFilled(); // export view cells ExportBspLeaves(tree); return true; } bool X3dExporter::ExportVspKdTree(const VspKdTree &tree, const int maxPvs) { stack tStack; tStack.push(tree.GetRoot()); //Mesh *mesh = new Mesh; if (maxPvs > 0) mUseForcedMaterial = true; while (!tStack.empty()) { VspKdNode *node = tStack.top(); tStack.pop(); if (node->IsLeaf()) { AxisAlignedBox3 box = tree.GetBBox(node); Mesh *mesh = new Mesh; // add 6 vertices of the box int index = (int)mesh->mVertices.size(); for (int i=0; i < 8; ++ i) { Vector3 v; box.GetVertex(i, v); mesh->mVertices.push_back(v); } mesh->AddFace(new Face(index + 0, index + 1, index + 3, index + 2) ); mesh->AddFace(new Face(index + 0, index + 2, index + 6, index + 4) ); mesh->AddFace(new Face(index + 4, index + 6, index + 7, index + 5) ); mesh->AddFace(new Face(index + 3, index + 1, index + 5, index + 7) ); mesh->AddFace(new Face(index + 0, index + 4, index + 5, index + 1) ); mesh->AddFace(new Face(index + 2, index + 3, index + 7, index + 6) ); if (maxPvs > 0) { VspKdLeaf *leaf = dynamic_cast(node); mForcedMaterial.mDiffuseColor.b = 1.0f; leaf->UpdatePvsSize(); const float importance = (float)leaf->GetPvsSize() / (float)maxPvs; mForcedMaterial.mDiffuseColor.r = importance; mForcedMaterial.mDiffuseColor.g = 1.0f - mForcedMaterial.mDiffuseColor.r; } ExportMesh(mesh); DEL_PTR(mesh); } else { VspKdInterior *interior = dynamic_cast(node); tStack.push(interior->GetFront()); tStack.push(interior->GetBack()); } } //ExportMesh(mesh); //DEL_PTR(mesh); return true; } bool X3dExporter::ExportKdTree(const KdTree &tree) { if (mExportRayDensity) { return ExportKdTreeRayDensity(tree); } stack tStack; tStack.push(tree.GetRoot()); Mesh *mesh = new Mesh; while (!tStack.empty()) { KdNode *node = tStack.top(); tStack.pop(); AxisAlignedBox3 box = tree.GetBox(node); // add 6 vertices of the box int index = (int)mesh->mVertices.size(); for (int i=0; i < 8; i++) { Vector3 v; box.GetVertex(i, v); mesh->mVertices.push_back(v); } mesh->AddFace(new Face(index + 0, index + 1, index + 3, index + 2) ); mesh->AddFace(new Face(index + 0, index + 2, index + 6, index + 4) ); mesh->AddFace(new Face(index + 4, index + 6, index + 7, index + 5) ); mesh->AddFace(new Face(index + 3, index + 1, index + 5, index + 7) ); mesh->AddFace(new Face(index + 0, index + 4, index + 5, index + 1) ); mesh->AddFace(new Face(index + 2, index + 3, index + 7, index + 6) ); if (!node->IsLeaf()) { KdInterior *interior = (KdInterior *)node; tStack.push(interior->mFront); tStack.push(interior->mBack); } } ExportMesh(mesh); delete mesh; return true; // TODO return true; } bool X3dExporter::ExportVssTree(const VssTree &tree ) { stack tStack; tStack.push(tree.GetRoot()); Mesh *mesh = new Mesh; VssRayContainer rays; while (!tStack.empty()) { VssTreeNode *node = tStack.top(); tStack.pop(); if (!node->IsLeaf()) { VssTreeInterior *interior = (VssTreeInterior *)node; tStack.push(interior->front); tStack.push(interior->back); } else { VssTreeLeaf *leaf = (VssTreeLeaf *)node; AxisAlignedBox3 box; box = tree.GetBBox(leaf); box.AddBoxToMesh(mesh); if (tree.ValidLeaf(leaf)) { Vector3 origin = box.Center(); box = tree.GetDirBBox(leaf); VssRay *ray; const indices[][2] = {{0,0}, {0,1}, {1,1}, {1,0}}; MeshInstance dummy(mesh); for (int i=0; i < 4; i++) { // Vector3 v = box.GetVertex(indices[i][0], indices[i][1], 0); Vector3 v = box.Center(); Vector3 direction = VssRay::GetDirection(v.x, v.y); if (Magnitude(direction) > Limits::Small) direction.Normalize(); else direction = Vector3(0, 1, 0); float k = 100.0f*leaf->GetImportance(); // get 4 corners of the ray directions ray = new VssRay(origin, origin + (direction*k), NULL, &dummy); rays.push_back(ray); } } } } ExportMesh(mesh); ExportRays(rays); CLEAR_CONTAINER(rays); delete mesh; return true; } bool X3dExporter::ExportVssTree2(const VssTree &tree, const Vector3 direction ) { stack tStack; mUseForcedMaterial = true; Vector3 dirParam; dirParam.x = VssRay::GetDirParam(0, Normalize(direction)); dirParam.y = VssRay::GetDirParam(1, Normalize(direction)); float maxImportance = 0.0f; tStack.push(tree.GetRoot()); while (!tStack.empty()) { VssTreeNode *node = tStack.top(); tStack.pop(); if (!node->IsLeaf()) { VssTreeInterior *interior = (VssTreeInterior *)node; if (interior->axis < 3) { tStack.push(interior->front); tStack.push(interior->back); } else { if (dirParam[interior->axis-3] < interior->position) tStack.push(interior->back); else tStack.push(interior->front); } } else { VssTreeLeaf *leaf = (VssTreeLeaf *)node; if (tree.ValidLeaf(leaf)) { float i = leaf->GetImportance(); if (i > maxImportance) maxImportance = i; } } } tStack.push(tree.GetRoot()); while (!tStack.empty()) { VssTreeNode *node = tStack.top(); tStack.pop(); if (!node->IsLeaf()) { VssTreeInterior *interior = (VssTreeInterior *)node; if (interior->axis < 3) { tStack.push(interior->front); tStack.push(interior->back); } else { if (dirParam[interior->axis-3] < interior->position) tStack.push(interior->back); else tStack.push(interior->front); } } else { VssTreeLeaf *leaf = (VssTreeLeaf *)node; if (tree.ValidLeaf(leaf)) { AxisAlignedBox3 box; box = tree.GetBBox(leaf); Mesh *mesh = new Mesh; box.AddBoxToMesh(mesh); // get 4 corners of the ray directions mForcedMaterial.mDiffuseColor.b = 1.0f; mForcedMaterial.mDiffuseColor.r = leaf->GetImportance()/maxImportance; mForcedMaterial.mDiffuseColor.g = 1.0f - mForcedMaterial.mDiffuseColor.r; ExportMesh(mesh); delete mesh; } } } mUseForcedMaterial = false; return true; } bool X3dExporter::ExportBspTreeRayDensity(const BspTree &tree) { stack tStack; tStack.push(tree.GetRoot()); bool fm = mUseForcedMaterial; mUseForcedMaterial = true; mForcedMaterial.mDiffuseColor.g = 1.0f; mForcedMaterial.mDiffuseColor.b = 1.0f; while (!tStack.empty()) { BspNode *node = tStack.top(); tStack.pop(); if (node->IsLeaf()) { ViewCell *vc = dynamic_cast(node)->GetViewCell(); // set the mesh material according to the ray density if (vc->mPassingRays.mRays) { float importance = vc->mPassingRays.mContributions / (float)vc->mPassingRays.mRays; mForcedMaterial.mDiffuseColor.r = importance; mForcedMaterial.mDiffuseColor.g = 1.0f - mForcedMaterial.mDiffuseColor.r; ExportViewCell(vc); } } else { BspInterior *interior = (BspInterior *)node; tStack.push(interior->GetFront()); tStack.push(interior->GetBack()); } } // restore the state of forced material mUseForcedMaterial = fm; return true; } bool X3dExporter::ExportKdTreeRayDensity(const KdTree &tree) { stack tStack; tStack.push(tree.GetRoot()); bool fm = mUseForcedMaterial; mUseForcedMaterial = true; mForcedMaterial.mDiffuseColor.g = 1.0f; mForcedMaterial.mDiffuseColor.b = 1.0f; while (!tStack.empty()) { KdNode *node = tStack.top(); tStack.pop(); if (node->IsLeaf()) { AxisAlignedBox3 box = tree.GetBox(node); Mesh *mesh = new Mesh; // add 6 vertices of the box int index = (int)mesh->mVertices.size(); for (int i=0; i < 8; i++) { Vector3 v; box.GetVertex(i, v); mesh->mVertices.push_back(v); } mesh->AddFace(new Face(index + 0, index + 1, index + 3, index + 2) ); mesh->AddFace(new Face(index + 0, index + 2, index + 6, index + 4) ); mesh->AddFace(new Face(index + 4, index + 6, index + 7, index + 5) ); mesh->AddFace(new Face(index + 3, index + 1, index + 5, index + 7) ); mesh->AddFace(new Face(index + 0, index + 4, index + 5, index + 1) ); mesh->AddFace(new Face(index + 2, index + 3, index + 7, index + 6) ); // set the mesh material according to the ray density KdLeaf *leaf = (KdLeaf *) node; if (leaf->mPassingRays.mRays) { float importance = leaf->mPassingRays.mContributions/(float)leaf->mPassingRays.mRays; // float importance = leaf->mPassingRays.mContributions/1000.0f; // float importance = leaf->mPassingRays.mRays/1000.0f; ///(float)leaf->mPassingRays.mRays; // mForcedMaterial.mDiffuseColor.r = log10(leaf->mPassingRays.mRays)/3.0f; mForcedMaterial.mDiffuseColor.r = importance; mForcedMaterial.mDiffuseColor.g = 1.0f - mForcedMaterial.mDiffuseColor.r; ExportMesh(mesh); } delete mesh; } else { KdInterior *interior = (KdInterior *)node; tStack.push(interior->mFront); tStack.push(interior->mBack); } } // restore the state of forced material mUseForcedMaterial = fm; return true; } struct BspSplitData { /// the current node BspNode *mNode; vector mPlanes; vector mSides; bool mIsFront; int mDepth; BspSplitData(BspNode *node): mNode(node), mIsFront(false), mDepth(0) {}; BspSplitData(BspNode *node, vector planes, vector sides, const bool isFront, const int depth): mNode(node), mPlanes(planes), mSides(sides), mIsFront(isFront), mDepth(depth) {}; }; void X3dExporter::ExportLeavesGeometry(const BspTree &tree, const vector &leaves) { vector::const_iterator it, it_end = leaves.end(); for (it = leaves.begin(); it != it_end; ++ it) { BspNodeGeometry geom; tree.ConstructGeometry(*it, geom); ExportPolygons(geom.mPolys); } } void X3dExporter::ExportBspNodeSplits(BspNode *root, const AxisAlignedBox3 &box, const bool exportDepth, const bool epsilon) { std::stack tStack; BspSplitData tData(root); tStack.push(tData); PolygonContainer polys; vector depths; int maxDepth = 0; while (!tStack.empty()) { // filter polygons donw the tree BspSplitData tData = tStack.top(); tStack.pop(); if (tData.mNode->IsLeaf()) { if (tData.mDepth > maxDepth) maxDepth = tData.mDepth; } else { BspInterior *interior = dynamic_cast(tData.mNode); // add current side of split plane if (tData.mNode != root) tData.mSides.push_back(tData.mIsFront); // bounded plane is added to the polygons Polygon3 *planePoly = box.CrossSection(interior->GetPlane()); // do all the splits with the previous planes for (int i = 0; i < (int)tData.mPlanes.size(); ++ i) { if (planePoly->ClassifyPlane(tData.mPlanes[i], epsilon) == Polygon3::SPLIT) { Polygon3 *frontPoly = new Polygon3(); Polygon3 *backPoly = new Polygon3(); planePoly->Split(tData.mPlanes[i], *frontPoly, *backPoly, epsilon); DEL_PTR(planePoly); if(tData.mSides[i] == true) { planePoly = frontPoly; DEL_PTR(backPoly); } else { planePoly = backPoly; DEL_PTR(frontPoly); } } } tData.mPlanes.push_back(interior->GetPlane()); // add plane to split planes if (planePoly->Valid(epsilon)) { polys.push_back(planePoly); depths.push_back(tData.mDepth); } else DEL_PTR(planePoly); // push the children on the stack tStack.push(BspSplitData(interior->GetFront(), tData.mPlanes, tData.mSides, true, tData.mDepth + 1)); tStack.push(BspSplitData(interior->GetBack(), tData.mPlanes, tData.mSides, false, tData.mDepth + 1)); } } if (maxDepth > 0) { mUseForcedMaterial = true; for (int i = 0; i < (int)polys.size(); ++ i) { mForcedMaterial.mDiffuseColor.b = 1.0f; float importance = (float)depths[i]/ (float)maxDepth; mForcedMaterial.mDiffuseColor.r = importance; mForcedMaterial.mDiffuseColor.g = 1.0f - mForcedMaterial.mDiffuseColor.r; ExportPolygon(polys[i]); } } else { ExportPolygons(polys); } CLEAR_CONTAINER(polys); } void X3dExporter::ExportBspSplits(const BspTree &tree, const bool exportDepth) { ExportBspNodeSplits(tree.GetRoot(), tree.GetBoundingBox(), exportDepth, tree.GetEpsilon()); } void X3dExporter::ExportBspSplits(const VspBspTree &tree, const bool exportDepth) { ExportBspNodeSplits(tree.GetRoot(), tree.GetBoundingBox(), exportDepth, tree.GetEpsilon()); } void X3dExporter::ExportBspSplitPlanes(const BspTree &tree) { std::stack tStack; tStack.push(tree.GetRoot()); PolygonContainer polys; while (!tStack.empty()) { // filter polygons donw the tree BspNode *node = tStack.top(); tStack.pop(); if (!node->IsLeaf()) { BspInterior *interior = dynamic_cast(node); // bounded plane is added to the polygons polys.push_back(tree.GetBoundingBox().CrossSection(interior->GetPlane())); // push the children on the stack tStack.push(interior->GetBack()); tStack.push(interior->GetFront()); } } ExportPolygons(polys); CLEAR_CONTAINER(polys); } void X3dExporter::ExportGeometry(const ObjectContainer &objects) { for (int j = 0; j < objects.size(); ++ j) ExportIntersectable(objects[j]); } bool X3dExporter::ExportRssTree2(const RssTree &tree, const Vector3 direction ) { stack tStack; mUseForcedMaterial = true; Vector3 dirParam; dirParam.x = VssRay::GetDirParam(0, Normalize(direction)); dirParam.y = VssRay::GetDirParam(1, Normalize(direction)); float maxImportance = 0.0f; tStack.push(tree.GetRoot()); while (!tStack.empty()) { RssTreeNode *node = tStack.top(); tStack.pop(); if (!node->IsLeaf()) { RssTreeInterior *interior = (RssTreeInterior *)node; if (interior->axis < 3) { tStack.push(interior->front); tStack.push(interior->back); } else { if (dirParam[interior->axis-3] < interior->position) tStack.push(interior->back); else tStack.push(interior->front); } } else { RssTreeLeaf *leaf = (RssTreeLeaf *)node; if (tree.ValidLeaf(leaf)) { float i = leaf->GetImportance(); if (i > maxImportance) maxImportance = i; } } } tStack.push(tree.GetRoot()); while (!tStack.empty()) { RssTreeNode *node = tStack.top(); tStack.pop(); if (!node->IsLeaf()) { RssTreeInterior *interior = (RssTreeInterior *)node; if (interior->axis < 3) { tStack.push(interior->front); tStack.push(interior->back); } else { if (dirParam[interior->axis-3] < interior->position) tStack.push(interior->back); else tStack.push(interior->front); } } else { RssTreeLeaf *leaf = (RssTreeLeaf *)node; if (tree.ValidLeaf(leaf)) { AxisAlignedBox3 box; box = tree.GetShrankedBBox(leaf); Mesh *mesh = new Mesh; box.AddBoxToMesh(mesh); // get 4 corners of the ray directions mForcedMaterial.mDiffuseColor.b = 1.0f; mForcedMaterial.mDiffuseColor.r = leaf->GetImportance()/maxImportance; mForcedMaterial.mDiffuseColor.g = 1.0f - mForcedMaterial.mDiffuseColor.r; ExportMesh(mesh); delete mesh; } } } mUseForcedMaterial = false; return true; } void X3dExporter::ExportViewpoint(const Vector3 &point, const Vector3 &direction) { stream<<""<"< planes = beam.mPlanes; planes.push_back(fplane); for (int i = 0; i < planes.size(); ++ i) { Polygon3 *poly = bbox.CrossSection(planes[i]); if (!poly->Valid(Limits::Small)) DEL_PTR(poly); for (int j = 0; (j < planes.size()) && poly; ++ j) { if (j != i) { Polygon3 *front = new Polygon3(); Polygon3 *back = new Polygon3(); poly->Split(planes[j], *front, *back, Limits::Small); DEL_PTR(poly); DEL_PTR(front); if (!back->Valid(Limits::Small)) DEL_PTR(back); poly = back; } } if (poly) polys.push_back(poly); } ExportPolygons(polys); CLEAR_CONTAINER(polys); }