/* tessMeshSplice (eOrg, eDst) is the basic operation for changing the * mesh connectivity and topology. It changes the mesh so that * eOrg->Onext <- OLD (eDst->Onext) * eDst->Onext <- OLD (eOrg->Onext) * where OLD(...) means the value before the meshSplice operation. * * This can have two effects on the vertex structure: * - if eOrg->Org != eDst->Org, the two vertices are merged together * - if eOrg->Org == eDst->Org, the origin is split into two vertices * In both cases, eDst->Org is changed and eOrg->Org is untouched. * * Similarly (and independently) for the face structure, * - if eOrg->Lface == eDst->Lface, one loop is split into two * - if eOrg->Lface != eDst->Lface, two distinct loops are joined into one * In both cases, eDst->Lface is changed and eOrg->Lface is unaffected. * * Some special cases: * If eDst == eOrg, the operation has no effect. * If eDst == eOrg->Lnext, the new face will have a single edge. * If eDst == eOrg->Lprev, the old face will have a single edge. * If eDst == eOrg->Onext, the new vertex will have a single edge. * If eDst == eOrg->Oprev, the old vertex will have a single edge. */ int tessMeshSplice(TMesh* pMesh, THalfEdge *pEdgeOrg, THalfEdge *pEdgeDst) { int bJoiningLoops = false; int bJoiningVertices = false; if (pEdgeOrg == pEdgeDst) return 1; if (pEdgeDst->pOrigin != pEdgeOrg->pOrigin) { /* We are merging two disjoint vertices -- destroy eDst->Org */ bJoiningVertices = true; KillVertex(pMesh, pEdgeDst->pOrigin, pEdgeOrg->pOrigin); } if (pEdgeDst->Lface != pEdgeOrg->Lface) { /* We are connecting two disjoint loops -- destroy eDst->Lface */ bJoiningLoops = true; KillFace(pMesh, pEdgeDst->Lface, pEdgeOrg->Lface); } /* Change the edge structure */ Splice(pEdgeDst, pEdgeOrg); if (!bJoiningVertices) { TVertex *pNewVertex = (TVertex*)BucketAlloc(pMesh->pVertexBucket); if (pNewVertex == NULL) return 0; /* We split one vertex into two -- the new vertex is eDst->Org. * Make sure the old vertex points to a valid half-edge. */ MakeVertex(pNewVertex, pEdgeDst, pEdgeOrg->pOrigin); pEdgeOrg->pOrigin->pHalfEdge = pEdgeOrg; } if (!bJoiningLoops) { TFace *pNewFace = (TFace*)BucketAlloc(pMesh->pFaceBucket); if (pNewFace == NULL) return 0; /* We split one loop into two -- the new loop is eDst->Lface. * Make sure the old face points to a valid half-edge. */ MakeFace(pNewFace, pEdgeDst, pEdgeOrg->Lface); pEdgeOrg->Lface->pHalfEdge = pEdgeOrg; } return 1; }
/* tessMeshDelete (eDel) removes the edge eDel. There are several cases: * if (eDel->Lface != eDel->Rface), we join two loops into one; the loop * eDel->Lface is deleted. Otherwise, we are splitting one loop into two; * the newly created loop will contain eDel->Dst. If the deletion of eDel * would create isolated vertices, those are deleted as well. * * This function could be implemented as two calls to tessMeshSplice * plus a few calls to memFree, but this would allocate and delete * unnecessary vertices and faces. */ int tessMeshDelete (TMesh *mesh, THalfEdge *eDel) { THalfEdge *eDelSym = eDel->Sym; int joiningLoops = false; /* First step: disconnect the origin vertex eDel->Org. We make all * changes to get a consistent mesh in this "intermediate" state. */ if (eDel->Lface != eDel->Rface) { /* We are joining two loops into one -- remove the left face */ joiningLoops = true; KillFace (mesh, eDel->Lface, eDel->Rface) ; } if (eDel->Onext == eDel) { KillVertex (mesh, eDel->pOrigin, NULL) ; } else { /* Make sure that eDel->Org and eDel->Rface point to valid half-edges */ eDel->Rface->pHalfEdge = eDel->Oprev; eDel->pOrigin->pHalfEdge = eDel->Onext; Splice (eDel, eDel->Oprev) ; if (! joiningLoops) { TFace *newFace= (TFace*)BucketAlloc (mesh->pFaceBucket) ; if (newFace == NULL) return 0; /* We are splitting one loop into two -- create a new loop for eDel. */ MakeFace (newFace, eDel, eDel->Lface) ; } } /* Claim: the mesh is now in a consistent state, except that eDel->Org * may have been deleted. Now we disconnect eDel->Dst. */ if (eDelSym->Onext == eDelSym) { KillVertex (mesh, eDelSym->pOrigin, NULL) ; KillFace (mesh, eDelSym->Lface, NULL) ; } else { /* Make sure that eDel->Dst and eDel->Lface point to valid half-edges */ eDel->Lface->pHalfEdge = eDelSym->Oprev; eDelSym->pOrigin->pHalfEdge = eDelSym->Onext; Splice (eDelSym, eDelSym->Oprev) ; } /* Any isolated vertices or faces have already been freed. */ KillEdge (mesh, eDel) ; return 1; }
/* tessMeshMakeEdge creates one edge, two vertices, and a loop (face). * The loop consists of the two new half-edges. */ THalfEdge *tessMeshMakeEdge(TMesh *pMesh) { TVertex *newVertex1 = (TVertex*)BucketAlloc(pMesh->pVertexBucket); TVertex *newVertex2 = (TVertex*)BucketAlloc(pMesh->pVertexBucket); TFace *newFace = (TFace*)BucketAlloc(pMesh->pFaceBucket); THalfEdge *e; /* if any one is null then all get freed */ if (newVertex1 == NULL || newVertex2 == NULL || newFace == NULL) { if (newVertex1 != NULL) BucketFree (pMesh->pVertexBucket, newVertex1) ; if (newVertex2 != NULL) BucketFree (pMesh->pVertexBucket, newVertex2) ; if (newFace != NULL) BucketFree (pMesh->pFaceBucket, newFace) ; return NULL; } e = MakeEdge (pMesh, &pMesh->eHead) ; if (e == NULL) return NULL; MakeVertex (newVertex1, e, &pMesh->vHead) ; MakeVertex (newVertex2, e->Sym, &pMesh->vHead) ; MakeFace (newFace, e, &pMesh->fHead) ; return e; }
/* MakeEdge creates a new pair of half-edges which form their own loop. * No vertex or face structures are allocated, but these must be assigned * before the current edge operation is completed. */ static THalfEdge *MakeEdge(TMesh* pMesh, THalfEdge *pEdgeNext) { THalfEdge *pEdge = NULL; THalfEdge *pSymEdge = NULL; THalfEdge *pPrevEdge = NULL; EdgePair *pPair = (EdgePair *)BucketAlloc(pMesh->pEdgeBucket); if (pPair == NULL) return NULL; pEdge = &pPair->Edge; pSymEdge = &pPair->SymEdge; /* Make sure eNext points to the first edge of the edge pair */ if (pEdgeNext->Sym < pEdgeNext) { pEdgeNext = pEdgeNext->Sym; } /* Insert in circular doubly-linked list before eNext. * Note that the prev pointer is stored in Sym->next. */ pPrevEdge = pEdgeNext->Sym->pNext; pSymEdge->pNext = pPrevEdge; pPrevEdge->Sym->pNext = pEdge; pEdge->pNext = pEdgeNext; pEdgeNext->Sym->pNext = pSymEdge; pEdge->Sym = pSymEdge; pEdge->Onext = pEdge; pEdge->Lnext = pSymEdge; pEdge->pOrigin = NULL; pEdge->Lface = NULL; pEdge->nWinding = 0; pEdge->pActiveRegion = NULL; pSymEdge->Sym = pEdge; pSymEdge->Onext = pSymEdge; pSymEdge->Lnext = pEdge; pSymEdge->pOrigin = NULL; pSymEdge->Lface = NULL; pSymEdge->nWinding = 0; pSymEdge->pActiveRegion = NULL; return pEdge; }
/* tessMeshConnect (eOrg, eDst) creates a new edge from eOrg->Dst * to eDst->Org, and returns the corresponding half-edge eNew. * If eOrg->Lface == eDst->Lface, this splits one loop into two, * and the newly created loop is eNew->Lface. Otherwise, two disjoint * loops are merged into one, and the loop eDst->Lface is destroyed. * * If (eOrg == eDst), the new face will have only two edges. * If (eOrg->Lnext == eDst), the old face is reduced to a single edge. * If (eOrg->Lnext->Lnext == eDst), the old face is reduced to two edges. */ THalfEdge *tessMeshConnect (TMesh *mesh, THalfEdge *eOrg, THalfEdge *eDst) { THalfEdge *eNewSym; int joiningLoops = false; THalfEdge *eNew = MakeEdge (mesh, eOrg) ; if (eNew == NULL) return NULL; eNewSym = eNew->Sym; if (eDst->Lface != eOrg->Lface) { /* We are connecting two disjoint loops -- destroy eDst->Lface */ joiningLoops = true; KillFace (mesh, eDst->Lface, eOrg->Lface) ; } /* Connect the new edge appropriately */ Splice(eNew, eOrg->Lnext) ; Splice(eNewSym, eDst) ; /* Set the vertex and face information */ eNew->pOrigin = eOrg->Dst; eNewSym->pOrigin = eDst->pOrigin; eNew->Lface = eNewSym->Lface = eOrg->Lface; /* Make sure the old face points to a valid half-edge */ eOrg->Lface->pHalfEdge = eNewSym; if (! joiningLoops) { TFace *newFace= (TFace*)BucketAlloc (mesh->pFaceBucket) ; if (newFace == NULL) return NULL; /* We split one loop into two -- the new loop is eNew->Lface */ MakeFace (newFace, eNew, eOrg->Lface) ; } return eNew; }
/* tessMeshAddEdgeVertex (eOrg) creates a new edge eNew such that * eNew == eOrg->Lnext, and eNew->Dst is a newly created vertex. * eOrg and eNew will have the same left face. */ THalfEdge *tessMeshAddEdgeVertex (TMesh *mesh, THalfEdge *eOrg) { THalfEdge *eNewSym; THalfEdge *eNew = MakeEdge (mesh, eOrg) ; if (eNew == NULL) return NULL; eNewSym = eNew->Sym; /* Connect the new edge appropriately */ Splice (eNew, eOrg->Lnext) ; /* Set the vertex and face information */ eNew->pOrigin = eOrg->Dst; { TVertex *newVertex= (TVertex*)BucketAlloc (mesh->pVertexBucket) ; if (newVertex == NULL) return NULL; MakeVertex (newVertex, eNewSym, eNew->pOrigin) ; } eNew->Lface = eNewSym->Lface = eOrg->Lface; return eNew; }
// // Created by citiral on 9/23/16. // #include "alloc.h" #if __KERNEL_ALLOCATOR == __KERNEL_ALLOCATOR_LINEAR LinearAlloc kernelAllocator = LinearAlloc(); #elif __KERNEL_ALLOCATOR == __KERNEL_ALLOCATOR_BUCKET BucketAlloc kernelAllocator = BucketAlloc(); #endif