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:
10 ** http://oss.sgi.com/projects/FreeB
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.
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.
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.
34 ** $Date: 2001/03/17 00:25:41 $ $Revision: 1.1 $
37 ** $Header: /home/krh/git/sync/mesa-cvs-repo/Mesa/src/glu/sgi/libnurbs/nurbtess/sampleCompRight.cc,v 1.1 2001/03/17 00:25:41 brianp Exp $
42 #include "glimports.h"
44 #include "sampleCompRight.h"
46 #define max(a,b) ((a>b)? a:b)
47 #define min(a,b) ((a>b)? b:a)
53 /*notice that we need leftChain because the
54 *corners could be on the leftChain.
56 void sampleCompRight(Real
* topVertex
, Real
* botVertex
,
57 vertexArray
* leftChain
,
58 Int leftStartIndex
, Int leftEndIndex
,
59 vertexArray
* rightChain
,
60 Int rightStartIndex
, Int rightEndIndex
,
61 gridBoundaryChain
* rightGridChain
,
62 Int gridIndex1
, Int gridIndex2
,
63 Int up_rightCornerWhere
,
64 Int up_rightCornerIndex
,
65 Int down_rightCornerWhere
,
66 Int down_rightCornerIndex
,
69 /*find out whether there is a trim vertex which is
70 *inbetween the top and bot grid lines or not.
74 Int gridMidIndex1
, gridMidIndex2
;
75 //midIndex1: array[i] <= v, array[i+1] > v
76 //midIndex2: array[i] >= v, array[i+1] < v
77 midIndex1
= rightChain
->findIndexBelowGen(rightGridChain
->get_v_value(gridIndex1
),
80 midIndex2
= -1; //initilization
81 if(midIndex1
<= rightEndIndex
&& gridIndex1
< gridIndex2
)
82 if(rightChain
->getVertex(midIndex1
)[1] >= rightGridChain
->get_v_value(gridIndex2
))
84 //midIndex2 must exist:
85 midIndex2
= rightChain
->findIndexAboveGen(rightGridChain
->get_v_value(gridIndex2
),
86 midIndex1
, //midIndex1<=midIndex2
88 //find gridMidIndex1 so that either it=gridIndex1 when the gridline is
89 // at the same height as trim vertex midIndex1, or it is the last one
90 //which is strictly above midIndex1.
92 Real temp
= rightChain
->getVertex(midIndex1
)[1];
93 if(rightGridChain
->get_v_value(gridIndex1
) == temp
)
94 gridMidIndex1
= gridIndex1
;
97 gridMidIndex1
= gridIndex1
;
98 while(rightGridChain
->get_v_value(gridMidIndex1
) > temp
)
102 }//end of find gridMindIndex1
103 //find gridMidIndex2 so that it is the (first one below or equal
104 //midIndex) last one above or equal midIndex2
106 Real temp
= rightChain
->getVertex(midIndex2
)[1];
107 for(gridMidIndex2
= gridMidIndex1
+1; gridMidIndex2
<= gridIndex2
; gridMidIndex2
++)
108 if(rightGridChain
->get_v_value(gridMidIndex2
) <= temp
)
111 assert(gridMidIndex2
<= gridIndex2
);
112 }//end of find gridMidIndex2
117 //to interprete the corner information
120 Int cornerRightStart
;
123 Int cornerLeftDownStart
;
124 if(up_rightCornerWhere
== 2) //right corner is on right chain
126 cornerTop
= rightChain
->getVertex(up_rightCornerIndex
);
127 cornerRightStart
= up_rightCornerIndex
+1;
128 cornerLeftUpEnd
= -1; //no left
130 else if(up_rightCornerWhere
== 1) //right corner is on top
132 cornerTop
= topVertex
;
133 cornerRightStart
= rightStartIndex
;
134 cornerLeftUpEnd
= -1; //no left
136 else //right corner is on left chain
138 cornerTop
= topVertex
;
139 cornerRightStart
= rightStartIndex
;
140 cornerLeftUpEnd
= up_rightCornerIndex
;
143 if(down_rightCornerWhere
== 2) //right corner is on right chan
145 cornerBot
= rightChain
->getVertex(down_rightCornerIndex
);
146 cornerRightEnd
= down_rightCornerIndex
-1;
147 cornerLeftDownStart
= leftEndIndex
+1; //no left
149 else if (down_rightCornerWhere
== 1) //right corner is at bot
151 cornerBot
= botVertex
;
152 cornerRightEnd
= rightEndIndex
;
153 cornerLeftDownStart
= leftEndIndex
+1; //no left
155 else //right corner is on the left chain
157 cornerBot
= botVertex
;
158 cornerRightEnd
= rightEndIndex
;
159 cornerLeftDownStart
= down_rightCornerIndex
;
163 if(midIndex2
>= 0) //there is a trm point between grid lines
166 sampleRightSingleTrimEdgeRegionGen(cornerTop
, rightChain
->getVertex(midIndex1
),
176 0, //no left down section,
180 sampleRightSingleTrimEdgeRegionGen(rightChain
->getVertex(midIndex2
),
189 0, //no left up section
195 sampleRightStripRecF(rightChain
,
206 sampleRightSingleTrimEdgeRegionGen(cornerTop
, cornerBot
,
222 void sampleRightSingleTrimEdgeRegionGen(Real topVertex
[2], Real botVertex
[2],
223 vertexArray
* rightChain
,
226 gridBoundaryChain
* gridChain
,
229 vertexArray
* leftChain
,
237 /*creat an array to store all the up and down secments of the left chain,
238 *and the right end grid points
240 *although vertex array is a dynamic array, but to gain efficiency,
241 *it is better to initiliza the exact array size
243 vertexArray
vArray(gridEndIndex
-gridBeginIndex
+1 +
244 max(0,leftUpEnd
- leftUpBegin
+1)+
245 max(0,leftDownEnd
- leftDownBegin
+1));
246 //append the vertices on the up section of the left chain
247 for(i
=leftUpBegin
; i
<= leftUpEnd
; i
++)
248 vArray
.appendVertex(leftChain
->getVertex(i
));
250 //append the vertices of the right extremal grid points,
251 //and at the same time, perform triangulation for the stair cases
252 vArray
.appendVertex(gridChain
->get_vertex(gridBeginIndex
));
254 for(k
=1, i
=gridBeginIndex
+1; i
<= gridEndIndex
; i
++, k
++)
256 vArray
.appendVertex(gridChain
->get_vertex(i
));
258 //output the fan of the grid points of the (i)th and (i-1)th grid line.
259 gridChain
->rightEndFan(i
, pStream
);
262 //append all the vertices on the down section of the left chain
263 for(i
=leftDownBegin
; i
<= leftDownEnd
; i
++)
264 vArray
.appendVertex(leftChain
->getVertex(i
));
265 monoTriangulationRecGen(topVertex
, botVertex
,
266 &vArray
, 0, vArray
.getNumElements()-1,
267 rightChain
, rightStart
, rightEnd
,
271 void sampleRightSingleTrimEdgeRegion(Real upperVert
[2], Real lowerVert
[2],
272 gridBoundaryChain
* gridChain
,
278 vertexArray
vArray(endIndex
-beginIndex
+1);
279 vArray
.appendVertex(gridChain
->get_vertex(beginIndex
));
280 for(k
=1, i
=beginIndex
+1; i
<= endIndex
; i
++, k
++)
282 vArray
.appendVertex(gridChain
->get_vertex(i
));
283 //output the fan of the grid points of the (i)_th and i-1th gridLine
284 gridChain
->rightEndFan(i
, pStream
);
286 monoTriangulation2(upperVert
, lowerVert
, &vArray
, 0, endIndex
-beginIndex
,
287 1, //increase chain (to the left)
292 /*the gridlines from rightGridChainStartIndex to
293 *rightGridChainEndIndex are assumed to form a
294 *connected componenet
295 *the trm vertex of topRightIndex is assumed to be below
296 *or equal the first gridLine, and the trm vertex of
297 *botRightIndex is assumed to be above or equal the last gridline
298 **there could be multipe trm vertices equal to the last gridline, but
299 **only one could be equal to top gridline. shape: ____| (recall that
300 **for left chain recF, we allow shape: |----
301 *if botRightIndex<topRightIndex, then no connected componenet exists, and
302 *no triangles are generated.
303 *Othewise, botRightIndex>= topRightIndex, there is at least one triangles to
306 void sampleRightStripRecF(vertexArray
* rightChain
,
309 gridBoundaryChain
* rightGridChain
,
310 Int rightGridChainStartIndex
,
311 Int rightGridChainEndIndex
,
316 //sstop conditionL: if topRightIndex > botRightIndex, then stop
317 if(topRightIndex
> botRightIndex
)
320 //if there is only one grid line, return
321 if(rightGridChainStartIndex
>= rightGridChainEndIndex
)
325 assert(rightChain
->getVertex(topRightIndex
)[1] <= rightGridChain
->get_v_value(rightGridChainStartIndex
) &&
326 rightChain
->getVertex(botRightIndex
)[1] >= rightGridChain
->get_v_value(rightGridChainEndIndex
));
328 //firstfind the first trim vertex which is strictly below the second top
330 Real secondGridChainV
= rightGridChain
->get_v_value(rightGridChainStartIndex
+1);
331 Int index1
= topRightIndex
;
332 while(rightChain
->getVertex(index1
)[1] >= secondGridChainV
){
334 if(index1
> botRightIndex
)
337 //now rightChain->getVertex(index1-1)[1] >= secondGridChainV and
338 //rightChain->getVertex(index1)[1] < secondGridChainV and
339 //we should include index1-1 to perform a gridStep
342 //now we have rightChain->getVertex(index1)[1] >= secondGridChainV, and
343 //rightChain->getVertex(index1+1)[1] < secondGridChainV
344 sampleRightOneGridStep(rightChain
, topRightIndex
, index1
, rightGridChain
, rightGridChainStartIndex
, pStream
);
346 //if rightChain->getVertex(index1)[1] ==secondGridChainV then we can
347 //recurvesively to the rest
348 if(rightChain
->getVertex(index1
)[1] == secondGridChainV
)
352 sampleRightStripRecF(rightChain
, index1
, botRightIndex
, rightGridChain
, rightGridChainStartIndex
+1, rightGridChainEndIndex
, pStream
);
354 else if(index1
< botRightIndex
)
356 //otherwise, we have rightChain->getVertex(index1)[1] > secondV
357 //let the next trim vertex be nextTrimVertex, (which should be strictly
358 //below the second grid line). Find the last grid line index2 which is STRICTLY ABOVE
360 //sample one trm edge region.
361 Real
*uppervert
, *lowervert
;
362 uppervert
= rightChain
->getVertex(index1
);
363 lowervert
= rightChain
->getVertex(index1
+1); //okay since index1<botRightindex
364 Int index2
= rightGridChainStartIndex
+1;
365 while(rightGridChain
->get_v_value(index2
) > lowervert
[1])
368 if(index2
> rightGridChainEndIndex
)
373 sampleRightSingleTrimEdgeRegion(uppervert
, lowervert
, rightGridChain
, rightGridChainStartIndex
+1, index2
, pStream
);
376 sampleRightStripRecF(rightChain
, index1
+1, botRightIndex
, rightGridChain
, index2
, rightGridChainEndIndex
, pStream
);
380 //the degenerate case of sampleRightOneGridStep
381 void sampleRightOneGridStepNoMiddle(vertexArray
* rightChain
,
384 gridBoundaryChain
* rightGridChain
,
385 Int rightGridChainStartIndex
,
388 /*since there is no middle, there is at most one point which is on the
389 *second grid line, there could be multiple points on the first (top)
392 rightGridChain
->rightEndFan(rightGridChainStartIndex
+1, pStream
);
393 monoTriangulation2(rightGridChain
->get_vertex(rightGridChainStartIndex
),
394 rightGridChain
->get_vertex(rightGridChainStartIndex
+1),
402 //sampling the right area in between two grid lines
404 void sampleRightOneGridStep(vertexArray
* rightChain
,
407 gridBoundaryChain
* rightGridChain
,
408 Int rightGridChainStartIndex
,
411 if(checkMiddle(rightChain
, beginRightIndex
, endRightIndex
,
412 rightGridChain
->get_v_value(rightGridChainStartIndex
),
413 rightGridChain
->get_v_value(rightGridChainStartIndex
+1))<0)
415 sampleRightOneGridStepNoMiddle(rightChain
, beginRightIndex
, endRightIndex
, rightGridChain
, rightGridChainStartIndex
, pStream
);
421 directedLine
* poly
= NULL
;
424 gridWrap
* grid
= rightGridChain
->getGrid();
429 Int innerInd
= rightGridChain
->getInnerIndex(rightGridChainStartIndex
+1);
430 Int upperInd
= rightGridChain
->getUlineIndex(rightGridChainStartIndex
);
431 Int lowerInd
= rightGridChain
->getUlineIndex(rightGridChainStartIndex
+1);
432 Real upperV
= rightGridChain
->get_v_value(rightGridChainStartIndex
);
433 Real lowerV
= rightGridChain
->get_v_value(rightGridChainStartIndex
+1);
436 vert1
[1]=vert2
[1]=upperV
;
441 vert1
[0]=grid
->get_u_value(i
);
442 vert2
[0]=grid
->get_u_value(i
-1);
443 sline
= new sampledLine(vert1
, vert2
);
444 dline
= new directedLine(INCREASING
, sline
);
451 //the vertical grid line segment
452 vert1
[0]=vert2
[0] = grid
->get_u_value(innerInd
);
455 sline
=new sampledLine(vert1
, vert2
);
456 dline
=new directedLine(INCREASING
, sline
);
462 //the lower grid line
463 vert1
[1]=vert2
[1]=lowerV
;
464 for(i
=innerInd
; i
<lowerInd
; i
++)
466 vert1
[0] = grid
->get_u_value(i
);
467 vert2
[0] = grid
->get_u_value(i
+1);
468 sline
= new sampledLine(vert1
, vert2
);
469 dline
= new directedLine(INCREASING
, sline
);
473 //the edge connecting lower grid to right chain
474 vert1
[0]=grid
->get_u_value(lowerInd
);
475 sline
= new sampledLine(vert1
, rightChain
->getVertex(endRightIndex
));
476 dline
= new directedLine(INCREASING
, sline
);
481 for(i
=endRightIndex
; i
>beginRightIndex
; i
--)
483 sline
= new sampledLine(rightChain
->getVertex(i
), rightChain
->getVertex(i
-1));
484 dline
= new directedLine(INCREASING
, sline
);
488 //the edge connecting right chain with upper grid
490 vert2
[0]=grid
->get_u_value(upperInd
);
491 sline
= new sampledLine(rightChain
->getVertex(beginRightIndex
), vert2
);
492 dline
= new directedLine(INCREASING
, sline
);
494 monoTriangulationOpt(poly
, pStream
);
496 poly
->deleteSinglePolygonWithSline();
501 //this following code cannot be reached, but leave it for debuggig purpose.
503 //find the maximal U-monotone chain of beginRightIndex, beginRightIndex+1,...
505 Real prevU
= rightChain
->getVertex(i
)[0];
506 for(i
=beginRightIndex
+1; i
<= endRightIndex
; i
++){
507 Real thisU
= rightChain
->getVertex(i
)[0];
513 //from beginRightIndex to i-1 is strictly U-monotne
514 //if(i-1==beginRightIndex and the vertex of rightchain is on the first
515 //gridline, then we should use 2 vertices on the right chain. Of we only
516 //use one (begin), we would output degenrate triangles.
517 if(i
-1 == beginRightIndex
&& rightChain
->getVertex(beginRightIndex
)[1] == rightGridChain
->get_v_value(rightGridChainStartIndex
))
520 Int j
= endRightIndex
-1;
521 if(rightGridChain
->getInnerIndex(rightGridChainStartIndex
+1) < rightGridChain
->getUlineIndex(rightGridChainStartIndex
+1))
523 j
= rightChain
->findDecreaseChainFromEnd(i
-1/*beginRightIndex*/, endRightIndex
);
524 Int temp
= endRightIndex
;
525 //now from j+1 to end is strictly U-monotone.
526 //if j+1 is on the last grid line, then we wat to skip to the vertex
527 //whcih is strictly above the second grid line. This vertex must exist
528 //since there is a middle vertex
529 if(j
+1 == endRightIndex
)
531 while(rightChain
->getVertex(j
+1)[1] == rightGridChain
->get_v_value(rightGridChainStartIndex
+1))
534 monoTriangulation2(rightChain
->getVertex(j
+1),
535 rightGridChain
->get_vertex(rightGridChainStartIndex
+1),
539 0, //a decrease chain
545 stripOfFanRight(rightChain
, temp
, j
+1, rightGridChain
->getGrid(),
546 rightGridChain
->getVlineIndex(rightGridChainStartIndex
+1),
547 rightGridChain
->getInnerIndex(rightGridChainStartIndex
+1),
548 rightGridChain
->getUlineIndex(rightGridChainStartIndex
+1),
550 0 //the grid line is below the trim line
556 stripOfFanRight(rightChain
, i
-1, beginRightIndex
, rightGridChain
->getGrid(),
557 rightGridChain
->getVlineIndex(rightGridChainStartIndex
),
558 rightGridChain
->getInnerIndex(rightGridChainStartIndex
+1),
559 rightGridChain
->getUlineIndex(rightGridChainStartIndex
),
561 1 //the grid line is above the trm lines
564 //monotone triangulate the remaining rightchain together with the
565 //two vertices on the two grid v-lines
567 vert
[0][0] = vert
[1][0] = rightGridChain
->getInner_u_value(rightGridChainStartIndex
+1);
568 vert
[0][1] = rightGridChain
->get_v_value(rightGridChainStartIndex
);
569 vert
[1][1] = rightGridChain
->get_v_value(rightGridChainStartIndex
+1);
571 monoTriangulation2(&vert
[0][0],
576 0, ///a decreae chain
582 void stripOfFanRight(vertexArray
* rightChain
,
590 Int gridLineUp
/*1 if the grid line is above the trim lines*/
593 assert(largeIndex
>= smallIndex
);
596 grid_v_value
= grid
->get_v_value(vlineIndex
);
598 Real2
* trimVerts
=(Real2
*) malloc(sizeof(Real2
)* (largeIndex
-smallIndex
+1));
602 Real2
* gridVerts
=(Real2
*) malloc(sizeof(Real2
)* (ulineLargeIndex
-ulineSmallIndex
+1));
606 if(! gridLineUp
) /*trim line is above grid line, so trim vertices are going right when index increases*/
607 for(k
=0, i
=smallIndex
; i
<=largeIndex
; i
++, k
++)
609 trimVerts
[k
][0] = rightChain
->getVertex(i
)[0];
610 trimVerts
[k
][1] = rightChain
->getVertex(i
)[1];
613 for(k
=0, i
=largeIndex
; i
>=smallIndex
; i
--, k
++)
615 trimVerts
[k
][0] = rightChain
->getVertex(i
)[0];
616 trimVerts
[k
][1] = rightChain
->getVertex(i
)[1];
619 for(k
=0, i
=ulineSmallIndex
; i
<= ulineLargeIndex
; i
++, k
++)
621 gridVerts
[k
][0] = grid
->get_u_value(i
);
622 gridVerts
[k
][1] = grid_v_value
;
627 ulineLargeIndex
-ulineSmallIndex
+1, gridVerts
,
628 largeIndex
-smallIndex
+1, trimVerts
,
631 triangulateXYMono(largeIndex
-smallIndex
+1, trimVerts
,
632 ulineLargeIndex
-ulineSmallIndex
+1, gridVerts
,