mesher.cc revision f220fa62
1/*
2** License Applicability. Except to the extent portions of this file are
3** made subject to an alternative license as permitted in the SGI Free
4** Software License B, Version 1.1 (the "License"), the contents of this
5** file are subject only to the provisions of the License. You may not use
6** this file except in compliance with the License. You may obtain a copy
7** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
8** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
9**
10** http://oss.sgi.com/projects/FreeB
11**
12** Note that, as provided in the License, the Software is distributed on an
13** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
14** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
15** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
16** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
17**
18** Original Code. The Original Code is: OpenGL Sample Implementation,
19** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
20** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
21** Copyright in any portions created by third parties is as indicated
22** elsewhere herein. All Rights Reserved.
23**
24** Additional Notice Provisions: The application programming interfaces
25** established by SGI in conjunction with the Original Code are The
26** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
27** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
28** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
29** Window System(R) (Version 1.3), released October 19, 1998. This software
30** was created using the OpenGL(R) version 1.2.1 Sample Implementation
31** published by SGI, but has not been independently verified as being
32** compliant with the OpenGL(R) version 1.2.1 Specification.
33*/
34
35/*
36 * mesher.c++
37 *
38 */
39
40#include "glimports.h"
41#include "myassert.h"
42#include "mystdio.h"
43#include "gridvertex.h"
44#include "gridtrimvertex.h"
45#include "jarcloc.h"
46#include "gridline.h"
47#include "trimline.h"
48#include "uarray.h"
49#include "backend.h"
50#include "mesher.h"
51
52
53const float Mesher::ZERO = 0.0;
54
55Mesher::Mesher( Backend& b )
56	: backend( b ),
57	p( sizeof( GridTrimVertex ), 100, "GridTrimVertexPool" )
58{
59    stacksize = 0;
60    vdata = 0;
61    last[0] = 0;
62    last[1] = 0;
63    itop = 0;
64    lastedge = 0; //needed to prevent purify UMR
65}
66
67Mesher::~Mesher( void )
68{
69    if( vdata ) delete[] vdata;
70}
71
72void
73Mesher::init( unsigned int npts )
74{
75    p.clear();
76    if( stacksize < npts ) {
77	stacksize = 2 * npts;
78	if( vdata ) delete[] vdata;
79	vdata = new GridTrimVertex_p[stacksize];
80    }
81}
82
83inline void
84Mesher::push( GridTrimVertex *gt )
85{
86    assert( itop+1 != (int)stacksize );
87    vdata[++itop] = gt;
88}
89
90inline void
91Mesher::pop( long )
92{
93}
94
95inline void
96Mesher::openMesh()
97{
98    backend.bgntmesh( "addedge" );
99}
100
101inline void
102Mesher::closeMesh()
103{
104    backend.endtmesh();
105}
106
107inline void
108Mesher::swapMesh()
109{
110    backend.swaptmesh();
111}
112
113inline void
114Mesher::clearStack()
115{
116    itop = -1;
117    last[0] = 0;
118}
119
120void
121Mesher::finishLower( GridTrimVertex *gtlower )
122{
123    for( push(gtlower);
124	 nextlower( gtlower=new(p) GridTrimVertex );
125	 push(gtlower) )
126	    addLower();
127    addLast();
128}
129
130void
131Mesher::finishUpper( GridTrimVertex *gtupper )
132{
133    for( push(gtupper);
134	 nextupper( gtupper=new(p) GridTrimVertex );
135	 push(gtupper) )
136	    addUpper();
137    addLast();
138}
139
140void
141Mesher::mesh( void )
142{
143    GridTrimVertex *gtlower, *gtupper;
144
145    Hull::init( );
146    nextupper( gtupper = new(p) GridTrimVertex );
147    nextlower( gtlower = new(p) GridTrimVertex );
148
149    clearStack();
150    openMesh();
151    push(gtupper);
152
153    nextupper( gtupper = new(p) GridTrimVertex );
154    nextlower( gtlower );
155
156    assert( gtupper->t && gtlower->t );
157
158    if( gtupper->t->param[0] < gtlower->t->param[0] ) {
159	push(gtupper);
160	lastedge = 1;
161	if( nextupper( gtupper=new(p) GridTrimVertex ) == 0 ) {
162	    finishLower(gtlower);
163	    return;
164	}
165    } else if( gtupper->t->param[0] > gtlower->t->param[0] ) {
166	push(gtlower);
167	lastedge = 0;
168	if( nextlower( gtlower=new(p) GridTrimVertex ) == 0 ) {
169	    finishUpper(gtupper);
170	    return;
171	}
172    } else {
173	if( lastedge == 0 ) {
174	    push(gtupper);
175	    lastedge = 1;
176	    if( nextupper(gtupper=new(p) GridTrimVertex) == 0 ) {
177		finishLower(gtlower);
178		return;
179	    }
180	} else {
181	    push(gtlower);
182	    lastedge = 0;
183	    if( nextlower( gtlower=new(p) GridTrimVertex ) == 0 ) {
184		finishUpper(gtupper);
185		return;
186	    }
187	}
188    }
189
190    while ( 1 ) {
191	if( gtupper->t->param[0] < gtlower->t->param[0] ) {
192            push(gtupper);
193	    addUpper();
194	    if( nextupper( gtupper=new(p) GridTrimVertex ) == 0 ) {
195		finishLower(gtlower);
196		return;
197	    }
198	} else if( gtupper->t->param[0] > gtlower->t->param[0] ) {
199    	    push(gtlower);
200	    addLower();
201	    if( nextlower( gtlower=new(p) GridTrimVertex ) == 0 ) {
202		finishUpper(gtupper);
203		return;
204	    }
205	} else {
206	    if( lastedge == 0 ) {
207		push(gtupper);
208		addUpper();
209		if( nextupper( gtupper=new(p) GridTrimVertex ) == 0 ) {
210		    finishLower(gtlower);
211		    return;
212		}
213	    } else {
214		push(gtlower);
215		addLower();
216		if( nextlower( gtlower=new(p) GridTrimVertex ) == 0 ) {
217		    finishUpper(gtupper);
218		    return;
219		}
220	    }
221	}
222    }
223}
224
225inline int
226Mesher::isCcw( int ilast )
227{
228    REAL area = det3( vdata[ilast]->t, vdata[itop-1]->t, vdata[itop-2]->t );
229    return (area < ZERO) ? 0 : 1;
230}
231
232inline int
233Mesher::isCw( int ilast  )
234{
235    REAL area = det3( vdata[ilast]->t, vdata[itop-1]->t, vdata[itop-2]->t );
236    return (area > -ZERO) ? 0 : 1;
237}
238
239inline int
240Mesher::equal( int x, int y )
241{
242    return( last[0] == vdata[x] && last[1] == vdata[y] );
243}
244
245inline void
246Mesher::copy( int x, int y )
247{
248    last[0] = vdata[x]; last[1] = vdata[y];
249}
250
251inline void
252Mesher::move( int x, int y )
253{
254    vdata[x] = vdata[y];
255}
256
257inline void
258Mesher::output( int x )
259{
260    backend.tmeshvert( vdata[x] );
261}
262
263/*---------------------------------------------------------------------------
264 * addedge - addedge an edge to the triangulation
265 *
266 *	This code has been re-written to generate large triangle meshes
267 *	from a monotone polygon.  Although smaller triangle meshes
268 *	could be generated faster and with less code, larger meshes
269 *	actually give better SYSTEM performance.  This is because
270 *	vertices are processed in the backend slower than they are
271 *	generated by this code and any decrease in the number of vertices
272 *	results in a decrease in the time spent in the backend.
273 *---------------------------------------------------------------------------
274 */
275
276void
277Mesher::addLast( )
278{
279    register int ilast = itop;
280
281    if( lastedge == 0 ) {
282	if( equal( 0, 1 ) ) {
283	    output( ilast );
284	    swapMesh();
285	    for( register int i = 2; i < ilast; i++ ) {
286		swapMesh();
287		output( i );
288	    }
289	    copy( ilast, ilast-1 );
290	} else if( equal( ilast-2, ilast-1) ) {
291	    swapMesh();
292	    output( ilast );
293	    for( register int i = ilast-3; i >= 0; i-- ) {
294		output( i );
295		swapMesh();
296	    }
297	    copy( 0, ilast );
298	} else {
299	    closeMesh();	openMesh();
300	    output( ilast );
301	    output( 0 );
302	    for( register int i = 1; i < ilast; i++ ) {
303		swapMesh();
304		output( i );
305	    }
306	    copy( ilast, ilast-1 );
307	}
308    } else {
309	if( equal( 1, 0) ) {
310	    swapMesh();
311	    output( ilast );
312	    for( register int i = 2; i < ilast; i++ ) {
313		output( i );
314		swapMesh();
315	    }
316	    copy( ilast-1, ilast );
317	} else if( equal( ilast-1, ilast-2) ) {
318	    output( ilast );
319	    swapMesh();
320	    for( register int i = ilast-3; i >= 0; i-- ) {
321		swapMesh();
322		output( i );
323	    }
324	    copy( ilast, 0 );
325	} else {
326	    closeMesh();	openMesh();
327	    output( 0 );
328	    output( ilast );
329	    for( register int i = 1; i < ilast; i++ ) {
330		output( i );
331		swapMesh();
332	    }
333	    copy( ilast-1, ilast );
334	}
335    }
336    closeMesh();
337    //for( register long k=0; k<=ilast; k++ ) pop( k );
338}
339
340void
341Mesher::addUpper( )
342{
343    register int ilast = itop;
344
345    if( lastedge == 0 ) {
346	if( equal( 0, 1 ) ) {
347	    output( ilast );
348	    swapMesh();
349	    for( register int i = 2; i < ilast; i++ ) {
350		swapMesh();
351		output( i );
352	    }
353	    copy( ilast, ilast-1 );
354	} else if( equal( ilast-2, ilast-1) ) {
355	    swapMesh();
356	    output( ilast );
357	    for( register int i = ilast-3; i >= 0; i-- ) {
358		output( i );
359		swapMesh();
360	    }
361	    copy( 0, ilast );
362	} else {
363	    closeMesh();	openMesh();
364	    output( ilast );
365	    output( 0 );
366	    for( register int i = 1; i < ilast; i++ ) {
367		swapMesh();
368		output( i );
369	    }
370	    copy( ilast, ilast-1 );
371	}
372	lastedge = 1;
373        //for( register long k=0; k<ilast-1; k++ ) pop( k );
374	move( 0, ilast-1 );
375	move( 1, ilast );
376	itop = 1;
377    } else {
378	if( ! isCcw( ilast ) ) return;
379	do {
380	    itop--;
381	} while( (itop > 1) && isCcw( ilast ) );
382
383	if( equal( ilast-1, ilast-2 ) ) {
384	    output( ilast );
385	    swapMesh();
386	    for( register int i=ilast-3; i>=itop-1; i-- ) {
387		swapMesh();
388		output( i );
389	    }
390	    copy( ilast, itop-1 );
391	} else if( equal( itop, itop-1 ) ) {
392	    swapMesh();
393	    output( ilast );
394	    for( register int i = itop+1; i < ilast; i++ ) {
395		output( i );
396		swapMesh();
397	    }
398	    copy( ilast-1, ilast );
399	} else {
400	    closeMesh();	openMesh();
401	    output( ilast );
402	    output( ilast-1 );
403	    for( register int i=ilast-2; i>=itop-1; i-- ) {
404		swapMesh();
405		output( i );
406	    }
407	    copy( ilast, itop-1 );
408	}
409        //for( register int k=itop; k<ilast; k++ ) pop( k );
410	move( itop, ilast );
411    }
412}
413
414void
415Mesher::addLower()
416{
417    register int ilast = itop;
418
419    if( lastedge == 1 ) {
420	if( equal( 1, 0) ) {
421	    swapMesh();
422	    output( ilast );
423	    for( register int i = 2; i < ilast; i++ ) {
424		output( i );
425		swapMesh();
426	    }
427	    copy( ilast-1, ilast );
428	} else if( equal( ilast-1, ilast-2) ) {
429	    output( ilast );
430	    swapMesh();
431	    for( register int i = ilast-3; i >= 0; i-- ) {
432		swapMesh();
433		output( i );
434	    }
435	    copy( ilast, 0 );
436	} else {
437	    closeMesh();	openMesh();
438	    output( 0 );
439	    output( ilast );
440	    for( register int i = 1; i < ilast; i++ ) {
441		output( i );
442		swapMesh();
443	    }
444	    copy( ilast-1, ilast );
445	}
446
447	lastedge = 0;
448        //for( register long k=0; k<ilast-1; k++ ) pop( k );
449	move( 0, ilast-1 );
450	move( 1, ilast );
451	itop = 1;
452    } else {
453	if( ! isCw( ilast ) ) return;
454	do {
455	    itop--;
456	} while( (itop > 1) && isCw( ilast ) );
457
458	if( equal( ilast-2, ilast-1) ) {
459	    swapMesh();
460	    output( ilast );
461	    for( register int i=ilast-3; i>=itop-1; i--) {
462		output( i );
463		swapMesh( );
464	    }
465	    copy( itop-1, ilast );
466	} else if( equal( itop-1, itop) ) {
467	    output( ilast );
468	    swapMesh();
469	    for( register int i=itop+1; i<ilast; i++ ) {
470		swapMesh( );
471		output( i );
472	    }
473	    copy( ilast, ilast-1 );
474	} else {
475	    closeMesh();	openMesh();
476	    output( ilast-1 );
477	    output( ilast );
478	    for( register int i=ilast-2; i>=itop-1; i-- ) {
479		output( i );
480		swapMesh( );
481	    }
482	    copy( itop-1, ilast );
483	}
484        //for( register int k=itop; k<ilast; k++ ) pop( k );
485	move( itop, ilast );
486    }
487}
488
489
490