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:40 $ $Revision: 1.1 $
37 ** $Header: /home/krh/git/sync/mesa-cvs-repo/Mesa/src/glu/sgi/libnurbs/interface/bezierPatchMesh.cc,v 1.1 2001/03/17 00:25:40 brianp Exp $
45 #include "bezierEval.h"
46 #include "bezierPatchMesh.h"
48 static int isDegenerate(float A
[2], float B
[2], float C
[2]);
50 void drawStrips(float *vertex_array
, float *normal_array
, int *length_array
, GLenum
*type_array
, int num_strips
)
54 /*k is the index of the first component of the current vertex*/
55 for(i
=0; i
<num_strips
; i
++)
57 glBegin(type_array
[i
]);
58 for(j
=0; j
<length_array
[i
]; j
++)
60 glNormal3fv(normal_array
+k
);
61 glVertex3fv(vertex_array
+k
);
68 void bezierPatchMeshListDelDeg(bezierPatchMesh
* list
)
70 bezierPatchMesh
* temp
;
71 for(temp
=list
; temp
!= NULL
; temp
= temp
->next
)
73 bezierPatchMeshDelDeg(temp
);
77 void bezierPatchMeshListDelete(bezierPatchMesh
*list
)
79 if(list
== NULL
) return;
80 bezierPatchMeshListDelete(list
->next
);
81 bezierPatchMeshDelete(list
);
87 bezierPatchMesh
* bezierPatchMeshListReverse(bezierPatchMesh
* list
)
89 bezierPatchMesh
* ret
=NULL
;
90 bezierPatchMesh
* temp
;
91 bezierPatchMesh
* nextone
;
92 for(temp
= list
; temp
!= NULL
; temp
= nextone
)
95 ret
=bezierPatchMeshListInsert(ret
, temp
);
100 /*maptype is either GL_MAP2_VERTEX_3 or GL_MAP2_VERTEX_4
102 bezierPatchMesh
*bezierPatchMeshMake(int maptype
, float umin
, float umax
, int ustride
, int uorder
, float vmin
, float vmax
, int vstride
, int vorder
, float *ctlpoints
, int size_UVarray
, int size_length_array
)
109 bezierPatchMesh
*ret
= (bezierPatchMesh
*) malloc(sizeof(bezierPatchMesh
));
113 ret
->bpatch_normal
= NULL
;
114 ret
->bpatch_color
= NULL
;
115 ret
->bpatch_texcoord
= NULL
;
117 if(maptype
== GL_MAP2_VERTEX_3
) dimension
= 3;
118 else if (maptype
==GL_MAP2_VERTEX_4
) dimension
= 4;
120 fprintf(stderr
, "error in inMap2f, maptype=%i is wrong, maptype,map is invalid\n", maptype
);
124 ret
->bpatch
= bezierPatchMake(umin
, vmin
, umax
, vmax
, uorder
, vorder
, dimension
);
125 /*copy the control points there*/
126 the_ustride
= vorder
* dimension
;
127 the_vstride
= dimension
;
128 for(i
=0; i
<uorder
; i
++)
129 for(j
=0; j
<vorder
; j
++)
130 for(k
=0; k
<dimension
; k
++)
131 ret
->bpatch
->ctlpoints
[i
* the_ustride
+ j
*the_vstride
+k
] = ctlpoints
[i
*ustride
+j
*vstride
+k
];
134 ret
->size_UVarray
= size_UVarray
;
135 ret
->size_length_array
= size_length_array
;
136 ret
->UVarray
= (float*) malloc(sizeof(float) * size_UVarray
);
137 assert(ret
->UVarray
);
138 ret
->length_array
= (int *)malloc(sizeof(int) * size_length_array
);
139 assert(ret
->length_array
);
140 ret
->type_array
= (GLenum
*)malloc(sizeof(GLenum
) * size_length_array
);
141 assert(ret
->type_array
);
143 ret
->index_UVarray
= 0;
144 ret
->index_length_array
= 0;
146 ret
->vertex_array
= NULL
;
147 ret
->normal_array
= NULL
;
148 ret
->color_array
= NULL
;
149 ret
->texcoord_array
= NULL
;
155 bezierPatchMesh
*bezierPatchMeshMake2(int size_UVarray
, int size_length_array
)
157 bezierPatchMesh
*ret
= (bezierPatchMesh
*) malloc(sizeof(bezierPatchMesh
));
161 ret
->bpatch_normal
= NULL
;
162 ret
->bpatch_color
= NULL
;
163 ret
->bpatch_texcoord
= NULL
;
165 ret
->size_UVarray
= size_UVarray
;
166 ret
->size_length_array
= size_length_array
;
167 ret
->UVarray
= (float*) malloc(sizeof(float) * size_UVarray
);
168 assert(ret
->UVarray
);
169 ret
->length_array
= (int *)malloc(sizeof(int) * size_length_array
);
170 assert(ret
->length_array
);
171 ret
->type_array
= (GLenum
*)malloc(sizeof(GLenum
) * size_length_array
);
172 assert(ret
->type_array
);
174 ret
->index_UVarray
= 0;
175 ret
->index_length_array
= 0;
177 ret
->vertex_array
= NULL
;
178 ret
->normal_array
= NULL
;
179 ret
->color_array
= NULL
;
180 ret
->texcoord_array
= NULL
;
186 void bezierPatchMeshPutPatch(bezierPatchMesh
*bpm
, int maptype
, float umin
, float umax
, int ustride
, int uorder
, float vmin
, float vmax
, int vstride
, int vorder
, float *ctlpoints
)
189 case GL_MAP2_VERTEX_3
:
190 bpm
->bpatch
= bezierPatchMake2(umin
, vmin
, umax
, vmax
, uorder
, vorder
, 3, ustride
, vstride
, ctlpoints
);
192 case GL_MAP2_VERTEX_4
:
193 bpm
->bpatch
= bezierPatchMake2(umin
, vmin
, umax
, vmax
, uorder
, vorder
, 4,ustride
, vstride
, ctlpoints
);
196 bpm
->bpatch_normal
= bezierPatchMake2(umin
, vmin
, umax
, vmax
, uorder
, vorder
, 3, ustride
, vstride
, ctlpoints
);
199 bpm
->bpatch_color
= bezierPatchMake2(umin
, vmin
, umax
, vmax
, uorder
, vorder
, 1, ustride
, vstride
, ctlpoints
);
201 case GL_MAP2_COLOR_4
:
202 bpm
->bpatch_color
= bezierPatchMake2(umin
, vmin
, umax
, vmax
, uorder
, vorder
, 4, ustride
, vstride
, ctlpoints
);
204 case GL_MAP2_TEXTURE_COORD_1
:
205 bpm
->bpatch_texcoord
= bezierPatchMake2(umin
, vmin
, umax
, vmax
, uorder
, vorder
, 1, ustride
, vstride
, ctlpoints
);
207 case GL_MAP2_TEXTURE_COORD_2
:
208 bpm
->bpatch_texcoord
= bezierPatchMake2(umin
, vmin
, umax
, vmax
, uorder
, vorder
, 2, ustride
, vstride
, ctlpoints
);
210 case GL_MAP2_TEXTURE_COORD_3
:
211 bpm
->bpatch_texcoord
= bezierPatchMake2(umin
, vmin
, umax
, vmax
, uorder
, vorder
, 3, ustride
, vstride
, ctlpoints
);
213 case GL_MAP2_TEXTURE_COORD_4
:
214 bpm
->bpatch_texcoord
= bezierPatchMake2(umin
, vmin
, umax
, vmax
, uorder
, vorder
, 4, ustride
, vstride
, ctlpoints
);
217 fprintf(stderr
, "error in bezierPatchMeshPutPatch, maptype=%i is wrong, maptype,map is invalid\n", maptype
);
222 /*delete everything including the arrays. So if you want to output the
223 *pointers of the arrays, you should not use this function to deallocate space.
224 *you should dealocate manually
226 void bezierPatchMeshDelete(bezierPatchMesh
*bpm
)
228 if(bpm
->bpatch
!= NULL
)
229 bezierPatchDelete(bpm
->bpatch
);
230 if(bpm
->bpatch_normal
!= NULL
)
231 bezierPatchDelete(bpm
->bpatch_normal
);
232 if(bpm
->bpatch_color
!= NULL
)
233 bezierPatchDelete(bpm
->bpatch_color
);
234 if(bpm
->bpatch_texcoord
!= NULL
)
235 bezierPatchDelete(bpm
->bpatch_texcoord
);
238 free(bpm
->length_array
);
239 free(bpm
->vertex_array
);
240 free(bpm
->normal_array
);
241 free(bpm
->type_array
);
246 *type is the primitive type:
248 void bezierPatchMeshBeginStrip(bezierPatchMesh
*bpm
, GLenum type
)
254 /*signal the end of the current strip*/
255 void bezierPatchMeshEndStrip(bezierPatchMesh
*bpm
)
259 /*if there are no vertices in this strip, then nothing needs to be done*/
260 if(bpm
->counter
== 0) return;
262 /*if the length_array is full, it should be expanded*/
263 if(bpm
->index_length_array
>= bpm
->size_length_array
)
265 int *temp
= (int*) malloc(sizeof(int) * (bpm
->size_length_array
*2 + 1));
267 GLenum
*temp_type
= (GLenum
*) malloc(sizeof(GLenum
) * (bpm
->size_length_array
*2 + 1));
270 bpm
->size_length_array
= bpm
->size_length_array
*2 + 1;
273 for(i
=0; i
<bpm
->index_length_array
; i
++)
275 temp
[i
] = bpm
->length_array
[i
];
276 temp_type
[i
] = bpm
->type_array
[i
];
279 /*deallocate old array*/
280 free(bpm
->length_array
);
281 free(bpm
->type_array
);
283 /*point to the new array which is twice as bigger*/
284 bpm
->length_array
= temp
;
285 bpm
->type_array
= temp_type
;
287 bpm
->type_array
[bpm
->index_length_array
] = bpm
->type
;
288 bpm
->length_array
[bpm
->index_length_array
++] = bpm
->counter
;
293 void bezierPatchMeshInsertUV(bezierPatchMesh
*bpm
, float u
, float v
)
296 /*if the UVarray is full, it should be expanded*/
297 if(bpm
->index_UVarray
+1 >= bpm
->size_UVarray
)
299 float *temp
= (float*) malloc(sizeof(float) * (bpm
->size_UVarray
* 2 + 2));
303 bpm
->size_UVarray
= bpm
->size_UVarray
*2 + 2;
306 for(i
=0; i
<bpm
->index_UVarray
; i
++)
308 temp
[i
] = bpm
->UVarray
[i
];
311 /*deallocate old array*/
314 /*pointing to the new arrays*/
317 /*insert the new UV*/
318 bpm
->UVarray
[bpm
->index_UVarray
] = u
;
319 bpm
->index_UVarray
++;
320 bpm
->UVarray
[bpm
->index_UVarray
] = v
;
321 bpm
->index_UVarray
++;
323 /*update counter: one more vertex*/
329 void bezierPatchMeshPrint(bezierPatchMesh
*bpm
)
332 printf("the bezier patch is\n");
333 bezierPatchPrint(bpm
->bpatch
);
334 printf("index_length_array= %i\n", bpm
->index_length_array
);
335 printf("size_length_array =%i\n", bpm
->size_length_array
);
336 printf("index_UVarray =%i\n", bpm
->index_UVarray
);
337 printf("size_UVarray =%i\n", bpm
->size_UVarray
);
338 printf("UVarray is\n");
339 for(i
=0; i
<bpm
->index_UVarray
; i
++)
340 printf("%f ", bpm
->UVarray
[i
]);
342 printf("length_array is\n");
343 for(i
=0; i
<bpm
->index_length_array
; i
++)
344 printf("%i ", bpm
->length_array
[i
]);
349 /*insert a new patch in front of the current linked list and return the new list*/
350 bezierPatchMesh
* bezierPatchMeshListInsert(bezierPatchMesh
* list
, bezierPatchMesh
* bpm
)
356 /*print all the patches*/
357 void bezierPatchMeshListPrint(bezierPatchMesh
* list
)
359 bezierPatchMesh
*temp
;
360 for(temp
= list
; temp
!= NULL
; temp
= temp
->next
)
362 bezierPatchMeshPrint(temp
);
366 int bezierPatchMeshListTotalStrips(bezierPatchMesh
* list
)
369 bezierPatchMesh
*temp
;
370 for(temp
=list
; temp
!= NULL
; temp
= temp
->next
)
372 sum
+= temp
->index_length_array
;
377 int bezierPatchMeshListTotalVert(bezierPatchMesh
* list
)
380 bezierPatchMesh
*temp
;
381 for(temp
=list
; temp
!= NULL
; temp
= temp
->next
)
383 sum
+= temp
->index_UVarray
;
388 int bezierPatchMeshListNumTriangles(bezierPatchMesh
* list
)
391 bezierPatchMesh
* temp
;
392 for(temp
=list
; temp
!= NULL
; temp
= temp
->next
)
394 sum
+= bezierPatchMeshNumTriangles(temp
);
399 int bezierPatchMeshNumTriangles(bezierPatchMesh
* bpm
)
403 for(i
=0; i
<bpm
->index_length_array
; i
++)
405 switch(bpm
->type_array
[i
])
408 sum
+= bpm
->length_array
[i
]/3;
410 case GL_TRIANGLE_FAN
:
411 if(bpm
->length_array
[i
] > 2)
412 sum
+= bpm
->length_array
[i
]-2;
414 case GL_TRIANGLE_STRIP
:
415 if(bpm
->length_array
[i
] > 2)
416 sum
+= bpm
->length_array
[i
]-2;
419 if(bpm
->length_array
[i
]>2)
420 sum
+= (bpm
->length_array
[i
]-2);
423 fprintf(stderr
,"error in bezierPatchMeshListNumTriangles, type invalid\n");
429 /*delete degenerate triangles*/
430 void bezierPatchMeshDelDeg(bezierPatchMesh
* bpm
)
432 if(bpm
== NULL
) return;
434 int *new_length_array
;
435 GLenum
*new_type_array
;
436 int index_new_length_array
;
438 int index_new_UVarray
;
440 new_length_array
= (int*)malloc(sizeof(int) * bpm
->index_length_array
);
441 assert(new_length_array
);
442 new_type_array
= (GLenum
*)malloc(sizeof(GLenum
) * bpm
->index_length_array
);
443 assert(new_length_array
);
444 new_UVarray
= (float*) malloc(sizeof(float) * bpm
->index_UVarray
);
447 index_new_length_array
= 0;
450 for(i
=0; i
<bpm
->index_length_array
; i
++){
452 /*(if not degenerate, we have to copy*/
453 if( (bpm
->length_array
[i
] != 3) || (!isDegenerate(bpm
->UVarray
+k
, bpm
->UVarray
+k
+2, bpm
->UVarray
+k
+4)))
455 for(j
=0; j
<2* bpm
->length_array
[i
]; j
++)
456 new_UVarray
[index_new_UVarray
++] = bpm
->UVarray
[k
++];
458 new_length_array
[index_new_length_array
] = bpm
->length_array
[i
];
459 new_type_array
[index_new_length_array
] = bpm
->type_array
[i
];
460 index_new_length_array
++;
468 free(bpm
->length_array
);
469 free(bpm
->type_array
);
470 bpm
->UVarray
=new_UVarray
;
471 bpm
->length_array
=new_length_array
;
472 bpm
->type_array
=new_type_array
;
473 bpm
->index_UVarray
= index_new_UVarray
;
474 bpm
->index_length_array
= index_new_length_array
;
479 *the xyz and normals are stored in vertex_array,
480 *and normal_array. the spaces of both are allocated here
482 void bezierPatchMeshEval(bezierPatchMesh
* bpm
)
486 float u0
= bpm
->bpatch
->umin
;
487 float u1
= bpm
->bpatch
->umax
;
488 int uorder
= bpm
->bpatch
->uorder
;
489 float v0
= bpm
->bpatch
->vmin
;
490 float v1
= bpm
->bpatch
->vmax
;
491 int vorder
= bpm
->bpatch
->vorder
;
492 int dimension
= bpm
->bpatch
->dimension
;
493 int ustride
= dimension
* vorder
;
494 int vstride
= dimension
;
495 float *ctlpoints
= bpm
->bpatch
->ctlpoints
;
497 bpm
->vertex_array
= (float*) malloc(sizeof(float)* (bpm
->index_UVarray
/2) * 3);
498 assert(bpm
->vertex_array
);
499 bpm
->normal_array
= (float*) malloc(sizeof(float)* (bpm
->index_UVarray
/2) * 3);
500 assert(bpm
->normal_array
);
504 for(i
=0; i
<bpm
->index_length_array
; i
++)
506 for(j
=0; j
<bpm
->length_array
[i
]; j
++)
509 v
= bpm
->UVarray
[k
+1];
510 bezierSurfEval(u0
,u1
,uorder
, v0
, v1
, vorder
, dimension
, ctlpoints
, ustride
, vstride
, u
,v
, bpm
->vertex_array
+l
);
511 bezierSurfEvalNormal(u0
,u1
,uorder
, v0
, v1
, vorder
, dimension
, ctlpoints
, ustride
, vstride
, u
,v
, bpm
->normal_array
+l
);
518 void bezierPatchMeshListEval(bezierPatchMesh
* list
)
520 bezierPatchMesh
* temp
;
521 for(temp
= list
; temp
!= NULL
; temp
= temp
->next
)
523 bezierPatchMeshEval(temp
);
527 void bezierPatchMeshDraw(bezierPatchMesh
* bpm
)
531 /*k is the index of the first component of the current vertex*/
532 for(i
=0; i
<bpm
->index_length_array
; i
++)
534 glBegin(bpm
->type_array
[i
]);
535 for(j
=0; j
<bpm
->length_array
[i
]; j
++)
537 glNormal3fv(bpm
->normal_array
+k
);
538 glVertex3fv(bpm
->vertex_array
+k
);
545 void bezierPatchMeshListDraw(bezierPatchMesh
* list
)
547 bezierPatchMesh
* temp
;
548 for(temp
= list
; temp
!= NULL
; temp
= temp
->next
)
550 bezierPatchMeshDraw(temp
);
554 void bezierPatchMeshListCollect(bezierPatchMesh
* list
, float **vertex_array
, float **normal_array
, int **length_array
, GLenum
**type_array
, int *num_strips
)
557 bezierPatchMesh
*temp
;
558 int total_num_vertices
= bezierPatchMeshListTotalVert(list
);
559 (*vertex_array
) = (float *) malloc(sizeof(float) * total_num_vertices
*3);
560 assert(*vertex_array
);
561 (*normal_array
) = (float *) malloc(sizeof(float) * total_num_vertices
*3);
562 assert(*normal_array
);
564 *num_strips
= bezierPatchMeshListTotalStrips(list
);
566 *length_array
= (int*) malloc(sizeof(int) * (*num_strips
));
567 assert(*length_array
);
569 *type_array
= (GLenum
*) malloc(sizeof(GLenum
) * (*num_strips
));
574 for(temp
= list
; temp
!= NULL
; temp
= temp
->next
)
577 for(i
=0; i
<temp
->index_length_array
; i
++)
579 for(j
=0; j
<temp
->length_array
[i
]; j
++)
581 (*vertex_array
)[k
] = temp
->vertex_array
[x
];
582 (*vertex_array
)[k
+1] = temp
->vertex_array
[x
+1];
583 (*vertex_array
)[k
+2] = temp
->vertex_array
[x
+2];
585 (*normal_array
)[k
] = temp
->normal_array
[x
];
586 (*normal_array
)[k
+1] = temp
->normal_array
[x
+1];
587 (*normal_array
)[k
+2] = temp
->normal_array
[x
+2];
592 (*type_array
)[l
] = temp
->type_array
[i
];
593 (*length_array
)[l
++] = temp
->length_array
[i
];
600 static int isDegenerate(float A
[2], float B
[2], float C
[2])
602 if( (A
[0] == B
[0] && A
[1]==B
[1]) ||
603 (A
[0] == C
[0] && A
[1]==C
[1]) ||
604 (B
[0] == C
[0] && B
[1]==C
[1])