void mango_main(){ Geometry::Box *platform; BouncingBall *ball; platform = new Geometry::Box(); ball = new BouncingBall(); platform->setDimensions(1.0, 0.1, 1.0); ball->setRadius(0.2); ball->set(RENDER | STEP); platform->set(RENDER); }
void drawBox(RenderingContext & rc, const Geometry::Box & box) { static Util::Reference<Mesh> mesh; if (mesh.isNull()) { VertexDescription vertexDescription; vertexDescription.appendPosition3D(); vertexDescription.appendNormalFloat(); const Geometry::Box unitBox(Geometry::Vec3(-0.5f, -0.5f, -0.5f), Geometry::Vec3(0.5f, 0.5f, 0.5f)); mesh = MeshUtils::MeshBuilder::createBox(vertexDescription, unitBox); } Geometry::Matrix4x4 matrix; matrix.translate(box.getCenter()); matrix.scale(box.getExtentX(), box.getExtentY(), box.getExtentZ()); rc.pushMatrix_modelToCamera(); rc.multMatrix_modelToCamera(matrix); rc.displayMesh(mesh.get()); rc.popMatrix_modelToCamera(); }
void drawWireframeBox(RenderingContext & rc, const Geometry::Box & box) { static Util::Reference<Mesh> mesh; if (mesh.isNull()) { VertexDescription vertexDescription; vertexDescription.appendPosition3D(); mesh = new Mesh(vertexDescription, 8, 16); mesh->setDataStrategy(SimpleMeshDataStrategy::getPureLocalStrategy()); mesh->setDrawMode(Mesh::DRAW_LINE_STRIP); MeshIndexData & id = mesh->openIndexData(); uint32_t * indices = id.data(); /* * Corners: * 6---------7 * /| /| * / | / | * 2---------3 | * | | | | * | 4------|--5 * | / | / * |/ |/ * 0---------1 */ indices[0] = 0; indices[1] = 2; indices[2] = 3; indices[3] = 1; indices[4] = 5; indices[5] = 7; indices[6] = 6; indices[7] = 4; indices[8] = 0; indices[9] = 1; indices[10] = 3; indices[11] = 7; indices[12] = 5; indices[13] = 4; indices[14] = 6; indices[15] = 2; id.updateIndexRange(); id.markAsChanged(); } MeshVertexData & vd = mesh->openVertexData(); float * vertices = reinterpret_cast<float *>(vd.data()); for (uint_fast8_t c = 0; c < 8; ++c) { const Geometry::Vec3 & corner = box.getCorner(static_cast<Geometry::corner_t> (c)); *vertices++ = corner.getX(); *vertices++ = corner.getY(); *vertices++ = corner.getZ(); } vd._setBoundingBox(box); vd.markAsChanged(); rc.displayMesh(mesh.get()); }
static void describeGeometryNode(ExporterContext & /*ctxt*/,DescriptionMap & desc, Node * node) { desc.setString(Consts::ATTR_NODE_TYPE, Consts::NODE_TYPE_GEOMETRY); std::unique_ptr<DescriptionMap> dataDesc(new DescriptionMap); GeometryNode * gn = dynamic_cast<GeometryNode*>(node); // annotate with bounding box const Geometry::Box bb = gn->getBB(); const Geometry::Vec3 center = bb.getCenter(); std::stringstream s; s << center.getX() << " " << center.getY() << " " << center.getZ() << " " << bb.getExtentX() << " " << bb.getExtentY() << " " << bb.getExtentZ(); dataDesc->setString(Consts::ATTR_MESH_BB, s.str()); Rendering::Mesh * m = gn->getMesh(); if(m!=nullptr) { // mesh present? // no filename -> store data in .minsg if(m->getFileName().empty()) { std::ostringstream meshStream; if(Rendering::Serialization::saveMesh(gn->getMesh(), "mmf", meshStream)) { dataDesc->setString(Consts::ATTR_DATA_TYPE,"mesh"); dataDesc->setString(Consts::ATTR_DATA_ENCODING,"base64"); const std::string streamString = meshStream.str(); const std::string meshString = Util::encodeBase64(std::vector<uint8_t>(streamString.begin(), streamString.end())); dataDesc->setString(Consts::DATA_BLOCK,meshString); } } else { // filename given? Util::FileName meshFilename(m->getFileName()); // // make path to mesh relative to scene (if mesh lies below the scene) // Util::FileUtils::makeRelativeIfPossible(ctxt.sceneFile, meshFilename); dataDesc->setString(Consts::ATTR_DATA_TYPE,"mesh"); dataDesc->setString(Consts::ATTR_MESH_FILENAME,meshFilename.toShortString()); } ExporterTools::addDataEntry(desc, std::move(dataDesc)); } }
void PolygonDensityEvaluator::calcPriority(Region * r) { int testsPerAxis = getAttribute(Util::StringIdentifier("#Tests per axis"))->toUnsignedInt(); Geometry::Box box = r->getBounds(); PrioSplit px = calcPriority(Geometry::Helper::splitUpBox(box, testsPerAxis,1,1)); PrioSplit py = calcPriority(Geometry::Helper::splitUpBox(box, 1,testsPerAxis,1)); PrioSplit pz = calcPriority(Geometry::Helper::splitUpBox(box, 1,1,testsPerAxis)); float volumePower = pow(box.getVolume(), getAttribute(Util::StringIdentifier("Volume Power"))->toFloat()); px.prio *= volumePower; py.prio *= volumePower; pz.prio *= volumePower; float p = std::max(std::max(px.prio,py.prio),pz.prio); r->setAttribute(Util::StringIdentifier("PolygonDensityPrio"), GenericAttribute::createNumber<float>(p)); float f = getAttribute(Util::StringIdentifier("Extent Power"))->toFloat(); px.prio *= pow(box.getExtentX(),f); py.prio *= pow(box.getExtentY(),f); pz.prio *= pow(box.getExtentZ(),f); p = std::max(std::max(px.prio,py.prio),pz.prio); if(p==px.prio) { r->setAttribute(Util::StringIdentifier("PolygonDensitySplit"), GenericAttribute::createNumber<int>(0)); r->setAttribute(Util::StringIdentifier("PolygonDensityRatio"), GenericAttribute::createNumber<float>(px.ratio)); } else if(p==py.prio) { r->setAttribute(Util::StringIdentifier("PolygonDensitySplit"), GenericAttribute::createNumber<int>(1)); r->setAttribute(Util::StringIdentifier("PolygonDensityRatio"), GenericAttribute::createNumber<float>(py.ratio)); } else if(p==pz.prio) { r->setAttribute(Util::StringIdentifier("PolygonDensitySplit"), GenericAttribute::createNumber<int>(2)); r->setAttribute(Util::StringIdentifier("PolygonDensityRatio"), GenericAttribute::createNumber<float>(pz.ratio)); } else FAIL(); }
float PolygonDensityEvaluator::calcDensity(const Geometry::Box & b) { return countPolygons(b) / b.getVolume(); }
void BoxTest::testGetters() { const Geometry::Box b1(-1.0f, 1.0f, -2.0f, 2.0f, -3.0f, 3.0f); const Geometry::Box b2; CPPUNIT_ASSERT(b1.getMaxX() == 1.0f); CPPUNIT_ASSERT(b1.getMax(Geometry::dimension_t::X) == 1.0f); CPPUNIT_ASSERT(b1.getMaxY() == 2.0f); CPPUNIT_ASSERT(b1.getMax(Geometry::dimension_t::Y) == 2.0f); CPPUNIT_ASSERT(b1.getMaxZ() == 3.0f); CPPUNIT_ASSERT(b1.getMax(Geometry::dimension_t::Z) == 3.0f); CPPUNIT_ASSERT(b1.getMinX() == -1.0f); CPPUNIT_ASSERT(b1.getMin(Geometry::dimension_t::X) == -1.0f); CPPUNIT_ASSERT(b1.getMinY() == -2.0f); CPPUNIT_ASSERT(b1.getMin(Geometry::dimension_t::Y) == -2.0f); CPPUNIT_ASSERT(b1.getMinZ() == -3.0f); CPPUNIT_ASSERT(b1.getMin(Geometry::dimension_t::Z) == -3.0f); CPPUNIT_ASSERT(b1.getExtentMax() == 6.0f); CPPUNIT_ASSERT(b1.getExtentMin() == 2.0f); CPPUNIT_ASSERT(b1.getExtentX() == 2.0f); CPPUNIT_ASSERT(b1.getExtent(Geometry::dimension_t::X) == 2.0f); CPPUNIT_ASSERT(b1.getExtentY() == 4.0f); CPPUNIT_ASSERT(b1.getExtent(Geometry::dimension_t::Y) == 4.0f); CPPUNIT_ASSERT(b1.getExtentZ() == 6.0f); CPPUNIT_ASSERT(b1.getExtent(Geometry::dimension_t::Z) == 6.0f); CPPUNIT_ASSERT(b1.getVolume() == 48.0f); CPPUNIT_ASSERT(b1.getSurfaceArea() == 88.0f); CPPUNIT_ASSERT(b1.getCenter() == Geometry::Vec3(0.0f, 0.0f, 0.0f)); CPPUNIT_ASSERT(b1.getBoundingSphereRadius() == 0.5f * std::sqrt(56.0f)); }
void BoxTest::testMisc() { const Geometry::Box b1(-1.0f, 1.0f, -2.0f, 2.0f, -3.0f, 3.0f); Geometry::Box b2; b2 = Geometry::Box(); CPPUNIT_ASSERT(b2.isValid()); b2.invalidate(); CPPUNIT_ASSERT(b2.isInvalid()); CPPUNIT_ASSERT(b1.getCorner(Geometry::corner_t::xyz) == Geometry::Vec3(b1.getMinX(), b1.getMinY(), b1.getMinZ())); CPPUNIT_ASSERT(b1.getCorner(Geometry::corner_t::Xyz) == Geometry::Vec3(b1.getMaxX(), b1.getMinY(), b1.getMinZ())); CPPUNIT_ASSERT(b1.getCorner(Geometry::corner_t::xYz) == Geometry::Vec3(b1.getMinX(), b1.getMaxY(), b1.getMinZ())); CPPUNIT_ASSERT(b1.getCorner(Geometry::corner_t::XYz) == Geometry::Vec3(b1.getMaxX(), b1.getMaxY(), b1.getMinZ())); CPPUNIT_ASSERT(b1.getCorner(Geometry::corner_t::xyZ) == Geometry::Vec3(b1.getMinX(), b1.getMinY(), b1.getMaxZ())); CPPUNIT_ASSERT(b1.getCorner(Geometry::corner_t::XyZ) == Geometry::Vec3(b1.getMaxX(), b1.getMinY(), b1.getMaxZ())); CPPUNIT_ASSERT(b1.getCorner(Geometry::corner_t::xYZ) == Geometry::Vec3(b1.getMinX(), b1.getMaxY(), b1.getMaxZ())); CPPUNIT_ASSERT(b1.getCorner(Geometry::corner_t::XYZ) == Geometry::Vec3(b1.getMaxX(), b1.getMaxY(), b1.getMaxZ())); CPPUNIT_ASSERT(Geometry::Box::getOppositeCorner(Geometry::corner_t::xyz) == Geometry::corner_t::XYZ); CPPUNIT_ASSERT(Geometry::Box::getOppositeCorner(Geometry::corner_t::Xyz) == Geometry::corner_t::xYZ); CPPUNIT_ASSERT(Geometry::Box::getOppositeCorner(Geometry::corner_t::xYz) == Geometry::corner_t::XyZ); CPPUNIT_ASSERT(Geometry::Box::getOppositeCorner(Geometry::corner_t::XYz) == Geometry::corner_t::xyZ); CPPUNIT_ASSERT(Geometry::Box::getOppositeCorner(Geometry::corner_t::xyZ) == Geometry::corner_t::XYz); CPPUNIT_ASSERT(Geometry::Box::getOppositeCorner(Geometry::corner_t::XyZ) == Geometry::corner_t::xYz); CPPUNIT_ASSERT(Geometry::Box::getOppositeCorner(Geometry::corner_t::xYZ) == Geometry::corner_t::Xyz); CPPUNIT_ASSERT(Geometry::Box::getOppositeCorner(Geometry::corner_t::XYZ) == Geometry::corner_t::xyz); CPPUNIT_ASSERT(Geometry::Helper::getNormal(Geometry::side_t::X_NEG) == Geometry::Vec3(-1.0f, 0.0f, 0.0f)); CPPUNIT_ASSERT(Geometry::Helper::getNormal(Geometry::side_t::X_POS) == Geometry::Vec3(1.0f, 0.0f, 0.0f)); CPPUNIT_ASSERT(Geometry::Helper::getNormal(Geometry::side_t::Y_NEG) == Geometry::Vec3(0.0f, -1.0f, 0.0f)); CPPUNIT_ASSERT(Geometry::Helper::getNormal(Geometry::side_t::Y_POS) == Geometry::Vec3(0.0f, 1.0f, 0.0f)); CPPUNIT_ASSERT(Geometry::Helper::getNormal(Geometry::side_t::Z_NEG) == Geometry::Vec3(0.0f, 0.0f, -1.0f)); CPPUNIT_ASSERT(Geometry::Helper::getNormal(Geometry::side_t::Z_POS) == Geometry::Vec3(0.0f, 0.0f, 1.0f)); for (uint_fast8_t s = 0; s < 6; ++s) { const Geometry::side_t side = static_cast<const Geometry::side_t>(s); const Geometry::corner_t * corners = Geometry::Helper::getCornerIndices(side); for (uint_fast8_t i = 0; i < 4; ++i) { const uint_fast8_t prevCorner = i % 4; const uint_fast8_t currentCorner = (i + 1) % 4; const uint_fast8_t nextCorner = (i + 2) % 4; const Geometry::Vec3 edgeA = b1.getCorner(corners[nextCorner]) - b1.getCorner(corners[currentCorner]); const Geometry::Vec3 edgeB = b1.getCorner(corners[prevCorner]) - b1.getCorner(corners[currentCorner]); Geometry::Vec3 normal = edgeA.cross(edgeB); normal.normalize(); CPPUNIT_ASSERT(Geometry::Helper::getNormal(side) == normal); } } const Geometry::Vec3 v1(-1.1f, 0.0f, 0.0f); const Geometry::Vec3 v2(0.0f, 0.0f, 0.0f); const Geometry::Vec3 v3(1.1f, 0.0f, 0.0f); CPPUNIT_ASSERT(!b1.contains(-1.1f, 0.0f, 0.0f)); CPPUNIT_ASSERT(b1.contains(0.0f, 0.0f, 0.0f)); CPPUNIT_ASSERT(!b1.contains(1.1f, 0.0f, 0.0f)); CPPUNIT_ASSERT(!b1.contains(v1)); CPPUNIT_ASSERT(b1.contains(v2)); CPPUNIT_ASSERT(!b1.contains(v3)); CPPUNIT_ASSERT( Geometry::Intersection::isBoxIntersectingTriangle(b1, Geometry::Triangle<Geometry::Vec3>(v1, v2, v3))); CPPUNIT_ASSERT(b1.contains(Geometry::Box())); CPPUNIT_ASSERT(b1.contains(b1)); CPPUNIT_ASSERT(!b1.contains(Geometry::Box(-1.1f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f))); CPPUNIT_ASSERT(Geometry::Intersection::isBoxIntersectingBox(Geometry::Box(0, 1, 0, 1, 0, 1), Geometry::Box(0, 1, 0, 1, 0, 1))); CPPUNIT_ASSERT(!Geometry::Intersection::isBoxIntersectingBox(Geometry::Box(0, 1, 0, 1, 0, 1), Geometry::Box(2, 3, 2, 3, 2, 3))); CPPUNIT_ASSERT(!Geometry::Intersection::isBoxIntersectingBox(Geometry::Box(0, 1, 0, 1, 0, 1), Geometry::Box(0, 3, 2, 3, 2, 3))); CPPUNIT_ASSERT(!Geometry::Intersection::isBoxIntersectingBox(Geometry::Box(0, 1, 0, 1, 0, 1), Geometry::Box(2, 3, 0, 3, 2, 3))); CPPUNIT_ASSERT(!Geometry::Intersection::isBoxIntersectingBox(Geometry::Box(0, 1, 0, 1, 0, 1), Geometry::Box(2, 3, 2, 3, 0, 3))); CPPUNIT_ASSERT(Geometry::Intersection::isBoxIntersectingBox(Geometry::Box(0, 1, 0, 1, 0, 1), Geometry::Box(-1, 2, -1, 2, -1, 2))); CPPUNIT_ASSERT( Geometry::Intersection::isBoxIntersectingBox(b1, Geometry::Box(-1.1f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f))); CPPUNIT_ASSERT( !Geometry::Intersection::isBoxIntersectingBox(b1, Geometry::Box(-1.1f, -1.0f, -2.1f, -2.0f, -3.0f, -3.0f))); b2 = Geometry::Box(0.5f, 1.5f, 1.5f, 2.5f, 2.5f, 3.5f); CPPUNIT_ASSERT(Geometry::Intersection::isBoxIntersectingBox(b1, b2)); CPPUNIT_ASSERT(Geometry::Intersection::getBoxBoxIntersection(b1, b2) == Geometry::Box(0.5f, 1.0f, 1.5f, 2.0f, 2.5f, 3.0f)); CPPUNIT_ASSERT(b1.getDistance(Geometry::Vec3(-2.0f, 0.0f, 0.0f)) == 1.0f); CPPUNIT_ASSERT(b1.getDistance(Geometry::Vec3(2.0f, 0.0f, 0.0f)) == 1.0f); CPPUNIT_ASSERT(b1.getDistance(Geometry::Vec3(0.0f, -3.0f, 0.0f)) == 1.0f); CPPUNIT_ASSERT(b1.getDistance(Geometry::Vec3(0.0f, 3.0f, 0.0f)) == 1.0f); CPPUNIT_ASSERT(b1.getDistance(Geometry::Vec3(0.0f, 0.0f, -4.0f)) == 1.0f); CPPUNIT_ASSERT(b1.getDistance(Geometry::Vec3(0.0f, 0.0f, 4.0f)) == 1.0f); CPPUNIT_ASSERT(b1.getDistanceSquared(Geometry::Vec3(-2.0f, -3.0f, -4.0f)) == 3.0f); CPPUNIT_ASSERT(b1.getDistanceSquared(Geometry::Vec3(2.0f, 3.0f, 4.0f)) == 3.0f); // Make sure the box b1 was never changed. CPPUNIT_ASSERT(b1 == Geometry::Box(-1.0f, 1.0f, -2.0f, 2.0f, -3.0f, 3.0f)); }
int main(int argc, char *argv[]){ Geometry::Box *b; Geometry::Sphere *s; Geometry::Cylinder *c; Geometry::Shell *sh; Geometry::Arrow *a[3]; Geometry::CoordinateSystem *cs; Geometry::VertexArray *va; Geometry::Circle *ci[2]; Geometry::NGon *n[2]; Geometry::Rectangle *r[2]; // Setup Mango::initialize(); Mango::OnGlut::initialize(argc, argv); // Create a box and set its render event b = new Geometry::Box(); b->set(RENDER); // Create a sphere and set its render event s = new Geometry::Sphere(); s->setRadius(0.7); s->position = Vector(2, 0, 0); s->set(RENDER); // Create a cylinder and set its render event c = new Geometry::Cylinder(); c->position = Vector(0, 0, -2); c->setHeight(1.0); c->setRadius(0.5); c->set(RENDER); // Create a shell and set its render event sh = new Geometry::Shell(); sh->position = Vector(2, 0, -2); sh->setRadius(0.7); sh->setFraction(0.6); sh->setThickness(0.05); sh->setOrientation(-25, 205, 0); sh->set(RENDER); // Create a few arrows a[0] = new Geometry::Arrow(); a[0]->position = Vector(-2, -0.5, -2); a[0]->set(RENDER); a[1] = new Geometry::Arrow(); a[1]->position = Vector(-1.6, -0.5, -2); a[1]->setLength(0.4); a[1]->setBlueComponent(0.8); a[1]->set(RENDER); a[2] = new Geometry::Arrow(); a[2]->position = Vector(-1.8, -0.5, -1.6); a[2]->setLength(1.75); a[2]->setThickness(0.3); a[2]->setRedComponent(0.6); a[2]->set(RENDER); // Create a coordinate system cs = new Geometry::CoordinateSystem(); cs->position = Vector(2, -0.3, 1.6); cs->setAxisLength(0.8); cs->setAxisThickness(0.1); cs->setRightHanded(1); cs->set(RENDER); // Create a vertex array va = new Geometry::VertexArray(); va->add(-0.5, 0.0, 0.0); va->add(0.0, 0.5, 0.0); va->add(0.0, 1.5, 0.0); va->add(0.0, 0.5, 0.0); va->add(0.5, 0.0, 0.0); va->add(0.0, 1.5, 0.0); va->setRenderReverseOrientation(true); va->setStyle(GL_TRIANGLES); va->position = Vector(0, -0.5, 2); va->set(RENDER); // Create circles ci[0] = new Geometry::Circle(); ci[0]->position = Vector(-2.0, 0, 2.0); ci[0]->setRadius(0.7); ci[0]->setGreenComponent(0.9); ci[0]->set(RENDER); ci[1] = new Geometry::Circle(); ci[1]->position = Vector(-2.0, 0, 2.0); ci[1]->setRadius(0.2); ci[1]->setStyle(FILL); ci[1]->setOrientation(0, 90, 0); ci[1]->setRenderReverseOrientation(true); ci[1]->set(RENDER); // Create ngons n[0] = new Geometry::NGon(); n[0]->position = Vector(-2.0, 0, 0); n[0]->setRadius(0.3); n[0]->setStyle(FILL); n[0]->setNumberOfSides(6); n[0]->setRenderReverseOrientation(true); n[0]->set(RENDER); n[1] = new Geometry::NGon(); n[1]->position = Vector(-2.0, 0, 0); n[1]->setOrientation(0, 90, 0); n[1]->set(RENDER); // Create rectangles r[0] = new Geometry::Rectangle(); r[0]->position = Vector(-4.0, 0, 0); r[0]->setOrientation(0, 45, 0); r[0]->set(RENDER); r[1] = new Geometry::Rectangle(); r[1]->position = Vector(-4.0, 0, 0); r[1]->setOrientation(0, 135, 0); r[1]->setDimensions(0.5, 0.5/1.1618); r[1]->setStyle(FILL); r[1]->set(RENDER); // Start the main loop Mango::OnGlut::start(); // Teardown Mango::finalize(); }
void drawFastAbsBox(RenderingContext & rc, const Geometry::Box & b){ #ifdef LIB_GL rc.pushAndSetShader(nullptr); // Too slow: // rc.pushMatrix_modelToCamera(); // rc.resetMatrix(); // rc.applyChanges(); glPushMatrix(); glLoadTransposeMatrixf( rc.getMatrix_worldToCamera().getData()); static const unsigned int indices[]={ 1,3,2,0, 5,7,3,1, 4,6,7,5, 0,2,6,4, 7,6,2,3, 4,5,1,0 }; float corners[8][3] = {{b.getMaxX(), b.getMaxY(), b.getMaxZ()}, {b.getMinX(), b.getMaxY(), b.getMaxZ()}, {b.getMaxX(), b.getMinY(), b.getMaxZ()}, {b.getMinX(), b.getMinY(), b.getMaxZ()}, {b.getMaxX(), b.getMaxY(), b.getMinZ()}, {b.getMinX(), b.getMaxY(), b.getMinZ()}, {b.getMaxX(), b.getMinY(), b.getMinZ()}, {b.getMinX(), b.getMinY(), b.getMinZ()}}; glBegin(GL_QUADS); for(auto & index : indices){ glVertex3fv(corners[index]); } glEnd(); glPopMatrix(); // rc.popMatrix_modelToCamera(); rc.popShader(); #else drawAbsBox(rc,b); #endif }
//! ---|> [State] State::stateResult_t CHCRenderer::doEnableState(FrameContext & context,Node * rootNode, const RenderParam & rp){ if(rp.getFlag(SKIP_RENDERER)) return State::STATE_SKIPPED; if(debugShowVisible){ std::deque<Node *> nodes; { const auto children = getChildNodes(rootNode); nodes.insert(nodes.end(), children.begin(), children.end()); } while(!nodes.empty()){ Node& node = *nodes.front(); nodes.pop_front(); auto& nodeInfo = getNodeInfo(node); if(nodeInfo.frameNr == frameNr && nodeInfo.visible){ if(node.isClosed()) context.displayNode(&node,rp); else { const auto children = getChildNodes(&node); nodes.insert(nodes.end(), children.begin(), children.end()); } } } }else{ ++frameNr; // used for statistics unsigned int stat_numTests = 0; unsigned int stat_numTestsInvisible = 0; unsigned int stat_numTestsVisible = 0; Statistics & statistics = context.getStatistics(); RenderParam childParam = rp + USE_WORLD_MATRIX; const auto& camera = *context.getCamera(); const Geometry::Vec3 camPos = camera.getWorldOrigin(); const float bbEnlargement = camera.getNearPlane(); NodeDistancePriorityQueue_F2B distanceQueue(camPos); std::queue<std::pair<Rendering::OcclusionQuery, Node*>> queryQueue; const auto traverseNode = [&](Node& node){ if( node.isClosed() ){ // leaf node context.displayNode(&node, childParam ); }else{ for(auto & child : getChildNodes(&node)) distanceQueue.push(child); } }; const auto pullUpVisibility = [&](Node& node){ for(Node* n=&node; n&&n!=rootNode; n = n->getParent()){ auto& nodeInfo = getNodeInfo(*n); if(nodeInfo.frameNr == frameNr && nodeInfo.visible) break; nodeInfo.visible = true; nodeInfo.frameNr = frameNr; }; }; const auto startQuery = [&](Node& node,const Geometry::Box& worldBoundingBox){ Rendering::OcclusionQuery query; Rendering::OcclusionQuery::enableTestMode(context.getRenderingContext()); query.begin(); Rendering::drawAbsBox(context.getRenderingContext(), worldBoundingBox ); query.end(); Rendering::OcclusionQuery::disableTestMode(context.getRenderingContext()); return std::make_pair(std::move(query),&node); }; traverseNode(*rootNode); while(!distanceQueue.empty() || !queryQueue.empty()){ // ---- PART 1: process finished occlusion queries while( !queryQueue.empty() && (distanceQueue.empty() || queryQueue.front().first.isResultAvailable()) ){ if( queryQueue.front().first.getResult()>0 ){ ++stat_numTestsVisible; statistics.pushEvent( Statistics::EVENT_TYPE_END_TEST_VISIBLE, 1); Node& node = *queryQueue.front().second; pullUpVisibility(node); auto& nodeInfo = getNodeInfo( node ); if( !nodeInfo.wasVisible ) traverseNode(node); }else{ ++stat_numTestsInvisible; statistics.pushEvent( Statistics::EVENT_TYPE_END_TEST_INVISIBLE, 1); } queryQueue.pop(); } // ---- PART 2: tree traversal if( !distanceQueue.empty() ){ Node& node = *distanceQueue.top(); distanceQueue.pop(); const Geometry::Box worldBoundingBox = node.getWorldBB(); if (camera.testBoxFrustumIntersection( node.getWorldBB()) == Geometry::Frustum::intersection_t::OUTSIDE) { continue; } Geometry::Box enlargedBox = worldBoundingBox; enlargedBox.resizeAbs( bbEnlargement ); if( enlargedBox.contains(camPos) ){ pullUpVisibility(node); traverseNode(node); continue; } auto& nodeInfo = getNodeInfo( node ); // identify previously visible nodes const bool wasVisible = nodeInfo.frameNr == frameNr-1 && nodeInfo.visible; nodeInfo.wasVisible = wasVisible; // reset node's visibility flag nodeInfo.visible = false; // update node's visited flag nodeInfo.frameNr = frameNr; // test leafs and previously invisible nodes if( node.isClosed() || !wasVisible){ // on testing front // start test ++stat_numTests; statistics.pushEvent(Statistics::EVENT_TYPE_START_TEST, 1); queryQueue.push( std::move(startQuery(node,worldBoundingBox)) ); } // traverse a node unless it was invisible if( wasVisible ) traverseNode( node ); } } statistics.addValue(OcclusionCullingStatistics::instance(statistics).getOccTestVisibleCounter(), stat_numTestsVisible); statistics.addValue(OcclusionCullingStatistics::instance(statistics).getOccTestInvisibleCounter(), stat_numTestsInvisible); statistics.addValue(OcclusionCullingStatistics::instance(statistics).getOccTestCounter(), stat_numTests); } // std::cout << std::endl; return State::STATE_SKIP_RENDERING; }