Merge branch 'master' into gallium-0.2
[mesa.git] / src / glu / sgi / libnurbs / interface / bezierPatchMesh.cc
1 /*
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:
9 **
10 ** http://oss.sgi.com/projects/FreeB
11 **
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.
17 **
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.
23 **
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.
33 **
34 */
35 /*
36 */
37
38 #include "gluos.h"
39 #include <stdlib.h>
40 #include <stdio.h>
41 #include <assert.h>
42 #include <GL/gl.h>
43 #include "bezierEval.h"
44 #include "bezierPatchMesh.h"
45
46 static int isDegenerate(float A[2], float B[2], float C[2]);
47
48 void drawStrips(float *vertex_array, float *normal_array, int *length_array, GLenum *type_array, int num_strips)
49 {
50 int i,j,k;
51 k=0;
52 /*k is the index of the first component of the current vertex*/
53 for(i=0; i<num_strips; i++)
54 {
55 glBegin(type_array[i]);
56 for(j=0; j<length_array[i]; j++)
57 {
58 glNormal3fv(normal_array+k);
59 glVertex3fv(vertex_array+k);
60 k += 3;
61 }
62 glEnd();
63 }
64 }
65
66 void bezierPatchMeshListDelDeg(bezierPatchMesh* list)
67 {
68 bezierPatchMesh* temp;
69 for(temp=list; temp != NULL; temp = temp->next)
70 {
71 bezierPatchMeshDelDeg(temp);
72 }
73 }
74
75 void bezierPatchMeshListDelete(bezierPatchMesh *list)
76 {
77 if(list == NULL) return;
78 bezierPatchMeshListDelete(list->next);
79 bezierPatchMeshDelete(list);
80 }
81
82
83
84
85 bezierPatchMesh* bezierPatchMeshListReverse(bezierPatchMesh* list)
86 {
87 bezierPatchMesh* ret=NULL;
88 bezierPatchMesh* temp;
89 bezierPatchMesh* nextone;
90 for(temp = list; temp != NULL; temp = nextone)
91 {
92 nextone = temp->next;
93 ret=bezierPatchMeshListInsert(ret, temp);
94 }
95 return ret;
96 }
97
98 /*maptype is either GL_MAP2_VERTEX_3 or GL_MAP2_VERTEX_4
99 */
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)
101 {
102 int i,j,k;
103 int dimension;
104 int the_ustride;
105 int the_vstride;
106
107 bezierPatchMesh *ret = (bezierPatchMesh*) malloc(sizeof(bezierPatchMesh));
108 assert(ret);
109
110 ret->bpatch = NULL;
111 ret->bpatch_normal = NULL;
112 ret->bpatch_color = NULL;
113 ret->bpatch_texcoord = NULL;
114
115 if(maptype == GL_MAP2_VERTEX_3) dimension = 3;
116 else if (maptype==GL_MAP2_VERTEX_4) dimension = 4;
117 else {
118 fprintf(stderr, "error in inMap2f, maptype=%i is wrong, maptype,map is invalid\n", maptype);
119 return NULL;
120 }
121
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];
130
131
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);
140
141 ret->index_UVarray = 0;
142 ret->index_length_array = 0;
143
144 ret->vertex_array = NULL;
145 ret->normal_array = NULL;
146 ret->color_array = NULL;
147 ret->texcoord_array = NULL;
148
149 ret->next = NULL;
150 return ret;
151 }
152
153 bezierPatchMesh *bezierPatchMeshMake2(int size_UVarray, int size_length_array)
154 {
155 bezierPatchMesh *ret = (bezierPatchMesh*) malloc(sizeof(bezierPatchMesh));
156 assert(ret);
157
158 ret->bpatch = NULL;
159 ret->bpatch_normal = NULL;
160 ret->bpatch_color = NULL;
161 ret->bpatch_texcoord = NULL;
162
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);
171
172 ret->index_UVarray = 0;
173 ret->index_length_array = 0;
174
175 ret->vertex_array = NULL;
176 ret->normal_array = NULL;
177 ret->color_array = NULL;
178 ret->texcoord_array = NULL;
179
180 ret->next = NULL;
181 return ret;
182 }
183
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)
185 {
186 switch(maptype){
187 case GL_MAP2_VERTEX_3:
188 bpm->bpatch = bezierPatchMake2(umin, vmin, umax, vmax, uorder, vorder, 3, ustride, vstride, ctlpoints);
189 break;
190 case GL_MAP2_VERTEX_4:
191 bpm->bpatch = bezierPatchMake2(umin, vmin, umax, vmax, uorder, vorder, 4,ustride, vstride, ctlpoints );
192 break;
193 case GL_MAP2_NORMAL:
194 bpm->bpatch_normal = bezierPatchMake2(umin, vmin, umax, vmax, uorder, vorder, 3, ustride, vstride, ctlpoints);
195 break;
196 case GL_MAP2_INDEX:
197 bpm->bpatch_color = bezierPatchMake2(umin, vmin, umax, vmax, uorder, vorder, 1, ustride, vstride, ctlpoints);
198 break;
199 case GL_MAP2_COLOR_4:
200 bpm->bpatch_color = bezierPatchMake2(umin, vmin, umax, vmax, uorder, vorder, 4, ustride, vstride, ctlpoints);
201 break;
202 case GL_MAP2_TEXTURE_COORD_1:
203 bpm->bpatch_texcoord = bezierPatchMake2(umin, vmin, umax, vmax, uorder, vorder, 1, ustride, vstride, ctlpoints);
204 break;
205 case GL_MAP2_TEXTURE_COORD_2:
206 bpm->bpatch_texcoord = bezierPatchMake2(umin, vmin, umax, vmax, uorder, vorder, 2, ustride, vstride, ctlpoints);
207 break;
208 case GL_MAP2_TEXTURE_COORD_3:
209 bpm->bpatch_texcoord = bezierPatchMake2(umin, vmin, umax, vmax, uorder, vorder, 3, ustride, vstride, ctlpoints);
210 break;
211 case GL_MAP2_TEXTURE_COORD_4:
212 bpm->bpatch_texcoord = bezierPatchMake2(umin, vmin, umax, vmax, uorder, vorder, 4, ustride, vstride, ctlpoints);
213 break;
214 default:
215 fprintf(stderr, "error in bezierPatchMeshPutPatch, maptype=%i is wrong, maptype,map is invalid\n", maptype);
216 }
217 }
218
219
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
223 */
224 void bezierPatchMeshDelete(bezierPatchMesh *bpm)
225 {
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);
234
235 free(bpm->UVarray);
236 free(bpm->length_array);
237 free(bpm->vertex_array);
238 free(bpm->normal_array);
239 free(bpm->type_array);
240 free(bpm);
241 }
242
243 /*begin a strip
244 *type is the primitive type:
245 */
246 void bezierPatchMeshBeginStrip(bezierPatchMesh *bpm, GLenum type)
247 {
248 bpm->counter = 0;
249 bpm->type = type;
250 }
251
252 /*signal the end of the current strip*/
253 void bezierPatchMeshEndStrip(bezierPatchMesh *bpm)
254 {
255 int i;
256
257 /*if there are no vertices in this strip, then nothing needs to be done*/
258 if(bpm->counter == 0) return;
259
260 /*if the length_array is full, it should be expanded*/
261 if(bpm->index_length_array >= bpm->size_length_array)
262 {
263 int *temp = (int*) malloc(sizeof(int) * (bpm->size_length_array*2 + 1));
264 assert(temp);
265 GLenum *temp_type = (GLenum*) malloc(sizeof(GLenum) * (bpm->size_length_array*2 + 1));
266 assert(temp_type);
267 /*update the size*/
268 bpm->size_length_array = bpm->size_length_array*2 + 1;
269
270 /*copy*/
271 for(i=0; i<bpm->index_length_array; i++)
272 {
273 temp[i] = bpm->length_array[i];
274 temp_type[i] = bpm->type_array[i];
275 }
276
277 /*deallocate old array*/
278 free(bpm->length_array);
279 free(bpm->type_array);
280
281 /*point to the new array which is twice as bigger*/
282 bpm->length_array = temp;
283 bpm->type_array = temp_type;
284 }
285 bpm->type_array[bpm->index_length_array] = bpm->type;
286 bpm->length_array[bpm->index_length_array++] = bpm->counter;
287
288 }
289
290 /*insert (u,v) */
291 void bezierPatchMeshInsertUV(bezierPatchMesh *bpm, float u, float v)
292 {
293 int i;
294 /*if the UVarray is full, it should be expanded*/
295 if(bpm->index_UVarray+1 >= bpm->size_UVarray)
296 {
297 float *temp = (float*) malloc(sizeof(float) * (bpm->size_UVarray * 2 + 2));
298 assert(temp);
299
300 /*update the size*/
301 bpm->size_UVarray = bpm->size_UVarray*2 + 2;
302
303 /*copy*/
304 for(i=0; i<bpm->index_UVarray; i++)
305 {
306 temp[i] = bpm->UVarray[i];
307 }
308
309 /*deallocate old array*/
310 free(bpm->UVarray);
311
312 /*pointing to the new arrays*/
313 bpm->UVarray = temp;
314 }
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++;
320
321 /*update counter: one more vertex*/
322 bpm->counter++;
323
324
325 }
326
327 void bezierPatchMeshPrint(bezierPatchMesh *bpm)
328 {
329 int i;
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]);
339
340 printf("length_array is\n");
341 for(i=0; i<bpm->index_length_array; i++)
342 printf("%i ", bpm->length_array[i]);
343 printf("\n");
344
345 }
346
347 /*insert a new patch in front of the current linked list and return the new list*/
348 bezierPatchMesh* bezierPatchMeshListInsert(bezierPatchMesh* list, bezierPatchMesh* bpm)
349 {
350 bpm->next=list;
351 return bpm;
352 }
353
354 /*print all the patches*/
355 void bezierPatchMeshListPrint(bezierPatchMesh* list)
356 {
357 bezierPatchMesh *temp;
358 for(temp = list; temp != NULL; temp = temp->next)
359 {
360 bezierPatchMeshPrint(temp);
361 }
362 }
363
364 int bezierPatchMeshListTotalStrips(bezierPatchMesh* list)
365 {
366 int sum=0;
367 bezierPatchMesh *temp;
368 for(temp=list; temp != NULL; temp = temp->next)
369 {
370 sum += temp->index_length_array;
371 }
372 return sum;
373 }
374
375 int bezierPatchMeshListTotalVert(bezierPatchMesh* list)
376 {
377 int sum=0;
378 bezierPatchMesh *temp;
379 for(temp=list; temp != NULL; temp = temp->next)
380 {
381 sum += temp->index_UVarray;
382 }
383 return sum/2;
384 }
385
386 int bezierPatchMeshListNumTriangles(bezierPatchMesh* list)
387 {
388 int sum=0;
389 bezierPatchMesh* temp;
390 for(temp=list; temp != NULL; temp = temp->next)
391 {
392 sum += bezierPatchMeshNumTriangles(temp);
393 }
394 return sum;
395 }
396
397 int bezierPatchMeshNumTriangles(bezierPatchMesh* bpm)
398 {
399 int i;
400 int sum=0;
401 for(i=0; i<bpm->index_length_array; i++)
402 {
403 switch(bpm->type_array[i])
404 {
405 case GL_TRIANGLES:
406 sum += bpm->length_array[i]/3;
407 break;
408 case GL_TRIANGLE_FAN:
409 if(bpm->length_array[i] > 2)
410 sum += bpm->length_array[i]-2;
411 break;
412 case GL_TRIANGLE_STRIP:
413 if(bpm->length_array[i] > 2)
414 sum += bpm->length_array[i]-2;
415 break;
416 case GL_QUAD_STRIP:
417 if(bpm->length_array[i]>2)
418 sum += (bpm->length_array[i]-2);
419 break;
420 default:
421 fprintf(stderr,"error in bezierPatchMeshListNumTriangles, type invalid\n");
422 }
423 }
424 return sum;
425 }
426
427 /*delete degenerate triangles*/
428 void bezierPatchMeshDelDeg(bezierPatchMesh* bpm)
429 {
430 if(bpm == NULL) return;
431 int i,j,k;
432 int *new_length_array;
433 GLenum *new_type_array;
434 int index_new_length_array;
435 float *new_UVarray;
436 int index_new_UVarray;
437
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);
443 assert(new_UVarray);
444
445 index_new_length_array = 0;
446 index_new_UVarray=0;
447 k=0;
448 for(i=0; i<bpm->index_length_array; i++){
449
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)))
452 {
453 for(j=0; j<2* bpm->length_array[i]; j++)
454 new_UVarray[index_new_UVarray++] = bpm->UVarray[k++];
455
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++;
459 }
460 else
461 {
462 k += 6;
463 }
464 }
465 free(bpm->UVarray);
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;
473
474 }
475
476 /*(u,v) to XYZ
477 *the xyz and normals are stored in vertex_array,
478 *and normal_array. the spaces of both are allocated here
479 */
480 void bezierPatchMeshEval(bezierPatchMesh* bpm)
481 {
482 int i,j,k,l;
483 float u,v;
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;
494
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);
499
500 k=0;
501 l=0;
502 for(i=0; i<bpm->index_length_array; i++)
503 {
504 for(j=0; j<bpm->length_array[i]; j++)
505 {
506 u = bpm->UVarray[k];
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);
510 k += 2;
511 l += 3;
512 }
513 }
514 }
515
516 void bezierPatchMeshListEval(bezierPatchMesh* list)
517 {
518 bezierPatchMesh* temp;
519 for(temp = list; temp != NULL; temp = temp->next)
520 {
521 bezierPatchMeshEval(temp);
522 }
523 }
524
525 void bezierPatchMeshDraw(bezierPatchMesh* bpm)
526 {
527 int i,j,k;
528 k=0;
529 /*k is the index of the first component of the current vertex*/
530 for(i=0; i<bpm->index_length_array; i++)
531 {
532 glBegin(bpm->type_array[i]);
533 for(j=0; j<bpm->length_array[i]; j++)
534 {
535 glNormal3fv(bpm->normal_array+k);
536 glVertex3fv(bpm->vertex_array+k);
537 k+= 3;
538 }
539 glEnd();
540 }
541 }
542
543 void bezierPatchMeshListDraw(bezierPatchMesh* list)
544 {
545 bezierPatchMesh* temp;
546 for(temp = list; temp != NULL; temp = temp->next)
547 {
548 bezierPatchMeshDraw(temp);
549 }
550 }
551
552 void bezierPatchMeshListCollect(bezierPatchMesh* list, float **vertex_array, float **normal_array, int **length_array, GLenum **type_array, int *num_strips)
553 {
554 int i,j,k,l;
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);
561
562 *num_strips = bezierPatchMeshListTotalStrips(list);
563
564 *length_array = (int*) malloc(sizeof(int) * (*num_strips));
565 assert(*length_array);
566
567 *type_array = (GLenum*) malloc(sizeof(GLenum) * (*num_strips));
568 assert(*type_array);
569
570 k=0;
571 l=0;
572 for(temp = list; temp != NULL; temp = temp->next)
573 {
574 int x=0;
575 for(i=0; i<temp->index_length_array; i++)
576 {
577 for(j=0; j<temp->length_array[i]; j++)
578 {
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];
582
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];
586
587 x += 3;
588 k += 3;
589 }
590 (*type_array)[l] = temp->type_array[i];
591 (*length_array)[l++] = temp->length_array[i];
592 }
593 }
594 }
595
596
597
598 static int isDegenerate(float A[2], float B[2], float C[2])
599 {
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])
603 )
604 return 1;
605 else
606 return 0;
607 }
608
609
610
611