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 bezierPatchMesh
*ret
= (bezierPatchMesh
*) malloc(sizeof(bezierPatchMesh
));
111 ret
->bpatch_normal
= NULL
;
112 ret
->bpatch_color
= NULL
;
113 ret
->bpatch_texcoord
= NULL
;
115 if(maptype
== GL_MAP2_VERTEX_3
) dimension
= 3;
116 else if (maptype
==GL_MAP2_VERTEX_4
) dimension
= 4;
118 fprintf(stderr
, "error in inMap2f, maptype=%i is wrong, maptype,map is invalid\n", maptype
);
122 ret
->bpatch
= bezierPatchMake(umin
, vmin
, umax
, vmax
, uorder
, vorder
, dimension
);
123 /*copy the control points there*/
124 the_ustride
= vorder
* dimension
;
125 the_vstride
= dimension
;
126 for(i
=0; i
<uorder
; i
++)
127 for(j
=0; j
<vorder
; j
++)
128 for(k
=0; k
<dimension
; k
++)
129 ret
->bpatch
->ctlpoints
[i
* the_ustride
+ j
*the_vstride
+k
] = ctlpoints
[i
*ustride
+j
*vstride
+k
];
132 ret
->size_UVarray
= size_UVarray
;
133 ret
->size_length_array
= size_length_array
;
134 ret
->UVarray
= (float*) malloc(sizeof(float) * size_UVarray
);
135 assert(ret
->UVarray
);
136 ret
->length_array
= (int *)malloc(sizeof(int) * size_length_array
);
137 assert(ret
->length_array
);
138 ret
->type_array
= (GLenum
*)malloc(sizeof(GLenum
) * size_length_array
);
139 assert(ret
->type_array
);
141 ret
->index_UVarray
= 0;
142 ret
->index_length_array
= 0;
144 ret
->vertex_array
= NULL
;
145 ret
->normal_array
= NULL
;
146 ret
->color_array
= NULL
;
147 ret
->texcoord_array
= NULL
;
153 bezierPatchMesh
*bezierPatchMeshMake2(int size_UVarray
, int size_length_array
)
155 bezierPatchMesh
*ret
= (bezierPatchMesh
*) malloc(sizeof(bezierPatchMesh
));
159 ret
->bpatch_normal
= NULL
;
160 ret
->bpatch_color
= NULL
;
161 ret
->bpatch_texcoord
= NULL
;
163 ret
->size_UVarray
= size_UVarray
;
164 ret
->size_length_array
= size_length_array
;
165 ret
->UVarray
= (float*) malloc(sizeof(float) * size_UVarray
);
166 assert(ret
->UVarray
);
167 ret
->length_array
= (int *)malloc(sizeof(int) * size_length_array
);
168 assert(ret
->length_array
);
169 ret
->type_array
= (GLenum
*)malloc(sizeof(GLenum
) * size_length_array
);
170 assert(ret
->type_array
);
172 ret
->index_UVarray
= 0;
173 ret
->index_length_array
= 0;
175 ret
->vertex_array
= NULL
;
176 ret
->normal_array
= NULL
;
177 ret
->color_array
= NULL
;
178 ret
->texcoord_array
= NULL
;
184 void bezierPatchMeshPutPatch(bezierPatchMesh
*bpm
, int maptype
, float umin
, float umax
, int ustride
, int uorder
, float vmin
, float vmax
, int vstride
, int vorder
, float *ctlpoints
)
187 case GL_MAP2_VERTEX_3
:
188 bpm
->bpatch
= bezierPatchMake2(umin
, vmin
, umax
, vmax
, uorder
, vorder
, 3, ustride
, vstride
, ctlpoints
);
190 case GL_MAP2_VERTEX_4
:
191 bpm
->bpatch
= bezierPatchMake2(umin
, vmin
, umax
, vmax
, uorder
, vorder
, 4,ustride
, vstride
, ctlpoints
);
194 bpm
->bpatch_normal
= bezierPatchMake2(umin
, vmin
, umax
, vmax
, uorder
, vorder
, 3, ustride
, vstride
, ctlpoints
);
197 bpm
->bpatch_color
= bezierPatchMake2(umin
, vmin
, umax
, vmax
, uorder
, vorder
, 1, ustride
, vstride
, ctlpoints
);
199 case GL_MAP2_COLOR_4
:
200 bpm
->bpatch_color
= bezierPatchMake2(umin
, vmin
, umax
, vmax
, uorder
, vorder
, 4, ustride
, vstride
, ctlpoints
);
202 case GL_MAP2_TEXTURE_COORD_1
:
203 bpm
->bpatch_texcoord
= bezierPatchMake2(umin
, vmin
, umax
, vmax
, uorder
, vorder
, 1, ustride
, vstride
, ctlpoints
);
205 case GL_MAP2_TEXTURE_COORD_2
:
206 bpm
->bpatch_texcoord
= bezierPatchMake2(umin
, vmin
, umax
, vmax
, uorder
, vorder
, 2, ustride
, vstride
, ctlpoints
);
208 case GL_MAP2_TEXTURE_COORD_3
:
209 bpm
->bpatch_texcoord
= bezierPatchMake2(umin
, vmin
, umax
, vmax
, uorder
, vorder
, 3, ustride
, vstride
, ctlpoints
);
211 case GL_MAP2_TEXTURE_COORD_4
:
212 bpm
->bpatch_texcoord
= bezierPatchMake2(umin
, vmin
, umax
, vmax
, uorder
, vorder
, 4, ustride
, vstride
, ctlpoints
);
215 fprintf(stderr
, "error in bezierPatchMeshPutPatch, maptype=%i is wrong, maptype,map is invalid\n", maptype
);
220 /*delete everything including the arrays. So if you want to output the
221 *pointers of the arrays, you should not use this function to deallocate space.
222 *you should dealocate manually
224 void bezierPatchMeshDelete(bezierPatchMesh
*bpm
)
226 if(bpm
->bpatch
!= NULL
)
227 bezierPatchDelete(bpm
->bpatch
);
228 if(bpm
->bpatch_normal
!= NULL
)
229 bezierPatchDelete(bpm
->bpatch_normal
);
230 if(bpm
->bpatch_color
!= NULL
)
231 bezierPatchDelete(bpm
->bpatch_color
);
232 if(bpm
->bpatch_texcoord
!= NULL
)
233 bezierPatchDelete(bpm
->bpatch_texcoord
);
236 free(bpm
->length_array
);
237 free(bpm
->vertex_array
);
238 free(bpm
->normal_array
);
239 free(bpm
->type_array
);
244 *type is the primitive type:
246 void bezierPatchMeshBeginStrip(bezierPatchMesh
*bpm
, GLenum type
)
252 /*signal the end of the current strip*/
253 void bezierPatchMeshEndStrip(bezierPatchMesh
*bpm
)
257 /*if there are no vertices in this strip, then nothing needs to be done*/
258 if(bpm
->counter
== 0) return;
260 /*if the length_array is full, it should be expanded*/
261 if(bpm
->index_length_array
>= bpm
->size_length_array
)
263 int *temp
= (int*) malloc(sizeof(int) * (bpm
->size_length_array
*2 + 1));
265 GLenum
*temp_type
= (GLenum
*) malloc(sizeof(GLenum
) * (bpm
->size_length_array
*2 + 1));
268 bpm
->size_length_array
= bpm
->size_length_array
*2 + 1;
271 for(i
=0; i
<bpm
->index_length_array
; i
++)
273 temp
[i
] = bpm
->length_array
[i
];
274 temp_type
[i
] = bpm
->type_array
[i
];
277 /*deallocate old array*/
278 free(bpm
->length_array
);
279 free(bpm
->type_array
);
281 /*point to the new array which is twice as bigger*/
282 bpm
->length_array
= temp
;
283 bpm
->type_array
= temp_type
;
285 bpm
->type_array
[bpm
->index_length_array
] = bpm
->type
;
286 bpm
->length_array
[bpm
->index_length_array
++] = bpm
->counter
;
291 void bezierPatchMeshInsertUV(bezierPatchMesh
*bpm
, float u
, float v
)
294 /*if the UVarray is full, it should be expanded*/
295 if(bpm
->index_UVarray
+1 >= bpm
->size_UVarray
)
297 float *temp
= (float*) malloc(sizeof(float) * (bpm
->size_UVarray
* 2 + 2));
301 bpm
->size_UVarray
= bpm
->size_UVarray
*2 + 2;
304 for(i
=0; i
<bpm
->index_UVarray
; i
++)
306 temp
[i
] = bpm
->UVarray
[i
];
309 /*deallocate old array*/
312 /*pointing to the new arrays*/
315 /*insert the new UV*/
316 bpm
->UVarray
[bpm
->index_UVarray
] = u
;
317 bpm
->index_UVarray
++;
318 bpm
->UVarray
[bpm
->index_UVarray
] = v
;
319 bpm
->index_UVarray
++;
321 /*update counter: one more vertex*/
327 void bezierPatchMeshPrint(bezierPatchMesh
*bpm
)
330 printf("the bezier patch is\n");
331 bezierPatchPrint(bpm
->bpatch
);
332 printf("index_length_array= %i\n", bpm
->index_length_array
);
333 printf("size_length_array =%i\n", bpm
->size_length_array
);
334 printf("index_UVarray =%i\n", bpm
->index_UVarray
);
335 printf("size_UVarray =%i\n", bpm
->size_UVarray
);
336 printf("UVarray is\n");
337 for(i
=0; i
<bpm
->index_UVarray
; i
++)
338 printf("%f ", bpm
->UVarray
[i
]);
340 printf("length_array is\n");
341 for(i
=0; i
<bpm
->index_length_array
; i
++)
342 printf("%i ", bpm
->length_array
[i
]);
347 /*insert a new patch in front of the current linked list and return the new list*/
348 bezierPatchMesh
* bezierPatchMeshListInsert(bezierPatchMesh
* list
, bezierPatchMesh
* bpm
)
354 /*print all the patches*/
355 void bezierPatchMeshListPrint(bezierPatchMesh
* list
)
357 bezierPatchMesh
*temp
;
358 for(temp
= list
; temp
!= NULL
; temp
= temp
->next
)
360 bezierPatchMeshPrint(temp
);
364 int bezierPatchMeshListTotalStrips(bezierPatchMesh
* list
)
367 bezierPatchMesh
*temp
;
368 for(temp
=list
; temp
!= NULL
; temp
= temp
->next
)
370 sum
+= temp
->index_length_array
;
375 int bezierPatchMeshListTotalVert(bezierPatchMesh
* list
)
378 bezierPatchMesh
*temp
;
379 for(temp
=list
; temp
!= NULL
; temp
= temp
->next
)
381 sum
+= temp
->index_UVarray
;
386 int bezierPatchMeshListNumTriangles(bezierPatchMesh
* list
)
389 bezierPatchMesh
* temp
;
390 for(temp
=list
; temp
!= NULL
; temp
= temp
->next
)
392 sum
+= bezierPatchMeshNumTriangles(temp
);
397 int bezierPatchMeshNumTriangles(bezierPatchMesh
* bpm
)
401 for(i
=0; i
<bpm
->index_length_array
; i
++)
403 switch(bpm
->type_array
[i
])
406 sum
+= bpm
->length_array
[i
]/3;
408 case GL_TRIANGLE_FAN
:
409 if(bpm
->length_array
[i
] > 2)
410 sum
+= bpm
->length_array
[i
]-2;
412 case GL_TRIANGLE_STRIP
:
413 if(bpm
->length_array
[i
] > 2)
414 sum
+= bpm
->length_array
[i
]-2;
417 if(bpm
->length_array
[i
]>2)
418 sum
+= (bpm
->length_array
[i
]-2);
421 fprintf(stderr
,"error in bezierPatchMeshListNumTriangles, type invalid\n");
427 /*delete degenerate triangles*/
428 void bezierPatchMeshDelDeg(bezierPatchMesh
* bpm
)
430 if(bpm
== NULL
) return;
432 int *new_length_array
;
433 GLenum
*new_type_array
;
434 int index_new_length_array
;
436 int index_new_UVarray
;
438 new_length_array
= (int*)malloc(sizeof(int) * bpm
->index_length_array
);
439 assert(new_length_array
);
440 new_type_array
= (GLenum
*)malloc(sizeof(GLenum
) * bpm
->index_length_array
);
441 assert(new_length_array
);
442 new_UVarray
= (float*) malloc(sizeof(float) * bpm
->index_UVarray
);
445 index_new_length_array
= 0;
448 for(i
=0; i
<bpm
->index_length_array
; i
++){
450 /*(if not degenerate, we have to copy*/
451 if( (bpm
->length_array
[i
] != 3) || (!isDegenerate(bpm
->UVarray
+k
, bpm
->UVarray
+k
+2, bpm
->UVarray
+k
+4)))
453 for(j
=0; j
<2* bpm
->length_array
[i
]; j
++)
454 new_UVarray
[index_new_UVarray
++] = bpm
->UVarray
[k
++];
456 new_length_array
[index_new_length_array
] = bpm
->length_array
[i
];
457 new_type_array
[index_new_length_array
] = bpm
->type_array
[i
];
458 index_new_length_array
++;
466 free(bpm
->length_array
);
467 free(bpm
->type_array
);
468 bpm
->UVarray
=new_UVarray
;
469 bpm
->length_array
=new_length_array
;
470 bpm
->type_array
=new_type_array
;
471 bpm
->index_UVarray
= index_new_UVarray
;
472 bpm
->index_length_array
= index_new_length_array
;
477 *the xyz and normals are stored in vertex_array,
478 *and normal_array. the spaces of both are allocated here
480 void bezierPatchMeshEval(bezierPatchMesh
* bpm
)
484 float u0
= bpm
->bpatch
->umin
;
485 float u1
= bpm
->bpatch
->umax
;
486 int uorder
= bpm
->bpatch
->uorder
;
487 float v0
= bpm
->bpatch
->vmin
;
488 float v1
= bpm
->bpatch
->vmax
;
489 int vorder
= bpm
->bpatch
->vorder
;
490 int dimension
= bpm
->bpatch
->dimension
;
491 int ustride
= dimension
* vorder
;
492 int vstride
= dimension
;
493 float *ctlpoints
= bpm
->bpatch
->ctlpoints
;
495 bpm
->vertex_array
= (float*) malloc(sizeof(float)* (bpm
->index_UVarray
/2) * 3);
496 assert(bpm
->vertex_array
);
497 bpm
->normal_array
= (float*) malloc(sizeof(float)* (bpm
->index_UVarray
/2) * 3);
498 assert(bpm
->normal_array
);
502 for(i
=0; i
<bpm
->index_length_array
; i
++)
504 for(j
=0; j
<bpm
->length_array
[i
]; j
++)
507 v
= bpm
->UVarray
[k
+1];
508 bezierSurfEval(u0
,u1
,uorder
, v0
, v1
, vorder
, dimension
, ctlpoints
, ustride
, vstride
, u
,v
, bpm
->vertex_array
+l
);
509 bezierSurfEvalNormal(u0
,u1
,uorder
, v0
, v1
, vorder
, dimension
, ctlpoints
, ustride
, vstride
, u
,v
, bpm
->normal_array
+l
);
516 void bezierPatchMeshListEval(bezierPatchMesh
* list
)
518 bezierPatchMesh
* temp
;
519 for(temp
= list
; temp
!= NULL
; temp
= temp
->next
)
521 bezierPatchMeshEval(temp
);
525 void bezierPatchMeshDraw(bezierPatchMesh
* bpm
)
529 /*k is the index of the first component of the current vertex*/
530 for(i
=0; i
<bpm
->index_length_array
; i
++)
532 glBegin(bpm
->type_array
[i
]);
533 for(j
=0; j
<bpm
->length_array
[i
]; j
++)
535 glNormal3fv(bpm
->normal_array
+k
);
536 glVertex3fv(bpm
->vertex_array
+k
);
543 void bezierPatchMeshListDraw(bezierPatchMesh
* list
)
545 bezierPatchMesh
* temp
;
546 for(temp
= list
; temp
!= NULL
; temp
= temp
->next
)
548 bezierPatchMeshDraw(temp
);
552 void bezierPatchMeshListCollect(bezierPatchMesh
* list
, float **vertex_array
, float **normal_array
, int **length_array
, GLenum
**type_array
, int *num_strips
)
555 bezierPatchMesh
*temp
;
556 int total_num_vertices
= bezierPatchMeshListTotalVert(list
);
557 (*vertex_array
) = (float *) malloc(sizeof(float) * total_num_vertices
*3);
558 assert(*vertex_array
);
559 (*normal_array
) = (float *) malloc(sizeof(float) * total_num_vertices
*3);
560 assert(*normal_array
);
562 *num_strips
= bezierPatchMeshListTotalStrips(list
);
564 *length_array
= (int*) malloc(sizeof(int) * (*num_strips
));
565 assert(*length_array
);
567 *type_array
= (GLenum
*) malloc(sizeof(GLenum
) * (*num_strips
));
572 for(temp
= list
; temp
!= NULL
; temp
= temp
->next
)
575 for(i
=0; i
<temp
->index_length_array
; i
++)
577 for(j
=0; j
<temp
->length_array
[i
]; j
++)
579 (*vertex_array
)[k
] = temp
->vertex_array
[x
];
580 (*vertex_array
)[k
+1] = temp
->vertex_array
[x
+1];
581 (*vertex_array
)[k
+2] = temp
->vertex_array
[x
+2];
583 (*normal_array
)[k
] = temp
->normal_array
[x
];
584 (*normal_array
)[k
+1] = temp
->normal_array
[x
+1];
585 (*normal_array
)[k
+2] = temp
->normal_array
[x
+2];
590 (*type_array
)[l
] = temp
->type_array
[i
];
591 (*length_array
)[l
++] = temp
->length_array
[i
];
598 static int isDegenerate(float A
[2], float B
[2], float C
[2])
600 if( (A
[0] == B
[0] && A
[1]==B
[1]) ||
601 (A
[0] == C
[0] && A
[1]==C
[1]) ||
602 (B
[0] == C
[0] && B
[1]==C
[1])