SpatialMarkup SpatialConvex::triangleTest(uint64 id) { SpatialMarkup mark; // // do the face test on the triangle mark = testNode(V(NV(0)),V(NV(1)),V(NV(2))); // do we have a final result code? // if rEJECT, fULL then return if(mark > fULL) return mark; if(mark == fULL) { fillChildren(id); // propagate final result to children return mark; } // if pARTIAL or dONTKNOW, then continue, test children, // but do not reach beyond the leaf nodes. // If Convex is fully contained within one (sWALLOWED), // we can stop looking further in another child if (NC(id,0)!=0) { triangleTest(NC(id,0)); triangleTest(NC(id,1)); triangleTest(NC(id,2)); triangleTest(NC(id,3)); // we are at the leafnodes // If we have to recurse further, calculate intersections one by one // If not, just set the proper bit in partial_ or append id to plist_. } else { if(addlevel_) { // from now on, continue to build the triangles dynamically. // until maxlevel_ levels depth. testPartial(addlevel_, N(id).id_, V(NV(0)), V(NV(1)), V(NV(2))); } else { if(bitresult_) partial_->set((uint32)index_->leafNumberById(N(id).id_),true); else plist_->append(N(id).id_); } } return mark; }
void VoxelTree::fillChildren(const Surface &sur, const SpacialHash &faceHash, const SpacialHash &faceHashHiRes, int levelNum, int pX, int pY, int pZ, const Array<int> &tris, int numLevels, const Point3D &PMIN, float eL){ // for each voxel for (int x = 0; x < 2; x++){ int cX = pX*2 + x; for (int y = 0; y < 2; y++){ int cY = pY*2 + y; for (int z = 0; z < 2; z++){ int cZ = pZ*2 + z; Point3D pMin; pMin.x = PMIN.x + cX * eL; pMin.y = PMIN.y + cY * eL; pMin.z = PMIN.z + cZ * eL; // test if the cell is an edge cell Array<int> subTris; filterTriangles(&subTris, tris, sur, pMin, eL); if (subTris.getSize()){ if (levelNum == numLevels-1) level.setFlag(cX, cY, cZ, VL_FLAG_EDGE); else fillChildren(sur, faceHash, faceHashHiRes, levelNum+1, cX, cY, cZ, subTris, numLevels, PMIN, eL/2.0); } else{ // test if the cell is inside the object Point3D pMid; pMid.x = PMIN.x + (cX + 0.5)* eL; pMid.y = PMIN.y + (cY + 0.5)* eL; pMid.z = PMIN.z + (cZ + 0.5)* eL; bool in = ::insideSurface(pMid, sur, faceHash, faceHashHiRes); char flag = in? VL_FLAG_INTERNAL : VL_FLAG_OUTSIDE; if (levelNum == numLevels-1) level.setFlag(cX, cY, cZ, flag); else fillFlags(levelNum+1, cX, cY, cZ, flag, numLevels); } } } } }
/////////////FILLCHILDREN///////////////////////////////// // fillChildren: mark children as full // void SpatialConvex::fillChildren(uint64 id) { if(range_) plist_->append(N(id).id_); else { if(NC(id,0)!=0) { for(size_t i = 0; i < 4; i++) { fillChildren(NC(id,i)); } } else { // we are at the leaf. If we still have levels to recurse, // fill them. If not, just set the full_ bitlist's or flist_ list's // value correctly. if(addlevel_) setfull(N(id).id_,addlevel_); else { if(bitresult_) full_->set((uint32)index_->leafNumberById(N(id).id_), true); else flist_->append(N(id).id_); } } } }
void VoxelTree::setup(const Surface &sur, const SpacialHash &faceHash, const SpacialHash &faceHashHiRes, int numLevels){ this->sur = &sur; this->faceHash = &faceHash; this->faceHashHiRes = &faceHashHiRes; // work out the bounding box Point3D pMin = sur.pMin; float lX = sur.pMax.x - sur.pMin.x; float lY = sur.pMax.y - sur.pMin.y; float lZ = sur.pMax.z - sur.pMin.z; float l = lX; if (lY > l) l = lY; if (lZ > l) l = lZ; // create the levels int d = pow(2, numLevels); level.setup(pMin, l, d); // initialise the list of triangle Array<int> tris; int numTris = sur.triangles.getSize(); tris.resize(numTris); for (int i = 0; i < numTris; i++) tris.index(i) = i; // fill the levels fillChildren(sur, faceHash, faceHashHiRes, 0, 0, 0, 0, tris, numLevels, pMin, l/2.0); // verify lowest set of cells /*{ const VoxelLevel *vl = &level; float eL = vl->getLength(); int d = vl->getD(); OUTPUTINFO("d = %d\n", d); for (int i = 0; i < d; i++){ for (int j = 0; j < d; j++){ for (int k = 0; k < d; k++){ char flag = vl->getFlag(i, j, k); Point3D pMin; vl->getMinPt(&pMin, i, j, k); Point3D pMid; vl->getMidPt(&pMid, i, j, k); char flag1 = vl->getFlag(pMid); if (flag1 != flag) OUTPUTINFO("Test Fail : %d %d\n", flag, flag1); Array<int> selTri; filterTriangles(&selTri, tris, sur, pMin, eL); OUTPUTINFO("%d Triangles\n", selTri.getSize()); if (selTri.getSize()){ // EDGE if (flag != VL_FLAG_EDGE) OUTPUTINFO("Should be VL_FLAG_EDGE was (%d)\n", flag); } else{ // IN/OUT bool in = ::insideSurface(pMid, sur, sh); if (in && flag != VL_FLAG_INTERNAL) OUTPUTINFO("Should be VL_FLAG_INTERNAL was (%d)\n", flag); else if (!in && flag != VL_FLAG_OUTSIDE) OUTPUTINFO("Should be VL_FLAG_INTERNAL was (%d)\n", flag); } } } } }*/ }