bezierPatchMesh.cc [plain text]
#include "gluos.h"
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <GL/gl.h>
#include "bezierEval.h"
#include "bezierPatchMesh.h"
static int isDegenerate(float A[2], float B[2], float C[2]);
void drawStrips(float *vertex_array, float *normal_array, int *length_array, GLenum *type_array, int num_strips)
{
int i,j,k;
k=0;
for(i=0; i<num_strips; i++)
{
glBegin(type_array[i]);
for(j=0; j<length_array[i]; j++)
{
glNormal3fv(normal_array+k);
glVertex3fv(vertex_array+k);
k += 3;
}
glEnd();
}
}
void bezierPatchMeshListDelDeg(bezierPatchMesh* list)
{
bezierPatchMesh* temp;
for(temp=list; temp != NULL; temp = temp->next)
{
bezierPatchMeshDelDeg(temp);
}
}
void bezierPatchMeshListDelete(bezierPatchMesh *list)
{
if(list == NULL) return;
bezierPatchMeshListDelete(list->next);
bezierPatchMeshDelete(list);
}
bezierPatchMesh* bezierPatchMeshListReverse(bezierPatchMesh* list)
{
bezierPatchMesh* ret=NULL;
bezierPatchMesh* temp;
bezierPatchMesh* nextone;
for(temp = list; temp != NULL; temp = nextone)
{
nextone = temp->next;
ret=bezierPatchMeshListInsert(ret, temp);
}
return ret;
}
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)
{
int i,j,k;
int dimension;
int the_ustride;
int the_vstride;
bezierPatchMesh *ret = (bezierPatchMesh*) malloc(sizeof(bezierPatchMesh));
assert(ret);
ret->bpatch = NULL;
ret->bpatch_normal = NULL;
ret->bpatch_color = NULL;
ret->bpatch_texcoord = NULL;
if(maptype == GL_MAP2_VERTEX_3) dimension = 3;
else if (maptype==GL_MAP2_VERTEX_4) dimension = 4;
else {
fprintf(stderr, "error in inMap2f, maptype=%i is wrong, maptype,map is invalid\n", maptype);
return NULL;
}
ret->bpatch = bezierPatchMake(umin, vmin, umax, vmax, uorder, vorder, dimension);
the_ustride = vorder * dimension;
the_vstride = dimension;
for(i=0; i<uorder; i++)
for(j=0; j<vorder; j++)
for(k=0; k<dimension; k++)
ret->bpatch->ctlpoints[i * the_ustride + j*the_vstride+k] = ctlpoints[i*ustride+j*vstride+k];
ret->size_UVarray = size_UVarray;
ret->size_length_array = size_length_array;
ret->UVarray = (float*) malloc(sizeof(float) * size_UVarray);
assert(ret->UVarray);
ret->length_array = (int *)malloc(sizeof(int) * size_length_array);
assert(ret->length_array);
ret->type_array = (GLenum *)malloc(sizeof(GLenum) * size_length_array);
assert(ret->type_array);
ret->index_UVarray = 0;
ret->index_length_array = 0;
ret->vertex_array = NULL;
ret->normal_array = NULL;
ret->color_array = NULL;
ret->texcoord_array = NULL;
ret->next = NULL;
return ret;
}
bezierPatchMesh *bezierPatchMeshMake2(int size_UVarray, int size_length_array)
{
bezierPatchMesh *ret = (bezierPatchMesh*) malloc(sizeof(bezierPatchMesh));
assert(ret);
ret->bpatch = NULL;
ret->bpatch_normal = NULL;
ret->bpatch_color = NULL;
ret->bpatch_texcoord = NULL;
ret->size_UVarray = size_UVarray;
ret->size_length_array = size_length_array;
ret->UVarray = (float*) malloc(sizeof(float) * size_UVarray);
assert(ret->UVarray);
ret->length_array = (int *)malloc(sizeof(int) * size_length_array);
assert(ret->length_array);
ret->type_array = (GLenum *)malloc(sizeof(GLenum) * size_length_array);
assert(ret->type_array);
ret->index_UVarray = 0;
ret->index_length_array = 0;
ret->vertex_array = NULL;
ret->normal_array = NULL;
ret->color_array = NULL;
ret->texcoord_array = NULL;
ret->next = NULL;
return ret;
}
void bezierPatchMeshPutPatch(bezierPatchMesh *bpm, int maptype, float umin, float umax, int ustride, int uorder, float vmin, float vmax, int vstride, int vorder, float *ctlpoints)
{
switch(maptype){
case GL_MAP2_VERTEX_3:
bpm->bpatch = bezierPatchMake2(umin, vmin, umax, vmax, uorder, vorder, 3, ustride, vstride, ctlpoints);
break;
case GL_MAP2_VERTEX_4:
bpm->bpatch = bezierPatchMake2(umin, vmin, umax, vmax, uorder, vorder, 4,ustride, vstride, ctlpoints );
break;
case GL_MAP2_NORMAL:
bpm->bpatch_normal = bezierPatchMake2(umin, vmin, umax, vmax, uorder, vorder, 3, ustride, vstride, ctlpoints);
break;
case GL_MAP2_INDEX:
bpm->bpatch_color = bezierPatchMake2(umin, vmin, umax, vmax, uorder, vorder, 1, ustride, vstride, ctlpoints);
break;
case GL_MAP2_COLOR_4:
bpm->bpatch_color = bezierPatchMake2(umin, vmin, umax, vmax, uorder, vorder, 4, ustride, vstride, ctlpoints);
break;
case GL_MAP2_TEXTURE_COORD_1:
bpm->bpatch_texcoord = bezierPatchMake2(umin, vmin, umax, vmax, uorder, vorder, 1, ustride, vstride, ctlpoints);
break;
case GL_MAP2_TEXTURE_COORD_2:
bpm->bpatch_texcoord = bezierPatchMake2(umin, vmin, umax, vmax, uorder, vorder, 2, ustride, vstride, ctlpoints);
break;
case GL_MAP2_TEXTURE_COORD_3:
bpm->bpatch_texcoord = bezierPatchMake2(umin, vmin, umax, vmax, uorder, vorder, 3, ustride, vstride, ctlpoints);
break;
case GL_MAP2_TEXTURE_COORD_4:
bpm->bpatch_texcoord = bezierPatchMake2(umin, vmin, umax, vmax, uorder, vorder, 4, ustride, vstride, ctlpoints);
break;
default:
fprintf(stderr, "error in bezierPatchMeshPutPatch, maptype=%i is wrong, maptype,map is invalid\n", maptype);
}
}
void bezierPatchMeshDelete(bezierPatchMesh *bpm)
{
if(bpm->bpatch != NULL)
bezierPatchDelete(bpm->bpatch);
if(bpm->bpatch_normal != NULL)
bezierPatchDelete(bpm->bpatch_normal);
if(bpm->bpatch_color != NULL)
bezierPatchDelete(bpm->bpatch_color);
if(bpm->bpatch_texcoord != NULL)
bezierPatchDelete(bpm->bpatch_texcoord);
free(bpm->UVarray);
free(bpm->length_array);
free(bpm->vertex_array);
free(bpm->normal_array);
free(bpm->type_array);
free(bpm);
}
void bezierPatchMeshBeginStrip(bezierPatchMesh *bpm, GLenum type)
{
bpm->counter = 0;
bpm->type = type;
}
void bezierPatchMeshEndStrip(bezierPatchMesh *bpm)
{
int i;
if(bpm->counter == 0) return;
if(bpm->index_length_array >= bpm->size_length_array)
{
int *temp = (int*) malloc(sizeof(int) * (bpm->size_length_array*2 + 1));
assert(temp);
GLenum *temp_type = (GLenum*) malloc(sizeof(GLenum) * (bpm->size_length_array*2 + 1));
assert(temp_type);
bpm->size_length_array = bpm->size_length_array*2 + 1;
for(i=0; i<bpm->index_length_array; i++)
{
temp[i] = bpm->length_array[i];
temp_type[i] = bpm->type_array[i];
}
free(bpm->length_array);
free(bpm->type_array);
bpm->length_array = temp;
bpm->type_array = temp_type;
}
bpm->type_array[bpm->index_length_array] = bpm->type;
bpm->length_array[bpm->index_length_array++] = bpm->counter;
}
void bezierPatchMeshInsertUV(bezierPatchMesh *bpm, float u, float v)
{
int i;
if(bpm->index_UVarray+1 >= bpm->size_UVarray)
{
float *temp = (float*) malloc(sizeof(float) * (bpm->size_UVarray * 2 + 2));
assert(temp);
bpm->size_UVarray = bpm->size_UVarray*2 + 2;
for(i=0; i<bpm->index_UVarray; i++)
{
temp[i] = bpm->UVarray[i];
}
free(bpm->UVarray);
bpm->UVarray = temp;
}
bpm->UVarray[bpm->index_UVarray] = u;
bpm->index_UVarray++;
bpm->UVarray[bpm->index_UVarray] = v;
bpm->index_UVarray++;
bpm->counter++;
}
void bezierPatchMeshPrint(bezierPatchMesh *bpm)
{
int i;
printf("the bezier patch is\n");
bezierPatchPrint(bpm->bpatch);
printf("index_length_array= %i\n", bpm->index_length_array);
printf("size_length_array =%i\n", bpm->size_length_array);
printf("index_UVarray =%i\n", bpm->index_UVarray);
printf("size_UVarray =%i\n", bpm->size_UVarray);
printf("UVarray is\n");
for(i=0; i<bpm->index_UVarray; i++)
printf("%f ", bpm->UVarray[i]);
printf("length_array is\n");
for(i=0; i<bpm->index_length_array; i++)
printf("%i ", bpm->length_array[i]);
printf("\n");
}
bezierPatchMesh* bezierPatchMeshListInsert(bezierPatchMesh* list, bezierPatchMesh* bpm)
{
bpm->next=list;
return bpm;
}
void bezierPatchMeshListPrint(bezierPatchMesh* list)
{
bezierPatchMesh *temp;
for(temp = list; temp != NULL; temp = temp->next)
{
bezierPatchMeshPrint(temp);
}
}
int bezierPatchMeshListTotalStrips(bezierPatchMesh* list)
{
int sum=0;
bezierPatchMesh *temp;
for(temp=list; temp != NULL; temp = temp->next)
{
sum += temp->index_length_array;
}
return sum;
}
int bezierPatchMeshListTotalVert(bezierPatchMesh* list)
{
int sum=0;
bezierPatchMesh *temp;
for(temp=list; temp != NULL; temp = temp->next)
{
sum += temp->index_UVarray;
}
return sum/2;
}
int bezierPatchMeshListNumTriangles(bezierPatchMesh* list)
{
int sum=0;
bezierPatchMesh* temp;
for(temp=list; temp != NULL; temp = temp->next)
{
sum += bezierPatchMeshNumTriangles(temp);
}
return sum;
}
int bezierPatchMeshNumTriangles(bezierPatchMesh* bpm)
{
int i;
int sum=0;
for(i=0; i<bpm->index_length_array; i++)
{
switch(bpm->type_array[i])
{
case GL_TRIANGLES:
sum += bpm->length_array[i]/3;
break;
case GL_TRIANGLE_FAN:
if(bpm->length_array[i] > 2)
sum += bpm->length_array[i]-2;
break;
case GL_TRIANGLE_STRIP:
if(bpm->length_array[i] > 2)
sum += bpm->length_array[i]-2;
break;
case GL_QUAD_STRIP:
if(bpm->length_array[i]>2)
sum += (bpm->length_array[i]-2);
break;
default:
fprintf(stderr,"error in bezierPatchMeshListNumTriangles, type invalid\n");
}
}
return sum;
}
void bezierPatchMeshDelDeg(bezierPatchMesh* bpm)
{
if(bpm == NULL) return;
int i,j,k;
int *new_length_array;
GLenum *new_type_array;
int index_new_length_array;
float *new_UVarray;
int index_new_UVarray;
new_length_array = (int*)malloc(sizeof(int) * bpm->index_length_array);
assert(new_length_array);
new_type_array = (GLenum*)malloc(sizeof(GLenum) * bpm->index_length_array);
assert(new_length_array);
new_UVarray = (float*) malloc(sizeof(float) * bpm->index_UVarray);
assert(new_UVarray);
index_new_length_array = 0;
index_new_UVarray=0;
k=0;
for(i=0; i<bpm->index_length_array; i++){
if( (bpm->length_array[i] != 3) || (!isDegenerate(bpm->UVarray+k, bpm->UVarray+k+2, bpm->UVarray+k+4)))
{
for(j=0; j<2* bpm->length_array[i]; j++)
new_UVarray[index_new_UVarray++] = bpm->UVarray[k++];
new_length_array[index_new_length_array] = bpm->length_array[i];
new_type_array[index_new_length_array] = bpm->type_array[i];
index_new_length_array++;
}
else
{
k += 6;
}
}
free(bpm->UVarray);
free(bpm->length_array);
free(bpm->type_array);
bpm->UVarray=new_UVarray;
bpm->length_array=new_length_array;
bpm->type_array=new_type_array;
bpm->index_UVarray = index_new_UVarray;
bpm->index_length_array = index_new_length_array;
}
void bezierPatchMeshEval(bezierPatchMesh* bpm)
{
int i,j,k,l;
float u,v;
float u0 = bpm->bpatch->umin;
float u1 = bpm->bpatch->umax;
int uorder = bpm->bpatch->uorder;
float v0 = bpm->bpatch->vmin;
float v1 = bpm->bpatch->vmax;
int vorder = bpm->bpatch->vorder;
int dimension = bpm->bpatch->dimension;
int ustride = dimension * vorder;
int vstride = dimension;
float *ctlpoints = bpm->bpatch->ctlpoints;
bpm->vertex_array = (float*) malloc(sizeof(float)* (bpm->index_UVarray/2) * 3);
assert(bpm->vertex_array);
bpm->normal_array = (float*) malloc(sizeof(float)* (bpm->index_UVarray/2) * 3);
assert(bpm->normal_array);
k=0;
l=0;
for(i=0; i<bpm->index_length_array; i++)
{
for(j=0; j<bpm->length_array[i]; j++)
{
u = bpm->UVarray[k];
v = bpm->UVarray[k+1];
bezierSurfEval(u0,u1,uorder, v0, v1, vorder, dimension, ctlpoints, ustride, vstride, u,v, bpm->vertex_array+l);
bezierSurfEvalNormal(u0,u1,uorder, v0, v1, vorder, dimension, ctlpoints, ustride, vstride, u,v, bpm->normal_array+l);
k += 2;
l += 3;
}
}
}
void bezierPatchMeshListEval(bezierPatchMesh* list)
{
bezierPatchMesh* temp;
for(temp = list; temp != NULL; temp = temp->next)
{
bezierPatchMeshEval(temp);
}
}
void bezierPatchMeshDraw(bezierPatchMesh* bpm)
{
int i,j,k;
k=0;
for(i=0; i<bpm->index_length_array; i++)
{
glBegin(bpm->type_array[i]);
for(j=0; j<bpm->length_array[i]; j++)
{
glNormal3fv(bpm->normal_array+k);
glVertex3fv(bpm->vertex_array+k);
k+= 3;
}
glEnd();
}
}
void bezierPatchMeshListDraw(bezierPatchMesh* list)
{
bezierPatchMesh* temp;
for(temp = list; temp != NULL; temp = temp->next)
{
bezierPatchMeshDraw(temp);
}
}
void bezierPatchMeshListCollect(bezierPatchMesh* list, float **vertex_array, float **normal_array, int **length_array, GLenum **type_array, int *num_strips)
{
int i,j,k,l;
bezierPatchMesh *temp;
int total_num_vertices = bezierPatchMeshListTotalVert(list);
(*vertex_array) = (float *) malloc(sizeof(float) * total_num_vertices*3);
assert(*vertex_array);
(*normal_array) = (float *) malloc(sizeof(float) * total_num_vertices*3);
assert(*normal_array);
*num_strips = bezierPatchMeshListTotalStrips(list);
*length_array = (int*) malloc(sizeof(int) * (*num_strips));
assert(*length_array);
*type_array = (GLenum*) malloc(sizeof(GLenum) * (*num_strips));
assert(*type_array);
k=0;
l=0;
for(temp = list; temp != NULL; temp = temp->next)
{
int x=0;
for(i=0; i<temp->index_length_array; i++)
{
for(j=0; j<temp->length_array[i]; j++)
{
(*vertex_array)[k] = temp->vertex_array[x];
(*vertex_array)[k+1] = temp->vertex_array[x+1];
(*vertex_array)[k+2] = temp->vertex_array[x+2];
(*normal_array)[k] = temp->normal_array[x];
(*normal_array)[k+1] = temp->normal_array[x+1];
(*normal_array)[k+2] = temp->normal_array[x+2];
x += 3;
k += 3;
}
(*type_array)[l] = temp->type_array[i];
(*length_array)[l++] = temp->length_array[i];
}
}
}
static int isDegenerate(float A[2], float B[2], float C[2])
{
if( (A[0] == B[0] && A[1]==B[1]) ||
(A[0] == C[0] && A[1]==C[1]) ||
(B[0] == C[0] && B[1]==C[1])
)
return 1;
else
return 0;
}