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