C:/jkyprian/devel/lib3ds/lib3ds/mesh.c

00001 /*
00002  * The 3D Studio File Format Library
00003  * Copyright (C) 1996-2007 by Jan Eric Kyprianidis <www.kyprianidis.com>
00004  * All rights reserved.
00005  *
00006  * This program is  free  software;  you can redistribute it and/or modify it
00007  * under the terms of the  GNU Lesser General Public License  as published by 
00008  * the  Free Software Foundation;  either version 2.1 of the License,  or (at 
00009  * your option) any later version.
00010  *
00011  * This  program  is  distributed in  the  hope that it will  be useful,  but
00012  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
00013  * or  FITNESS FOR A  PARTICULAR PURPOSE.  See the  GNU Lesser General Public  
00014  * License for more details.
00015  *
00016  * You should  have received  a copy of the GNU Lesser General Public License
00017  * along with  this program;  if not, write to the  Free Software Foundation,
00018  * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00019  *
00020  * $Id: mesh.c,v 1.29 2007/06/20 17:04:08 jeh Exp $
00021  */
00022 #include <lib3ds/mesh.h>
00023 #include <lib3ds/io.h>
00024 #include <lib3ds/chunk.h>
00025 #include <lib3ds/vector.h>
00026 #include <lib3ds/matrix.h>
00027 #include <stdlib.h>
00028 #include <string.h>
00029 #include <math.h>
00030 #include <float.h>
00031 
00032 
00038 static Lib3dsBool
00039 face_array_read(Lib3dsMesh *mesh, Lib3dsIo *io)
00040 {
00041   Lib3dsChunk c;
00042   Lib3dsWord chunk;
00043   int i;
00044   int faces;
00045 
00046   if (!lib3ds_chunk_read_start(&c, LIB3DS_FACE_ARRAY, io)) {
00047     return(LIB3DS_FALSE);
00048   }
00049   lib3ds_mesh_free_face_list(mesh);
00050   
00051   faces=lib3ds_io_read_word(io);
00052   if (faces) {
00053     if (!lib3ds_mesh_new_face_list(mesh, faces)) {
00054       LIB3DS_ERROR_LOG;
00055       return(LIB3DS_FALSE);
00056     }
00057     for (i=0; i<faces; ++i) {
00058       strcpy(mesh->faceL[i].material, "");
00059       mesh->faceL[i].points[0]=lib3ds_io_read_word(io);
00060       mesh->faceL[i].points[1]=lib3ds_io_read_word(io);
00061       mesh->faceL[i].points[2]=lib3ds_io_read_word(io);
00062       mesh->faceL[i].flags=lib3ds_io_read_word(io);
00063     }
00064     lib3ds_chunk_read_tell(&c, io);
00065 
00066     while ((chunk=lib3ds_chunk_read_next(&c, io))!=0) {
00067       switch (chunk) {
00068         case LIB3DS_SMOOTH_GROUP:
00069           {
00070             unsigned i;
00071 
00072             for (i=0; i<mesh->faces; ++i) {
00073               mesh->faceL[i].smoothing=lib3ds_io_read_dword(io);
00074             }
00075           }
00076           break;
00077         case LIB3DS_MSH_MAT_GROUP:
00078           {
00079             char name[64];
00080             unsigned faces;
00081             unsigned i;
00082             unsigned index;
00083 
00084             if (!lib3ds_io_read_string(io, name, 64)) {
00085               return(LIB3DS_FALSE);
00086             }
00087             faces=lib3ds_io_read_word(io);
00088             for (i=0; i<faces; ++i) {
00089               index=lib3ds_io_read_word(io);
00090               ASSERT(index<mesh->faces);
00091               strcpy(mesh->faceL[index].material, name);
00092             }
00093           }
00094           break;
00095         case LIB3DS_MSH_BOXMAP:
00096           {
00097             char name[64];
00098 
00099             if (!lib3ds_io_read_string(io, name, 64)) {
00100               return(LIB3DS_FALSE);
00101             }
00102             strcpy(mesh->box_map.front, name);
00103             if (!lib3ds_io_read_string(io, name, 64)) {
00104               return(LIB3DS_FALSE);
00105             }
00106             strcpy(mesh->box_map.back, name);
00107             if (!lib3ds_io_read_string(io, name, 64)) {
00108               return(LIB3DS_FALSE);
00109             }
00110             strcpy(mesh->box_map.left, name);
00111             if (!lib3ds_io_read_string(io, name, 64)) {
00112               return(LIB3DS_FALSE);
00113             }
00114             strcpy(mesh->box_map.right, name);
00115             if (!lib3ds_io_read_string(io, name, 64)) {
00116               return(LIB3DS_FALSE);
00117             }
00118             strcpy(mesh->box_map.top, name);
00119             if (!lib3ds_io_read_string(io, name, 64)) {
00120               return(LIB3DS_FALSE);
00121             }
00122             strcpy(mesh->box_map.bottom, name);
00123           }
00124           break;
00125         default:
00126           lib3ds_chunk_unknown(chunk);
00127       }
00128     }
00129     
00130   }
00131   lib3ds_chunk_read_end(&c, io);
00132   return(LIB3DS_TRUE);
00133 }
00134 
00135 
00150 Lib3dsMesh*
00151 lib3ds_mesh_new(const char *name)
00152 {
00153   Lib3dsMesh *mesh;
00154 
00155   ASSERT(name);
00156   ASSERT(strlen(name)<64);
00157   
00158   mesh=(Lib3dsMesh*)calloc(sizeof(Lib3dsMesh), 1);
00159   if (!mesh) {
00160     return(0);
00161   }
00162   strcpy(mesh->name, name);
00163   lib3ds_matrix_identity(mesh->matrix);
00164   mesh->map_data.maptype=LIB3DS_MAP_NONE;
00165   return(mesh);
00166 }
00167 
00168 
00176 void
00177 lib3ds_mesh_free(Lib3dsMesh *mesh)
00178 {
00179   lib3ds_mesh_free_point_list(mesh);
00180   lib3ds_mesh_free_flag_list(mesh);
00181   lib3ds_mesh_free_texel_list(mesh);
00182   lib3ds_mesh_free_face_list(mesh);
00183   memset(mesh, 0, sizeof(Lib3dsMesh));
00184   free(mesh);
00185 }
00186 
00187 
00201 Lib3dsBool
00202 lib3ds_mesh_new_point_list(Lib3dsMesh *mesh, Lib3dsDword points)
00203 {
00204   ASSERT(mesh);
00205   if (mesh->pointL) {
00206     ASSERT(mesh->points);
00207     lib3ds_mesh_free_point_list(mesh);
00208   }
00209   ASSERT(!mesh->pointL && !mesh->points);
00210   mesh->points=0;
00211   mesh->pointL=calloc(sizeof(Lib3dsPoint)*points,1);
00212   if (!mesh->pointL) {
00213     LIB3DS_ERROR_LOG;
00214     return(LIB3DS_FALSE);
00215   }
00216   mesh->points=points;
00217   return(LIB3DS_TRUE);
00218 }
00219 
00220 
00231 void
00232 lib3ds_mesh_free_point_list(Lib3dsMesh *mesh)
00233 {
00234   ASSERT(mesh);
00235   if (mesh->pointL) {
00236     ASSERT(mesh->points);
00237     free(mesh->pointL);
00238     mesh->pointL=0;
00239     mesh->points=0;
00240   }
00241   else {
00242     ASSERT(!mesh->points);
00243   }
00244 }
00245 
00246 
00261 Lib3dsBool
00262 lib3ds_mesh_new_flag_list(Lib3dsMesh *mesh, Lib3dsDword flags)
00263 {
00264   ASSERT(mesh);
00265   if (mesh->flagL) {
00266     ASSERT(mesh->flags);
00267     lib3ds_mesh_free_flag_list(mesh);
00268   }
00269   ASSERT(!mesh->flagL && !mesh->flags);
00270   mesh->flags=0;
00271   mesh->flagL=calloc(sizeof(Lib3dsWord)*flags,1);
00272   if (!mesh->flagL) {
00273     LIB3DS_ERROR_LOG;
00274     return(LIB3DS_FALSE);
00275   }
00276   mesh->flags=flags;
00277   return(LIB3DS_TRUE);
00278 }
00279 
00280 
00291 void
00292 lib3ds_mesh_free_flag_list(Lib3dsMesh *mesh)
00293 {
00294   ASSERT(mesh);
00295   if (mesh->flagL) {
00296     ASSERT(mesh->flags);
00297     free(mesh->flagL);
00298     mesh->flagL=0;
00299     mesh->flags=0;
00300   }
00301   else {
00302     ASSERT(!mesh->flags);
00303   }
00304 }
00305 
00306 
00320 Lib3dsBool
00321 lib3ds_mesh_new_texel_list(Lib3dsMesh *mesh, Lib3dsDword texels)
00322 {
00323   ASSERT(mesh);
00324   if (mesh->texelL) {
00325     ASSERT(mesh->texels);
00326     lib3ds_mesh_free_texel_list(mesh);
00327   }
00328   ASSERT(!mesh->texelL && !mesh->texels);
00329   mesh->texels=0;
00330   mesh->texelL=calloc(sizeof(Lib3dsTexel)*texels,1);
00331   if (!mesh->texelL) {
00332     LIB3DS_ERROR_LOG;
00333     return(LIB3DS_FALSE);
00334   }
00335   mesh->texels=texels;
00336   return(LIB3DS_TRUE);
00337 }
00338 
00339 
00350 void
00351 lib3ds_mesh_free_texel_list(Lib3dsMesh *mesh)
00352 {
00353   ASSERT(mesh);
00354   if (mesh->texelL) {
00355     ASSERT(mesh->texels);
00356     free(mesh->texelL);
00357     mesh->texelL=0;
00358     mesh->texels=0;
00359   }
00360   else {
00361     ASSERT(!mesh->texels);
00362   }
00363 }
00364 
00365 
00379 Lib3dsBool
00380 lib3ds_mesh_new_face_list(Lib3dsMesh *mesh, Lib3dsDword faces)
00381 {
00382   ASSERT(mesh);
00383   if (mesh->faceL) {
00384     ASSERT(mesh->faces);
00385     lib3ds_mesh_free_face_list(mesh);
00386   }
00387   ASSERT(!mesh->faceL && !mesh->faces);
00388   mesh->faces=0;
00389   mesh->faceL=calloc(sizeof(Lib3dsFace)*faces,1);
00390   if (!mesh->faceL) {
00391     LIB3DS_ERROR_LOG;
00392     return(LIB3DS_FALSE);
00393   }
00394   mesh->faces=faces;
00395   return(LIB3DS_TRUE);
00396 }
00397 
00398 
00409 void
00410 lib3ds_mesh_free_face_list(Lib3dsMesh *mesh)
00411 {
00412   ASSERT(mesh);
00413   if (mesh->faceL) {
00414     ASSERT(mesh->faces);
00415     free(mesh->faceL);
00416     mesh->faceL=0;
00417     mesh->faces=0;
00418   }
00419   else {
00420     ASSERT(!mesh->faces);
00421   }
00422 }
00423 
00424 
00434 void
00435 lib3ds_mesh_bounding_box(Lib3dsMesh *mesh, Lib3dsVector bmin, Lib3dsVector bmax)
00436 {
00437   unsigned i;
00438   bmin[0] = bmin[1] = bmin[2] = FLT_MAX; 
00439   bmax[0] = bmax[1] = bmax[2] = FLT_MIN; 
00440 
00441   for (i=0; i<mesh->points; ++i) {
00442     lib3ds_vector_min(bmin, mesh->pointL[i].pos);
00443     lib3ds_vector_max(bmax, mesh->pointL[i].pos);
00444   }
00445 }
00446 
00447 
00448 typedef struct _Lib3dsFaces Lib3dsFaces; 
00449 
00450 struct _Lib3dsFaces {
00451   Lib3dsFaces *next;
00452   Lib3dsFace *face;
00453 };
00454 
00455 
00478 void
00479 lib3ds_mesh_calculate_normals(Lib3dsMesh *mesh, Lib3dsVector *normalL)
00480 {
00481   Lib3dsFaces **fl; 
00482   Lib3dsFaces *fa; 
00483   unsigned i,j,k;
00484 
00485   if (!mesh->faces) {
00486     return;
00487   }
00488 
00489   fl=calloc(sizeof(Lib3dsFaces*),mesh->points);
00490   ASSERT(fl);
00491   fa=calloc(sizeof(Lib3dsFaces),3*mesh->faces);
00492   ASSERT(fa);
00493   k=0;
00494   for (i=0; i<mesh->faces; ++i) {
00495     Lib3dsFace *f=&mesh->faceL[i];
00496     for (j=0; j<3; ++j) {
00497       Lib3dsFaces* l=&fa[k++];
00498       ASSERT(f->points[j]<mesh->points);
00499       l->face=f;
00500       l->next=fl[f->points[j]];
00501       fl[f->points[j]]=l;
00502     }
00503   }
00504   
00505   for (i=0; i<mesh->faces; ++i) {
00506     Lib3dsFace *f=&mesh->faceL[i];
00507     for (j=0; j<3; ++j) {
00508       // FIXME: static array needs at least check!!
00509       Lib3dsVector n,N[128];
00510       Lib3dsFaces *p;
00511       int k,l;
00512       int found;
00513 
00514       ASSERT(f->points[j]<mesh->points);
00515 
00516       if (f->smoothing) {
00517         lib3ds_vector_zero(n);
00518         k=0;
00519         for (p=fl[f->points[j]]; p; p=p->next) {
00520           found=0;
00521           for (l=0; l<k; ++l) {
00522             if( l >= 128 )
00523               printf("array N overflow: i=%d, j=%d, k=%d\n", i,j,k);
00524             if (fabs(lib3ds_vector_dot(N[l], p->face->normal)-1.0)<1e-5) {
00525               found=1;
00526               break;
00527             }
00528           }
00529           if (!found) {
00530             if (f->smoothing & p->face->smoothing) {
00531               lib3ds_vector_add(n,n, p->face->normal);
00532               lib3ds_vector_copy(N[k], p->face->normal);
00533               ++k;
00534             }
00535           }
00536         }
00537       } 
00538       else {
00539         lib3ds_vector_copy(n, f->normal);
00540       }
00541       lib3ds_vector_normalize(n);
00542 
00543       lib3ds_vector_copy(normalL[3*i+j], n);
00544     }
00545   }
00546 
00547   free(fa);
00548   free(fl);
00549 }
00550 
00551 
00564 void
00565 lib3ds_mesh_dump(Lib3dsMesh *mesh)
00566 {
00567   unsigned i;
00568   Lib3dsVector p;
00569 
00570   ASSERT(mesh);
00571   printf("  %s vertices=%ld faces=%ld\n",
00572     mesh->name,
00573     mesh->points,
00574     mesh->faces
00575   );
00576   printf("  matrix:\n");
00577   lib3ds_matrix_dump(mesh->matrix);
00578   printf("  point list:\n");
00579   for (i=0; i<mesh->points; ++i) {
00580     lib3ds_vector_copy(p, mesh->pointL[i].pos);
00581     printf ("    %8f %8f %8f\n", p[0], p[1], p[2]);
00582   }
00583   printf("  facelist:\n");
00584   for (i=0; i<mesh->faces; ++i) {
00585     printf ("    %4d %4d %4d  smoothing:%X  flags:%X  material:\"%s\"\n",
00586       mesh->faceL[i].points[0],
00587       mesh->faceL[i].points[1],
00588       mesh->faceL[i].points[2],
00589       (unsigned)mesh->faceL[i].smoothing,
00590       mesh->faceL[i].flags,
00591       mesh->faceL[i].material
00592     );
00593   }
00594 }
00595 
00596 
00600 Lib3dsBool
00601 lib3ds_mesh_read(Lib3dsMesh *mesh, Lib3dsIo *io)
00602 {
00603   Lib3dsChunk c;
00604   Lib3dsWord chunk;
00605 
00606   if (!lib3ds_chunk_read_start(&c, LIB3DS_N_TRI_OBJECT, io)) {
00607     return(LIB3DS_FALSE);
00608   }
00609 
00610   while ((chunk=lib3ds_chunk_read_next(&c, io))!=0) {
00611     switch (chunk) {
00612       case LIB3DS_MESH_MATRIX:
00613         {
00614           int i,j;
00615           
00616           lib3ds_matrix_identity(mesh->matrix);
00617           for (i=0; i<4; i++) {
00618             for (j=0; j<3; j++) {
00619               mesh->matrix[i][j]=lib3ds_io_read_float(io);
00620             }
00621           }
00622         }
00623         break;
00624       case LIB3DS_MESH_COLOR:
00625         {
00626           mesh->color=lib3ds_io_read_byte(io);
00627         }
00628         break;
00629       case LIB3DS_POINT_ARRAY:
00630         {
00631           unsigned i,j;
00632           unsigned points;
00633           
00634           lib3ds_mesh_free_point_list(mesh);
00635           points=lib3ds_io_read_word(io);
00636           if (points) {
00637             if (!lib3ds_mesh_new_point_list(mesh, points)) {
00638               LIB3DS_ERROR_LOG;
00639               return(LIB3DS_FALSE);
00640             }
00641             for (i=0; i<mesh->points; ++i) {
00642               for (j=0; j<3; ++j) {
00643                 mesh->pointL[i].pos[j]=lib3ds_io_read_float(io);
00644               }
00645             }
00646             ASSERT((!mesh->flags) || (mesh->points==mesh->flags));
00647             ASSERT((!mesh->texels) || (mesh->points==mesh->texels));
00648           }
00649         }
00650         break;
00651       case LIB3DS_POINT_FLAG_ARRAY:
00652         {
00653           unsigned i;
00654           unsigned flags;
00655           
00656           lib3ds_mesh_free_flag_list(mesh);
00657           flags=lib3ds_io_read_word(io);
00658           if (flags) {
00659             if (!lib3ds_mesh_new_flag_list(mesh, flags)) {
00660               LIB3DS_ERROR_LOG;
00661               return(LIB3DS_FALSE);
00662             }
00663             for (i=0; i<mesh->flags; ++i) {
00664               mesh->flagL[i]=lib3ds_io_read_word(io);
00665             }
00666             ASSERT((!mesh->points) || (mesh->flags==mesh->points));
00667             ASSERT((!mesh->texels) || (mesh->flags==mesh->texels));
00668           }
00669         }
00670         break;
00671       case LIB3DS_FACE_ARRAY:
00672         {
00673           lib3ds_chunk_read_reset(&c, io);
00674           if (!face_array_read(mesh, io)) {
00675             return(LIB3DS_FALSE);
00676           }
00677         }
00678         break;
00679       case LIB3DS_MESH_TEXTURE_INFO:
00680         {
00681           int i,j;
00682 
00683           for (i=0; i<2; ++i) {
00684             mesh->map_data.tile[i]=lib3ds_io_read_float(io);
00685           }
00686           for (i=0; i<3; ++i) {
00687             mesh->map_data.pos[i]=lib3ds_io_read_float(io);
00688           }
00689           mesh->map_data.scale=lib3ds_io_read_float(io);
00690 
00691           lib3ds_matrix_identity(mesh->map_data.matrix);
00692           for (i=0; i<4; i++) {
00693             for (j=0; j<3; j++) {
00694               mesh->map_data.matrix[i][j]=lib3ds_io_read_float(io);
00695             }
00696           }
00697           for (i=0; i<2; ++i) {
00698             mesh->map_data.planar_size[i]=lib3ds_io_read_float(io);
00699           }
00700           mesh->map_data.cylinder_height=lib3ds_io_read_float(io);
00701         }
00702         break;
00703       case LIB3DS_TEX_VERTS:
00704         {
00705           unsigned i;
00706           unsigned texels;
00707           
00708           lib3ds_mesh_free_texel_list(mesh);
00709           texels=lib3ds_io_read_word(io);
00710           if (texels) {
00711             if (!lib3ds_mesh_new_texel_list(mesh, texels)) {
00712               LIB3DS_ERROR_LOG;
00713               return(LIB3DS_FALSE);
00714             }
00715             for (i=0; i<mesh->texels; ++i) {
00716               mesh->texelL[i][0]=lib3ds_io_read_float(io);
00717               mesh->texelL[i][1]=lib3ds_io_read_float(io);
00718             }
00719             ASSERT((!mesh->points) || (mesh->texels==mesh->points));
00720             ASSERT((!mesh->flags) || (mesh->texels==mesh->flags));
00721           }
00722         }
00723         break;
00724       default:
00725         lib3ds_chunk_unknown(chunk);
00726     }
00727   }
00728   {
00729     unsigned j;
00730 
00731     for (j=0; j<mesh->faces; ++j) {
00732       ASSERT(mesh->faceL[j].points[0]<mesh->points);
00733       ASSERT(mesh->faceL[j].points[1]<mesh->points);
00734       ASSERT(mesh->faceL[j].points[2]<mesh->points);
00735       lib3ds_vector_normal(
00736         mesh->faceL[j].normal,
00737         mesh->pointL[mesh->faceL[j].points[0]].pos,
00738         mesh->pointL[mesh->faceL[j].points[1]].pos,
00739         mesh->pointL[mesh->faceL[j].points[2]].pos
00740       );
00741     }
00742   }
00743 
00744   if (lib3ds_matrix_det(mesh->matrix) < 0.0)
00745   {
00746     /* Flip X coordinate of vertices if mesh matrix 
00747        has negative determinant */
00748     Lib3dsMatrix inv_matrix, M;
00749     Lib3dsVector tmp;
00750     unsigned i;
00751 
00752     lib3ds_matrix_copy(inv_matrix, mesh->matrix);
00753     lib3ds_matrix_inv(inv_matrix);
00754 
00755     lib3ds_matrix_copy(M, mesh->matrix);
00756     lib3ds_matrix_scale_xyz(M, -1.0f, 1.0f, 1.0f);
00757     lib3ds_matrix_mult(M, inv_matrix);
00758 
00759     for (i=0; i<mesh->points; ++i) {
00760       lib3ds_vector_transform(tmp, M, mesh->pointL[i].pos);
00761       lib3ds_vector_copy(mesh->pointL[i].pos, tmp);
00762     }
00763   }
00764 
00765   lib3ds_chunk_read_end(&c, io);
00766 
00767   return(LIB3DS_TRUE);
00768 }
00769 
00770 
00771 static Lib3dsBool
00772 point_array_write(Lib3dsMesh *mesh, Lib3dsIo *io)
00773 {
00774   Lib3dsChunk c;
00775   unsigned i;
00776 
00777   if (!mesh->points || !mesh->pointL) {
00778     return(LIB3DS_TRUE);
00779   }
00780   ASSERT(mesh->points<0x10000);
00781   c.chunk=LIB3DS_POINT_ARRAY;
00782   c.size=8+12*mesh->points;
00783   lib3ds_chunk_write(&c, io);
00784   
00785   lib3ds_io_write_word(io, (Lib3dsWord)mesh->points);
00786 
00787   if (lib3ds_matrix_det(mesh->matrix) >= 0.0f) {
00788     for (i=0; i<mesh->points; ++i) {
00789       lib3ds_io_write_vector(io, mesh->pointL[i].pos);
00790     }
00791   }
00792   else {
00793     /* Flip X coordinate of vertices if mesh matrix 
00794        has negative determinant */
00795     Lib3dsMatrix inv_matrix, M;
00796     Lib3dsVector tmp;
00797 
00798     lib3ds_matrix_copy(inv_matrix, mesh->matrix);
00799     lib3ds_matrix_inv(inv_matrix);
00800     lib3ds_matrix_copy(M, mesh->matrix);
00801     lib3ds_matrix_scale_xyz(M, -1.0f, 1.0f, 1.0f);
00802     lib3ds_matrix_mult(M, inv_matrix);
00803 
00804     for (i=0; i<mesh->points; ++i) {
00805       lib3ds_vector_transform(tmp, M, mesh->pointL[i].pos);
00806       lib3ds_io_write_vector(io, tmp);
00807     }
00808   }
00809 
00810   return(LIB3DS_TRUE);
00811 }
00812 
00813 
00814 static Lib3dsBool
00815 flag_array_write(Lib3dsMesh *mesh, Lib3dsIo *io)
00816 {
00817   Lib3dsChunk c;
00818   unsigned i;
00819   
00820   if (!mesh->flags || !mesh->flagL) {
00821     return(LIB3DS_TRUE);
00822   }
00823   ASSERT(mesh->flags<0x10000);
00824   c.chunk=LIB3DS_POINT_FLAG_ARRAY;
00825   c.size=8+2*mesh->flags;
00826   lib3ds_chunk_write(&c, io);
00827   
00828   lib3ds_io_write_word(io, (Lib3dsWord)mesh->flags);
00829   for (i=0; i<mesh->flags; ++i) {
00830     lib3ds_io_write_word(io, mesh->flagL[i]);
00831   }
00832   return(LIB3DS_TRUE);
00833 }
00834 
00835 
00836 static Lib3dsBool
00837 face_array_write(Lib3dsMesh *mesh, Lib3dsIo *io)
00838 {
00839   Lib3dsChunk c;
00840   
00841   if (!mesh->faces || !mesh->faceL) {
00842     return(LIB3DS_TRUE);
00843   }
00844   ASSERT(mesh->faces<0x10000);
00845   c.chunk=LIB3DS_FACE_ARRAY;
00846   if (!lib3ds_chunk_write_start(&c, io)) {
00847     return(LIB3DS_FALSE);
00848   }
00849   {
00850     unsigned i;
00851 
00852     lib3ds_io_write_word(io, (Lib3dsWord)mesh->faces);
00853     for (i=0; i<mesh->faces; ++i) {
00854       lib3ds_io_write_word(io, mesh->faceL[i].points[0]);
00855       lib3ds_io_write_word(io, mesh->faceL[i].points[1]);
00856       lib3ds_io_write_word(io, mesh->faceL[i].points[2]);
00857       lib3ds_io_write_word(io, mesh->faceL[i].flags);
00858     }
00859   }
00860 
00861   { /*---- MSH_MAT_GROUP ----*/
00862     Lib3dsChunk c;
00863     unsigned i,j;
00864     Lib3dsWord num;
00865     char *matf=calloc(sizeof(char), mesh->faces);
00866     if (!matf) {
00867       return(LIB3DS_FALSE);
00868     }
00869     
00870     for (i=0; i<mesh->faces; ++i) {
00871       if (!matf[i] && strlen(mesh->faceL[i].material)) {
00872         matf[i]=1;
00873         num=1;
00874         
00875         for (j=i+1; j<mesh->faces; ++j) {
00876           if (strcmp(mesh->faceL[i].material, mesh->faceL[j].material)==0) ++num;
00877         }
00878         
00879         c.chunk=LIB3DS_MSH_MAT_GROUP;
00880         c.size=6+ (Lib3dsDword)strlen(mesh->faceL[i].material)+1 +2+2*num;
00881         lib3ds_chunk_write(&c, io);
00882         lib3ds_io_write_string(io, mesh->faceL[i].material);
00883         lib3ds_io_write_word(io, num);
00884         lib3ds_io_write_word(io, (Lib3dsWord)i);
00885         
00886         for (j=i+1; j<mesh->faces; ++j) {
00887           if (strcmp(mesh->faceL[i].material, mesh->faceL[j].material)==0) {
00888             lib3ds_io_write_word(io, (Lib3dsWord)j);
00889             matf[j]=1;
00890           }
00891         }
00892       }      
00893     }
00894     free(matf);
00895   }
00896 
00897   { /*---- SMOOTH_GROUP ----*/
00898     Lib3dsChunk c;
00899     unsigned i;
00900     
00901     c.chunk=LIB3DS_SMOOTH_GROUP;
00902     c.size=6+4*mesh->faces;
00903     lib3ds_chunk_write(&c, io);
00904     
00905     for (i=0; i<mesh->faces; ++i) {
00906       lib3ds_io_write_dword(io, mesh->faceL[i].smoothing);
00907     }
00908   }
00909   
00910   { /*---- MSH_BOXMAP ----*/
00911     Lib3dsChunk c;
00912 
00913     if (strlen(mesh->box_map.front) ||
00914       strlen(mesh->box_map.back) ||
00915       strlen(mesh->box_map.left) ||
00916       strlen(mesh->box_map.right) ||
00917       strlen(mesh->box_map.top) ||
00918       strlen(mesh->box_map.bottom)) {
00919     
00920       c.chunk=LIB3DS_MSH_BOXMAP;
00921       if (!lib3ds_chunk_write_start(&c, io)) {
00922         return(LIB3DS_FALSE);
00923       }
00924       
00925       lib3ds_io_write_string(io, mesh->box_map.front);
00926       lib3ds_io_write_string(io, mesh->box_map.back);
00927       lib3ds_io_write_string(io, mesh->box_map.left);
00928       lib3ds_io_write_string(io, mesh->box_map.right);
00929       lib3ds_io_write_string(io, mesh->box_map.top);
00930       lib3ds_io_write_string(io, mesh->box_map.bottom);
00931       
00932       if (!lib3ds_chunk_write_end(&c, io)) {
00933         return(LIB3DS_FALSE);
00934       }
00935     }
00936   }
00937 
00938   if (!lib3ds_chunk_write_end(&c, io)) {
00939     return(LIB3DS_FALSE);
00940   }
00941   return(LIB3DS_TRUE);
00942 }
00943 
00944 
00945 static Lib3dsBool
00946 texel_array_write(Lib3dsMesh *mesh, Lib3dsIo *io)
00947 {
00948   Lib3dsChunk c;
00949   unsigned i;
00950   
00951   if (!mesh->texels || !mesh->texelL) {
00952     return(LIB3DS_TRUE);
00953   }
00954   ASSERT(mesh->texels<0x10000);
00955   c.chunk=LIB3DS_TEX_VERTS;
00956   c.size=8+8*mesh->texels;
00957   lib3ds_chunk_write(&c, io);
00958   
00959   lib3ds_io_write_word(io, (Lib3dsWord)mesh->texels);
00960   for (i=0; i<mesh->texels; ++i) {
00961     lib3ds_io_write_float(io, mesh->texelL[i][0]);
00962     lib3ds_io_write_float(io, mesh->texelL[i][1]);
00963   }
00964   return(LIB3DS_TRUE);
00965 }
00966 
00967 
00971 Lib3dsBool
00972 lib3ds_mesh_write(Lib3dsMesh *mesh, Lib3dsIo *io)
00973 {
00974   Lib3dsChunk c;
00975 
00976   c.chunk=LIB3DS_N_TRI_OBJECT;
00977   if (!lib3ds_chunk_write_start(&c,io)) {
00978     return(LIB3DS_FALSE);
00979   }
00980   if (!point_array_write(mesh, io)) {
00981     return(LIB3DS_FALSE);
00982   }
00983   if (!texel_array_write(mesh, io)) {
00984     return(LIB3DS_FALSE);
00985   }
00986 
00987   if (mesh->map_data.maptype!=LIB3DS_MAP_NONE) { /*---- LIB3DS_MESH_TEXTURE_INFO ----*/
00988     Lib3dsChunk c;
00989     int i,j;
00990     
00991     c.chunk=LIB3DS_MESH_TEXTURE_INFO;
00992     c.size=92;
00993     if (!lib3ds_chunk_write(&c,io)) {
00994       return(LIB3DS_FALSE);
00995     }
00996 
00997     lib3ds_io_write_word(io, mesh->map_data.maptype);
00998 
00999     for (i=0; i<2; ++i) {
01000       lib3ds_io_write_float(io, mesh->map_data.tile[i]);
01001     }
01002     for (i=0; i<3; ++i) {
01003       lib3ds_io_write_float(io, mesh->map_data.pos[i]);
01004     }
01005     lib3ds_io_write_float(io, mesh->map_data.scale);
01006 
01007     for (i=0; i<4; i++) {
01008       for (j=0; j<3; j++) {
01009         lib3ds_io_write_float(io, mesh->map_data.matrix[i][j]);
01010       }
01011     }
01012     for (i=0; i<2; ++i) {
01013       lib3ds_io_write_float(io, mesh->map_data.planar_size[i]);
01014     }
01015     lib3ds_io_write_float(io, mesh->map_data.cylinder_height);
01016   }
01017 
01018   if (!flag_array_write(mesh, io)) {
01019     return(LIB3DS_FALSE);
01020   }
01021   { /*---- LIB3DS_MESH_MATRIX ----*/
01022     Lib3dsChunk c;
01023     int i,j;
01024 
01025     c.chunk=LIB3DS_MESH_MATRIX;
01026     c.size=54;
01027     if (!lib3ds_chunk_write(&c,io)) {
01028       return(LIB3DS_FALSE);
01029     }
01030     for (i=0; i<4; i++) {
01031       for (j=0; j<3; j++) {
01032         lib3ds_io_write_float(io, mesh->matrix[i][j]);
01033       }
01034     }
01035   }
01036 
01037   if (mesh->color) { /*---- LIB3DS_MESH_COLOR ----*/
01038     Lib3dsChunk c;
01039     
01040     c.chunk=LIB3DS_MESH_COLOR;
01041     c.size=7;
01042     if (!lib3ds_chunk_write(&c,io)) {
01043       return(LIB3DS_FALSE);
01044     }
01045     lib3ds_io_write_byte(io, mesh->color);
01046   }
01047   if (!face_array_write(mesh, io)) {
01048     return(LIB3DS_FALSE);
01049   }
01050 
01051   if (!lib3ds_chunk_write_end(&c,io)) {
01052     return(LIB3DS_FALSE);
01053   }
01054   return(LIB3DS_TRUE);
01055 }
01056 

Hosted by
SourceForge.net Logo
Generated at Wed Jun 20 18:51:36 2007 by Doxygen 1.5.2