Clone of mesa.
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022
  1. /* $Id: tess.c,v 1.12 1999/10/11 17:48:53 gareth Exp $ */
  2. /*
  3. * Mesa 3-D graphics library
  4. * Version: 3.1
  5. *
  6. * Copyright (C) 1999 Brian Paul All Rights Reserved.
  7. *
  8. * Permission is hereby granted, free of charge, to any person obtaining a
  9. * copy of this software and associated documentation files (the "Software"),
  10. * to deal in the Software without restriction, including without limitation
  11. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  12. * and/or sell copies of the Software, and to permit persons to whom the
  13. * Software is furnished to do so, subject to the following conditions:
  14. *
  15. * The above copyright notice and this permission notice shall be included
  16. * in all copies or substantial portions of the Software.
  17. *
  18. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  19. * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  20. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  21. * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  22. * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  23. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  24. */
  25. /*
  26. * $Log: tess.c,v $
  27. * Revision 1.12 1999/10/11 17:48:53 gareth
  28. * Correctly initialized GLUtesselator user data pointer.
  29. *
  30. * Revision 1.11 1999/10/11 17:26:48 gareth
  31. * Updated debugging output. I'm going to change it all to something
  32. * much more like the GLX project. This was a set of macros left over
  33. * from a research project I'd done, and I like the GLX logging more.
  34. *
  35. * Revision 1.10 1999/10/03 00:56:07 gareth
  36. * Added tessellation winding rule support. Misc bug fixes.
  37. *
  38. * Revision 1.9 1999/09/17 06:34:46 gareth
  39. * Winding rule updates.
  40. *
  41. * Revision 1.8 1999/09/17 03:07:28 tjump
  42. * Win32 build req't updates
  43. *
  44. * Revision 1.7 1999/09/16 06:41:42 gareth
  45. * Misc winding rule bug fixes.
  46. *
  47. * Revision 1.6 1999/09/15 02:11:10 gareth
  48. * Fixed vector macro calls, specifically COPY_3V params.
  49. *
  50. * Revision 1.5 1999/09/14 05:37:58 gareth
  51. * Fixed legacy gluNextContour impact on gluTessEndContour.
  52. *
  53. * Revision 1.4 1999/09/13 22:20:13 gareth
  54. * Fixed file headers. Tracking down macro bugs.
  55. *
  56. */
  57. /*****************************************************************************
  58. *
  59. * GLU 1.3 Polygon Tessellation by Gareth Hughes <garethh@lucent.com>
  60. *
  61. *****************************************************************************/
  62. #include <stdarg.h>
  63. #include <stdio.h>
  64. #include <stdlib.h>
  65. #include <GL/glu.h>
  66. #include "tess.h"
  67. #include "tess_macros.h"
  68. #include "tess_fist.h"
  69. #if 0
  70. #include "tess_grid.h"
  71. #endif
  72. /*****************************************************************************
  73. * Internal function prototypes:
  74. *****************************************************************************/
  75. static void init_callbacks( tess_callbacks_t *callbacks );
  76. static void tess_cleanup( GLUtesselator *tobj );
  77. static void inspect_current_contour( GLUtesselator *tobj );
  78. static void delete_current_contour( GLUtesselator *tobj );
  79. static void delete_all_contours( GLUtesselator *tobj );
  80. #define TESS_CHECK_ERRORS(t) if ( (t)->error != GLU_NO_ERROR ) goto cleanup
  81. /*****************************************************************************
  82. *
  83. * GLU TESSELLATION FUNCTIONS
  84. *
  85. *****************************************************************************/
  86. /*****************************************************************************
  87. * gluNewTess
  88. *****************************************************************************/
  89. GLUtesselator* GLAPIENTRY gluNewTess( void )
  90. {
  91. GLUtesselator *tobj;
  92. DEBUGP( 15, ( "-> gluNewTess()\n" ) );
  93. if ( ( tobj = (GLUtesselator *)
  94. malloc( sizeof(GLUtesselator) ) ) == NULL )
  95. {
  96. return NULL;
  97. }
  98. init_callbacks( &tobj->callbacks );
  99. tobj->boundary_only = GL_FALSE;
  100. tobj->winding_rule = GLU_TESS_WINDING_ODD;
  101. tobj->tolerance = 0.0;
  102. tobj->plane.normal[X] = 0.0;
  103. tobj->plane.normal[Y] = 0.0;
  104. tobj->plane.normal[Z] = 0.0;
  105. tobj->plane.dist = 0.0;
  106. tobj->contour_count = 0;
  107. tobj->contours = tobj->last_contour = NULL;
  108. tobj->current_contour = NULL;
  109. CLEAR_BBOX_2DV( tobj->mins, tobj->maxs );
  110. tobj->vertex_count = 0;
  111. tobj->sorted_vertices = NULL;
  112. #if 0
  113. tobj->grid = NULL;
  114. #endif
  115. tobj->cvc_lists = NULL;
  116. tobj->user_data = NULL;
  117. tobj->label = 0;
  118. tobj->error = GLU_NO_ERROR;
  119. DEBUGP( 15, ( "<- gluNewTess() tobj:%p\n", tobj ) );
  120. return tobj;
  121. }
  122. /*****************************************************************************
  123. * gluDeleteTess
  124. *****************************************************************************/
  125. void GLAPIENTRY gluDeleteTess( GLUtesselator *tobj )
  126. {
  127. DEBUGP( 15, ( "-> gluDeleteTess( tobj:%p )\n", tobj ) );
  128. if ( tobj->error == GLU_NO_ERROR && ( tobj->contour_count > 0 ) )
  129. {
  130. /* gluEndPolygon was not called. */
  131. DEBUGP( 0, ( "*** error 3 ***\n" ) );
  132. tess_error_callback( tobj, GLU_TESS_ERROR3 );
  133. }
  134. /* Delete all internal structures. */
  135. tess_cleanup( tobj );
  136. free( tobj );
  137. DEBUGP( 15, ( "<- gluDeleteTess()\n" ) );
  138. }
  139. /*****************************************************************************
  140. * gluTessBeginPolygon
  141. *****************************************************************************/
  142. void GLAPIENTRY gluTessBeginPolygon( GLUtesselator *tobj, void *polygon_data )
  143. {
  144. DEBUGP( 15, ( "-> gluTessBeginPolygon( tobj:%p data:%p )\n", tobj, polygon_data ) );
  145. tobj->error = GLU_NO_ERROR;
  146. if ( tobj->current_contour != NULL )
  147. {
  148. /* gluEndPolygon was not called. */
  149. DEBUGP( 0, ( "*** error 3 ***\n" ) );
  150. tess_error_callback( tobj, GLU_TESS_ERROR3 );
  151. tess_cleanup( tobj );
  152. }
  153. tobj->data = polygon_data;
  154. tobj->vertex_count = 0;
  155. DEBUGP( 15, ( "<- gluTessBeginPolygon( tobj:%p data:%p )\n", tobj, polygon_data ) );
  156. }
  157. /*****************************************************************************
  158. * gluTessBeginContour
  159. *****************************************************************************/
  160. void GLAPIENTRY gluTessBeginContour( GLUtesselator *tobj )
  161. {
  162. DEBUGP( 15, ( " -> gluTessBeginContour( tobj:%p )\n", tobj ) );
  163. TESS_CHECK_ERRORS( tobj );
  164. if ( tobj->current_contour != NULL )
  165. {
  166. /* gluTessEndContour was not called. */
  167. DEBUGP( 0, ( "*** error 4 ***\n" ) );
  168. tess_error_callback( tobj, GLU_TESS_ERROR4 );
  169. return;
  170. }
  171. if ( ( tobj->current_contour =
  172. (tess_contour_t *) malloc( sizeof(tess_contour_t) ) ) == NULL )
  173. {
  174. DEBUGP( 0, ( "*** memory error ***\n" ) );
  175. tess_error_callback( tobj, GLU_OUT_OF_MEMORY );
  176. return;
  177. }
  178. COPY_3V( tobj->current_contour->plane.normal, tobj->plane.normal );
  179. tobj->current_contour->plane.dist = tobj->plane.dist;
  180. tobj->current_contour->vertex_count = 0;
  181. tobj->current_contour->vertices =
  182. tobj->current_contour->last_vertex = NULL;
  183. tobj->current_contour->reflex_vertices = NULL;
  184. tobj->current_contour->cross_vertices = hashtable_init( HT_DEFAULT_SIZE );
  185. tobj->current_contour->orientation = GLU_UNKNOWN;
  186. tobj->current_contour->area = 0.0;
  187. tobj->current_contour->label = 0;
  188. CLEAR_BBOX_2DV( tobj->current_contour->mins,
  189. tobj->current_contour->maxs );
  190. tobj->current_contour->rotx = tobj->current_contour->roty = 0.0;
  191. cleanup:
  192. DEBUGP( 15, ( " <- gluTessBeginContour( tobj:%p )\n", tobj ) );
  193. return;
  194. }
  195. /*****************************************************************************
  196. * gluTessVertex
  197. *****************************************************************************/
  198. void GLAPIENTRY gluTessVertex( GLUtesselator *tobj, GLdouble coords[3],
  199. void *vertex_data )
  200. {
  201. tess_contour_t *current = tobj->current_contour;
  202. tess_vertex_t *last_vertex;
  203. DEBUGP( 15, ( " -> gluTessVertex( tobj:%p coords:(%.2f,%.2f,%.2f) )\n", tobj, coords[0], coords[1], coords[2] ) );
  204. TESS_CHECK_ERRORS( tobj );
  205. if ( current == NULL )
  206. {
  207. /* gluTessBeginContour was not called. */
  208. DEBUGP( 0, ( "*** error 2 ***\n" ) );
  209. tess_error_callback( tobj, GLU_TESS_ERROR2 );
  210. return;
  211. }
  212. tobj->vertex_count++;
  213. last_vertex = current->last_vertex;
  214. if ( last_vertex == NULL )
  215. {
  216. if ( ( last_vertex = (tess_vertex_t *)
  217. malloc( sizeof(tess_vertex_t) ) ) == NULL )
  218. {
  219. DEBUGP( 0, ( "*** memory error ***\n" ) );
  220. tess_error_callback( tobj, GLU_OUT_OF_MEMORY );
  221. return;
  222. }
  223. current->vertices = last_vertex;
  224. current->last_vertex = last_vertex;
  225. last_vertex->index = -1;
  226. last_vertex->data = vertex_data;
  227. last_vertex->coords[X] = coords[X];
  228. last_vertex->coords[Y] = coords[Y];
  229. last_vertex->coords[Z] = coords[Z];
  230. last_vertex->side = 0.0;
  231. last_vertex->label = 0;
  232. last_vertex->mark = 0;
  233. last_vertex->next = NULL;
  234. last_vertex->previous = NULL;
  235. current->vertex_count++;
  236. }
  237. else
  238. {
  239. tess_vertex_t *vertex;
  240. if ( ( vertex = (tess_vertex_t *)
  241. malloc( sizeof(tess_vertex_t) ) ) == NULL )
  242. {
  243. DEBUGP( 0, ( "*** memory error ***\n" ) );
  244. tess_error_callback( tobj, GLU_OUT_OF_MEMORY );
  245. return;
  246. }
  247. vertex->index = -1;
  248. vertex->data = vertex_data;
  249. vertex->coords[X] = coords[X];
  250. vertex->coords[Y] = coords[Y];
  251. vertex->coords[Z] = coords[Z];
  252. vertex->side = 0.0;
  253. vertex->label = 0;
  254. vertex->mark = 0;
  255. vertex->next = NULL;
  256. vertex->previous = last_vertex;
  257. current->vertex_count++;
  258. last_vertex->next = vertex;
  259. current->last_vertex = vertex;
  260. }
  261. cleanup:
  262. DEBUGP( 15, ( " <- gluTessVertex( tobj:%p )\n", tobj ) );
  263. return;
  264. }
  265. /*****************************************************************************
  266. * gluTessEndContour
  267. *****************************************************************************/
  268. void GLAPIENTRY gluTessEndContour( GLUtesselator *tobj )
  269. {
  270. DEBUGP( 15, ( " -> gluTessEndContour( tobj:%p )\n", tobj ) );
  271. TESS_CHECK_ERRORS( tobj );
  272. if ( tobj->current_contour == NULL )
  273. {
  274. /* gluTessBeginContour was not called. */
  275. DEBUGP( 0, ( "*** error 2 ***\n" ) );
  276. tess_error_callback( tobj, GLU_TESS_ERROR2 );
  277. return;
  278. }
  279. if ( tobj->current_contour->vertex_count > 0 )
  280. {
  281. inspect_current_contour( tobj );
  282. }
  283. else
  284. {
  285. delete_current_contour( tobj );
  286. }
  287. cleanup:
  288. DEBUGP( 15, ( " <- gluTessEndContour( tobj:%p )\n", tobj ) );
  289. return;
  290. }
  291. /*****************************************************************************
  292. * gluTessEndPolygon
  293. *****************************************************************************/
  294. void GLAPIENTRY gluTessEndPolygon( GLUtesselator *tobj )
  295. {
  296. DEBUGP( 15, ( "-> gluTessEndPolygon( tobj:%p )\n", tobj ) );
  297. TESS_CHECK_ERRORS( tobj );
  298. if ( tobj->current_contour != NULL )
  299. {
  300. /* gluTessBeginPolygon was not called. */
  301. DEBUGP( 0, ( "*** error 1 ***\n" ) );
  302. tess_error_callback( tobj, GLU_TESS_ERROR1 );
  303. return;
  304. }
  305. TESS_CHECK_ERRORS( tobj );
  306. /*
  307. * Ensure we have at least one contour to tessellate. If we have none,
  308. * clean up and exit gracefully.
  309. */
  310. if ( tobj->contour_count == 0 )
  311. {
  312. tess_cleanup( tobj );
  313. return;
  314. }
  315. /* Wrap the contour list. */
  316. tobj->last_contour->next = tobj->contours;
  317. tobj->contours->previous = tobj->last_contour;
  318. /* tess_find_contour_hierarchies(tobj); */
  319. TESS_CHECK_ERRORS( tobj );
  320. /* tess_handle_holes(tobj); */
  321. TESS_CHECK_ERRORS( tobj );
  322. /*
  323. * Before we tessellate the contours, ensure we have the appropriate
  324. * callbacks registered. We at least need the begin, vertex and end
  325. * callbacks to do any meaningful work.
  326. */
  327. if ( ( ( tobj->callbacks.begin != NULL ) ||
  328. ( tobj->callbacks.beginData != NULL ) ) &&
  329. ( ( tobj->callbacks.vertex != NULL ) ||
  330. ( tobj->callbacks.vertexData != NULL ) ) &&
  331. ( ( tobj->callbacks.end != NULL ) ||
  332. ( tobj->callbacks.endData != NULL ) ) )
  333. {
  334. if ( ( tobj->callbacks.edgeFlag == NULL ) &&
  335. ( tobj->callbacks.edgeFlagData == NULL ) )
  336. {
  337. fist_tessellation( tobj );
  338. }
  339. else
  340. {
  341. fist_tessellation( tobj );
  342. }
  343. }
  344. cleanup:
  345. delete_all_contours( tobj );
  346. DEBUGP( 15, ( "<- gluTessEndPolygon( tobj:%p )\n", tobj ) );
  347. }
  348. /*****************************************************************************
  349. * gluTessCallback
  350. *****************************************************************************/
  351. void GLAPIENTRY gluTessCallback( GLUtesselator *tobj, GLenum which,
  352. void (GLCALLBACK *fn)() )
  353. {
  354. switch ( which )
  355. {
  356. /* Register the begin callbacks. */
  357. case GLU_TESS_BEGIN:
  358. tobj->callbacks.begin = (void (GLCALLBACK*)(GLenum)) fn;
  359. break;
  360. case GLU_TESS_BEGIN_DATA:
  361. tobj->callbacks.beginData = (void (GLCALLBACK*)(GLenum, void *)) fn;
  362. break;
  363. /* Register the edge flag callbacks. */
  364. case GLU_TESS_EDGE_FLAG:
  365. tobj->callbacks.edgeFlag = (void (GLCALLBACK*)(GLboolean)) fn;
  366. break;
  367. case GLU_TESS_EDGE_FLAG_DATA:
  368. tobj->callbacks.edgeFlagData =
  369. (void (GLCALLBACK*)(GLboolean, void *)) fn;
  370. break;
  371. /* Register the vertex callbacks. */
  372. case GLU_TESS_VERTEX:
  373. tobj->callbacks.vertex = (void (GLCALLBACK*)(void *)) fn;
  374. break;
  375. case GLU_TESS_VERTEX_DATA:
  376. tobj->callbacks.vertexData = (void (GLCALLBACK*)(void *, void *)) fn;
  377. break;
  378. /* Register the end callbacks. */
  379. case GLU_TESS_END:
  380. tobj->callbacks.end = (void (GLCALLBACK*)(void)) fn;
  381. break;
  382. case GLU_TESS_END_DATA:
  383. tobj->callbacks.endData = (void (GLCALLBACK*)(void *)) fn;
  384. break;
  385. /* Register the error callbacks. */
  386. case GLU_TESS_ERROR:
  387. tobj->callbacks.error = (void (GLCALLBACK*)(GLenum)) fn;
  388. break;
  389. case GLU_TESS_ERROR_DATA:
  390. tobj->callbacks.errorData = (void (GLCALLBACK*)(GLenum, void *)) fn;
  391. break;
  392. /* Register the combine callbacks. */
  393. case GLU_TESS_COMBINE:
  394. tobj->callbacks.combine =
  395. (void (GLCALLBACK*)(GLdouble[3], void *[4],
  396. GLfloat [4], void **)) fn;
  397. break;
  398. case GLU_TESS_COMBINE_DATA:
  399. tobj->callbacks.combineData =
  400. (void (GLCALLBACK*)(GLdouble[3], void *[4], GLfloat [4],
  401. void **, void *)) fn;
  402. break;
  403. default:
  404. DEBUGP( 0, ( " gluTessCallback( tobj:%p which:%d ) invalid enum\n", tobj, which ) );
  405. tobj->error = GLU_INVALID_ENUM;
  406. break;
  407. }
  408. }
  409. /*****************************************************************************
  410. * gluTessProperty
  411. *
  412. * Set the current value of the given property.
  413. *****************************************************************************/
  414. void GLAPIENTRY gluTessProperty( GLUtesselator *tobj, GLenum which,
  415. GLdouble value )
  416. {
  417. switch ( which )
  418. {
  419. case GLU_TESS_BOUNDARY_ONLY:
  420. tobj->boundary_only = (GLboolean) value;
  421. break;
  422. case GLU_TESS_TOLERANCE:
  423. DEBUGP( 15, ( " gluTessProperty( tobj:%p ) tolerance: %0.9f\n", tobj, value ) );
  424. tobj->tolerance = value;
  425. break;
  426. case GLU_TESS_WINDING_RULE:
  427. tobj->winding_rule = (GLenum) value;
  428. break;
  429. default:
  430. DEBUGP( 0, ( " gluTessProperty( tobj:%p which:%d ) invalid enum\n", tobj, which ) );
  431. tobj->error = GLU_INVALID_ENUM;
  432. break;
  433. }
  434. }
  435. /*****************************************************************************
  436. * gluGetTessProperty
  437. *
  438. * Return the current value of the given property.
  439. *****************************************************************************/
  440. void GLAPIENTRY gluGetTessProperty( GLUtesselator *tobj, GLenum which,
  441. GLdouble *value )
  442. {
  443. switch ( which )
  444. {
  445. case GLU_TESS_BOUNDARY_ONLY:
  446. *value = tobj->boundary_only;
  447. break;
  448. case GLU_TESS_TOLERANCE:
  449. *value = tobj->tolerance;
  450. break;
  451. case GLU_TESS_WINDING_RULE:
  452. *value = tobj->winding_rule;
  453. break;
  454. default:
  455. DEBUGP( 0, ( " gluGetTessProperty( tobj:%p which:%d ) invalid enum\n", tobj, which ) );
  456. tobj->error = GLU_INVALID_ENUM;
  457. break;
  458. }
  459. }
  460. /*****************************************************************************
  461. * gluTessNormal
  462. *
  463. * Set the current tessellation normal.
  464. *****************************************************************************/
  465. void GLAPIENTRY gluTessNormal( GLUtesselator *tobj, GLdouble x,
  466. GLdouble y, GLdouble z )
  467. {
  468. DEBUGP( 15, ( " gluTessNormal( tobj:%p n:(%.2f,%.2f,%.2f) )\n", tobj, x, y, z ) );
  469. tobj->plane.normal[X] = x;
  470. tobj->plane.normal[Y] = y;
  471. tobj->plane.normal[Z] = z;
  472. }
  473. /*****************************************************************************
  474. *
  475. * OBSOLETE TESSELLATION FUNCTIONS
  476. *
  477. *****************************************************************************/
  478. void GLAPIENTRY gluBeginPolygon( GLUtesselator *tobj )
  479. {
  480. gluTessBeginPolygon( tobj, NULL );
  481. gluTessBeginContour( tobj );
  482. }
  483. void GLAPIENTRY gluNextContour( GLUtesselator *tobj, GLenum type )
  484. {
  485. gluTessEndContour( tobj );
  486. gluTessBeginContour( tobj );
  487. }
  488. void GLAPIENTRY gluEndPolygon( GLUtesselator *tobj )
  489. {
  490. gluTessEndContour( tobj );
  491. gluTessEndPolygon( tobj );
  492. }
  493. /*****************************************************************************
  494. * tess_error_callback
  495. *
  496. * Internal error handler. Call the user-registered error callback.
  497. *
  498. * 2nd arg changed from 'errno' to 'errnum' since MSVC defines errnum as
  499. * a macro (of all things) and thus breaks the build -tjump
  500. *****************************************************************************/
  501. void tess_error_callback( GLUtesselator *tobj, GLenum errnum )
  502. {
  503. if ( tobj->error == GLU_NO_ERROR )
  504. {
  505. tobj->error = errnum;
  506. }
  507. if ( tobj->callbacks.errorData != NULL )
  508. {
  509. ( tobj->callbacks.errorData )( errnum, tobj->user_data );
  510. }
  511. else if ( tobj->callbacks.error != NULL )
  512. {
  513. ( tobj->callbacks.error )( errnum );
  514. }
  515. }
  516. /*****************************************************************************
  517. *
  518. * INTERNAL FUNCTIONS
  519. *
  520. *****************************************************************************/
  521. /*****************************************************************************
  522. * init_callbacks
  523. *****************************************************************************/
  524. static void init_callbacks( tess_callbacks_t *callbacks )
  525. {
  526. callbacks->begin = ( void (GLCALLBACK*)(GLenum) ) NULL;
  527. callbacks->beginData = ( void (GLCALLBACK*)(GLenum, void *) ) NULL;
  528. callbacks->edgeFlag = ( void (GLCALLBACK*)(GLboolean) ) NULL;
  529. callbacks->edgeFlagData = ( void (GLCALLBACK*)(GLboolean, void *) ) NULL;
  530. callbacks->vertex = ( void (GLCALLBACK*)(void *) ) NULL;
  531. callbacks->vertexData = ( void (GLCALLBACK*)(void *, void *) ) NULL;
  532. callbacks->end = ( void (GLCALLBACK*)(void) ) NULL;
  533. callbacks->endData = ( void (GLCALLBACK*)(void *) ) NULL;
  534. callbacks->error = ( void (GLCALLBACK*)(GLenum) ) NULL;
  535. callbacks->errorData = ( void (GLCALLBACK*)(GLenum, void *) ) NULL;
  536. callbacks->combine = ( void (GLCALLBACK*)(GLdouble [3], void *[4],
  537. GLfloat [4], void **) ) NULL;
  538. callbacks->combineData = ( void (GLCALLBACK*)(GLdouble [3], void *[4],
  539. GLfloat [4], void **,
  540. void *) ) NULL;
  541. }
  542. /*****************************************************************************
  543. * tess_cleanup
  544. *****************************************************************************/
  545. static void tess_cleanup( GLUtesselator *tobj )
  546. {
  547. DEBUGP( 15, ( " -> tess_cleanup( tobj:%p )\n", tobj ) );
  548. if ( tobj->current_contour != NULL )
  549. {
  550. delete_current_contour( tobj );
  551. }
  552. if ( tobj->contours != NULL )
  553. {
  554. delete_all_contours( tobj );
  555. }
  556. DEBUGP( 15, ( " <- tess_cleanup( tobj:%p )\n", tobj ) );
  557. }
  558. /*****************************************************************************
  559. * inspect_current_contour
  560. *****************************************************************************/
  561. static GLenum find_normal( GLUtesselator *tobj );
  562. static void project_current_contour( GLUtesselator *tobj );
  563. static GLenum save_current_contour( GLUtesselator *tobj );
  564. static void inspect_current_contour( GLUtesselator *tobj )
  565. {
  566. tess_contour_t *current = tobj->current_contour;
  567. GLdouble origin[3] = { 0.0, 0.0, 0.0 };
  568. DEBUGP( 15, ( " -> inspect_current_contour( tobj:%p )\n", tobj ) );
  569. if ( current->vertex_count < 3 )
  570. {
  571. DEBUGP( 15, ( " count %d < 3, deleting\n", current->vertex_count ) );
  572. delete_current_contour( tobj );
  573. return;
  574. }
  575. current->last_vertex->next = current->vertices;
  576. current->vertices->previous = current->last_vertex;
  577. if ( ( tobj->contours == NULL ) &&
  578. ( COMPARE_3DV( current->plane.normal, origin ) ) )
  579. {
  580. /* We haven't been given a normal, so let's take a guess. */
  581. if ( find_normal( tobj ) == GLU_ERROR ) {
  582. return;
  583. }
  584. COPY_3V( tobj->plane.normal, current->plane.normal );
  585. tobj->plane.dist = current->plane.dist;
  586. }
  587. else
  588. {
  589. DEBUGP( 15, ( " normal: (%.2f,%.2f,%.2f)\n", tobj->plane.normal[X], tobj->plane.normal[Y], tobj->plane.normal[Z] ) );
  590. }
  591. project_current_contour( tobj );
  592. if ( save_current_contour( tobj ) == GLU_ERROR ) {
  593. return;
  594. }
  595. DEBUGP( 15, ( " <- inspect_current_contour( tobj:%p )\n", tobj ) );
  596. }
  597. /*****************************************************************************
  598. * find_normal
  599. *****************************************************************************/
  600. static GLenum find_normal( GLUtesselator *tobj )
  601. {
  602. tess_contour_t *contour = tobj->current_contour;
  603. tess_vertex_t *va, *vb, *vc;
  604. GLdouble a[3], b[3], c[3];
  605. DEBUGP( 15, ( " -> find_normal( tobj:%p )\n", tobj ) );
  606. if ( contour == NULL ) { return GLU_ERROR; }
  607. va = contour->vertices;
  608. vb = va->next;
  609. /* If va and vb are the same point, keep looking for a different vertex. */
  610. while ( COMPARE_3DV( va->coords, vb->coords ) && ( vb != va ) ) {
  611. vb = vb->next;
  612. }
  613. if ( vb == va ) {
  614. DEBUGP( 0, ( "*** error 7 ***\n" ) );
  615. tess_error_callback( tobj, GLU_TESS_ERROR7 );
  616. }
  617. SUB_3V( a, vb->coords, va->coords );
  618. for ( vc = vb->next; vc != va; vc = vc->next )
  619. {
  620. SUB_3V( b, vc->coords, va->coords );
  621. CROSS3( c, a, b );
  622. if ( ( ABSD( c[X] ) > EQUAL_EPSILON ) ||
  623. ( ABSD( c[Y] ) > EQUAL_EPSILON ) ||
  624. ( ABSD( c[Z] ) > EQUAL_EPSILON ) )
  625. {
  626. COPY_3V( contour->plane.normal, c );
  627. NORMALIZE_3DV( contour->plane.normal );
  628. contour->plane.dist = - DOT3( contour->plane.normal, va->coords );
  629. DEBUGP( 15, ( " <- find_normal( tobj:%p ) n: (%.2f,%.2f,%.2f)\n", tobj, contour->plane.normal[X], contour->plane.normal[Y], contour->plane.normal[Z] ) );
  630. return GLU_NO_ERROR;
  631. }
  632. }
  633. DEBUGP( 0, ( "*** error 7 ***\n" ) );
  634. tess_error_callback( tobj, GLU_TESS_ERROR7 );
  635. return GLU_ERROR;
  636. }
  637. /*****************************************************************************
  638. * project_current_contour
  639. *****************************************************************************/
  640. static GLdouble twice_contour_area( tess_vertex_t *vertex,
  641. tess_vertex_t *last_vertex );
  642. static void project_current_contour( GLUtesselator *tobj )
  643. {
  644. tess_contour_t *current = tobj->current_contour;
  645. tess_vertex_t *vertex;
  646. GLdouble area;
  647. GLdouble zaxis[3] = { 0.0, 0.0, 1.0 }, znormal[3], xnormal[3];
  648. GLdouble dot, rotx, roty;
  649. GLuint i;
  650. DEBUGP( 15, ( " -> project_current_contour( tobj:%p )\n", tobj ) );
  651. if ( current == NULL ) { return; }
  652. /* Rotate the plane normal around the y-axis. */
  653. znormal[X] = current->plane.normal[X];
  654. znormal[Y] = 0.0;
  655. znormal[Z] = current->plane.normal[Z];
  656. dot = DOT3( znormal, zaxis );
  657. current->roty = roty = acos( dot );
  658. /* Rotate the plane normal around the x-axis. */
  659. xnormal[X] = cos( roty ) * znormal[X] - sin( roty ) * znormal[Z];
  660. xnormal[Y] = znormal[Y];
  661. xnormal[Z] = sin( roty ) * znormal[X] + cos( roty ) * znormal[Z];
  662. dot = DOT3( xnormal, zaxis );
  663. current->rotx = rotx = acos( dot );
  664. for ( vertex = current->vertices, i = 0;
  665. i < current->vertex_count; vertex = vertex->next, i++ )
  666. {
  667. tess_plane_t *plane = &current->plane;
  668. GLdouble proj[3], yrot[3], xrot[3];
  669. /* FIXME: This needs a cleanup, 'cos I'm sure it's inefficient. */
  670. proj[X] = vertex->coords[X] - plane->dist * plane->normal[X];
  671. proj[Y] = vertex->coords[Y] - plane->dist * plane->normal[Y];
  672. proj[Z] = vertex->coords[Z] - plane->dist * plane->normal[Z];
  673. yrot[X] = cos( roty ) * proj[X] - sin( roty ) * proj[Z];
  674. yrot[Y] = proj[Y];
  675. yrot[Z] = sin( roty ) * proj[X] + cos( roty ) * proj[Z];
  676. xrot[X] = yrot[X];
  677. xrot[Y] = cos( rotx ) * yrot[Y] - sin( rotx ) * yrot[Z];
  678. xrot[Z] = sin( rotx ) * yrot[Y] + cos( rotx ) * yrot[Z];
  679. vertex->v[X] = xrot[X];
  680. vertex->v[Y] = xrot[Y];
  681. ACC_BBOX_2V( vertex->v, tobj->mins, tobj->maxs );
  682. ACC_BBOX_2V( vertex->v, current->mins, current->maxs );
  683. }
  684. area = twice_contour_area( current->vertices,
  685. current->last_vertex );
  686. if ( area >= 0.0 )
  687. {
  688. current->orientation = GLU_CCW;
  689. current->area = area;
  690. }
  691. else
  692. {
  693. current->orientation = GLU_CW;
  694. current->area = -area;
  695. }
  696. DEBUGP( 15, ( " <- project_current_contour( tobj:%p )\n", tobj ) );
  697. }
  698. /*****************************************************************************
  699. * twice_contour_area
  700. *****************************************************************************/
  701. static GLdouble twice_contour_area( tess_vertex_t *vertex,
  702. tess_vertex_t *last_vertex )
  703. {
  704. tess_vertex_t *next;
  705. GLdouble area, x, y;
  706. area = 0.0;
  707. x = vertex->v[X];
  708. y = vertex->v[Y];
  709. vertex = vertex->next;
  710. while ( vertex != last_vertex )
  711. {
  712. next = vertex->next;
  713. area +=
  714. (vertex->v[X] - x) * (next->v[Y] - y) -
  715. (vertex->v[Y] - y) * (next->v[X] - x);
  716. vertex = vertex->next;
  717. }
  718. return area;
  719. }
  720. /*****************************************************************************
  721. * save_current_contour
  722. *****************************************************************************/
  723. static GLenum save_current_contour( GLUtesselator *tobj )
  724. {
  725. tess_contour_t *current = tobj->current_contour;
  726. tess_vertex_t *vertex;
  727. GLuint i;
  728. if ( current == NULL ) { return GLU_ERROR; }
  729. if ( tobj->contours == NULL )
  730. {
  731. tobj->contours = tobj->last_contour = current;
  732. current->next = current->previous = NULL;
  733. }
  734. else
  735. {
  736. current->previous = tobj->last_contour;
  737. tobj->last_contour->next = current;
  738. tobj->last_contour = current;
  739. current->next = NULL;
  740. }
  741. for ( vertex = current->vertices, i = 0;
  742. i < current->vertex_count; vertex = vertex->next, i++ )
  743. {
  744. vertex->shadow_vertex = NULL;
  745. vertex->edge_flag = GL_TRUE;
  746. }
  747. current->type = GLU_UNKNOWN;
  748. tobj->contour_count++;
  749. tobj->current_contour = NULL;
  750. return GLU_NO_ERROR;
  751. }
  752. /*****************************************************************************
  753. * delete_current_contour
  754. *****************************************************************************/
  755. static void delete_current_contour( GLUtesselator *tobj )
  756. {
  757. tess_contour_t *current = tobj->current_contour;
  758. tess_vertex_t *vertex, *next;
  759. GLuint i;
  760. if ( current == NULL ) { return; }
  761. for ( vertex = current->vertices, i = 0; i < current->vertex_count; i++)
  762. {
  763. next = vertex->next;
  764. free( vertex );
  765. vertex = next;
  766. }
  767. free( current );
  768. tobj->current_contour = NULL;
  769. }
  770. /*****************************************************************************
  771. * delete_all_contours
  772. *****************************************************************************/
  773. static void delete_all_contours( GLUtesselator *tobj )
  774. {
  775. tess_contour_t *current = tobj->current_contour, *next_contour;
  776. tess_vertex_t *vertex, *next_vertex;
  777. GLuint i;
  778. if ( current != NULL )
  779. {
  780. delete_current_contour( tobj );
  781. }
  782. for ( current = tobj->contours, i = 0; i < tobj->contour_count; i++ )
  783. {
  784. vertex = current->vertices;
  785. while ( vertex != current->last_vertex )
  786. {
  787. next_vertex = vertex->next;
  788. free( vertex );
  789. vertex = next_vertex;
  790. }
  791. if ( vertex ) {
  792. free( vertex );
  793. }
  794. next_contour = current->next;
  795. free( current );
  796. current = next_contour;
  797. }
  798. tobj->contour_count = tobj->vertex_count = 0;
  799. tobj->contours = tobj->last_contour = NULL;
  800. CLEAR_BBOX_2DV( tobj->mins, tobj->maxs );
  801. ZERO_3V( tobj->plane.normal );
  802. tobj->plane.dist = 0.0;
  803. }
  804. #ifdef DEBUG
  805. /*****************************************************************************
  806. * Debugging output
  807. *****************************************************************************/
  808. int tess_debug_level = 1;
  809. int vdebugstr( char *format_str, ... )
  810. {
  811. va_list ap;
  812. va_start( ap, format_str );
  813. vfprintf( DEBUG_STREAM, format_str, ap );
  814. va_end( ap );
  815. return 0;
  816. }
  817. #endif