Synchronize with trunk's revision r57629.
[reactos.git] / dll / opengl / glu32 / src / libnurbs / internals / splitarcs.cc
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 * splitarcs.c++
37 *
38 */
39
40 #include "glimports.h"
41 #include "myassert.h"
42 #include "mysetjmp.h"
43 #include "mystdio.h"
44 #include "subdivider.h"
45 #include "arcsorter.h"
46 #include "arc.h"
47 #include "bin.h"
48
49 /* local preprocessor definitions */
50 #define MAXARCS 10
51
52 /*----------------------------------------------------------------------------
53 * Subdivider::split - split trim regions in source bin by line (param == value).
54 *----------------------------------------------------------------------------
55 */
56
57 void
58 Subdivider::split( Bin& bin, Bin& left, Bin& right, int param, REAL value )
59 {
60 Bin intersections, unknown;
61
62 partition( bin, left, intersections, right, unknown, param, value );
63
64 int count = intersections.numarcs();
65 if( count % 2 ) {
66 #ifndef NDEBUG
67 left.show( "left" );
68 intersections.show( "intersections" );
69 right.show( "right" );
70 #endif
71 ::mylongjmp( jumpbuffer, 29 );
72 }
73
74 Arc_ptr arclist[MAXARCS], *list;
75 if( count >= MAXARCS ) {
76 list = new Arc_ptr[count];
77 } else {
78 list = arclist;
79 }
80
81 Arc_ptr jarc, *last, *lptr;
82 for( last = list; (jarc=intersections.removearc()) != NULL; last++ )
83 *last = jarc;
84
85 if( param == 0 ) { /* sort into increasing t order */
86 ArcSdirSorter sorter(*this);
87 sorter.qsort( list, count );
88
89 //::qsort ((void *)list, count, sizeof(Arc_ptr), (cmpfunc)compare_s);
90 for( lptr=list; lptr<last; lptr+=2 )
91 check_s ( lptr[0], lptr[1] );
92 for( lptr=list; lptr<last; lptr+=2 )
93 join_s ( left, right, lptr[0], lptr[1] );
94 for( lptr=list; lptr != last; lptr++ ) {
95 if( ((*lptr)->head()[0] <= value) && ((*lptr)->tail()[0] <= value) )
96 left.addarc( *lptr );
97 else
98 right.addarc( *lptr );
99 }
100 } else { /* sort into decreasing s order */
101 ArcTdirSorter sorter(*this);
102 sorter.qsort( list, count );
103 //::qsort ((void *)list, count, sizeof(Arc_ptr), (cmpfunc)compare_t);
104 for( lptr=list; lptr<last; lptr+=2 )
105 check_t ( lptr[0], lptr[1] );
106 for( lptr=list; lptr<last; lptr+=2 )
107 join_t ( left, right, lptr[0], lptr[1] );
108 for( lptr=list; lptr != last; lptr++ ) {
109 if( ((*lptr)->head()[1] <= value) && ((*lptr)->tail()[1] <= value) )
110 left.addarc( *lptr );
111 else
112 right.addarc( *lptr );
113 }
114 }
115
116 if( list != arclist ) delete[] list;
117 unknown.adopt();
118 }
119
120
121 void
122 Subdivider::check_s( Arc_ptr jarc1, Arc_ptr jarc2 )
123 {
124 assert( jarc1->check( ) != 0 );
125 assert( jarc2->check( ) != 0 );
126 assert( jarc1->next->check( ) != 0 );
127 assert( jarc2->next->check( ) != 0 );
128 assert( jarc1 != jarc2 );
129
130 /* XXX - if these assertions fail, it is due to user error or
131 undersampling */
132 if( ! ( jarc1->tail()[0] < (jarc1)->head()[0] ) ) {
133 #ifndef NDEBUG
134 _glu_dprintf( "s difference %f\n", (jarc1)->tail()[0] - (jarc1)->head()[0] );
135 #endif
136 ::mylongjmp( jumpbuffer, 28 );
137 }
138
139 if( ! ( jarc2->tail()[0] > (jarc2)->head()[0] ) ) {
140 #ifndef NDEBUG
141 _glu_dprintf( "s difference %f\n", (jarc2)->tail()[0] - (jarc2)->head()[0] );
142 #endif
143 ::mylongjmp( jumpbuffer, 28 );
144 }
145 }
146
147 inline void
148 Subdivider::link( Arc_ptr jarc1, Arc_ptr jarc2, Arc_ptr up, Arc_ptr down )
149 {
150 up->nuid = down->nuid = 0; // XXX
151
152 up->next = jarc2;
153 down->next = jarc1;
154 up->prev = jarc1->prev;
155 down->prev = jarc2->prev;
156
157 down->next->prev = down;
158 up->next->prev = up;
159 down->prev->next = down;
160 up->prev->next = up;
161 }
162
163 inline void
164 Subdivider::simple_link( Arc_ptr jarc1, Arc_ptr jarc2 )
165 {
166 Arc_ptr tmp = jarc2->prev;
167 jarc2->prev = jarc1->prev;
168 jarc1->prev = tmp;
169 jarc2->prev->next = jarc2;
170 jarc1->prev->next = jarc1;
171 }
172
173
174 /*----------------------------------------------------------------------------
175 * join - add a pair of oppositely directed jordan arcs between two arcs
176 *----------------------------------------------------------------------------
177 */
178
179 void
180 Subdivider::join_s( Bin& left, Bin& right, Arc_ptr jarc1, Arc_ptr jarc2 )
181 {
182 assert( jarc1->check( ) != 0);
183 assert( jarc2->check( ) != 0);
184 assert( jarc1 != jarc2 );
185
186 if( ! jarc1->getitail() )
187 jarc1 = jarc1->next;
188
189 if( ! jarc2->getitail() )
190 jarc2 = jarc2->next;
191
192 REAL s = jarc1->tail()[0];
193 REAL t1 = jarc1->tail()[1];
194 REAL t2 = jarc2->tail()[1];
195
196 if( t1 == t2 ) {
197 simple_link( jarc1, jarc2 );
198 } else {
199 Arc_ptr newright = new(arcpool) Arc( arc_right, 0 );
200 Arc_ptr newleft = new(arcpool) Arc( arc_left, 0 );
201 assert( t1 < t2 );
202 if( isBezierArcType() ) {
203 arctessellator.bezier( newright, s, s, t1, t2 );
204 arctessellator.bezier( newleft, s, s, t2, t1 );
205 } else {
206 arctessellator.pwl_right( newright, s, t1, t2, stepsizes[0] );
207 arctessellator.pwl_left( newleft, s, t2, t1, stepsizes[2] );
208 }
209 link( jarc1, jarc2, newright, newleft );
210 left.addarc( newright );
211 right.addarc( newleft );
212 }
213
214 assert( jarc1->check( ) != 0 );
215 assert( jarc2->check( ) != 0 );
216 assert( jarc1->next->check( ) != 0);
217 assert( jarc2->next->check( ) != 0);
218 }
219
220 void
221 Subdivider::check_t( Arc_ptr jarc1, Arc_ptr jarc2 )
222 {
223 assert( jarc1->check( ) != 0 );
224 assert( jarc2->check( ) != 0 );
225 assert( jarc1->next->check( ) != 0 );
226 assert( jarc2->next->check( ) != 0 );
227 assert( jarc1 != jarc2 );
228
229 /* XXX - if these assertions fail, it is due to user error or
230 undersampling */
231 if( ! ( jarc1->tail()[1] < (jarc1)->head()[1] ) ) {
232 #ifndef NDEBUG
233 _glu_dprintf( "t difference %f\n", jarc1->tail()[1] - (jarc1)->head()[1] );
234 #endif
235 ::mylongjmp( jumpbuffer, 28 );
236 }
237
238 if( ! ( jarc2->tail()[1] > (jarc2)->head()[1] ) ) {
239 #ifndef NDEBUG
240 _glu_dprintf( "t difference %f\n", jarc2->tail()[1] - (jarc2)->head()[1] );
241 #endif
242 ::mylongjmp( jumpbuffer, 28 );
243 }
244 }
245
246 /*----------------------------------------------------------------------------
247 * join_t - add a pair of oppositely directed jordan arcs between two arcs
248 *----------------------------------------------------------------------------
249 */
250
251 void
252 Subdivider::join_t( Bin& bottom, Bin& top, Arc_ptr jarc1, Arc_ptr jarc2 )
253 {
254 assert( jarc1->check( ) != 0 );
255 assert( jarc2->check( ) != 0 );
256 assert( jarc1->next->check( ) != 0 );
257 assert( jarc2->next->check( ) != 0 );
258 assert( jarc1 != jarc2 );
259
260 if( ! jarc1->getitail() )
261 jarc1 = jarc1->next;
262
263 if( ! jarc2->getitail() )
264 jarc2 = jarc2->next;
265
266 REAL s1 = jarc1->tail()[0];
267 REAL s2 = jarc2->tail()[0];
268 REAL t = jarc1->tail()[1];
269
270 if( s1 == s2 ) {
271 simple_link( jarc1, jarc2 );
272 } else {
273 Arc_ptr newtop = new(arcpool) Arc( arc_top, 0 );
274 Arc_ptr newbot = new(arcpool) Arc( arc_bottom, 0 );
275 assert( s1 > s2 );
276 if( isBezierArcType() ) {
277 arctessellator.bezier( newtop, s1, s2, t, t );
278 arctessellator.bezier( newbot, s2, s1, t, t );
279 } else {
280 arctessellator.pwl_top( newtop, t, s1, s2, stepsizes[1] );
281 arctessellator.pwl_bottom( newbot, t, s2, s1, stepsizes[3] );
282 }
283 link( jarc1, jarc2, newtop, newbot );
284 bottom.addarc( newtop );
285 top.addarc( newbot );
286 }
287
288 assert( jarc1->check( ) != 0 );
289 assert( jarc2->check( ) != 0 );
290 assert( jarc1->next->check( ) != 0 );
291 assert( jarc2->next->check( ) != 0 );
292 }
293