Tizen 2.0 Release
[profile/ivi/osmesa.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   if(maptype == GL_MAP2_VERTEX_3) dimension = 3;
108   else if (maptype==GL_MAP2_VERTEX_4) dimension = 4;
109   else {
110     fprintf(stderr, "error in inMap2f, maptype=%i is wrong, maptype,map is invalid\n", maptype);
111     return NULL;
112   }
113
114   bezierPatchMesh *ret = (bezierPatchMesh*) malloc(sizeof(bezierPatchMesh));
115   assert(ret);
116
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);
121
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];
129   
130
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);
139
140   ret->index_UVarray = 0;
141   ret->index_length_array = 0;
142
143   ret->vertex_array = NULL;
144   ret->normal_array = NULL;
145   ret->color_array  = NULL;
146   ret->texcoord_array = NULL;
147
148   ret->next = NULL;
149   return ret;
150 }
151
152 bezierPatchMesh *bezierPatchMeshMake2(int size_UVarray, int size_length_array)
153 {
154   bezierPatchMesh *ret = (bezierPatchMesh*) malloc(sizeof(bezierPatchMesh));
155   assert(ret);
156
157   ret->bpatch = NULL;
158   ret->bpatch_normal = NULL;
159   ret->bpatch_color  = NULL;
160   ret->bpatch_texcoord = NULL;
161
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);
170
171   ret->index_UVarray = 0;
172   ret->index_length_array = 0;
173
174   ret->vertex_array = NULL;
175   ret->normal_array = NULL;
176   ret->color_array  = NULL;
177   ret->texcoord_array = NULL;
178
179   ret->next = NULL;
180   return ret;
181 }
182
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)
184 {
185   switch(maptype){
186   case GL_MAP2_VERTEX_3:
187     bpm->bpatch = bezierPatchMake2(umin, vmin, umax, vmax, uorder, vorder, 3, ustride, vstride, ctlpoints);
188     break;
189   case GL_MAP2_VERTEX_4:
190     bpm->bpatch = bezierPatchMake2(umin, vmin, umax, vmax, uorder, vorder, 4,ustride, vstride, ctlpoints );
191     break;
192   case GL_MAP2_NORMAL:
193     bpm->bpatch_normal = bezierPatchMake2(umin, vmin, umax, vmax, uorder, vorder, 3, ustride, vstride, ctlpoints);
194     break;
195   case GL_MAP2_INDEX:
196     bpm->bpatch_color = bezierPatchMake2(umin, vmin, umax, vmax, uorder, vorder, 1, ustride, vstride, ctlpoints);
197     break;
198   case GL_MAP2_COLOR_4:
199     bpm->bpatch_color = bezierPatchMake2(umin, vmin, umax, vmax, uorder, vorder, 4, ustride, vstride, ctlpoints);
200     break;
201   case GL_MAP2_TEXTURE_COORD_1:
202     bpm->bpatch_texcoord = bezierPatchMake2(umin, vmin, umax, vmax, uorder, vorder, 1, ustride, vstride, ctlpoints);
203     break;
204   case GL_MAP2_TEXTURE_COORD_2:
205     bpm->bpatch_texcoord = bezierPatchMake2(umin, vmin, umax, vmax, uorder, vorder, 2, ustride, vstride, ctlpoints);
206     break;    
207   case GL_MAP2_TEXTURE_COORD_3:
208     bpm->bpatch_texcoord = bezierPatchMake2(umin, vmin, umax, vmax, uorder, vorder, 3, ustride, vstride, ctlpoints);
209     break;    
210   case GL_MAP2_TEXTURE_COORD_4:
211     bpm->bpatch_texcoord = bezierPatchMake2(umin, vmin, umax, vmax, uorder, vorder, 4, ustride, vstride, ctlpoints);
212     break;    
213   default:
214     fprintf(stderr, "error in bezierPatchMeshPutPatch, maptype=%i is wrong, maptype,map is invalid\n", maptype);
215   }
216 }
217   
218
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
222  */
223 void bezierPatchMeshDelete(bezierPatchMesh *bpm)
224 {
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);
233   
234   free(bpm->UVarray);
235   free(bpm->length_array);
236   free(bpm->vertex_array);
237   free(bpm->normal_array);
238   free(bpm->type_array);
239   free(bpm);
240 }
241  
242 /*begin a strip
243  *type is the primitive type:
244  */
245 void bezierPatchMeshBeginStrip(bezierPatchMesh *bpm, GLenum type)
246 {
247   bpm->counter = 0;
248   bpm->type = type;
249 }
250
251 /*signal the end of the current strip*/
252 void bezierPatchMeshEndStrip(bezierPatchMesh *bpm)
253 {
254   int i;
255   
256   /*if there are no vertices in this strip, then nothing needs to be done*/
257   if(bpm->counter == 0) return;
258   
259   /*if the length_array is full, it should be expanded*/
260   if(bpm->index_length_array >= bpm->size_length_array)
261     {
262       int *temp = (int*) malloc(sizeof(int) * (bpm->size_length_array*2 + 1));
263       assert(temp);
264       GLenum *temp_type = (GLenum*) malloc(sizeof(GLenum) * (bpm->size_length_array*2 + 1));
265       assert(temp_type);
266       /*update the size*/
267       bpm->size_length_array = bpm->size_length_array*2 + 1;
268       
269       /*copy*/
270       for(i=0; i<bpm->index_length_array; i++)
271         {
272           temp[i] = bpm->length_array[i];
273           temp_type[i] = bpm->type_array[i];
274         }
275       
276       /*deallocate old array*/
277       free(bpm->length_array);
278       free(bpm->type_array);
279       
280       /*point to the new array which is twice as bigger*/
281       bpm->length_array = temp;
282       bpm->type_array = temp_type;
283     }
284   bpm->type_array[bpm->index_length_array] = bpm->type;
285   bpm->length_array[bpm->index_length_array++] = bpm->counter;
286
287 }
288
289 /*insert (u,v) */
290 void bezierPatchMeshInsertUV(bezierPatchMesh *bpm, float u, float v)
291 {
292   int i;
293   /*if the UVarray is full, it should be expanded*/
294   if(bpm->index_UVarray+1 >= bpm->size_UVarray)
295     {
296       float *temp = (float*) malloc(sizeof(float) * (bpm->size_UVarray * 2 + 2));
297       assert(temp);
298       
299       /*update the size*/
300       bpm->size_UVarray = bpm->size_UVarray*2 + 2;
301       
302       /*copy*/
303       for(i=0; i<bpm->index_UVarray; i++)
304         {
305           temp[i] = bpm->UVarray[i];
306         }
307       
308       /*deallocate old array*/
309       free(bpm->UVarray);
310       
311       /*pointing to the new arrays*/
312       bpm->UVarray = temp;
313     }
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++;
319
320   /*update counter: one more vertex*/
321   bpm->counter++;
322
323
324 }
325
326 void bezierPatchMeshPrint(bezierPatchMesh *bpm)
327 {
328   int i;
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]);
338
339   printf("length_array is\n");
340   for(i=0; i<bpm->index_length_array; i++)
341     printf("%i ", bpm->length_array[i]);
342   printf("\n");
343
344 }
345
346 /*insert a new patch in front of the current linked list and return the new list*/
347 bezierPatchMesh* bezierPatchMeshListInsert(bezierPatchMesh* list, bezierPatchMesh* bpm)
348 {
349   bpm->next=list;
350   return bpm;
351 }
352
353 /*print all the patches*/
354 void bezierPatchMeshListPrint(bezierPatchMesh* list)
355 {
356   bezierPatchMesh *temp;
357   for(temp = list; temp != NULL; temp = temp->next)
358     {
359       bezierPatchMeshPrint(temp);
360     }
361 }
362
363 int bezierPatchMeshListTotalStrips(bezierPatchMesh* list)
364 {
365   int sum=0;
366   bezierPatchMesh *temp;
367   for(temp=list; temp != NULL; temp = temp->next)
368     {
369       sum += temp->index_length_array;
370     }
371   return sum;
372 }
373
374 int bezierPatchMeshListTotalVert(bezierPatchMesh* list)
375 {
376   int sum=0;
377   bezierPatchMesh *temp;
378   for(temp=list; temp != NULL; temp = temp->next)
379     {
380       sum += temp->index_UVarray;
381     }
382   return sum/2;
383 }
384
385 int bezierPatchMeshListNumTriangles(bezierPatchMesh* list)
386 {
387   int sum=0;
388   bezierPatchMesh* temp;
389   for(temp=list; temp != NULL; temp = temp->next)
390     {
391       sum +=  bezierPatchMeshNumTriangles(temp);
392     }
393   return sum;
394 }
395
396 int bezierPatchMeshNumTriangles(bezierPatchMesh* bpm)
397 {
398   int i;
399   int sum=0;
400   for(i=0; i<bpm->index_length_array; i++)
401     {
402       switch(bpm->type_array[i])
403         {
404         case GL_TRIANGLES:
405           sum += bpm->length_array[i]/3;
406           break;
407         case GL_TRIANGLE_FAN:
408           if(bpm->length_array[i] > 2)
409             sum += bpm->length_array[i]-2;
410           break;
411         case GL_TRIANGLE_STRIP:
412           if(bpm->length_array[i] > 2)
413             sum += bpm->length_array[i]-2;
414           break;
415         case GL_QUAD_STRIP:
416           if(bpm->length_array[i]>2)
417             sum += (bpm->length_array[i]-2);
418           break;
419         default:
420           fprintf(stderr,"error in bezierPatchMeshListNumTriangles, type invalid\n");
421         }
422     }
423   return sum;
424 }
425
426 /*delete degenerate triangles*/
427 void bezierPatchMeshDelDeg(bezierPatchMesh* bpm)
428 {
429   if(bpm == NULL) return;
430   int i,j,k;
431   int *new_length_array;
432   GLenum *new_type_array;
433   int index_new_length_array;
434   float *new_UVarray;
435   int index_new_UVarray;
436
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);
442   assert(new_UVarray);
443
444   index_new_length_array = 0;
445   index_new_UVarray=0;
446   k=0;
447   for(i=0; i<bpm->index_length_array; i++){
448     
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)))
451           {
452             for(j=0; j<2* bpm->length_array[i]; j++)
453               new_UVarray[index_new_UVarray++] = bpm->UVarray[k++];
454
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++;
458           }
459     else
460       {
461         k += 6;
462       }
463   }  
464   free(bpm->UVarray);
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;
472   
473 }
474
475 /*(u,v) to XYZ
476  *the xyz and normals are stored in vertex_array, 
477  *and normal_array. the spaces of both are allocated here
478  */
479 void bezierPatchMeshEval(bezierPatchMesh* bpm)
480 {
481   int i,j,k,l;
482   float u,v;
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;
493   
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);
498
499   k=0;
500   l=0;
501   for(i=0; i<bpm->index_length_array; i++)
502     {
503       for(j=0; j<bpm->length_array[i]; j++)
504         {
505           u = bpm->UVarray[k];
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);
509           k += 2;
510           l += 3;
511         }
512     }
513 }
514     
515 void bezierPatchMeshListEval(bezierPatchMesh* list)
516 {
517   bezierPatchMesh* temp;
518   for(temp = list; temp != NULL; temp = temp->next)
519     {
520       bezierPatchMeshEval(temp);
521     }
522 }
523
524 void bezierPatchMeshDraw(bezierPatchMesh* bpm)
525 {
526   int i,j,k;
527   k=0;
528   /*k is the index of the first component of the current vertex*/
529   for(i=0; i<bpm->index_length_array; i++)
530     {
531       glBegin(bpm->type_array[i]);
532       for(j=0; j<bpm->length_array[i]; j++)
533         {
534           glNormal3fv(bpm->normal_array+k);
535           glVertex3fv(bpm->vertex_array+k);
536           k+= 3;
537         }
538       glEnd();
539     }
540 }
541
542 void bezierPatchMeshListDraw(bezierPatchMesh* list)
543 {
544   bezierPatchMesh* temp;
545   for(temp = list; temp != NULL; temp = temp->next)
546     {
547       bezierPatchMeshDraw(temp);
548     }
549 }
550
551 void bezierPatchMeshListCollect(bezierPatchMesh* list, float **vertex_array, float **normal_array, int **length_array, GLenum **type_array, int *num_strips)
552 {
553   int i,j,k,l;
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);
560
561   *num_strips = bezierPatchMeshListTotalStrips(list);
562    
563   *length_array = (int*) malloc(sizeof(int) * (*num_strips));
564   assert(*length_array);
565
566   *type_array = (GLenum*) malloc(sizeof(GLenum) * (*num_strips));
567   assert(*type_array);
568   
569   k=0;
570   l=0;
571   for(temp = list; temp != NULL; temp = temp->next)
572     {
573       int x=0;
574       for(i=0; i<temp->index_length_array; i++)
575         {
576           for(j=0; j<temp->length_array[i]; j++)
577             {
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];
581
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];
585
586               x += 3;
587               k += 3;
588             }
589           (*type_array)[l]  = temp->type_array[i];
590           (*length_array)[l++] = temp->length_array[i];
591         }
592     }
593 }
594
595
596
597 static int isDegenerate(float A[2], float B[2], float C[2])
598 {
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])
602      )
603     return 1;
604   else
605     return 0;
606 }
607
608
609
610