clumesh.c

00001 #include <clu.h>
00002 
00007 static void _cluMeshGenerateNormalsPrimitiveSet(CLmesh* mesh, CLprimitiveset* primitiveset)
00008 {
00009   GLuint i;
00010   CLnormal temp; /* face normal */
00011   GLboolean optimise = GL_TRUE;
00012 
00013   if (primitiveset->num_indices < 3) /* cannot determine any normals */
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               /* set triangle normals */
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               /* go through all vertices */
00051               for (i = 0; i < mesh->num_vertices; i++)
00052               {
00053                   /* go through all triangles */
00054                   for (j = 0; j < primitiveset->num_indices; j+=3)
00055                   {
00056                       /* if the triangles is adjacent to the vertex */
00057                       if ((primitiveset->indices[j] == i) ||
00058                           (primitiveset->indices[j+1] == i) ||
00059                           (primitiveset->indices[j+2] == i))
00060                       {
00061                           /* initially tag the face as unique */
00062                           face_unique = GL_TRUE;
00063                           
00064                           /* record normal */
00065                           normal = triangle_normals + j/3;
00066                           
00067                           /* go through all remaining triangles */
00068                           for (k = j + 3; k < primitiveset->num_indices; k+=3)
00069                           {
00070                               /* if the triangle is also adjacent to the vertex */
00071                               if ((primitiveset->indices[k] == i) ||
00072                                   (primitiveset->indices[k+1] == i) ||
00073                                   (primitiveset->indices[k+2] == i))
00074                               {
00075                                   /* record normal2 */
00076                                   normal2 = triangle_normals + k/3;
00077                                   
00078                                   /* and if the triangle normals are the same */
00079                                   if (cluNormalDotProduct(normal, normal2) == 1.0f) 
00080                                       /* or use >= 0.999999... */
00081                                   {
00082                                       /* this face is not unique */
00083                                       face_unique = GL_FALSE;
00084                                       
00085                                       break;
00086                                   }
00087                               }
00088                           }
00089                           
00090                           /* if the face is unique, add its normal to the vert normal */
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       /* to do */
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 /* add a vertex to a mesh vertex cannot be null, other properties can
00205    be undefined if mesh or vertex is null */
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; /* new index */
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   /* FIX THIS!!! what's wrong? anyone?*/
00301   return ni;
00302 }
00303 
00304 GLboolean cluMeshRemoveVertex(CLmesh* mesh, GLuint index)
00305 {
00306   GLuint i;
00307 
00308   /* printf("%d %d\n", index, mesh->num_vertices); */
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   /* go through all primitive sets, if *any* contain polygons that we can
00359      generate normals for, create a normals array */
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;   /* old num_vertices */
00408   GLboolean*      vertex_used;    /* which vertices are used? */
00409   GLuint*         vertex_map;     /* old vertex values to new vertex values */
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   /* tag all vertices as unused */
00419   for (i = 0; i < num_vertices; i++)
00420     vertex_used[i] = GL_FALSE;
00421 
00422   /* tag used vertices */
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   /* removed unused vertices */
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   /* set primitiveset indices correctly using vertex map */
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 /* NOT centroid, the actual centre... clear as mud :) */
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) /* centre mesh on origin */
00569 {
00570   CLvertex v;
00571 
00572   return cluMeshSetOrigin(mesh, cluSetVertex(&v, 0.0f, 0.0f, 0.0f));
00573   
00574   /*
00575   GLuint i;
00576   CLnormal n;
00577 
00578   cluMeshLocalOrigin((CLvertex*)&n, mesh);
00579 
00580   for (i = 0; i < mesh->num_vertices; i++)
00581     cluVertexSubtract(mesh->vertices + i, &n);
00582   
00583   return mesh;
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    It is impossible to merge primitive sets if they are of different
00620    modes.
00621 
00622    eg. A mesh with some GL_TRIANGLES and some GL_LINES cannot be
00623    merged well
00624 
00625    For this function, we look at the mode of the first primitive set
00626    and merge only those sets with that mode.  All sets of different
00627    mode are discarded.
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     /* count the total num_indices for all sets with the correct mode */
00645     for (i = 0 ; i < mesh->num_primitivesets ; i++)
00646     {
00647         total_indices += mesh->primitivesets[i]->num_indices;
00648     }
00649 
00650     /* malloc the new master set */
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     /* copy the old indices */
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     /* free old sets */
00665     for(i = 0 ; i < mesh->num_primitivesets ; i++)
00666     {
00667         clDeletePrimitiveSet(mesh->primitivesets[i]);
00668     }
00669     free(mesh->primitivesets);
00670 
00671     /* point mesh to new set */
00672     mesh->num_primitivesets = 1;
00673     mesh->primitivesets = (CLprimitiveset**) malloc (sizeof(CLprimitiveset*));
00674     mesh->primitivesets[0] = new;
00675 }

Generated on Thu Dec 27 13:53:42 2007 for CLU by  doxygen 1.4.6