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/11/29 16:16:55 $ $Revision: 1.2 $
37 ** $Header: /home/krh/git/sync/mesa-cvs-repo/Mesa/src/glu/sgi/libnurbs/nurbtess/sampleCompBot.cc,v 1.2 2001/11/29 16:16:55 kschultz Exp $
43 #include "sampleCompBot.h"
44 #include "sampleCompRight.h"
46 #define max(a,b) ((a>b)? a:b)
48 //return: index_mono, index_pass
49 //from [pass, mono] is strictly U-monotone
50 //from [corner, pass] is <u
51 // vertex[pass][0] >= u
52 //if everybost is <u, then pass = end+1.
53 //otherwise both mono and pass are meanng full and we have corner<=pass<=mono<=end
54 void findBotLeftSegment(vertexArray
* leftChain
,
63 assert(leftCorner
<= leftEnd
);
64 for(i
=leftCorner
; i
<= leftEnd
; i
++)
65 if(leftChain
->getVertex(i
)[0] >= u
)
68 if(ret_index_pass
<= leftEnd
)
70 for(i
=ret_index_pass
; i
< leftEnd
; i
++)
72 if(leftChain
->getVertex(i
+1)[0] <= leftChain
->getVertex(i
)[0])
80 void findBotRightSegment(vertexArray
* rightChain
,
88 assert(rightCorner
<= rightEnd
);
89 for(i
=rightCorner
; i
<= rightEnd
; i
++)
90 if(rightChain
->getVertex(i
)[0] <= u
)
97 if(ret_index_pass
<= rightEnd
)
99 for(i
=ret_index_pass
; i
< rightEnd
; i
++)
101 if(rightChain
->getVertex(i
+1)[0] >= rightChain
->getVertex(i
)[0])
109 void sampleBotRightWithGridLinePost(Real
* botVertex
,
110 vertexArray
* rightChain
,
121 //the possible section which is to the right of rightU
122 if(segIndexPass
> rightCorner
) //from corner to pass-1 is > u.
125 if(segIndexPass
<= rightEnd
) //there is a point to the left of u
126 tempBot
= rightChain
->getVertex(segIndexPass
);
127 else //nothing is to the left of u.
130 tempTop
[0] = grid
->get_u_value(rightU
);
131 tempTop
[1] = grid
->get_v_value(gridV
);
133 monoTriangulation2(tempTop
, tempBot
,
137 0, // a decrease chain
141 //the possible section which is strictly Umonotone
142 if(segIndexPass
<= rightEnd
) //segIndex pass and mono exist
144 //if there are grid points which are to the left of botVertex
145 //then we should use botVertex to form a fan with these points to
146 //optimize the triangulation
148 if(botVertex
[0] <= grid
->get_u_value(leftU
))
152 //we also have to make sure that botVertex is the left most vertex on the chain
154 for(i
=segIndexMono
; i
<=rightEnd
; i
++)
155 if(rightChain
->getVertex(i
)[0] <= botVertex
[0])
164 //find midU so that grid->get_u_value(midU) <= botVertex[0]
165 //and grid->get_u_value(midU) > botVertex[0]
167 while(grid
->get_u_value(midU
) <= botVertex
[0])
175 grid
->outputFanWithPoint(gridV
, leftU
, midU
, botVertex
, pStream
);
176 stripOfFanRight(rightChain
, segIndexMono
, segIndexPass
, grid
, gridV
, midU
, rightU
, pStream
, 1);
178 tempTop
[0] = grid
->get_u_value(midU
);
179 tempTop
[1] = grid
->get_v_value(gridV
);
180 monoTriangulation2(tempTop
, botVertex
, rightChain
, segIndexMono
, rightEnd
, 0, pStream
);
184 stripOfFanRight(rightChain
, segIndexMono
, segIndexPass
, grid
, gridV
, leftU
, rightU
, pStream
, 1);
186 tempTop
[0] = grid
->get_u_value(leftU
);
187 tempTop
[1] = grid
->get_v_value(gridV
);
188 monoTriangulation2(tempTop
, botVertex
, rightChain
, segIndexMono
, rightEnd
, 0, pStream
);
191 else //the botVertex forms a fan witht eh grid points
192 grid
->outputFanWithPoint(gridV
, leftU
, rightU
, botVertex
, pStream
);
195 void sampleBotRightWithGridLine(Real
* botVertex
,
196 vertexArray
* rightChain
,
205 //if right chaain is empty, then there is only one bot vertex with
207 if(rightEnd
<rightCorner
){
208 grid
->outputFanWithPoint(gridV
, leftU
, rightU
, botVertex
, pStream
);
212 Int segIndexMono
, segIndexPass
;
213 findBotRightSegment(rightChain
,
216 grid
->get_u_value(rightU
),
220 sampleBotRightWithGridLinePost(botVertex
,
234 void sampleBotLeftWithGridLinePost(Real
* botVertex
,
235 vertexArray
* leftChain
,
247 //the possible section which is to the left of leftU
248 if(segIndexPass
> leftCorner
) //at least leftCorner is to the left of leftU
251 if(segIndexPass
<= leftEnd
) //from corner to pass-1 is <u
252 tempBot
= leftChain
->getVertex(segIndexPass
);
253 else //nothing is to the rigth of u
256 tempTop
[0] = grid
->get_u_value(leftU
);
257 tempTop
[1] = grid
->get_v_value(gridV
);
258 monoTriangulation2(tempTop
, tempBot
, leftChain
, leftCorner
, segIndexPass
-1,
259 1, //a increase chain,
262 //the possible section which is strictly Umonotone
263 if(segIndexPass
<= leftEnd
) //segIndexpass and mono exist
265 stripOfFanLeft(leftChain
, segIndexMono
, segIndexPass
, grid
, gridV
, leftU
, rightU
, pStream
, 1);
267 tempTop
[0] = grid
->get_u_value(rightU
);
268 tempTop
[1] = grid
->get_v_value(gridV
);
270 monoTriangulation2(tempTop
, botVertex
, leftChain
, segIndexMono
, leftEnd
,
274 else //the botVertex forms a fan with the grid points
276 grid
->outputFanWithPoint(gridV
, leftU
, rightU
, botVertex
, pStream
);
281 void sampleBotLeftWithGridLine(Real
* botVertex
,
282 vertexArray
* leftChain
,
292 //if leftChain is empty, then there is only one botVertex with one grid line
293 if(leftEnd
< leftCorner
){
294 grid
->outputFanWithPoint(gridV
, leftU
, rightU
, botVertex
, pStream
);
298 Int segIndexPass
, segIndexMono
;
299 findBotLeftSegment(leftChain
, leftEnd
, leftCorner
, grid
->get_u_value(leftU
), segIndexMono
, segIndexPass
);
301 sampleBotLeftWithGridLinePost(botVertex
,
309 leftU
, rightU
, pStream
);
312 //return 1 if separator exists, 0 otherwise
313 Int
findBotSeparator(vertexArray
* leftChain
,
316 vertexArray
* rightChain
,
322 Int oldLeftI
, oldRightI
, newLeftI
, newRightI
;
324 Real leftMax
/*= leftChain->getVertex(leftCorner)[0]*/;
325 Real rightMin
/*= rightChain->getVertex(rightCorner)[0]*/;
326 if(leftChain
->getVertex(leftCorner
)[1] < rightChain
->getVertex(rightCorner
)[1])//leftlower
328 oldLeftI
= leftCorner
-1;
329 oldRightI
= rightCorner
;
330 leftMax
= leftChain
->getVertex(leftCorner
)[0] - Real(1.0) ; //initilize to be left of leftCorner
331 rightMin
= rightChain
->getVertex(rightCorner
)[0];
335 oldLeftI
= leftCorner
;
336 oldRightI
= rightCorner
-1;
337 leftMax
= leftChain
->getVertex(leftCorner
)[0];
338 rightMin
= rightChain
->getVertex(rightCorner
)[0] + Real(1.0);
341 //i: the current working leftChain Index
342 //j: the curent working right chian index
343 //if(left(i) is lower than right(j), then the two chains above right(j) are separated.
344 //else the two chains below left(i) are separated.
350 newRightI
= oldRightI
;
351 if(i
> leftEnd
) //left chain is doen , go through remaining right chain
353 for(k
=j
+1; k
<= rightEnd
; k
++)
355 if(rightChain
->getVertex(k
)[0] > leftMax
) //no conflict
357 //update oldRightI if necessary
358 if(rightChain
->getVertex(k
)[0] < rightMin
)
360 rightMin
= rightChain
->getVertex(k
)[0];
364 else //there is a conflict
365 break; //the for-loop, above right(k+1) is separated: oldLeftI, oldRightI
367 break; //the while loop
369 else if(j
> rightEnd
) //right Chain is doen
371 for(k
=i
+1; k
<= leftEnd
; k
++)
373 if(leftChain
->getVertex(k
)[0] < rightMin
) //no conflict
375 //update oldLeftI if necessary
376 if(leftChain
->getVertex(k
)[0] > leftMax
)
378 leftMax
= leftChain
->getVertex(k
)[0];
382 else //there is a conflict
383 break; //the for-loop, above left(k+1) is separated: oldLeftI, oldRightI
385 break; //the while loop
387 else if(leftChain
->getVertex(i
)[1] < rightChain
->getVertex(j
)[1]) //left lower
390 if(leftChain
->getVertex(i
)[0] > leftMax
) //update leftMax amd newLeftI
392 leftMax
= leftChain
->getVertex(i
)[0];
395 for(k
=j
+1; k
<= rightEnd
; k
++) //update rightMin and newRightI;
397 if(rightChain
->getVertex(k
)[1] < leftChain
->getVertex(i
)[1]) //right gets lower
399 if(rightChain
->getVertex(k
)[0] < rightMin
)
401 rightMin
= rightChain
->getVertex(k
)[0];
405 j
= k
; //next working j, since j will he lower than i in next loop
406 if(leftMax
>= rightMin
) //there is a conflict
408 else //still no conflict
411 oldRightI
= newRightI
;
417 if(rightChain
->getVertex(j
)[0] < rightMin
)
419 rightMin
= rightChain
->getVertex(j
)[0];
422 for(k
=i
+1; k
<= leftEnd
; k
++)
424 if(leftChain
->getVertex(k
)[1] < rightChain
->getVertex(j
)[1])
426 if(leftChain
->getVertex(k
)[0] > leftMax
)
428 leftMax
= leftChain
->getVertex(k
)[0];
432 i
=k
; //nexct working i, since i will be lower than j next loop
433 if(leftMax
>= rightMin
) //there is conflict
435 else //still no conflict
438 oldRightI
= newRightI
;
442 //now oldLeftI and oldRight I are the desired separator index notice that they are not
444 if(oldLeftI
< leftCorner
|| oldRightI
< rightCorner
)
445 return 0; //no separator
448 ret_sep_left
= oldLeftI
;
449 ret_sep_right
= oldRightI
;
454 void sampleCompBot(Real
* botVertex
,
455 vertexArray
* leftChain
,
457 vertexArray
* rightChain
,
459 gridBoundaryChain
* leftGridChain
,
460 gridBoundaryChain
* rightGridChain
,
462 Int down_leftCornerWhere
,
463 Int down_leftCornerIndex
,
464 Int down_rightCornerWhere
,
465 Int down_rightCornerIndex
,
469 if(down_leftCornerWhere
== 1 && down_rightCornerWhere
== 1) //the bot is botVertex with possible grid points
472 leftGridChain
->getGrid()->outputFanWithPoint(leftGridChain
->getVlineIndex(gridIndex
),
473 leftGridChain
->getUlineIndex(gridIndex
),
474 rightGridChain
->getUlineIndex(gridIndex
),
479 else if(down_leftCornerWhere
!= 0)
484 if(down_leftCornerWhere
== 1){
485 tempRightEnd
= rightEnd
;
490 tempRightEnd
= down_leftCornerIndex
-1;
491 tempBot
= rightChain
->getVertex(down_leftCornerIndex
);
494 sampleBotRightWithGridLine(tempBot
,
497 down_rightCornerIndex
,
498 rightGridChain
->getGrid(),
499 leftGridChain
->getVlineIndex(gridIndex
),
500 leftGridChain
->getUlineIndex(gridIndex
),
501 rightGridChain
->getUlineIndex(gridIndex
),
504 else if(down_rightCornerWhere
!= 2)
509 if(down_rightCornerWhere
== 1){
510 tempLeftEnd
= leftEnd
;
513 else //right corner is on left chain
515 tempLeftEnd
= down_rightCornerIndex
-1;
516 tempBot
= leftChain
->getVertex(down_rightCornerIndex
);
520 sampleBotLeftWithGridLine(tempBot
, leftChain
, tempLeftEnd
, down_leftCornerIndex
,
521 leftGridChain
->getGrid(),
522 leftGridChain
->getVlineIndex(gridIndex
),
523 leftGridChain
->getUlineIndex(gridIndex
),
524 rightGridChain
->getUlineIndex(gridIndex
),
528 else //down_leftCornereWhere == 0, down_rightCornerwhere == 2
530 sampleCompBotSimple(botVertex
,
538 down_leftCornerWhere
,
539 down_leftCornerIndex
,
540 down_rightCornerWhere
,
541 down_rightCornerIndex
,
547 //the following code is trying to do some optimization, but not quite working. so it is not reachable, but leave it here for reference
548 Int sep_left
, sep_right
;
549 if(findBotSeparator(leftChain
, leftEnd
, down_leftCornerIndex
,
550 rightChain
, rightEnd
, down_rightCornerIndex
,
555 if(leftChain
->getVertex(sep_left
)[0] >= leftGridChain
->get_u_value(gridIndex
) &&
556 rightChain
->getVertex(sep_right
)[0] <= rightGridChain
->get_u_value(gridIndex
))
559 Int segLeftMono
, segLeftPass
, segRightMono
, segRightPass
;
560 findBotLeftSegment(leftChain
,
562 down_leftCornerIndex
,
563 leftGridChain
->get_u_value(gridIndex
),
566 findBotRightSegment(rightChain
,
568 down_rightCornerIndex
,
569 rightGridChain
->get_u_value(gridIndex
),
572 if(leftChain
->getVertex(segLeftMono
)[1] <= rightChain
->getVertex(segRightMono
)[1])
574 gridSep
= rightGridChain
->getUlineIndex(gridIndex
);
575 while(leftGridChain
->getGrid()->get_u_value(gridSep
) > leftChain
->getVertex(segLeftMono
)[0])
580 gridSep
= leftGridChain
->getUlineIndex(gridIndex
);
581 while(leftGridChain
->getGrid()->get_u_value(gridSep
) < rightChain
->getVertex(segRightMono
)[0])
585 sampleBotLeftWithGridLinePost(leftChain
->getVertex(segLeftMono
),
590 down_leftCornerIndex
,
591 leftGridChain
->getGrid(),
592 leftGridChain
->getVlineIndex(gridIndex
),
593 leftGridChain
->getUlineIndex(gridIndex
),
596 sampleBotRightWithGridLinePost(rightChain
->getVertex(segRightMono
),
601 down_rightCornerIndex
,
602 rightGridChain
->getGrid(),
603 rightGridChain
->getVlineIndex(gridIndex
),
605 rightGridChain
->getUlineIndex(gridIndex
),
608 tempTop
[0] = leftGridChain
->getGrid()->get_u_value(gridSep
);
609 tempTop
[1] = leftGridChain
->get_v_value(gridIndex
);
610 monoTriangulationRecGen(tempTop
, botVertex
,
611 leftChain
, segLeftMono
, leftEnd
,
612 rightChain
, segRightMono
, rightEnd
,
614 }//end if both sides have vertices inside the gridboundary points
615 else if(leftChain
->getVertex(sep_left
)[0] >= leftGridChain
->get_u_value(gridIndex
)) //left n right out
618 Int segLeftMono
, segLeftPass
;
619 findBotLeftSegment(leftChain
,
621 down_leftCornerIndex
,
622 leftGridChain
->get_u_value(gridIndex
),
625 assert(segLeftPass
<= sep_left
); //make sure there is a point to the right of u.
626 monoTriangulation2(leftGridChain
->get_vertex(gridIndex
),
627 leftChain
->getVertex(segLeftPass
),
629 down_leftCornerIndex
,
631 1, //a increase chain
633 stripOfFanLeft(leftChain
, segLeftMono
, segLeftPass
,
634 leftGridChain
->getGrid(),
635 leftGridChain
->getVlineIndex(gridIndex
),
636 leftGridChain
->getUlineIndex(gridIndex
),
637 rightGridChain
->getUlineIndex(gridIndex
),
640 sampleBotLeftWithGridLinePost(leftChain->getVertex(segLeftMono),
645 down_leftCornerIndex,
646 leftGridChain->getGrid(),
647 leftGridChain->getVlineIndex(gridIndex),
648 leftGridChain->getUlineIndex(gridIndex),
649 rightGridChain->getUlineIndex(gridIndex),
653 monoTriangulationRecGen(rightGridChain
->get_vertex(gridIndex
),
655 leftChain
, segLeftMono
, leftEnd
,
656 rightChain
, down_rightCornerIndex
, rightEnd
,
658 }//end left in right out
659 else if(rightChain
->getVertex(sep_right
)[0] <= rightGridChain
->get_u_value(gridIndex
))//left out right in
661 Int segRightMono
, segRightPass
;
662 findBotRightSegment(rightChain
, sep_right
, down_rightCornerIndex
,
663 rightGridChain
->get_u_value(gridIndex
),
667 assert(segRightPass
<= sep_right
); //make sure there is a point to the left of u.
668 monoTriangulation2(rightGridChain
->get_vertex(gridIndex
),
669 rightChain
->getVertex(segRightPass
),
671 down_rightCornerIndex
,
673 0, // a decrease chain
676 stripOfFanRight(rightChain
, segRightMono
, segRightPass
,
677 rightGridChain
->getGrid(),
678 rightGridChain
->getVlineIndex(gridIndex
),
679 leftGridChain
->getUlineIndex(gridIndex
),
680 rightGridChain
->getUlineIndex(gridIndex
),
684 monoTriangulationRecGen(leftGridChain
->get_vertex(gridIndex
),
686 leftChain
, down_leftCornerIndex
, leftEnd
,
687 rightChain
, segRightMono
, rightEnd
,
690 }//end left out right in
691 else //left out, right out
693 sampleCompBotSimple(botVertex
,
701 down_leftCornerWhere
,
702 down_leftCornerIndex
,
703 down_rightCornerWhere
,
704 down_rightCornerIndex
,
707 }//end leftout right out
708 }//end if separator exists
712 sampleCompBotSimple(botVertex
,
720 down_leftCornerWhere
,
721 down_leftCornerIndex
,
722 down_rightCornerWhere
,
723 down_rightCornerIndex
,
728 }//end if the functin
731 void sampleCompBotSimple(Real
* botVertex
,
732 vertexArray
* leftChain
,
734 vertexArray
* rightChain
,
736 gridBoundaryChain
* leftGridChain
,
737 gridBoundaryChain
* rightGridChain
,
739 Int down_leftCornerWhere
,
740 Int down_leftCornerIndex
,
741 Int down_rightCornerWhere
,
742 Int down_rightCornerIndex
,
745 //the plan is to use monotriangulation algorithm.
749 Int ActualLeftStart
, ActualLeftEnd
;
750 Int ActualRightStart
, ActualRightEnd
;
752 //creat an array to store the points on the grid line
753 gridWrap
* grid
= leftGridChain
->getGrid();
754 Int gridV
= leftGridChain
->getVlineIndex(gridIndex
);
755 Int gridLeftU
= leftGridChain
->getUlineIndex(gridIndex
);
756 Int gridRightU
= rightGridChain
->getUlineIndex(gridIndex
);
757 Real2
* gridPoints
= (Real2
*) malloc(sizeof(Real2
) * (gridRightU
- gridLeftU
+1));
760 for(k
=0, i
=gridRightU
; i
>= gridLeftU
; i
--, k
++)
762 gridPoints
[k
][0] = grid
->get_u_value(i
);
763 gridPoints
[k
][1] = grid
->get_v_value(gridV
);
766 if(down_rightCornerWhere
!= 0) //rightCorner is not on lef
767 ActualLeftEnd
= leftEnd
;
769 ActualLeftEnd
= down_rightCornerIndex
-1; //down_rightCornerIndex will be th actualBot
771 if(down_leftCornerWhere
!= 0) //left corner is not on let chian
772 ActualLeftStart
= leftEnd
+1; //meaning that there is no actual left section
774 ActualLeftStart
= down_leftCornerIndex
;
776 vertexArray
ActualLeftChain(max(0, ActualLeftEnd
- ActualLeftStart
+1) + gridRightU
- gridLeftU
+1);
778 for(i
=0; i
<gridRightU
- gridLeftU
+1 ; i
++)
779 ActualLeftChain
.appendVertex(gridPoints
[i
]);
780 for(i
=ActualLeftStart
; i
<= ActualLeftEnd
; i
++)
781 ActualLeftChain
.appendVertex(leftChain
->getVertex(i
));
783 //determine ActualRightStart
784 if(down_rightCornerWhere
!= 2) //right is not on right
785 ActualRightStart
= rightEnd
+1; //meaning no section on right
787 ActualRightStart
= down_rightCornerIndex
;
789 //determine actualrightEnd
790 if(down_leftCornerWhere
!= 2) //left is not on right
793 ActualRightEnd
= rightEnd
;
795 else //left corner is on right
797 ActualRightEnd
= down_leftCornerIndex
-1; //down_leftCornerIndex will be the bot
802 if(down_rightCornerWhere
== 2)
804 if(down_leftCornerWhere
== 2)
805 ActualBot
= rightChain
->getVertex(down_leftCornerIndex
);
807 ActualBot
= botVertex
;
809 else if(down_rightCornerWhere
== 1) //right corner bot
810 ActualBot
= botVertex
;
811 else //down_rightCornerWhere == 0
812 ActualBot
= leftChain
->getVertex(down_rightCornerIndex
);
814 ActualTop
= gridPoints
[0];
816 printf("in bot simple, actual leftChain is \n");
817 ActualLeftChain.print();
818 printf("Actual Top = %f,%f\n", ActualTop[0],ActualTop[1]);
819 printf("Actual Bot = %f,%f\n", ActualBot[0],ActualBot[1]);
820 printf("Actual right start = %i, end=%i\n",ActualRightStart, ActualRightEnd);
822 if(rightChain
->getVertex(ActualRightStart
)[1] == ActualTop
[1])
823 monoTriangulationRecGenOpt(rightChain
->getVertex(ActualRightStart
),
827 ActualLeftChain
.getNumElements()-1,
833 monoTriangulationRecGenOpt(ActualTop
, ActualBot
,
835 1, //the first one is the top vertex
836 ActualLeftChain
.getNumElements()-1,