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.
43 #include "bezierEval.h"
44 #include "bezierPatchMesh.h"
46 static int isDegenerate(float A
[2], float B
[2], float C
[2]);
48 void drawStrips(float *vertex_array
, float *normal_array
, int *length_array
, GLenum
*type_array
, int num_strips
)
52 /*k is the index of the first component of the current vertex*/
53 for(i
=0; i
<num_strips
; i
++)
55 glBegin(type_array
[i
]);
56 for(j
=0; j
<length_array
[i
]; j
++)
58 glNormal3fv(normal_array
+k
);
59 glVertex3fv(vertex_array
+k
);
66 void bezierPatchMeshListDelDeg(bezierPatchMesh
* list
)
68 bezierPatchMesh
* temp
;
69 for(temp
=list
; temp
!= NULL
; temp
= temp
->next
)
71 bezierPatchMeshDelDeg(temp
);
75 void bezierPatchMeshListDelete(bezierPatchMesh
*list
)
77 if(list
== NULL
) return;
78 bezierPatchMeshListDelete(list
->next
);
79 bezierPatchMeshDelete(list
);
85 bezierPatchMesh
* bezierPatchMeshListReverse(bezierPatchMesh
* list
)
87 bezierPatchMesh
* ret
=NULL
;
88 bezierPatchMesh
* temp
;
89 bezierPatchMesh
* nextone
;
90 for(temp
= list
; temp
!= NULL
; temp
= nextone
)
93 ret
=bezierPatchMeshListInsert(ret
, temp
);
98 /*maptype is either GL_MAP2_VERTEX_3 or GL_MAP2_VERTEX_4
100 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
)
107 if(maptype
== GL_MAP2_VERTEX_3
) dimension
= 3;
108 else if (maptype
==GL_MAP2_VERTEX_4
) dimension
= 4;
110 fprintf(stderr
, "error in inMap2f, maptype=%i is wrong, maptype,map is invalid\n", maptype
);
114 bezierPatchMesh
*ret
= (bezierPatchMesh
*) malloc(sizeof(bezierPatchMesh
));
117 ret
->bpatch_normal
= NULL
;
118 ret
->bpatch_color
= NULL
;
119 ret
->bpatch_texcoord
= NULL
;
120 ret
->bpatch
= bezierPatchMake(umin
, vmin
, umax
, vmax
, uorder
, vorder
, dimension
);
122 /*copy the control points there*/
123 the_ustride
= vorder
* dimension
;
124 the_vstride
= dimension
;
125 for(i
=0; i
<uorder
; i
++)
126 for(j
=0; j
<vorder
; j
++)
127 for(k
=0; k
<dimension
; k
++)
128 ret
->bpatch
->ctlpoints
[i
* the_ustride
+ j
*the_vstride
+k
] = ctlpoints
[i
*ustride
+j
*vstride
+k
];
131 ret
->size_UVarray
= size_UVarray
;
132 ret
->size_length_array
= size_length_array
;
133 ret
->UVarray
= (float*) malloc(sizeof(float) * size_UVarray
);
134 assert(ret
->UVarray
);
135 ret
->length_array
= (int *)malloc(sizeof(int) * size_length_array
);
136 assert(ret
->length_array
);
137 ret
->type_array
= (GLenum
*)malloc(sizeof(GLenum
) * size_length_array
);
138 assert(ret
->type_array
);
140 ret
->index_UVarray
= 0;
141 ret
->index_length_array
= 0;
143 ret
->vertex_array
= NULL
;
144 ret
->normal_array
= NULL
;
145 ret
->color_array
= NULL
;
146 ret
->texcoord_array
= NULL
;
152 bezierPatchMesh
*bezierPatchMeshMake2(int size_UVarray
, int size_length_array
)
154 bezierPatchMesh
*ret
= (bezierPatchMesh
*) malloc(sizeof(bezierPatchMesh
));
158 ret
->bpatch_normal
= NULL
;
159 ret
->bpatch_color
= NULL
;
160 ret
->bpatch_texcoord
= NULL
;
162 ret
->size_UVarray
= size_UVarray
;
163 ret
->size_length_array
= size_length_array
;
164 ret
->UVarray
= (float*) malloc(sizeof(float) * size_UVarray
);
165 assert(ret
->UVarray
);
166 ret
->length_array
= (int *)malloc(sizeof(int) * size_length_array
);
167 assert(ret
->length_array
);
168 ret
->type_array
= (GLenum
*)malloc(sizeof(GLenum
) * size_length_array
);
169 assert(ret
->type_array
);
171 ret
->index_UVarray
= 0;
172 ret
->index_length_array
= 0;
174 ret
->vertex_array
= NULL
;
175 ret
->normal_array
= NULL
;
176 ret
->color_array
= NULL
;
177 ret
->texcoord_array
= NULL
;
183 void bezierPatchMeshPutPatch(bezierPatchMesh
*bpm
, int maptype
, float umin
, float umax
, int ustride
, int uorder
, float vmin
, float vmax
, int vstride
, int vorder
, float *ctlpoints
)
186 case GL_MAP2_VERTEX_3
:
187 bpm
->bpatch
= bezierPatchMake2(umin
, vmin
, umax
, vmax
, uorder
, vorder
, 3, ustride
, vstride
, ctlpoints
);
189 case GL_MAP2_VERTEX_4
:
190 bpm
->bpatch
= bezierPatchMake2(umin
, vmin
, umax
, vmax
, uorder
, vorder
, 4,ustride
, vstride
, ctlpoints
);
193 bpm
->bpatch_normal
= bezierPatchMake2(umin
, vmin
, umax
, vmax
, uorder
, vorder
, 3, ustride
, vstride
, ctlpoints
);
196 bpm
->bpatch_color
= bezierPatchMake2(umin
, vmin
, umax
, vmax
, uorder
, vorder
, 1, ustride
, vstride
, ctlpoints
);
198 case GL_MAP2_COLOR_4
:
199 bpm
->bpatch_color
= bezierPatchMake2(umin
, vmin
, umax
, vmax
, uorder
, vorder
, 4, ustride
, vstride
, ctlpoints
);
201 case GL_MAP2_TEXTURE_COORD_1
:
202 bpm
->bpatch_texcoord
= bezierPatchMake2(umin
, vmin
, umax
, vmax
, uorder
, vorder
, 1, ustride
, vstride
, ctlpoints
);
204 case GL_MAP2_TEXTURE_COORD_2
:
205 bpm
->bpatch_texcoord
= bezierPatchMake2(umin
, vmin
, umax
, vmax
, uorder
, vorder
, 2, ustride
, vstride
, ctlpoints
);
207 case GL_MAP2_TEXTURE_COORD_3
:
208 bpm
->bpatch_texcoord
= bezierPatchMake2(umin
, vmin
, umax
, vmax
, uorder
, vorder
, 3, ustride
, vstride
, ctlpoints
);
210 case GL_MAP2_TEXTURE_COORD_4
:
211 bpm
->bpatch_texcoord
= bezierPatchMake2(umin
, vmin
, umax
, vmax
, uorder
, vorder
, 4, ustride
, vstride
, ctlpoints
);
214 fprintf(stderr
, "error in bezierPatchMeshPutPatch, maptype=%i is wrong, maptype,map is invalid\n", maptype
);
219 /*delete everything including the arrays. So if you want to output the
220 *pointers of the arrays, you should not use this function to deallocate space.
221 *you should dealocate manually
223 void bezierPatchMeshDelete(bezierPatchMesh
*bpm
)
225 if(bpm
->bpatch
!= NULL
)
226 bezierPatchDelete(bpm
->bpatch
);
227 if(bpm
->bpatch_normal
!= NULL
)
228 bezierPatchDelete(bpm
->bpatch_normal
);
229 if(bpm
->bpatch_color
!= NULL
)
230 bezierPatchDelete(bpm
->bpatch_color
);
231 if(bpm
->bpatch_texcoord
!= NULL
)
232 bezierPatchDelete(bpm
->bpatch_texcoord
);
235 free(bpm
->length_array
);
236 free(bpm
->vertex_array
);
237 free(bpm
->normal_array
);
238 free(bpm
->type_array
);
243 *type is the primitive type:
245 void bezierPatchMeshBeginStrip(bezierPatchMesh
*bpm
, GLenum type
)
251 /*signal the end of the current strip*/
252 void bezierPatchMeshEndStrip(bezierPatchMesh
*bpm
)
256 /*if there are no vertices in this strip, then nothing needs to be done*/
257 if(bpm
->counter
== 0) return;
259 /*if the length_array is full, it should be expanded*/
260 if(bpm
->index_length_array
>= bpm
->size_length_array
)
262 int *temp
= (int*) malloc(sizeof(int) * (bpm
->size_length_array
*2 + 1));
264 GLenum
*temp_type
= (GLenum
*) malloc(sizeof(GLenum
) * (bpm
->size_length_array
*2 + 1));
267 bpm
->size_length_array
= bpm
->size_length_array
*2 + 1;
270 for(i
=0; i
<bpm
->index_length_array
; i
++)
272 temp
[i
] = bpm
->length_array
[i
];
273 temp_type
[i
] = bpm
->type_array
[i
];
276 /*deallocate old array*/
277 free(bpm
->length_array
);
278 free(bpm
->type_array
);
280 /*point to the new array which is twice as bigger*/
281 bpm
->length_array
= temp
;
282 bpm
->type_array
= temp_type
;
284 bpm
->type_array
[bpm
->index_length_array
] = bpm
->type
;
285 bpm
->length_array
[bpm
->index_length_array
++] = bpm
->counter
;
290 void bezierPatchMeshInsertUV(bezierPatchMesh
*bpm
, float u
, float v
)
293 /*if the UVarray is full, it should be expanded*/
294 if(bpm
->index_UVarray
+1 >= bpm
->size_UVarray
)
296 float *temp
= (float*) malloc(sizeof(float) * (bpm
->size_UVarray
* 2 + 2));
300 bpm
->size_UVarray
= bpm
->size_UVarray
*2 + 2;
303 for(i
=0; i
<bpm
->index_UVarray
; i
++)
305 temp
[i
] = bpm
->UVarray
[i
];
308 /*deallocate old array*/
311 /*pointing to the new arrays*/
314 /*insert the new UV*/
315 bpm
->UVarray
[bpm
->index_UVarray
] = u
;
316 bpm
->index_UVarray
++;
317 bpm
->UVarray
[bpm
->index_UVarray
] = v
;
318 bpm
->index_UVarray
++;
320 /*update counter: one more vertex*/
326 void bezierPatchMeshPrint(bezierPatchMesh
*bpm
)
329 printf("the bezier patch is\n");
330 bezierPatchPrint(bpm
->bpatch
);
331 printf("index_length_array= %i\n", bpm
->index_length_array
);
332 printf("size_length_array =%i\n", bpm
->size_length_array
);
333 printf("index_UVarray =%i\n", bpm
->index_UVarray
);
334 printf("size_UVarray =%i\n", bpm
->size_UVarray
);
335 printf("UVarray is\n");
336 for(i
=0; i
<bpm
->index_UVarray
; i
++)
337 printf("%f ", bpm
->UVarray
[i
]);
339 printf("length_array is\n");
340 for(i
=0; i
<bpm
->index_length_array
; i
++)
341 printf("%i ", bpm
->length_array
[i
]);
346 /*insert a new patch in front of the current linked list and return the new list*/
347 bezierPatchMesh
* bezierPatchMeshListInsert(bezierPatchMesh
* list
, bezierPatchMesh
* bpm
)
353 /*print all the patches*/
354 void bezierPatchMeshListPrint(bezierPatchMesh
* list
)
356 bezierPatchMesh
*temp
;
357 for(temp
= list
; temp
!= NULL
; temp
= temp
->next
)
359 bezierPatchMeshPrint(temp
);
363 int bezierPatchMeshListTotalStrips(bezierPatchMesh
* list
)
366 bezierPatchMesh
*temp
;
367 for(temp
=list
; temp
!= NULL
; temp
= temp
->next
)
369 sum
+= temp
->index_length_array
;
374 int bezierPatchMeshListTotalVert(bezierPatchMesh
* list
)
377 bezierPatchMesh
*temp
;
378 for(temp
=list
; temp
!= NULL
; temp
= temp
->next
)
380 sum
+= temp
->index_UVarray
;
385 int bezierPatchMeshListNumTriangles(bezierPatchMesh
* list
)
388 bezierPatchMesh
* temp
;
389 for(temp
=list
; temp
!= NULL
; temp
= temp
->next
)
391 sum
+= bezierPatchMeshNumTriangles(temp
);
396 int bezierPatchMeshNumTriangles(bezierPatchMesh
* bpm
)
400 for(i
=0; i
<bpm
->index_length_array
; i
++)
402 switch(bpm
->type_array
[i
])
405 sum
+= bpm
->length_array
[i
]/3;
407 case GL_TRIANGLE_FAN
:
408 if(bpm
->length_array
[i
] > 2)
409 sum
+= bpm
->length_array
[i
]-2;
411 case GL_TRIANGLE_STRIP
:
412 if(bpm
->length_array
[i
] > 2)
413 sum
+= bpm
->length_array
[i
]-2;
416 if(bpm
->length_array
[i
]>2)
417 sum
+= (bpm
->length_array
[i
]-2);
420 fprintf(stderr
,"error in bezierPatchMeshListNumTriangles, type invalid\n");
426 /*delete degenerate triangles*/
427 void bezierPatchMeshDelDeg(bezierPatchMesh
* bpm
)
429 if(bpm
== NULL
) return;
431 int *new_length_array
;
432 GLenum
*new_type_array
;
433 int index_new_length_array
;
435 int index_new_UVarray
;
437 new_length_array
= (int*)malloc(sizeof(int) * bpm
->index_length_array
);
438 assert(new_length_array
);
439 new_type_array
= (GLenum
*)malloc(sizeof(GLenum
) * bpm
->index_length_array
);
440 assert(new_length_array
);
441 new_UVarray
= (float*) malloc(sizeof(float) * bpm
->index_UVarray
);
444 index_new_length_array
= 0;
447 for(i
=0; i
<bpm
->index_length_array
; i
++){
449 /*(if not degenerate, we have to copy*/
450 if( (bpm
->length_array
[i
] != 3) || (!isDegenerate(bpm
->UVarray
+k
, bpm
->UVarray
+k
+2, bpm
->UVarray
+k
+4)))
452 for(j
=0; j
<2* bpm
->length_array
[i
]; j
++)
453 new_UVarray
[index_new_UVarray
++] = bpm
->UVarray
[k
++];
455 new_length_array
[index_new_length_array
] = bpm
->length_array
[i
];
456 new_type_array
[index_new_length_array
] = bpm
->type_array
[i
];
457 index_new_length_array
++;
465 free(bpm
->length_array
);
466 free(bpm
->type_array
);
467 bpm
->UVarray
=new_UVarray
;
468 bpm
->length_array
=new_length_array
;
469 bpm
->type_array
=new_type_array
;
470 bpm
->index_UVarray
= index_new_UVarray
;
471 bpm
->index_length_array
= index_new_length_array
;
476 *the xyz and normals are stored in vertex_array,
477 *and normal_array. the spaces of both are allocated here
479 void bezierPatchMeshEval(bezierPatchMesh
* bpm
)
483 float u0
= bpm
->bpatch
->umin
;
484 float u1
= bpm
->bpatch
->umax
;
485 int uorder
= bpm
->bpatch
->uorder
;
486 float v0
= bpm
->bpatch
->vmin
;
487 float v1
= bpm
->bpatch
->vmax
;
488 int vorder
= bpm
->bpatch
->vorder
;
489 int dimension
= bpm
->bpatch
->dimension
;
490 int ustride
= dimension
* vorder
;
491 int vstride
= dimension
;
492 float *ctlpoints
= bpm
->bpatch
->ctlpoints
;
494 bpm
->vertex_array
= (float*) malloc(sizeof(float)* (bpm
->index_UVarray
/2) * 3);
495 assert(bpm
->vertex_array
);
496 bpm
->normal_array
= (float*) malloc(sizeof(float)* (bpm
->index_UVarray
/2) * 3);
497 assert(bpm
->normal_array
);
501 for(i
=0; i
<bpm
->index_length_array
; i
++)
503 for(j
=0; j
<bpm
->length_array
[i
]; j
++)
506 v
= bpm
->UVarray
[k
+1];
507 bezierSurfEval(u0
,u1
,uorder
, v0
, v1
, vorder
, dimension
, ctlpoints
, ustride
, vstride
, u
,v
, bpm
->vertex_array
+l
);
508 bezierSurfEvalNormal(u0
,u1
,uorder
, v0
, v1
, vorder
, dimension
, ctlpoints
, ustride
, vstride
, u
,v
, bpm
->normal_array
+l
);
515 void bezierPatchMeshListEval(bezierPatchMesh
* list
)
517 bezierPatchMesh
* temp
;
518 for(temp
= list
; temp
!= NULL
; temp
= temp
->next
)
520 bezierPatchMeshEval(temp
);
524 void bezierPatchMeshDraw(bezierPatchMesh
* bpm
)
528 /*k is the index of the first component of the current vertex*/
529 for(i
=0; i
<bpm
->index_length_array
; i
++)
531 glBegin(bpm
->type_array
[i
]);
532 for(j
=0; j
<bpm
->length_array
[i
]; j
++)
534 glNormal3fv(bpm
->normal_array
+k
);
535 glVertex3fv(bpm
->vertex_array
+k
);
542 void bezierPatchMeshListDraw(bezierPatchMesh
* list
)
544 bezierPatchMesh
* temp
;
545 for(temp
= list
; temp
!= NULL
; temp
= temp
->next
)
547 bezierPatchMeshDraw(temp
);
551 void bezierPatchMeshListCollect(bezierPatchMesh
* list
, float **vertex_array
, float **normal_array
, int **length_array
, GLenum
**type_array
, int *num_strips
)
554 bezierPatchMesh
*temp
;
555 int total_num_vertices
= bezierPatchMeshListTotalVert(list
);
556 (*vertex_array
) = (float *) malloc(sizeof(float) * total_num_vertices
*3);
557 assert(*vertex_array
);
558 (*normal_array
) = (float *) malloc(sizeof(float) * total_num_vertices
*3);
559 assert(*normal_array
);
561 *num_strips
= bezierPatchMeshListTotalStrips(list
);
563 *length_array
= (int*) malloc(sizeof(int) * (*num_strips
));
564 assert(*length_array
);
566 *type_array
= (GLenum
*) malloc(sizeof(GLenum
) * (*num_strips
));
571 for(temp
= list
; temp
!= NULL
; temp
= temp
->next
)
574 for(i
=0; i
<temp
->index_length_array
; i
++)
576 for(j
=0; j
<temp
->length_array
[i
]; j
++)
578 (*vertex_array
)[k
] = temp
->vertex_array
[x
];
579 (*vertex_array
)[k
+1] = temp
->vertex_array
[x
+1];
580 (*vertex_array
)[k
+2] = temp
->vertex_array
[x
+2];
582 (*normal_array
)[k
] = temp
->normal_array
[x
];
583 (*normal_array
)[k
+1] = temp
->normal_array
[x
+1];
584 (*normal_array
)[k
+2] = temp
->normal_array
[x
+2];
589 (*type_array
)[l
] = temp
->type_array
[i
];
590 (*length_array
)[l
++] = temp
->length_array
[i
];
597 static int isDegenerate(float A
[2], float B
[2], float C
[2])
599 if( (A
[0] == B
[0] && A
[1]==B
[1]) ||
600 (A
[0] == C
[0] && A
[1]==C
[1]) ||
601 (B
[0] == C
[0] && B
[1]==C
[1])