FreeWRL/FreeX3D  3.0.0
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 <libnurbs2.h>
43 //#include <GL/gl.h>
44 #include "bezierEval.h"
45 #include "bezierPatchMesh.h"
46 
47 static int isDegenerate(float A[2], float B[2], float C[2]);
48 
49 void drawStrips(float *vertex_array, float *normal_array, int *length_array, GLenum *type_array, int num_strips)
50 {
51  int i,j,k;
52  k=0;
53 #ifdef HAVE_GL_H
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 #endif
67 }
68 
69 void bezierPatchMeshListDelDeg(bezierPatchMesh* list)
70 {
71  bezierPatchMesh* temp;
72  for(temp=list; temp != NULL; temp = temp->next)
73  {
74  bezierPatchMeshDelDeg(temp);
75  }
76 }
77 
78 void bezierPatchMeshListDelete(bezierPatchMesh *list)
79 {
80  if(list == NULL) return;
81  bezierPatchMeshListDelete(list->next);
82  bezierPatchMeshDelete(list);
83 }
84 
85 
86 
87 
88 bezierPatchMesh* bezierPatchMeshListReverse(bezierPatchMesh* list)
89 {
90  bezierPatchMesh* ret=NULL;
91  bezierPatchMesh* temp;
92  bezierPatchMesh* nextone;
93  for(temp = list; temp != NULL; temp = nextone)
94  {
95  nextone = temp->next;
96  ret=bezierPatchMeshListInsert(ret, temp);
97  }
98  return ret;
99 }
100 
101 /*maptype is either GL_MAP2_VERTEX_3 or GL_MAP2_VERTEX_4
102  */
103 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)
104 {
105  int i,j,k;
106  int dimension;
107  int the_ustride;
108  int the_vstride;
109 
110  if(maptype == GL_MAP2_VERTEX_3) dimension = 3;
111  else if (maptype==GL_MAP2_VERTEX_4) dimension = 4;
112  else {
113  fprintf(stderr, "error in inMap2f, maptype=%i is wrong, maptype,map is invalid\n", maptype);
114  return NULL;
115  }
116 
117  bezierPatchMesh *ret = (bezierPatchMesh*) malloc(sizeof(bezierPatchMesh));
118  assert(ret);
119 
120  ret->bpatch_normal = NULL;
121  ret->bpatch_color = NULL;
122  ret->bpatch_texcoord = NULL;
123  ret->bpatch = bezierPatchMake(umin, vmin, umax, vmax, uorder, vorder, dimension);
124 
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  #ifdef HAVE_GL_H
532  /*k is the index of the first component of the current vertex*/
533  for(i=0; i<bpm->index_length_array; i++)
534  {
535  glBegin(bpm->type_array[i]);
536  for(j=0; j<bpm->length_array[i]; j++)
537  {
538  glNormal3fv(bpm->normal_array+k);
539  glVertex3fv(bpm->vertex_array+k);
540  k+= 3;
541  }
542  glEnd();
543  }
544 #endif
545 }
546 
547 void bezierPatchMeshListDraw(bezierPatchMesh* list)
548 {
549  bezierPatchMesh* temp;
550  for(temp = list; temp != NULL; temp = temp->next)
551  {
552  bezierPatchMeshDraw(temp);
553  }
554 }
555 
556 void bezierPatchMeshListCollect(bezierPatchMesh* list, float **vertex_array, float **normal_array, int **length_array, GLenum **type_array, int *num_strips)
557 {
558  int i,j,k,l;
559  bezierPatchMesh *temp;
560  int total_num_vertices = bezierPatchMeshListTotalVert(list);
561  (*vertex_array) = (float *) malloc(sizeof(float) * total_num_vertices*3);
562  assert(*vertex_array);
563  (*normal_array) = (float *) malloc(sizeof(float) * total_num_vertices*3);
564  assert(*normal_array);
565 
566  *num_strips = bezierPatchMeshListTotalStrips(list);
567 
568  *length_array = (int*) malloc(sizeof(int) * (*num_strips));
569  assert(*length_array);
570 
571  *type_array = (GLenum*) malloc(sizeof(GLenum) * (*num_strips));
572  assert(*type_array);
573 
574  k=0;
575  l=0;
576  for(temp = list; temp != NULL; temp = temp->next)
577  {
578  int x=0;
579  for(i=0; i<temp->index_length_array; i++)
580  {
581  for(j=0; j<temp->length_array[i]; j++)
582  {
583  (*vertex_array)[k] = temp->vertex_array[x];
584  (*vertex_array)[k+1] = temp->vertex_array[x+1];
585  (*vertex_array)[k+2] = temp->vertex_array[x+2];
586 
587  (*normal_array)[k] = temp->normal_array[x];
588  (*normal_array)[k+1] = temp->normal_array[x+1];
589  (*normal_array)[k+2] = temp->normal_array[x+2];
590 
591  x += 3;
592  k += 3;
593  }
594  (*type_array)[l] = temp->type_array[i];
595  (*length_array)[l++] = temp->length_array[i];
596  }
597  }
598 }
599 
600 
601 
602 static int isDegenerate(float A[2], float B[2], float C[2])
603 {
604  if( (A[0] == B[0] && A[1]==B[1]) ||
605  (A[0] == C[0] && A[1]==C[1]) ||
606  (B[0] == C[0] && B[1]==C[1])
607  )
608  return 1;
609  else
610  return 0;
611 }
612 
613 
614 
615