00001 #include <clu.h>
00002
00007 static void _cluMeshGenerateNormalsPrimitiveSet(CLmesh* mesh, CLprimitiveset* primitiveset)
00008 {
00009 GLuint i;
00010 CLnormal temp;
00011 GLboolean optimise = GL_TRUE;
00012
00013 if (primitiveset->num_indices < 3)
00014 return;
00015
00016 if (primitiveset->num_indices > 5000)
00017 optimise = GL_FALSE;
00018
00019 switch(primitiveset->mode)
00020 {
00021 case GL_TRIANGLES:
00022 {
00023 if (optimise)
00024 {
00025
00026 GLuint j;
00027 GLuint k;
00028
00029 CLnormal* triangle_normals;
00030 CLnormal* normal;
00031 CLnormal* normal2;
00032
00033 GLboolean face_unique;
00034
00035 triangle_normals = (CLnormal*)malloc((primitiveset->num_indices/3)
00036 * sizeof(CLnormal));
00037
00038 normal = triangle_normals;
00039
00040
00041 for (i = 0; i < primitiveset->num_indices; i+=3)
00042 {
00043 cluSetNormalTriangle(normal,
00044 &mesh->vertices[primitiveset->indices[i]],
00045 &mesh->vertices[primitiveset->indices[i+1]],
00046 &mesh->vertices[primitiveset->indices[i+2]]);
00047 normal++;
00048 }
00049
00050
00051 for (i = 0; i < mesh->num_vertices; i++)
00052 {
00053
00054 for (j = 0; j < primitiveset->num_indices; j+=3)
00055 {
00056
00057 if ((primitiveset->indices[j] == i) ||
00058 (primitiveset->indices[j+1] == i) ||
00059 (primitiveset->indices[j+2] == i))
00060 {
00061
00062 face_unique = GL_TRUE;
00063
00064
00065 normal = triangle_normals + j/3;
00066
00067
00068 for (k = j + 3; k < primitiveset->num_indices; k+=3)
00069 {
00070
00071 if ((primitiveset->indices[k] == i) ||
00072 (primitiveset->indices[k+1] == i) ||
00073 (primitiveset->indices[k+2] == i))
00074 {
00075
00076 normal2 = triangle_normals + k/3;
00077
00078
00079 if (cluNormalDotProduct(normal, normal2) == 1.0f)
00080
00081 {
00082
00083 face_unique = GL_FALSE;
00084
00085 break;
00086 }
00087 }
00088 }
00089
00090
00091 if (face_unique)
00092 {
00093 cluNormalAdd(&mesh->normals[i], normal);
00094 }
00095 }
00096
00097 normal++;
00098 }
00099 }
00100
00101 free(triangle_normals);
00102
00103 break;
00104 }
00105 else
00106 {
00107 GLuint i;
00108
00109 for (i = 0; i < primitiveset->num_indices; i+=3)
00110 {
00111 cluSetNormalTriangle(&temp,
00112 &mesh->vertices[primitiveset->indices[i]],
00113 &mesh->vertices[primitiveset->indices[i+1]],
00114 &mesh->vertices[primitiveset->indices[i+2]]);
00115
00116 cluNormalAdd(&mesh->normals[primitiveset->indices[i]], &temp);
00117 cluNormalAdd(&mesh->normals[primitiveset->indices[i+1]], &temp);
00118 cluNormalAdd(&mesh->normals[primitiveset->indices[i+2]], &temp);
00119 }
00120 break;
00121 }
00122
00123 }
00124
00125 case GL_TRIANGLE_STRIP:
00126 {
00127 GLboolean swap;
00128
00129 swap = GL_TRUE;
00130
00131 for (i = 0; i < primitiveset->num_indices - 2; i++)
00132 {
00133 if (swap)
00134 {
00135 cluSetNormalTriangle(&temp,
00136 &mesh->vertices[primitiveset->indices[i]],
00137 &mesh->vertices[primitiveset->indices[i+1]],
00138 &mesh->vertices[primitiveset->indices[i+2]]);
00139 }
00140 else
00141 {
00142 cluSetNormalTriangle(&temp,
00143 &mesh->vertices[primitiveset->indices[i]],
00144 &mesh->vertices[primitiveset->indices[i+2]],
00145 &mesh->vertices[primitiveset->indices[i+1]]);
00146 }
00147
00148 cluNormalAdd(&mesh->normals[primitiveset->indices[i]], &temp);
00149 cluNormalAdd(&mesh->normals[primitiveset->indices[i+1]], &temp);
00150 cluNormalAdd(&mesh->normals[primitiveset->indices[i+2]], &temp);
00151
00152 swap = !swap;
00153 }
00154 }
00155 break;
00156
00157 case GL_TRIANGLE_FAN:
00158 for (i = 1; i < primitiveset->num_indices; i+=2)
00159 {
00160 cluSetNormalTriangle(&temp,
00161 &mesh->vertices[primitiveset->indices[0]],
00162 &mesh->vertices[primitiveset->indices[i]],
00163 &mesh->vertices[primitiveset->indices[i+1]]);
00164
00165 cluNormalAdd(&mesh->normals[primitiveset->indices[0]], &temp);
00166 cluNormalAdd(&mesh->normals[primitiveset->indices[i]], &temp);
00167 cluNormalAdd(&mesh->normals[primitiveset->indices[i+1]], &temp);
00168 }
00169 break;
00170
00171 case GL_QUADS:
00172 for (i = 0; i < primitiveset->num_indices; i+=4)
00173 {
00174 cluSetNormalTriangle(&temp,
00175 &mesh->vertices[primitiveset->indices[i]],
00176 &mesh->vertices[primitiveset->indices[i+1]],
00177 &mesh->vertices[primitiveset->indices[i+2]]);
00178
00179 cluNormalAdd(&mesh->normals[primitiveset->indices[i]], &temp);
00180 cluNormalAdd(&mesh->normals[primitiveset->indices[i+1]], &temp);
00181 cluNormalAdd(&mesh->normals[primitiveset->indices[i+2]], &temp);
00182 cluNormalAdd(&mesh->normals[primitiveset->indices[i+3]], &temp);
00183 }
00184 break;
00185
00186 case GL_QUAD_STRIP:
00187
00188 break;
00189
00190 case GL_POLYGON:
00191 cluSetNormalTriangle(&temp,
00192 &mesh->vertices[primitiveset->indices[0]],
00193 &mesh->vertices[primitiveset->indices[1]],
00194 &mesh->vertices[primitiveset->indices[2]]);
00195 for (i = 0; i < primitiveset->num_indices; i++)
00196 cluNormalAdd(&mesh->normals[primitiveset->indices[i]], &temp);
00197 break;
00198
00199 default:
00200 return;
00201 }
00202 }
00203
00204
00205
00206 GLuint cluMeshAddVertex(CLmesh* mesh,
00207 const CLvertex* vertex,
00208 const CLcolour* colour,
00209 const CLnormal* normal,
00210 const CLtexcoord* texcoord,
00211 const CLedgeflag* edgeflag)
00212 {
00213 GLuint ni;
00214
00215 ni = mesh->num_vertices;
00216
00217 mesh->num_vertices++;
00218
00219 mesh->vertices = (CLvertex*)realloc(mesh->vertices,
00220 mesh->num_vertices * sizeof(CLvertex));
00221 clCopyVertex(&mesh->vertices[ni], vertex);
00222
00223 if (mesh->num_vertices == 1)
00224 {
00225 if (colour)
00226 {
00227 mesh->colours = (CLcolour*)realloc(mesh->colours, mesh->num_vertices
00228 * sizeof(CLcolour));
00229 clCopyColour(&mesh->colours[0], colour);
00230 }
00231
00232 if (normal)
00233 {
00234 mesh->normals = (CLnormal*)realloc(mesh->normals, mesh->num_vertices
00235 * sizeof(CLnormal));
00236 clCopyNormal(&mesh->normals[0], normal);
00237 }
00238
00239 if (texcoord)
00240 {
00241 mesh->texcoords = (CLtexcoord*)realloc(mesh->texcoords,
00242 mesh->num_vertices
00243 * sizeof(CLtexcoord));
00244 clCopyTexCoord(&mesh->texcoords[0], texcoord);
00245 }
00246
00247 if (edgeflag)
00248 {
00249 mesh->edgeflags = (CLedgeflag*)realloc(mesh->edgeflags,
00250 mesh->num_vertices
00251 * sizeof(CLedgeflag));
00252 clCopyEdgeFlag(&mesh->edgeflags[0], edgeflag);
00253 }
00254 }
00255 else
00256 {
00257 if (mesh->colours)
00258 {
00259 mesh->colours = (CLcolour*)realloc(mesh->colours, mesh->num_vertices
00260 * sizeof(CLcolour));
00261 if (colour)
00262 clCopyColour(&mesh->colours[ni], colour);
00263 else
00264 clDefaultColour(&mesh->colours[ni]);
00265 }
00266
00267 if (mesh->normals)
00268 {
00269 mesh->normals = (CLnormal*)realloc(mesh->normals, mesh->num_vertices
00270 * sizeof(CLnormal));
00271 if (normal)
00272 clCopyNormal(&mesh->normals[ni], normal);
00273 else
00274 clDefaultNormal(&mesh->normals[ni]);
00275 }
00276
00277 if (mesh->texcoords)
00278 {
00279 mesh->texcoords = (CLtexcoord*)realloc(mesh->texcoords,
00280 mesh->num_vertices
00281 * sizeof(CLtexcoord));
00282 if (texcoord)
00283 clCopyTexCoord(&mesh->texcoords[ni], texcoord);
00284 else
00285 clDefaultTexCoord(&mesh->texcoords[ni]);
00286 }
00287
00288 if (mesh->edgeflags)
00289 {
00290 mesh->edgeflags = (CLedgeflag*)realloc(mesh->edgeflags,
00291 mesh->num_vertices
00292 * sizeof(CLedgeflag));
00293 if (edgeflag)
00294 clCopyEdgeFlag(&mesh->edgeflags[ni], edgeflag);
00295 else
00296 clDefaultEdgeFlag(&mesh->edgeflags[ni]);
00297 }
00298 }
00299
00300
00301 return ni;
00302 }
00303
00304 GLboolean cluMeshRemoveVertex(CLmesh* mesh, GLuint index)
00305 {
00306 GLuint i;
00307
00308
00309
00310 for (i = index; i < mesh->num_vertices - 1; i++)
00311 clCopyVertex(&mesh->vertices[i], &mesh->vertices[i+1]);
00312
00313 if (mesh->colours)
00314 for (i = index; i < mesh->num_vertices - 1; i++)
00315 clCopyColour(&mesh->colours[i], &mesh->colours[i+1]);
00316
00317 if (mesh->normals)
00318 for (i = index; i < mesh->num_vertices - 1; i++)
00319 clCopyNormal(&mesh->normals[i], &mesh->normals[i+1]);
00320
00321 if (mesh->texcoords)
00322 for (i = index; i < mesh->num_vertices - 1; i++)
00323 clCopyTexCoord(&mesh->texcoords[i], &mesh->texcoords[i+1]);
00324
00325 if (mesh->edgeflags)
00326 for (i = index; i < mesh->num_vertices - 1; i++)
00327 mesh->edgeflags[i] = mesh->edgeflags[i+1];
00328
00329 mesh->num_vertices--;
00330
00331 mesh->vertices = (CLvertex*)realloc(mesh->vertices, mesh->num_vertices
00332 * sizeof(CLvertex));
00333
00334 if (mesh->colours)
00335 mesh->colours = (CLcolour*)realloc(mesh->colours, mesh->num_vertices
00336 * sizeof(CLcolour));
00337
00338 if (mesh->normals)
00339 mesh->normals = (CLnormal*)realloc(mesh->normals, mesh->num_vertices
00340 * sizeof(CLnormal));
00341
00342 if (mesh->texcoords)
00343 mesh->texcoords = (CLtexcoord*)realloc(mesh->texcoords, mesh->num_vertices
00344 * sizeof(CLtexcoord));
00345
00346 if (mesh->edgeflags)
00347 mesh->edgeflags = (CLedgeflag*)realloc(mesh->edgeflags, mesh->num_vertices
00348 * sizeof(CLedgeflag));
00349
00350 return GL_TRUE;
00351 }
00352
00353 CLmesh* cluMeshGenerateNormals(CLmesh* mesh)
00354 {
00355 unsigned int i;
00356 GLboolean generate_normals;
00357
00358
00359
00360
00361 generate_normals = GL_FALSE;
00362
00363 for (i = 0; ((i < mesh->num_primitivesets) && (!generate_normals)); i++)
00364 {
00365 switch(mesh->primitivesets[i]->mode)
00366 {
00367 case GL_TRIANGLES:
00368 case GL_TRIANGLE_STRIP:
00369 case GL_TRIANGLE_FAN:
00370 case GL_QUADS:
00371 case GL_QUAD_STRIP:
00372 case GL_POLYGON:
00373 generate_normals = GL_TRUE;
00374 }
00375 }
00376
00377 if (!generate_normals)
00378 {
00379 mesh->normals = 0;
00380
00381 return mesh;
00382 }
00383
00384 mesh->normals = (CLnormal*)realloc(mesh->normals,
00385 mesh->num_vertices * sizeof(CLnormal));
00386
00387
00388 for (i = 0; i < mesh->num_vertices; i++)
00389 cluSetNormal(mesh->normals + i, 0.0f, 0.0f, 0.0f);
00390
00391 for (i = 0; i < mesh->num_primitivesets; i++)
00392 _cluMeshGenerateNormalsPrimitiveSet(mesh, mesh->primitivesets[i]);
00393
00394 for (i = 0; i < mesh->num_vertices; i++)
00395 cluNormalNormalise(mesh->normals + i);
00396
00397 return mesh;
00398 }
00399
00400 CLmesh* cluMeshRemoveUnusedVertices(CLmesh* mesh)
00401 {
00402 unsigned int i;
00403 unsigned int j;
00404
00405 CLprimitiveset* primitiveset;
00406
00407 GLuint num_vertices;
00408 GLboolean* vertex_used;
00409 GLuint* vertex_map;
00410 GLuint vertex_offset;
00411 unsigned int num_removed;
00412
00413 num_vertices = mesh->num_vertices;
00414
00415 vertex_used = (GLboolean*)malloc(mesh->num_vertices * sizeof(GLboolean));
00416 vertex_map = (GLuint*)malloc(mesh->num_vertices * sizeof(GLuint));
00417
00418
00419 for (i = 0; i < num_vertices; i++)
00420 vertex_used[i] = GL_FALSE;
00421
00422
00423 for (i = 0; i < mesh->num_primitivesets; i++)
00424 {
00425 primitiveset = mesh->primitivesets[i];
00426
00427 for (j = 0; j < primitiveset->num_indices; j++)
00428 vertex_used[primitiveset->indices[j]] = GL_TRUE;
00429 }
00430
00431
00432 vertex_offset = 0;
00433 num_removed = 0;
00434
00435 for (i = 0; i < num_vertices; i++)
00436 {
00437 if (vertex_used[i])
00438 vertex_map[i] = i - vertex_offset;
00439 else
00440 {
00441 cluMeshRemoveVertex(mesh, i - vertex_offset);
00442 vertex_offset++;
00443 num_removed++;
00444 }
00445 }
00446
00447 printf("%u vertices removed from mesh\n", num_removed);
00448
00449
00450 for (i = 0; i < mesh->num_primitivesets; i++)
00451 {
00452 primitiveset = mesh->primitivesets[i];
00453
00454 for (j = 0; j < primitiveset->num_indices; j++)
00455 {
00456 primitiveset->indices[j] = vertex_map[primitiveset->indices[j]];
00457 }
00458 }
00459
00460 return mesh;
00461 }
00462
00463 GLfloat cluMeshWidth(CLmesh* mesh)
00464 {
00465 GLuint i;
00466 GLfloat min_x;
00467 GLfloat max_x;
00468
00469 min_x = MAXFLOAT;
00470 max_x = -MAXFLOAT;
00471
00472 for (i = 0 ; i < mesh->num_vertices ; i++)
00473 {
00474 max_x = CL_MAX(max_x, mesh->vertices[i].x);
00475 min_x = CL_MIN(min_x, mesh->vertices[i].x);
00476 }
00477
00478 return max_x - min_x;
00479 }
00480
00481 GLfloat cluMeshHeight(CLmesh* mesh)
00482 {
00483 GLuint i;
00484 GLfloat min_y;
00485 GLfloat max_y;
00486
00487 min_y = MAXFLOAT;
00488 max_y = -MAXFLOAT;
00489
00490 for (i = 0 ; i < mesh->num_vertices ; i++)
00491 {
00492 max_y = CL_MAX(max_y, mesh->vertices[i].y);
00493 min_y = CL_MIN(min_y, mesh->vertices[i].y);
00494 }
00495
00496 return max_y - min_y;
00497 }
00498
00499 GLfloat cluMeshDepth(CLmesh* mesh)
00500 {
00501 GLuint i;
00502 GLfloat min_z;
00503 GLfloat max_z;
00504
00505 min_z = MAXFLOAT;
00506 max_z = -MAXFLOAT;
00507
00508 for (i = 0 ; i < mesh->num_vertices ; i++)
00509 {
00510 max_z = CL_MAX(max_z, mesh->vertices[i].z);
00511 min_z = CL_MIN(min_z, mesh->vertices[i].z);
00512 }
00513
00514 return max_z - min_z;
00515 }
00516
00517
00518 CLvertex* cluMeshLocalOrigin(CLvertex* v, const CLmesh* mesh)
00519 {
00520 GLuint i;
00521 GLfloat min_x;
00522 GLfloat max_x;
00523 GLfloat min_y;
00524 GLfloat max_y;
00525 GLfloat min_z;
00526 GLfloat max_z;
00527
00528 min_x = MAXFLOAT;
00529 max_x = -MAXFLOAT;
00530 min_y = MAXFLOAT;
00531 max_y = -MAXFLOAT;
00532 min_z = MAXFLOAT;
00533 max_z = -MAXFLOAT;
00534
00535 for (i = 0; i < mesh->num_vertices; i++)
00536 {
00537 min_x = CL_MIN(min_x, mesh->vertices[i].x);
00538 max_x = CL_MAX(max_x, mesh->vertices[i].x);
00539 min_y = CL_MIN(min_y, mesh->vertices[i].y);
00540 max_y = CL_MAX(max_y, mesh->vertices[i].y);
00541 min_z = CL_MIN(min_z, mesh->vertices[i].z);
00542 max_z = CL_MAX(max_z, mesh->vertices[i].z);
00543 }
00544
00545 v->x = min_x + (max_x - min_x) / 2.0f;
00546 v->y = min_y + (max_y - min_y) / 2.0f;
00547 v->z = min_z + (max_z - min_z) / 2.0f;
00548
00549 return v;
00550 }
00551
00552 CLmesh* cluMeshSetOrigin(CLmesh* mesh, const CLvertex* v)
00553 {
00554 GLuint i;
00555
00556 CLvertex origin;
00557 CLnormal n;
00558
00559 cluMeshLocalOrigin(&origin, mesh);
00560 cluNormalDifference(&n, v, &origin);
00561
00562 for (i = 0; i < mesh->num_vertices; i++)
00563 cluVertexAdd(mesh->vertices + i, &n);
00564
00565 return mesh;
00566 }
00567
00568 CLmesh* cluMeshCentre(CLmesh* mesh)
00569 {
00570 CLvertex v;
00571
00572 return cluMeshSetOrigin(mesh, cluSetVertex(&v, 0.0f, 0.0f, 0.0f));
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585 }
00586
00587 CLmesh* cluMeshScale(CLmesh* mesh, GLfloat scale)
00588 {
00589 return cluMeshResize(mesh, scale, scale, scale);
00590 }
00591
00592 CLmesh* cluMeshScaleUnitCube(CLmesh* mesh)
00593 {
00594 return cluMeshScale(mesh,
00595 1.0f / (CL_MAX(cluMeshWidth(mesh),
00596 CL_MAX(cluMeshHeight(mesh),
00597 cluMeshDepth(mesh)))));
00598 }
00599
00600 CLmesh* cluMeshResize(CLmesh* mesh, GLfloat sx, GLfloat sy, GLfloat sz)
00601 {
00602 GLuint i;
00603 CLvertex* vertex;
00604
00605 for (i = 0; i < mesh->num_vertices; i++)
00606 {
00607 vertex = mesh->vertices + i;
00608
00609 vertex->x *= sx;
00610 vertex->y *= sy;
00611 vertex->z *= sz;
00612 }
00613
00614 return mesh;
00615 }
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629 GLvoid cluMeshMergePrimitiveSets(CLmesh* mesh)
00630 {
00631 GLenum mode;
00632 GLuint i = 0;
00633 GLuint total_indices = 0;
00634 CLprimitiveset* new = 0;
00635
00636 if (mesh->num_primitivesets == 1)
00637 {
00638 printf("cluMeshMergePrimitiveSets() - No merging necessary\n");
00639 return;
00640 }
00641
00642 mode = mesh->primitivesets[0]->mode;
00643
00644
00645 for (i = 0 ; i < mesh->num_primitivesets ; i++)
00646 {
00647 total_indices += mesh->primitivesets[i]->num_indices;
00648 }
00649
00650
00651 new = clDefaultPrimitiveSet(clNewPrimitiveSet());
00652 new->mode = mode;
00653 new->num_indices = total_indices;
00654 new->indices = (GLuint*) malloc (total_indices * sizeof(GLuint));
00655
00656
00657 total_indices = 0;
00658 for (i = 0 ; i < mesh->num_primitivesets ; i++)
00659 {
00660 memcpy(&new->indices[total_indices], mesh->primitivesets[i]->indices, mesh->primitivesets[i]->num_indices * sizeof(GLuint));
00661 total_indices += mesh->primitivesets[i]->num_indices;
00662 }
00663
00664
00665 for(i = 0 ; i < mesh->num_primitivesets ; i++)
00666 {
00667 clDeletePrimitiveSet(mesh->primitivesets[i]);
00668 }
00669 free(mesh->primitivesets);
00670
00671
00672 mesh->num_primitivesets = 1;
00673 mesh->primitivesets = (CLprimitiveset**) malloc (sizeof(CLprimitiveset*));
00674 mesh->primitivesets[0] = new;
00675 }