mesh.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798
  1. /*
  2. * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
  3. * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
  4. *
  5. * Permission is hereby granted, free of charge, to any person obtaining a
  6. * copy of this software and associated documentation files (the "Software"),
  7. * to deal in the Software without restriction, including without limitation
  8. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  9. * and/or sell copies of the Software, and to permit persons to whom the
  10. * Software is furnished to do so, subject to the following conditions:
  11. *
  12. * The above copyright notice including the dates of first publication and
  13. * either this permission notice or a reference to
  14. * http://oss.sgi.com/projects/FreeB/
  15. * shall be included in all copies or substantial portions of the Software.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  18. * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  20. * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  21. * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
  22. * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  23. * SOFTWARE.
  24. *
  25. * Except as contained in this notice, the name of Silicon Graphics, Inc.
  26. * shall not be used in advertising or otherwise to promote the sale, use or
  27. * other dealings in this Software without prior written authorization from
  28. * Silicon Graphics, Inc.
  29. */
  30. /*
  31. ** Author: Eric Veach, July 1994.
  32. **
  33. */
  34. #include "gluos.h"
  35. #include <stddef.h>
  36. #include <assert.h>
  37. #include "mesh.h"
  38. #include "memalloc.h"
  39. #ifndef TRUE
  40. #define TRUE 1
  41. #endif
  42. #ifndef FALSE
  43. #define FALSE 0
  44. #endif
  45. static GLUvertex *allocVertex()
  46. {
  47. return (GLUvertex *)memAlloc( sizeof( GLUvertex ));
  48. }
  49. static GLUface *allocFace()
  50. {
  51. return (GLUface *)memAlloc( sizeof( GLUface ));
  52. }
  53. /************************ Utility Routines ************************/
  54. /* Allocate and free half-edges in pairs for efficiency.
  55. * The *only* place that should use this fact is allocation/free.
  56. */
  57. typedef struct { GLUhalfEdge e, eSym; } EdgePair;
  58. /* MakeEdge creates a new pair of half-edges which form their own loop.
  59. * No vertex or face structures are allocated, but these must be assigned
  60. * before the current edge operation is completed.
  61. */
  62. static GLUhalfEdge *MakeEdge( GLUhalfEdge *eNext )
  63. {
  64. GLUhalfEdge *e;
  65. GLUhalfEdge *eSym;
  66. GLUhalfEdge *ePrev;
  67. EdgePair *pair = (EdgePair *)memAlloc( sizeof( EdgePair ));
  68. if (pair == NULL) return NULL;
  69. e = &pair->e;
  70. eSym = &pair->eSym;
  71. /* Make sure eNext points to the first edge of the edge pair */
  72. if( eNext->Sym < eNext ) { eNext = eNext->Sym; }
  73. /* Insert in circular doubly-linked list before eNext.
  74. * Note that the prev pointer is stored in Sym->next.
  75. */
  76. ePrev = eNext->Sym->next;
  77. eSym->next = ePrev;
  78. ePrev->Sym->next = e;
  79. e->next = eNext;
  80. eNext->Sym->next = eSym;
  81. e->Sym = eSym;
  82. e->Onext = e;
  83. e->Lnext = eSym;
  84. e->Org = NULL;
  85. e->Lface = NULL;
  86. e->winding = 0;
  87. e->activeRegion = NULL;
  88. eSym->Sym = e;
  89. eSym->Onext = eSym;
  90. eSym->Lnext = e;
  91. eSym->Org = NULL;
  92. eSym->Lface = NULL;
  93. eSym->winding = 0;
  94. eSym->activeRegion = NULL;
  95. return e;
  96. }
  97. /* Splice( a, b ) is best described by the Guibas/Stolfi paper or the
  98. * CS348a notes (see mesh.h). Basically it modifies the mesh so that
  99. * a->Onext and b->Onext are exchanged. This can have various effects
  100. * depending on whether a and b belong to different face or vertex rings.
  101. * For more explanation see __gl_meshSplice() below.
  102. */
  103. static void Splice( GLUhalfEdge *a, GLUhalfEdge *b )
  104. {
  105. GLUhalfEdge *aOnext = a->Onext;
  106. GLUhalfEdge *bOnext = b->Onext;
  107. aOnext->Sym->Lnext = b;
  108. bOnext->Sym->Lnext = a;
  109. a->Onext = bOnext;
  110. b->Onext = aOnext;
  111. }
  112. /* MakeVertex( newVertex, eOrig, vNext ) attaches a new vertex and makes it the
  113. * origin of all edges in the vertex loop to which eOrig belongs. "vNext" gives
  114. * a place to insert the new vertex in the global vertex list. We insert
  115. * the new vertex *before* vNext so that algorithms which walk the vertex
  116. * list will not see the newly created vertices.
  117. */
  118. static void MakeVertex( GLUvertex *newVertex,
  119. GLUhalfEdge *eOrig, GLUvertex *vNext )
  120. {
  121. GLUhalfEdge *e;
  122. GLUvertex *vPrev;
  123. GLUvertex *vNew = newVertex;
  124. assert(vNew != NULL);
  125. /* insert in circular doubly-linked list before vNext */
  126. vPrev = vNext->prev;
  127. vNew->prev = vPrev;
  128. vPrev->next = vNew;
  129. vNew->next = vNext;
  130. vNext->prev = vNew;
  131. vNew->anEdge = eOrig;
  132. vNew->data = NULL;
  133. /* leave coords, s, t undefined */
  134. /* fix other edges on this vertex loop */
  135. e = eOrig;
  136. do {
  137. e->Org = vNew;
  138. e = e->Onext;
  139. } while( e != eOrig );
  140. }
  141. /* MakeFace( newFace, eOrig, fNext ) attaches a new face and makes it the left
  142. * face of all edges in the face loop to which eOrig belongs. "fNext" gives
  143. * a place to insert the new face in the global face list. We insert
  144. * the new face *before* fNext so that algorithms which walk the face
  145. * list will not see the newly created faces.
  146. */
  147. static void MakeFace( GLUface *newFace, GLUhalfEdge *eOrig, GLUface *fNext )
  148. {
  149. GLUhalfEdge *e;
  150. GLUface *fPrev;
  151. GLUface *fNew = newFace;
  152. assert(fNew != NULL);
  153. /* insert in circular doubly-linked list before fNext */
  154. fPrev = fNext->prev;
  155. fNew->prev = fPrev;
  156. fPrev->next = fNew;
  157. fNew->next = fNext;
  158. fNext->prev = fNew;
  159. fNew->anEdge = eOrig;
  160. fNew->data = NULL;
  161. fNew->trail = NULL;
  162. fNew->marked = FALSE;
  163. /* The new face is marked "inside" if the old one was. This is a
  164. * convenience for the common case where a face has been split in two.
  165. */
  166. fNew->inside = fNext->inside;
  167. /* fix other edges on this face loop */
  168. e = eOrig;
  169. do {
  170. e->Lface = fNew;
  171. e = e->Lnext;
  172. } while( e != eOrig );
  173. }
  174. /* KillEdge( eDel ) destroys an edge (the half-edges eDel and eDel->Sym),
  175. * and removes from the global edge list.
  176. */
  177. static void KillEdge( GLUhalfEdge *eDel )
  178. {
  179. GLUhalfEdge *ePrev, *eNext;
  180. /* Half-edges are allocated in pairs, see EdgePair above */
  181. if( eDel->Sym < eDel ) { eDel = eDel->Sym; }
  182. /* delete from circular doubly-linked list */
  183. eNext = eDel->next;
  184. ePrev = eDel->Sym->next;
  185. eNext->Sym->next = ePrev;
  186. ePrev->Sym->next = eNext;
  187. memFree( eDel );
  188. }
  189. /* KillVertex( vDel ) destroys a vertex and removes it from the global
  190. * vertex list. It updates the vertex loop to point to a given new vertex.
  191. */
  192. static void KillVertex( GLUvertex *vDel, GLUvertex *newOrg )
  193. {
  194. GLUhalfEdge *e, *eStart = vDel->anEdge;
  195. GLUvertex *vPrev, *vNext;
  196. /* change the origin of all affected edges */
  197. e = eStart;
  198. do {
  199. e->Org = newOrg;
  200. e = e->Onext;
  201. } while( e != eStart );
  202. /* delete from circular doubly-linked list */
  203. vPrev = vDel->prev;
  204. vNext = vDel->next;
  205. vNext->prev = vPrev;
  206. vPrev->next = vNext;
  207. memFree( vDel );
  208. }
  209. /* KillFace( fDel ) destroys a face and removes it from the global face
  210. * list. It updates the face loop to point to a given new face.
  211. */
  212. static void KillFace( GLUface *fDel, GLUface *newLface )
  213. {
  214. GLUhalfEdge *e, *eStart = fDel->anEdge;
  215. GLUface *fPrev, *fNext;
  216. /* change the left face of all affected edges */
  217. e = eStart;
  218. do {
  219. e->Lface = newLface;
  220. e = e->Lnext;
  221. } while( e != eStart );
  222. /* delete from circular doubly-linked list */
  223. fPrev = fDel->prev;
  224. fNext = fDel->next;
  225. fNext->prev = fPrev;
  226. fPrev->next = fNext;
  227. memFree( fDel );
  228. }
  229. /****************** Basic Edge Operations **********************/
  230. /* __gl_meshMakeEdge creates one edge, two vertices, and a loop (face).
  231. * The loop consists of the two new half-edges.
  232. */
  233. GLUhalfEdge *__gl_meshMakeEdge( GLUmesh *mesh )
  234. {
  235. GLUvertex *newVertex1= allocVertex();
  236. GLUvertex *newVertex2= allocVertex();
  237. GLUface *newFace= allocFace();
  238. GLUhalfEdge *e;
  239. /* if any one is null then all get freed */
  240. if (newVertex1 == NULL || newVertex2 == NULL || newFace == NULL) {
  241. if (newVertex1 != NULL) memFree(newVertex1);
  242. if (newVertex2 != NULL) memFree(newVertex2);
  243. if (newFace != NULL) memFree(newFace);
  244. return NULL;
  245. }
  246. e = MakeEdge( &mesh->eHead );
  247. if (e == NULL) {
  248. memFree(newVertex1);
  249. memFree(newVertex2);
  250. memFree(newFace);
  251. return NULL;
  252. }
  253. MakeVertex( newVertex1, e, &mesh->vHead );
  254. MakeVertex( newVertex2, e->Sym, &mesh->vHead );
  255. MakeFace( newFace, e, &mesh->fHead );
  256. return e;
  257. }
  258. /* __gl_meshSplice( eOrg, eDst ) is the basic operation for changing the
  259. * mesh connectivity and topology. It changes the mesh so that
  260. * eOrg->Onext <- OLD( eDst->Onext )
  261. * eDst->Onext <- OLD( eOrg->Onext )
  262. * where OLD(...) means the value before the meshSplice operation.
  263. *
  264. * This can have two effects on the vertex structure:
  265. * - if eOrg->Org != eDst->Org, the two vertices are merged together
  266. * - if eOrg->Org == eDst->Org, the origin is split into two vertices
  267. * In both cases, eDst->Org is changed and eOrg->Org is untouched.
  268. *
  269. * Similarly (and independently) for the face structure,
  270. * - if eOrg->Lface == eDst->Lface, one loop is split into two
  271. * - if eOrg->Lface != eDst->Lface, two distinct loops are joined into one
  272. * In both cases, eDst->Lface is changed and eOrg->Lface is unaffected.
  273. *
  274. * Some special cases:
  275. * If eDst == eOrg, the operation has no effect.
  276. * If eDst == eOrg->Lnext, the new face will have a single edge.
  277. * If eDst == eOrg->Lprev, the old face will have a single edge.
  278. * If eDst == eOrg->Onext, the new vertex will have a single edge.
  279. * If eDst == eOrg->Oprev, the old vertex will have a single edge.
  280. */
  281. int __gl_meshSplice( GLUhalfEdge *eOrg, GLUhalfEdge *eDst )
  282. {
  283. int joiningLoops = FALSE;
  284. int joiningVertices = FALSE;
  285. if( eOrg == eDst ) return 1;
  286. if( eDst->Org != eOrg->Org ) {
  287. /* We are merging two disjoint vertices -- destroy eDst->Org */
  288. joiningVertices = TRUE;
  289. KillVertex( eDst->Org, eOrg->Org );
  290. }
  291. if( eDst->Lface != eOrg->Lface ) {
  292. /* We are connecting two disjoint loops -- destroy eDst->Lface */
  293. joiningLoops = TRUE;
  294. KillFace( eDst->Lface, eOrg->Lface );
  295. }
  296. /* Change the edge structure */
  297. Splice( eDst, eOrg );
  298. if( ! joiningVertices ) {
  299. GLUvertex *newVertex= allocVertex();
  300. if (newVertex == NULL) return 0;
  301. /* We split one vertex into two -- the new vertex is eDst->Org.
  302. * Make sure the old vertex points to a valid half-edge.
  303. */
  304. MakeVertex( newVertex, eDst, eOrg->Org );
  305. eOrg->Org->anEdge = eOrg;
  306. }
  307. if( ! joiningLoops ) {
  308. GLUface *newFace= allocFace();
  309. if (newFace == NULL) return 0;
  310. /* We split one loop into two -- the new loop is eDst->Lface.
  311. * Make sure the old face points to a valid half-edge.
  312. */
  313. MakeFace( newFace, eDst, eOrg->Lface );
  314. eOrg->Lface->anEdge = eOrg;
  315. }
  316. return 1;
  317. }
  318. /* __gl_meshDelete( eDel ) removes the edge eDel. There are several cases:
  319. * if (eDel->Lface != eDel->Rface), we join two loops into one; the loop
  320. * eDel->Lface is deleted. Otherwise, we are splitting one loop into two;
  321. * the newly created loop will contain eDel->Dst. If the deletion of eDel
  322. * would create isolated vertices, those are deleted as well.
  323. *
  324. * This function could be implemented as two calls to __gl_meshSplice
  325. * plus a few calls to memFree, but this would allocate and delete
  326. * unnecessary vertices and faces.
  327. */
  328. int __gl_meshDelete( GLUhalfEdge *eDel )
  329. {
  330. GLUhalfEdge *eDelSym = eDel->Sym;
  331. int joiningLoops = FALSE;
  332. /* First step: disconnect the origin vertex eDel->Org. We make all
  333. * changes to get a consistent mesh in this "intermediate" state.
  334. */
  335. if( eDel->Lface != eDel->Rface ) {
  336. /* We are joining two loops into one -- remove the left face */
  337. joiningLoops = TRUE;
  338. KillFace( eDel->Lface, eDel->Rface );
  339. }
  340. if( eDel->Onext == eDel ) {
  341. KillVertex( eDel->Org, NULL );
  342. } else {
  343. /* Make sure that eDel->Org and eDel->Rface point to valid half-edges */
  344. eDel->Rface->anEdge = eDel->Oprev;
  345. eDel->Org->anEdge = eDel->Onext;
  346. Splice( eDel, eDel->Oprev );
  347. if( ! joiningLoops ) {
  348. GLUface *newFace= allocFace();
  349. if (newFace == NULL) return 0;
  350. /* We are splitting one loop into two -- create a new loop for eDel. */
  351. MakeFace( newFace, eDel, eDel->Lface );
  352. }
  353. }
  354. /* Claim: the mesh is now in a consistent state, except that eDel->Org
  355. * may have been deleted. Now we disconnect eDel->Dst.
  356. */
  357. if( eDelSym->Onext == eDelSym ) {
  358. KillVertex( eDelSym->Org, NULL );
  359. KillFace( eDelSym->Lface, NULL );
  360. } else {
  361. /* Make sure that eDel->Dst and eDel->Lface point to valid half-edges */
  362. eDel->Lface->anEdge = eDelSym->Oprev;
  363. eDelSym->Org->anEdge = eDelSym->Onext;
  364. Splice( eDelSym, eDelSym->Oprev );
  365. }
  366. /* Any isolated vertices or faces have already been freed. */
  367. KillEdge( eDel );
  368. return 1;
  369. }
  370. /******************** Other Edge Operations **********************/
  371. /* All these routines can be implemented with the basic edge
  372. * operations above. They are provided for convenience and efficiency.
  373. */
  374. /* __gl_meshAddEdgeVertex( eOrg ) creates a new edge eNew such that
  375. * eNew == eOrg->Lnext, and eNew->Dst is a newly created vertex.
  376. * eOrg and eNew will have the same left face.
  377. */
  378. GLUhalfEdge *__gl_meshAddEdgeVertex( GLUhalfEdge *eOrg )
  379. {
  380. GLUhalfEdge *eNewSym;
  381. GLUhalfEdge *eNew = MakeEdge( eOrg );
  382. if (eNew == NULL) return NULL;
  383. eNewSym = eNew->Sym;
  384. /* Connect the new edge appropriately */
  385. Splice( eNew, eOrg->Lnext );
  386. /* Set the vertex and face information */
  387. eNew->Org = eOrg->Dst;
  388. {
  389. GLUvertex *newVertex= allocVertex();
  390. if (newVertex == NULL) return NULL;
  391. MakeVertex( newVertex, eNewSym, eNew->Org );
  392. }
  393. eNew->Lface = eNewSym->Lface = eOrg->Lface;
  394. return eNew;
  395. }
  396. /* __gl_meshSplitEdge( eOrg ) splits eOrg into two edges eOrg and eNew,
  397. * such that eNew == eOrg->Lnext. The new vertex is eOrg->Dst == eNew->Org.
  398. * eOrg and eNew will have the same left face.
  399. */
  400. GLUhalfEdge *__gl_meshSplitEdge( GLUhalfEdge *eOrg )
  401. {
  402. GLUhalfEdge *eNew;
  403. GLUhalfEdge *tempHalfEdge= __gl_meshAddEdgeVertex( eOrg );
  404. if (tempHalfEdge == NULL) return NULL;
  405. eNew = tempHalfEdge->Sym;
  406. /* Disconnect eOrg from eOrg->Dst and connect it to eNew->Org */
  407. Splice( eOrg->Sym, eOrg->Sym->Oprev );
  408. Splice( eOrg->Sym, eNew );
  409. /* Set the vertex and face information */
  410. eOrg->Dst = eNew->Org;
  411. eNew->Dst->anEdge = eNew->Sym; /* may have pointed to eOrg->Sym */
  412. eNew->Rface = eOrg->Rface;
  413. eNew->winding = eOrg->winding; /* copy old winding information */
  414. eNew->Sym->winding = eOrg->Sym->winding;
  415. return eNew;
  416. }
  417. /* __gl_meshConnect( eOrg, eDst ) creates a new edge from eOrg->Dst
  418. * to eDst->Org, and returns the corresponding half-edge eNew.
  419. * If eOrg->Lface == eDst->Lface, this splits one loop into two,
  420. * and the newly created loop is eNew->Lface. Otherwise, two disjoint
  421. * loops are merged into one, and the loop eDst->Lface is destroyed.
  422. *
  423. * If (eOrg == eDst), the new face will have only two edges.
  424. * If (eOrg->Lnext == eDst), the old face is reduced to a single edge.
  425. * If (eOrg->Lnext->Lnext == eDst), the old face is reduced to two edges.
  426. */
  427. GLUhalfEdge *__gl_meshConnect( GLUhalfEdge *eOrg, GLUhalfEdge *eDst )
  428. {
  429. GLUhalfEdge *eNewSym;
  430. int joiningLoops = FALSE;
  431. GLUhalfEdge *eNew = MakeEdge( eOrg );
  432. if (eNew == NULL) return NULL;
  433. eNewSym = eNew->Sym;
  434. if( eDst->Lface != eOrg->Lface ) {
  435. /* We are connecting two disjoint loops -- destroy eDst->Lface */
  436. joiningLoops = TRUE;
  437. KillFace( eDst->Lface, eOrg->Lface );
  438. }
  439. /* Connect the new edge appropriately */
  440. Splice( eNew, eOrg->Lnext );
  441. Splice( eNewSym, eDst );
  442. /* Set the vertex and face information */
  443. eNew->Org = eOrg->Dst;
  444. eNewSym->Org = eDst->Org;
  445. eNew->Lface = eNewSym->Lface = eOrg->Lface;
  446. /* Make sure the old face points to a valid half-edge */
  447. eOrg->Lface->anEdge = eNewSym;
  448. if( ! joiningLoops ) {
  449. GLUface *newFace= allocFace();
  450. if (newFace == NULL) return NULL;
  451. /* We split one loop into two -- the new loop is eNew->Lface */
  452. MakeFace( newFace, eNew, eOrg->Lface );
  453. }
  454. return eNew;
  455. }
  456. /******************** Other Operations **********************/
  457. /* __gl_meshZapFace( fZap ) destroys a face and removes it from the
  458. * global face list. All edges of fZap will have a NULL pointer as their
  459. * left face. Any edges which also have a NULL pointer as their right face
  460. * are deleted entirely (along with any isolated vertices this produces).
  461. * An entire mesh can be deleted by zapping its faces, one at a time,
  462. * in any order. Zapped faces cannot be used in further mesh operations!
  463. */
  464. void __gl_meshZapFace( GLUface *fZap )
  465. {
  466. GLUhalfEdge *eStart = fZap->anEdge;
  467. GLUhalfEdge *e, *eNext, *eSym;
  468. GLUface *fPrev, *fNext;
  469. /* walk around face, deleting edges whose right face is also NULL */
  470. eNext = eStart->Lnext;
  471. do {
  472. e = eNext;
  473. eNext = e->Lnext;
  474. e->Lface = NULL;
  475. if( e->Rface == NULL ) {
  476. /* delete the edge -- see __gl_MeshDelete above */
  477. if( e->Onext == e ) {
  478. KillVertex( e->Org, NULL );
  479. } else {
  480. /* Make sure that e->Org points to a valid half-edge */
  481. e->Org->anEdge = e->Onext;
  482. Splice( e, e->Oprev );
  483. }
  484. eSym = e->Sym;
  485. if( eSym->Onext == eSym ) {
  486. KillVertex( eSym->Org, NULL );
  487. } else {
  488. /* Make sure that eSym->Org points to a valid half-edge */
  489. eSym->Org->anEdge = eSym->Onext;
  490. Splice( eSym, eSym->Oprev );
  491. }
  492. KillEdge( e );
  493. }
  494. } while( e != eStart );
  495. /* delete from circular doubly-linked list */
  496. fPrev = fZap->prev;
  497. fNext = fZap->next;
  498. fNext->prev = fPrev;
  499. fPrev->next = fNext;
  500. memFree( fZap );
  501. }
  502. /* __gl_meshNewMesh() creates a new mesh with no edges, no vertices,
  503. * and no loops (what we usually call a "face").
  504. */
  505. GLUmesh *__gl_meshNewMesh( void )
  506. {
  507. GLUvertex *v;
  508. GLUface *f;
  509. GLUhalfEdge *e;
  510. GLUhalfEdge *eSym;
  511. GLUmesh *mesh = (GLUmesh *)memAlloc( sizeof( GLUmesh ));
  512. if (mesh == NULL) {
  513. return NULL;
  514. }
  515. v = &mesh->vHead;
  516. f = &mesh->fHead;
  517. e = &mesh->eHead;
  518. eSym = &mesh->eHeadSym;
  519. v->next = v->prev = v;
  520. v->anEdge = NULL;
  521. v->data = NULL;
  522. f->next = f->prev = f;
  523. f->anEdge = NULL;
  524. f->data = NULL;
  525. f->trail = NULL;
  526. f->marked = FALSE;
  527. f->inside = FALSE;
  528. e->next = e;
  529. e->Sym = eSym;
  530. e->Onext = NULL;
  531. e->Lnext = NULL;
  532. e->Org = NULL;
  533. e->Lface = NULL;
  534. e->winding = 0;
  535. e->activeRegion = NULL;
  536. eSym->next = eSym;
  537. eSym->Sym = e;
  538. eSym->Onext = NULL;
  539. eSym->Lnext = NULL;
  540. eSym->Org = NULL;
  541. eSym->Lface = NULL;
  542. eSym->winding = 0;
  543. eSym->activeRegion = NULL;
  544. return mesh;
  545. }
  546. /* __gl_meshUnion( mesh1, mesh2 ) forms the union of all structures in
  547. * both meshes, and returns the new mesh (the old meshes are destroyed).
  548. */
  549. GLUmesh *__gl_meshUnion( GLUmesh *mesh1, GLUmesh *mesh2 )
  550. {
  551. GLUface *f1 = &mesh1->fHead;
  552. GLUvertex *v1 = &mesh1->vHead;
  553. GLUhalfEdge *e1 = &mesh1->eHead;
  554. GLUface *f2 = &mesh2->fHead;
  555. GLUvertex *v2 = &mesh2->vHead;
  556. GLUhalfEdge *e2 = &mesh2->eHead;
  557. /* Add the faces, vertices, and edges of mesh2 to those of mesh1 */
  558. if( f2->next != f2 ) {
  559. f1->prev->next = f2->next;
  560. f2->next->prev = f1->prev;
  561. f2->prev->next = f1;
  562. f1->prev = f2->prev;
  563. }
  564. if( v2->next != v2 ) {
  565. v1->prev->next = v2->next;
  566. v2->next->prev = v1->prev;
  567. v2->prev->next = v1;
  568. v1->prev = v2->prev;
  569. }
  570. if( e2->next != e2 ) {
  571. e1->Sym->next->Sym->next = e2->next;
  572. e2->next->Sym->next = e1->Sym->next;
  573. e2->Sym->next->Sym->next = e1;
  574. e1->Sym->next = e2->Sym->next;
  575. }
  576. memFree( mesh2 );
  577. return mesh1;
  578. }
  579. #ifdef DELETE_BY_ZAPPING
  580. /* __gl_meshDeleteMesh( mesh ) will free all storage for any valid mesh.
  581. */
  582. void __gl_meshDeleteMesh( GLUmesh *mesh )
  583. {
  584. GLUface *fHead = &mesh->fHead;
  585. while( fHead->next != fHead ) {
  586. __gl_meshZapFace( fHead->next );
  587. }
  588. assert( mesh->vHead.next == &mesh->vHead );
  589. memFree( mesh );
  590. }
  591. #else
  592. /* __gl_meshDeleteMesh( mesh ) will free all storage for any valid mesh.
  593. */
  594. void __gl_meshDeleteMesh( GLUmesh *mesh )
  595. {
  596. GLUface *f, *fNext;
  597. GLUvertex *v, *vNext;
  598. GLUhalfEdge *e, *eNext;
  599. for( f = mesh->fHead.next; f != &mesh->fHead; f = fNext ) {
  600. fNext = f->next;
  601. memFree( f );
  602. }
  603. for( v = mesh->vHead.next; v != &mesh->vHead; v = vNext ) {
  604. vNext = v->next;
  605. memFree( v );
  606. }
  607. for( e = mesh->eHead.next; e != &mesh->eHead; e = eNext ) {
  608. /* One call frees both e and e->Sym (see EdgePair above) */
  609. eNext = e->next;
  610. memFree( e );
  611. }
  612. memFree( mesh );
  613. }
  614. #endif
  615. #ifndef NDEBUG
  616. /* __gl_meshCheckMesh( mesh ) checks a mesh for self-consistency.
  617. */
  618. void __gl_meshCheckMesh( GLUmesh *mesh )
  619. {
  620. GLUface *fHead = &mesh->fHead;
  621. GLUvertex *vHead = &mesh->vHead;
  622. GLUhalfEdge *eHead = &mesh->eHead;
  623. GLUface *f, *fPrev;
  624. GLUvertex *v, *vPrev;
  625. GLUhalfEdge *e, *ePrev;
  626. fPrev = fHead;
  627. for( fPrev = fHead ; (f = fPrev->next) != fHead; fPrev = f) {
  628. assert( f->prev == fPrev );
  629. e = f->anEdge;
  630. do {
  631. assert( e->Sym != e );
  632. assert( e->Sym->Sym == e );
  633. assert( e->Lnext->Onext->Sym == e );
  634. assert( e->Onext->Sym->Lnext == e );
  635. assert( e->Lface == f );
  636. e = e->Lnext;
  637. } while( e != f->anEdge );
  638. }
  639. assert( f->prev == fPrev && f->anEdge == NULL && f->data == NULL );
  640. vPrev = vHead;
  641. for( vPrev = vHead ; (v = vPrev->next) != vHead; vPrev = v) {
  642. assert( v->prev == vPrev );
  643. e = v->anEdge;
  644. do {
  645. assert( e->Sym != e );
  646. assert( e->Sym->Sym == e );
  647. assert( e->Lnext->Onext->Sym == e );
  648. assert( e->Onext->Sym->Lnext == e );
  649. assert( e->Org == v );
  650. e = e->Onext;
  651. } while( e != v->anEdge );
  652. }
  653. assert( v->prev == vPrev && v->anEdge == NULL && v->data == NULL );
  654. ePrev = eHead;
  655. for( ePrev = eHead ; (e = ePrev->next) != eHead; ePrev = e) {
  656. assert( e->Sym->next == ePrev->Sym );
  657. assert( e->Sym != e );
  658. assert( e->Sym->Sym == e );
  659. assert( e->Org != NULL );
  660. assert( e->Dst != NULL );
  661. assert( e->Lnext->Onext->Sym == e );
  662. assert( e->Onext->Sym->Lnext == e );
  663. }
  664. assert( e->Sym->next == ePrev->Sym
  665. && e->Sym == &mesh->eHeadSym
  666. && e->Sym->Sym == e
  667. && e->Org == NULL && e->Dst == NULL
  668. && e->Lface == NULL && e->Rface == NULL );
  669. }
  670. #endif