mesh.c 22 KB

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