1f220fa62Smrg/*
2f220fa62Smrg** License Applicability. Except to the extent portions of this file are
3f220fa62Smrg** made subject to an alternative license as permitted in the SGI Free
4f220fa62Smrg** Software License B, Version 1.1 (the "License"), the contents of this
5f220fa62Smrg** file are subject only to the provisions of the License. You may not use
6f220fa62Smrg** this file except in compliance with the License. You may obtain a copy
7f220fa62Smrg** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
8f220fa62Smrg** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
9f220fa62Smrg**
10f220fa62Smrg** http://oss.sgi.com/projects/FreeB
11f220fa62Smrg**
12f220fa62Smrg** Note that, as provided in the License, the Software is distributed on an
13f220fa62Smrg** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
14f220fa62Smrg** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
15f220fa62Smrg** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
16f220fa62Smrg** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
17f220fa62Smrg**
18f220fa62Smrg** Original Code. The Original Code is: OpenGL Sample Implementation,
19f220fa62Smrg** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
20f220fa62Smrg** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
21f220fa62Smrg** Copyright in any portions created by third parties is as indicated
22f220fa62Smrg** elsewhere herein. All Rights Reserved.
23f220fa62Smrg**
24f220fa62Smrg** Additional Notice Provisions: The application programming interfaces
25f220fa62Smrg** established by SGI in conjunction with the Original Code are The
26f220fa62Smrg** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
27f220fa62Smrg** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
28f220fa62Smrg** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
29f220fa62Smrg** Window System(R) (Version 1.3), released October 19, 1998. This software
30f220fa62Smrg** was created using the OpenGL(R) version 1.2.1 Sample Implementation
31f220fa62Smrg** published by SGI, but has not been independently verified as being
32f220fa62Smrg** compliant with the OpenGL(R) version 1.2.1 Specification.
33f220fa62Smrg**
34f220fa62Smrg*/
35f220fa62Smrg/*
36f220fa62Smrg*/
37f220fa62Smrg
38f220fa62Smrg#include "gluos.h"
39f220fa62Smrg#include <stdlib.h>
40f220fa62Smrg#include <stdio.h>
41f220fa62Smrg#include <assert.h>
42f220fa62Smrg#include <GL/gl.h>
43f220fa62Smrg#include "bezierEval.h"
44f220fa62Smrg#include "bezierPatchMesh.h"
45f220fa62Smrg
46f220fa62Smrgstatic int isDegenerate(float A[2], float B[2], float C[2]);
47f220fa62Smrg
48f220fa62Smrgvoid drawStrips(float *vertex_array, float *normal_array, int *length_array, GLenum *type_array, int num_strips)
49f220fa62Smrg{
50f220fa62Smrg  int i,j,k;
51f220fa62Smrg  k=0;
52f220fa62Smrg  /*k is the index of the first component of the current vertex*/
53f220fa62Smrg  for(i=0; i<num_strips; i++)
54f220fa62Smrg    {
55f220fa62Smrg      glBegin(type_array[i]);
56f220fa62Smrg      for(j=0; j<length_array[i]; j++)
57f220fa62Smrg	{
58f220fa62Smrg	  glNormal3fv(normal_array+k);
59f220fa62Smrg	  glVertex3fv(vertex_array+k);
60f220fa62Smrg	  k += 3;
61f220fa62Smrg	}
62f220fa62Smrg      glEnd();
63f220fa62Smrg    }
64f220fa62Smrg}
65f220fa62Smrg
66f220fa62Smrgvoid bezierPatchMeshListDelDeg(bezierPatchMesh* list)
67f220fa62Smrg{
68f220fa62Smrg  bezierPatchMesh* temp;
69f220fa62Smrg  for(temp=list; temp != NULL; temp = temp->next)
70f220fa62Smrg    {
71f220fa62Smrg      bezierPatchMeshDelDeg(temp);
72f220fa62Smrg    }
73f220fa62Smrg}
74f220fa62Smrg
75f220fa62Smrgvoid bezierPatchMeshListDelete(bezierPatchMesh *list)
76f220fa62Smrg{
77f220fa62Smrg  if(list == NULL) return;
78f220fa62Smrg  bezierPatchMeshListDelete(list->next);
79f220fa62Smrg  bezierPatchMeshDelete(list);
80f220fa62Smrg}
81f220fa62Smrg
82f220fa62Smrg
83f220fa62Smrg
84f220fa62Smrg
85f220fa62SmrgbezierPatchMesh* bezierPatchMeshListReverse(bezierPatchMesh* list)
86f220fa62Smrg{
87f220fa62Smrg bezierPatchMesh* ret=NULL;
88f220fa62Smrg bezierPatchMesh* temp;
89f220fa62Smrg bezierPatchMesh* nextone;
90f220fa62Smrg  for(temp = list; temp != NULL; temp = nextone)
91f220fa62Smrg    {
92f220fa62Smrg      nextone = temp->next;
93f220fa62Smrg      ret=bezierPatchMeshListInsert(ret, temp);
94f220fa62Smrg    }
95f220fa62Smrg return ret;
96f220fa62Smrg}
97f220fa62Smrg
98f220fa62Smrg/*maptype is either GL_MAP2_VERTEX_3 or GL_MAP2_VERTEX_4
99f220fa62Smrg */
100f220fa62SmrgbezierPatchMesh *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)
101f220fa62Smrg{
102f220fa62Smrg  int i,j,k;
103f220fa62Smrg  int dimension;
104f220fa62Smrg  int the_ustride;
105f220fa62Smrg  int the_vstride;
106f220fa62Smrg
107f220fa62Smrg  if(maptype == GL_MAP2_VERTEX_3) dimension = 3;
108f220fa62Smrg  else if (maptype==GL_MAP2_VERTEX_4) dimension = 4;
109f220fa62Smrg  else {
110f220fa62Smrg    fprintf(stderr, "error in inMap2f, maptype=%i is wrong, maptype,map is invalid\n", maptype);
111f220fa62Smrg    return NULL;
112f220fa62Smrg  }
113f220fa62Smrg
114f220fa62Smrg  bezierPatchMesh *ret = (bezierPatchMesh*) malloc(sizeof(bezierPatchMesh));
115f220fa62Smrg  assert(ret);
116f220fa62Smrg
117f220fa62Smrg  ret->bpatch_normal = NULL;
118f220fa62Smrg  ret->bpatch_color  = NULL;
119f220fa62Smrg  ret->bpatch_texcoord = NULL;
120f220fa62Smrg  ret->bpatch = bezierPatchMake(umin, vmin, umax, vmax, uorder, vorder, dimension);
121f220fa62Smrg
122f220fa62Smrg  /*copy the control points there*/
123f220fa62Smrg  the_ustride = vorder * dimension;
124f220fa62Smrg  the_vstride = dimension;
125f220fa62Smrg  for(i=0; i<uorder; i++)
126f220fa62Smrg    for(j=0; j<vorder; j++)
127f220fa62Smrg      for(k=0; k<dimension; k++)
128f220fa62Smrg	ret->bpatch->ctlpoints[i * the_ustride + j*the_vstride+k] = ctlpoints[i*ustride+j*vstride+k];
129f220fa62Smrg
130f220fa62Smrg
131f220fa62Smrg  ret->size_UVarray = size_UVarray;
132f220fa62Smrg  ret->size_length_array = size_length_array;
133f220fa62Smrg  ret->UVarray = (float*) malloc(sizeof(float) * size_UVarray);
134f220fa62Smrg  assert(ret->UVarray);
135f220fa62Smrg  ret->length_array = (int *)malloc(sizeof(int) * size_length_array);
136f220fa62Smrg  assert(ret->length_array);
137f220fa62Smrg  ret->type_array = (GLenum *)malloc(sizeof(GLenum) * size_length_array);
138f220fa62Smrg  assert(ret->type_array);
139f220fa62Smrg
140f220fa62Smrg  ret->index_UVarray = 0;
141f220fa62Smrg  ret->index_length_array = 0;
142f220fa62Smrg
143f220fa62Smrg  ret->vertex_array = NULL;
144f220fa62Smrg  ret->normal_array = NULL;
145f220fa62Smrg  ret->color_array  = NULL;
146f220fa62Smrg  ret->texcoord_array = NULL;
147f220fa62Smrg
148f220fa62Smrg  ret->next = NULL;
149f220fa62Smrg  return ret;
150f220fa62Smrg}
151f220fa62Smrg
152f220fa62SmrgbezierPatchMesh *bezierPatchMeshMake2(int size_UVarray, int size_length_array)
153f220fa62Smrg{
154f220fa62Smrg  bezierPatchMesh *ret = (bezierPatchMesh*) malloc(sizeof(bezierPatchMesh));
155f220fa62Smrg  assert(ret);
156f220fa62Smrg
157f220fa62Smrg  ret->bpatch = NULL;
158f220fa62Smrg  ret->bpatch_normal = NULL;
159f220fa62Smrg  ret->bpatch_color  = NULL;
160f220fa62Smrg  ret->bpatch_texcoord = NULL;
161f220fa62Smrg
162f220fa62Smrg  ret->size_UVarray = size_UVarray;
163f220fa62Smrg  ret->size_length_array = size_length_array;
164f220fa62Smrg  ret->UVarray = (float*) malloc(sizeof(float) * size_UVarray);
165f220fa62Smrg  assert(ret->UVarray);
166f220fa62Smrg  ret->length_array = (int *)malloc(sizeof(int) * size_length_array);
167f220fa62Smrg  assert(ret->length_array);
168f220fa62Smrg  ret->type_array = (GLenum *)malloc(sizeof(GLenum) * size_length_array);
169f220fa62Smrg  assert(ret->type_array);
170f220fa62Smrg
171f220fa62Smrg  ret->index_UVarray = 0;
172f220fa62Smrg  ret->index_length_array = 0;
173f220fa62Smrg
174f220fa62Smrg  ret->vertex_array = NULL;
175f220fa62Smrg  ret->normal_array = NULL;
176f220fa62Smrg  ret->color_array  = NULL;
177f220fa62Smrg  ret->texcoord_array = NULL;
178f220fa62Smrg
179f220fa62Smrg  ret->next = NULL;
180f220fa62Smrg  return ret;
181f220fa62Smrg}
182f220fa62Smrg
183f220fa62Smrgvoid bezierPatchMeshPutPatch(bezierPatchMesh *bpm, int maptype, float umin, float umax, int ustride, int uorder, float vmin, float vmax, int vstride, int vorder, float *ctlpoints)
184f220fa62Smrg{
185f220fa62Smrg  switch(maptype){
186f220fa62Smrg  case GL_MAP2_VERTEX_3:
187f220fa62Smrg    bpm->bpatch = bezierPatchMake2(umin, vmin, umax, vmax, uorder, vorder, 3, ustride, vstride, ctlpoints);
188f220fa62Smrg    break;
189f220fa62Smrg  case GL_MAP2_VERTEX_4:
190f220fa62Smrg    bpm->bpatch = bezierPatchMake2(umin, vmin, umax, vmax, uorder, vorder, 4,ustride, vstride, ctlpoints );
191f220fa62Smrg    break;
192f220fa62Smrg  case GL_MAP2_NORMAL:
193f220fa62Smrg    bpm->bpatch_normal = bezierPatchMake2(umin, vmin, umax, vmax, uorder, vorder, 3, ustride, vstride, ctlpoints);
194f220fa62Smrg    break;
195f220fa62Smrg  case GL_MAP2_INDEX:
196f220fa62Smrg    bpm->bpatch_color = bezierPatchMake2(umin, vmin, umax, vmax, uorder, vorder, 1, ustride, vstride, ctlpoints);
197f220fa62Smrg    break;
198f220fa62Smrg  case GL_MAP2_COLOR_4:
199f220fa62Smrg    bpm->bpatch_color = bezierPatchMake2(umin, vmin, umax, vmax, uorder, vorder, 4, ustride, vstride, ctlpoints);
200f220fa62Smrg    break;
201f220fa62Smrg  case GL_MAP2_TEXTURE_COORD_1:
202f220fa62Smrg    bpm->bpatch_texcoord = bezierPatchMake2(umin, vmin, umax, vmax, uorder, vorder, 1, ustride, vstride, ctlpoints);
203f220fa62Smrg    break;
204f220fa62Smrg  case GL_MAP2_TEXTURE_COORD_2:
205f220fa62Smrg    bpm->bpatch_texcoord = bezierPatchMake2(umin, vmin, umax, vmax, uorder, vorder, 2, ustride, vstride, ctlpoints);
206f220fa62Smrg    break;
207f220fa62Smrg  case GL_MAP2_TEXTURE_COORD_3:
208f220fa62Smrg    bpm->bpatch_texcoord = bezierPatchMake2(umin, vmin, umax, vmax, uorder, vorder, 3, ustride, vstride, ctlpoints);
209f220fa62Smrg    break;
210f220fa62Smrg  case GL_MAP2_TEXTURE_COORD_4:
211f220fa62Smrg    bpm->bpatch_texcoord = bezierPatchMake2(umin, vmin, umax, vmax, uorder, vorder, 4, ustride, vstride, ctlpoints);
212f220fa62Smrg    break;
213f220fa62Smrg  default:
214f220fa62Smrg    fprintf(stderr, "error in bezierPatchMeshPutPatch, maptype=%i is wrong, maptype,map is invalid\n", maptype);
215f220fa62Smrg  }
216f220fa62Smrg}
217f220fa62Smrg
218f220fa62Smrg
219f220fa62Smrg/*delete everything including the arrays. So if you want to output the
220f220fa62Smrg *pointers of the arrays, you should not use this function to deallocate space.
221f220fa62Smrg *you should dealocate manually
222f220fa62Smrg */
223f220fa62Smrgvoid bezierPatchMeshDelete(bezierPatchMesh *bpm)
224f220fa62Smrg{
225f220fa62Smrg  if(bpm->bpatch != NULL)
226f220fa62Smrg    bezierPatchDelete(bpm->bpatch);
227f220fa62Smrg  if(bpm->bpatch_normal != NULL)
228f220fa62Smrg    bezierPatchDelete(bpm->bpatch_normal);
229f220fa62Smrg  if(bpm->bpatch_color != NULL)
230f220fa62Smrg    bezierPatchDelete(bpm->bpatch_color);
231f220fa62Smrg  if(bpm->bpatch_texcoord != NULL)
232f220fa62Smrg    bezierPatchDelete(bpm->bpatch_texcoord);
233f220fa62Smrg
234f220fa62Smrg  free(bpm->UVarray);
235f220fa62Smrg  free(bpm->length_array);
236f220fa62Smrg  free(bpm->vertex_array);
237f220fa62Smrg  free(bpm->normal_array);
238f220fa62Smrg  free(bpm->type_array);
239f220fa62Smrg  free(bpm);
240f220fa62Smrg}
241f220fa62Smrg
242f220fa62Smrg/*begin a strip
243f220fa62Smrg *type is the primitive type:
244f220fa62Smrg */
245f220fa62Smrgvoid bezierPatchMeshBeginStrip(bezierPatchMesh *bpm, GLenum type)
246f220fa62Smrg{
247f220fa62Smrg  bpm->counter = 0;
248f220fa62Smrg  bpm->type = type;
249f220fa62Smrg}
250f220fa62Smrg
251f220fa62Smrg/*signal the end of the current strip*/
252f220fa62Smrgvoid bezierPatchMeshEndStrip(bezierPatchMesh *bpm)
253f220fa62Smrg{
254f220fa62Smrg  int i;
255f220fa62Smrg
256f220fa62Smrg  /*if there are no vertices in this strip, then nothing needs to be done*/
257f220fa62Smrg  if(bpm->counter == 0) return;
258f220fa62Smrg
259f220fa62Smrg  /*if the length_array is full, it should be expanded*/
260f220fa62Smrg  if(bpm->index_length_array >= bpm->size_length_array)
261f220fa62Smrg    {
262f220fa62Smrg      int *temp = (int*) malloc(sizeof(int) * (bpm->size_length_array*2 + 1));
263f220fa62Smrg      assert(temp);
264f220fa62Smrg      GLenum *temp_type = (GLenum*) malloc(sizeof(GLenum) * (bpm->size_length_array*2 + 1));
265f220fa62Smrg      assert(temp_type);
266f220fa62Smrg      /*update the size*/
267f220fa62Smrg      bpm->size_length_array = bpm->size_length_array*2 + 1;
268f220fa62Smrg
269f220fa62Smrg      /*copy*/
270f220fa62Smrg      for(i=0; i<bpm->index_length_array; i++)
271f220fa62Smrg	{
272f220fa62Smrg	  temp[i] = bpm->length_array[i];
273f220fa62Smrg	  temp_type[i] = bpm->type_array[i];
274f220fa62Smrg	}
275f220fa62Smrg
276f220fa62Smrg      /*deallocate old array*/
277f220fa62Smrg      free(bpm->length_array);
278f220fa62Smrg      free(bpm->type_array);
279f220fa62Smrg
280f220fa62Smrg      /*point to the new array which is twice as bigger*/
281f220fa62Smrg      bpm->length_array = temp;
282f220fa62Smrg      bpm->type_array = temp_type;
283f220fa62Smrg    }
284f220fa62Smrg  bpm->type_array[bpm->index_length_array] = bpm->type;
285f220fa62Smrg  bpm->length_array[bpm->index_length_array++] = bpm->counter;
286f220fa62Smrg
287f220fa62Smrg}
288f220fa62Smrg
289f220fa62Smrg/*insert (u,v) */
290f220fa62Smrgvoid bezierPatchMeshInsertUV(bezierPatchMesh *bpm, float u, float v)
291f220fa62Smrg{
292f220fa62Smrg  int i;
293f220fa62Smrg  /*if the UVarray is full, it should be expanded*/
294f220fa62Smrg  if(bpm->index_UVarray+1 >= bpm->size_UVarray)
295f220fa62Smrg    {
296f220fa62Smrg      float *temp = (float*) malloc(sizeof(float) * (bpm->size_UVarray * 2 + 2));
297f220fa62Smrg      assert(temp);
298f220fa62Smrg
299f220fa62Smrg      /*update the size*/
300f220fa62Smrg      bpm->size_UVarray = bpm->size_UVarray*2 + 2;
301f220fa62Smrg
302f220fa62Smrg      /*copy*/
303f220fa62Smrg      for(i=0; i<bpm->index_UVarray; i++)
304f220fa62Smrg	{
305f220fa62Smrg	  temp[i] = bpm->UVarray[i];
306f220fa62Smrg	}
307f220fa62Smrg
308f220fa62Smrg      /*deallocate old array*/
309f220fa62Smrg      free(bpm->UVarray);
310f220fa62Smrg
311f220fa62Smrg      /*pointing to the new arrays*/
312f220fa62Smrg      bpm->UVarray = temp;
313f220fa62Smrg    }
314f220fa62Smrg  /*insert the new UV*/
315f220fa62Smrg  bpm->UVarray[bpm->index_UVarray] = u;
316f220fa62Smrg  bpm->index_UVarray++;
317f220fa62Smrg  bpm->UVarray[bpm->index_UVarray] = v;
318f220fa62Smrg  bpm->index_UVarray++;
319f220fa62Smrg
320f220fa62Smrg  /*update counter: one more vertex*/
321f220fa62Smrg  bpm->counter++;
322f220fa62Smrg
323f220fa62Smrg
324f220fa62Smrg}
325f220fa62Smrg
326f220fa62Smrgvoid bezierPatchMeshPrint(bezierPatchMesh *bpm)
327f220fa62Smrg{
328f220fa62Smrg  int i;
329f220fa62Smrg  printf("the bezier patch is\n");
330f220fa62Smrg  bezierPatchPrint(bpm->bpatch);
331f220fa62Smrg  printf("index_length_array= %i\n", bpm->index_length_array);
332f220fa62Smrg  printf("size_length_array =%i\n", bpm->size_length_array);
333f220fa62Smrg  printf("index_UVarray =%i\n", bpm->index_UVarray);
334f220fa62Smrg  printf("size_UVarray =%i\n", bpm->size_UVarray);
335f220fa62Smrg  printf("UVarray is\n");
336f220fa62Smrg  for(i=0; i<bpm->index_UVarray; i++)
337f220fa62Smrg    printf("%f ", bpm->UVarray[i]);
338f220fa62Smrg
339f220fa62Smrg  printf("length_array is\n");
340f220fa62Smrg  for(i=0; i<bpm->index_length_array; i++)
341f220fa62Smrg    printf("%i ", bpm->length_array[i]);
342f220fa62Smrg  printf("\n");
343f220fa62Smrg
344f220fa62Smrg}
345f220fa62Smrg
346f220fa62Smrg/*insert a new patch in front of the current linked list and return the new list*/
347f220fa62SmrgbezierPatchMesh* bezierPatchMeshListInsert(bezierPatchMesh* list, bezierPatchMesh* bpm)
348f220fa62Smrg{
349f220fa62Smrg  bpm->next=list;
350f220fa62Smrg  return bpm;
351f220fa62Smrg}
352f220fa62Smrg
353f220fa62Smrg/*print all the patches*/
354f220fa62Smrgvoid bezierPatchMeshListPrint(bezierPatchMesh* list)
355f220fa62Smrg{
356f220fa62Smrg  bezierPatchMesh *temp;
357f220fa62Smrg  for(temp = list; temp != NULL; temp = temp->next)
358f220fa62Smrg    {
359f220fa62Smrg      bezierPatchMeshPrint(temp);
360f220fa62Smrg    }
361f220fa62Smrg}
362f220fa62Smrg
363f220fa62Smrgint bezierPatchMeshListTotalStrips(bezierPatchMesh* list)
364f220fa62Smrg{
365f220fa62Smrg  int sum=0;
366f220fa62Smrg  bezierPatchMesh *temp;
367f220fa62Smrg  for(temp=list; temp != NULL; temp = temp->next)
368f220fa62Smrg    {
369f220fa62Smrg      sum += temp->index_length_array;
370f220fa62Smrg    }
371f220fa62Smrg  return sum;
372f220fa62Smrg}
373f220fa62Smrg
374f220fa62Smrgint bezierPatchMeshListTotalVert(bezierPatchMesh* list)
375f220fa62Smrg{
376f220fa62Smrg  int sum=0;
377f220fa62Smrg  bezierPatchMesh *temp;
378f220fa62Smrg  for(temp=list; temp != NULL; temp = temp->next)
379f220fa62Smrg    {
380f220fa62Smrg      sum += temp->index_UVarray;
381f220fa62Smrg    }
382f220fa62Smrg  return sum/2;
383f220fa62Smrg}
384f220fa62Smrg
385f220fa62Smrgint bezierPatchMeshListNumTriangles(bezierPatchMesh* list)
386f220fa62Smrg{
387f220fa62Smrg  int sum=0;
388f220fa62Smrg  bezierPatchMesh* temp;
389f220fa62Smrg  for(temp=list; temp != NULL; temp = temp->next)
390f220fa62Smrg    {
391f220fa62Smrg      sum +=  bezierPatchMeshNumTriangles(temp);
392f220fa62Smrg    }
393f220fa62Smrg  return sum;
394f220fa62Smrg}
395f220fa62Smrg
396f220fa62Smrgint bezierPatchMeshNumTriangles(bezierPatchMesh* bpm)
397f220fa62Smrg{
398f220fa62Smrg  int i;
399f220fa62Smrg  int sum=0;
400f220fa62Smrg  for(i=0; i<bpm->index_length_array; i++)
401f220fa62Smrg    {
402f220fa62Smrg      switch(bpm->type_array[i])
403f220fa62Smrg	{
404f220fa62Smrg	case GL_TRIANGLES:
405f220fa62Smrg	  sum += bpm->length_array[i]/3;
406f220fa62Smrg	  break;
407f220fa62Smrg	case GL_TRIANGLE_FAN:
408f220fa62Smrg	  if(bpm->length_array[i] > 2)
409f220fa62Smrg	    sum += bpm->length_array[i]-2;
410f220fa62Smrg	  break;
411f220fa62Smrg	case GL_TRIANGLE_STRIP:
412f220fa62Smrg	  if(bpm->length_array[i] > 2)
413f220fa62Smrg	    sum += bpm->length_array[i]-2;
414f220fa62Smrg	  break;
415f220fa62Smrg	case GL_QUAD_STRIP:
416f220fa62Smrg	  if(bpm->length_array[i]>2)
417f220fa62Smrg	    sum += (bpm->length_array[i]-2);
418f220fa62Smrg	  break;
419f220fa62Smrg	default:
420f220fa62Smrg	  fprintf(stderr,"error in bezierPatchMeshListNumTriangles, type invalid\n");
421f220fa62Smrg	}
422f220fa62Smrg    }
423f220fa62Smrg  return sum;
424f220fa62Smrg}
425f220fa62Smrg
426f220fa62Smrg/*delete degenerate triangles*/
427f220fa62Smrgvoid bezierPatchMeshDelDeg(bezierPatchMesh* bpm)
428f220fa62Smrg{
429f220fa62Smrg  if(bpm == NULL) return;
430f220fa62Smrg  int i,j,k;
431f220fa62Smrg  int *new_length_array;
432f220fa62Smrg  GLenum *new_type_array;
433f220fa62Smrg  int index_new_length_array;
434f220fa62Smrg  float *new_UVarray;
435f220fa62Smrg  int index_new_UVarray;
436f220fa62Smrg
437f220fa62Smrg  new_length_array = (int*)malloc(sizeof(int) * bpm->index_length_array);
438f220fa62Smrg  assert(new_length_array);
439f220fa62Smrg  new_type_array = (GLenum*)malloc(sizeof(GLenum) * bpm->index_length_array);
440f220fa62Smrg  assert(new_length_array);
441f220fa62Smrg  new_UVarray = (float*) malloc(sizeof(float) * bpm->index_UVarray);
442f220fa62Smrg  assert(new_UVarray);
443f220fa62Smrg
444f220fa62Smrg  index_new_length_array = 0;
445f220fa62Smrg  index_new_UVarray=0;
446f220fa62Smrg  k=0;
447f220fa62Smrg  for(i=0; i<bpm->index_length_array; i++){
448f220fa62Smrg
449f220fa62Smrg    /*(if not degenerate, we have to copy*/
450f220fa62Smrg    if( (bpm->length_array[i] != 3) || (!isDegenerate(bpm->UVarray+k, bpm->UVarray+k+2, bpm->UVarray+k+4)))
451f220fa62Smrg	  {
452f220fa62Smrg	    for(j=0; j<2* bpm->length_array[i]; j++)
453f220fa62Smrg	      new_UVarray[index_new_UVarray++] = bpm->UVarray[k++];
454f220fa62Smrg
455f220fa62Smrg	    new_length_array[index_new_length_array] = bpm->length_array[i];
456f220fa62Smrg	    new_type_array[index_new_length_array] = bpm->type_array[i];
457f220fa62Smrg	    index_new_length_array++;
458f220fa62Smrg	  }
459f220fa62Smrg    else
460f220fa62Smrg      {
461f220fa62Smrg	k += 6;
462f220fa62Smrg      }
463f220fa62Smrg  }
464f220fa62Smrg  free(bpm->UVarray);
465f220fa62Smrg  free(bpm->length_array);
466f220fa62Smrg  free(bpm->type_array);
467f220fa62Smrg  bpm->UVarray=new_UVarray;
468f220fa62Smrg  bpm->length_array=new_length_array;
469f220fa62Smrg  bpm->type_array=new_type_array;
470f220fa62Smrg  bpm->index_UVarray = index_new_UVarray;
471f220fa62Smrg  bpm->index_length_array = index_new_length_array;
472f220fa62Smrg
473f220fa62Smrg}
474f220fa62Smrg
475f220fa62Smrg/*(u,v) to XYZ
476f220fa62Smrg *the xyz and normals are stored in vertex_array,
477f220fa62Smrg *and normal_array. the spaces of both are allocated here
478f220fa62Smrg */
479f220fa62Smrgvoid bezierPatchMeshEval(bezierPatchMesh* bpm)
480f220fa62Smrg{
481f220fa62Smrg  int i,j,k,l;
482f220fa62Smrg  float u,v;
483f220fa62Smrg  float u0 = bpm->bpatch->umin;
484f220fa62Smrg  float u1 = bpm->bpatch->umax;
485f220fa62Smrg  int uorder = bpm->bpatch->uorder;
486f220fa62Smrg  float v0 = bpm->bpatch->vmin;
487f220fa62Smrg  float v1 = bpm->bpatch->vmax;
488f220fa62Smrg  int vorder = bpm->bpatch->vorder;
489f220fa62Smrg  int dimension = bpm->bpatch->dimension;
490f220fa62Smrg  int ustride = dimension * vorder;
491f220fa62Smrg  int vstride = dimension;
492f220fa62Smrg  float *ctlpoints = bpm->bpatch->ctlpoints;
493f220fa62Smrg
494f220fa62Smrg  bpm->vertex_array = (float*) malloc(sizeof(float)* (bpm->index_UVarray/2) * 3);
495f220fa62Smrg  assert(bpm->vertex_array);
496f220fa62Smrg  bpm->normal_array = (float*) malloc(sizeof(float)* (bpm->index_UVarray/2) * 3);
497f220fa62Smrg  assert(bpm->normal_array);
498f220fa62Smrg
499f220fa62Smrg  k=0;
500f220fa62Smrg  l=0;
501f220fa62Smrg  for(i=0; i<bpm->index_length_array; i++)
502f220fa62Smrg    {
503f220fa62Smrg      for(j=0; j<bpm->length_array[i]; j++)
504f220fa62Smrg	{
505f220fa62Smrg	  u = bpm->UVarray[k];
506f220fa62Smrg	  v = bpm->UVarray[k+1];
507f220fa62Smrg	  bezierSurfEval(u0,u1,uorder, v0, v1, vorder, dimension, ctlpoints, ustride, vstride, u,v, bpm->vertex_array+l);
508f220fa62Smrg	  bezierSurfEvalNormal(u0,u1,uorder, v0, v1, vorder, dimension, ctlpoints, ustride, vstride, u,v, bpm->normal_array+l);
509f220fa62Smrg	  k += 2;
510f220fa62Smrg	  l += 3;
511f220fa62Smrg	}
512f220fa62Smrg    }
513f220fa62Smrg}
514f220fa62Smrg
515f220fa62Smrgvoid bezierPatchMeshListEval(bezierPatchMesh* list)
516f220fa62Smrg{
517f220fa62Smrg  bezierPatchMesh* temp;
518f220fa62Smrg  for(temp = list; temp != NULL; temp = temp->next)
519f220fa62Smrg    {
520f220fa62Smrg      bezierPatchMeshEval(temp);
521f220fa62Smrg    }
522f220fa62Smrg}
523f220fa62Smrg
524f220fa62Smrgvoid bezierPatchMeshDraw(bezierPatchMesh* bpm)
525f220fa62Smrg{
526f220fa62Smrg  int i,j,k;
527f220fa62Smrg  k=0;
528f220fa62Smrg  /*k is the index of the first component of the current vertex*/
529f220fa62Smrg  for(i=0; i<bpm->index_length_array; i++)
530f220fa62Smrg    {
531f220fa62Smrg      glBegin(bpm->type_array[i]);
532f220fa62Smrg      for(j=0; j<bpm->length_array[i]; j++)
533f220fa62Smrg	{
534f220fa62Smrg	  glNormal3fv(bpm->normal_array+k);
535f220fa62Smrg	  glVertex3fv(bpm->vertex_array+k);
536f220fa62Smrg	  k+= 3;
537f220fa62Smrg	}
538f220fa62Smrg      glEnd();
539f220fa62Smrg    }
540f220fa62Smrg}
541f220fa62Smrg
542f220fa62Smrgvoid bezierPatchMeshListDraw(bezierPatchMesh* list)
543f220fa62Smrg{
544f220fa62Smrg  bezierPatchMesh* temp;
545f220fa62Smrg  for(temp = list; temp != NULL; temp = temp->next)
546f220fa62Smrg    {
547f220fa62Smrg      bezierPatchMeshDraw(temp);
548f220fa62Smrg    }
549f220fa62Smrg}
550f220fa62Smrg
551f220fa62Smrgvoid bezierPatchMeshListCollect(bezierPatchMesh* list, float **vertex_array, float **normal_array, int **length_array, GLenum **type_array, int *num_strips)
552f220fa62Smrg{
553f220fa62Smrg  int i,j,k,l;
554f220fa62Smrg  bezierPatchMesh *temp;
555f220fa62Smrg  int total_num_vertices = bezierPatchMeshListTotalVert(list);
556f220fa62Smrg  (*vertex_array) = (float *) malloc(sizeof(float) * total_num_vertices*3);
557f220fa62Smrg  assert(*vertex_array);
558f220fa62Smrg  (*normal_array) = (float *) malloc(sizeof(float) * total_num_vertices*3);
559f220fa62Smrg  assert(*normal_array);
560f220fa62Smrg
561f220fa62Smrg  *num_strips = bezierPatchMeshListTotalStrips(list);
562f220fa62Smrg
563f220fa62Smrg  *length_array = (int*) malloc(sizeof(int) * (*num_strips));
564f220fa62Smrg  assert(*length_array);
565f220fa62Smrg
566f220fa62Smrg  *type_array = (GLenum*) malloc(sizeof(GLenum) * (*num_strips));
567f220fa62Smrg  assert(*type_array);
568f220fa62Smrg
569f220fa62Smrg  k=0;
570f220fa62Smrg  l=0;
571f220fa62Smrg  for(temp = list; temp != NULL; temp = temp->next)
572f220fa62Smrg    {
573f220fa62Smrg      int x=0;
574f220fa62Smrg      for(i=0; i<temp->index_length_array; i++)
575f220fa62Smrg	{
576f220fa62Smrg	  for(j=0; j<temp->length_array[i]; j++)
577f220fa62Smrg	    {
578f220fa62Smrg	      (*vertex_array)[k] = temp->vertex_array[x];
579f220fa62Smrg	      (*vertex_array)[k+1] = temp->vertex_array[x+1];
580f220fa62Smrg	      (*vertex_array)[k+2] = temp->vertex_array[x+2];
581f220fa62Smrg
582f220fa62Smrg	      (*normal_array)[k] = temp->normal_array[x];
583f220fa62Smrg	      (*normal_array)[k+1] = temp->normal_array[x+1];
584f220fa62Smrg	      (*normal_array)[k+2] = temp->normal_array[x+2];
585f220fa62Smrg
586f220fa62Smrg	      x += 3;
587f220fa62Smrg	      k += 3;
588f220fa62Smrg	    }
589f220fa62Smrg	  (*type_array)[l]  = temp->type_array[i];
590f220fa62Smrg	  (*length_array)[l++] = temp->length_array[i];
591f220fa62Smrg	}
592f220fa62Smrg    }
593f220fa62Smrg}
594f220fa62Smrg
595f220fa62Smrg
596f220fa62Smrg
597f220fa62Smrgstatic int isDegenerate(float A[2], float B[2], float C[2])
598f220fa62Smrg{
599f220fa62Smrg  if( (A[0] == B[0] && A[1]==B[1]) ||
600f220fa62Smrg      (A[0] == C[0] && A[1]==C[1]) ||
601f220fa62Smrg      (B[0] == C[0] && B[1]==C[1])
602f220fa62Smrg     )
603f220fa62Smrg    return 1;
604f220fa62Smrg  else
605f220fa62Smrg    return 0;
606f220fa62Smrg}
607f220fa62Smrg
608f220fa62Smrg
609f220fa62Smrg
610f220fa62Smrg
611