void octreeSolid::intersectWithBox(octreeSNode* node, Vec3f &ldf, Vec3f &ruf, arrayInt &idxs) { if (!node) { return; } GeometricFunc geoFc; Box boxNode(node->leftDownTight, node->rightUpTight); if (geoFc.collisionBtwBox(Box(ldf, ruf), boxNode)) { if (node->bEnd && geoFc.isPointInBox(ldf, ruf, boxNode.center)) { // Sine boxIn may slightly cover the node box, we check the center point idxs.push_back(node->idxInLeaf); } else { for (int i = 0; i < 8; i++) { intersectWithBox(node->children[i], ldf, ruf, idxs); } } } }
bool octreeSolid::isColidWithBox(octreeSNode* node, Box &b) { GeometricFunc geoF; if (geoF.collisionBtwBox(b, Box(node->leftDownTight, node->rightUpTight))) { if (node->bEnd) { if (geoF.isPointInBox(b.leftDown, b.rightUp, (node->leftDownTight+node->rightUpTight)/2)) { return true; } return false; } else { for (int i = 0; i < 8; i++) { if (node->children[i]) { if (isColidWithBox(node->children[i], b)) { return true; } } } return false; } } else return false; }
void octreeSolid::constructTreeRecur(octreeSNode * node, int depth) { // Stop at leaf if (node->nodeDepth == depth) { node->bEnd = true; leaves.push_back(node); return; } Vec3f mid = (node->leftDownf + node->rightUpf)/2; std::vector<Box> boxes = get8ChildrenBox(node->leftDownf, node->rightUpf); GeometricFunc geoFunc; for (int i = 0; i < 8; i++) { if (isSurfIntersectWithBox(sufObj, boxes[i]) || geoFunc.isPointInSurf(sufObj->point(), sufObj->face(), sufObj->getBVH()->root(), boxes[i].center)) { octreeSNode* newN = new octreeSNode; newN->leftDownf = boxes[i].leftDown; newN->rightUpf = boxes[i].rightUp; newN->nodeDepth = node->nodeDepth+1; newN->parent = node; node->children[i] = newN; constructTreeRecur(newN, depth); } else { node->children[i] = nullptr; } } }
neighborPos poseManager::possibleNeighbor(meshPiece* parent, meshPiece* child) { // To be neighbor, they should be in contact or there is no other box between them // Best is to check overlap. maximum is the size of voxel GeometricFunc geoF; Vec3f diag(voxelSizef, voxelSizef, voxelSizef); if(geoF.collisionBtwBox(Box(parent->leftDown, parent->rightUp), Box(child->leftDown - diag/2.0, child->rightUp + diag/2.0))) { Vec3f parentLD = parent->leftDown; Vec3f parentRU = parent->rightUp; Vec3f childLD = child->leftDown; Vec3f childRU = child->rightUp; neighborPos *pp = posArray(); float error = 0.001*voxelSizef; for (int xyzd = 0; xyzd < 3; xyzd++) // Test on three direction { // Check if Plus if (childLD[xyzd] > parentRU[xyzd]-error) { return pp[xyzd * 2]; } if (childRU[xyzd] < parentLD[xyzd] + error) { return pp[xyzd * 2 + 1]; } } } return NONE_NB; }
void ReTriangulation::legalizeTriangle(Vec3f point[], Vec3i& face, Vec3f& normal) { GeometricFunc func; Vec3f n=func.computeNormal(point); if(n*normal<0) { int temp=face[1]; face[1]=face[2]; face[2]=temp; } }
void ReTriangulation::legalizeTriangle(std::vector<Vec3f>* point, Vec3i& face, Vec3f& normal) { GeometricFunc func; Vec3f n=func.computeNormal(point, face); if(n*normal<0) { int temp=face[1]; face[1]=face[2]; face[2]=temp; } }
neighborPos poseGroupCutManager::possibleNeighbor(meshPiece* parent, meshPiece* child) { // To be neighbor, they should be in contact or there is no other box between them // Best is to check overlap. maximum is the size of voxel GeometricFunc geoF; Vec3f diag(voxelSizef, voxelSizef, voxelSizef); // Otherwise, use center distance if (geoF.collisionBtwBox(Box(parent->leftDown, parent->rightUp), Box(child->leftDown - diag / 2.0, child->rightUp + diag / 2.0))) { // If have face contact int direct; if (geoF.isBoxFaceContactBox(Box(parent->leftDown, parent->rightUp), Box(child->leftDown, child->rightUp), direct)) { int p = direct*2; if (parent->leftDown[direct] > child->leftDown[direct]) { p++; } return (neighborPos)p; } else { Vec3f pSizef = parent->rightUp - parent->leftDown; Vec3f centerP = (parent->rightUp + parent->leftDown) / 2.0; Vec3f centerC = (child->rightUp + child->leftDown) / 2.0; Vec3f dd = centerC - centerP; // scale float longest = 0; int idx = -1; for (int j = 0; j < 3; j++) { dd[j] = dd[j] / (pSizef[j] / 2.0); if (longest < abs(dd[j])) { longest = abs(dd[j]); idx = j; } } neighborPos *pp = posArray(); if (dd[idx] > 0) return pp[idx * 2]; // plus axis direction else return pp[idx * 2 + 1]; // minus axis direction } } return NONE_NB; }
bool octreeSolid::isSurfIntersectWithBox(SurfaceObj * sufObj, Box boxf) { CollisionManager colMngr; if (colMngr.isSurfaceWithAABBIntersectBox(sufObj->getBVH()->root(), boxf, sufObj->point(), sufObj->face())) { return true; } else { GeometricFunc geoFunc; if (geoFunc.isPointInSurf(sufObj->point(), sufObj->face(), sufObj->getBVH()->root(), (boxf.leftDown+boxf.rightUp)/2)) { return true; // For optimization, all of it children should automatically set as inside } return false; } }
int manipulateVoxel::getNearestNeighborBox(int voxelIdx) { arrayInt vShareFace = s_voxelObj->m_boxShareFaceWithBox[voxelIdx]; int boxIdxNeareast = -1; float nearest = MAX; std::vector<voxelBox> *boxes = &s_voxelObj->m_boxes; for (auto nbIdx : vShareFace) { arrayInt listMeshIdxs = m_voxelState[nbIdx]; if (m_hashBoxIdx[nbIdx] != -1) { listMeshIdxs.push_back(m_hashBoxIdx[nbIdx]); } for (auto mIdx : listMeshIdxs) { // Compute distance Vec3f center = meshBox[mIdx]->centerPoint(); Vec3f size3F = meshBox[mIdx]->m_BoxSize3F*curScaleF; Vec3f ld3F = center - size3F / 2; Vec3f ru3F = center + size3F / 2; GeometricFunc geoFunc; float dis = geoFunc.disBtwPointAndBox(Box(ld3F, ru3F), boxes->at(voxelIdx).center); if (dis < nearest) { nearest = dis; boxIdxNeareast = mIdx; } } } return boxIdxNeareast; }
void octreeSolid::intersectWithBox(octreeSNode* node, meshPiece &boxOut, meshPiece &boxIn) { if (!node) return; GeometricFunc geoFc; BOOL isInside; if (geoFc.isBoxInBox(boxIn.leftDown, boxIn.rightUp, node->leftDownTight, node->rightUpTight)) { // Cover entirely. Fit intersect box boxOut.volumef += node->volumef; enlargerToCoverBox(boxOut, node->leftDownTight, node->rightUpTight); } else { Box boxNode(node->leftDownTight, node->rightUpTight); if(geoFc.collisionBtwBox(Box(boxIn.leftDown, boxIn.rightUp), boxNode)) { if (node->bEnd && geoFc.isPointInBox(boxIn.leftDown, boxIn.rightUp, boxNode.center)) { // Sine boxIn may slightly cover the node box, we check the center point boxOut.volumef += node->volumef; enlargerToCoverBox(boxOut, node->leftDownTight, node->rightUpTight); } else { for (int i = 0; i < 8; i++) { intersectWithBox(node->children[i], boxOut, boxIn); } } } } }
int manipulateVoxel::getNearestBox(int voxelIdx) { std::vector<voxelBox> *boxes = &s_voxelObj->m_boxes; float smallest = MAX; int idxSmallest; for (int i = 0; i < meshBox.size(); i++) { Vec3f center = meshBox[i]->centerPoint(); Vec3f size3F = meshBox[i]->m_BoxSize3F*curScaleF; Vec3f ld3F = center - size3F / 2; Vec3f ru3F = center + size3F / 2; GeometricFunc geoFunc; float dis = geoFunc.disBtwPointAndBox(Box(ld3F, ru3F), boxes->at(voxelIdx).center); if (dis < smallest) { smallest = dis; idxSmallest = i; } } return idxSmallest; }
void octreeSolid::intersectWithBox(octreeSNode* node, Box boxIn, Box &intersectBox, float &volumeSide) { if (!node) return; GeometricFunc geoFc; BOOL isInside; if (geoFc.isBoxInBox(boxIn.leftDown, boxIn.rightUp, node->leftDownTight, node->rightUpTight)) { // Cover entirely. Fit intersect box volumeSide += node->volumef; geoFc.fitBoxToCoverBox(intersectBox, node->leftDownTight, node->rightUpTight); } else { Box boxNode(node->leftDownTight, node->rightUpTight); if(geoFc.collisionBtwBox(boxIn, boxNode)) { if (node->bEnd && geoFc.isPointInBox(boxIn.leftDown, boxIn.rightUp, boxNode.center)) { // Sine boxIn may slightly cover the node box, we check the center point volumeSide += node->volumef; geoFc.fitBoxToCoverBox(intersectBox, node->leftDownTight, node->rightUpTight); } else { for (int i = 0; i < 8; i++) { intersectWithBox(node->children[i], boxIn, intersectBox, volumeSide); } } } } }
void ReTriangulation::delaunayTriangulation(std::vector<Vec3f>* point, Vec3i face, std::vector<int>& idx, std::vector<int>& pointOnEdge, std::vector<int>& pointOnFace, std::vector<Vec3i>& triangles, int preNbPoint) { GeometricFunc func; std::vector<std::vector<int>> trianglesAroundEdge; std::vector<std::vector<int>> edgesInTriangle; std::vector<Vec2i> edges; Vec3f normal=func.computeNormal(point, face); triangles.push_back(face); for(int i=0;i<pointOnEdge.size();i++) { for(int j=0;j<triangles.size();j++) { int edgeIdx=-1; for(int k=0;k<3;k++) { Vec3f l1=(*point)[triangles[j][k]]; Vec3f l2=(*point)[triangles[j][(k+1)%3]]; Vec3f p=(*point)[pointOnEdge[i]]; if(func.isPointInLine(l1, l2, p)) { edgeIdx=(k+2)%3; break; } } if(edgeIdx>-1) { //add triangles and edges triangles.push_back(Vec3i(triangles[j][(edgeIdx+1)%3], pointOnEdge[i], triangles[j][edgeIdx])); triangles.push_back(Vec3i(pointOnEdge[i], triangles[j][(edgeIdx+2)%3], triangles[j][edgeIdx])); //remove triangle triangles[j]=triangles[triangles.size()-1]; triangles.pop_back(); break; } } } for(int i=0;i<pointOnFace.size();i++) { int count=0; for(int j=0;j<triangles.size();j++) { int edgeIdx=-1; for(int k=0;k<3;k++) { Vec3f l1=(*point)[triangles[j][k]]; Vec3f l2=(*point)[triangles[j][(k+1)%3]]; Vec3f p=(*point)[pointOnFace[i]]; if(func.isPointInLine(l1, l2, p)) { edgeIdx=(k+2)%3; break; } } if(edgeIdx>-1) { //add triangles and edges triangles.push_back(Vec3i(triangles[j][(edgeIdx+1)%3], pointOnFace[i], triangles[j][edgeIdx])); triangles.push_back(Vec3i(pointOnFace[i], triangles[j][(edgeIdx+2)%3], triangles[j][edgeIdx])); //remove triangle triangles[j]=triangles[triangles.size()-1]; triangles.pop_back(); count++; if(count>1) break; } else if(func.isPointInTri(point, triangles[j], pointOnFace[i])) { //add triangles triangles.push_back(Vec3i(pointOnFace[i], triangles[j][0], triangles[j][1])); triangles.push_back(Vec3i(pointOnFace[i], triangles[j][1], triangles[j][2])); triangles.push_back(Vec3i(pointOnFace[i], triangles[j][2], triangles[j][0])); //remove triangle triangles[j]=triangles[triangles.size()-1]; triangles.pop_back(); int triIdx=triangles.size()-2; legalizeEdge(point, pointOnFace[i], Vec2i(triangles[triIdx][1], triangles[triIdx][2]), triIdx, triangles); triIdx=triangles.size()-1; legalizeEdge(point, pointOnFace[i], Vec2i(triangles[triIdx][1], triangles[triIdx][2]), triIdx, triangles); triIdx=j; legalizeEdge(point, pointOnFace[i], Vec2i(triangles[triIdx][1], triangles[triIdx][2]), triIdx, triangles); break; } } } for(int i=0;i<idx.size();i++) { for(int j=0;j<triangles.size();j++) { for(int k=0;k<3;k++) { if(triangles[j][k]==idx[i]) { triangles[j]=triangles[triangles.size()-1]; triangles.pop_back(); j--; break; } } } } }
int ReTriangulation::legalizeEdge(std::vector<Vec3f>* point, int pointIdx, Vec2i edge, int triIdx, std::vector<Vec3i>& triangles) { GeometricFunc func; int _triIdx; int _pointIdx; bool flag=true; //1. find the triangle that contains the edge for(int i=0;i<triangles.size();i++) { if(func.isTriangleContainEdge(edge, triangles[i])) { if(i!=triIdx) { _triIdx=i; for(int j=0;j<3;j++) { if((triangles[i][j]!=edge[0])&&(triangles[i][j]!=edge[1])) { _pointIdx=triangles[i][j]; break; } } flag=false; break; } } } if(flag) { return 0; } else { Vec3f faceNormal=func.computeNormal(point, triangles[_triIdx]); Vec3f circumCenter=func.computeCircumcenter(point, triangles[_triIdx], faceNormal); float radius=((*point)[edge[0]]-circumCenter).norm(); if(((*point)[pointIdx]-circumCenter).norm()<radius) { Vec3i face1=Vec3i(pointIdx, _pointIdx, edge[0]); Vec3i face2=Vec3i(pointIdx, _pointIdx, edge[1]); Vec3f normal1=func.computeNormal(point, face1); if(normal1*faceNormal<0) { int temp=face1[2]; face1[2]=face1[1]; face1[1]=temp; } else { int temp=face2[2]; face2[2]=face2[1]; face2[1]=temp; } //replace triangles triangles[triIdx]=face1; triangles[_triIdx]=face2; legalizeEdge(point, pointIdx, Vec2i(_pointIdx, edge[0]), triIdx, triangles); legalizeEdge(point, pointIdx, Vec2i(_pointIdx, edge[1]), _triIdx, triangles); } } return 0; }
void ReTriangulation::legalizeEdge(std::vector<Vec3f>* point, std::vector<Vec2i>& illegalEdge, std::vector<Vec3i>& triangles) { GeometricFunc func; int i=0; while(1) { if(illegalEdge.empty()) break; std::vector<int> triIdx; std::vector<int> pointIdx; if(illegalEdge.size()<=i) i=0; Vec2i edge=illegalEdge[i]; // illegal한 edge를 포함하는 triangle들을 찾는다 for(int j=0;j<triangles.size();j++) { if(func.isTriangleContainEdge(illegalEdge[i], triangles[j])) { triIdx.push_back(j); for(int k=0;k<3;k++) { if((triangles[j][k]!=edge[0])&&(triangles[j][k]!=edge[1])) { pointIdx.push_back(triangles[j][k]); break; } } } } if(triIdx.size()==2) { // 새로 생기는 edge가 illegal edge인지 검사한다. Vec2i _edge(pointIdx[0], pointIdx[1]); bool flag=true; for(int j=0;j<illegalEdge.size();j++) { if(func.isEdgeSame(illegalEdge[j], _edge)) { flag=false; break; } } if(flag) { triangles[triIdx[0]]=Vec3i(pointIdx[0], pointIdx[1], edge[0]); triangles[triIdx[1]]=Vec3i(pointIdx[0], pointIdx[1], edge[1]); illegalEdge[i]=illegalEdge[illegalEdge.size()-1]; illegalEdge.pop_back(); i--; } } else { illegalEdge[i]=illegalEdge[illegalEdge.size()-1]; illegalEdge.pop_back(); i--; } i++; } }