00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
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
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
00747
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
00794
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 {
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 {
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 {
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) {
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 {
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) {
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