Files
OpenSceneGraph/src/osgPlugins/3ds/mesh.cpp
Robert Osfield f5cf560fe1 Renamed the follow plugins to facilitate CMake build
lib3ds -> 3ds
ac3d -> ac
directx -> x
ESRIShape -> shp
2007-03-11 13:23:06 +00:00

968 lines
21 KiB
C++

/*
* The 3D Studio File Format Library
* Copyright (C) 1996-2001 by J.E. Hoffmann <je-h@gmx.net>
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Id$
*/
#define LIB3DS_EXPORT
#include "mesh.h"
#include "readwrite.h"
#include "chunk.h"
#include "vector.h"
#include "matrix.h"
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "config.h"
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif
/*!
* \defgroup mesh Meshes
*
* \author J.E. Hoffmann <je-h@gmx.net>
*/
static Lib3dsBool
face_array_read(Lib3dsMesh *mesh, FILE *f)
{
Lib3dsChunk c;
Lib3dsWord chunk;
int i;
int faces;
if (!lib3ds_chunk_read_start(&c, LIB3DS_FACE_ARRAY, f)) {
return(LIB3DS_FALSE);
}
lib3ds_mesh_free_face_list(mesh);
faces=lib3ds_word_read(f);
if (faces) {
if (!lib3ds_mesh_new_face_list(mesh, faces)) {
LIB3DS_ERROR_LOG;
return(LIB3DS_FALSE);
}
for (i=0; i<faces; ++i) {
strcpy(mesh->faceL[i].material, "");
mesh->faceL[i].points[0]=lib3ds_word_read(f);
mesh->faceL[i].points[1]=lib3ds_word_read(f);
mesh->faceL[i].points[2]=lib3ds_word_read(f);
mesh->faceL[i].flags=lib3ds_word_read(f);
}
lib3ds_chunk_read_tell(&c, f);
while ((chunk=lib3ds_chunk_read_next(&c, f))!=0) {
switch (chunk) {
case LIB3DS_SMOOTH_GROUP:
{
unsigned i;
for (i=0; i<mesh->faces; ++i) {
mesh->faceL[i].smoothing=lib3ds_dword_read(f);
}
}
break;
case LIB3DS_MSH_MAT_GROUP:
{
char name[64];
unsigned faces;
unsigned i;
unsigned index;
if (!lib3ds_string_read(name, 64, f)) {
return(LIB3DS_FALSE);
}
faces=lib3ds_word_read(f);
for (i=0; i<faces; ++i) {
index=lib3ds_word_read(f);
ASSERT(index<mesh->faces);
strcpy(mesh->faceL[index].material, name);
}
}
break;
case LIB3DS_MSH_BOXMAP:
{
char name[64];
if (!lib3ds_string_read(name, 64, f)) {
return(LIB3DS_FALSE);
}
strcpy(mesh->box_map.front, name);
if (!lib3ds_string_read(name, 64, f)) {
return(LIB3DS_FALSE);
}
strcpy(mesh->box_map.back, name);
if (!lib3ds_string_read(name, 64, f)) {
return(LIB3DS_FALSE);
}
strcpy(mesh->box_map.left, name);
if (!lib3ds_string_read(name, 64, f)) {
return(LIB3DS_FALSE);
}
strcpy(mesh->box_map.right, name);
if (!lib3ds_string_read(name, 64, f)) {
return(LIB3DS_FALSE);
}
strcpy(mesh->box_map.top, name);
if (!lib3ds_string_read(name, 64, f)) {
return(LIB3DS_FALSE);
}
strcpy(mesh->box_map.bottom, name);
}
break;
default:
lib3ds_chunk_unknown(chunk);
}
}
}
lib3ds_chunk_read_end(&c, f);
return(LIB3DS_TRUE);
}
/*!
* \ingroup mesh
*/
Lib3dsMesh*
lib3ds_mesh_new(const char *name)
{
Lib3dsMesh *mesh;
ASSERT(name);
ASSERT(strlen(name)<64);
mesh=(Lib3dsMesh*)calloc(sizeof(Lib3dsMesh), 1);
if (!mesh) {
return(0);
}
strcpy(mesh->name, name);
lib3ds_matrix_identity(mesh->matrix);
mesh->map_data.maptype=LIB3DS_MAP_NONE;
return(mesh);
}
/*!
* \ingroup mesh
*/
void
lib3ds_mesh_free(Lib3dsMesh *mesh)
{
lib3ds_mesh_free_point_list(mesh);
lib3ds_mesh_free_flag_list(mesh);
lib3ds_mesh_free_texel_list(mesh);
lib3ds_mesh_free_face_list(mesh);
memset(mesh, 0, sizeof(Lib3dsMesh));
free(mesh);
}
/*!
* \ingroup mesh
*/
Lib3dsBool
lib3ds_mesh_new_point_list(Lib3dsMesh *mesh, Lib3dsDword points)
{
ASSERT(mesh);
if (mesh->pointL) {
ASSERT(mesh->points);
lib3ds_mesh_free_point_list(mesh);
}
ASSERT(!mesh->pointL && !mesh->points);
mesh->points=0;
mesh->pointL=(Lib3dsPoint*)calloc(sizeof(Lib3dsPoint)*points,1);
if (!mesh->pointL) {
LIB3DS_ERROR_LOG;
return(LIB3DS_FALSE);
}
mesh->points=points;
return(LIB3DS_TRUE);
}
/*!
* \ingroup mesh
*/
void
lib3ds_mesh_free_point_list(Lib3dsMesh *mesh)
{
ASSERT(mesh);
if (mesh->pointL) {
ASSERT(mesh->points);
free(mesh->pointL);
mesh->pointL=0;
mesh->points=0;
}
else {
ASSERT(!mesh->points);
}
}
/*!
* \ingroup mesh
*/
Lib3dsBool
lib3ds_mesh_new_flag_list(Lib3dsMesh *mesh, Lib3dsDword flags)
{
ASSERT(mesh);
if (mesh->flagL) {
ASSERT(mesh->flags);
lib3ds_mesh_free_flag_list(mesh);
}
ASSERT(!mesh->flagL && !mesh->flags);
mesh->flags=0;
mesh->flagL=(Lib3dsWord*)calloc(sizeof(Lib3dsWord)*flags,1);
if (!mesh->flagL) {
LIB3DS_ERROR_LOG;
return(LIB3DS_FALSE);
}
mesh->flags=flags;
return(LIB3DS_TRUE);
}
/*!
* \ingroup mesh
*/
void
lib3ds_mesh_free_flag_list(Lib3dsMesh *mesh)
{
ASSERT(mesh);
if (mesh->flagL) {
ASSERT(mesh->flags);
free(mesh->flagL);
mesh->flagL=0;
mesh->flags=0;
}
else {
ASSERT(!mesh->flags);
}
}
/*!
* \ingroup mesh
*/
Lib3dsBool
lib3ds_mesh_new_texel_list(Lib3dsMesh *mesh, Lib3dsDword texels)
{
ASSERT(mesh);
if (mesh->texelL) {
ASSERT(mesh->texels);
lib3ds_mesh_free_texel_list(mesh);
}
ASSERT(!mesh->texelL && !mesh->texels);
mesh->texels=0;
mesh->texelL=(Lib3dsTexel*) calloc(sizeof(Lib3dsTexel)*texels,1);
if (!mesh->texelL) {
LIB3DS_ERROR_LOG;
return(LIB3DS_FALSE);
}
mesh->texels=texels;
return(LIB3DS_TRUE);
}
/*!
* \ingroup mesh
*/
void
lib3ds_mesh_free_texel_list(Lib3dsMesh *mesh)
{
ASSERT(mesh);
if (mesh->texelL) {
ASSERT(mesh->texels);
free(mesh->texelL);
mesh->texelL=0;
mesh->texels=0;
}
else {
ASSERT(!mesh->texels);
}
}
/*!
* \ingroup mesh
*/
Lib3dsBool
lib3ds_mesh_new_face_list(Lib3dsMesh *mesh, Lib3dsDword faces)
{
ASSERT(mesh);
if (mesh->faceL) {
ASSERT(mesh->faces);
lib3ds_mesh_free_face_list(mesh);
}
ASSERT(!mesh->faceL && !mesh->faces);
mesh->faces=0;
mesh->faceL=(Lib3dsFace*)calloc(sizeof(Lib3dsFace)*faces,1);
if (!mesh->faceL) {
LIB3DS_ERROR_LOG;
return(LIB3DS_FALSE);
}
mesh->faces=faces;
return(LIB3DS_TRUE);
}
/*!
* \ingroup mesh
*/
void
lib3ds_mesh_free_face_list(Lib3dsMesh *mesh)
{
ASSERT(mesh);
if (mesh->faceL) {
ASSERT(mesh->faces);
free(mesh->faceL);
mesh->faceL=0;
mesh->faces=0;
}
else {
ASSERT(!mesh->faces);
}
}
typedef struct _Lib3dsFaces Lib3dsFaces;
struct _Lib3dsFaces {
Lib3dsFaces *next;
Lib3dsFace *face;
};
/*!
* \ingroup mesh
*/
void
lib3ds_mesh_bounding_box(Lib3dsMesh *mesh, Lib3dsVector min, Lib3dsVector max)
{
unsigned i,j;
Lib3dsFloat v;
if (!mesh->points) {
lib3ds_vector_zero(min);
lib3ds_vector_zero(max);
return;
}
lib3ds_vector_copy(min, mesh->pointL[0].pos);
lib3ds_vector_copy(max, mesh->pointL[0].pos);
for (i=1; i<mesh->points; ++i) {
for (j=0; j<3; ++j) {
v=mesh->pointL[i].pos[j];
if (v<min[j]) {
min[j]=v;
}
if (v>max[j]) {
max[j]=v;
}
}
};
}
/*!
* Calculates the vertex normals corresponding to the smoothing group
* settings for each face of a mesh.
*
* \param mesh A pointer to the mesh to calculate the normals for.
* \param normalL A pointer to a buffer to store the calculated
* normals. The buffer must have the size:
* 3*sizeof(Lib3dsVector)*mesh->faces.
*
* To allocate the normal buffer do for example the following:
* \code
* Lib3dsVector *normalL = malloc(3*sizeof(Lib3dsVector)*mesh->faces);
* \endcode
*
* To access the normal of the i-th vertex of the j-th face do the
* following:
* \code
* normalL[3*j+i]
* \endcode
*/
void
lib3ds_mesh_calculate_normals(Lib3dsMesh *mesh, Lib3dsVector *normalL)
{
Lib3dsFaces **fl;
Lib3dsFaces *fa;
unsigned i,j,k;
if (!mesh->faces) {
return;
}
fl=(Lib3dsFaces**)calloc(sizeof(Lib3dsFaces*),mesh->points);
ASSERT(fl);
fa=(Lib3dsFaces*)calloc(sizeof(Lib3dsFaces),3*mesh->faces);
ASSERT(fa);
k=0;
for (i=0; i<mesh->faces; ++i) {
Lib3dsFace *f=&mesh->faceL[i];
for (j=0; j<3; ++j) {
Lib3dsFaces* l=&fa[k++];
ASSERT(f->points[j]<mesh->points);
l->face=f;
l->next=fl[f->points[j]];
fl[f->points[j]]=l;
}
}
for (i=0; i<mesh->faces; ++i) {
Lib3dsFace *f=&mesh->faceL[i];
for (j=0; j<3; ++j) {
Lib3dsVector n,N[32];
Lib3dsFaces *p;
int k,l;
int found;
ASSERT(f->points[j]<mesh->points);
if (f->smoothing) {
lib3ds_vector_zero(n);
k=0;
for (p=fl[f->points[j]]; p; p=p->next) {
found=0;
for (l=0; l<k; ++l) {
if (fabs(lib3ds_vector_dot(N[l], p->face->normal)-1.0)<1e-5) {
found=1;
break;
}
}
if (!found) {
if (f->smoothing & p->face->smoothing) {
lib3ds_vector_add(n,n, p->face->normal);
lib3ds_vector_copy(N[k], p->face->normal);
++k;
}
}
}
}
else {
lib3ds_vector_copy(n, f->normal);
}
lib3ds_vector_normalize(n);
lib3ds_vector_copy(normalL[3*i+j], n);
}
}
free(fa);
free(fl);
}
/*!
* This function prints data associated with the specified mesh such as
* vertex and point lists.
*
* \param mesh Points to a mesh that you wish to view the data for.
*
* \return None
*
* \warning WIN32: Should only be used in a console window not in a GUI.
*
* \ingroup mesh
*/
void
lib3ds_mesh_dump(Lib3dsMesh *mesh)
{
unsigned i;
Lib3dsVector p;
ASSERT(mesh);
printf(" %s vertices=%d faces=%d\n",
mesh->name,
mesh->points,
mesh->faces
);
printf(" matrix:\n");
lib3ds_matrix_dump(mesh->matrix);
printf(" point list:\n");
for (i=0; i<mesh->points; ++i) {
lib3ds_vector_copy(p, mesh->pointL[i].pos);
printf (" %8f %8f %8f\n", p[0], p[1], p[2]);
}
printf(" facelist:\n");
for (i=0; i<mesh->points; ++i) {
printf (" %4d %4d %4d smoothing:%X\n",
mesh->faceL[i].points[0],
mesh->faceL[i].points[1],
mesh->faceL[i].points[2],
static_cast<int>(mesh->faceL[i].smoothing)
);
}
}
/*!
* \ingroup mesh
*/
Lib3dsBool
lib3ds_mesh_read(Lib3dsMesh *mesh, FILE *f)
{
Lib3dsChunk c;
Lib3dsWord chunk;
if (!lib3ds_chunk_read_start(&c, LIB3DS_N_TRI_OBJECT, f)) {
return(LIB3DS_FALSE);
}
while ((chunk=lib3ds_chunk_read_next(&c, f))!=0) {
switch (chunk) {
case LIB3DS_MESH_MATRIX:
{
int i,j;
lib3ds_matrix_identity(mesh->matrix);
for (i=0; i<4; i++) {
for (j=0; j<3; j++) {
mesh->matrix[i][j]=lib3ds_float_read(f);
}
}
}
break;
case LIB3DS_MESH_COLOR:
{
mesh->color=lib3ds_byte_read(f);
}
break;
case LIB3DS_POINT_ARRAY:
{
unsigned i,j;
unsigned points;
lib3ds_mesh_free_point_list(mesh);
points=lib3ds_word_read(f);
if (points) {
if (!lib3ds_mesh_new_point_list(mesh, points)) {
LIB3DS_ERROR_LOG;
return(LIB3DS_FALSE);
}
for (i=0; i<mesh->points; ++i) {
for (j=0; j<3; ++j) {
mesh->pointL[i].pos[j]=lib3ds_float_read(f);
}
}
ASSERT((!mesh->flags) || (mesh->points==mesh->flags));
ASSERT((!mesh->texels) || (mesh->points==mesh->texels));
}
}
break;
case LIB3DS_POINT_FLAG_ARRAY:
{
unsigned i;
unsigned flags;
lib3ds_mesh_free_flag_list(mesh);
flags=lib3ds_word_read(f);
if (flags) {
if (!lib3ds_mesh_new_flag_list(mesh, flags)) {
LIB3DS_ERROR_LOG;
return(LIB3DS_FALSE);
}
for (i=0; i<mesh->flags; ++i) {
mesh->flagL[i]=lib3ds_word_read(f);
}
ASSERT((!mesh->points) || (mesh->flags==mesh->points));
ASSERT((!mesh->texels) || (mesh->flags==mesh->texels));
}
}
break;
case LIB3DS_FACE_ARRAY:
{
lib3ds_chunk_read_reset(&c, f);
if (!face_array_read(mesh, f)) {
return(LIB3DS_FALSE);
}
}
break;
case LIB3DS_MESH_TEXTURE_INFO:
{
int i,j;
for (i=0; i<2; ++i) {
mesh->map_data.tile[i]=lib3ds_float_read(f);
}
for (i=0; i<3; ++i) {
mesh->map_data.pos[i]=lib3ds_float_read(f);
}
mesh->map_data.scale=lib3ds_float_read(f);
lib3ds_matrix_identity(mesh->map_data.matrix);
for (i=0; i<4; i++) {
for (j=0; j<3; j++) {
mesh->map_data.matrix[i][j]=lib3ds_float_read(f);
}
}
for (i=0; i<2; ++i) {
mesh->map_data.planar_size[i]=lib3ds_float_read(f);
}
mesh->map_data.cylinder_height=lib3ds_float_read(f);
}
break;
case LIB3DS_TEX_VERTS:
{
unsigned i;
unsigned texels;
lib3ds_mesh_free_texel_list(mesh);
texels=lib3ds_word_read(f);
if (texels) {
if (!lib3ds_mesh_new_texel_list(mesh, texels)) {
LIB3DS_ERROR_LOG;
return(LIB3DS_FALSE);
}
for (i=0; i<mesh->texels; ++i) {
mesh->texelL[i][0]=lib3ds_float_read(f);
mesh->texelL[i][1]=lib3ds_float_read(f);
}
ASSERT((!mesh->points) || (mesh->texels==mesh->points));
ASSERT((!mesh->flags) || (mesh->texels==mesh->flags));
}
}
break;
default:
lib3ds_chunk_unknown(chunk);
}
}
{
unsigned j;
for (j=0; j<mesh->faces; ++j) {
ASSERT(mesh->faceL[j].points[0]<mesh->points);
ASSERT(mesh->faceL[j].points[1]<mesh->points);
ASSERT(mesh->faceL[j].points[2]<mesh->points);
lib3ds_vector_normal(
mesh->faceL[j].normal,
mesh->pointL[mesh->faceL[j].points[0]].pos,
mesh->pointL[mesh->faceL[j].points[1]].pos,
mesh->pointL[mesh->faceL[j].points[2]].pos
);
}
}
lib3ds_chunk_read_end(&c, f);
return(LIB3DS_TRUE);
}
static Lib3dsBool
point_array_write(Lib3dsMesh *mesh, FILE *f)
{
Lib3dsChunk c;
unsigned i;
if (!mesh->points || !mesh->pointL) {
return(LIB3DS_TRUE);
}
ASSERT(mesh->points<0x10000);
c.chunk=LIB3DS_POINT_ARRAY;
c.size=8+12*mesh->points;
lib3ds_chunk_write(&c, f);
lib3ds_word_write((Lib3dsWord)mesh->points, f);
for (i=0; i<mesh->points; ++i) {
lib3ds_vector_write(mesh->pointL[i].pos, f);
}
return(LIB3DS_TRUE);
}
static Lib3dsBool
flag_array_write(Lib3dsMesh *mesh, FILE *f)
{
Lib3dsChunk c;
unsigned i;
if (!mesh->flags || !mesh->flagL) {
return(LIB3DS_TRUE);
}
ASSERT(mesh->flags<0x10000);
c.chunk=LIB3DS_POINT_FLAG_ARRAY;
c.size=8+2*mesh->flags;
lib3ds_chunk_write(&c, f);
lib3ds_word_write((Lib3dsWord)mesh->flags, f);
for (i=0; i<mesh->flags; ++i) {
lib3ds_word_write(mesh->flagL[i], f);
}
return(LIB3DS_TRUE);
}
static Lib3dsBool
face_array_write(Lib3dsMesh *mesh, FILE *f)
{
Lib3dsChunk c;
if (!mesh->faces || !mesh->faceL) {
return(LIB3DS_TRUE);
}
ASSERT(mesh->faces<0x10000);
c.chunk=LIB3DS_FACE_ARRAY;
if (!lib3ds_chunk_write_start(&c, f)) {
return(LIB3DS_FALSE);
}
{
unsigned i;
lib3ds_word_write((Lib3dsWord)mesh->faces, f);
for (i=0; i<mesh->faces; ++i) {
lib3ds_word_write(mesh->faceL[i].points[0], f);
lib3ds_word_write(mesh->faceL[i].points[1], f);
lib3ds_word_write(mesh->faceL[i].points[2], f);
lib3ds_word_write(mesh->faceL[i].flags, f);
}
}
{ /*---- MSH_MAT_GROUP ----*/
Lib3dsChunk c;
unsigned i,j;
Lib3dsWord num;
char *matf=(char*)calloc(sizeof(char), mesh->faces);
if (!matf) {
return(LIB3DS_FALSE);
}
for (i=0; i<mesh->faces; ++i) {
if (!matf[i] && strlen(mesh->faceL[i].material)) {
matf[i]=1;
num=1;
for (j=i+1; j<mesh->faces; ++j) {
if (strcmp(mesh->faceL[i].material, mesh->faceL[j].material)==0) ++num;
}
c.chunk=LIB3DS_MSH_MAT_GROUP;
c.size=6+ strlen(mesh->faceL[i].material)+1 +2+2*num;
lib3ds_chunk_write(&c, f);
lib3ds_string_write(mesh->faceL[i].material, f);
lib3ds_word_write(num, f);
lib3ds_word_write((Lib3dsWord)i, f);
for (j=i+1; j<mesh->faces; ++j) {
if (strcmp(mesh->faceL[i].material, mesh->faceL[j].material)==0) {
lib3ds_word_write((Lib3dsWord)j, f);
matf[j]=1;
}
}
}
}
free(matf);
}
{ /*---- SMOOTH_GROUP ----*/
Lib3dsChunk c;
unsigned i;
c.chunk=LIB3DS_SMOOTH_GROUP;
c.size=6+4*mesh->faces;
lib3ds_chunk_write(&c, f);
for (i=0; i<mesh->faces; ++i) {
lib3ds_dword_write(mesh->faceL[i].smoothing, f);
}
}
{ /*---- MSH_BOXMAP ----*/
Lib3dsChunk c;
if (strlen(mesh->box_map.front) ||
strlen(mesh->box_map.back) ||
strlen(mesh->box_map.left) ||
strlen(mesh->box_map.right) ||
strlen(mesh->box_map.top) ||
strlen(mesh->box_map.bottom)) {
c.chunk=LIB3DS_MSH_BOXMAP;
if (!lib3ds_chunk_write_start(&c, f)) {
return(LIB3DS_FALSE);
}
lib3ds_string_write(mesh->box_map.front, f);
lib3ds_string_write(mesh->box_map.back, f);
lib3ds_string_write(mesh->box_map.left, f);
lib3ds_string_write(mesh->box_map.right, f);
lib3ds_string_write(mesh->box_map.top, f);
lib3ds_string_write(mesh->box_map.bottom, f);
if (!lib3ds_chunk_write_end(&c, f)) {
return(LIB3DS_FALSE);
}
}
}
if (!lib3ds_chunk_write_end(&c, f)) {
return(LIB3DS_FALSE);
}
return(LIB3DS_TRUE);
}
static Lib3dsBool
texel_array_write(Lib3dsMesh *mesh, FILE *f)
{
Lib3dsChunk c;
unsigned i;
if (!mesh->texels || !mesh->texelL) {
return(LIB3DS_TRUE);
}
ASSERT(mesh->texels<0x10000);
c.chunk=LIB3DS_TEX_VERTS;
c.size=8+8*mesh->texels;
lib3ds_chunk_write(&c, f);
lib3ds_word_write((Lib3dsWord)mesh->texels, f);
for (i=0; i<mesh->texels; ++i) {
lib3ds_float_write(mesh->texelL[i][0], f);
lib3ds_float_write(mesh->texelL[i][1], f);
}
return(LIB3DS_TRUE);
}
/*!
* \ingroup mesh
*/
Lib3dsBool
lib3ds_mesh_write(Lib3dsMesh *mesh, FILE *f)
{
Lib3dsChunk c;
c.chunk=LIB3DS_N_TRI_OBJECT;
if (!lib3ds_chunk_write_start(&c,f)) {
return(LIB3DS_FALSE);
}
if (!point_array_write(mesh, f)) {
return(LIB3DS_FALSE);
}
if (!texel_array_write(mesh, f)) {
return(LIB3DS_FALSE);
}
if (mesh->map_data.maptype!=LIB3DS_MAP_NONE) { /*---- LIB3DS_MESH_TEXTURE_INFO ----*/
Lib3dsChunk c;
int i,j;
c.chunk=LIB3DS_MESH_TEXTURE_INFO;
c.size=92;
if (!lib3ds_chunk_write(&c,f)) {
return(LIB3DS_FALSE);
}
lib3ds_word_write(mesh->map_data.maptype, f);
for (i=0; i<2; ++i) {
lib3ds_float_write(mesh->map_data.tile[i], f);
}
for (i=0; i<3; ++i) {
lib3ds_float_write(mesh->map_data.pos[i], f);
}
lib3ds_float_write(mesh->map_data.scale, f);
for (i=0; i<4; i++) {
for (j=0; j<3; j++) {
lib3ds_float_write(mesh->map_data.matrix[i][j], f);
}
}
for (i=0; i<2; ++i) {
lib3ds_float_write(mesh->map_data.planar_size[i], f);
}
lib3ds_float_write(mesh->map_data.cylinder_height, f);
}
if (!flag_array_write(mesh, f)) {
return(LIB3DS_FALSE);
}
{ /*---- LIB3DS_MESH_MATRIX ----*/
Lib3dsChunk c;
int i,j;
c.chunk=LIB3DS_MESH_MATRIX;
c.size=54;
if (!lib3ds_chunk_write(&c,f)) {
return(LIB3DS_FALSE);
}
for (i=0; i<4; i++) {
for (j=0; j<3; j++) {
lib3ds_float_write(mesh->matrix[i][j], f);
}
}
}
if (mesh->color) { /*---- LIB3DS_MESH_COLOR ----*/
Lib3dsChunk c;
c.chunk=LIB3DS_MESH_COLOR;
c.size=7;
if (!lib3ds_chunk_write(&c,f)) {
return(LIB3DS_FALSE);
}
lib3ds_byte_write(mesh->color, f);
}
if (!face_array_write(mesh, f)) {
return(LIB3DS_FALSE);
}
if (!lib3ds_chunk_write_end(&c,f)) {
return(LIB3DS_FALSE);
}
return(LIB3DS_TRUE);
}
/*!
\typedef Lib3dsFace
\ingroup mesh
\sa _Lib3dsFace
*/
/*!
\typedef Lib3dsBoxMap
\ingroup mesh
\sa _Lib3dsBoxMap
*/
/*!
\typedef Lib3dsMapData
\ingroup mesh
\sa _Lib3dsMapData
*/
/*!
\typedef Lib3dsMesh
\ingroup mesh
\sa _Lib3dsMesh
*/