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 611