BBox3f TriangleMeshFull::extract(size_t id, RTCTriangle* triangles_o, size_t& numTriangles, Vec3fa* positions_o, size_t& numVertices) const { BBox3f bounds = empty; if (motion.size()) { for (size_t j=0; j<triangles.size(); j++) { const TriangleMeshFull::Triangle& tri = triangles[j]; triangles_o[numTriangles++] = RTCTriangle((int)numVertices+2*tri.v0,(int)numVertices+2*tri.v1,(int)numVertices+2*tri.v2,(int)(0x80000000 | id),(int)j); } for (size_t j=0; j<position.size(); j++) { const Vector3f p = position[j]; const Vector3f dpdt = motion[j]; positions_o[numVertices++] = Vector3f(p.x,p.y,p.z); positions_o[numVertices++] = Vector3f(dpdt.x,dpdt.y,dpdt.z); bounds.grow(p); bounds.grow(p+dpdt); } } else { for (size_t j=0; j<triangles.size(); j++) { const TriangleMeshFull::Triangle& tri = triangles[j]; triangles_o[numTriangles++] = RTCTriangle((int)numVertices+tri.v0,(int)numVertices+tri.v1,(int)numVertices+tri.v2,(int)id,(int)j); } for (size_t j=0; j<position.size(); j++) { const Vector3f p = position[j]; positions_o[numVertices++] = Vector3f(p.x,p.y,p.z); bounds.grow(p); } } return bounds; }
TEST(BBoxTest, mergedWithVec) { const BBox3f bounds(Vec3f(-12.0f, -3.0f, 4.0f), Vec3f(7.0f, 8.0f, 9.0f)); const Vec3f vec(-10.0f, -6.0f, 10.0f); const BBox3f merged(Vec3f(-12.0f, -6.0f, 4.0f), Vec3f(7.0f, 8.0f, 10.0f)); ASSERT_EQ(merged, bounds.mergedWith(vec)); }
BBox3f TriangleMeshTriangle4::update(char* prim, size_t num, void* geom) const { BBox3f bounds = empty; TriangleMeshScene::TriangleMesh* mesh = (TriangleMeshScene::TriangleMesh*) geom; for (size_t j=0; j<num; j++) { Triangle4& dst = ((Triangle4*) prim)[j]; ssei vgeomID = -1, vprimID = -1, vmask = -1; sse3f v0 = zero, v1 = zero, v2 = zero; for (size_t i=0; i<4; i++) { if (dst.primID[i] == -1) break; const unsigned geomID = dst.geomID[i]; const unsigned primID = dst.primID[i]; const TriangleMeshScene::TriangleMesh::Triangle& tri = mesh->triangle(primID); const Vec3fa p0 = mesh->vertex(tri.v[0]); const Vec3fa p1 = mesh->vertex(tri.v[1]); const Vec3fa p2 = mesh->vertex(tri.v[2]); bounds.extend(merge(BBox3f(p0),BBox3f(p1),BBox3f(p2))); vgeomID [i] = geomID; vprimID [i] = primID; vmask [i] = mesh->mask; v0.x[i] = p0.x; v0.y[i] = p0.y; v0.z[i] = p0.z; v1.x[i] = p1.x; v1.y[i] = p1.y; v1.z[i] = p1.z; v2.x[i] = p2.x; v2.y[i] = p2.y; v2.z[i] = p2.z; } new (&dst) Triangle4(v0,v1,v2,vgeomID,vprimID,vmask); } return bounds; }
TEST(BBoxTest, mergedWithBBox) { const BBox3f bounds1(Vec3f(-12.0f, -3.0f, 4.0f), Vec3f(7.0f, 8.0f, 9.0f)); const BBox3f bounds2(Vec3f(-10.0f, -5.0f, 3.0f), Vec3f(9.0f, 9.0f, 5.0f)); const BBox3f merged( Vec3f(-12.0f, -5.0f, 3.0f), Vec3f(9.0f, 9.0f, 9.0f)); ASSERT_EQ(merged, bounds1.mergedWith(bounds2)); }
int TriangleMeshWithNormals::extract(RTCScene scene, size_t id) const { unsigned mesh = rtcNewTriangleMesh (scene, RTC_GEOMETRY_STATIC, triangles.size(), vertices.size()); //if (mesh != id) throw std::runtime_error("ID does not match"); Vec3fa* vertices_o = (Vec3fa*) rtcMapBuffer(scene,mesh,RTC_VERTEX_BUFFER); RTCTriangle* triangles_o = (RTCTriangle*) rtcMapBuffer(scene,mesh,RTC_INDEX_BUFFER); for (size_t j=0; j<triangles.size(); j++) { const TriangleMeshWithNormals::Triangle& tri = triangles[j]; triangles_o[j].v0 = tri.v0; triangles_o[j].v1 = tri.v1; triangles_o[j].v2 = tri.v2; } BBox3f bounds = empty; for (size_t j=0; j<vertices.size(); j++) { const Vector3f p = vertices[j].p; vertices_o[j].x = p.x; vertices_o[j].y = p.y; vertices_o[j].z = p.z; bounds.grow(p); } rtcUnmapBuffer(scene,mesh,RTC_VERTEX_BUFFER); rtcUnmapBuffer(scene,mesh,RTC_INDEX_BUFFER); return mesh; }
TEST(BBoxTest, relativePosition) { const BBox3f bounds(Vec3f(-12.0f, -3.0f, 4.0f), Vec3f( 8.0f, 9.0f, 8.0f)); const Vec3f point1(-1.0f, 0.0f, 0.0f); const BBox3f::RelativePosition pos1 = bounds.relativePosition(point1); ASSERT_EQ(BBox3f::RelativePosition::Range_Within, pos1[0]); ASSERT_EQ(BBox3f::RelativePosition::Range_Within, pos1[1]); ASSERT_EQ(BBox3f::RelativePosition::Range_Less, pos1[2]); }
TEST(BBoxTest, containsBBox) { const BBox3f bounds1(Vec3f(-12.0f, -3.0f, 4.0f), Vec3f( 8.0f, 9.0f, 8.0f)); const BBox3f bounds2(Vec3f(-10.0f, -2.0f, 5.0f), Vec3f( 7.0f, 8.0f, 7.0f)); const BBox3f bounds3(Vec3f(-13.0f, -2.0f, 5.0f), Vec3f( 7.0f, 8.0f, 7.0f)); ASSERT_TRUE(bounds1.contains(bounds1)); ASSERT_TRUE(bounds1.contains(bounds2)); ASSERT_FALSE(bounds1.contains(bounds3)); }
TEST(BBoxTest, intersectsBBox) { const BBox3f bounds1(Vec3f(-12.0f, -3.0f, 4.0f), Vec3f( 8.0f, 9.0f, 8.0f)); const BBox3f bounds2(Vec3f(-10.0f, -2.0f, 5.0f), Vec3f( 7.0f, 8.0f, 7.0f)); const BBox3f bounds3(Vec3f(-13.0f, -2.0f, 5.0f), Vec3f( 7.0f, 8.0f, 7.0f)); const BBox3f bounds4(Vec3f(-15.0f, 10.0f, 9.0f), Vec3f(-13.0f, 12.0f, 10.0f)); const BBox3f bounds5(Vec3f(-15.0f, 10.0f, 9.0f), Vec3f(-12.0f, 12.0f, 10.0f)); ASSERT_TRUE(bounds1.intersects(bounds1)); ASSERT_TRUE(bounds1.intersects(bounds2)); ASSERT_TRUE(bounds1.intersects(bounds3)); ASSERT_FALSE(bounds1.intersects(bounds4)); ASSERT_FALSE(bounds1.intersects(bounds5)); }
BBox3f TriangleMeshWithNormals::extract(size_t id, RTCTriangle* triangles_o, size_t& numTriangles, Vec3fa* positions_o, size_t& numVertices) const { BBox3f bounds = empty; for (size_t j=0; j<triangles.size(); j++) { const TriangleMeshWithNormals::Triangle& tri = triangles[j]; triangles_o[numTriangles++] = RTCTriangle((int)numVertices+tri.v0,(int)numVertices+tri.v1,(int)numVertices+tri.v2,(int)id,(int)j); } for (size_t j=0; j<vertices.size(); j++) { const Vector3f p = vertices[j].p; positions_o[numVertices++] = Vector3f(p.x,p.y,p.z); bounds.grow(p); } return bounds; }
void BVH4BuilderTopLevel::task_build_parallel(size_t threadIndex, size_t threadCount, size_t taskIndex, size_t taskCount, TaskScheduler::Event* event_i) { /* ignore meshes that need all threads */ size_t objectID = taskIndex; if (builders[objectID] && builders[objectID]->needAllThreads) return; /* build all other meshes */ BBox3f bounds = build(threadIndex,threadCount,objectID); if (!bounds.empty()) g_state->thread_bounds[threadIndex].extend(bounds); }
void FallBackSplitter<Heuristic,PrimRefBlockList>::split(size_t threadIndex, PrimRefAlloc* alloc, const RTCGeometry* geom, PrimRefBlockList& prims, const PrimInfo& pinfo, PrimRefBlockList& lprims, PrimInfo& linfo, Split& lsplit, PrimRefBlockList& rprims, PrimInfo& rinfo, Split& rsplit) { /* enforce split */ size_t lnum = 0; BBox3f lgeomBounds = empty; BBox3f lcentBounds = empty; size_t rnum = 0; BBox3f rgeomBounds = empty; BBox3f rcentBounds = empty; atomic_set<PrimRefBlock>::item* lblock = lprims.insert(alloc->malloc(threadIndex)); atomic_set<PrimRefBlock>::item* rblock = rprims.insert(alloc->malloc(threadIndex)); while (atomic_set<PrimRefBlock>::item* block = prims.take()) { for (size_t i=0; i<block->size(); i++) { const PrimRef& prim = block->at(i); const BBox3f bounds = prim.bounds(); if ((lnum+rnum)&1) { lnum++; lgeomBounds.grow(bounds); lcentBounds.grow(center2(bounds)); if (likely(lblock->insert(prim))) continue; lblock = lprims.insert(alloc->malloc(threadIndex)); lblock->insert(prim); } else { rnum++; rgeomBounds.grow(bounds); rcentBounds.grow(center2(bounds)); if (likely(rblock->insert(prim))) continue; rblock = rprims.insert(alloc->malloc(threadIndex)); rblock->insert(prim); } } } new (&linfo) PrimInfo(lnum,lgeomBounds,lcentBounds); new (&rinfo) PrimInfo(rnum,rgeomBounds,rcentBounds); /* perform binning of left side */ Heuristic lheuristic(linfo,geom); typename PrimRefBlockList::iterator liter(lprims); while (typename PrimRefBlockList::item* block = liter.next()) { lheuristic.bin(block->base(),block->size()); } lheuristic.best(lsplit); /* perform binning of right side */ Heuristic rheuristic(rinfo,geom); typename PrimRefBlockList::iterator riter(rprims); while (typename PrimRefBlockList::item* block = riter.next()) { rheuristic.bin(block->base(),block->size()); } rheuristic.best(rsplit); }
void recursiveBuild(uint32_t nodeIndex, uint32_t start, uint32_t end, uint32_t* indices, PositionFunctor getPosition, uint32_t& nextFreeNode) { if(start + 1 == end) { // One node to process, it's a leaf m_Nodes[nodeIndex].setAsLeaf(); m_NodesData[nodeIndex].m_nIndex = indices[start]; m_NodesData[nodeIndex].m_Position = getPosition(indices[start]); return; } // Compute the bounding box of the data BBox3f bound; for(uint32_t i = start; i != end; ++i) { bound += getPosition(indices[i]); } // The split axis is the one with maximal extent for the data uint32_t splitAxis = maxComponent(abs(bound.size())); uint32_t splitIndex = (start + end) / 2; // Reorganize the pointers such that the middle element is the middle element on the split axis std::nth_element(indices + start, indices + splitIndex, indices + end, [splitAxis, &getPosition](uint32_t lhs, uint32_t rhs) -> bool { float v1 = getPosition(lhs)[splitAxis]; float v2 = getPosition(rhs)[splitAxis]; return v1 == v2 ? lhs < rhs : v1 < v2; }); float splitPosition = getPosition(indices[splitIndex])[splitAxis]; m_Nodes[nodeIndex].setAsInnerNode(splitPosition, splitAxis); m_NodesData[nodeIndex].m_nIndex = indices[splitIndex]; m_NodesData[nodeIndex].m_Position = getPosition(indices[splitIndex]); // Build the left subtree if(start < splitIndex) { m_Nodes[nodeIndex].m_bHasLeftChild = true; uint32_t childIndex = nextFreeNode++; recursiveBuild(childIndex, start, splitIndex, indices, getPosition, nextFreeNode); } // Build the right subtree if(splitIndex + 1 < end) { m_Nodes[nodeIndex].m_nRightChildIndex = nextFreeNode++; recursiveBuild(m_Nodes[nodeIndex].m_nRightChildIndex, splitIndex + 1, end, indices, getPosition, nextFreeNode); } }
BBox3f TriangleMeshTriangle1v::update(char* prim, size_t num, void* geom) const { BBox3f bounds = empty; const TriangleMeshScene::TriangleMesh* mesh = (const TriangleMeshScene::TriangleMesh*) geom; for (size_t j=0; j<num; j++) { Triangle1v& dst = ((Triangle1v*) prim)[j]; const unsigned geomID = dst.geomID(); const unsigned primID = dst.primID(); const TriangleMeshScene::TriangleMesh::Triangle& tri = mesh->triangle(primID); const Vec3fa v0 = mesh->vertex(tri.v[0]); const Vec3fa v1 = mesh->vertex(tri.v[1]); const Vec3fa v2 = mesh->vertex(tri.v[2]); new (&dst) Triangle1v(v0,v1,v2,geomID,primID,mesh->mask); bounds.extend(merge(BBox3f(v0),BBox3f(v1),BBox3f(v2))); } return bounds; }
TEST(BBoxTest, intersectWithRay) { const BBox3f bounds(Vec3f(-12.0f, -3.0f, 4.0f), Vec3f( 8.0f, 9.0f, 8.0f)); Vec3f normal; float distance = bounds.intersectWithRay(Ray3f(Vec3f::Null, Vec3f::NegZ)); ASSERT_TRUE(Math::isnan(distance)); distance = bounds.intersectWithRay(Ray3f(Vec3f::Null, Vec3f::PosZ), &normal); ASSERT_FALSE(Math::isnan(distance)); ASSERT_FLOAT_EQ(4.0f, distance); ASSERT_VEC_EQ(Vec3f::NegZ, normal); const Vec3f origin = Vec3f(-10.0f, -7.0f, 14.0f); const Vec3f diff = Vec3f(-2.0f, 3.0f, 8.0f) - origin; const Vec3f dir = diff.normalized(); distance = bounds.intersectWithRay(Ray3f(origin, dir), &normal); ASSERT_FALSE(Math::isnan(distance)); ASSERT_FLOAT_EQ(diff.length(), distance); ASSERT_VEC_EQ(Vec3f::PosZ, normal); }
void PtexViewer::frameView(bool reset) { if (reset) _cam.reset(); if (_displayFace>=0) { _cam.setLookAt(Vec3f(0.5, 0.5, 0)); _cam.setDistance(1.41); } else { if (_mode3d && _envCube && reset) { _cam.setLookAt(Vec3f(0,0,0)); _cam.setDistance(1e-4); } else { _cam.setLookAt(_bounds.getCenter()); _cam.setDistance(_bounds.diagonal()); } } }
float BVH4i::sah (NodeRef& node, const BBox3f& bounds) { float f = bounds.empty() ? 0.0f : area(bounds); if (node.isNode()) { Node* n = node.node(nodePtr()); for (size_t c=0; c<4; c++) f += sah(n->child(c),n->bounds(c)); return f; } else { size_t num; node.leaf(triPtr(),num); return f*num; } }
void FallBackSplitter<Heuristic,PrimRefBlockList>::split(size_t threadIndex, PrimRefAlloc* alloc, const RTCGeometry* geom, PrimRefBlockList& prims, const PrimInfo& pinfo, PrimRefBlockList& lprims, PrimInfo& linfo, PrimRefBlockList& rprims, PrimInfo& rinfo) { /* enforce split */ size_t lnum = 0; BBox3f lgeomBounds = empty; BBox3f lcentBounds = empty; size_t rnum = 0; BBox3f rgeomBounds = empty; BBox3f rcentBounds = empty; atomic_set<PrimRefBlock>::item* lblock = lprims.insert(alloc->malloc(threadIndex)); atomic_set<PrimRefBlock>::item* rblock = rprims.insert(alloc->malloc(threadIndex)); while (atomic_set<PrimRefBlock>::item* block = prims.take()) { for (size_t i=0; i<block->size(); i++) { const PrimRef& prim = block->at(i); const BBox3f bounds = prim.bounds(); if ((lnum+rnum)&1) { lnum++; lgeomBounds.grow(bounds); lcentBounds.grow(center2(bounds)); if (likely(lblock->insert(prim))) continue; lblock = lprims.insert(alloc->malloc(threadIndex)); lblock->insert(prim); } else { rnum++; rgeomBounds.grow(bounds); rcentBounds.grow(center2(bounds)); if (likely(rblock->insert(prim))) continue; rblock = rprims.insert(alloc->malloc(threadIndex)); rblock->insert(prim); } } } new (&linfo) PrimInfo(lnum,lgeomBounds,lcentBounds); new (&rinfo) PrimInfo(rnum,rgeomBounds,rcentBounds); }
TEST(BBoxTest, repaired) { const BBox3f bounds (Vec3f( 3.0f, 4.0f, 0.0f), Vec3f(-1.0f, 0.0f, 1.0f)); const BBox3f repaired(Vec3f(-1.0f, 0.0f, 0.0f), Vec3f( 3.0f, 4.0f, 1.0f)); ASSERT_EQ(repaired, bounds.repaired()); }
TEST(BBoxTest, translated) { const BBox3f bounds (Vec3f(-12.0f, -3.0f, 4.0f), Vec3f( 8.0f, 9.0f, 8.0f)); const BBox3f translated(Vec3f(-10.0f, -4.0f, 1.0f), Vec3f(10.0f, 8.0f, 5.0f)); ASSERT_EQ(translated, bounds.translated(Vec3f(2.0f, -1.0f, -3.0f))); }
TEST(BBoxTest, expanded) { const BBox3f bounds (Vec3f(-12.0f, -3.0f, 4.0f), Vec3f( 8.0f, 9.0f, 8.0f)); const BBox3f expanded(Vec3f(-14.0f, -5.0f, 2.0f), Vec3f(10.0f, 11.0f, 10.0f)); ASSERT_EQ(expanded, bounds.expanded(2.0f)); }
void GLVoxelizerTripiana2009::initGLState(uint32_t resolution, BBox3f bbox, GLVoxelFramebuffer& framebuffer, Mat4f& gridToWorldMatrix) { auto v = bbox.upper - bbox.lower; auto bboxCenter = 0.5f * (bbox.lower + bbox.upper); // Grow of 5% the size of the bounding box to ensure that we don't miss any triangle that are at the edge bbox.lower = bboxCenter - 0.55f * v; bbox.upper = bboxCenter + 0.55f * v; auto m_res = resolution; // Requiered number of color buffer auto m_numRenderTargets = ceil((double)m_res / 128.0); auto bboxSize = bbox.size(); auto m_AABCLength = reduceMax(bboxSize); auto m_voxelLength = m_AABCLength / (float)m_res; auto m_origBBox = bboxCenter - glm::vec3(0.5f * m_AABCLength); gridToWorldMatrix = scale(translate(Mat4f(1.f), m_origBBox), glm::vec3(m_voxelLength)); // Use the shaders m_Program.use(); // Desactivate depth, cullface glDisable(GL_DEPTH_TEST); glDisable(GL_CULL_FACE); // Blending activated glEnable(GL_COLOR_LOGIC_OP); glLogicOp(GL_OR); // Init FrameBuffer if (!framebuffer.init(m_res, m_res, m_res, m_numRenderTargets)){ std::cerr << "FBO Error" << std::endl; } //Projection matrix : Adapt the viewport to the size of the mesh glm::mat4 P = glm::ortho(-m_AABCLength * 0.5f, m_AABCLength * 0.5f, -m_AABCLength * 0.5f, m_AABCLength * 0.5f, 0.f, m_AABCLength); glm::vec3 position(bboxCenter.x, bboxCenter.y, bboxCenter.z + 0.5 * m_AABCLength); glm::vec3 point(bboxCenter.x, bboxCenter.y, bboxCenter.z); glm::mat4 V = glm::lookAt(position, point, glm::vec3(0, 1, 0)); // Get the MVP Matrix glm::mat4 MVPMatrix = P * V; // Set uniforms MVP.set(MVPMatrix); halfPixelSize.set(Vec2f(1.f / m_res)); numVoxels.set(resolution); origBBox.set(m_origBBox); numRenderTargets.set(m_numRenderTargets); voxelSize.set(m_voxelLength); framebuffer.bind(GL_DRAW_FRAMEBUFFER); // Set the list of draw buffers. std::vector<GLenum> DrawBuffers(m_numRenderTargets, 0); for (int i = 0; i < m_numRenderTargets; ++i){ DrawBuffers[i] = GL_COLOR_ATTACHMENT0 + i; } glDrawBuffers(m_numRenderTargets, DrawBuffers.data()); glViewport(0, 0, m_res, m_res); // Clear the window glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); }
TEST(BBoxTest, containsPoint) { const BBox3f bounds(Vec3f(-12.0f, -3.0f, 4.0f), Vec3f( 8.0f, 9.0f, 8.0f)); ASSERT_TRUE(bounds.contains(Vec3f(2.0f, 1.0f, 7.0f))); ASSERT_TRUE(bounds.contains(Vec3f(-12.0f, -3.0f, 7.0f))); ASSERT_FALSE(bounds.contains(Vec3f(-13.0f, -3.0f, 7.0f))); }
TEST(BBoxTest, translatedToOrigin) { const BBox3f bounds (Vec3f(-12.0f, -3.0f, 4.0f), Vec3f( 8.0f, 9.0f, 8.0f)); const BBox3f translated(Vec3f(-10.0f, -6.0f, -2.0f), Vec3f(10.0f, 6.0f, 2.0f)); ASSERT_EQ(translated, bounds.translatedToOrigin()); }