void EdgeAdjacency::CreateTriangle(int32 startingI) { int32 i = startingI; int32 i0, i1, i2; polygonGroup->GetIndex(i, i0); polygonGroup->GetIndex(i+1, i1); polygonGroup->GetIndex(i+2, i2); Vector3 p0, p1, p2; polygonGroup->GetCoord(i0, p0); polygonGroup->GetCoord(i1, p1); polygonGroup->GetCoord(i2, p2); Edge edge0; FillEdge(edge0, i0, i1); int32 edgeIndex0 = GetEdgeIndex(edge0); Edge edge1; FillEdge(edge1, i1, i2); int32 edgeIndex1 = GetEdgeIndex(edge1); Edge edge2; FillEdge(edge2, i2, i0); int32 edgeIndex2 = GetEdgeIndex(edge2); TriangleData triangleData; triangleData.i0 = i0; triangleData.i1 = i1; triangleData.i2 = i2; if(edges[edgeIndex0].sharedTriangles.size() < 2) { edges[edgeIndex0].sharedTriangles.push_back(triangleData); } if(edges[edgeIndex1].sharedTriangles.size() < 2) { edges[edgeIndex1].sharedTriangles.push_back(triangleData); } if(edges[edgeIndex2].sharedTriangles.size() < 2) { edges[edgeIndex2].sharedTriangles.push_back(triangleData); } }
int IRefiner:: get_local_edge_mark(Face* f, Edge* e) const { const int edgeInd = GetEdgeIndex(f, e); UG_COND_THROW(edgeInd == -1, "Given edge is not an edge of the given face."); if(marked_local(f)){ const int faceLocalMark = get_local_mark(f); return (faceLocalMark >> edgeInd) & 1; } else if(marked_full(f)){
void HACD::CreateGraph() { // vertex to triangle adjacency information std::vector< std::set<long> > vertexToTriangles; vertexToTriangles.resize(m_nPoints); for(size_t t = 0; t < m_nTriangles; ++t) { vertexToTriangles[m_triangles[t].X()].insert(static_cast<long>(t)); vertexToTriangles[m_triangles[t].Y()].insert(static_cast<long>(t)); vertexToTriangles[m_triangles[t].Z()].insert(static_cast<long>(t)); } m_graph.Clear(); m_graph.Allocate(m_nTriangles, 5 * m_nTriangles); unsigned long long tr1[3]; unsigned long long tr2[3]; long i1, j1, k1, i2, j2, k2; long t1, t2; for (size_t v = 0; v < m_nPoints; v++) { std::set<long>::const_iterator it1(vertexToTriangles[v].begin()), itEnd(vertexToTriangles[v].end()); for(; it1 != itEnd; ++it1) { t1 = *it1; i1 = m_triangles[t1].X(); j1 = m_triangles[t1].Y(); k1 = m_triangles[t1].Z(); tr1[0] = GetEdgeIndex(i1, j1); tr1[1] = GetEdgeIndex(j1, k1); tr1[2] = GetEdgeIndex(k1, i1); std::set<long>::const_iterator it2(it1); for(++it2; it2 != itEnd; ++it2) { t2 = *it2; i2 = m_triangles[t2].X(); j2 = m_triangles[t2].Y(); k2 = m_triangles[t2].Z(); tr2[0] = GetEdgeIndex(i2, j2); tr2[1] = GetEdgeIndex(j2, k2); tr2[2] = GetEdgeIndex(k2, i2); int shared = 0; for(int i = 0; i < 3; ++i) { for(int j = 0; j < 3; ++j) { if (tr1[i] == tr2[j]) { shared++; } } } if (shared == 1) // two triangles are connected if they share exactly one edge { m_graph.AddEdge(t1, t2); } } } } if (m_ccConnectDist >= 0.0) { m_graph.ExtractCCs(); if (m_callBack) { char msg[1024]; sprintf(msg, "nCC %lu\n", static_cast<long unsigned int>(m_graph.m_nCCs)); (*m_callBack)(msg, 0.0, 0.0, m_graph.GetNVertices()); } if (m_graph.m_nCCs > 1) { std::vector< std::set<long> > cc2V; cc2V.resize(m_graph.m_nCCs); long cc; for(size_t t = 0; t < m_nTriangles; ++t) { cc = m_graph.m_vertices[t].m_cc; cc2V[cc].insert(m_triangles[t].X()); cc2V[cc].insert(m_triangles[t].Y()); cc2V[cc].insert(m_triangles[t].Z()); } for(size_t cc1 = 0; cc1 < m_graph.m_nCCs; ++cc1) { for(size_t cc2 = cc1+1; cc2 < m_graph.m_nCCs; ++cc2) { std::set<long>::const_iterator itV1(cc2V[cc1].begin()), itVEnd1(cc2V[cc1].end()); for(; itV1 != itVEnd1; ++itV1) { double distC1C2 = std::numeric_limits<double>::max(); double dist; t1 = -1; t2 = -1; std::set<long>::const_iterator itV2(cc2V[cc2].begin()), itVEnd2(cc2V[cc2].end()); for(; itV2 != itVEnd2; ++itV2) { dist = (m_points[*itV1] - m_points[*itV2]).GetNorm(); if (dist < distC1C2) { distC1C2 = dist; t1 = *vertexToTriangles[*itV1].begin(); std::set<long>::const_iterator it2(vertexToTriangles[*itV2].begin()), it2End(vertexToTriangles[*itV2].end()); t2 = -1; for(; it2 != it2End; ++it2) { if (*it2 != t1) { t2 = *it2; break; } } } } if (distC1C2 <= m_ccConnectDist && t1 >= 0 && t2 >= 0) { m_graph.AddEdge(t1, t2); } } } } } } }
void HACD::InitializeDualGraph() { long i, j, k; Vec3<Real> u, v, w, normal; delete [] m_normals; m_normals = new Vec3<Real>[m_nPoints]; if (m_addFacesPoints) { delete [] m_facePoints; delete [] m_faceNormals; m_facePoints = new Vec3<Real>[m_nTriangles]; m_faceNormals = new Vec3<Real>[m_nTriangles]; /* m_facePoints = new Vec3<Real>[4*m_nTriangles]; m_faceNormals = new Vec3<Real>[4*m_nTriangles]; */ } memset(m_normals, 0, sizeof(Vec3<Real>) * m_nPoints); RaycastMesh rm; if (m_addExtraDistPoints) { rm.Initialize(m_nPoints, m_nTriangles, m_points, m_triangles, 15); m_extraDistPoints = new Vec3<Real>[m_nTriangles]; m_extraDistNormals = new Vec3<Real>[m_nTriangles]; } double progressOld = -1.0; double progress = 0.0; char msg[1024]; double ptgStep = 1.0; m_area = 0.0; for(unsigned long f = 0; f < m_nTriangles; f++) { progress = f * 100.0 / m_nTriangles; if (fabs(progress-progressOld) > ptgStep && m_callBack) { sprintf(msg, "%3.2f %% \t \t \r", progress); (*m_callBack)(msg, progress, 0.0, m_nTriangles); progressOld = progress; } i = m_triangles[f].X(); j = m_triangles[f].Y(); k = m_triangles[f].Z(); m_graph.m_vertices[f].m_distPoints.PushBack(DPoint(i, 0, false, false)); m_graph.m_vertices[f].m_distPoints.PushBack(DPoint(j, 0, false, false)); m_graph.m_vertices[f].m_distPoints.PushBack(DPoint(k, 0, false, false)); ICHull * ch = new ICHull(m_heapManager); m_graph.m_vertices[f].m_convexHull = ch; ch->AddPoint(m_points[i], i); ch->AddPoint(m_points[j], j); ch->AddPoint(m_points[k], k); ch->SetDistPoints(0); u = m_points[j] - m_points[i]; v = m_points[k] - m_points[i]; w = m_points[k] - m_points[j]; normal = u ^ v; m_normals[i] += normal; m_normals[j] += normal; m_normals[k] += normal; m_graph.m_vertices[f].m_surf = normal.GetNorm(); m_area += m_graph.m_vertices[f].m_surf; normal.Normalize(); m_graph.m_vertices[f].m_boudaryEdges.Insert(GetEdgeIndex(i,j)); m_graph.m_vertices[f].m_boudaryEdges.Insert(GetEdgeIndex(j,k)); m_graph.m_vertices[f].m_boudaryEdges.Insert(GetEdgeIndex(k,i)); if(m_addFacesPoints) { m_faceNormals[f] = normal; m_facePoints[f] = (m_points[i] + m_points[j] + m_points[k]) / 3.0; m_graph.m_vertices[f].m_distPoints.PushBack(DPoint(-static_cast<long>(f)-1, 0, false, true)); } } // Now we have all the points in the KD tree, optimize the distance points insertion by running them in parallel // if possible. if (m_addExtraDistPoints) { if (m_callBack) (*m_callBack)("++ Also adding distance points\n", 0.0, 0.0, 0); progressOld = -1.0; progress = 0.0; long completed = 0; #ifdef THREAD_DIST_POINTS #pragma omp parallel for #endif for(long f = 0; f < (long)m_nTriangles; f++) { Vec3<Real> seedPoint((m_points[i] + m_points[j] + m_points[k]) / 3.0); Vec3<Real> hitPoint; Vec3<Real> hitNormal; normal = -normal; size_t faceIndex = m_nTriangles; Float dist; long hitTriangle; if (rm.Raycast(seedPoint,normal,hitTriangle,dist, hitPoint, hitNormal)) { faceIndex = hitTriangle; } if (faceIndex < m_nTriangles ) { m_extraDistPoints[f] = hitPoint; m_extraDistNormals[f] = hitNormal; m_graph.m_vertices[f].m_distPoints.PushBack(DPoint(m_nPoints+f, 0, false, true)); } // Atomic update of the progress #ifdef THREAD_DIST_POINTS #pragma omp critical #endif { completed++; progress = completed * 100.0 / m_nTriangles; if (fabs(progress-progressOld) > ptgStep && m_callBack) { sprintf(msg, "%3.2f %% \t \t \r", progress); (*m_callBack)(msg, progress, 0.0, m_nTriangles); progressOld = progress; } } } } for (size_t v = 0; v < m_nPoints; v++) { m_normals[v].Normalize(); } }
StrBuf* GenLynxSprite (const Bitmap* B, const Collection* A) /* Generate binary output in Lynx sprite format for the bitmap B. The output * is stored in a string buffer (which is actually a dynamic char array) and * returned. * * The Lynx will draw 4 quadrants: * - Down right * - Up right * - Up left * - Down left * * The sprite will end with a byte 0. */ { enum Mode M; StrBuf* D; signed X, Y; unsigned OX, OY; char ColorBits; char ColorMask; char EdgeIndex; /* Get EdgeIndex */ EdgeIndex = GetEdgeIndex (A); /* Action point of the sprite */ OX = GetActionPointX (A); OY = GetActionPointY (A); if (OX >= GetBitmapWidth (B)) { Error ("Action point X cannot be larger than bitmap width"); } if (OY >= GetBitmapHeight (B)) { Error ("Action point Y cannot be larger than bitmap height"); } printf("OX = %d OY = %d\n", OX, OY); /* Output the image properties */ Print (stdout, 1, "Image is %ux%u with %u colors%s\n", GetBitmapWidth (B), GetBitmapHeight (B), GetBitmapColors (B), BitmapIsIndexed (B)? " (indexed)" : ""); /* Get the sprite mode */ M = GetMode (A); /* Now check if bitmap indexes are ok */ if (GetBitmapColors (B) > 16) { Error ("Too many colors for a Lynx sprite"); } ColorBits = 4; ColorMask = 0x0f; if (GetBitmapColors (B) < 9) { ColorBits = 3; ColorMask = 0x07; } if (GetBitmapColors (B) < 5) { ColorBits = 2; ColorMask = 0x03; } if (GetBitmapColors (B) < 3) { ColorBits = 1; ColorMask = 0x01; } /* Create the output buffer and resize it to the required size. */ D = NewStrBuf (); SB_Realloc (D, 63); /* Convert the image for quadrant bottom right */ for (Y = OY; Y < (signed)GetBitmapHeight (B); ++Y) { signed i = 0; signed LastOpaquePixel = -1; char LineBuffer[512]; /* The maximum size is 508 pixels */ /* Fill the LineBuffer for easier optimisation */ for (X = OX; X < (signed)GetBitmapWidth (B); ++X) { /* Fetch next bit into byte buffer */ LineBuffer[i] = GetPixel (B, X, Y).Index & ColorMask; if (LineBuffer[i] != EdgeIndex) { LastOpaquePixel = i; } ++i; } encodeSprite(D, M, ColorBits, ColorMask, LineBuffer, i, LastOpaquePixel); } if ((OY == 0) && (OX == 0)) { /* Trivial case only one quadrant */ /* Mark end of sprite */ SB_AppendChar (D, 0); /* Return the converted bitmap */ return D; } /* Next quadrant */ SB_AppendChar (D, 1); /* Convert the image for quadrant top right */ for (Y = OY - 1; Y >= 0; --Y) { signed i = 0; signed LastOpaquePixel = -1; char LineBuffer[512]; /* The maximum size is 508 pixels */ /* Fill the LineBuffer for easier optimisation */ for (X = OX; X < (signed)GetBitmapWidth (B); ++X) { /* Fetch next bit into byte buffer */ LineBuffer[i] = GetPixel (B, X, Y).Index & ColorMask; if (LineBuffer[i] != EdgeIndex) { LastOpaquePixel = i; } ++i; } encodeSprite(D, M, ColorBits, ColorMask, LineBuffer, i, LastOpaquePixel); } if (OX == 0) { /* Special case only two quadrants */ /* Mark end of sprite */ SB_AppendChar (D, 0); /* Return the converted bitmap */ return D; } /* Next quadrant */ SB_AppendChar (D, 1); /* Convert the image for quadrant top left */ for (Y = OY - 1; Y >= 0; --Y) { signed i = 0; signed LastOpaquePixel = -1; char LineBuffer[512]; /* The maximum size is 508 pixels */ /* Fill the LineBuffer for easier optimisation */ for (X = OX - 1; X >= 0; --X) { /* Fetch next bit into byte buffer */ LineBuffer[i] = GetPixel (B, X, Y).Index & ColorMask; if (LineBuffer[i] != EdgeIndex) { LastOpaquePixel = i; } ++i; } encodeSprite(D, M, ColorBits, ColorMask, LineBuffer, i, LastOpaquePixel); } /* Next quadrant */ SB_AppendChar (D, 1); /* Convert the image for quadrant bottom left */ for (Y = OY; Y < (signed)GetBitmapHeight (B); ++Y) { signed i = 0; signed LastOpaquePixel = -1; char LineBuffer[512]; /* The maximum size is 508 pixels */ /* Fill the LineBuffer for easier optimisation */ for (X = OX - 1; X >= 0; --X) { /* Fetch next bit into byte buffer */ LineBuffer[i] = GetPixel (B, X, Y).Index & ColorMask; if (LineBuffer[i] != EdgeIndex) { LastOpaquePixel = i; } ++i; } encodeSprite(D, M, ColorBits, ColorMask, LineBuffer, i, LastOpaquePixel); } /* End sprite */ SB_AppendChar (D, 0); /* Return the converted bitmap */ return D; }
void HACD::InitializeDualGraph() { long i, j, k; Vec3<Real> u, v, w, normal; delete [] m_normals; m_normals = new Vec3<Real>[m_nPoints]; if (m_addFacesPoints) { delete [] m_facePoints; delete [] m_faceNormals; m_facePoints = new Vec3<Real>[m_nTriangles]; m_faceNormals = new Vec3<Real>[m_nTriangles]; } memset(m_normals, 0, sizeof(Vec3<Real>) * m_nPoints); for(unsigned long f = 0; f < m_nTriangles; f++) { if (m_callBack) (*m_callBack)("+ InitializeDualGraph\n", f, m_nTriangles, 0); if (gCancelRequest) return; i = m_triangles[f].X(); j = m_triangles[f].Y(); k = m_triangles[f].Z(); m_graph.m_vertices[f].m_distPoints[i].m_distOnly = false; m_graph.m_vertices[f].m_distPoints[j].m_distOnly = false; m_graph.m_vertices[f].m_distPoints[k].m_distOnly = false; ICHull * ch = new ICHull; m_graph.m_vertices[f].m_convexHull = ch; ch->AddPoint(m_points[i], i); ch->AddPoint(m_points[j], j); ch->AddPoint(m_points[k], k); ch->SetDistPoints(&m_graph.m_vertices[f].m_distPoints); u = m_points[j] - m_points[i]; v = m_points[k] - m_points[i]; w = m_points[k] - m_points[j]; normal = u ^ v; m_normals[i] += normal; m_normals[j] += normal; m_normals[k] += normal; m_graph.m_vertices[f].m_surf = normal.GetNorm(); m_graph.m_vertices[f].m_perimeter = u.GetNorm() + v.GetNorm() + w.GetNorm(); normal.Normalize(); m_graph.m_vertices[f].m_boudaryEdges.insert(GetEdgeIndex(i,j)); m_graph.m_vertices[f].m_boudaryEdges.insert(GetEdgeIndex(j,k)); m_graph.m_vertices[f].m_boudaryEdges.insert(GetEdgeIndex(k,i)); if(m_addFacesPoints) { m_faceNormals[f] = normal; m_facePoints[f] = (m_points[i] + m_points[j] + m_points[k]) / 3.0; m_graph.m_vertices[f].m_distPoints[-static_cast<long>(f)-1].m_distOnly = true; } if (m_addExtraDistPoints) {// we need a kd-tree structure to accelerate this part! long i1, j1, k1; Vec3<Real> u1, v1, normal1; normal = -normal; double distance = 0.0; double distMin = 0.0; size_t faceIndex = m_nTriangles; Vec3<Real> seedPoint((m_points[i] + m_points[j] + m_points[k]) / 3.0); long nhit = 0; for(size_t f1 = 0; f1 < m_nTriangles; f1++) { i1 = m_triangles[f1].X(); j1 = m_triangles[f1].Y(); k1 = m_triangles[f1].Z(); u1 = m_points[j1] - m_points[i1]; v1 = m_points[k1] - m_points[i1]; normal1 = (u1 ^ v1); if (normal * normal1 > 0.0) { nhit = IntersectRayTriangle(Vec3<double>(seedPoint.X(), seedPoint.Y(), seedPoint.Z()), Vec3<double>(normal.X(), normal.Y(), normal.Z()), Vec3<double>(m_points[i1].X(), m_points[i1].Y(), m_points[i1].Z()), Vec3<double>(m_points[j1].X(), m_points[j1].Y(), m_points[j1].Z()), Vec3<double>(m_points[k1].X(), m_points[k1].Y(), m_points[k1].Z()), distance); if ((nhit==1) && ((distMin > distance) || (faceIndex == m_nTriangles))) { distMin = distance; faceIndex = f1; } } } if (faceIndex < m_nTriangles ) { i1 = m_triangles[faceIndex].X(); j1 = m_triangles[faceIndex].Y(); k1 = m_triangles[faceIndex].Z(); m_graph.m_vertices[f].m_distPoints[i1].m_distOnly = true; m_graph.m_vertices[f].m_distPoints[j1].m_distOnly = true; m_graph.m_vertices[f].m_distPoints[k1].m_distOnly = true; if (m_addFacesPoints) { m_graph.m_vertices[f].m_distPoints[-static_cast<long>(faceIndex)-1].m_distOnly = true; } } } } for (size_t v = 0; v < m_nPoints; v++) { m_normals[v].Normalize(); } }
void MakeContourFaces(Mesh * mesh, ContourPoint * v0, ContourPoint * v1, FlowLinePoint *v0child, FlowLinePoint *v1child) { if (v0 == NULL || v1 == NULL || v0child == NULL || v1child == NULL || v0child->stitchTarget == NULL || v1child->stitchTarget == NULL) return; // check if the flowlines cross if (!ParamPointCC::ConvexInChart(v0->vertex->GetData().sourceLoc, v0child->vertex->GetData().sourceLoc, v1child->vertex->GetData().sourceLoc, v1->vertex->GetData().sourceLoc)) // if (!ParamPointCC::SameSide(v0->vertex->GetData().sourceLoc, v0child->vertex->GetData().sourceLoc, // v1->vertex->GetData().sourceLoc, v1child->vertex->GetData().sourceLoc) && // !ParamPointCC::SameSide(v1->vertex->GetData().sourceLoc, v1child->vertex->GetData().sourceLoc, // v0->vertex->GetData().sourceLoc, v0child->vertex->GetData().sourceLoc)) { printf("WARNING: CROSSING FLOWLINES/NON-CONVEX FLOWLINE QUAD\n"); return; } assert(v0->vertex->GetData().facing == CONTOUR && v1->vertex->GetData().facing == CONTOUR && v0child->vertex->GetData().facing != CONTOUR && v1child->vertex->GetData().facing != CONTOUR); // find the common face that they came from MeshFace * commonFace = NULL; if (v0->sourceEdge->GetLeftFace() != NULL && (v0->sourceEdge->GetLeftFace() == v1->sourceEdge->GetLeftFace() || v0->sourceEdge->GetLeftFace() == v1->sourceEdge->GetRightFace())) commonFace = v0->sourceEdge->GetLeftFace(); else if (v0->sourceEdge->GetRightFace() != NULL && (v0->sourceEdge->GetRightFace() == v1->sourceEdge->GetLeftFace() || v0->sourceEdge->GetRightFace() == v1->sourceEdge->GetRightFace())) commonFace = v0->sourceEdge->GetRightFace(); assert(commonFace != NULL); double v0ind = GetEdgeIndex(commonFace, v0); double v1ind = GetEdgeIndex(commonFace, v1); int v0Cind = GetVertexIndex(commonFace, v0child->stitchTarget); int v1Cind = GetVertexIndex(commonFace, v1child->stitchTarget); for(int i=0; i<4; i++) printf("v[%d] = %s\n", i, FacingToString(commonFace->GetVertex(i)->GetData().facing)); assert(v0ind != v1ind); assert(v0Cind >= 0 && v0Cind <= 3 && v1Cind >= 0 && v1Cind <= 3); if (v0ind == 3.5 && v0Cind == 0) v0Cind = 4; if (v1ind == 3.5 && v1Cind == 0) v1Cind = 4; printf("v0: %08X, v1: %08X, v0ind: %f, v1ind: %f, v0Cind: %d, v1Cind: %d\n", v0, v1, v0ind, v1ind, v0Cind, v1Cind); assert(v0child->vertex->GetEdge(v1child->vertex) == NULL && v1child->vertex->GetEdge(v0child->vertex) == NULL); if (v0ind > v0Cind) { if ( v1ind < v1Cind) { printf("A: %08X, B: %08X\n", v0->vertex->GetEdge(v1->vertex), v1->vertex->GetEdge(v0->vertex)); NewFaceDebug(mesh, v0->vertex, v1->vertex, v1child->vertex); NewFaceDebug(mesh, v0->vertex, v1child->vertex, v0child->vertex); // int vIDa[3] = { v0->vertex->GetID(), v1->vertex->GetID(), v1child->vertex->GetID() }; // int vIDb[3] = { v0->vertex->GetID(), v1child->vertex->GetID(), v0child->vertex->GetID() }; // NewFaceDebug(mesh, 3, vIDa); // NewFaceDebug(mesh, 3, vIDb); // newFaces.push_back(FaceRec(v0->vertex, v1->vertex, v1child->vertex)); // newFaces.push_back(FaceRec(v0->vertex, v1child->vertex, v0child->vertex)); } else printf("WARNING: SKIPPING MESSED-UP TRIANGLE\n"); } else { if (v1ind > v1Cind) { printf("C: %08X, D: %08X\n", v0->vertex->GetEdge(v1->vertex), v1->vertex->GetEdge(v0->vertex)); NewFaceDebug(mesh, v1->vertex, v0->vertex, v0child->vertex); NewFaceDebug(mesh, v1->vertex, v0child->vertex, v1child->vertex); // int vIDa[3] = { v1->vertex->GetID(), v0->vertex->GetID(), v0child->vertex->GetID() }; // int vIDb[3] = { v1->vertex->GetID(), v0child->vertex->GetID(), v1child->vertex->GetID() }; // NewFaceDebug(mesh, 3, vIDa); // NewFaceDebug(mesh, 3, vIDb); // newFaces.push_back(FaceRec(v1->vertex, v0->vertex, v0child->vertex)); // newFaces.push_back(FaceRec(v1->vertex, v0child->vertex, v1child->vertex)); } else printf("WARNING: SKIPPING MESSED-UP TRIANGLE\n"); } }
BOOL CSSolid::SplitFaceByVertices(CSSVertex *pVertex1, CSSVertex *pVertex2) { if(GetEdgeIndex(pVertex1->id, pVertex2->id) != -1) return FALSE; // already an edge there! // find the face, first - get a list of affected edges and find // two with a common face int iNumEdges1, iNumEdges2; SSHANDLE hFace = 0; CSSEdge *pEdges1[64], *pEdges2[64], **pTmp; pTmp = FindAffectedEdges(&pVertex1->id, 1, iNumEdges1); memcpy(pEdges1, pTmp, iNumEdges1 * sizeof(CSSEdge*)); pTmp = FindAffectedEdges(&pVertex2->id, 1, iNumEdges2); memcpy(pEdges2, pTmp, iNumEdges2 * sizeof(CSSEdge*)); for(int i = 0; i < iNumEdges1; i++) { SSHANDLE hFace0 = pEdges1[i]->Faces[0]; SSHANDLE hFace1 = pEdges1[i]->Faces[1]; for(int i2 = 0; i2 < iNumEdges2; i2++) { if(hFace0 == pEdges2[i2]->Faces[0] || hFace0 == pEdges2[i2]->Faces[1]) { hFace = hFace0; break; } else if(hFace1 == pEdges2[i2]->Faces[0] || hFace1 == pEdges2[i2]->Faces[1]) { hFace = hFace1; break; } } } // couldn't find a common face if(hFace == 0) return FALSE; CSSFace *pFace = (CSSFace*) GetHandleData(hFace); // create a new face CSSFace *pNewFace = AddFace(); memcpy(&pNewFace->texture, &pFace->texture, sizeof(TEXTURE)); // create a new edge between two vertices CSSEdge *pNewEdge = AddEdge(); pNewEdge->hvStart = pVertex1->id; pNewEdge->hvEnd = pVertex2->id; CalcEdgeCenter(pNewEdge); // assign face ids to the new edge AssignFace(pNewEdge, pFace->id); AssignFace(pNewEdge, pNewFace->id); // set up edges - start with newvertex1 SSHANDLE hNewEdges[64]; int nNewEdges; BOOL bFirst = TRUE; CSSFace *pStoreFace = pFace; SSHANDLE *phVertexList = CreatePointHandleList(*pFace); int nVertices = pFace->nEdges; int v1index, v2index; // find where the vertices are and // kill face references in edges first for(i = 0; i < nVertices; i++) { int iNextVertex = GetNext(i, 1, nVertices); int iEdgeIndex = GetEdgeIndex(phVertexList[i], phVertexList[iNextVertex]); CSSEdge *pEdge = &m_Edges[iEdgeIndex]; AssignFace(pEdge, pFace->id, TRUE); if(phVertexList[i] == pVertex1->id) v1index = i; else if(phVertexList[i] == pVertex2->id) v2index = i; } DoNextFace: nNewEdges = 0; for(i = v1index; ; i++) { if(i == nVertices) i = 0; if(i == v2index) break; int iNextVertex = GetNext(i, 1, nVertices); int iEdgeIndex = GetEdgeIndex(phVertexList[i], phVertexList[iNextVertex]); ASSERT(iEdgeIndex != -1); hNewEdges[nNewEdges++] = m_Edges[iEdgeIndex].id; AssignFace(&m_Edges[iEdgeIndex], pFace->id); } // now add the middle edge hNewEdges[nNewEdges++] = pNewEdge->id; // now set up in face pStoreFace->nEdges = nNewEdges; memcpy(pStoreFace->Edges, hNewEdges, sizeof(SSHANDLE) * nNewEdges); if(bFirst) { int tmp = v1index; v1index = v2index; v2index = tmp; pStoreFace = pNewFace; bFirst = FALSE; goto DoNextFace; } delete phVertexList; return(TRUE); }
void CSSolid::FromMapSolid(CMapSolid *p, bool bSkipDisplacementFaces) { // so we can pass NULL (default) or another solid (to copy): CMapSolid *pSolid; if(p) pSolid = p; else pSolid = m_pMapSolid; m_nFaces = 0; m_nEdges = 0; m_nVertices = 0; // Create vertices, edges, faces. int nSolidFaces = pSolid->GetFaceCount(); for(int i = 0; i < nSolidFaces; i++) { CMapFace *pSolidFace = pSolid->GetFace(i); if (bSkipDisplacementFaces) { if (pSolidFace->HasDisp()) continue; } // Add a face CSSFace *pFace = AddFace(); memcpy(pFace->PlanePts, pSolidFace->plane.planepts, sizeof(Vector) * 3); pFace->texture = pSolidFace->texture; pFace->normal = pSolidFace->plane.normal; pFace->m_nFaceID = pSolidFace->GetFaceID(); // Displacement. if ( pSolidFace->HasDisp() ) { pFace->m_hDisp = EditDispMgr()->Create(); CMapDisp *pDisp = EditDispMgr()->GetDisp( pFace->m_hDisp ); CMapDisp *pSolidDisp = EditDispMgr()->GetDisp( pSolidFace->GetDisp() ); pDisp->CopyFrom( pSolidDisp, false ); } // Convert vertices and edges int nFacePoints = pSolidFace->nPoints; Vector *pFacePoints = pSolidFace->Points; SSHANDLE hLastVertex = 0; // valid IDs start at 1 SSHANDLE hThisVertex, hFirstVertex; for(int pt = 0; pt <= nFacePoints; pt++) { int iVertex; if(pt < nFacePoints) { // YWB: Change leniency from 1.0 down to 0.1 iVertex = GetVertexIndex(pFacePoints[pt], 0.1f); if (iVertex == -1) { // not found - add the vertex CSSVertex *pVertex = AddVertex(&iVertex); pVertex->pos = pFacePoints[pt]; } // assign this vertex handle hThisVertex = m_Vertices[iVertex].id; if (pt == 0) hFirstVertex = hThisVertex; } else { // connect last to first hThisVertex = hFirstVertex; } if (hLastVertex) { // create the edge from the last vertex to current vertex. // first check to see if this edge already exists.. int iEdge = GetEdgeIndex(hLastVertex, hThisVertex); CSSEdge *pEdge; if (iEdge == -1) { // not found - add new edge pEdge = AddEdge(&iEdge); pEdge->hvStart = hLastVertex; pEdge->hvEnd = hThisVertex; // make sure edge center is valid: CalcEdgeCenter(pEdge); } else { pEdge = &m_Edges[iEdge]; } // add the edge to the face pFace->Edges[pFace->nEdges++] = pEdge->id; // set edge's face array if(!pEdge->Faces[0]) pEdge->Faces[0] = pFace->id; else if(!pEdge->Faces[1]) pEdge->Faces[1] = pFace->id; else { // YWB try filling in front side // rather than ASSERT(0) crash pEdge->Faces[0] = pFace->id; AfxMessageBox("Edge with both face id's already filled, skipping..."); } } hLastVertex = hThisVertex; } } }
BOOL CSSolid::SplitFaceByEdges(CSSEdge *pEdge1, CSSEdge *pEdge2) { SSHANDLE hFace; // find the handle of the face if(pEdge1->Faces[0] == pEdge2->Faces[0] || pEdge1->Faces[0] == pEdge2->Faces[1]) { hFace = pEdge1->Faces[0]; } else if(pEdge1->Faces[1] == pEdge2->Faces[0] || pEdge1->Faces[1] == pEdge2->Faces[1]) { hFace = pEdge1->Faces[1]; } else return FALSE; // not the same face // get pointer to face CSSFace *pFace = (CSSFace*) GetHandleData(hFace); // create new objects CSSFace *pNewFace = AddFace(); CSSEdge *pNewEdgeMid = AddEdge(); int iNewVertex1, iNewVertex2; CSSVertex *pNewVertex1 = AddVertex(&iNewVertex1); CSSVertex *pNewVertex2 = AddVertex(&iNewVertex2); // assign faces to new edge AssignFace(pNewEdgeMid, pFace->id); AssignFace(pNewEdgeMid, pNewFace->id); // copy texture info from one face to the other memcpy(&pNewFace->texture, &pFace->texture, sizeof(TEXTURE)); // set vertex positions m_Vertices[iNewVertex1].pos = pEdge1->ptCenter; m_Vertices[iNewVertex2].pos = pEdge2->ptCenter; // set up middle edge pNewEdgeMid->hvStart = pNewVertex1->id; pNewEdgeMid->hvEnd = pNewVertex2->id; CalcEdgeCenter(pNewEdgeMid); // set up new side edges CSSEdge *pEdgeTmp = AddEdge(); pEdgeTmp->hvStart = pEdge1->hvStart; pEdgeTmp->hvEnd = pNewVertex1->id; CalcEdgeCenter(pEdgeTmp); pEdgeTmp = AddEdge(); pEdgeTmp->hvStart = pEdge1->hvEnd; pEdgeTmp->hvEnd = pNewVertex1->id; CalcEdgeCenter(pEdgeTmp); pEdgeTmp = AddEdge(); pEdgeTmp->hvStart = pEdge2->hvStart; pEdgeTmp->hvEnd = pNewVertex2->id; CalcEdgeCenter(pEdgeTmp); pEdgeTmp = AddEdge(); pEdgeTmp->hvStart = pEdge2->hvEnd; pEdgeTmp->hvEnd = pNewVertex2->id; CalcEdgeCenter(pEdgeTmp); /* FILE *fp = fopen("split", "w"); for(i = 0; i < nVertices; i++) { fprintf(fp, "%lu\n", phVertexList[i]); } fclose(fp); */ // set up edges - start with newvertex1 SSHANDLE hNewEdges[64]; int nNewEdges; BOOL bFirst = TRUE; CSSFace *pStoreFace = pFace; // ** do two new faces first ** int nv1index, nv2index; SSHANDLE *phVertexList = CreateNewVertexList(pFace, pEdge1, pEdge2, nv1index, nv2index, pNewVertex1, pNewVertex2); int nVertices = pFace->nEdges; if(nv1index != -1) ++nVertices; if(nv2index != -1) ++nVertices; // kill face references in edges first for(int i = 0; i < nVertices; i++) { int iNextVertex = GetNext(i, 1, nVertices); int iEdgeIndex = GetEdgeIndex(phVertexList[i], phVertexList[iNextVertex]); CSSEdge *pEdge = &m_Edges[iEdgeIndex]; ASSERT(pEdge->id != pEdge1->id); ASSERT(pEdge->id != pEdge2->id); AssignFace(pEdge, pFace->id, TRUE); } DoNextFace: nNewEdges = 0; for(i = nv1index; ; i++) { if(i == nVertices) i = 0; if(i == nv2index) break; int iNextVertex = GetNext(i, 1, nVertices); int iEdgeIndex = GetEdgeIndex(phVertexList[i], phVertexList[iNextVertex]); ASSERT(iEdgeIndex != -1); hNewEdges[nNewEdges++] = m_Edges[iEdgeIndex].id; AssignFace(&m_Edges[iEdgeIndex], pStoreFace->id); } // now add the middle edge hNewEdges[nNewEdges++] = pNewEdgeMid->id; // now set up in face pStoreFace->nEdges = nNewEdges; memcpy(pStoreFace->Edges, hNewEdges, sizeof(SSHANDLE) * nNewEdges); if(bFirst) { int tmp = nv1index; nv1index = nv2index; nv2index = tmp; pStoreFace = pNewFace; bFirst = FALSE; goto DoNextFace; } delete phVertexList; // ** now regular faces ** for(int iFace = 0; iFace < m_nFaces; iFace++) { CSSFace *pUpdFace = &m_Faces[iFace]; if(pUpdFace == pNewFace || pUpdFace == pFace) continue; SSHANDLE *phVertexList = CreateNewVertexList(pUpdFace, pEdge1, pEdge2, nv1index, nv2index, pNewVertex1, pNewVertex2); if(phVertexList == NULL) // don't need to update this face continue; nNewEdges = 0; nVertices = pUpdFace->nEdges; if(nv1index != -1) ++nVertices; if(nv2index != -1) ++nVertices; for(i = 0; i < nVertices; i++) { int iNextVertex = GetNext(i, 1, nVertices); int iEdgeIndex = GetEdgeIndex(phVertexList[i], phVertexList[iNextVertex]); ASSERT(iEdgeIndex != -1); AssignFace(&m_Edges[iEdgeIndex], pUpdFace->id); hNewEdges[nNewEdges++] = m_Edges[iEdgeIndex].id; } // now set up in face pUpdFace->nEdges = nNewEdges; memcpy(pUpdFace->Edges, hNewEdges, sizeof(SSHANDLE) * nNewEdges); delete phVertexList; } SSHANDLE id1 = pEdge1->id; SSHANDLE id2 = pEdge2->id; // delete old edges for(i = 0; i < m_nEdges; i++) { if(m_Edges[i].id == id1 || m_Edges[i].id == id2) { DeleteEdge(i); --i; } } return TRUE; }
int GetIncorrectEdgeIndex(EdgeId edge) const { return GetEdgeIndex(edge, not_out_edges_); }
int GetOutEdgeIndex(EdgeId edge) const { return GetEdgeIndex(edge, out_edges_); }