diff options
Diffstat (limited to '3rdparty/lib3ds')
42 files changed, 13779 insertions, 0 deletions
diff --git a/3rdparty/lib3ds/README b/3rdparty/lib3ds/README new file mode 100644 index 000000000..71722ce8c --- /dev/null +++ b/3rdparty/lib3ds/README @@ -0,0 +1,15 @@ + +Lib3ds is a free toolkit for handling the "3DS" format for 3D model files. +Its main goal is to simplify the creation of 3DS import and export filters. + +This project is not related in any form to Autodesk Inc. The library is +based on unofficial information about the 3DS format found on the web. + +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. + +The official Lib3ds Homepage can be found under: + http://lib3ds.sourceforge.net + diff --git a/3rdparty/lib3ds/atmosphere.c b/3rdparty/lib3ds/atmosphere.c new file mode 100644 index 000000000..3e51f9d43 --- /dev/null +++ b/3rdparty/lib3ds/atmosphere.c @@ -0,0 +1,296 @@ +/* + * The 3D Studio File Format Library + * Copyright (C) 1996-2007 by Jan Eric Kyprianidis <www.kyprianidis.com> + * 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: atmosphere.c,v 1.12 2007/06/20 17:04:08 jeh Exp $ + */ +#include <lib3ds/atmosphere.h> +#include <lib3ds/chunk.h> +#include <lib3ds/io.h> + + +/*! + * \defgroup atmosphere Atmosphere Settings + */ + + +static Lib3dsBool +fog_read(Lib3dsFog *fog, Lib3dsIo *io) +{ + Lib3dsChunk c; + Lib3dsWord chunk; + + if (!lib3ds_chunk_read_start(&c, LIB3DS_FOG, io)) { + return(LIB3DS_FALSE); + } + fog->near_plane = lib3ds_io_read_float(io); + fog->near_density=lib3ds_io_read_float(io); + fog->far_plane=lib3ds_io_read_float(io); + fog->far_density=lib3ds_io_read_float(io); + lib3ds_chunk_read_tell(&c, io); + + while ((chunk=lib3ds_chunk_read_next(&c, io))!=0) { + switch (chunk) { + case LIB3DS_LIN_COLOR_F: + { + int i; + for (i=0; i<3; ++i) { + fog->col[i]=lib3ds_io_read_float(io); + } + } + break; + case LIB3DS_COLOR_F: + break; + case LIB3DS_FOG_BGND: + { + fog->fog_background=LIB3DS_TRUE; + } + break; + default: + lib3ds_chunk_unknown(chunk); + } + } + + lib3ds_chunk_read_end(&c, io); + return(LIB3DS_TRUE); +} + + +static Lib3dsBool +layer_fog_read(Lib3dsLayerFog *fog, Lib3dsIo *io) +{ + Lib3dsChunk c; + Lib3dsWord chunk; + Lib3dsBool have_lin=LIB3DS_FALSE; + + if (!lib3ds_chunk_read_start(&c, LIB3DS_LAYER_FOG, io)) { + return(LIB3DS_FALSE); + } + fog->near_y=lib3ds_io_read_float(io); + fog->far_y=lib3ds_io_read_float(io); + fog->density=lib3ds_io_read_float(io); + fog->flags=lib3ds_io_read_dword(io); + lib3ds_chunk_read_tell(&c, io); + + while ((chunk=lib3ds_chunk_read_next(&c, io))!=0) { + switch (chunk) { + case LIB3DS_LIN_COLOR_F: + lib3ds_io_read_rgb(io, fog->col); + have_lin=LIB3DS_TRUE; + break; + case LIB3DS_COLOR_F: + lib3ds_io_read_rgb(io, fog->col); + break; + default: + lib3ds_chunk_unknown(chunk); + } + } + + lib3ds_chunk_read_end(&c, io); + return(LIB3DS_TRUE); +} + + +static Lib3dsBool +distance_cue_read(Lib3dsDistanceCue *cue, Lib3dsIo *io) +{ + Lib3dsChunk c; + Lib3dsWord chunk; + + if (!lib3ds_chunk_read_start(&c, LIB3DS_DISTANCE_CUE, io)) { + return(LIB3DS_FALSE); + } + cue->near_plane=lib3ds_io_read_float(io); + cue->near_dimming=lib3ds_io_read_float(io); + cue->far_plane=lib3ds_io_read_float(io); + cue->far_dimming=lib3ds_io_read_float(io); + lib3ds_chunk_read_tell(&c, io); + + while ((chunk=lib3ds_chunk_read_next(&c, io))!=0) { + switch (chunk) { + case LIB3DS_DCUE_BGND: + { + cue->cue_background=LIB3DS_TRUE; + } + break; + default: + lib3ds_chunk_unknown(chunk); + } + } + + lib3ds_chunk_read_end(&c, io); + return(LIB3DS_TRUE); +} + + +/*! + * \ingroup atmosphere + */ +Lib3dsBool +lib3ds_atmosphere_read(Lib3dsAtmosphere *atmosphere, Lib3dsIo *io) +{ + Lib3dsChunk c; + + if (!lib3ds_chunk_read(&c, io)) { + return(LIB3DS_FALSE); + } + + switch (c.chunk) { + case LIB3DS_FOG: + { + lib3ds_chunk_read_reset(&c, io); + if (!fog_read(&atmosphere->fog, io)) { + return(LIB3DS_FALSE); + } + } + break; + case LIB3DS_LAYER_FOG: + { + lib3ds_chunk_read_reset(&c, io); + if (!layer_fog_read(&atmosphere->layer_fog, io)) { + return(LIB3DS_FALSE); + } + } + break; + case LIB3DS_DISTANCE_CUE: + { + lib3ds_chunk_read_reset(&c, io); + if (!distance_cue_read(&atmosphere->dist_cue, io)) { + return(LIB3DS_FALSE); + } + } + break; + case LIB3DS_USE_FOG: + { + atmosphere->fog.use=LIB3DS_TRUE; + } + break; + case LIB3DS_USE_LAYER_FOG: + { + atmosphere->fog.use=LIB3DS_TRUE; + } + break; + case LIB3DS_USE_DISTANCE_CUE: + { + atmosphere->dist_cue.use=LIB3DS_TRUE; + } + break; + } + + return(LIB3DS_TRUE); +} + + +/*! + * \ingroup atmosphere + */ +Lib3dsBool +lib3ds_atmosphere_write(Lib3dsAtmosphere *atmosphere, Lib3dsIo *io) +{ + if (atmosphere->fog.use) { /*---- LIB3DS_FOG ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_FOG; + if (!lib3ds_chunk_write_start(&c,io)) { + return(LIB3DS_FALSE); + } + lib3ds_io_write_float(io, atmosphere->fog.near_plane); + lib3ds_io_write_float(io, atmosphere->fog.near_density); + lib3ds_io_write_float(io, atmosphere->fog.far_plane); + lib3ds_io_write_float(io, atmosphere->fog.far_density); + { + Lib3dsChunk c; + c.chunk=LIB3DS_COLOR_F; + c.size=18; + lib3ds_chunk_write(&c,io); + lib3ds_io_write_rgb(io, atmosphere->fog.col); + } + if (atmosphere->fog.fog_background) { + Lib3dsChunk c; + c.chunk=LIB3DS_FOG_BGND; + c.size=6; + lib3ds_chunk_write(&c,io); + } + if (!lib3ds_chunk_write_end(&c,io)) { + return(LIB3DS_FALSE); + } + } + + if (atmosphere->layer_fog.use) { /*---- LIB3DS_LAYER_FOG ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_LAYER_FOG; + c.size=40; + lib3ds_chunk_write(&c,io); + lib3ds_io_write_float(io, atmosphere->layer_fog.near_y); + lib3ds_io_write_float(io, atmosphere->layer_fog.far_y); + lib3ds_io_write_float(io, atmosphere->layer_fog.near_y); + lib3ds_io_write_dword(io, atmosphere->layer_fog.flags); + { + Lib3dsChunk c; + c.chunk=LIB3DS_COLOR_F; + c.size=18; + lib3ds_chunk_write(&c,io); + lib3ds_io_write_rgb(io, atmosphere->fog.col); + } + } + + if (atmosphere->dist_cue.use) { /*---- LIB3DS_DISTANCE_CUE ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_DISTANCE_CUE; + if (!lib3ds_chunk_write_start(&c,io)) { + return(LIB3DS_FALSE); + } + lib3ds_io_write_float(io, atmosphere->dist_cue.near_plane); + lib3ds_io_write_float(io, atmosphere->dist_cue.near_dimming); + lib3ds_io_write_float(io, atmosphere->dist_cue.far_plane); + lib3ds_io_write_float(io, atmosphere->dist_cue.far_dimming); + if (atmosphere->dist_cue.cue_background) { + Lib3dsChunk c; + c.chunk=LIB3DS_DCUE_BGND; + c.size=6; + lib3ds_chunk_write(&c,io); + } + if (!lib3ds_chunk_write_end(&c,io)) { + return(LIB3DS_FALSE); + } + } + + if (atmosphere->fog.use) { /*---- LIB3DS_USE_FOG ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_USE_FOG; + c.size=6; + lib3ds_chunk_write(&c,io); + } + + if (atmosphere->layer_fog.use) { /*---- LIB3DS_USE_LAYER_FOG ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_USE_LAYER_FOG; + c.size=6; + lib3ds_chunk_write(&c,io); + } + + if (atmosphere->dist_cue.use) { /*---- LIB3DS_USE_DISTANCE_CUE ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_USE_V_GRADIENT; + c.size=6; + lib3ds_chunk_write(&c,io); + } + + return(LIB3DS_TRUE); +} + + diff --git a/3rdparty/lib3ds/atmosphere.h b/3rdparty/lib3ds/atmosphere.h new file mode 100644 index 000000000..c261e7e24 --- /dev/null +++ b/3rdparty/lib3ds/atmosphere.h @@ -0,0 +1,100 @@ +/* -*- c -*- */ +#ifndef INCLUDED_LIB3DS_ATMOSPHERE_H +#define INCLUDED_LIB3DS_ATMOSPHERE_H +/* + * The 3D Studio File Format Library + * Copyright (C) 1996-2007 by Jan Eric Kyprianidis <www.kyprianidis.com> + * 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: atmosphere.h,v 1.8 2007/06/20 17:04:08 jeh Exp $ + */ + +#ifndef INCLUDED_LIB3DS_TYPES_H +#include <lib3ds/types.h> +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Fog atmosphere settings + * \ingroup atmosphere + */ +typedef struct Lib3dsFog { + Lib3dsBool use; + Lib3dsRgb col; + Lib3dsBool fog_background; + Lib3dsFloat near_plane; + Lib3dsFloat near_density; + Lib3dsFloat far_plane; + Lib3dsFloat far_density; +} Lib3dsFog; + +/** + * Layer fog atmosphere flags + * \ingroup atmosphere + */ +typedef enum Lib3dsLayerFogFlags { + LIB3DS_BOTTOM_FALL_OFF =0x00000001, + LIB3DS_TOP_FALL_OFF =0x00000002, + LIB3DS_FOG_BACKGROUND =0x00100000 +} Lib3dsLayerFogFlags; + +/** + * Layer fog atmosphere settings + * \ingroup atmosphere + */ +typedef struct Lib3dsLayerFog { + Lib3dsBool use; + Lib3dsDword flags; + Lib3dsRgb col; + Lib3dsFloat near_y; + Lib3dsFloat far_y; + Lib3dsFloat density; +} Lib3dsLayerFog; + +/** + * Distance cue atmosphere settings + * \ingroup atmosphere + */ +typedef struct Lib3dsDistanceCue { + Lib3dsBool use; + Lib3dsBool cue_background; + Lib3dsFloat near_plane; + Lib3dsFloat near_dimming; + Lib3dsFloat far_plane; + Lib3dsFloat far_dimming; +} Lib3dsDistanceCue; + +/** + * Atmosphere settings + * \ingroup atmosphere + */ +struct Lib3dsAtmosphere { + Lib3dsFog fog; + Lib3dsLayerFog layer_fog; + Lib3dsDistanceCue dist_cue; +}; + +extern LIB3DSAPI Lib3dsBool lib3ds_atmosphere_read(Lib3dsAtmosphere *atmosphere, Lib3dsIo *io); +extern LIB3DSAPI Lib3dsBool lib3ds_atmosphere_write(Lib3dsAtmosphere *atmosphere, Lib3dsIo *io); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/3rdparty/lib3ds/background.c b/3rdparty/lib3ds/background.c new file mode 100644 index 000000000..a72c554df --- /dev/null +++ b/3rdparty/lib3ds/background.c @@ -0,0 +1,255 @@ +/* + * The 3D Studio File Format Library + * Copyright (C) 1996-2007 by Jan Eric Kyprianidis <www.kyprianidis.com> + * 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: background.c,v 1.12 2007/06/20 17:04:08 jeh Exp $ + */ +#include <lib3ds/background.h> +#include <lib3ds/chunk.h> +#include <lib3ds/io.h> +#include <string.h> +#include <math.h> + + +/*! + * \defgroup background Background Settings + */ + + +static Lib3dsBool +solid_bgnd_read(Lib3dsBackground *background, Lib3dsIo *io) +{ + Lib3dsChunk c; + Lib3dsWord chunk; + Lib3dsBool have_lin=LIB3DS_FALSE; + + if (!lib3ds_chunk_read_start(&c, LIB3DS_SOLID_BGND, io)) { + return(LIB3DS_FALSE); + } + + while ((chunk=lib3ds_chunk_read_next(&c, io))!=0) { + switch (chunk) { + case LIB3DS_LIN_COLOR_F: + lib3ds_io_read_rgb(io, background->solid.col); + have_lin=LIB3DS_TRUE; + break; + case LIB3DS_COLOR_F: + lib3ds_io_read_rgb(io, background->solid.col); + break; + default: + lib3ds_chunk_unknown(chunk); + } + } + + lib3ds_chunk_read_end(&c, io); + return(LIB3DS_TRUE); +} + + +static Lib3dsBool +v_gradient_read(Lib3dsBackground *background, Lib3dsIo *io) +{ + Lib3dsChunk c; + Lib3dsWord chunk; + int index[2]; + Lib3dsRgb col[2][3]; + int have_lin=0; + + + if (!lib3ds_chunk_read_start(&c, LIB3DS_V_GRADIENT, io)) { + return(LIB3DS_FALSE); + } + background->gradient.percent=lib3ds_io_read_float(io); + lib3ds_chunk_read_tell(&c, io); + + index[0]=index[1]=0; + while ((chunk=lib3ds_chunk_read_next(&c, io))!=0) { + switch (chunk) { + case LIB3DS_COLOR_F: + lib3ds_io_read_rgb(io, col[0][index[0]]); + index[0]++; + break; + case LIB3DS_LIN_COLOR_F: + lib3ds_io_read_rgb(io, col[1][index[1]]); + index[1]++; + have_lin=1; + break; + default: + lib3ds_chunk_unknown(chunk); + } + } + { + int i; + for (i=0; i<3; ++i) { + background->gradient.top[i]=col[have_lin][0][i]; + background->gradient.middle[i]=col[have_lin][1][i]; + background->gradient.bottom[i]=col[have_lin][2][i]; + } + } + lib3ds_chunk_read_end(&c, io); + return(LIB3DS_TRUE); +} + + +/*! + * \ingroup background + */ +Lib3dsBool +lib3ds_background_read(Lib3dsBackground *background, Lib3dsIo *io) +{ + Lib3dsChunk c; + + if (!lib3ds_chunk_read(&c, io)) { + return(LIB3DS_FALSE); + } + + switch (c.chunk) { + case LIB3DS_BIT_MAP: + { + if (!lib3ds_io_read_string(io, background->bitmap.name, 64)) { + return(LIB3DS_FALSE); + } + } + break; + case LIB3DS_SOLID_BGND: + { + lib3ds_chunk_read_reset(&c, io); + if (!solid_bgnd_read(background, io)) { + return(LIB3DS_FALSE); + } + } + break; + case LIB3DS_V_GRADIENT: + { + lib3ds_chunk_read_reset(&c, io); + if (!v_gradient_read(background, io)) { + return(LIB3DS_FALSE); + } + } + break; + case LIB3DS_USE_BIT_MAP: + { + background->bitmap.use=LIB3DS_TRUE; + } + break; + case LIB3DS_USE_SOLID_BGND: + { + background->solid.use=LIB3DS_TRUE; + } + break; + case LIB3DS_USE_V_GRADIENT: + { + background->gradient.use=LIB3DS_TRUE; + } + break; + } + + return(LIB3DS_TRUE); +} + + +static Lib3dsBool +colorf_write(Lib3dsRgba rgb, Lib3dsIo *io) +{ + Lib3dsChunk c; + + c.chunk=LIB3DS_COLOR_F; + c.size=18; + lib3ds_chunk_write(&c,io); + lib3ds_io_write_rgb(io, rgb); + + c.chunk=LIB3DS_LIN_COLOR_F; + c.size=18; + lib3ds_chunk_write(&c,io); + lib3ds_io_write_rgb(io, rgb); + return(LIB3DS_TRUE); +} + + +static Lib3dsBool +colorf_defined(Lib3dsRgba rgb) +{ + int i; + for (i=0; i<3; ++i) { + if (fabs(rgb[i])>LIB3DS_EPSILON) { + break; + } + } + return(i<3); +} + + +/*! + * \ingroup background + */ +Lib3dsBool +lib3ds_background_write(Lib3dsBackground *background, Lib3dsIo *io) +{ + if (strlen(background->bitmap.name)) { /*---- LIB3DS_BIT_MAP ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_BIT_MAP; + c.size=6+1+(Lib3dsDword)strlen(background->bitmap.name); + lib3ds_chunk_write(&c,io); + lib3ds_io_write_string(io, background->bitmap.name); + } + + if (colorf_defined(background->solid.col)) { /*---- LIB3DS_SOLID_BGND ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_SOLID_BGND; + c.size=42; + lib3ds_chunk_write(&c,io); + colorf_write(background->solid.col, io); + } + + if (colorf_defined(background->gradient.top) || + colorf_defined(background->gradient.middle) || + colorf_defined(background->gradient.bottom)) { /*---- LIB3DS_V_GRADIENT ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_V_GRADIENT; + c.size=118; + lib3ds_chunk_write(&c,io); + lib3ds_io_write_float(io, background->gradient.percent); + colorf_write(background->gradient.top,io); + colorf_write(background->gradient.middle,io); + colorf_write(background->gradient.bottom,io); + } + + if (background->bitmap.use) { /*---- LIB3DS_USE_BIT_MAP ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_USE_BIT_MAP; + c.size=6; + lib3ds_chunk_write(&c,io); + } + + if (background->solid.use) { /*---- LIB3DS_USE_SOLID_BGND ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_USE_SOLID_BGND; + c.size=6; + lib3ds_chunk_write(&c,io); + } + + if (background->gradient.use) { /*---- LIB3DS_USE_V_GRADIENT ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_USE_V_GRADIENT; + c.size=6; + lib3ds_chunk_write(&c,io); + } + + return(LIB3DS_TRUE); +} + diff --git a/3rdparty/lib3ds/background.h b/3rdparty/lib3ds/background.h new file mode 100644 index 000000000..e1083708a --- /dev/null +++ b/3rdparty/lib3ds/background.h @@ -0,0 +1,85 @@ +/* -*- c -*- */ +#ifndef INCLUDED_LIB3DS_BACKGROUND_H +#define INCLUDED_LIB3DS_BACKGROUND_H +/* + * The 3D Studio File Format Library + * Copyright (C) 1996-2007 by Jan Eric Kyprianidis <www.kyprianidis.com> + * 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: background.h,v 1.8 2007/06/20 17:04:08 jeh Exp $ + */ + +#ifndef INCLUDED_LIB3DS_TYPES_H +#include <lib3ds/types.h> +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Bitmap background settings + * \ingroup background + */ +typedef struct Lib3dsBitmap { + Lib3dsBool use; + char name[64]; +} Lib3dsBitmap; + +/** + * Solid color background settings + * \ingroup background + */ +typedef struct Lib3dsSolid { + Lib3dsBool use; + Lib3dsRgb col; +} Lib3dsSolid; + +/** + * Gradient background settings + * \ingroup background + */ +typedef struct Lib3dsGradient { + Lib3dsBool use; + Lib3dsFloat percent; + Lib3dsRgb top; + Lib3dsRgb middle; + Lib3dsRgb bottom; +} Lib3dsGradient; + +/** + * Background settings + * \ingroup background + */ +struct Lib3dsBackground { + Lib3dsBitmap bitmap; + Lib3dsSolid solid; + Lib3dsGradient gradient; +}; + +extern LIB3DSAPI Lib3dsBool lib3ds_background_read(Lib3dsBackground *background, Lib3dsIo *io); +extern LIB3DSAPI Lib3dsBool lib3ds_background_write(Lib3dsBackground *background, Lib3dsIo *io); + +#ifdef __cplusplus +} +#endif +#endif + + + + + diff --git a/3rdparty/lib3ds/camera.c b/3rdparty/lib3ds/camera.c new file mode 100644 index 000000000..7bbea0f78 --- /dev/null +++ b/3rdparty/lib3ds/camera.c @@ -0,0 +1,231 @@ +/* + * The 3D Studio File Format Library + * Copyright (C) 1996-2007 by Jan Eric Kyprianidis <www.kyprianidis.com> + * 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: camera.c,v 1.17 2007/06/20 17:04:08 jeh Exp $ + */ +#include <lib3ds/camera.h> +#include <lib3ds/chunk.h> +#include <lib3ds/io.h> +#include <stdlib.h> +#include <math.h> +#include <string.h> + + +/*! + * \defgroup camera Cameras + */ + + +/*! + * Return a new Lib3dsCamera object. + * + * Object is initialized with the given name and fov=45. All other + * values are 0. + * + * \param name Name of this camera. Must not be NULL. Must be < 64 characters. + * + * \return Lib3dsCamera object or NULL on failure. + * + * \ingroup camera + */ +Lib3dsCamera* +lib3ds_camera_new(const char *name) +{ + Lib3dsCamera *camera; + + ASSERT(name); + ASSERT(strlen(name)<64); + + camera=(Lib3dsCamera*)calloc(sizeof(Lib3dsCamera), 1); + if (!camera) { + return(0); + } + strcpy(camera->name, name); + camera->fov=45.0f; + return(camera); +} + + +/*! + * Free a Lib3dsCamera object and all of its resources. + * + * \param camera Lib3dsCamera object to be freed. + * + * \ingroup camera + */ +void +lib3ds_camera_free(Lib3dsCamera *camera) +{ + memset(camera, 0, sizeof(Lib3dsCamera)); + free(camera); +} + + +/*! + * Dump information about a Lib3dsCamera object to stdout. + * + * \param camera Object to be dumped. + * + * \see lib3ds_file_dump_cameras + * + * \ingroup camera + */ +void +lib3ds_camera_dump(Lib3dsCamera *camera) +{ + ASSERT(camera); + printf(" name: %s\n", camera->name); + printf(" position: (%f, %f, %f)\n", + camera->position[0], camera->position[1], camera->position[2]); + printf(" target (%f, %f, %f)\n", + camera->target[0], camera->target[1], camera->target[2]); + printf(" roll: %f\n", camera->roll); + printf(" fov: %f\n", camera->fov); + printf(" see_cone: %s\n", camera->see_cone ? "yes" : "no"); + printf(" near_range: %f\n", camera->near_range); + printf(" far_range: %f\n", camera->far_range); + printf("\n"); +} + + +/*! + * Read a camera definition from a file. + * + * This function is called by lib3ds_file_read(), and you probably + * don't want to call it directly. + * + * \param camera A Lib3dsCamera to be filled in. + * \param io A Lib3dsIo object previously set up by the caller. + * + * \return LIB3DS_TRUE on success, LIB3DS_FALSE on failure. + * + * \see lib3ds_file_read + * + * \ingroup camera + */ +Lib3dsBool +lib3ds_camera_read(Lib3dsCamera *camera, Lib3dsIo *io) +{ + Lib3dsChunk c; + Lib3dsWord chunk; + + if (!lib3ds_chunk_read_start(&c, LIB3DS_N_CAMERA, io)) { + return(LIB3DS_FALSE); + } + { + int i; + for (i=0; i<3; ++i) { + camera->position[i]=lib3ds_io_read_float(io); + } + for (i=0; i<3; ++i) { + camera->target[i]=lib3ds_io_read_float(io); + } + } + camera->roll=lib3ds_io_read_float(io); + { + float s; + s=lib3ds_io_read_float(io); + if (fabs(s)<LIB3DS_EPSILON) { + camera->fov=45.0; + } + else { + camera->fov=2400.0f/s; + } + } + lib3ds_chunk_read_tell(&c, io); + + while ((chunk=lib3ds_chunk_read_next(&c, io))!=0) { + switch (chunk) { + case LIB3DS_CAM_SEE_CONE: + { + camera->see_cone=LIB3DS_TRUE; + } + break; + case LIB3DS_CAM_RANGES: + { + camera->near_range=lib3ds_io_read_float(io); + camera->far_range=lib3ds_io_read_float(io); + } + break; + default: + lib3ds_chunk_unknown(chunk); + } + } + + lib3ds_chunk_read_end(&c, io); + return(LIB3DS_TRUE); +} + + +/*! + * Write a camera definition to a file. + * + * This function is called by lib3ds_file_write(), and you probably + * don't want to call it directly. + * + * \param camera A Lib3dsCamera to be written. + * \param io A Lib3dsIo object previously set up by the caller. + * + * \return LIB3DS_TRUE on success, LIB3DS_FALSE on failure. + * + * \see lib3ds_file_write + * + * \ingroup camera + */ +Lib3dsBool +lib3ds_camera_write(Lib3dsCamera *camera, Lib3dsIo *io) +{ + Lib3dsChunk c; + + c.chunk=LIB3DS_N_CAMERA; + if (!lib3ds_chunk_write_start(&c,io)) { + return(LIB3DS_FALSE); + } + + lib3ds_io_write_vector(io, camera->position); + lib3ds_io_write_vector(io, camera->target); + lib3ds_io_write_float(io, camera->roll); + if (fabs(camera->fov)<LIB3DS_EPSILON) { + lib3ds_io_write_float(io, 2400.0f/45.0f); + } + else { + lib3ds_io_write_float(io, 2400.0f/camera->fov); + } + + if (camera->see_cone) { + Lib3dsChunk c; + c.chunk=LIB3DS_CAM_SEE_CONE; + c.size=6; + lib3ds_chunk_write(&c, io); + } + { + Lib3dsChunk c; + c.chunk=LIB3DS_CAM_RANGES; + c.size=14; + lib3ds_chunk_write(&c, io); + lib3ds_io_write_float(io, camera->near_range); + lib3ds_io_write_float(io, camera->far_range); + } + + if (!lib3ds_chunk_write_end(&c,io)) { + return(LIB3DS_FALSE); + } + return(LIB3DS_TRUE); +} + diff --git a/3rdparty/lib3ds/camera.h b/3rdparty/lib3ds/camera.h new file mode 100644 index 000000000..2d48db801 --- /dev/null +++ b/3rdparty/lib3ds/camera.h @@ -0,0 +1,61 @@ +/* -*- c -*- */ +#ifndef INCLUDED_LIB3DS_CAMERA_H +#define INCLUDED_LIB3DS_CAMERA_H +/* + * The 3D Studio File Format Library + * Copyright (C) 1996-2007 by Jan Eric Kyprianidis <www.kyprianidis.com> + * 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: camera.h,v 1.11 2007/06/20 17:04:08 jeh Exp $ + */ + +#ifndef INCLUDED_LIB3DS_TYPES_H +#include <lib3ds/types.h> +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Camera object + * \ingroup camera + */ +struct Lib3dsCamera { + Lib3dsCamera *next; + char name[64]; + Lib3dsDword object_flags; /*< @see Lib3dsObjectFlags */ + Lib3dsVector position; + Lib3dsVector target; + Lib3dsFloat roll; + Lib3dsFloat fov; + Lib3dsBool see_cone; + Lib3dsFloat near_range; + Lib3dsFloat far_range; +}; + +extern LIB3DSAPI Lib3dsCamera* lib3ds_camera_new(const char *name); +extern LIB3DSAPI void lib3ds_camera_free(Lib3dsCamera *mesh); +extern LIB3DSAPI void lib3ds_camera_dump(Lib3dsCamera *camera); +extern LIB3DSAPI Lib3dsBool lib3ds_camera_read(Lib3dsCamera *camera, Lib3dsIo *io); +extern LIB3DSAPI Lib3dsBool lib3ds_camera_write(Lib3dsCamera *camera, Lib3dsIo *io); + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/3rdparty/lib3ds/chunk.c b/3rdparty/lib3ds/chunk.c new file mode 100644 index 000000000..4a3773353 --- /dev/null +++ b/3rdparty/lib3ds/chunk.c @@ -0,0 +1,320 @@ +/* + * The 3D Studio File Format Library + * Copyright (C) 1996-2007 by Jan Eric Kyprianidis <www.kyprianidis.com> + * 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: chunk.c,v 1.18 2007/06/20 17:04:08 jeh Exp $ + */ +#include <lib3ds/chunk.h> +#include <lib3ds/io.h> +#include <lib3ds/chunktable.h> +#include <string.h> +#include <stdarg.h> + + +/*#define LIB3DS_CHUNK_DEBUG*/ +/*#define LIB3DS_CHUNK_WARNING*/ + + +/*! + * \defgroup chunk Chunk Handling + */ + + +static Lib3dsBool enable_dump=LIB3DS_FALSE; +static Lib3dsBool enable_unknown=LIB3DS_FALSE; +static char lib3ds_chunk_level[128]=""; + + +static void +lib3ds_chunk_debug_enter(Lib3dsChunk *c) +{ + LIB3DS_UNUSED(c); + strcat(lib3ds_chunk_level, " "); +} + + +static void +lib3ds_chunk_debug_leave(Lib3dsChunk *c) +{ + LIB3DS_UNUSED(c); + lib3ds_chunk_level[strlen(lib3ds_chunk_level)-2]=0; +} + + +static void +lib3ds_chunk_debug_dump(Lib3dsChunk *c) +{ + if (enable_dump) { + printf("%s%s (0x%X) size=%lu\n", + lib3ds_chunk_level, + lib3ds_chunk_name(c->chunk), + c->chunk, + (unsigned long)(c->size) + ); + } +} + + +/*! + * \ingroup chunk + */ +void +lib3ds_chunk_enable_dump(Lib3dsBool enable, Lib3dsBool unknown) +{ + enable_dump=enable; + enable_unknown=unknown; +} + + +/*! + * \ingroup chunk + * + * Reads a 3d-Studio chunk header from a little endian file stream. + * + * \param c The chunk to store the data. + * \param io The file stream. + * + * \return True on success, False otherwise. + */ +Lib3dsBool +lib3ds_chunk_read(Lib3dsChunk *c, Lib3dsIo *io) +{ + ASSERT(c); + ASSERT(io); + c->cur=lib3ds_io_tell(io); + c->chunk=lib3ds_io_read_word(io); + c->size=lib3ds_io_read_dword(io); + c->end=c->cur+c->size; + c->cur+=6; + if (lib3ds_io_error(io) || (c->size<6)) { + return(LIB3DS_FALSE); + } + return(LIB3DS_TRUE); + +} + + +/*! + * \ingroup chunk + */ +Lib3dsBool +lib3ds_chunk_read_start(Lib3dsChunk *c, Lib3dsWord chunk, Lib3dsIo *io) +{ + ASSERT(c); + ASSERT(io); + if (!lib3ds_chunk_read(c, io)) { + return(LIB3DS_FALSE); + } + lib3ds_chunk_debug_enter(c); + return((chunk==0) || (c->chunk==chunk)); +} + + +/*! + * \ingroup chunk + */ +void +lib3ds_chunk_read_tell(Lib3dsChunk *c, Lib3dsIo *io) +{ + c->cur=lib3ds_io_tell(io); +} + + +/*! + * \ingroup chunk + */ +Lib3dsWord +lib3ds_chunk_read_next(Lib3dsChunk *c, Lib3dsIo *io) +{ + Lib3dsChunk d; + + if (c->cur>=c->end) { + ASSERT(c->cur==c->end); + return(0); + } + + lib3ds_io_seek(io, (long)c->cur, LIB3DS_SEEK_SET); + d.chunk=lib3ds_io_read_word(io); + d.size=lib3ds_io_read_dword(io); + lib3ds_chunk_debug_dump(&d); + c->cur+=d.size; + return(d.chunk); +} + + +/*! + * \ingroup chunk + */ +void +lib3ds_chunk_read_reset(Lib3dsChunk *c, Lib3dsIo *io) +{ + LIB3DS_UNUSED(c); + lib3ds_io_seek(io, -6, LIB3DS_SEEK_CUR); +} + + +/*! + * \ingroup chunk + */ +void +lib3ds_chunk_read_end(Lib3dsChunk *c, Lib3dsIo *io) +{ + lib3ds_chunk_debug_leave(c); + lib3ds_io_seek(io, c->end, LIB3DS_SEEK_SET); +} + + +/*! + * \ingroup chunk + * + * Writes a 3d-Studio chunk header into a little endian file stream. + * + * \param c The chunk to be written. + * \param io The file stream. + * + * \return True on success, False otherwise. + */ +Lib3dsBool +lib3ds_chunk_write(Lib3dsChunk *c, Lib3dsIo *io) +{ + ASSERT(c); + if (!lib3ds_io_write_word(io, c->chunk)) { + LIB3DS_ERROR_LOG; + return(LIB3DS_FALSE); + } + if (!lib3ds_io_write_dword(io, c->size)) { + LIB3DS_ERROR_LOG; + return(LIB3DS_FALSE); + } + return(LIB3DS_TRUE); +} + + +/*! + * \ingroup chunk + */ +Lib3dsBool +lib3ds_chunk_write_start(Lib3dsChunk *c, Lib3dsIo *io) +{ + ASSERT(c); + c->size=0; + c->cur=lib3ds_io_tell(io); + if (!lib3ds_io_write_word(io, c->chunk)) { + return(LIB3DS_FALSE); + } + if (!lib3ds_io_write_dword(io, c->size)) { + return(LIB3DS_FALSE); + } + return(LIB3DS_TRUE); +} + + +/*! + * \ingroup chunk + */ +Lib3dsBool +lib3ds_chunk_write_end(Lib3dsChunk *c, Lib3dsIo *io) +{ + ASSERT(c); + c->size=lib3ds_io_tell(io) - c->cur; + lib3ds_io_seek(io, c->cur+2, LIB3DS_SEEK_SET); + if (!lib3ds_io_write_dword(io, c->size)) { + LIB3DS_ERROR_LOG; + return(LIB3DS_FALSE); + } + + c->cur+=c->size; + lib3ds_io_seek(io, c->cur, LIB3DS_SEEK_SET); + if (lib3ds_io_error(io)) { + LIB3DS_ERROR_LOG; + return(LIB3DS_FALSE); + } + return(LIB3DS_TRUE); +} + + +/*! +* \ingroup chunk +*/ +Lib3dsBool +lib3ds_chunk_write_switch(Lib3dsWord chunk, Lib3dsIo *io) +{ + Lib3dsChunk c; + c.chunk=chunk; + c.size=6; + return lib3ds_chunk_write(&c,io); +} + + +/*! + * \ingroup chunk + */ +const char* +lib3ds_chunk_name(Lib3dsWord chunk) +{ + Lib3dsChunkTable *p; + + for (p=lib3ds_chunk_table; p->name!=0; ++p) { + if (p->chunk==chunk) { + return(p->name); + } + } + return("***UNKNOWN***"); +} + + +/*! + * \ingroup chunk + */ +void +lib3ds_chunk_unknown(Lib3dsWord chunk) +{ + if (enable_unknown) { + printf("%s***WARNING*** Unknown Chunk: %s (0x%X)\n", + lib3ds_chunk_level, + lib3ds_chunk_name(chunk), + chunk + ); + } +} + + +/*! + * \ingroup chunk + */ +void +lib3ds_chunk_dump_info(const char *format, ...) +{ + if (enable_dump) { + char s[1024]; + va_list marker; + + va_start(marker, format); + vsprintf(s, format, marker); + va_end(marker); + + printf("%s%s\n", lib3ds_chunk_level, s); + } +} + + + + + + + diff --git a/3rdparty/lib3ds/chunk.h b/3rdparty/lib3ds/chunk.h new file mode 100644 index 000000000..4cbda1b8f --- /dev/null +++ b/3rdparty/lib3ds/chunk.h @@ -0,0 +1,290 @@ +/* -*- c -*- */ +#ifndef INCLUDED_LIB3DS_CHUNK_H +#define INCLUDED_LIB3DS_CHUNK_H +/* + * The 3D Studio File Format Library + * Copyright (C) 1996-2007 by Jan Eric Kyprianidis <www.kyprianidis.com> + * 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: chunk.h,v 1.16 2007/06/20 17:04:08 jeh Exp $ + */ + +#ifndef INCLUDED_LIB3DS_TYPES_H +#include <lib3ds/types.h> +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum _Lib3dsChunks { + LIB3DS_NULL_CHUNK =0x0000, + LIB3DS_M3DMAGIC =0x4D4D, /*3DS file*/ + LIB3DS_SMAGIC =0x2D2D, + LIB3DS_LMAGIC =0x2D3D, + LIB3DS_MLIBMAGIC =0x3DAA, /*MLI file*/ + LIB3DS_MATMAGIC =0x3DFF, + LIB3DS_CMAGIC =0xC23D, /*PRJ file*/ + LIB3DS_M3D_VERSION =0x0002, + LIB3DS_M3D_KFVERSION =0x0005, + + LIB3DS_COLOR_F =0x0010, + LIB3DS_COLOR_24 =0x0011, + LIB3DS_LIN_COLOR_24 =0x0012, + LIB3DS_LIN_COLOR_F =0x0013, + LIB3DS_INT_PERCENTAGE =0x0030, + LIB3DS_FLOAT_PERCENTAGE =0x0031, + + LIB3DS_MDATA =0x3D3D, + LIB3DS_MESH_VERSION =0x3D3E, + LIB3DS_MASTER_SCALE =0x0100, + LIB3DS_LO_SHADOW_BIAS =0x1400, + LIB3DS_HI_SHADOW_BIAS =0x1410, + LIB3DS_SHADOW_MAP_SIZE =0x1420, + LIB3DS_SHADOW_SAMPLES =0x1430, + LIB3DS_SHADOW_RANGE =0x1440, + LIB3DS_SHADOW_FILTER =0x1450, + LIB3DS_RAY_BIAS =0x1460, + LIB3DS_O_CONSTS =0x1500, + LIB3DS_AMBIENT_LIGHT =0x2100, + LIB3DS_BIT_MAP =0x1100, + LIB3DS_SOLID_BGND =0x1200, + LIB3DS_V_GRADIENT =0x1300, + LIB3DS_USE_BIT_MAP =0x1101, + LIB3DS_USE_SOLID_BGND =0x1201, + LIB3DS_USE_V_GRADIENT =0x1301, + LIB3DS_FOG =0x2200, + LIB3DS_FOG_BGND =0x2210, + LIB3DS_LAYER_FOG =0x2302, + LIB3DS_DISTANCE_CUE =0x2300, + LIB3DS_DCUE_BGND =0x2310, + LIB3DS_USE_FOG =0x2201, + LIB3DS_USE_LAYER_FOG =0x2303, + LIB3DS_USE_DISTANCE_CUE =0x2301, + + LIB3DS_MAT_ENTRY =0xAFFF, + LIB3DS_MAT_NAME =0xA000, + LIB3DS_MAT_AMBIENT =0xA010, + LIB3DS_MAT_DIFFUSE =0xA020, + LIB3DS_MAT_SPECULAR =0xA030, + LIB3DS_MAT_SHININESS =0xA040, + LIB3DS_MAT_SHIN2PCT =0xA041, + LIB3DS_MAT_TRANSPARENCY =0xA050, + LIB3DS_MAT_XPFALL =0xA052, + LIB3DS_MAT_USE_XPFALL =0xA240, + LIB3DS_MAT_REFBLUR =0xA053, + LIB3DS_MAT_SHADING =0xA100, + LIB3DS_MAT_USE_REFBLUR =0xA250, + LIB3DS_MAT_SELF_ILLUM =0xA080, + LIB3DS_MAT_TWO_SIDE =0xA081, + LIB3DS_MAT_DECAL =0xA082, + LIB3DS_MAT_ADDITIVE =0xA083, + LIB3DS_MAT_SELF_ILPCT =0xA084, + LIB3DS_MAT_WIRE =0xA085, + LIB3DS_MAT_FACEMAP =0xA088, + LIB3DS_MAT_PHONGSOFT =0xA08C, + LIB3DS_MAT_WIREABS =0xA08E, + LIB3DS_MAT_WIRE_SIZE =0xA087, + LIB3DS_MAT_TEXMAP =0xA200, + LIB3DS_MAT_SXP_TEXT_DATA =0xA320, + LIB3DS_MAT_TEXMASK =0xA33E, + LIB3DS_MAT_SXP_TEXTMASK_DATA =0xA32A, + LIB3DS_MAT_TEX2MAP =0xA33A, + LIB3DS_MAT_SXP_TEXT2_DATA =0xA321, + LIB3DS_MAT_TEX2MASK =0xA340, + LIB3DS_MAT_SXP_TEXT2MASK_DATA =0xA32C, + LIB3DS_MAT_OPACMAP =0xA210, + LIB3DS_MAT_SXP_OPAC_DATA =0xA322, + LIB3DS_MAT_OPACMASK =0xA342, + LIB3DS_MAT_SXP_OPACMASK_DATA =0xA32E, + LIB3DS_MAT_BUMPMAP =0xA230, + LIB3DS_MAT_SXP_BUMP_DATA =0xA324, + LIB3DS_MAT_BUMPMASK =0xA344, + LIB3DS_MAT_SXP_BUMPMASK_DATA =0xA330, + LIB3DS_MAT_SPECMAP =0xA204, + LIB3DS_MAT_SXP_SPEC_DATA =0xA325, + LIB3DS_MAT_SPECMASK =0xA348, + LIB3DS_MAT_SXP_SPECMASK_DATA =0xA332, + LIB3DS_MAT_SHINMAP =0xA33C, + LIB3DS_MAT_SXP_SHIN_DATA =0xA326, + LIB3DS_MAT_SHINMASK =0xA346, + LIB3DS_MAT_SXP_SHINMASK_DATA =0xA334, + LIB3DS_MAT_SELFIMAP =0xA33D, + LIB3DS_MAT_SXP_SELFI_DATA =0xA328, + LIB3DS_MAT_SELFIMASK =0xA34A, + LIB3DS_MAT_SXP_SELFIMASK_DATA =0xA336, + LIB3DS_MAT_REFLMAP =0xA220, + LIB3DS_MAT_REFLMASK =0xA34C, + LIB3DS_MAT_SXP_REFLMASK_DATA =0xA338, + LIB3DS_MAT_ACUBIC =0xA310, + LIB3DS_MAT_MAPNAME =0xA300, + LIB3DS_MAT_MAP_TILING =0xA351, + LIB3DS_MAT_MAP_TEXBLUR =0xA353, + LIB3DS_MAT_MAP_USCALE =0xA354, + LIB3DS_MAT_MAP_VSCALE =0xA356, + LIB3DS_MAT_MAP_UOFFSET =0xA358, + LIB3DS_MAT_MAP_VOFFSET =0xA35A, + LIB3DS_MAT_MAP_ANG =0xA35C, + LIB3DS_MAT_MAP_COL1 =0xA360, + LIB3DS_MAT_MAP_COL2 =0xA362, + LIB3DS_MAT_MAP_RCOL =0xA364, + LIB3DS_MAT_MAP_GCOL =0xA366, + LIB3DS_MAT_MAP_BCOL =0xA368, + + LIB3DS_NAMED_OBJECT =0x4000, + LIB3DS_N_DIRECT_LIGHT =0x4600, + LIB3DS_DL_OFF =0x4620, + LIB3DS_DL_OUTER_RANGE =0x465A, + LIB3DS_DL_INNER_RANGE =0x4659, + LIB3DS_DL_MULTIPLIER =0x465B, + LIB3DS_DL_EXCLUDE =0x4654, + LIB3DS_DL_ATTENUATE =0x4625, + LIB3DS_DL_SPOTLIGHT =0x4610, + LIB3DS_DL_SPOT_ROLL =0x4656, + LIB3DS_DL_SHADOWED =0x4630, + LIB3DS_DL_LOCAL_SHADOW2 =0x4641, + LIB3DS_DL_SEE_CONE =0x4650, + LIB3DS_DL_SPOT_RECTANGULAR =0x4651, + LIB3DS_DL_SPOT_ASPECT =0x4657, + LIB3DS_DL_SPOT_PROJECTOR =0x4653, + LIB3DS_DL_SPOT_OVERSHOOT =0x4652, + LIB3DS_DL_RAY_BIAS =0x4658, + LIB3DS_DL_RAYSHAD =0x4627, + LIB3DS_N_CAMERA =0x4700, + LIB3DS_CAM_SEE_CONE =0x4710, + LIB3DS_CAM_RANGES =0x4720, + LIB3DS_OBJ_HIDDEN =0x4010, + LIB3DS_OBJ_VIS_LOFTER =0x4011, + LIB3DS_OBJ_DOESNT_CAST =0x4012, + LIB3DS_OBJ_DONT_RCVSHADOW =0x4017, + LIB3DS_OBJ_MATTE =0x4013, + LIB3DS_OBJ_FAST =0x4014, + LIB3DS_OBJ_PROCEDURAL =0x4015, + LIB3DS_OBJ_FROZEN =0x4016, + LIB3DS_N_TRI_OBJECT =0x4100, + LIB3DS_POINT_ARRAY =0x4110, + LIB3DS_POINT_FLAG_ARRAY =0x4111, + LIB3DS_FACE_ARRAY =0x4120, + LIB3DS_MSH_MAT_GROUP =0x4130, + LIB3DS_SMOOTH_GROUP =0x4150, + LIB3DS_MSH_BOXMAP =0x4190, + LIB3DS_TEX_VERTS =0x4140, + LIB3DS_MESH_MATRIX =0x4160, + LIB3DS_MESH_COLOR =0x4165, + LIB3DS_MESH_TEXTURE_INFO =0x4170, + + LIB3DS_KFDATA =0xB000, + LIB3DS_KFHDR =0xB00A, + LIB3DS_KFSEG =0xB008, + LIB3DS_KFCURTIME =0xB009, + LIB3DS_AMBIENT_NODE_TAG =0xB001, + LIB3DS_OBJECT_NODE_TAG =0xB002, + LIB3DS_CAMERA_NODE_TAG =0xB003, + LIB3DS_TARGET_NODE_TAG =0xB004, + LIB3DS_LIGHT_NODE_TAG =0xB005, + LIB3DS_L_TARGET_NODE_TAG =0xB006, + LIB3DS_SPOTLIGHT_NODE_TAG =0xB007, + LIB3DS_NODE_ID =0xB030, + LIB3DS_NODE_HDR =0xB010, + LIB3DS_PIVOT =0xB013, + LIB3DS_INSTANCE_NAME =0xB011, + LIB3DS_MORPH_SMOOTH =0xB015, + LIB3DS_BOUNDBOX =0xB014, + LIB3DS_POS_TRACK_TAG =0xB020, + LIB3DS_COL_TRACK_TAG =0xB025, + LIB3DS_ROT_TRACK_TAG =0xB021, + LIB3DS_SCL_TRACK_TAG =0xB022, + LIB3DS_MORPH_TRACK_TAG =0xB026, + LIB3DS_FOV_TRACK_TAG =0xB023, + LIB3DS_ROLL_TRACK_TAG =0xB024, + LIB3DS_HOT_TRACK_TAG =0xB027, + LIB3DS_FALL_TRACK_TAG =0xB028, + LIB3DS_HIDE_TRACK_TAG =0xB029, + + LIB3DS_POLY_2D = 0x5000, + LIB3DS_SHAPE_OK = 0x5010, + LIB3DS_SHAPE_NOT_OK = 0x5011, + LIB3DS_SHAPE_HOOK = 0x5020, + LIB3DS_PATH_3D = 0x6000, + LIB3DS_PATH_MATRIX = 0x6005, + LIB3DS_SHAPE_2D = 0x6010, + LIB3DS_M_SCALE = 0x6020, + LIB3DS_M_TWIST = 0x6030, + LIB3DS_M_TEETER = 0x6040, + LIB3DS_M_FIT = 0x6050, + LIB3DS_M_BEVEL = 0x6060, + LIB3DS_XZ_CURVE = 0x6070, + LIB3DS_YZ_CURVE = 0x6080, + LIB3DS_INTERPCT = 0x6090, + LIB3DS_DEFORM_LIMIT = 0x60A0, + + LIB3DS_USE_CONTOUR = 0x6100, + LIB3DS_USE_TWEEN = 0x6110, + LIB3DS_USE_SCALE = 0x6120, + LIB3DS_USE_TWIST = 0x6130, + LIB3DS_USE_TEETER = 0x6140, + LIB3DS_USE_FIT = 0x6150, + LIB3DS_USE_BEVEL = 0x6160, + + LIB3DS_DEFAULT_VIEW = 0x3000, + LIB3DS_VIEW_TOP = 0x3010, + LIB3DS_VIEW_BOTTOM = 0x3020, + LIB3DS_VIEW_LEFT = 0x3030, + LIB3DS_VIEW_RIGHT = 0x3040, + LIB3DS_VIEW_FRONT = 0x3050, + LIB3DS_VIEW_BACK = 0x3060, + LIB3DS_VIEW_USER = 0x3070, + LIB3DS_VIEW_CAMERA = 0x3080, + LIB3DS_VIEW_WINDOW = 0x3090, + + LIB3DS_VIEWPORT_LAYOUT_OLD = 0x7000, + LIB3DS_VIEWPORT_DATA_OLD = 0x7010, + LIB3DS_VIEWPORT_LAYOUT = 0x7001, + LIB3DS_VIEWPORT_DATA = 0x7011, + LIB3DS_VIEWPORT_DATA_3 = 0x7012, + LIB3DS_VIEWPORT_SIZE = 0x7020, + LIB3DS_NETWORK_VIEW = 0x7030 +} Lib3dsChunks; + +typedef struct Lib3dsChunk { + Lib3dsWord chunk; + Lib3dsDword size; + Lib3dsDword end; + Lib3dsDword cur; +} Lib3dsChunk; + +extern LIB3DSAPI void lib3ds_chunk_enable_dump(Lib3dsBool enable, Lib3dsBool unknown); +extern LIB3DSAPI Lib3dsBool lib3ds_chunk_read(Lib3dsChunk *c, Lib3dsIo *io); +extern LIB3DSAPI Lib3dsBool lib3ds_chunk_read_start(Lib3dsChunk *c, Lib3dsWord chunk, Lib3dsIo *io); +extern LIB3DSAPI void lib3ds_chunk_read_tell(Lib3dsChunk *c, Lib3dsIo *io); +extern LIB3DSAPI Lib3dsWord lib3ds_chunk_read_next(Lib3dsChunk *c, Lib3dsIo *io); +extern LIB3DSAPI void lib3ds_chunk_read_reset(Lib3dsChunk *c, Lib3dsIo *io); +extern LIB3DSAPI void lib3ds_chunk_read_end(Lib3dsChunk *c, Lib3dsIo *io); +extern LIB3DSAPI Lib3dsBool lib3ds_chunk_write(Lib3dsChunk *c, Lib3dsIo *io); +extern LIB3DSAPI Lib3dsBool lib3ds_chunk_write_start(Lib3dsChunk *c, Lib3dsIo *io); +extern LIB3DSAPI Lib3dsBool lib3ds_chunk_write_end(Lib3dsChunk *c, Lib3dsIo *io); +extern LIB3DSAPI Lib3dsBool lib3ds_chunk_write_switch(Lib3dsWord chunk, Lib3dsIo *io); +extern LIB3DSAPI const char* lib3ds_chunk_name(Lib3dsWord chunk); +extern LIB3DSAPI void lib3ds_chunk_unknown(Lib3dsWord chunk); +extern LIB3DSAPI void lib3ds_chunk_dump_info(const char *format, ...); + +#ifdef __cplusplus +} +#endif +#endif + + diff --git a/3rdparty/lib3ds/chunktable.h b/3rdparty/lib3ds/chunktable.h new file mode 100644 index 000000000..2b50c0214 --- /dev/null +++ b/3rdparty/lib3ds/chunktable.h @@ -0,0 +1,264 @@ +/* -*- c -*- */ +#ifndef INCLUDED_LIB3DS_CHUNKTABLE_H +#define INCLUDED_LIB3DS_CHUNKTABLE_H +/* + * The 3D Studio File Format Library + * Copyright (C) 1996-2007 by Jan Eric Kyprianidis <www.kyprianidis.com> + * 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: chunktable.h,v 1.16 2007/06/20 17:04:08 jeh Exp $ + */ + +#ifndef INCLUDED_LIB3DS_CHUNK_H +#include <lib3ds/chunk.h> +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct Lib3dsChunkTable { + Lib3dsDword chunk; + const char* name; +} Lib3dsChunkTable; + +static Lib3dsChunkTable lib3ds_chunk_table[]={ + {LIB3DS_NULL_CHUNK, "LIB3DS_NULL_CHUNK"}, + {LIB3DS_M3DMAGIC, "LIB3DS_M3DMAGIC"}, + {LIB3DS_SMAGIC, "LIB3DS_SMAGIC"}, + {LIB3DS_LMAGIC, "LIB3DS_LMAGIC"}, + {LIB3DS_MLIBMAGIC, "LIB3DS_MLIBMAGIC"}, + {LIB3DS_MATMAGIC, "LIB3DS_MATMAGIC"}, + {LIB3DS_CMAGIC, "LIB3DS_CMAGIC"}, + {LIB3DS_M3D_VERSION, "LIB3DS_M3D_VERSION"}, + {LIB3DS_M3D_KFVERSION, "LIB3DS_M3D_KFVERSION"}, + {LIB3DS_COLOR_F, "LIB3DS_COLOR_F"}, + {LIB3DS_COLOR_24, "LIB3DS_COLOR_24"}, + {LIB3DS_LIN_COLOR_24, "LIB3DS_LIN_COLOR_24"}, + {LIB3DS_LIN_COLOR_F, "LIB3DS_LIN_COLOR_F"}, + {LIB3DS_INT_PERCENTAGE, "LIB3DS_INT_PERCENTAGE"}, + {LIB3DS_FLOAT_PERCENTAGE, "LIB3DS_FLOAT_PERCENTAGE"}, + {LIB3DS_MDATA, "LIB3DS_MDATA"}, + {LIB3DS_MESH_VERSION, "LIB3DS_MESH_VERSION"}, + {LIB3DS_MASTER_SCALE, "LIB3DS_MASTER_SCALE"}, + {LIB3DS_LO_SHADOW_BIAS, "LIB3DS_LO_SHADOW_BIAS"}, + {LIB3DS_HI_SHADOW_BIAS, "LIB3DS_HI_SHADOW_BIAS"}, + {LIB3DS_SHADOW_MAP_SIZE, "LIB3DS_SHADOW_MAP_SIZE"}, + {LIB3DS_SHADOW_SAMPLES, "LIB3DS_SHADOW_SAMPLES"}, + {LIB3DS_SHADOW_RANGE, "LIB3DS_SHADOW_RANGE"}, + {LIB3DS_SHADOW_FILTER, "LIB3DS_SHADOW_FILTER"}, + {LIB3DS_RAY_BIAS, "LIB3DS_RAY_BIAS"}, + {LIB3DS_O_CONSTS, "LIB3DS_O_CONSTS"}, + {LIB3DS_AMBIENT_LIGHT, "LIB3DS_AMBIENT_LIGHT"}, + {LIB3DS_BIT_MAP, "LIB3DS_BIT_MAP"}, + {LIB3DS_SOLID_BGND, "LIB3DS_SOLID_BGND"}, + {LIB3DS_V_GRADIENT, "LIB3DS_V_GRADIENT"}, + {LIB3DS_USE_BIT_MAP, "LIB3DS_USE_BIT_MAP"}, + {LIB3DS_USE_SOLID_BGND, "LIB3DS_USE_SOLID_BGND"}, + {LIB3DS_USE_V_GRADIENT, "LIB3DS_USE_V_GRADIENT"}, + {LIB3DS_FOG, "LIB3DS_FOG"}, + {LIB3DS_FOG_BGND, "LIB3DS_FOG_BGND"}, + {LIB3DS_LAYER_FOG, "LIB3DS_LAYER_FOG"}, + {LIB3DS_DISTANCE_CUE, "LIB3DS_DISTANCE_CUE"}, + {LIB3DS_DCUE_BGND, "LIB3DS_DCUE_BGND"}, + {LIB3DS_USE_FOG, "LIB3DS_USE_FOG"}, + {LIB3DS_USE_LAYER_FOG, "LIB3DS_USE_LAYER_FOG"}, + {LIB3DS_USE_DISTANCE_CUE, "LIB3DS_USE_DISTANCE_CUE"}, + {LIB3DS_MAT_ENTRY, "LIB3DS_MAT_ENTRY"}, + {LIB3DS_MAT_NAME, "LIB3DS_MAT_NAME"}, + {LIB3DS_MAT_AMBIENT, "LIB3DS_MAT_AMBIENT"}, + {LIB3DS_MAT_DIFFUSE, "LIB3DS_MAT_DIFFUSE"}, + {LIB3DS_MAT_SPECULAR, "LIB3DS_MAT_SPECULAR"}, + {LIB3DS_MAT_SHININESS, "LIB3DS_MAT_SHININESS"}, + {LIB3DS_MAT_SHIN2PCT, "LIB3DS_MAT_SHIN2PCT"}, + {LIB3DS_MAT_TRANSPARENCY, "LIB3DS_MAT_TRANSPARENCY"}, + {LIB3DS_MAT_XPFALL, "LIB3DS_MAT_XPFALL"}, + {LIB3DS_MAT_USE_XPFALL, "LIB3DS_MAT_USE_XPFALL"}, + {LIB3DS_MAT_REFBLUR, "LIB3DS_MAT_REFBLUR"}, + {LIB3DS_MAT_SHADING, "LIB3DS_MAT_SHADING"}, + {LIB3DS_MAT_USE_REFBLUR, "LIB3DS_MAT_USE_REFBLUR"}, + {LIB3DS_MAT_SELF_ILLUM, "LIB3DS_MAT_SELF_ILLUM"}, + {LIB3DS_MAT_TWO_SIDE, "LIB3DS_MAT_TWO_SIDE"}, + {LIB3DS_MAT_DECAL, "LIB3DS_MAT_DECAL"}, + {LIB3DS_MAT_ADDITIVE, "LIB3DS_MAT_ADDITIVE"}, + {LIB3DS_MAT_SELF_ILPCT, "LIB3DS_MAT_SELF_ILPCT"}, + {LIB3DS_MAT_WIRE, "LIB3DS_MAT_WIRE"}, + {LIB3DS_MAT_FACEMAP, "LIB3DS_MAT_FACEMAP"}, + {LIB3DS_MAT_PHONGSOFT, "LIB3DS_MAT_PHONGSOFT"}, + {LIB3DS_MAT_WIREABS, "LIB3DS_MAT_WIREABS"}, + {LIB3DS_MAT_WIRE_SIZE, "LIB3DS_MAT_WIRE_SIZE"}, + {LIB3DS_MAT_TEXMAP, "LIB3DS_MAT_TEXMAP"}, + {LIB3DS_MAT_SXP_TEXT_DATA, "LIB3DS_MAT_SXP_TEXT_DATA"}, + {LIB3DS_MAT_TEXMASK, "LIB3DS_MAT_TEXMASK"}, + {LIB3DS_MAT_SXP_TEXTMASK_DATA, "LIB3DS_MAT_SXP_TEXTMASK_DATA"}, + {LIB3DS_MAT_TEX2MAP, "LIB3DS_MAT_TEX2MAP"}, + {LIB3DS_MAT_SXP_TEXT2_DATA, "LIB3DS_MAT_SXP_TEXT2_DATA"}, + {LIB3DS_MAT_TEX2MASK, "LIB3DS_MAT_TEX2MASK"}, + {LIB3DS_MAT_SXP_TEXT2MASK_DATA, "LIB3DS_MAT_SXP_TEXT2MASK_DATA"}, + {LIB3DS_MAT_OPACMAP, "LIB3DS_MAT_OPACMAP"}, + {LIB3DS_MAT_SXP_OPAC_DATA, "LIB3DS_MAT_SXP_OPAC_DATA"}, + {LIB3DS_MAT_OPACMASK, "LIB3DS_MAT_OPACMASK"}, + {LIB3DS_MAT_SXP_OPACMASK_DATA, "LIB3DS_MAT_SXP_OPACMASK_DATA"}, + {LIB3DS_MAT_BUMPMAP, "LIB3DS_MAT_BUMPMAP"}, + {LIB3DS_MAT_SXP_BUMP_DATA, "LIB3DS_MAT_SXP_BUMP_DATA"}, + {LIB3DS_MAT_BUMPMASK, "LIB3DS_MAT_BUMPMASK"}, + {LIB3DS_MAT_SXP_BUMPMASK_DATA, "LIB3DS_MAT_SXP_BUMPMASK_DATA"}, + {LIB3DS_MAT_SPECMAP, "LIB3DS_MAT_SPECMAP"}, + {LIB3DS_MAT_SXP_SPEC_DATA, "LIB3DS_MAT_SXP_SPEC_DATA"}, + {LIB3DS_MAT_SPECMASK, "LIB3DS_MAT_SPECMASK"}, + {LIB3DS_MAT_SXP_SPECMASK_DATA, "LIB3DS_MAT_SXP_SPECMASK_DATA"}, + {LIB3DS_MAT_SHINMAP, "LIB3DS_MAT_SHINMAP"}, + {LIB3DS_MAT_SXP_SHIN_DATA, "LIB3DS_MAT_SXP_SHIN_DATA"}, + {LIB3DS_MAT_SHINMASK, "LIB3DS_MAT_SHINMASK"}, + {LIB3DS_MAT_SXP_SHINMASK_DATA, "LIB3DS_MAT_SXP_SHINMASK_DATA"}, + {LIB3DS_MAT_SELFIMAP, "LIB3DS_MAT_SELFIMAP"}, + {LIB3DS_MAT_SXP_SELFI_DATA, "LIB3DS_MAT_SXP_SELFI_DATA"}, + {LIB3DS_MAT_SELFIMASK, "LIB3DS_MAT_SELFIMASK"}, + {LIB3DS_MAT_SXP_SELFIMASK_DATA, "LIB3DS_MAT_SXP_SELFIMASK_DATA"}, + {LIB3DS_MAT_REFLMAP, "LIB3DS_MAT_REFLMAP"}, + {LIB3DS_MAT_REFLMASK, "LIB3DS_MAT_REFLMASK"}, + {LIB3DS_MAT_SXP_REFLMASK_DATA, "LIB3DS_MAT_SXP_REFLMASK_DATA"}, + {LIB3DS_MAT_ACUBIC, "LIB3DS_MAT_ACUBIC"}, + {LIB3DS_MAT_MAPNAME, "LIB3DS_MAT_MAPNAME"}, + {LIB3DS_MAT_MAP_TILING, "LIB3DS_MAT_MAP_TILING"}, + {LIB3DS_MAT_MAP_TEXBLUR, "LIB3DS_MAT_MAP_TEXBLUR"}, + {LIB3DS_MAT_MAP_USCALE, "LIB3DS_MAT_MAP_USCALE"}, + {LIB3DS_MAT_MAP_VSCALE, "LIB3DS_MAT_MAP_VSCALE"}, + {LIB3DS_MAT_MAP_UOFFSET, "LIB3DS_MAT_MAP_UOFFSET"}, + {LIB3DS_MAT_MAP_VOFFSET, "LIB3DS_MAT_MAP_VOFFSET"}, + {LIB3DS_MAT_MAP_ANG, "LIB3DS_MAT_MAP_ANG"}, + {LIB3DS_MAT_MAP_COL1, "LIB3DS_MAT_MAP_COL1"}, + {LIB3DS_MAT_MAP_COL2, "LIB3DS_MAT_MAP_COL2"}, + {LIB3DS_MAT_MAP_RCOL, "LIB3DS_MAT_MAP_RCOL"}, + {LIB3DS_MAT_MAP_GCOL, "LIB3DS_MAT_MAP_GCOL"}, + {LIB3DS_MAT_MAP_BCOL, "LIB3DS_MAT_MAP_BCOL"}, + {LIB3DS_NAMED_OBJECT, "LIB3DS_NAMED_OBJECT"}, + {LIB3DS_N_DIRECT_LIGHT, "LIB3DS_N_DIRECT_LIGHT"}, + {LIB3DS_DL_OFF, "LIB3DS_DL_OFF"}, + {LIB3DS_DL_OUTER_RANGE, "LIB3DS_DL_OUTER_RANGE"}, + {LIB3DS_DL_INNER_RANGE, "LIB3DS_DL_INNER_RANGE"}, + {LIB3DS_DL_MULTIPLIER, "LIB3DS_DL_MULTIPLIER"}, + {LIB3DS_DL_EXCLUDE, "LIB3DS_DL_EXCLUDE"}, + {LIB3DS_DL_ATTENUATE, "LIB3DS_DL_ATTENUATE"}, + {LIB3DS_DL_SPOTLIGHT, "LIB3DS_DL_SPOTLIGHT"}, + {LIB3DS_DL_SPOT_ROLL, "LIB3DS_DL_SPOT_ROLL"}, + {LIB3DS_DL_SHADOWED, "LIB3DS_DL_SHADOWED"}, + {LIB3DS_DL_LOCAL_SHADOW2, "LIB3DS_DL_LOCAL_SHADOW2"}, + {LIB3DS_DL_SEE_CONE, "LIB3DS_DL_SEE_CONE"}, + {LIB3DS_DL_SPOT_RECTANGULAR, "LIB3DS_DL_SPOT_RECTANGULAR"}, + {LIB3DS_DL_SPOT_ASPECT, "LIB3DS_DL_SPOT_ASPECT"}, + {LIB3DS_DL_SPOT_PROJECTOR, "LIB3DS_DL_SPOT_PROJECTOR"}, + {LIB3DS_DL_SPOT_OVERSHOOT, "LIB3DS_DL_SPOT_OVERSHOOT"}, + {LIB3DS_DL_RAY_BIAS, "LIB3DS_DL_RAY_BIAS"}, + {LIB3DS_DL_RAYSHAD, "LIB3DS_DL_RAYSHAD"}, + {LIB3DS_N_CAMERA, "LIB3DS_N_CAMERA"}, + {LIB3DS_CAM_SEE_CONE, "LIB3DS_CAM_SEE_CONE"}, + {LIB3DS_CAM_RANGES, "LIB3DS_CAM_RANGES"}, + {LIB3DS_OBJ_HIDDEN, "LIB3DS_OBJ_HIDDEN"}, + {LIB3DS_OBJ_VIS_LOFTER, "LIB3DS_OBJ_VIS_LOFTER"}, + {LIB3DS_OBJ_DOESNT_CAST, "LIB3DS_OBJ_DOESNT_CAST"}, + {LIB3DS_OBJ_DONT_RCVSHADOW, "LIB3DS_OBJ_DONT_RCVSHADOW"}, + {LIB3DS_OBJ_MATTE, "LIB3DS_OBJ_MATTE"}, + {LIB3DS_OBJ_FAST, "LIB3DS_OBJ_FAST"}, + {LIB3DS_OBJ_PROCEDURAL, "LIB3DS_OBJ_PROCEDURAL"}, + {LIB3DS_OBJ_FROZEN, "LIB3DS_OBJ_FROZEN"}, + {LIB3DS_N_TRI_OBJECT, "LIB3DS_N_TRI_OBJECT"}, + {LIB3DS_POINT_ARRAY, "LIB3DS_POINT_ARRAY"}, + {LIB3DS_POINT_FLAG_ARRAY, "LIB3DS_POINT_FLAG_ARRAY"}, + {LIB3DS_FACE_ARRAY, "LIB3DS_FACE_ARRAY"}, + {LIB3DS_MSH_MAT_GROUP, "LIB3DS_MSH_MAT_GROUP"}, + {LIB3DS_SMOOTH_GROUP, "LIB3DS_SMOOTH_GROUP"}, + {LIB3DS_MSH_BOXMAP, "LIB3DS_MSH_BOXMAP"}, + {LIB3DS_TEX_VERTS, "LIB3DS_TEX_VERTS"}, + {LIB3DS_MESH_MATRIX, "LIB3DS_MESH_MATRIX"}, + {LIB3DS_MESH_COLOR, "LIB3DS_MESH_COLOR"}, + {LIB3DS_MESH_TEXTURE_INFO, "LIB3DS_MESH_TEXTURE_INFO"}, + {LIB3DS_KFDATA, "LIB3DS_KFDATA"}, + {LIB3DS_KFHDR, "LIB3DS_KFHDR"}, + {LIB3DS_KFSEG, "LIB3DS_KFSEG"}, + {LIB3DS_KFCURTIME, "LIB3DS_KFCURTIME"}, + {LIB3DS_AMBIENT_NODE_TAG, "LIB3DS_AMBIENT_NODE_TAG"}, + {LIB3DS_OBJECT_NODE_TAG, "LIB3DS_OBJECT_NODE_TAG"}, + {LIB3DS_CAMERA_NODE_TAG, "LIB3DS_CAMERA_NODE_TAG"}, + {LIB3DS_TARGET_NODE_TAG, "LIB3DS_TARGET_NODE_TAG"}, + {LIB3DS_LIGHT_NODE_TAG, "LIB3DS_LIGHT_NODE_TAG"}, + {LIB3DS_L_TARGET_NODE_TAG, "LIB3DS_L_TARGET_NODE_TAG"}, + {LIB3DS_SPOTLIGHT_NODE_TAG, "LIB3DS_SPOTLIGHT_NODE_TAG"}, + {LIB3DS_NODE_ID, "LIB3DS_NODE_ID"}, + {LIB3DS_NODE_HDR, "LIB3DS_NODE_HDR"}, + {LIB3DS_PIVOT, "LIB3DS_PIVOT"}, + {LIB3DS_INSTANCE_NAME, "LIB3DS_INSTANCE_NAME"}, + {LIB3DS_MORPH_SMOOTH, "LIB3DS_MORPH_SMOOTH"}, + {LIB3DS_BOUNDBOX, "LIB3DS_BOUNDBOX"}, + {LIB3DS_POS_TRACK_TAG, "LIB3DS_POS_TRACK_TAG"}, + {LIB3DS_COL_TRACK_TAG, "LIB3DS_COL_TRACK_TAG"}, + {LIB3DS_ROT_TRACK_TAG, "LIB3DS_ROT_TRACK_TAG"}, + {LIB3DS_SCL_TRACK_TAG, "LIB3DS_SCL_TRACK_TAG"}, + {LIB3DS_MORPH_TRACK_TAG, "LIB3DS_MORPH_TRACK_TAG"}, + {LIB3DS_FOV_TRACK_TAG, "LIB3DS_FOV_TRACK_TAG"}, + {LIB3DS_ROLL_TRACK_TAG, "LIB3DS_ROLL_TRACK_TAG"}, + {LIB3DS_HOT_TRACK_TAG, "LIB3DS_HOT_TRACK_TAG"}, + {LIB3DS_FALL_TRACK_TAG, "LIB3DS_FALL_TRACK_TAG"}, + {LIB3DS_HIDE_TRACK_TAG, "LIB3DS_HIDE_TRACK_TAG"}, + {LIB3DS_POLY_2D, "LIB3DS_POLY_2D"}, + {LIB3DS_SHAPE_OK, "LIB3DS_SHAPE_OK"}, + {LIB3DS_SHAPE_NOT_OK, "LIB3DS_SHAPE_NOT_OK"}, + {LIB3DS_SHAPE_HOOK, "LIB3DS_SHAPE_HOOK"}, + {LIB3DS_PATH_3D, "LIB3DS_PATH_3D"}, + {LIB3DS_PATH_MATRIX, "LIB3DS_PATH_MATRIX"}, + {LIB3DS_SHAPE_2D, "LIB3DS_SHAPE_2D"}, + {LIB3DS_M_SCALE, "LIB3DS_M_SCALE"}, + {LIB3DS_M_TWIST, "LIB3DS_M_TWIST"}, + {LIB3DS_M_TEETER, "LIB3DS_M_TEETER"}, + {LIB3DS_M_FIT, "LIB3DS_M_FIT"}, + {LIB3DS_M_BEVEL, "LIB3DS_M_BEVEL"}, + {LIB3DS_XZ_CURVE, "LIB3DS_XZ_CURVE"}, + {LIB3DS_YZ_CURVE, "LIB3DS_YZ_CURVE"}, + {LIB3DS_INTERPCT, "LIB3DS_INTERPCT"}, + {LIB3DS_DEFORM_LIMIT, "LIB3DS_DEFORM_LIMIT"}, + {LIB3DS_USE_CONTOUR, "LIB3DS_USE_CONTOUR"}, + {LIB3DS_USE_TWEEN, "LIB3DS_USE_TWEEN"}, + {LIB3DS_USE_SCALE, "LIB3DS_USE_SCALE"}, + {LIB3DS_USE_TWIST, "LIB3DS_USE_TWIST"}, + {LIB3DS_USE_TEETER, "LIB3DS_USE_TEETER"}, + {LIB3DS_USE_FIT, "LIB3DS_USE_FIT"}, + {LIB3DS_USE_BEVEL, "LIB3DS_USE_BEVEL"}, + {LIB3DS_DEFAULT_VIEW, "LIB3DS_DEFAULT_VIEW"}, + {LIB3DS_VIEW_TOP, "LIB3DS_VIEW_TOP"}, + {LIB3DS_VIEW_BOTTOM, "LIB3DS_VIEW_BOTTOM"}, + {LIB3DS_VIEW_LEFT, "LIB3DS_VIEW_LEFT"}, + {LIB3DS_VIEW_RIGHT, "LIB3DS_VIEW_RIGHT"}, + {LIB3DS_VIEW_FRONT, "LIB3DS_VIEW_FRONT"}, + {LIB3DS_VIEW_BACK, "LIB3DS_VIEW_BACK"}, + {LIB3DS_VIEW_USER, "LIB3DS_VIEW_USER"}, + {LIB3DS_VIEW_CAMERA, "LIB3DS_VIEW_CAMERA"}, + {LIB3DS_VIEW_WINDOW, "LIB3DS_VIEW_WINDOW"}, + {LIB3DS_VIEWPORT_LAYOUT_OLD, "LIB3DS_VIEWPORT_LAYOUT_OLD"}, + {LIB3DS_VIEWPORT_DATA_OLD, "LIB3DS_VIEWPORT_DATA_OLD"}, + {LIB3DS_VIEWPORT_LAYOUT, "LIB3DS_VIEWPORT_LAYOUT"}, + {LIB3DS_VIEWPORT_DATA, "LIB3DS_VIEWPORT_DATA"}, + {LIB3DS_VIEWPORT_DATA_3, "LIB3DS_VIEWPORT_DATA_3"}, + {LIB3DS_VIEWPORT_SIZE, "LIB3DS_VIEWPORT_SIZE"}, + {LIB3DS_NETWORK_VIEW, "LIB3DS_NETWORK_VIEW"}, + {0,0} +}; + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/3rdparty/lib3ds/chunktable.sed b/3rdparty/lib3ds/chunktable.sed new file mode 100644 index 000000000..11a62fc0d --- /dev/null +++ b/3rdparty/lib3ds/chunktable.sed @@ -0,0 +1,62 @@ +1 { + a\ +/* -*- c -*- */\ +#ifndef INCLUDED_LIB3DS_CHUNKTABLE_H\ +#define INCLUDED_LIB3DS_CHUNKTABLE_H\ +/*\ + * The 3D Studio File Format Library\ + * Copyright (C) 1996-2007 by Jan Eric Kyprianidis <www.kyprianidis.com>\ + * 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: chunktable.sed,v 1.7 2007/06/14 09:59:10 jeh Exp $\ + */\ +\ +#ifndef INCLUDED_LIB3DS_CHUNK_H\ +#include <lib3ds/chunk.h>\ +#endif\ +\ +#ifdef __cplusplus\ +extern "C" {\ +#endif\ +\ +typedef struct _Lib3dsChunkTable {\ + Lib3dsDword chunk;\ + const char* name;\ +} Lib3dsChunkTable;\ +\ +static Lib3dsChunkTable lib3ds_chunk_table[]={ +} +/^ *LIB3DS_/ { + s/ *\([0-9A-Z_]*\).*/ {\1, "\1"},/ + p +} +$ { + i\ + {0,0}\ +};\ +\ +#ifdef __cplusplus\ +};\ +#endif\ +#endif\ + +} +d + + + + diff --git a/3rdparty/lib3ds/ease.c b/3rdparty/lib3ds/ease.c new file mode 100644 index 000000000..57b9504c5 --- /dev/null +++ b/3rdparty/lib3ds/ease.c @@ -0,0 +1,62 @@ +/* + * The 3D Studio File Format Library + * Copyright (C) 1996-2007 by Jan Eric Kyprianidis <www.kyprianidis.com> + * 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: ease.c,v 1.6 2007/06/15 09:33:19 jeh Exp $ + */ +#include <lib3ds/ease.h> + + +/*! + * \defgroup ease Ease + */ + + +/*! + * \ingroup ease + */ +Lib3dsFloat +lib3ds_ease(Lib3dsFloat fp, Lib3dsFloat fc, Lib3dsFloat fn, + Lib3dsFloat ease_from, Lib3dsFloat ease_to) +{ + Lib3dsDouble s,step; + Lib3dsDouble tofrom; + Lib3dsDouble a; + + s=step=(Lib3dsFloat)(fc-fp)/(fn-fp); + tofrom=ease_to+ease_from; + if (tofrom!=0.0) { + if (tofrom>1.0) { + ease_to=(Lib3dsFloat)(ease_to/tofrom); + ease_from=(Lib3dsFloat)(ease_from/tofrom); + } + a=1.0/(2.0-(ease_to+ease_from)); + + if (step<ease_from) s=a/ease_from*step*step; + else { + if ((1.0-ease_to)<=step) { + step=1.0-step; + s=1.0-a/ease_to*step*step; + } + else { + s=((2.0*step)-ease_from)*a; + } + } + } + return((Lib3dsFloat)s); +} diff --git a/3rdparty/lib3ds/ease.h b/3rdparty/lib3ds/ease.h new file mode 100644 index 000000000..456f39141 --- /dev/null +++ b/3rdparty/lib3ds/ease.h @@ -0,0 +1,41 @@ +/* -*- c -*- */ +#ifndef INCLUDED_LIB3DS_EASE_H +#define INCLUDED_LIB3DS_EASE_H +/* + * The 3D Studio File Format Library + * Copyright (C) 1996-2007 by Jan Eric Kyprianidis <www.kyprianidis.com> + * 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: ease.h,v 1.6 2007/06/14 09:59:10 jeh Exp $ + */ + +#ifndef INCLUDED_LIB3DS_TYPES_H +#include <lib3ds/types.h> +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +extern LIB3DSAPI Lib3dsFloat lib3ds_ease(Lib3dsFloat fp, Lib3dsFloat fc, + Lib3dsFloat fn, Lib3dsFloat ease_from, Lib3dsFloat ease_to); + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/3rdparty/lib3ds/file.c b/3rdparty/lib3ds/file.c new file mode 100644 index 000000000..01fc4bd49 --- /dev/null +++ b/3rdparty/lib3ds/file.c @@ -0,0 +1,2029 @@ +/* + * The 3D Studio File Format Library + * Copyright (C) 1996-2007 by Jan Eric Kyprianidis <www.kyprianidis.com> + * 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: file.c,v 1.34 2007/06/20 17:04:08 jeh Exp $ + */ +#include <lib3ds/file.h> +#include <lib3ds/chunk.h> +#include <lib3ds/io.h> +#include <lib3ds/material.h> +#include <lib3ds/mesh.h> +#include <lib3ds/camera.h> +#include <lib3ds/light.h> +#include <lib3ds/node.h> +#include <lib3ds/matrix.h> +#include <lib3ds/vector.h> +#include <stdlib.h> +#include <string.h> +#include <math.h> +#include <float.h> + + +/*! + * \defgroup file Files + */ + + +static Lib3dsBool +fileio_error_func(void *self) +{ + FILE *f = (FILE*)self; + return(ferror(f)!=0); +} + + +static long +fileio_seek_func(void *self, long offset, Lib3dsIoSeek origin) +{ + FILE *f = (FILE*)self; + int o; + switch (origin) { + case LIB3DS_SEEK_SET: + o = SEEK_SET; + break; + case LIB3DS_SEEK_CUR: + o = SEEK_CUR; + break; + case LIB3DS_SEEK_END: + o = SEEK_END; + break; + default: + ASSERT(0); + return(0); + } + return (fseek(f, offset, o)); +} + + +static long +fileio_tell_func(void *self) +{ + FILE *f = (FILE*)self; + return(ftell(f)); +} + + +static size_t +fileio_read_func(void *self, void *buffer, size_t size) +{ + FILE *f = (FILE*)self; + return(fread(buffer, 1, size, f)); +} + + +static size_t +fileio_write_func(void *self, const void *buffer, size_t size) +{ + FILE *f = (FILE*)self; + return(fwrite(buffer, 1, size, f)); +} + + +/*! + * Loads a .3DS file from disk into memory. + * + * \param filename The filename of the .3DS file + * + * \return A pointer to the Lib3dsFile structure containing the + * data of the .3DS file. + * If the .3DS file can not be loaded NULL is returned. + * + * \note To free the returned structure use lib3ds_free. + * + * \see lib3ds_file_save + * \see lib3ds_file_new + * \see lib3ds_file_free + * + * \ingroup file + */ +Lib3dsFile* +lib3ds_file_load(const char *filename) +{ + FILE *f; + Lib3dsFile *file; + Lib3dsIo *io; + + f = fopen(filename, "rb"); + if (!f) { + return(0); + } + file = lib3ds_file_new(); + if (!file) { + fclose(f); + return(0); + } + + io = lib3ds_io_new( + f, + fileio_error_func, + fileio_seek_func, + fileio_tell_func, + fileio_read_func, + fileio_write_func + ); + if (!io) { + lib3ds_file_free(file); + fclose(f); + return(0); + } + + if (!lib3ds_file_read(file, io)) { + free(file); + lib3ds_io_free(io); + fclose(f); + return(0); + } + + lib3ds_io_free(io); + fclose(f); + return(file); +} + + +/*! + * Saves a .3DS file from memory to disk. + * + * \param file A pointer to a Lib3dsFile structure containing the + * the data that should be stored. + * \param filename The filename of the .3DS file to store the data in. + * + * \return TRUE on success, FALSE otherwise. + * + * \see lib3ds_file_load + * + * \ingroup file + */ +Lib3dsBool +lib3ds_file_save(Lib3dsFile *file, const char *filename) +{ + FILE *f; + Lib3dsIo *io; + Lib3dsBool result; + + f = fopen(filename, "wb"); + if (!f) { + return(LIB3DS_FALSE); + } + io = lib3ds_io_new( + f, + fileio_error_func, + fileio_seek_func, + fileio_tell_func, + fileio_read_func, + fileio_write_func + ); + if (!io) { + fclose(f); + return LIB3DS_FALSE; + } + + result = lib3ds_file_write(file, io); + + fclose(f); + + lib3ds_io_free(io); + return(result); +} + + +/*! + * Creates and returns a new, empty Lib3dsFile object. + * + * \return A pointer to the Lib3dsFile structure. + * If the structure cannot be allocated, NULL is returned. + * + * \ingroup file + */ +Lib3dsFile* +lib3ds_file_new() +{ + Lib3dsFile *file; + + file=(Lib3dsFile*)calloc(sizeof(Lib3dsFile),1); + if (!file) { + return(0); + } + file->mesh_version=3; + file->master_scale=1.0f; + file->keyf_revision=5; + strcpy(file->name, "LIB3DS"); + + file->frames=100; + file->segment_from=0; + file->segment_to=100; + file->current_frame=0; + + return(file); +} + + +/*! + * Free a Lib3dsFile object and all of its resources. + * + * \param file The Lib3dsFile object to be freed. + * + * \ingroup file + */ +void +lib3ds_file_free(Lib3dsFile* file) +{ + ASSERT(file); + lib3ds_viewport_set_views(&file->viewport,0); + lib3ds_viewport_set_views(&file->viewport_keyf,0); + { + Lib3dsMaterial *p,*q; + + for (p=file->materials; p; p=q) { + q=p->next; + lib3ds_material_free(p); + } + file->materials=0; + } + { + Lib3dsCamera *p,*q; + + for (p=file->cameras; p; p=q) { + q=p->next; + lib3ds_camera_free(p); + } + file->cameras=0; + } + { + Lib3dsLight *p,*q; + + for (p=file->lights; p; p=q) { + q=p->next; + lib3ds_light_free(p); + } + file->lights=0; + } + { + Lib3dsMesh *p,*q; + + for (p=file->meshes; p; p=q) { + q=p->next; + lib3ds_mesh_free(p); + } + file->meshes=0; + } + { + Lib3dsNode *p,*q; + + for (p=file->nodes; p; p=q) { + q=p->next; + lib3ds_node_free(p); + } + } + free(file); +} + + +/*! + * Evaluate all of the nodes in this Lib3dsFile object. + * + * \param file The Lib3dsFile object to be evaluated. + * \param t time value, between 0. and file->frames + * + * \see lib3ds_node_eval + * + * \ingroup file + */ +void +lib3ds_file_eval(Lib3dsFile *file, Lib3dsFloat t) +{ + Lib3dsNode *p; + + for (p=file->nodes; p!=0; p=p->next) { + lib3ds_node_eval(p, t); + } +} + + +static Lib3dsBool +named_object_read(Lib3dsFile *file, Lib3dsIo *io) +{ + Lib3dsChunk c; + char name[64]; + Lib3dsWord chunk; + Lib3dsMesh *mesh = NULL; + Lib3dsCamera *camera = NULL; + Lib3dsLight *light = NULL; + Lib3dsDword object_flags; + + if (!lib3ds_chunk_read_start(&c, LIB3DS_NAMED_OBJECT, io)) { + return(LIB3DS_FALSE); + } + if (!lib3ds_io_read_string(io, name, 64)) { + return(LIB3DS_FALSE); + } + lib3ds_chunk_dump_info(" NAME=%s", name); + lib3ds_chunk_read_tell(&c, io); + + object_flags = 0; + while ((chunk=lib3ds_chunk_read_next(&c, io))!=0) { + switch (chunk) { + case LIB3DS_N_TRI_OBJECT: + { + mesh=lib3ds_mesh_new(name); + if (!mesh) { + return(LIB3DS_FALSE); + } + lib3ds_chunk_read_reset(&c, io); + if (!lib3ds_mesh_read(mesh, io)) { + return(LIB3DS_FALSE); + } + lib3ds_file_insert_mesh(file, mesh); + } + break; + + case LIB3DS_N_CAMERA: + { + camera=lib3ds_camera_new(name); + if (!camera) { + return(LIB3DS_FALSE); + } + lib3ds_chunk_read_reset(&c, io); + if (!lib3ds_camera_read(camera, io)) { + return(LIB3DS_FALSE); + } + lib3ds_file_insert_camera(file, camera); + } + break; + + case LIB3DS_N_DIRECT_LIGHT: + { + light=lib3ds_light_new(name); + if (!light) { + return(LIB3DS_FALSE); + } + lib3ds_chunk_read_reset(&c, io); + if (!lib3ds_light_read(light, io)) { + return(LIB3DS_FALSE); + } + lib3ds_file_insert_light(file, light); + } + break; + + case LIB3DS_OBJ_HIDDEN: + object_flags |= LIB3DS_OBJECT_HIDDEN; + break; + + case LIB3DS_OBJ_DOESNT_CAST: + object_flags |= LIB3DS_OBJECT_DOESNT_CAST; + break; + + case LIB3DS_OBJ_VIS_LOFTER: + object_flags |= LIB3DS_OBJECT_VIS_LOFTER; + break; + + case LIB3DS_OBJ_MATTE: + object_flags |= LIB3DS_OBJECT_MATTE; + break; + + case LIB3DS_OBJ_DONT_RCVSHADOW: + object_flags |= LIB3DS_OBJECT_DONT_RCVSHADOW; + break; + + case LIB3DS_OBJ_FAST: + object_flags |= LIB3DS_OBJECT_FAST; + break; + + case LIB3DS_OBJ_FROZEN: + object_flags |= LIB3DS_OBJECT_FROZEN; + break; + + default: + lib3ds_chunk_unknown(chunk); + } + } + + if (mesh) + mesh->object_flags = object_flags; + if (camera) + camera->object_flags = object_flags; + if (light) + light->object_flags = object_flags; + + lib3ds_chunk_read_end(&c, io); + return(LIB3DS_TRUE); +} + + +static Lib3dsBool +ambient_read(Lib3dsFile *file, Lib3dsIo *io) +{ + Lib3dsChunk c; + Lib3dsWord chunk; + Lib3dsBool have_lin=LIB3DS_FALSE; + + if (!lib3ds_chunk_read_start(&c, LIB3DS_AMBIENT_LIGHT, io)) { + return(LIB3DS_FALSE); + } + + while ((chunk=lib3ds_chunk_read_next(&c, io))!=0) { + switch (chunk) { + case LIB3DS_LIN_COLOR_F: + { + int i; + for (i=0; i<3; ++i) { + file->ambient[i]=lib3ds_io_read_float(io); + } + } + have_lin=LIB3DS_TRUE; + break; + case LIB3DS_COLOR_F: + { + /* gamma corrected color chunk + replaced in 3ds R3 by LIN_COLOR_24 */ + if (!have_lin) { + int i; + for (i=0; i<3; ++i) { + file->ambient[i]=lib3ds_io_read_float(io); + } + } + } + break; + default: + lib3ds_chunk_unknown(chunk); + } + } + + lib3ds_chunk_read_end(&c, io); + return(LIB3DS_TRUE); +} + + +static Lib3dsBool +mdata_read(Lib3dsFile *file, Lib3dsIo *io) +{ + Lib3dsChunk c; + Lib3dsWord chunk; + + if (!lib3ds_chunk_read_start(&c, LIB3DS_MDATA, io)) { + return(LIB3DS_FALSE); + } + + while ((chunk=lib3ds_chunk_read_next(&c, io))!=0) { + switch (chunk) { + case LIB3DS_MESH_VERSION: + { + file->mesh_version=lib3ds_io_read_intd(io); + } + break; + case LIB3DS_MASTER_SCALE: + { + file->master_scale=lib3ds_io_read_float(io); + } + break; + case LIB3DS_SHADOW_MAP_SIZE: + case LIB3DS_LO_SHADOW_BIAS: + case LIB3DS_HI_SHADOW_BIAS: + case LIB3DS_SHADOW_SAMPLES: + case LIB3DS_SHADOW_RANGE: + case LIB3DS_SHADOW_FILTER: + case LIB3DS_RAY_BIAS: + { + lib3ds_chunk_read_reset(&c, io); + if (!lib3ds_shadow_read(&file->shadow, io)) { + return(LIB3DS_FALSE); + } + } + break; + case LIB3DS_VIEWPORT_LAYOUT: + case LIB3DS_DEFAULT_VIEW: + { + lib3ds_chunk_read_reset(&c, io); + if (!lib3ds_viewport_read(&file->viewport, io)) { + return(LIB3DS_FALSE); + } + } + break; + case LIB3DS_O_CONSTS: + { + int i; + for (i=0; i<3; ++i) { + file->construction_plane[i]=lib3ds_io_read_float(io); + } + } + break; + case LIB3DS_AMBIENT_LIGHT: + { + lib3ds_chunk_read_reset(&c, io); + if (!ambient_read(file, io)) { + return(LIB3DS_FALSE); + } + } + break; + case LIB3DS_BIT_MAP: + case LIB3DS_SOLID_BGND: + case LIB3DS_V_GRADIENT: + case LIB3DS_USE_BIT_MAP: + case LIB3DS_USE_SOLID_BGND: + case LIB3DS_USE_V_GRADIENT: + { + lib3ds_chunk_read_reset(&c, io); + if (!lib3ds_background_read(&file->background, io)) { + return(LIB3DS_FALSE); + } + } + break; + case LIB3DS_FOG: + case LIB3DS_LAYER_FOG: + case LIB3DS_DISTANCE_CUE: + case LIB3DS_USE_FOG: + case LIB3DS_USE_LAYER_FOG: + case LIB3DS_USE_DISTANCE_CUE: + { + lib3ds_chunk_read_reset(&c, io); + if (!lib3ds_atmosphere_read(&file->atmosphere, io)) { + return(LIB3DS_FALSE); + } + } + break; + case LIB3DS_MAT_ENTRY: + { + Lib3dsMaterial *material; + + material=lib3ds_material_new(); + if (!material) { + return(LIB3DS_FALSE); + } + lib3ds_chunk_read_reset(&c, io); + if (!lib3ds_material_read(material, io)) { + return(LIB3DS_FALSE); + } + lib3ds_file_insert_material(file, material); + } + break; + case LIB3DS_NAMED_OBJECT: + { + lib3ds_chunk_read_reset(&c, io); + if (!named_object_read(file, io)) { + return(LIB3DS_FALSE); + } + } + break; + default: + lib3ds_chunk_unknown(chunk); + } + } + + lib3ds_chunk_read_end(&c, io); + return(LIB3DS_TRUE); +} + + +static Lib3dsBool +kfdata_read(Lib3dsFile *file, Lib3dsIo *io) +{ + Lib3dsChunk c; + Lib3dsWord chunk; + Lib3dsDword node_number = 0; + + if (!lib3ds_chunk_read_start(&c, LIB3DS_KFDATA, io)) { + return(LIB3DS_FALSE); + } + + while ((chunk=lib3ds_chunk_read_next(&c, io))!=0) { + switch (chunk) { + case LIB3DS_KFHDR: + { + file->keyf_revision=lib3ds_io_read_word(io); + if (!lib3ds_io_read_string(io, file->name, 12+1)) { + return(LIB3DS_FALSE); + } + file->frames=lib3ds_io_read_intd(io); + } + break; + case LIB3DS_KFSEG: + { + file->segment_from=lib3ds_io_read_intd(io); + file->segment_to=lib3ds_io_read_intd(io); + } + break; + case LIB3DS_KFCURTIME: + { + file->current_frame=lib3ds_io_read_intd(io); + } + break; + case LIB3DS_VIEWPORT_LAYOUT: + case LIB3DS_DEFAULT_VIEW: + { + lib3ds_chunk_read_reset(&c, io); + if (!lib3ds_viewport_read(&file->viewport_keyf, io)) { + return(LIB3DS_FALSE); + } + } + break; + case LIB3DS_AMBIENT_NODE_TAG: + { + Lib3dsNode *node; + + node=lib3ds_node_new_ambient(); + if (!node) { + return(LIB3DS_FALSE); + } + node->node_id=node_number++; + lib3ds_chunk_read_reset(&c, io); + if (!lib3ds_node_read(node, file, io)) { + return(LIB3DS_FALSE); + } + lib3ds_file_insert_node(file, node); + } + break; + case LIB3DS_OBJECT_NODE_TAG: + { + Lib3dsNode *node; + + node=lib3ds_node_new_object(); + if (!node) { + return(LIB3DS_FALSE); + } + node->node_id=node_number++; + lib3ds_chunk_read_reset(&c, io); + if (!lib3ds_node_read(node, file, io)) { + return(LIB3DS_FALSE); + } + lib3ds_file_insert_node(file, node); + } + break; + case LIB3DS_CAMERA_NODE_TAG: + { + Lib3dsNode *node; + + node=lib3ds_node_new_camera(); + if (!node) { + return(LIB3DS_FALSE); + } + node->node_id=node_number++; + lib3ds_chunk_read_reset(&c, io); + if (!lib3ds_node_read(node, file, io)) { + return(LIB3DS_FALSE); + } + lib3ds_file_insert_node(file, node); + } + break; + case LIB3DS_TARGET_NODE_TAG: + { + Lib3dsNode *node; + + node=lib3ds_node_new_target(); + if (!node) { + return(LIB3DS_FALSE); + } + node->node_id=node_number++; + lib3ds_chunk_read_reset(&c, io); + if (!lib3ds_node_read(node, file, io)) { + return(LIB3DS_FALSE); + } + lib3ds_file_insert_node(file, node); + } + break; + case LIB3DS_LIGHT_NODE_TAG: + case LIB3DS_SPOTLIGHT_NODE_TAG: + { + Lib3dsNode *node; + + node=lib3ds_node_new_light(); + if (!node) { + return(LIB3DS_FALSE); + } + node->node_id=node_number++; + lib3ds_chunk_read_reset(&c, io); + if (!lib3ds_node_read(node, file, io)) { + return(LIB3DS_FALSE); + } + lib3ds_file_insert_node(file, node); + } + break; + case LIB3DS_L_TARGET_NODE_TAG: + { + Lib3dsNode *node; + + node=lib3ds_node_new_spot(); + if (!node) { + return(LIB3DS_FALSE); + } + node->node_id=node_number++; + lib3ds_chunk_read_reset(&c, io); + if (!lib3ds_node_read(node, file, io)) { + return(LIB3DS_FALSE); + } + lib3ds_file_insert_node(file, node); + } + break; + default: + lib3ds_chunk_unknown(chunk); + } + } + + lib3ds_chunk_read_end(&c, io); + return(LIB3DS_TRUE); +} + + +/*! + * Read 3ds file data into a Lib3dsFile object. + * + * \param file The Lib3dsFile object to be filled. + * \param io A Lib3dsIo object previously set up by the caller. + * + * \return LIB3DS_TRUE on success, LIB3DS_FALSE on failure. + * + * \ingroup file + */ +Lib3dsBool +lib3ds_file_read(Lib3dsFile *file, Lib3dsIo *io) +{ + Lib3dsChunk c; + Lib3dsWord chunk; + + if (!lib3ds_chunk_read_start(&c, 0, io)) { + return(LIB3DS_FALSE); + } + switch (c.chunk) { + case LIB3DS_MDATA: + { + lib3ds_chunk_read_reset(&c, io); + if (!mdata_read(file, io)) { + return(LIB3DS_FALSE); + } + } + break; + case LIB3DS_M3DMAGIC: + case LIB3DS_MLIBMAGIC: + case LIB3DS_CMAGIC: + { + while ((chunk=lib3ds_chunk_read_next(&c, io))!=0) { + switch (chunk) { + case LIB3DS_M3D_VERSION: + { + file->mesh_version=lib3ds_io_read_dword(io); + } + break; + case LIB3DS_MDATA: + { + lib3ds_chunk_read_reset(&c, io); + if (!mdata_read(file, io)) { + return(LIB3DS_FALSE); + } + } + break; + case LIB3DS_KFDATA: + { + lib3ds_chunk_read_reset(&c, io); + if (!kfdata_read(file, io)) { + return(LIB3DS_FALSE); + } + } + break; + default: + lib3ds_chunk_unknown(chunk); + } + } + } + break; + default: + lib3ds_chunk_unknown(c.chunk); + return(LIB3DS_FALSE); + } + + lib3ds_chunk_read_end(&c, io); + return(LIB3DS_TRUE); +} + + +static Lib3dsBool +colorf_write(Lib3dsRgba rgb, Lib3dsIo *io) +{ + Lib3dsChunk c; + + c.chunk=LIB3DS_COLOR_F; + c.size=18; + lib3ds_chunk_write(&c,io); + lib3ds_io_write_rgb(io, rgb); + + c.chunk=LIB3DS_LIN_COLOR_F; + c.size=18; + lib3ds_chunk_write(&c,io); + lib3ds_io_write_rgb(io, rgb); + return(LIB3DS_TRUE); +} + + +static Lib3dsBool +object_flags_write(Lib3dsDword flags, Lib3dsIo *io) +{ + if (flags){ + if (flags & LIB3DS_OBJECT_HIDDEN) { + if (!lib3ds_chunk_write_switch(LIB3DS_OBJ_HIDDEN, io)) + return LIB3DS_FALSE; + } + if (flags & LIB3DS_OBJECT_VIS_LOFTER) { + if (!lib3ds_chunk_write_switch(LIB3DS_OBJ_VIS_LOFTER, io)) + return LIB3DS_FALSE; + } + if (flags & LIB3DS_OBJECT_DOESNT_CAST) { + if (!lib3ds_chunk_write_switch(LIB3DS_OBJ_DOESNT_CAST, io)) + return LIB3DS_FALSE; + } + if (flags & LIB3DS_OBJECT_MATTE) { + if (!lib3ds_chunk_write_switch(LIB3DS_OBJ_MATTE, io)) + return LIB3DS_FALSE; + } + if (flags & LIB3DS_OBJECT_DONT_RCVSHADOW) { + if (!lib3ds_chunk_write_switch(LIB3DS_OBJ_DOESNT_CAST, io)) + return LIB3DS_FALSE; + } + if (flags & LIB3DS_OBJECT_FAST) { + if (!lib3ds_chunk_write_switch(LIB3DS_OBJ_FAST, io)) + return LIB3DS_FALSE; + } + if (flags & LIB3DS_OBJECT_FROZEN) { + if (!lib3ds_chunk_write_switch(LIB3DS_OBJ_FROZEN, io)) + return LIB3DS_FALSE; + } + } + return LIB3DS_TRUE; +} + + +static Lib3dsBool +mdata_write(Lib3dsFile *file, Lib3dsIo *io) +{ + Lib3dsChunk c; + + c.chunk=LIB3DS_MDATA; + if (!lib3ds_chunk_write_start(&c,io)) { + return(LIB3DS_FALSE); + } + + { /*---- LIB3DS_MESH_VERSION ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_MESH_VERSION; + c.size=10; + lib3ds_chunk_write(&c,io); + lib3ds_io_write_intd(io, file->mesh_version); + } + { /*---- LIB3DS_MASTER_SCALE ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_MASTER_SCALE; + c.size=10; + lib3ds_chunk_write(&c,io); + lib3ds_io_write_float(io, file->master_scale); + } + { /*---- LIB3DS_O_CONSTS ----*/ + int i; + for (i=0; i<3; ++i) { + if (fabs(file->construction_plane[i])>LIB3DS_EPSILON) { + break; + } + } + if (i<3) { + Lib3dsChunk c; + c.chunk=LIB3DS_O_CONSTS; + c.size=18; + lib3ds_chunk_write(&c,io); + lib3ds_io_write_vector(io, file->construction_plane); + } + } + + { /*---- LIB3DS_AMBIENT_LIGHT ----*/ + int i; + for (i=0; i<3; ++i) { + if (fabs(file->ambient[i])>LIB3DS_EPSILON) { + break; + } + } + if (i<3) { + Lib3dsChunk c; + c.chunk=LIB3DS_AMBIENT_LIGHT; + c.size=42; + lib3ds_chunk_write(&c,io); + colorf_write(file->ambient,io); + } + } + lib3ds_background_write(&file->background, io); + lib3ds_atmosphere_write(&file->atmosphere, io); + lib3ds_shadow_write(&file->shadow, io); + lib3ds_viewport_write(&file->viewport, io); + { + Lib3dsMaterial *p; + for (p=file->materials; p!=0; p=p->next) { + if (!lib3ds_material_write(p,io)) { + return(LIB3DS_FALSE); + } + } + } + { + Lib3dsCamera *p; + Lib3dsChunk c; + + for (p=file->cameras; p!=0; p=p->next) { + c.chunk=LIB3DS_NAMED_OBJECT; + if (!lib3ds_chunk_write_start(&c,io)) { + return(LIB3DS_FALSE); + } + lib3ds_io_write_string(io, p->name); + lib3ds_camera_write(p,io); + object_flags_write(p->object_flags,io); + if (!lib3ds_chunk_write_end(&c,io)) { + return(LIB3DS_FALSE); + } + } + } + { + Lib3dsLight *p; + Lib3dsChunk c; + + for (p=file->lights; p!=0; p=p->next) { + c.chunk=LIB3DS_NAMED_OBJECT; + if (!lib3ds_chunk_write_start(&c,io)) { + return(LIB3DS_FALSE); + } + lib3ds_io_write_string(io,p->name); + lib3ds_light_write(p,io); + object_flags_write(p->object_flags,io); + if (!lib3ds_chunk_write_end(&c,io)) { + return(LIB3DS_FALSE); + } + } + } + { + Lib3dsMesh *p; + Lib3dsChunk c; + + for (p=file->meshes; p!=0; p=p->next) { + c.chunk=LIB3DS_NAMED_OBJECT; + if (!lib3ds_chunk_write_start(&c,io)) { + return(LIB3DS_FALSE); + } + lib3ds_io_write_string(io, p->name); + lib3ds_mesh_write(p,io); + object_flags_write(p->object_flags,io); + if (!lib3ds_chunk_write_end(&c,io)) { + return(LIB3DS_FALSE); + } + } + } + + if (!lib3ds_chunk_write_end(&c,io)) { + return(LIB3DS_FALSE); + } + return(LIB3DS_TRUE); +} + + + +static Lib3dsBool +nodes_write(Lib3dsNode *node, Lib3dsFile *file, Lib3dsIo *io) +{ + { + Lib3dsNode *p; + for (p=node->childs; p!=0; p=p->next) { + if (!lib3ds_node_write(p, file, io)) { + return(LIB3DS_FALSE); + } + nodes_write(p, file, io); + } + } + return(LIB3DS_TRUE); +} + + +static Lib3dsBool +kfdata_write(Lib3dsFile *file, Lib3dsIo *io) +{ + Lib3dsChunk c; + + if (!file->nodes) { + return(LIB3DS_TRUE); + } + + c.chunk=LIB3DS_KFDATA; + if (!lib3ds_chunk_write_start(&c,io)) { + return(LIB3DS_FALSE); + } + + { /*---- LIB3DS_KFHDR ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_KFHDR; + c.size=6 + 2 + (Lib3dsDword)strlen(file->name)+1 +4; + lib3ds_chunk_write(&c,io); + lib3ds_io_write_intw(io, file->keyf_revision); + lib3ds_io_write_string(io, file->name); + lib3ds_io_write_intd(io, file->frames); + } + { /*---- LIB3DS_KFSEG ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_KFSEG; + c.size=14; + lib3ds_chunk_write(&c,io); + lib3ds_io_write_intd(io, file->segment_from); + lib3ds_io_write_intd(io, file->segment_to); + } + { /*---- LIB3DS_KFCURTIME ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_KFCURTIME; + c.size=10; + lib3ds_chunk_write(&c,io); + lib3ds_io_write_intd(io, file->current_frame); + } + lib3ds_viewport_write(&file->viewport_keyf, io); + + { + Lib3dsNode *p; + for (p=file->nodes; p!=0; p=p->next) { + if (!lib3ds_node_write(p, file, io)) { + return(LIB3DS_FALSE); + } + if (!nodes_write(p, file, io)) { + return(LIB3DS_FALSE); + } + } + } + + if (!lib3ds_chunk_write_end(&c,io)) { + return(LIB3DS_FALSE); + } + return(LIB3DS_TRUE); +} + + +/*! + * Write 3ds file data from a Lib3dsFile object to a file. + * + * \param file The Lib3dsFile object to be written. + * \param io A Lib3dsIo object previously set up by the caller. + * + * \return LIB3DS_TRUE on success, LIB3DS_FALSE on failure. + * + * \ingroup file + */ +Lib3dsBool +lib3ds_file_write(Lib3dsFile *file, Lib3dsIo *io) +{ + Lib3dsChunk c; + + c.chunk=LIB3DS_M3DMAGIC; + if (!lib3ds_chunk_write_start(&c,io)) { + LIB3DS_ERROR_LOG; + return(LIB3DS_FALSE); + } + + { /*---- LIB3DS_M3D_VERSION ----*/ + Lib3dsChunk c; + + c.chunk=LIB3DS_M3D_VERSION; + c.size=10; + lib3ds_chunk_write(&c,io); + lib3ds_io_write_dword(io, file->mesh_version); + } + + if (!mdata_write(file, io)) { + return(LIB3DS_FALSE); + } + if (!kfdata_write(file, io)) { + return(LIB3DS_FALSE); + } + + if (!lib3ds_chunk_write_end(&c,io)) { + return(LIB3DS_FALSE); + } + return(LIB3DS_TRUE); +} + + +/*! + * Insert a new Lib3dsMaterial object into the materials list of + * a Lib3dsFile object. + * + * The new Lib3dsMaterial object is inserted into the materials list + * in alphabetic order by name. + * + * \param file The Lib3dsFile object to be modified. + * \param material The Lib3dsMaterial object to be inserted into file->materials + * + * \ingroup file + */ +void +lib3ds_file_insert_material(Lib3dsFile *file, Lib3dsMaterial *material) +{ + Lib3dsMaterial *p,*q; + + ASSERT(file); + ASSERT(material); + ASSERT(!material->next); + + q=0; + for (p=file->materials; p!=0; p=p->next) { + if (strcmp(material->name, p->name)<0) { + break; + } + q=p; + } + if (!q) { + material->next=file->materials; + file->materials=material; + } + else { + material->next=q->next; + q->next=material; + } +} + + +/*! + * Remove a Lib3dsMaterial object from the materials list of + * a Lib3dsFile object. + * + * If the Lib3dsMaterial is not found in the materials list, nothing is + * done (except that an error log message may be generated.) + * + * \param file The Lib3dsFile object to be modified. + * \param material The Lib3dsMaterial object to be removed from file->materials + * + * \ingroup file + */ +void +lib3ds_file_remove_material(Lib3dsFile *file, Lib3dsMaterial *material) +{ + Lib3dsMaterial *p,*q; + + ASSERT(file); + ASSERT(material); + ASSERT(file->materials); + for (p=0,q=file->materials; q; p=q,q=q->next) { + if (q==material) { + break; + } + } + if (!q) { + ASSERT(LIB3DS_FALSE); + return; + } + if (!p) { + file->materials=material->next; + } + else { + p->next=q->next; + } + material->next=0; +} + + +/*! + * Return a Lib3dsMaterial object by name. + * + * \param file Lib3dsFile object to be searched. + * \param name Name of the Lib3dsMaterial object to be searched for. + * + * \return A pointer to the named Lib3dsMaterial, or NULL if not found. + * + * \ingroup file + */ +Lib3dsMaterial* +lib3ds_file_material_by_name(Lib3dsFile *file, const char *name) +{ + Lib3dsMaterial *p; + + ASSERT(file); + for (p=file->materials; p!=0; p=p->next) { + if (strcmp(p->name,name)==0) { + return(p); + } + } + return(0); +} + + +/*! + * Dump all Lib3dsMaterial objects found in a Lib3dsFile object. + * + * \param file Lib3dsFile object to be dumped. + * + * \see lib3ds_material_dump + * + * \ingroup file + */ +void +lib3ds_file_dump_materials(Lib3dsFile *file) +{ + Lib3dsMaterial *p; + + ASSERT(file); + for (p=file->materials; p!=0; p=p->next) { + lib3ds_material_dump(p); + } +} + + +/*! + * Insert a new Lib3dsMesh object into the meshes list of + * a Lib3dsFile object. + * + * The new Lib3dsMesh object is inserted into the meshes list + * in alphabetic order by name. + * + * \param file The Lib3dsFile object to be modified. + * \param mesh The Lib3dsMesh object to be inserted into file->meshes + * + * \ingroup file + */ +void +lib3ds_file_insert_mesh(Lib3dsFile *file, Lib3dsMesh *mesh) +{ + Lib3dsMesh *p,*q; + + ASSERT(file); + ASSERT(mesh); + ASSERT(!mesh->next); + + q=0; + for (p=file->meshes; p!=0; p=p->next) { + if (strcmp(mesh->name, p->name)<0) { + break; + } + q=p; + } + if (!q) { + mesh->next=file->meshes; + file->meshes=mesh; + } + else { + mesh->next=q->next; + q->next=mesh; + } +} + + +/*! + * Remove a Lib3dsMesh object from the meshes list of + * a Lib3dsFile object. + * + * If the Lib3dsMesh is not found in the meshes list, nothing is done + * (except that an error log message may be generated.) + * + * \param file The Lib3dsFile object to be modified. + * \param mesh The Lib3dsMesh object to be removed from file->meshes + * + * \ingroup file + */ +void +lib3ds_file_remove_mesh(Lib3dsFile *file, Lib3dsMesh *mesh) +{ + Lib3dsMesh *p,*q; + + ASSERT(file); + ASSERT(mesh); + ASSERT(file->meshes); + for (p=0,q=file->meshes; q; p=q,q=q->next) { + if (q==mesh) { + break; + } + } + if (!q) { + ASSERT(LIB3DS_FALSE); + return; + } + if (!p) { + file->meshes=mesh->next; + } + else { + p->next=q->next; + } + mesh->next=0; +} + + +/*! + * Return a Lib3dsMesh object from a Lib3dsFile by name. + * + * \param file Lib3dsFile object to be searched. + * \param name Name of the Lib3dsMesh object to be searched for. + * + * \return A pointer to the named Lib3dsMesh, or NULL if not found. + * + * \ingroup file + */ +Lib3dsMesh* +lib3ds_file_mesh_by_name(Lib3dsFile *file, const char *name) +{ + Lib3dsMesh *p; + + ASSERT(file); + for (p=file->meshes; p!=0; p=p->next) { + if (strcmp(p->name,name)==0) { + return(p); + } + } + return(0); +} + + +/*! + * Dump all Lib3dsMesh objects found in a Lib3dsFile object. + * + * \param file Lib3dsFile object to be dumped. + * + * \see lib3ds_mesh_dump + * + * \ingroup file + */ +void +lib3ds_file_dump_meshes(Lib3dsFile *file) +{ + Lib3dsMesh *p; + + ASSERT(file); + for (p=file->meshes; p!=0; p=p->next) { + lib3ds_mesh_dump(p); + } +} + + +static void +dump_instances(Lib3dsNode *node, const char* parent) +{ + Lib3dsNode *p; + char name[255]; + + ASSERT(node); + ASSERT(parent); + strcpy(name, parent); + strcat(name, "."); + strcat(name, node->name); + if (node->type==LIB3DS_OBJECT_NODE) { + printf(" %s : %s\n", name, node->data.object.instance); + } + for (p=node->childs; p!=0; p=p->next) { + dump_instances(p, parent); + } +} + + +/*! + * Dump all Lib3dsNode object names found in a Lib3dsFile object. + * + * For each node of type OBJECT_NODE, its name and data.object.instance + * fields are printed to stdout. Consider using lib3ds_file_dump_nodes() + * instead, as that function dumps more information. + * + * Nodes are dumped recursively. + * + * \param file Lib3dsFile object to be dumped. + * + * \see lib3ds_file_dump_nodes + * + * \ingroup file + */ +void +lib3ds_file_dump_instances(Lib3dsFile *file) +{ + Lib3dsNode *p; + + ASSERT(file); + for (p=file->nodes; p!=0; p=p->next) { + dump_instances(p,""); + } +} + + +/*! + * Insert a new Lib3dsCamera object into the cameras list of + * a Lib3dsFile object. + * + * The new Lib3dsCamera object is inserted into the cameras list + * in alphabetic order by name. + * + * \param file The Lib3dsFile object to be modified. + * \param camera The Lib3dsCamera object to be inserted into file->cameras + * + * \ingroup file + */ +void +lib3ds_file_insert_camera(Lib3dsFile *file, Lib3dsCamera *camera) +{ + Lib3dsCamera *p,*q; + + ASSERT(file); + ASSERT(camera); + ASSERT(!camera->next); + + q=0; + for (p=file->cameras; p!=0; p=p->next) { + if (strcmp(camera->name, p->name)<0) { + break; + } + q=p; + } + if (!q) { + camera->next=file->cameras; + file->cameras=camera; + } + else { + camera->next=q->next; + q->next=camera; + } +} + + +/*! + * Remove a Lib3dsCamera object from the cameras list of + * a Lib3dsFile object. + * + * If the Lib3dsCamera is not found in the cameras list, nothing is done + * (except that an error log message may be generated.) + * + * \param file The Lib3dsFile object to be modified. + * \param camera The Lib3dsCamera object to be removed from file->cameras + * + * \ingroup file + */ +void +lib3ds_file_remove_camera(Lib3dsFile *file, Lib3dsCamera *camera) +{ + Lib3dsCamera *p,*q; + + ASSERT(file); + ASSERT(camera); + ASSERT(file->cameras); + for (p=0,q=file->cameras; q; p=q,q=q->next) { + if (q==camera) { + break; + } + } + if (!q) { + ASSERT(LIB3DS_FALSE); + return; + } + if (!p) { + file->cameras=camera->next; + } + else { + p->next=q->next; + } + camera->next=0; +} + + +/*! + * Return a Lib3dsCamera object from a Lib3dsFile by name. + * + * \param file Lib3dsFile object to be searched. + * \param name Name of the Lib3dsCamera object to be searched for. + * + * \return A pointer to the named Lib3dsCamera, or NULL if not found. + * + * \ingroup file + */ +Lib3dsCamera* +lib3ds_file_camera_by_name(Lib3dsFile *file, const char *name) +{ + Lib3dsCamera *p; + + ASSERT(file); + for (p=file->cameras; p!=0; p=p->next) { + if (strcmp(p->name,name)==0) { + return(p); + } + } + return(0); +} + + +/*! + * Dump all Lib3dsCamera objects found in a Lib3dsFile object. + * + * \param file Lib3dsFile object to be dumped. + * + * \see lib3ds_camera_dump + * + * \ingroup file + */ +void +lib3ds_file_dump_cameras(Lib3dsFile *file) +{ + Lib3dsCamera *p; + + ASSERT(file); + for (p=file->cameras; p!=0; p=p->next) { + lib3ds_camera_dump(p); + } +} + + +/*! + * Insert a new Lib3dsLight object into the lights list of + * a Lib3dsFile object. + * + * The new Lib3dsLight object is inserted into the lights list + * in alphabetic order by name. + * + * \param file The Lib3dsFile object to be modified. + * \param light The Lib3dsLight object to be inserted into file->lights + * + * \ingroup file + */ +void +lib3ds_file_insert_light(Lib3dsFile *file, Lib3dsLight *light) +{ + Lib3dsLight *p,*q; + + ASSERT(file); + ASSERT(light); + ASSERT(!light->next); + + q=0; + for (p=file->lights; p!=0; p=p->next) { + if (strcmp(light->name, p->name)<0) { + break; + } + q=p; + } + if (!q) { + light->next=file->lights; + file->lights=light; + } + else { + light->next=q->next; + q->next=light; + } +} + + +/*! + * Remove a Lib3dsLight object from the lights list of + * a Lib3dsFile object. + * + * If the Lib3dsLight is not found in the lights list, nothing is done + * (except that an error log message may be generated.) + * + * \param file The Lib3dsFile object to be modified. + * \param light The Lib3dsLight object to be removed from file->lights + * + * \ingroup file + */ +void +lib3ds_file_remove_light(Lib3dsFile *file, Lib3dsLight *light) +{ + Lib3dsLight *p,*q; + + ASSERT(file); + ASSERT(light); + ASSERT(file->lights); + for (p=0,q=file->lights; q; p=q,q=q->next) { + if (q==light) { + break; + } + } + if (!q) { + ASSERT(LIB3DS_FALSE); + return; + } + if (!p) { + file->lights=light->next; + } + else { + p->next=q->next; + } + light->next=0; +} + + +/*! + * Return a Lib3dsLight object from a Lib3dsFile by name. + * + * \param file Lib3dsFile object to be searched. + * \param name Name of the Lib3dsLight object to be searched for. + * + * \return A pointer to the named Lib3dsLight, or NULL if not found. + * + * \ingroup file + */ +Lib3dsLight* +lib3ds_file_light_by_name(Lib3dsFile *file, const char *name) +{ + Lib3dsLight *p; + + ASSERT(file); + for (p=file->lights; p!=0; p=p->next) { + if (strcmp(p->name,name)==0) { + return(p); + } + } + return(0); +} + + +/*! + * Dump all Lib3dsLight objects found in a Lib3dsFile object. + * + * \param file Lib3dsFile object to be dumped. + * + * \see lib3ds_light_dump + * + * \ingroup file + */ +void +lib3ds_file_dump_lights(Lib3dsFile *file) +{ + Lib3dsLight *p; + + ASSERT(file); + for (p=file->lights; p!=0; p=p->next) { + lib3ds_light_dump(p); + } +} + + +/*! + * Return a node object by name and type. + * + * This function performs a recursive search for the specified node. + * Both name and type must match. + * + * \param file The Lib3dsFile to be searched. + * \param name The target node name. + * \param type The target node type + * + * \return A pointer to the first matching node, or NULL if not found. + * + * \see lib3ds_node_by_name + * + * \ingroup file + */ +Lib3dsNode* +lib3ds_file_node_by_name(Lib3dsFile *file, const char* name, Lib3dsNodeTypes type) +{ + Lib3dsNode *p,*q; + + ASSERT(file); + for (p=file->nodes; p!=0; p=p->next) { + if ((p->type==type) && (strcmp(p->name, name)==0)) { + return(p); + } + q=lib3ds_node_by_name(p, name, type); + if (q) { + return(q); + } + } + return(0); +} + + +/*! + * Return a node object by id. + * + * This function performs a recursive search for the specified node. + * + * \param file The Lib3dsFile to be searched. + * \param node_id The target node id. + * + * \return A pointer to the first matching node, or NULL if not found. + * + * \see lib3ds_node_by_id + * + * \ingroup file + */ +Lib3dsNode* +lib3ds_file_node_by_id(Lib3dsFile *file, Lib3dsWord node_id) +{ + Lib3dsNode *p,*q; + + ASSERT(file); + for (p=file->nodes; p!=0; p=p->next) { + if (p->node_id==node_id) { + return(p); + } + q=lib3ds_node_by_id(p, node_id); + if (q) { + return(q); + } + } + return(0); +} + + +/*! + * Insert a new node into a Lib3dsFile object. + * + * If the node's parent_id structure is not LIB3DS_NO_PARENT and the + * specified parent is found inside the Lib3dsFile object, then the + * node is inserted as a child of that parent. If the parent_id + * structure is LIB3DS_NO_PARENT or the specified parent is not found, + * then the node is inserted at the top level. + * + * Node is inserted in alphabetic order by name. + * + * Finally, if any other top-level nodes in file specify this node as + * their parent, they are relocated as a child of this node. + * + * \param file The Lib3dsFile object to be modified. + * \param node The node to be inserted into file + * + * \ingroup file + */ +void +lib3ds_file_insert_node(Lib3dsFile *file, Lib3dsNode *node) +{ + Lib3dsNode *parent,*p,*n; + + ASSERT(node); + ASSERT(!node->next); + ASSERT(!node->parent); + + parent=0; + if (node->parent_id!=LIB3DS_NO_PARENT) { + parent=lib3ds_file_node_by_id(file, node->parent_id); + } + node->parent=parent; + + if (!parent) { + for (p=0,n=file->nodes; n!=0; p=n,n=n->next) { + if (strcmp(n->name, node->name)>0) { + break; + } + } + if (!p) { + node->next=file->nodes; + file->nodes=node; + } + else { + node->next=p->next; + p->next=node; + } + } + else { + for (p=0,n=parent->childs; n!=0; p=n,n=n->next) { + if (strcmp(n->name, node->name)>0) { + break; + } + } + if (!p) { + node->next=parent->childs; + parent->childs=node; + } + else { + node->next=p->next; + p->next=node; + } + } + + if (node->node_id!=LIB3DS_NO_PARENT) { + for (n=file->nodes; n!=0; n=p) { + p=n->next; + if (n->parent_id==node->node_id) { + lib3ds_file_remove_node(file, n); + lib3ds_file_insert_node(file, n); + } + } + } +} + + +/*! + * Remove a node from the a Lib3dsFile object. + * + * \param file The Lib3dsFile object to be modified. + * \param node The Lib3dsNode object to be removed from file + * + * \return LIB3DS_TRUE on success, LIB3DS_FALSE if node is not found in file + * + * \ingroup file + */ +Lib3dsBool +lib3ds_file_remove_node(Lib3dsFile *file, Lib3dsNode *node) +{ + Lib3dsNode *p,*n; + + if (node->parent) { + for (p=0,n=node->parent->childs; n; p=n,n=n->next) { + if (n==node) { + break; + } + } + if (!n) { + return(LIB3DS_FALSE); + } + + if (!p) { + node->parent->childs=n->next; + } + else { + p->next=n->next; + } + } + else { + for (p=0,n=file->nodes; n; p=n,n=n->next) { + if (n==node) { + break; + } + } + if (!n) { + return(LIB3DS_FALSE); + } + + if (!p) { + file->nodes=n->next; + } + else { + p->next=n->next; + } + } + return(LIB3DS_TRUE); +} + + +/*! + * This function computes the bounding box of meshes, cameras and lights + * defined in the 3D editor. + * + * \param file The Lib3dsFile object to be examined. + * \param include_meshes Include meshes in bounding box calculation. + * \param include_cameras Include cameras in bounding box calculation. + * \param include_lights Include lights in bounding box calculation. + * \param bmin Returned minimum x,y,z values. + * \param bmax Returned maximum x,y,z values. + * + * \ingroup file + */ +void +lib3ds_file_bounding_box_of_objects(Lib3dsFile *file, Lib3dsBool include_meshes, + Lib3dsBool include_cameras, Lib3dsBool include_lights, + Lib3dsVector bmin, Lib3dsVector bmax) +{ + bmin[0] = bmin[1] = bmin[2] = FLT_MAX; + bmax[0] = bmax[1] = bmax[2] = FLT_MIN; + + if (include_meshes) { + Lib3dsVector lmin, lmax; + Lib3dsMesh *p=file->meshes; + while (p) { + lib3ds_mesh_bounding_box(p, lmin, lmax); + lib3ds_vector_min(bmin, lmin); + lib3ds_vector_max(bmax, lmax); + p=p->next; + } + } + if (include_cameras) { + Lib3dsCamera *p=file->cameras; + while (p) { + lib3ds_vector_min(bmin, p->position); + lib3ds_vector_max(bmax, p->position); + lib3ds_vector_min(bmin, p->target); + lib3ds_vector_max(bmax, p->target); + p=p->next; + } + } + if (include_lights) { + Lib3dsLight *p=file->lights; + while (p) { + lib3ds_vector_min(bmin, p->position); + lib3ds_vector_max(bmax, p->position); + if (p->spot_light) { + lib3ds_vector_min(bmin, p->spot); + lib3ds_vector_max(bmax, p->spot); + } + p=p->next; + } + } +} + + +static void +file_bounding_box_of_nodes_impl(Lib3dsNode *node, Lib3dsFile *file, Lib3dsBool include_meshes, + Lib3dsBool include_cameras, Lib3dsBool include_lights, + Lib3dsVector bmin, Lib3dsVector bmax) +{ + switch (node->type) + { + case LIB3DS_OBJECT_NODE: + if (include_meshes) { + Lib3dsMesh *mesh; + + mesh = lib3ds_file_mesh_by_name(file, node->data.object.instance); + if (!mesh) + mesh = lib3ds_file_mesh_by_name(file, node->name); + if (mesh) { + Lib3dsMatrix inv_matrix, M; + Lib3dsVector v; + unsigned i; + + lib3ds_matrix_copy(inv_matrix, mesh->matrix); + lib3ds_matrix_inv(inv_matrix); + lib3ds_matrix_copy(M, node->matrix); + lib3ds_matrix_translate_xyz(M, -node->data.object.pivot[0], -node->data.object.pivot[1], -node->data.object.pivot[2]); + lib3ds_matrix_mult(M, inv_matrix); + + for (i=0; i<mesh->points; ++i) { + lib3ds_vector_transform(v, M, mesh->pointL[i].pos); + lib3ds_vector_min(bmin, v); + lib3ds_vector_max(bmax, v); + } + } + } + break; + /* + case LIB3DS_CAMERA_NODE: + case LIB3DS_TARGET_NODE: + if (include_cameras) { + Lib3dsVector z,v; + lib3ds_vector_zero(z); + lib3ds_vector_transform(v, node->matrix, z); + lib3ds_vector_min(bmin, v); + lib3ds_vector_max(bmax, v); + } + break; + + case LIB3DS_LIGHT_NODE: + case LIB3DS_SPOT_NODE: + if (include_lights) { + Lib3dsVector z,v; + lib3ds_vector_zero(z); + lib3ds_vector_transform(v, node->matrix, z); + lib3ds_vector_min(bmin, v); + lib3ds_vector_max(bmax, v); + } + break; + */ + default: break; + } + { + Lib3dsNode *p=node->childs; + while (p) { + file_bounding_box_of_nodes_impl(p, file, include_meshes, include_cameras, include_lights, bmin, bmax); + p=p->next; + } + } +} + + +/*! + * This function computes the bounding box of mesh, camera and light instances + * defined in the Keyframer. + * + * \param file The Lib3dsFile object to be examined. + * \param include_meshes Include meshes in bounding box calculation. + * \param include_cameras Include cameras in bounding box calculation. + * \param include_lights Include lights in bounding box calculation. + * \param bmin Returned minimum x,y,z values. + * \param bmax Returned maximum x,y,z values. + * + * \ingroup file + */ +void +lib3ds_file_bounding_box_of_nodes(Lib3dsFile *file, Lib3dsBool include_meshes, + Lib3dsBool include_cameras, Lib3dsBool include_lights, + Lib3dsVector bmin, Lib3dsVector bmax) +{ + Lib3dsNode *p; + + bmin[0] = bmin[1] = bmin[2] = FLT_MAX; + bmax[0] = bmax[1] = bmax[2] = FLT_MIN; + p=file->nodes; + while (p) { + file_bounding_box_of_nodes_impl(p, file, include_meshes, include_cameras, include_lights, bmin, bmax); + p=p->next; + } +} + + +/*! + * Dump all node objects found in a Lib3dsFile object. + * + * Nodes are dumped recursively. + * + * \param file Lib3dsFile object to be dumped. + * + * \see lib3ds_node_dump + * + * \ingroup file + */ +void +lib3ds_file_dump_nodes(Lib3dsFile *file) +{ + Lib3dsNode *p; + + ASSERT(file); + for (p=file->nodes; p!=0; p=p->next) { + lib3ds_node_dump(p,1); + } +} + diff --git a/3rdparty/lib3ds/file.h b/3rdparty/lib3ds/file.h new file mode 100644 index 000000000..fa8138a1d --- /dev/null +++ b/3rdparty/lib3ds/file.h @@ -0,0 +1,106 @@ +/* -*- c -*- */ +#ifndef INCLUDED_LIB3DS_FILE_H +#define INCLUDED_LIB3DS_FILE_H +/* + * The 3D Studio File Format Library + * Copyright (C) 1996-2007 by Jan Eric Kyprianidis <www.kyprianidis.com> + * 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: file.h,v 1.24 2007/06/20 17:04:08 jeh Exp $ + */ + +#ifndef INCLUDED_LIB3DS_BACKGROUND_H +#include <lib3ds/background.h> +#endif +#ifndef INCLUDED_LIB3DS_ATMOSPHERE_H +#include <lib3ds/atmosphere.h> +#endif +#ifndef INCLUDED_LIB3DS_SHADOW_H +#include <lib3ds/shadow.h> +#endif +#ifndef INCLUDED_LIB3DS_VIEWPORT_H +#include <lib3ds/viewport.h> +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * 3DS file structure + * \ingroup file + */ +struct Lib3dsFile { + Lib3dsDword mesh_version; + Lib3dsWord keyf_revision; + char name[12+1]; + Lib3dsFloat master_scale; + Lib3dsVector construction_plane; + Lib3dsRgb ambient; + Lib3dsShadow shadow; + Lib3dsBackground background; + Lib3dsAtmosphere atmosphere; + Lib3dsViewport viewport; + Lib3dsViewport viewport_keyf; + Lib3dsIntd frames; + Lib3dsIntd segment_from; + Lib3dsIntd segment_to; + Lib3dsIntd current_frame; + Lib3dsMaterial *materials; + Lib3dsMesh *meshes; + Lib3dsCamera *cameras; + Lib3dsLight *lights; + Lib3dsNode *nodes; +}; + +extern LIB3DSAPI Lib3dsFile* lib3ds_file_load(const char *filename); +extern LIB3DSAPI Lib3dsBool lib3ds_file_save(Lib3dsFile *file, const char *filename); +extern LIB3DSAPI Lib3dsFile* lib3ds_file_new(); +extern LIB3DSAPI void lib3ds_file_free(Lib3dsFile *file); +extern LIB3DSAPI void lib3ds_file_eval(Lib3dsFile *file, Lib3dsFloat t); +extern LIB3DSAPI Lib3dsBool lib3ds_file_read(Lib3dsFile *file, Lib3dsIo *io); +extern LIB3DSAPI Lib3dsBool lib3ds_file_write(Lib3dsFile *file, Lib3dsIo *io); +extern LIB3DSAPI void lib3ds_file_insert_material(Lib3dsFile *file, Lib3dsMaterial *material); +extern LIB3DSAPI void lib3ds_file_remove_material(Lib3dsFile *file, Lib3dsMaterial *material); +extern LIB3DSAPI Lib3dsMaterial* lib3ds_file_material_by_name(Lib3dsFile *file, const char *name); +extern LIB3DSAPI void lib3ds_file_dump_materials(Lib3dsFile *file); +extern LIB3DSAPI void lib3ds_file_insert_mesh(Lib3dsFile *file, Lib3dsMesh *mesh); +extern LIB3DSAPI void lib3ds_file_remove_mesh(Lib3dsFile *file, Lib3dsMesh *mesh); +extern LIB3DSAPI Lib3dsMesh* lib3ds_file_mesh_by_name(Lib3dsFile *file, const char *name); +extern LIB3DSAPI void lib3ds_file_dump_meshes(Lib3dsFile *file); +extern LIB3DSAPI void lib3ds_file_dump_instances(Lib3dsFile *file); +extern LIB3DSAPI void lib3ds_file_insert_camera(Lib3dsFile *file, Lib3dsCamera *camera); +extern LIB3DSAPI void lib3ds_file_remove_camera(Lib3dsFile *file, Lib3dsCamera *camera); +extern LIB3DSAPI Lib3dsCamera* lib3ds_file_camera_by_name(Lib3dsFile *file, const char *name); +extern LIB3DSAPI void lib3ds_file_dump_cameras(Lib3dsFile *file); +extern LIB3DSAPI void lib3ds_file_insert_light(Lib3dsFile *file, Lib3dsLight *light); +extern LIB3DSAPI void lib3ds_file_remove_light(Lib3dsFile *file, Lib3dsLight *light); +extern LIB3DSAPI Lib3dsLight* lib3ds_file_light_by_name(Lib3dsFile *file, const char *name); +extern LIB3DSAPI void lib3ds_file_dump_lights(Lib3dsFile *file); +extern LIB3DSAPI Lib3dsNode* lib3ds_file_node_by_name(Lib3dsFile *file, const char* name, Lib3dsNodeTypes type); +extern LIB3DSAPI Lib3dsNode* lib3ds_file_node_by_id(Lib3dsFile *file, Lib3dsWord node_id); +extern LIB3DSAPI void lib3ds_file_insert_node(Lib3dsFile *file, Lib3dsNode *node); +extern LIB3DSAPI Lib3dsBool lib3ds_file_remove_node(Lib3dsFile *file, Lib3dsNode *node); +extern LIB3DSAPI void lib3ds_file_bounding_box_of_objects(Lib3dsFile *file, Lib3dsBool include_meshes, Lib3dsBool include_cameras, Lib3dsBool include_lights, Lib3dsVector bmin, Lib3dsVector bmax); +extern LIB3DSAPI void lib3ds_file_bounding_box_of_nodes(Lib3dsFile *file, Lib3dsBool include_meshes, Lib3dsBool include_cameras, Lib3dsBool include_lights, Lib3dsVector bmin, Lib3dsVector bmax); +extern LIB3DSAPI void lib3ds_file_dump_nodes(Lib3dsFile *file); + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/3rdparty/lib3ds/io.c b/3rdparty/lib3ds/io.c new file mode 100644 index 000000000..508b845bf --- /dev/null +++ b/3rdparty/lib3ds/io.c @@ -0,0 +1,524 @@ +/* + * The 3D Studio File Format Library + * Copyright (C) 1996-2007 by Jan Eric Kyprianidis <www.kyprianidis.com> + * 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: io.c,v 1.9 2007/06/20 17:04:08 jeh Exp $ + */ +#include <lib3ds/io.h> +#include <stdlib.h> +#include <string.h> + + +/*! + * \defgroup io Binary Input/Ouput Abstraction Layer + */ + +typedef union { + Lib3dsDword dword_value; + Lib3dsFloat float_value; +} Lib3dsDwordFloat; + + +struct Lib3dsIo { + void *self; + Lib3dsIoErrorFunc error_func; + Lib3dsIoSeekFunc seek_func; + Lib3dsIoTellFunc tell_func; + Lib3dsIoReadFunc read_func; + Lib3dsIoWriteFunc write_func; +}; + + +Lib3dsIo* +lib3ds_io_new(void *self, Lib3dsIoErrorFunc error_func, Lib3dsIoSeekFunc seek_func, + Lib3dsIoTellFunc tell_func, Lib3dsIoReadFunc read_func, Lib3dsIoWriteFunc write_func) +{ + Lib3dsIo *io = calloc(sizeof(Lib3dsIo),1); + ASSERT(io); + if (!io) { + return 0; + } + + io->self = self; + io->error_func = error_func; + io->seek_func = seek_func; + io->tell_func = tell_func; + io->read_func = read_func; + io->write_func = write_func; + + return io; +} + + +void +lib3ds_io_free(Lib3dsIo *io) +{ + ASSERT(io); + if (!io) { + return; + } + free(io); +} + + +Lib3dsBool +lib3ds_io_error(Lib3dsIo *io) +{ + ASSERT(io); + if (!io || !io->error_func) { + return 0; + } + return (*io->error_func)(io->self); +} + + +long +lib3ds_io_seek(Lib3dsIo *io, long offset, Lib3dsIoSeek origin) +{ + ASSERT(io); + if (!io || !io->seek_func) { + return 0; + } + return (*io->seek_func)(io->self, offset, origin); +} + + +long +lib3ds_io_tell(Lib3dsIo *io) +{ + ASSERT(io); + if (!io || !io->tell_func) { + return 0; + } + return (*io->tell_func)(io->self); +} + + +size_t +lib3ds_io_read(Lib3dsIo *io, void *buffer, size_t size) +{ + ASSERT(io); + if (!io || !io->read_func) { + return 0; + } + return (*io->read_func)(io->self, buffer, size); +} + + +size_t +lib3ds_io_write(Lib3dsIo *io, const void *buffer, size_t size) +{ + ASSERT(io); + if (!io || !io->write_func) { + return 0; + } + return (*io->write_func)(io->self, buffer, size); +} + + +/*! + * \ingroup io + * + * Read a byte from a file stream. + */ +Lib3dsByte +lib3ds_io_read_byte(Lib3dsIo *io) +{ + Lib3dsByte b; + + ASSERT(io); + lib3ds_io_read(io, &b, 1); + return(b); +} + + +/** + * Read a word from a file stream in little endian format. + */ +Lib3dsWord +lib3ds_io_read_word(Lib3dsIo *io) +{ + Lib3dsByte b[2]; + Lib3dsWord w; + + ASSERT(io); + lib3ds_io_read(io, b, 2); + w=((Lib3dsWord)b[1] << 8) | + ((Lib3dsWord)b[0]); + return(w); +} + + +/*! + * \ingroup io + * + * Read a dword from file a stream in little endian format. + */ +Lib3dsDword +lib3ds_io_read_dword(Lib3dsIo *io) +{ + Lib3dsByte b[4]; + Lib3dsDword d; + + ASSERT(io); + lib3ds_io_read(io, b, 4); + d=((Lib3dsDword)b[3] << 24) | + ((Lib3dsDword)b[2] << 16) | + ((Lib3dsDword)b[1] << 8) | + ((Lib3dsDword)b[0]); + return(d); +} + + +/*! + * \ingroup io + * + * Read a signed byte from a file stream. + */ +Lib3dsIntb +lib3ds_io_read_intb(Lib3dsIo *io) +{ + Lib3dsIntb b; + + ASSERT(io); + lib3ds_io_read(io, &b, 1); + return(b); +} + + +/*! + * \ingroup io + * + * Read a signed word from a file stream in little endian format. + */ +Lib3dsIntw +lib3ds_io_read_intw(Lib3dsIo *io) +{ + Lib3dsByte b[2]; + Lib3dsWord w; + + ASSERT(io); + lib3ds_io_read(io, b, 2); + w=((Lib3dsWord)b[1] << 8) | + ((Lib3dsWord)b[0]); + return((Lib3dsIntw)w); +} + + +/*! + * \ingroup io + * + * Read a signed dword a from file stream in little endian format. + */ +Lib3dsIntd +lib3ds_io_read_intd(Lib3dsIo *io) +{ + Lib3dsByte b[4]; + Lib3dsDword d; + + ASSERT(io); + lib3ds_io_read(io, b, 4); + d=((Lib3dsDword)b[3] << 24) | + ((Lib3dsDword)b[2] << 16) | + ((Lib3dsDword)b[1] << 8) | + ((Lib3dsDword)b[0]); + return((Lib3dsIntd)d); +} + + +/*! + * \ingroup io + * + * Read a float from a file stream in little endian format. + */ +Lib3dsFloat +lib3ds_io_read_float(Lib3dsIo *io) +{ + Lib3dsByte b[4]; + Lib3dsDwordFloat d; + + ASSERT(io); + lib3ds_io_read(io, b, 4); + d.dword_value=((Lib3dsDword)b[3] << 24) | + ((Lib3dsDword)b[2] << 16) | + ((Lib3dsDword)b[1] << 8) | + ((Lib3dsDword)b[0]); + return d.float_value; +} + + +/*! + * \ingroup io + * + * Read a vector from a file stream in little endian format. + * + * \param io IO input handle. + * \param v The vector to store the data. + */ +Lib3dsBool +lib3ds_io_read_vector(Lib3dsIo *io, Lib3dsVector v) +{ + ASSERT(io); + + v[0]=lib3ds_io_read_float(io); + v[1]=lib3ds_io_read_float(io); + v[2]=lib3ds_io_read_float(io); + + return(!lib3ds_io_error(io)); +} + + +/*! + * \ingroup io + */ +Lib3dsBool +lib3ds_io_read_rgb(Lib3dsIo *io, Lib3dsRgb rgb) +{ + ASSERT(io); + + rgb[0]=lib3ds_io_read_float(io); + rgb[1]=lib3ds_io_read_float(io); + rgb[2]=lib3ds_io_read_float(io); + + return(!lib3ds_io_error(io)); +} + + +/*! + * \ingroup io + * + * Read a zero-terminated string from a file stream. + * + * \param io IO input handle. + * \param s The buffer to store the read string. + * \param buflen Buffer length. + * + * \return True on success, False otherwise. + */ +Lib3dsBool +lib3ds_io_read_string(Lib3dsIo *io, char *s, int buflen) +{ + char c; + int k=0; + + ASSERT(io); + for (;;) { + if (lib3ds_io_read(io, &c, 1)!=1) { + return LIB3DS_FALSE; + } + *s++ = c; + if (!c) { + break; + } + ++k; + if (k>=buflen) { + return(LIB3DS_FALSE); + } + } + + return(!lib3ds_io_error(io)); +} + + +/*! + * \ingroup io + * + * Writes a byte into a file stream. + */ +Lib3dsBool +lib3ds_io_write_byte(Lib3dsIo *io, Lib3dsByte b) +{ + ASSERT(io); + if (lib3ds_io_write(io, &b, 1)!=1) { + return(LIB3DS_FALSE); + } + return(LIB3DS_TRUE); +} + + +/*! + * \ingroup io + * + * Writes a word into a little endian file stream. + */ +Lib3dsBool +lib3ds_io_write_word(Lib3dsIo *io, Lib3dsWord w) +{ + Lib3dsByte b[2]; + + ASSERT(io); + b[1]=((Lib3dsWord)w & 0xFF00) >> 8; + b[0]=((Lib3dsWord)w & 0x00FF); + if (lib3ds_io_write(io, b, 2)!=2) { + return(LIB3DS_FALSE); + } + return(LIB3DS_TRUE); +} + + +/*! + * \ingroup io + * + * Writes a dword into a little endian file stream. + */ +Lib3dsBool +lib3ds_io_write_dword(Lib3dsIo *io, Lib3dsDword d) +{ + Lib3dsByte b[4]; + + ASSERT(io); + b[3]=(Lib3dsByte)(((Lib3dsDword)d & 0xFF000000) >> 24); + b[2]=(Lib3dsByte)(((Lib3dsDword)d & 0x00FF0000) >> 16); + b[1]=(Lib3dsByte)(((Lib3dsDword)d & 0x0000FF00) >> 8); + b[0]=(Lib3dsByte)(((Lib3dsDword)d & 0x000000FF)); + if (lib3ds_io_write(io, b, 4)!=4) { + return(LIB3DS_FALSE); + } + return(LIB3DS_TRUE); +} + + +/*! + * \ingroup io + * + * Writes a signed byte in a file stream. + */ +Lib3dsBool +lib3ds_io_write_intb(Lib3dsIo *io, Lib3dsIntb b) +{ + ASSERT(io); + if (lib3ds_io_write(io, &b, 1)!=1) { + return(LIB3DS_FALSE); + } + return(LIB3DS_TRUE); +} + + +/*! + * \ingroup io + * + * Writes a signed word into a little endian file stream. + */ +Lib3dsBool +lib3ds_io_write_intw(Lib3dsIo *io, Lib3dsIntw w) +{ + Lib3dsByte b[2]; + + ASSERT(io); + b[1]=((Lib3dsWord)w & 0xFF00) >> 8; + b[0]=((Lib3dsWord)w & 0x00FF); + if (lib3ds_io_write(io, b, 2)!=2) { + return(LIB3DS_FALSE); + } + return(LIB3DS_TRUE); +} + + +/*! + * \ingroup io + * + * Writes a signed dword into a little endian file stream. + */ +Lib3dsBool +lib3ds_io_write_intd(Lib3dsIo *io, Lib3dsIntd d) +{ + Lib3dsByte b[4]; + + ASSERT(io); + b[3]=(Lib3dsByte)(((Lib3dsDword)d & 0xFF000000) >> 24); + b[2]=(Lib3dsByte)(((Lib3dsDword)d & 0x00FF0000) >> 16); + b[1]=(Lib3dsByte)(((Lib3dsDword)d & 0x0000FF00) >> 8); + b[0]=(Lib3dsByte)(((Lib3dsDword)d & 0x000000FF)); + if (lib3ds_io_write(io, b, 4)!=4) { + return(LIB3DS_FALSE); + } + return(LIB3DS_TRUE); +} + + +/*! + * \ingroup io + * + * Writes a float into a little endian file stream. + */ +Lib3dsBool +lib3ds_io_write_float(Lib3dsIo *io, Lib3dsFloat l) +{ + Lib3dsByte b[4]; + Lib3dsDwordFloat d; + + ASSERT(io); + d.float_value=l; + b[3]=(Lib3dsByte)(((Lib3dsDword)d.dword_value & 0xFF000000) >> 24); + b[2]=(Lib3dsByte)(((Lib3dsDword)d.dword_value & 0x00FF0000) >> 16); + b[1]=(Lib3dsByte)(((Lib3dsDword)d.dword_value & 0x0000FF00) >> 8); + b[0]=(Lib3dsByte)(((Lib3dsDword)d.dword_value & 0x000000FF)); + if (lib3ds_io_write(io, b, 4)!=4) { + return(LIB3DS_FALSE); + } + return(LIB3DS_TRUE); +} + + +/*! + * \ingroup io + * + * Writes a vector into a file stream in little endian format. + */ +Lib3dsBool +lib3ds_io_write_vector(Lib3dsIo *io, Lib3dsVector v) +{ + int i; + for (i=0; i<3; ++i) { + if (!lib3ds_io_write_float(io, v[i])) { + return(LIB3DS_FALSE); + } + } + return(LIB3DS_TRUE); +} + + +/*! + * \ingroup io + */ +Lib3dsBool +lib3ds_io_write_rgb(Lib3dsIo *io, Lib3dsRgb rgb) +{ + int i; + for (i=0; i<3; ++i) { + if (!lib3ds_io_write_float(io, rgb[i])) { + return(LIB3DS_FALSE); + } + } + return(LIB3DS_TRUE); +} + + +/*! + * \ingroup io + * + * Writes a zero-terminated string into a file stream. + */ +Lib3dsBool +lib3ds_io_write_string(Lib3dsIo *io, const char *s) +{ + ASSERT(s); + ASSERT(io); + lib3ds_io_write(io, s, strlen(s)+1); + return(!lib3ds_io_error(io)); +} diff --git a/3rdparty/lib3ds/io.h b/3rdparty/lib3ds/io.h new file mode 100644 index 000000000..b69a973ad --- /dev/null +++ b/3rdparty/lib3ds/io.h @@ -0,0 +1,82 @@ +/* -*- c -*- */ +#ifndef INCLUDED_LIB3DS_IO_H +#define INCLUDED_LIB3DS_IO_H +/* + * The 3D Studio File Format Library + * Copyright (C) 1996-2007 by Jan Eric Kyprianidis <www.kyprianidis.com> + * 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: io.h,v 1.6 2007/06/20 17:04:08 jeh Exp $ + */ + +#ifndef INCLUDED_LIB3DS_TYPES_H +#include <lib3ds/types.h> +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum Lib3dsIoSeek { + LIB3DS_SEEK_SET =0, + LIB3DS_SEEK_CUR =1, + LIB3DS_SEEK_END =2 +} Lib3dsIoSeek; + +typedef Lib3dsBool (*Lib3dsIoErrorFunc)(void *self); +typedef long (*Lib3dsIoSeekFunc)(void *self, long offset, Lib3dsIoSeek origin); +typedef long (*Lib3dsIoTellFunc)(void *self); +typedef size_t (*Lib3dsIoReadFunc)(void *self, void *buffer, size_t size); +typedef size_t (*Lib3dsIoWriteFunc)(void *self, const void *buffer, size_t size); + +extern LIB3DSAPI Lib3dsIo* lib3ds_io_new(void *self, Lib3dsIoErrorFunc error_func, + Lib3dsIoSeekFunc seek_func, Lib3dsIoTellFunc tell_func, + Lib3dsIoReadFunc read_func, Lib3dsIoWriteFunc write_func); +extern LIB3DSAPI void lib3ds_io_free(Lib3dsIo *io); +extern LIB3DSAPI Lib3dsBool lib3ds_io_error(Lib3dsIo *io); +extern LIB3DSAPI long lib3ds_io_seek(Lib3dsIo *io, long offset, Lib3dsIoSeek origin); +extern LIB3DSAPI long lib3ds_io_tell(Lib3dsIo *io); +extern LIB3DSAPI size_t lib3ds_io_read(Lib3dsIo *io, void *buffer, size_t size); +extern LIB3DSAPI size_t lib3ds_io_write(Lib3dsIo *io, const void *buffer, size_t size); + +extern LIB3DSAPI Lib3dsByte lib3ds_io_read_byte(Lib3dsIo *io); +extern LIB3DSAPI Lib3dsWord lib3ds_io_read_word(Lib3dsIo *io); +extern LIB3DSAPI Lib3dsDword lib3ds_io_read_dword(Lib3dsIo *io); +extern LIB3DSAPI Lib3dsIntb lib3ds_io_read_intb(Lib3dsIo *io); +extern LIB3DSAPI Lib3dsIntw lib3ds_io_read_intw(Lib3dsIo *io); +extern LIB3DSAPI Lib3dsIntd lib3ds_io_read_intd(Lib3dsIo *io); +extern LIB3DSAPI Lib3dsFloat lib3ds_io_read_float(Lib3dsIo *io); +extern LIB3DSAPI Lib3dsBool lib3ds_io_read_vector(Lib3dsIo *io, Lib3dsVector v); +extern LIB3DSAPI Lib3dsBool lib3ds_io_read_rgb(Lib3dsIo *io, Lib3dsRgb rgb); +extern LIB3DSAPI Lib3dsBool lib3ds_io_read_string(Lib3dsIo *io, char *s, int buflen); + +extern LIB3DSAPI Lib3dsBool lib3ds_io_write_byte(Lib3dsIo *io, Lib3dsByte b); +extern LIB3DSAPI Lib3dsBool lib3ds_io_write_word(Lib3dsIo *io, Lib3dsWord w); +extern LIB3DSAPI Lib3dsBool lib3ds_io_write_dword(Lib3dsIo *io, Lib3dsDword d); +extern LIB3DSAPI Lib3dsBool lib3ds_io_write_intb(Lib3dsIo *io, Lib3dsIntb b); +extern LIB3DSAPI Lib3dsBool lib3ds_io_write_intw(Lib3dsIo *io, Lib3dsIntw w); +extern LIB3DSAPI Lib3dsBool lib3ds_io_write_intd(Lib3dsIo *io, Lib3dsIntd d); +extern LIB3DSAPI Lib3dsBool lib3ds_io_write_float(Lib3dsIo *io, Lib3dsFloat l); +extern LIB3DSAPI Lib3dsBool lib3ds_io_write_vector(Lib3dsIo *io, Lib3dsVector v); +extern LIB3DSAPI Lib3dsBool lib3ds_io_write_rgb(Lib3dsIo *io, Lib3dsRgb rgb); +extern LIB3DSAPI Lib3dsBool lib3ds_io_write_string(Lib3dsIo *io, const char *s); + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/3rdparty/lib3ds/lib3ds.pri b/3rdparty/lib3ds/lib3ds.pri new file mode 100644 index 000000000..4f08f981b --- /dev/null +++ b/3rdparty/lib3ds/lib3ds.pri @@ -0,0 +1,44 @@ +INCLUDEPATH += $$PWD $$PWD/.. +VPATH += $$PWD + +HEADERS += \ + atmosphere.h \ + background.h \ + camera.h \ + chunk.h \ + chunktable.h \ + ease.h \ + file.h \ + io.h \ + light.h \ + material.h \ + matrix.h \ + mesh.h \ + node.h \ + quat.h \ + shadow.h \ + tcb.h \ + tracks.h \ + types.h \ + vector.h \ + viewport.h + +SOURCES += \ + atmosphere.c \ + background.c \ + camera.c \ + chunk.c \ + ease.c \ + file.c \ + io.c \ + light.c \ + material.c \ + matrix.c \ + mesh.c \ + node.c \ + quat.c \ + shadow.c \ + tcb.c \ + tracks.c \ + vector.c \ + viewport.c diff --git a/3rdparty/lib3ds/light.c b/3rdparty/lib3ds/light.c new file mode 100644 index 000000000..99a3ee682 --- /dev/null +++ b/3rdparty/lib3ds/light.c @@ -0,0 +1,414 @@ +/* + * The 3D Studio File Format Library + * Copyright (C) 1996-2007 by Jan Eric Kyprianidis <www.kyprianidis.com> + * 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: light.c,v 1.15 2007/06/20 17:04:08 jeh Exp $ + */ +#include <lib3ds/light.h> +#include <lib3ds/chunk.h> +#include <lib3ds/io.h> +#include <stdlib.h> +#include <math.h> +#include <string.h> + + +/*! + * \defgroup light Lights + */ + + +/*! + * \ingroup light + */ +Lib3dsLight* +lib3ds_light_new(const char *name) +{ + Lib3dsLight *light; + + ASSERT(name); + ASSERT(strlen(name)<64); + + light=(Lib3dsLight*)calloc(sizeof(Lib3dsLight), 1); + if (!light) { + return(0); + } + strcpy(light->name, name); + return(light); +} + + +/*! + * \ingroup light + */ +void +lib3ds_light_free(Lib3dsLight *light) +{ + memset(light, 0, sizeof(Lib3dsLight)); + free(light); +} + + +/*! + * \ingroup light + */ +void +lib3ds_light_dump(Lib3dsLight *light) +{ + ASSERT(light); + printf(" name: %s\n", light->name); + printf(" spot_light: %s\n", light->spot_light ? "yes" : "no"); + printf(" see_cone: %s\n", light->see_cone ? "yes" : "no"); + printf(" color: (%f, %f, %f)\n", + light->color[0], light->color[1], light->color[2]); + printf(" position (%f, %f, %f)\n", + light->position[0], light->position[1], light->position[2]); + printf(" spot (%f, %f, %f)\n", + light->spot[0], light->spot[1], light->spot[2]); + printf(" roll: %f\n", light->roll); + printf(" off: %s\n", light->off ? "yes" : "no"); + printf(" outer_range: %f\n", light->outer_range); + printf(" inner_range: %f\n", light->inner_range); + printf(" multiplier: %f\n", light->multiplier); + printf(" attenuation: %f\n", light->attenuation); + printf(" rectangular_spot: %s\n", light->rectangular_spot ? "yes" : "no"); + printf(" shadowed: %s\n", light->shadowed ? "yes" : "no"); + printf(" shadow_bias: %f\n", light->shadow_bias); + printf(" shadow_filter: %f\n", light->shadow_filter); + printf(" shadow_size: %d\n", light->shadow_size); + printf(" spot_aspect: %f\n", light->spot_aspect); + printf(" use_projector: %s\n", light->use_projector ? "yes" : "no"); + printf(" projector: %s\n", light->projector); + printf(" spot_overshoot: %d\n", (int)light->spot_overshoot); + printf(" ray_shadows: %s\n", light->ray_shadows ? "yes" : "no"); + printf(" ray_bias: %f\n", light->ray_bias); + printf(" hot_spot: %f\n", light->hot_spot); + printf(" fall_off: %f\n", light->fall_off); + printf("\n"); +} + + +/*! + * \ingroup light + */ +static Lib3dsBool +spotlight_read(Lib3dsLight *light, Lib3dsIo *io) +{ + Lib3dsChunk c; + Lib3dsWord chunk; + int i; + + if (!lib3ds_chunk_read_start(&c, LIB3DS_DL_SPOTLIGHT, io)) { + return(LIB3DS_FALSE); + } + light->spot_light=LIB3DS_TRUE; + for (i=0; i<3; ++i) { + light->spot[i]=lib3ds_io_read_float(io); + } + light->hot_spot = lib3ds_io_read_float(io); + light->fall_off = lib3ds_io_read_float(io); + lib3ds_chunk_read_tell(&c, io); + + while ((chunk=lib3ds_chunk_read_next(&c, io))!=0) { + switch (chunk) { + case LIB3DS_DL_SPOT_ROLL: + { + light->roll=lib3ds_io_read_float(io); + } + break; + case LIB3DS_DL_SHADOWED: + { + light->shadowed=LIB3DS_TRUE; + } + break; + case LIB3DS_DL_LOCAL_SHADOW2: + { + light->shadow_bias=lib3ds_io_read_float(io); + light->shadow_filter=lib3ds_io_read_float(io); + light->shadow_size=lib3ds_io_read_intw(io); + } + break; + case LIB3DS_DL_SEE_CONE: + { + light->see_cone=LIB3DS_TRUE; + } + break; + case LIB3DS_DL_SPOT_RECTANGULAR: + { + light->rectangular_spot=LIB3DS_TRUE; + } + break; + case LIB3DS_DL_SPOT_ASPECT: + { + light->spot_aspect=lib3ds_io_read_float(io); + } + break; + case LIB3DS_DL_SPOT_PROJECTOR: + { + light->use_projector=LIB3DS_TRUE; + if (!lib3ds_io_read_string(io, light->projector, 64)) { + return(LIB3DS_FALSE); + } + } + case LIB3DS_DL_SPOT_OVERSHOOT: + { + light->spot_overshoot=LIB3DS_TRUE; + } + break; + case LIB3DS_DL_RAY_BIAS: + { + light->ray_bias=lib3ds_io_read_float(io); + } + break; + case LIB3DS_DL_RAYSHAD: + { + light->ray_shadows=LIB3DS_TRUE; + } + break; + default: + lib3ds_chunk_unknown(chunk); + } + } + + lib3ds_chunk_read_end(&c, io); + return(LIB3DS_TRUE); +} + + +/*! + * \ingroup light + */ +Lib3dsBool +lib3ds_light_read(Lib3dsLight *light, Lib3dsIo *io) +{ + Lib3dsChunk c; + Lib3dsWord chunk; + + if (!lib3ds_chunk_read_start(&c, LIB3DS_N_DIRECT_LIGHT, io)) { + return(LIB3DS_FALSE); + } + { + int i; + for (i=0; i<3; ++i) { + light->position[i]=lib3ds_io_read_float(io); + } + } + lib3ds_chunk_read_tell(&c, io); + + while ((chunk=lib3ds_chunk_read_next(&c, io))!=0) { + switch (chunk) { + case LIB3DS_COLOR_F: + { + int i; + for (i=0; i<3; ++i) { + light->color[i]=lib3ds_io_read_float(io); + } + } + break; + case LIB3DS_DL_OFF: + { + light->off=LIB3DS_TRUE; + } + break; + case LIB3DS_DL_OUTER_RANGE: + { + light->outer_range=lib3ds_io_read_float(io); + } + break; + case LIB3DS_DL_INNER_RANGE: + { + light->inner_range=lib3ds_io_read_float(io); + } + break; + case LIB3DS_DL_MULTIPLIER: + { + light->multiplier=lib3ds_io_read_float(io); + } + break; + case LIB3DS_DL_EXCLUDE: + { + /* FIXME: */ + lib3ds_chunk_unknown(chunk); + } + case LIB3DS_DL_ATTENUATE: + { + light->attenuation=lib3ds_io_read_float(io); + } + break; + case LIB3DS_DL_SPOTLIGHT: + { + lib3ds_chunk_read_reset(&c, io); + if (!spotlight_read(light, io)) { + return(LIB3DS_FALSE); + } + } + break; + default: + lib3ds_chunk_unknown(chunk); + } + } + + lib3ds_chunk_read_end(&c, io); + return(LIB3DS_TRUE); +} + + +/*! + * \ingroup light + */ +Lib3dsBool +lib3ds_light_write(Lib3dsLight *light, Lib3dsIo *io) +{ + Lib3dsChunk c; + + c.chunk=LIB3DS_N_DIRECT_LIGHT; + if (!lib3ds_chunk_write_start(&c,io)) { + return(LIB3DS_FALSE); + } + lib3ds_io_write_vector(io, light->position); + { /*---- LIB3DS_COLOR_F ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_COLOR_F; + c.size=18; + lib3ds_chunk_write(&c, io); + lib3ds_io_write_rgb(io, light->color); + } + if (light->off) { /*---- LIB3DS_DL_OFF ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_DL_OFF; + c.size=6; + lib3ds_chunk_write(&c, io); + } + { /*---- LIB3DS_DL_OUTER_RANGE ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_DL_OUTER_RANGE; + c.size=10; + lib3ds_chunk_write(&c, io); + lib3ds_io_write_float(io, light->outer_range); + } + { /*---- LIB3DS_DL_INNER_RANGE ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_DL_INNER_RANGE; + c.size=10; + lib3ds_chunk_write(&c, io); + lib3ds_io_write_float(io, light->inner_range); + } + { /*---- LIB3DS_DL_MULTIPLIER ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_DL_MULTIPLIER; + c.size=10; + lib3ds_chunk_write(&c, io); + lib3ds_io_write_float(io, light->multiplier); + } + if (light->attenuation) { /*---- LIB3DS_DL_ATTENUATE ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_DL_ATTENUATE; + c.size=6; + lib3ds_chunk_write(&c, io); + } + + if (light->spot_light) { + Lib3dsChunk c; + + c.chunk=LIB3DS_DL_SPOTLIGHT; + if (!lib3ds_chunk_write_start(&c,io)) { + return(LIB3DS_FALSE); + } + lib3ds_io_write_vector(io, light->spot); + lib3ds_io_write_float(io, light->hot_spot); + lib3ds_io_write_float(io, light->fall_off); + + { /*---- LIB3DS_DL_SPOT_ROLL ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_DL_SPOT_ROLL; + c.size=10; + lib3ds_chunk_write(&c, io); + lib3ds_io_write_float(io, light->roll); + } + if (light->shadowed) { /*---- LIB3DS_DL_SHADOWED ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_DL_SHADOWED; + c.size=6; + lib3ds_chunk_write(&c, io); + } + if ((fabs(light->shadow_bias)>LIB3DS_EPSILON) || + (fabs(light->shadow_filter)>LIB3DS_EPSILON) || + (light->shadow_size!=0)) { /*---- LIB3DS_DL_LOCAL_SHADOW2 ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_DL_LOCAL_SHADOW2; + c.size=16; + lib3ds_chunk_write(&c, io); + lib3ds_io_write_float(io, light->shadow_bias); + lib3ds_io_write_float(io, light->shadow_filter); + lib3ds_io_write_intw(io, light->shadow_size); + } + if (light->see_cone) { /*---- LIB3DS_DL_SEE_CONE ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_DL_SEE_CONE; + c.size=6; + lib3ds_chunk_write(&c, io); + } + if (light->rectangular_spot) { /*---- LIB3DS_DL_SPOT_RECTANGULAR ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_DL_SPOT_RECTANGULAR; + c.size=6; + lib3ds_chunk_write(&c, io); + } + if (fabs(light->spot_aspect)>LIB3DS_EPSILON) { /*---- LIB3DS_DL_SPOT_ASPECT ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_DL_SPOT_ASPECT; + c.size=10; + lib3ds_chunk_write(&c, io); + lib3ds_io_write_float(io, light->spot_aspect); + } + if (light->use_projector) { /*---- LIB3DS_DL_SPOT_PROJECTOR ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_DL_SPOT_PROJECTOR; + c.size=10; + lib3ds_chunk_write(&c, io); + lib3ds_io_write_string(io, light->projector); + } + if (light->spot_overshoot) { /*---- LIB3DS_DL_SPOT_OVERSHOOT ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_DL_SPOT_OVERSHOOT; + c.size=6; + lib3ds_chunk_write(&c, io); + } + if (fabs(light->ray_bias)>LIB3DS_EPSILON) { /*---- LIB3DS_DL_RAY_BIAS ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_DL_RAY_BIAS; + c.size=10; + lib3ds_chunk_write(&c, io); + lib3ds_io_write_float(io, light->ray_bias); + } + if (light->ray_shadows) { /*---- LIB3DS_DL_RAYSHAD ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_DL_RAYSHAD; + c.size=6; + lib3ds_chunk_write(&c, io); + } + if (!lib3ds_chunk_write_end(&c,io)) { + return(LIB3DS_FALSE); + } + } + if (!lib3ds_chunk_write_end(&c,io)) { + return(LIB3DS_FALSE); + } + return(LIB3DS_TRUE); +} + + diff --git a/3rdparty/lib3ds/light.h b/3rdparty/lib3ds/light.h new file mode 100644 index 000000000..d8010d936 --- /dev/null +++ b/3rdparty/lib3ds/light.h @@ -0,0 +1,79 @@ +/* -*- c -*- */ +#ifndef INCLUDED_LIB3DS_LIGHT_H +#define INCLUDED_LIB3DS_LIGHT_H +/* + * The 3D Studio File Format Library + * Copyright (C) 1996-2007 by Jan Eric Kyprianidis <www.kyprianidis.com> + * 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: light.h,v 1.13 2007/06/20 17:04:08 jeh Exp $ + */ + +#ifndef INCLUDED_LIB3DS_TYPES_H +#include <lib3ds/types.h> +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Light + * \ingroup light + */ +struct Lib3dsLight { + Lib3dsLight *next; + char name[64]; + Lib3dsDword object_flags; /*< @see Lib3dsObjectFlags */ + Lib3dsBool spot_light; + Lib3dsBool see_cone; + Lib3dsRgb color; + Lib3dsVector position; + Lib3dsVector spot; + Lib3dsFloat roll; + Lib3dsBool off; + Lib3dsFloat outer_range; + Lib3dsFloat inner_range; + Lib3dsFloat multiplier; + /*const char** excludes;*/ + Lib3dsFloat attenuation; + Lib3dsBool rectangular_spot; + Lib3dsBool shadowed; + Lib3dsFloat shadow_bias; + Lib3dsFloat shadow_filter; + Lib3dsIntw shadow_size; + Lib3dsFloat spot_aspect; + Lib3dsBool use_projector; + char projector[64]; + Lib3dsIntd spot_overshoot; + Lib3dsBool ray_shadows; + Lib3dsFloat ray_bias; + Lib3dsFloat hot_spot; + Lib3dsFloat fall_off; +}; + +extern LIB3DSAPI Lib3dsLight* lib3ds_light_new(const char *name); +extern LIB3DSAPI void lib3ds_light_free(Lib3dsLight *mesh); +extern LIB3DSAPI void lib3ds_light_dump(Lib3dsLight *light); +extern LIB3DSAPI Lib3dsBool lib3ds_light_read(Lib3dsLight *light, Lib3dsIo *io); +extern LIB3DSAPI Lib3dsBool lib3ds_light_write(Lib3dsLight *light, Lib3dsIo *io); + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/3rdparty/lib3ds/material.c b/3rdparty/lib3ds/material.c new file mode 100644 index 000000000..4cd64e951 --- /dev/null +++ b/3rdparty/lib3ds/material.c @@ -0,0 +1,1089 @@ +/* + * The 3D Studio File Format Library + * Copyright (C) 1996-2007 by Jan Eric Kyprianidis <www.kyprianidis.com> + * 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: material.c,v 1.24 2007/06/20 17:04:08 jeh Exp $ + */ +#include <lib3ds/material.h> +#include <lib3ds/chunk.h> +#include <lib3ds/io.h> +#include <stdlib.h> +#include <math.h> +#include <string.h> + + +/*! + * \defgroup material Materials + */ + + +static void +initialize_texture_map(Lib3dsTextureMap *map) +{ + map->flags = 0x10; + map->percent = 1.0f; + map->scale[0] = 1.0f; + map->scale[1] = 1.0f; +} + + +/*! + * Creates and returns a new, empty Lib3dsMaterial object. + * + * Initial value of the material is a shiny grey. + * + * \return A pointer to the Lib3dsMaterial structure. + * If the structure cannot be allocated, NULL is returned. + * + * \ingroup material + */ +Lib3dsMaterial* +lib3ds_material_new() +{ + Lib3dsMaterial *mat; + + mat = (Lib3dsMaterial*)calloc(sizeof(Lib3dsMaterial), 1); + if (!mat) { + return(0); + } + + mat->ambient[0] = mat->ambient[1] = mat->ambient[2] = 0.588235f; + mat->diffuse[0] = mat->diffuse[1] = mat->diffuse[2] = 0.588235f; + mat->specular[0] = mat->specular[1] = mat->specular[2] = 0.898039f; + mat->shininess = 0.1f; + mat->wire_size = 1.0f; + mat->shading = 3; + + initialize_texture_map(&mat->texture1_map); + initialize_texture_map(&mat->texture1_mask); + initialize_texture_map(&mat->texture2_map); + initialize_texture_map(&mat->texture2_mask); + initialize_texture_map(&mat->opacity_map); + initialize_texture_map(&mat->opacity_mask); + initialize_texture_map(&mat->bump_map); + initialize_texture_map(&mat->bump_mask); + initialize_texture_map(&mat->specular_map); + initialize_texture_map(&mat->specular_mask); + initialize_texture_map(&mat->shininess_map); + initialize_texture_map(&mat->shininess_mask); + initialize_texture_map(&mat->self_illum_map); + initialize_texture_map(&mat->self_illum_mask); + initialize_texture_map(&mat->reflection_map); + initialize_texture_map(&mat->reflection_mask); + + return(mat); +} + + +/*! + * \ingroup material + */ +void +lib3ds_material_free(Lib3dsMaterial *material) +{ + memset(material, 0, sizeof(Lib3dsMaterial)); + free(material); +} + + +static Lib3dsBool +color_read(Lib3dsRgba rgb, Lib3dsIo *io) +{ + Lib3dsChunk c; + Lib3dsWord chunk; + Lib3dsBool have_lin=LIB3DS_FALSE; + + if (!lib3ds_chunk_read_start(&c, 0, io)) { + return(LIB3DS_FALSE); + } + + while ((chunk=lib3ds_chunk_read_next(&c, io))!=0) { + switch (chunk) { + case LIB3DS_LIN_COLOR_24: + { + int i; + for (i=0; i<3; ++i) { + rgb[i]=1.0f*lib3ds_io_read_byte(io)/255.0f; + } + rgb[3]=1.0f; + } + have_lin=LIB3DS_TRUE; + break; + case LIB3DS_COLOR_24: + /* gamma corrected color chunk + replaced in 3ds R3 by LIN_COLOR_24 */ + if (!have_lin) { + int i; + for (i=0; i<3; ++i) { + rgb[i]=1.0f*lib3ds_io_read_byte(io)/255.0f; + } + rgb[3]=1.0f; + } + break; + case LIB3DS_LIN_COLOR_F: + { + int i; + for (i=0; i<3; ++i) { + rgb[i]=lib3ds_io_read_float(io); + } + rgb[3]=1.0f; + } + have_lin=LIB3DS_TRUE; + break; + case LIB3DS_COLOR_F: + if (!have_lin) { + int i; + for (i=0; i<3; ++i) { + rgb[i]=lib3ds_io_read_float(io); + } + rgb[3]=1.0f; + } + break; + default: + lib3ds_chunk_unknown(chunk); + } + } + + lib3ds_chunk_read_end(&c, io); + return(LIB3DS_TRUE); +} + + +static Lib3dsBool +int_percentage_read(Lib3dsFloat *p, Lib3dsIo *io) +{ + Lib3dsChunk c; + Lib3dsWord chunk; + + if (!lib3ds_chunk_read_start(&c, 0, io)) { + return(LIB3DS_FALSE); + } + + while ((chunk=lib3ds_chunk_read_next(&c, io))!=0) { + switch (chunk) { + case LIB3DS_INT_PERCENTAGE: + { + Lib3dsIntw i=lib3ds_io_read_intw(io); + *p=(Lib3dsFloat)(1.0*i/100.0); + } + break; + default: + lib3ds_chunk_unknown(chunk); + } + } + + lib3ds_chunk_read_end(&c, io); + return(LIB3DS_TRUE); +} + + +static Lib3dsBool +texture_map_read(Lib3dsTextureMap *map, Lib3dsIo *io) +{ + Lib3dsChunk c; + Lib3dsWord chunk; + + if (!lib3ds_chunk_read_start(&c, 0, io)) { + return(LIB3DS_FALSE); + } + + while ((chunk=lib3ds_chunk_read_next(&c, io))!=0) { + switch (chunk) { + case LIB3DS_INT_PERCENTAGE: + { + map->percent=1.0f*lib3ds_io_read_intw(io)/100.0f; + } + break; + case LIB3DS_MAT_MAPNAME: + { + if (!lib3ds_io_read_string(io, map->name, 64)) { + return(LIB3DS_FALSE); + } + lib3ds_chunk_dump_info(" NAME=%s", map->name); + } + break; + case LIB3DS_MAT_MAP_TILING: + { + map->flags=lib3ds_io_read_word(io); + } + break; + case LIB3DS_MAT_MAP_TEXBLUR: + { + map->blur=lib3ds_io_read_float(io); + } + break; + case LIB3DS_MAT_MAP_USCALE: + { + map->scale[0]=lib3ds_io_read_float(io); + } + break; + case LIB3DS_MAT_MAP_VSCALE: + { + map->scale[1]=lib3ds_io_read_float(io); + } + break; + case LIB3DS_MAT_MAP_UOFFSET: + { + map->offset[0]=lib3ds_io_read_float(io); + } + break; + case LIB3DS_MAT_MAP_VOFFSET: + { + map->offset[1]=lib3ds_io_read_float(io); + } + break; + case LIB3DS_MAT_MAP_ANG: + { + map->rotation=lib3ds_io_read_float(io); + } + break; + case LIB3DS_MAT_MAP_COL1: + { + map->tint_1[0]=1.0f*lib3ds_io_read_byte(io)/255.0f; + map->tint_1[1]=1.0f*lib3ds_io_read_byte(io)/255.0f; + map->tint_1[2]=1.0f*lib3ds_io_read_byte(io)/255.0f; + } + break; + case LIB3DS_MAT_MAP_COL2: + { + map->tint_2[0]=1.0f*lib3ds_io_read_byte(io)/255.0f; + map->tint_2[1]=1.0f*lib3ds_io_read_byte(io)/255.0f; + map->tint_2[2]=1.0f*lib3ds_io_read_byte(io)/255.0f; + } + break; + case LIB3DS_MAT_MAP_RCOL: + { + map->tint_r[0]=1.0f*lib3ds_io_read_byte(io)/255.0f; + map->tint_r[1]=1.0f*lib3ds_io_read_byte(io)/255.0f; + map->tint_r[2]=1.0f*lib3ds_io_read_byte(io)/255.0f; + } + break; + case LIB3DS_MAT_MAP_GCOL: + { + map->tint_g[0]=1.0f*lib3ds_io_read_byte(io)/255.0f; + map->tint_g[1]=1.0f*lib3ds_io_read_byte(io)/255.0f; + map->tint_g[2]=1.0f*lib3ds_io_read_byte(io)/255.0f; + } + break; + case LIB3DS_MAT_MAP_BCOL: + { + map->tint_b[0]=1.0f*lib3ds_io_read_byte(io)/255.0f; + map->tint_b[1]=1.0f*lib3ds_io_read_byte(io)/255.0f; + map->tint_b[2]=1.0f*lib3ds_io_read_byte(io)/255.0f; + } + break; + default: + lib3ds_chunk_unknown(chunk); + } + } + + lib3ds_chunk_read_end(&c, io); + return(LIB3DS_TRUE); +} + + +/*! + * \ingroup material + */ +static void +texture_dump(const char *maptype, Lib3dsTextureMap *texture) +{ + ASSERT(texture); + if (strlen(texture->name)==0) { + return; + } + printf(" %s:\n", maptype); + printf(" name: %s\n", texture->name); + printf(" flags: %X\n", (unsigned)texture->flags); + printf(" percent: %f\n", texture->percent); + printf(" blur: %f\n", texture->blur); + printf(" scale: (%f, %f)\n", texture->scale[0], texture->scale[1]); + printf(" offset: (%f, %f)\n", texture->offset[0], texture->offset[1]); + printf(" rotation: %f\n", texture->rotation); + printf(" tint_1: (%f, %f, %f)\n", + texture->tint_1[0], texture->tint_1[1], texture->tint_1[2]); + printf(" tint_2: (%f, %f, %f)\n", + texture->tint_2[0], texture->tint_2[1], texture->tint_2[2]); + printf(" tint_r: (%f, %f, %f)\n", + texture->tint_r[0], texture->tint_r[1], texture->tint_r[2]); + printf(" tint_g: (%f, %f, %f)\n", + texture->tint_g[0], texture->tint_g[1], texture->tint_g[2]); + printf(" tint_b: (%f, %f, %f)\n", + texture->tint_b[0], texture->tint_b[1], texture->tint_b[2]); +} + + +/*! + * \ingroup material + */ +void +lib3ds_material_dump(Lib3dsMaterial *material) +{ + ASSERT(material); + printf(" name: %s\n", material->name); + printf(" ambient: (%f, %f, %f)\n", + material->ambient[0], material->ambient[1], material->ambient[2]); + printf(" diffuse: (%f, %f, %f)\n", + material->diffuse[0], material->diffuse[1], material->diffuse[2]); + printf(" specular: (%f, %f, %f)\n", + material->specular[0], material->specular[1], material->specular[2]); + printf(" shininess: %f\n", material->shininess); + printf(" shin_strength: %f\n", material->shin_strength); + printf(" use_blur: %s\n", material->use_blur ? "yes" : "no"); + printf(" blur: %f\n", material->blur); + printf(" falloff: %f\n", material->falloff); + printf(" additive: %s\n", material->additive ? "yes" : "no"); + printf(" use_falloff: %s\n", material->use_falloff ? "yes" : "no"); + printf(" self_illum: %s\n", material->self_illum ? "yes" : "no"); + printf(" self_ilpct: %f\n", material->self_ilpct); + printf(" shading: %d\n", material->shading); + printf(" soften: %s\n", material->soften ? "yes" : "no"); + printf(" face_map: %s\n", material->face_map ? "yes" : "no"); + printf(" two_sided: %s\n", material->two_sided ? "yes" : "no"); + printf(" map_decal: %s\n", material->map_decal ? "yes" : "no"); + printf(" use_wire: %s\n", material->use_wire ? "yes" : "no"); + printf(" use_wire_abs: %s\n", material->use_wire_abs ? "yes" : "no"); + printf(" wire_size: %f\n", material->wire_size); + texture_dump("texture1_map", &material->texture1_map); + texture_dump("texture1_mask", &material->texture1_mask); + texture_dump("texture2_map", &material->texture2_map); + texture_dump("texture2_mask", &material->texture2_mask); + texture_dump("opacity_map", &material->opacity_map); + texture_dump("opacity_mask", &material->opacity_mask); + texture_dump("bump_map", &material->bump_map); + texture_dump("bump_mask", &material->bump_mask); + texture_dump("specular_map", &material->specular_map); + texture_dump("specular_mask", &material->specular_mask); + texture_dump("shininess_map", &material->shininess_map); + texture_dump("shininess_mask", &material->shininess_mask); + texture_dump("self_illum_map", &material->self_illum_map); + texture_dump("self_illum_mask", &material->self_illum_mask); + texture_dump("reflection_map", &material->reflection_map); + texture_dump("reflection_mask", &material->reflection_mask); + printf(" autorefl_map:\n"); + printf(" flags %X\n", (unsigned)material->autorefl_map.flags); + printf(" level %d\n", (int)material->autorefl_map.level); + printf(" size %d\n", (int)material->autorefl_map.size); + printf(" frame_step %d\n", (int)material->autorefl_map.frame_step); + printf("\n"); +} + + +/*! + * \ingroup material + */ +Lib3dsBool +lib3ds_material_read(Lib3dsMaterial *material, Lib3dsIo *io) +{ + Lib3dsChunk c; + Lib3dsWord chunk; + + ASSERT(material); + if (!lib3ds_chunk_read_start(&c, LIB3DS_MAT_ENTRY, io)) { + return(LIB3DS_FALSE); + } + + while ((chunk=lib3ds_chunk_read_next(&c, io))!=0) { + switch (chunk) { + case LIB3DS_MAT_NAME: + { + if (!lib3ds_io_read_string(io, material->name, 64)) { + return(LIB3DS_FALSE); + } + lib3ds_chunk_dump_info(" NAME=%s", material->name); + } + break; + case LIB3DS_MAT_AMBIENT: + { + lib3ds_chunk_read_reset(&c, io); + if (!color_read(material->ambient, io)) { + return(LIB3DS_FALSE); + } + } + break; + case LIB3DS_MAT_DIFFUSE: + { + lib3ds_chunk_read_reset(&c, io); + if (!color_read(material->diffuse, io)) { + return(LIB3DS_FALSE); + } + } + break; + case LIB3DS_MAT_SPECULAR: + { + lib3ds_chunk_read_reset(&c, io); + if (!color_read(material->specular, io)) { + return(LIB3DS_FALSE); + } + } + break; + case LIB3DS_MAT_SHININESS: + { + lib3ds_chunk_read_reset(&c, io); + if (!int_percentage_read(&material->shininess, io)) { + return(LIB3DS_FALSE); + } + } + break; + case LIB3DS_MAT_SHIN2PCT: + { + lib3ds_chunk_read_reset(&c, io); + if (!int_percentage_read(&material->shin_strength, io)) { + return(LIB3DS_FALSE); + } + } + break; + case LIB3DS_MAT_TRANSPARENCY: + { + lib3ds_chunk_read_reset(&c, io); + if (!int_percentage_read(&material->transparency, io)) { + return(LIB3DS_FALSE); + } + } + break; + case LIB3DS_MAT_XPFALL: + { + lib3ds_chunk_read_reset(&c, io); + if (!int_percentage_read(&material->falloff, io)) { + return(LIB3DS_FALSE); + } + } + break; + case LIB3DS_MAT_SELF_ILPCT: + { + lib3ds_chunk_read_reset(&c, io); + if (!int_percentage_read(&material->self_ilpct, io)) { + return(LIB3DS_FALSE); + } + } + break; + case LIB3DS_MAT_USE_XPFALL: + { + material->use_falloff=LIB3DS_TRUE; + } + break; + case LIB3DS_MAT_REFBLUR: + { + lib3ds_chunk_read_reset(&c, io); + if (!int_percentage_read(&material->blur, io)) { + return(LIB3DS_FALSE); + } + } + break; + case LIB3DS_MAT_USE_REFBLUR: + { + material->use_blur=LIB3DS_TRUE; + } + break; + case LIB3DS_MAT_SHADING: + { + material->shading=lib3ds_io_read_intw(io); + } + break; + case LIB3DS_MAT_SELF_ILLUM: + { + material->self_illum=LIB3DS_TRUE; + } + break; + case LIB3DS_MAT_TWO_SIDE: + { + material->two_sided=LIB3DS_TRUE; + } + break; + case LIB3DS_MAT_DECAL: + { + material->map_decal=LIB3DS_TRUE; + } + break; + case LIB3DS_MAT_ADDITIVE: + { + material->additive=LIB3DS_TRUE; + } + break; + case LIB3DS_MAT_FACEMAP: + { + material->face_map=LIB3DS_TRUE; + } + break; + case LIB3DS_MAT_PHONGSOFT: + { + material->soften=LIB3DS_TRUE; + } + break; + case LIB3DS_MAT_WIRE: + { + material->use_wire=LIB3DS_TRUE; + } + break; + case LIB3DS_MAT_WIREABS: + { + material->use_wire_abs=LIB3DS_TRUE; + } + break; + case LIB3DS_MAT_WIRE_SIZE: + { + material->wire_size=lib3ds_io_read_float(io); + } + break; + case LIB3DS_MAT_TEXMAP: + { + lib3ds_chunk_read_reset(&c, io); + if (!texture_map_read(&material->texture1_map, io)) { + return(LIB3DS_FALSE); + } + } + break; + case LIB3DS_MAT_TEXMASK: + { + lib3ds_chunk_read_reset(&c, io); + if (!texture_map_read(&material->texture1_mask, io)) { + return(LIB3DS_FALSE); + } + } + break; + case LIB3DS_MAT_TEX2MAP: + { + lib3ds_chunk_read_reset(&c, io); + if (!texture_map_read(&material->texture2_map, io)) { + return(LIB3DS_FALSE); + } + } + break; + case LIB3DS_MAT_TEX2MASK: + { + lib3ds_chunk_read_reset(&c, io); + if (!texture_map_read(&material->texture2_mask, io)) { + return(LIB3DS_FALSE); + } + } + break; + case LIB3DS_MAT_OPACMAP: + { + lib3ds_chunk_read_reset(&c, io); + if (!texture_map_read(&material->opacity_map, io)) { + return(LIB3DS_FALSE); + } + } + break; + case LIB3DS_MAT_OPACMASK: + { + lib3ds_chunk_read_reset(&c, io); + if (!texture_map_read(&material->opacity_mask, io)) { + return(LIB3DS_FALSE); + } + } + break; + case LIB3DS_MAT_BUMPMAP: + { + lib3ds_chunk_read_reset(&c, io); + if (!texture_map_read(&material->bump_map, io)) { + return(LIB3DS_FALSE); + } + } + break; + case LIB3DS_MAT_BUMPMASK: + { + lib3ds_chunk_read_reset(&c, io); + if (!texture_map_read(&material->bump_mask, io)) { + return(LIB3DS_FALSE); + } + } + break; + case LIB3DS_MAT_SPECMAP: + { + lib3ds_chunk_read_reset(&c, io); + if (!texture_map_read(&material->specular_map, io)) { + return(LIB3DS_FALSE); + } + } + break; + case LIB3DS_MAT_SPECMASK: + { + lib3ds_chunk_read_reset(&c, io); + if (!texture_map_read(&material->specular_mask, io)) { + return(LIB3DS_FALSE); + } + } + break; + case LIB3DS_MAT_SHINMAP: + { + lib3ds_chunk_read_reset(&c, io); + if (!texture_map_read(&material->shininess_map, io)) { + return(LIB3DS_FALSE); + } + } + break; + case LIB3DS_MAT_SHINMASK: + { + lib3ds_chunk_read_reset(&c, io); + if (!texture_map_read(&material->shininess_mask, io)) { + return(LIB3DS_FALSE); + } + } + break; + case LIB3DS_MAT_SELFIMAP: + { + lib3ds_chunk_read_reset(&c, io); + if (!texture_map_read(&material->self_illum_map, io)) { + return(LIB3DS_FALSE); + } + } + break; + case LIB3DS_MAT_SELFIMASK: + { + lib3ds_chunk_read_reset(&c, io); + if (!texture_map_read(&material->self_illum_mask, io)) { + return(LIB3DS_FALSE); + } + } + break; + case LIB3DS_MAT_REFLMAP: + { + lib3ds_chunk_read_reset(&c, io); + if (!texture_map_read(&material->reflection_map, io)) { + return(LIB3DS_FALSE); + } + } + break; + case LIB3DS_MAT_REFLMASK: + { + lib3ds_chunk_read_reset(&c, io); + if (!texture_map_read(&material->reflection_mask, io)) { + return(LIB3DS_FALSE); + } + } + break; + case LIB3DS_MAT_ACUBIC: + { + lib3ds_io_read_intb(io); + material->autorefl_map.level=lib3ds_io_read_intb(io); + material->autorefl_map.flags=lib3ds_io_read_intw(io); + material->autorefl_map.size=lib3ds_io_read_intd(io); + material->autorefl_map.frame_step=lib3ds_io_read_intd(io); + } + break; + default: + lib3ds_chunk_unknown(chunk); + } + } + + lib3ds_chunk_read_end(&c, io); + return(LIB3DS_TRUE); +} + + +static Lib3dsBool +color_write(Lib3dsRgba rgb, Lib3dsIo *io) +{ + Lib3dsChunk c; + + c.chunk=LIB3DS_COLOR_24; + c.size=9; + lib3ds_chunk_write(&c,io); + lib3ds_io_write_byte(io, (Lib3dsByte)floor(255.0*rgb[0]+0.5)); + lib3ds_io_write_byte(io, (Lib3dsByte)floor(255.0*rgb[1]+0.5)); + lib3ds_io_write_byte(io, (Lib3dsByte)floor(255.0*rgb[2]+0.5)); + + c.chunk=LIB3DS_LIN_COLOR_24; + c.size=9; + lib3ds_chunk_write(&c,io); + lib3ds_io_write_byte(io, (Lib3dsByte)floor(255.0*rgb[0]+0.5)); + lib3ds_io_write_byte(io, (Lib3dsByte)floor(255.0*rgb[1]+0.5)); + lib3ds_io_write_byte(io, (Lib3dsByte)floor(255.0*rgb[2]+0.5)); + + return(LIB3DS_TRUE); +} + + +static Lib3dsBool +int_percentage_write(Lib3dsFloat p, Lib3dsIo *io) +{ + Lib3dsChunk c; + + c.chunk=LIB3DS_INT_PERCENTAGE; + c.size=8; + lib3ds_chunk_write(&c,io); + lib3ds_io_write_intw(io, (Lib3dsByte)floor(100.0*p+0.5)); + + return(LIB3DS_TRUE); +} + + +static Lib3dsBool +texture_map_write(Lib3dsWord chunk, Lib3dsTextureMap *map, Lib3dsIo *io) +{ + Lib3dsChunk c; + + if (strlen(map->name)==0) { + return(LIB3DS_TRUE); + } + c.chunk=chunk; + if (!lib3ds_chunk_write_start(&c,io)) { + return(LIB3DS_FALSE); + } + + int_percentage_write(map->percent,io); + + { /*---- LIB3DS_MAT_MAPNAME ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_MAT_MAPNAME; + c.size=6+(Lib3dsDword)strlen(map->name)+1; + lib3ds_chunk_write(&c,io); + lib3ds_io_write_string(io, map->name); + } + + { /*---- LIB3DS_MAT_MAP_TILING ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_MAT_MAP_TILING; + c.size=8; + lib3ds_chunk_write(&c,io); + lib3ds_io_write_word(io, (Lib3dsWord)map->flags); + } + + { /*---- LIB3DS_MAT_MAP_TEXBLUR ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_MAT_MAP_TEXBLUR; + c.size=10; + lib3ds_chunk_write(&c,io); + lib3ds_io_write_float(io, map->blur); + } + + { /*---- LIB3DS_MAT_MAP_USCALE ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_MAT_MAP_USCALE; + c.size=10; + lib3ds_chunk_write(&c,io); + lib3ds_io_write_float(io, map->scale[0]); + } + + { /*---- LIB3DS_MAT_MAP_VSCALE ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_MAT_MAP_VSCALE; + c.size=10; + lib3ds_chunk_write(&c,io); + lib3ds_io_write_float(io, map->scale[1]); + } + + { /*---- LIB3DS_MAT_MAP_UOFFSET ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_MAT_MAP_UOFFSET; + c.size=10; + lib3ds_chunk_write(&c,io); + lib3ds_io_write_float(io, map->offset[0]); + } + + { /*---- LIB3DS_MAT_MAP_VOFFSET ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_MAT_MAP_VOFFSET; + c.size=10; + lib3ds_chunk_write(&c,io); + lib3ds_io_write_float(io, map->offset[1]); + } + + { /*---- LIB3DS_MAT_MAP_ANG ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_MAT_MAP_ANG; + c.size=10; + lib3ds_chunk_write(&c,io); + lib3ds_io_write_float(io, map->rotation); + } + + { /*---- LIB3DS_MAT_MAP_COL1 ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_MAT_MAP_COL1; + c.size=9; + lib3ds_chunk_write(&c,io); + lib3ds_io_write_byte(io, (Lib3dsByte)floor(255.0*map->tint_1[0]+0.5)); + lib3ds_io_write_byte(io, (Lib3dsByte)floor(255.0*map->tint_1[1]+0.5)); + lib3ds_io_write_byte(io, (Lib3dsByte)floor(255.0*map->tint_1[2]+0.5)); + } + + { /*---- LIB3DS_MAT_MAP_COL2 ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_MAT_MAP_COL2; + c.size=9; + lib3ds_chunk_write(&c,io); + lib3ds_io_write_byte(io, (Lib3dsByte)floor(255.0*map->tint_2[0]+0.5)); + lib3ds_io_write_byte(io, (Lib3dsByte)floor(255.0*map->tint_2[1]+0.5)); + lib3ds_io_write_byte(io, (Lib3dsByte)floor(255.0*map->tint_2[2]+0.5)); + } + + { /*---- LIB3DS_MAT_MAP_RCOL ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_MAT_MAP_RCOL; + c.size=9; + lib3ds_chunk_write(&c,io); + lib3ds_io_write_byte(io, (Lib3dsByte)floor(255.0*map->tint_r[0]+0.5)); + lib3ds_io_write_byte(io, (Lib3dsByte)floor(255.0*map->tint_r[1]+0.5)); + lib3ds_io_write_byte(io, (Lib3dsByte)floor(255.0*map->tint_r[2]+0.5)); + } + + { /*---- LIB3DS_MAT_MAP_GCOL ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_MAT_MAP_GCOL; + c.size=9; + lib3ds_chunk_write(&c,io); + lib3ds_io_write_byte(io, (Lib3dsByte)floor(255.0*map->tint_g[0]+0.5)); + lib3ds_io_write_byte(io, (Lib3dsByte)floor(255.0*map->tint_g[1]+0.5)); + lib3ds_io_write_byte(io, (Lib3dsByte)floor(255.0*map->tint_g[2]+0.5)); + } + + { /*---- LIB3DS_MAT_MAP_BCOL ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_MAT_MAP_BCOL; + c.size=9; + lib3ds_chunk_write(&c,io); + lib3ds_io_write_byte(io, (Lib3dsByte)floor(255.0*map->tint_b[0]+0.5)); + lib3ds_io_write_byte(io, (Lib3dsByte)floor(255.0*map->tint_b[1]+0.5)); + lib3ds_io_write_byte(io, (Lib3dsByte)floor(255.0*map->tint_b[2]+0.5)); + } + + if (!lib3ds_chunk_write_end(&c,io)) { + return(LIB3DS_FALSE); + } + return(LIB3DS_TRUE); +} + + +/*! + * \ingroup material + */ +Lib3dsBool +lib3ds_material_write(Lib3dsMaterial *material, Lib3dsIo *io) +{ + Lib3dsChunk c; + + c.chunk=LIB3DS_MAT_ENTRY; + if (!lib3ds_chunk_write_start(&c,io)) { + return(LIB3DS_FALSE); + } + + { /*---- LIB3DS_MAT_NAME ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_MAT_NAME; + c.size=6+(Lib3dsDword)strlen(material->name)+1; + lib3ds_chunk_write(&c,io); + lib3ds_io_write_string(io, material->name); + } + + { /*---- LIB3DS_MAT_AMBIENT ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_MAT_AMBIENT; + c.size=24; + lib3ds_chunk_write(&c,io); + color_write(material->ambient,io); + } + + { /*---- LIB3DS_MAT_DIFFUSE ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_MAT_DIFFUSE; + c.size=24; + lib3ds_chunk_write(&c,io); + color_write(material->diffuse,io); + } + + { /*---- LIB3DS_MAT_SPECULAR ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_MAT_SPECULAR; + c.size=24; + lib3ds_chunk_write(&c,io); + color_write(material->specular,io); + } + + { /*---- LIB3DS_MAT_SHININESS ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_MAT_SHININESS; + c.size=14; + lib3ds_chunk_write(&c,io); + int_percentage_write(material->shininess,io); + } + + { /*---- LIB3DS_MAT_SHIN2PCT ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_MAT_SHIN2PCT; + c.size=14; + lib3ds_chunk_write(&c,io); + int_percentage_write(material->shin_strength,io); + } + + { /*---- LIB3DS_MAT_TRANSPARENCY ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_MAT_TRANSPARENCY; + c.size=14; + lib3ds_chunk_write(&c,io); + int_percentage_write(material->transparency,io); + } + + { /*---- LIB3DS_MAT_XPFALL ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_MAT_XPFALL; + c.size=14; + lib3ds_chunk_write(&c,io); + int_percentage_write(material->falloff,io); + } + + if (material->use_falloff) { /*---- LIB3DS_MAT_USE_XPFALL ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_MAT_USE_XPFALL; + c.size=6; + lib3ds_chunk_write(&c,io); + } + + { /*---- LIB3DS_MAT_SHADING ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_MAT_SHADING; + c.size=8; + lib3ds_chunk_write(&c,io); + lib3ds_io_write_intw(io, material->shading); + } + + { /*---- LIB3DS_MAT_REFBLUR ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_MAT_REFBLUR; + c.size=14; + lib3ds_chunk_write(&c,io); + int_percentage_write(material->blur,io); + } + + if (material->use_blur) { /*---- LIB3DS_MAT_USE_REFBLUR ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_MAT_USE_REFBLUR; + c.size=6; + lib3ds_chunk_write(&c,io); + } + + if (material->self_illum) { /*---- LIB3DS_MAT_SELF_ILLUM ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_MAT_SELF_ILLUM; + c.size=6; + lib3ds_chunk_write(&c,io); + } + + if (material->two_sided) { /*---- LIB3DS_MAT_TWO_SIDE ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_MAT_TWO_SIDE; + c.size=6; + lib3ds_chunk_write(&c,io); + } + + if (material->map_decal) { /*---- LIB3DS_MAT_DECAL ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_MAT_DECAL; + c.size=6; + lib3ds_chunk_write(&c,io); + } + + if (material->additive) { /*---- LIB3DS_MAT_ADDITIVE ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_MAT_ADDITIVE; + c.size=6; + lib3ds_chunk_write(&c,io); + } + + if (material->use_wire) { /*---- LIB3DS_MAT_WIRE ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_MAT_WIRE; + c.size=6; + lib3ds_chunk_write(&c,io); + } + + if (material->use_wire_abs) { /*---- LIB3DS_MAT_WIREABS ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_MAT_WIREABS; + c.size=6; + lib3ds_chunk_write(&c,io); + } + + { /*---- LIB3DS_MAT_WIRE_SIZE ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_MAT_WIRE_SIZE; + c.size=10; + lib3ds_chunk_write(&c,io); + lib3ds_io_write_float(io, material->wire_size); + } + + if (material->face_map) { /*---- LIB3DS_MAT_FACEMAP ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_MAT_FACEMAP; + c.size=6; + lib3ds_chunk_write(&c,io); + } + + if (material->soften) { /*---- LIB3DS_MAT_PHONGSOFT ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_MAT_PHONGSOFT; + c.size=6; + lib3ds_chunk_write(&c,io); + } + + if (!texture_map_write(LIB3DS_MAT_TEXMAP, &material->texture1_map, io)) { + return(LIB3DS_FALSE); + } + if (!texture_map_write(LIB3DS_MAT_TEXMASK, &material->texture1_mask, io)) { + return(LIB3DS_FALSE); + } + if (!texture_map_write(LIB3DS_MAT_TEX2MAP, &material->texture2_map, io)) { + return(LIB3DS_FALSE); + } + if (!texture_map_write(LIB3DS_MAT_TEX2MASK, &material->texture2_mask, io)) { + return(LIB3DS_FALSE); + } + if (!texture_map_write(LIB3DS_MAT_OPACMAP, &material->opacity_map, io)) { + return(LIB3DS_FALSE); + } + if (!texture_map_write(LIB3DS_MAT_OPACMASK, &material->opacity_mask, io)) { + return(LIB3DS_FALSE); + } + if (!texture_map_write(LIB3DS_MAT_BUMPMAP, &material->bump_map, io)) { + return(LIB3DS_FALSE); + } + if (!texture_map_write(LIB3DS_MAT_BUMPMASK, &material->bump_mask, io)) { + return(LIB3DS_FALSE); + } + if (!texture_map_write(LIB3DS_MAT_SPECMAP, &material->specular_map, io)) { + return(LIB3DS_FALSE); + } + if (!texture_map_write(LIB3DS_MAT_SPECMASK, &material->specular_mask, io)) { + return(LIB3DS_FALSE); + } + if (!texture_map_write(LIB3DS_MAT_SHINMAP, &material->shininess_map, io)) { + return(LIB3DS_FALSE); + } + if (!texture_map_write(LIB3DS_MAT_SHINMASK, &material->shininess_mask, io)) { + return(LIB3DS_FALSE); + } + if (!texture_map_write(LIB3DS_MAT_SELFIMAP, &material->self_illum_map, io)) { + return(LIB3DS_FALSE); + } + if (!texture_map_write(LIB3DS_MAT_SELFIMASK, &material->self_illum_mask, io)) { + return(LIB3DS_FALSE); + } + if (!texture_map_write(LIB3DS_MAT_REFLMAP, &material->reflection_map, io)) { + return(LIB3DS_FALSE); + } + if (!texture_map_write(LIB3DS_MAT_REFLMASK, &material->reflection_mask, io)) { + return(LIB3DS_FALSE); + } + + if (!lib3ds_chunk_write_end(&c,io)) { + return(LIB3DS_FALSE); + } + return(LIB3DS_TRUE); +} + + diff --git a/3rdparty/lib3ds/material.h b/3rdparty/lib3ds/material.h new file mode 100644 index 000000000..7e3e168e7 --- /dev/null +++ b/3rdparty/lib3ds/material.h @@ -0,0 +1,170 @@ +/* -*- c -*- */ +#ifndef INCLUDED_LIB3DS_MATERIAL_H +#define INCLUDED_LIB3DS_MATERIAL_H +/* + * The 3D Studio File Format Library + * Copyright (C) 1996-2007 by Jan Eric Kyprianidis <www.kyprianidis.com> + * 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: material.h,v 1.18 2007/06/20 17:04:08 jeh Exp $ + */ + +#ifndef INCLUDED_LIB3DS_TYPES_H +#include <lib3ds/types.h> +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \ingroup material + */ +typedef enum Lib3dsTextureMapFlags { + LIB3DS_DECALE =0x0001, + LIB3DS_MIRROR =0x0002, + LIB3DS_NEGATE =0x0008, + LIB3DS_NO_TILE =0x0010, + LIB3DS_SUMMED_AREA =0x0020, + LIB3DS_ALPHA_SOURCE =0x0040, + LIB3DS_TINT =0x0080, + LIB3DS_IGNORE_ALPHA =0x0100, + LIB3DS_RGB_TINT =0x0200 +} Lib3dsTextureMapFlags; + +/** + * Mateial texture map + * \ingroup material + */ +typedef struct Lib3dsTextureMap { + Lib3dsUserData user; + char name[64]; + Lib3dsDword flags; + Lib3dsFloat percent; + Lib3dsFloat blur; + Lib3dsFloat scale[2]; + Lib3dsFloat offset[2]; + Lib3dsFloat rotation; + Lib3dsRgb tint_1; + Lib3dsRgb tint_2; + Lib3dsRgb tint_r; + Lib3dsRgb tint_g; + Lib3dsRgb tint_b; +} Lib3dsTextureMap; + +/** + * \ingroup material + */ +typedef enum Lib3dsAutoReflMapFlags { + LIB3DS_USE_REFL_MAP =0x0001, + LIB3DS_READ_FIRST_FRAME_ONLY =0x0004, + LIB3DS_FLAT_MIRROR =0x0008 +} Lib3dsAutoReflectionMapFlags; + +/** + * \ingroup material + */ +typedef enum Lib3dsAutoReflMapAntiAliasLevel { + LIB3DS_ANTI_ALIAS_NONE =0, + LIB3DS_ANTI_ALIAS_LOW =1, + LIB3DS_ANTI_ALIAS_MEDIUM =2, + LIB3DS_ANTI_ALIAS_HIGH =3 +} Lib3dsAutoReflMapAntiAliasLevel; + +/** + * Auto reflection map settings + * \ingroup material + */ +typedef struct Lib3dsAutoReflMap { + Lib3dsDword flags; + Lib3dsIntd level; + Lib3dsIntd size; + Lib3dsIntd frame_step; +} Lib3dsAutoReflMap; + +/** + * \ingroup material + */ +typedef enum Lib3dsMaterialShading { + LIB3DS_WIRE_FRAME =0, + LIB3DS_FLAT =1, + LIB3DS_GOURAUD =2, + LIB3DS_PHONG =3, + LIB3DS_METAL =4 +} Lib3dsMaterialShading; + +/** + * Material + * \ingroup material + */ +struct Lib3dsMaterial { + Lib3dsUserData user; /*! Arbitrary user data */ + Lib3dsMaterial *next; + char name[64]; /*! Material name */ + Lib3dsRgba ambient; /*! Material ambient reflectivity */ + Lib3dsRgba diffuse; /*! Material diffuse reflectivity */ + Lib3dsRgba specular; /*! Material specular reflectivity */ + Lib3dsFloat shininess; /*! Material specular exponent */ + Lib3dsFloat shin_strength; + Lib3dsBool use_blur; + Lib3dsFloat blur; + Lib3dsFloat transparency; + Lib3dsFloat falloff; + Lib3dsBool additive; + Lib3dsFloat self_ilpct; + Lib3dsBool use_falloff; + Lib3dsBool self_illum; + Lib3dsIntw shading; + Lib3dsBool soften; + Lib3dsBool face_map; + Lib3dsBool two_sided; /*! Material visible from back */ + Lib3dsBool map_decal; + Lib3dsBool use_wire; + Lib3dsBool use_wire_abs; + Lib3dsFloat wire_size; + Lib3dsTextureMap texture1_map; + Lib3dsTextureMap texture1_mask; + Lib3dsTextureMap texture2_map; + Lib3dsTextureMap texture2_mask; + Lib3dsTextureMap opacity_map; + Lib3dsTextureMap opacity_mask; + Lib3dsTextureMap bump_map; + Lib3dsTextureMap bump_mask; + Lib3dsTextureMap specular_map; + Lib3dsTextureMap specular_mask; + Lib3dsTextureMap shininess_map; + Lib3dsTextureMap shininess_mask; + Lib3dsTextureMap self_illum_map; + Lib3dsTextureMap self_illum_mask; + Lib3dsTextureMap reflection_map; + Lib3dsTextureMap reflection_mask; + Lib3dsAutoReflMap autorefl_map; +}; + +extern LIB3DSAPI Lib3dsMaterial* lib3ds_material_new(); +extern LIB3DSAPI void lib3ds_material_free(Lib3dsMaterial *material); +extern LIB3DSAPI void lib3ds_material_dump(Lib3dsMaterial *material); +extern LIB3DSAPI Lib3dsBool lib3ds_material_read(Lib3dsMaterial *material, Lib3dsIo *io); +extern LIB3DSAPI Lib3dsBool lib3ds_material_write(Lib3dsMaterial *material, Lib3dsIo *io); + +#ifdef __cplusplus +} +#endif +#endif + + + diff --git a/3rdparty/lib3ds/matrix.c b/3rdparty/lib3ds/matrix.c new file mode 100644 index 000000000..58e7584a6 --- /dev/null +++ b/3rdparty/lib3ds/matrix.c @@ -0,0 +1,718 @@ +/* + * The 3D Studio File Format Library + * Copyright (C) 1996-2007 by Jan Eric Kyprianidis <www.kyprianidis.com> + * 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: matrix.c,v 1.14 2007/06/20 17:04:08 jeh Exp $ + */ +#include <lib3ds/matrix.h> +#include <lib3ds/quat.h> +#include <lib3ds/vector.h> +#include <string.h> +#include <math.h> + + +/*! + * \defgroup matrix Matrix Mathematics + */ + + +/*! +* \typedef Lib3dsMatrix +* \ingroup matrix +*/ + + +/*! + * Clear a matrix to all zeros. + * + * \param m Matrix to be cleared. + * + * \ingroup matrix + */ +void +lib3ds_matrix_zero(Lib3dsMatrix m) +{ + int i,j; + + for (i=0; i<4; i++) { + for (j=0; j<4; j++) m[i][j]=0.0f; + } +} + + +/*! + * Set a matrix to identity. + * + * \param m Matrix to be set. + * + * \ingroup matrix + */ +void +lib3ds_matrix_identity(Lib3dsMatrix m) +{ + int i,j; + + for (i=0; i<4; i++) { + for (j=0; j<4; j++) m[i][j]=0.0; + } + for (i=0; i<4; i++) m[i][i]=1.0; +} + + +/*! + * Copy a matrix. + * + * \ingroup matrix + */ +void +lib3ds_matrix_copy(Lib3dsMatrix dest, Lib3dsMatrix src) +{ + memcpy(dest, src, sizeof(Lib3dsMatrix)); +} + + +/*! + * Negate a matrix -- all elements negated. + * + * \ingroup matrix + */ +void +lib3ds_matrix_neg(Lib3dsMatrix m) +{ + int i,j; + + for (j=0; j<4; j++) { + for (i=0; i<4; i++) { + m[j][i]=-m[j][i]; + } + } +} + + +/*! + * Set all matrix elements to their absolute value. + * + * \ingroup matrix + */ +void +lib3ds_matrix_abs(Lib3dsMatrix m) +{ + int i,j; + + for (j=0; j<4; j++) { + for (i=0; i<4; i++) { + m[j][i]=(Lib3dsFloat)fabs(m[j][i]); + } + } +} + + +/*! + * Transpose a matrix in place. + * + * \ingroup matrix + */ +void +lib3ds_matrix_transpose(Lib3dsMatrix m) +{ + int i,j; + Lib3dsFloat swp; + + for (j=0; j<4; j++) { + for (i=j+1; i<4; i++) { + swp=m[j][i]; + m[j][i]=m[i][j]; + m[i][j]=swp; + } + } +} + + +/*! + * Add two matrices. + * + * \ingroup matrix + */ +void +_lib3ds_matrix_add(Lib3dsMatrix m, Lib3dsMatrix a, Lib3dsMatrix b) +{ + int i,j; + + for (j=0; j<4; j++) { + for (i=0; i<4; i++) { + m[j][i]=a[j][i]+b[j][i]; + } + } +} + + +/*! + * Subtract two matrices. + * + * \param m Result. + * \param a Addend. + * \param b Minuend. + * + * \ingroup matrix + */ +void +_lib3ds_matrix_sub(Lib3dsMatrix m, Lib3dsMatrix a, Lib3dsMatrix b) +{ + int i,j; + + for (j=0; j<4; j++) { + for (i=0; i<4; i++) { + m[j][i]=a[j][i]-b[j][i]; + } + } +} + + +/*! + * Multiplies a matrix by a second one (m = m * n). + * + * \ingroup matrix + */ +void +lib3ds_matrix_mult(Lib3dsMatrix m, Lib3dsMatrix n) +{ + Lib3dsMatrix tmp; + int i,j,k; + Lib3dsFloat ab; + + memcpy(tmp, m, sizeof(Lib3dsMatrix)); + for (j=0; j<4; j++) { + for (i=0; i<4; i++) { + ab=0.0f; + for (k=0; k<4; k++) ab+=tmp[k][i]*n[j][k]; + m[j][i]=ab; + } + } +} + + +/*! + * Multiply a matrix by a scalar. + * + * \param m Matrix to be set. + * \param k Scalar. + * + * \ingroup matrix + */ +void +lib3ds_matrix_scalar(Lib3dsMatrix m, Lib3dsFloat k) +{ + int i,j; + + for (j=0; j<4; j++) { + for (i=0; i<4; i++) { + m[j][i]*=k; + } + } +} + + +static Lib3dsFloat +det2x2( + Lib3dsFloat a, Lib3dsFloat b, + Lib3dsFloat c, Lib3dsFloat d) +{ + return((a)*(d)-(b)*(c)); +} + + +static Lib3dsFloat +det3x3( + Lib3dsFloat a1, Lib3dsFloat a2, Lib3dsFloat a3, + Lib3dsFloat b1, Lib3dsFloat b2, Lib3dsFloat b3, + Lib3dsFloat c1, Lib3dsFloat c2, Lib3dsFloat c3) +{ + return( + a1*det2x2(b2,b3,c2,c3)- + b1*det2x2(a2,a3,c2,c3)+ + c1*det2x2(a2,a3,b2,b3) + ); +} + + +/*! + * Find determinant of a matrix. + * + * \ingroup matrix + */ +Lib3dsFloat +lib3ds_matrix_det(Lib3dsMatrix m) +{ + Lib3dsFloat a1,a2,a3,a4,b1,b2,b3,b4,c1,c2,c3,c4,d1,d2,d3,d4; + + a1 = m[0][0]; + b1 = m[1][0]; + c1 = m[2][0]; + d1 = m[3][0]; + a2 = m[0][1]; + b2 = m[1][1]; + c2 = m[2][1]; + d2 = m[3][1]; + a3 = m[0][2]; + b3 = m[1][2]; + c3 = m[2][2]; + d3 = m[3][2]; + a4 = m[0][3]; + b4 = m[1][3]; + c4 = m[2][3]; + d4 = m[3][3]; + return( + a1 * det3x3(b2, b3, b4, c2, c3, c4, d2, d3, d4)- + b1 * det3x3(a2, a3, a4, c2, c3, c4, d2, d3, d4)+ + c1 * det3x3(a2, a3, a4, b2, b3, b4, d2, d3, d4)- + d1 * det3x3(a2, a3, a4, b2, b3, b4, c2, c3, c4) + ); +} + + +/*! + * Find the adjoint of a matrix. + * + * \ingroup matrix + */ +void +lib3ds_matrix_adjoint(Lib3dsMatrix m) +{ + Lib3dsFloat a1,a2,a3,a4,b1,b2,b3,b4,c1,c2,c3,c4,d1,d2,d3,d4; + + a1 = m[0][0]; + b1 = m[1][0]; + c1 = m[2][0]; + d1 = m[3][0]; + a2 = m[0][1]; + b2 = m[1][1]; + c2 = m[2][1]; + d2 = m[3][1]; + a3 = m[0][2]; + b3 = m[1][2]; + c3 = m[2][2]; + d3 = m[3][2]; + a4 = m[0][3]; + b4 = m[1][3]; + c4 = m[2][3]; + d4 = m[3][3]; + m[0][0]= det3x3 (b2, b3, b4, c2, c3, c4, d2, d3, d4); + m[0][1]= -det3x3 (a2, a3, a4, c2, c3, c4, d2, d3, d4); + m[0][2]= det3x3 (a2, a3, a4, b2, b3, b4, d2, d3, d4); + m[0][3]= -det3x3 (a2, a3, a4, b2, b3, b4, c2, c3, c4); + m[1][0]= -det3x3 (b1, b3, b4, c1, c3, c4, d1, d3, d4); + m[1][1]= det3x3 (a1, a3, a4, c1, c3, c4, d1, d3, d4); + m[1][2]= -det3x3 (a1, a3, a4, b1, b3, b4, d1, d3, d4); + m[1][3]= det3x3 (a1, a3, a4, b1, b3, b4, c1, c3, c4); + m[2][0]= det3x3 (b1, b2, b4, c1, c2, c4, d1, d2, d4); + m[2][1]= -det3x3 (a1, a2, a4, c1, c2, c4, d1, d2, d4); + m[2][2]= det3x3 (a1, a2, a4, b1, b2, b4, d1, d2, d4); + m[2][3]= -det3x3 (a1, a2, a4, b1, b2, b4, c1, c2, c4); + m[3][0]= -det3x3 (b1, b2, b3, c1, c2, c3, d1, d2, d3); + m[3][1]= det3x3 (a1, a2, a3, c1, c2, c3, d1, d2, d3); + m[3][2]= -det3x3 (a1, a2, a3, b1, b2, b3, d1, d2, d3); + m[3][3]= det3x3 (a1, a2, a3, b1, b2, b3, c1, c2, c3); +} + + +/*! + * Invert a matrix in place. + * + * \param m Matrix to invert. + * + * \return LIB3DS_TRUE on success, LIB3DS_FALSE on failure. + * \ingroup matrix + * + * GGemsII, K.Wu, Fast Matrix Inversion + */ +Lib3dsBool +lib3ds_matrix_inv(Lib3dsMatrix m) +{ + int i,j,k; + int pvt_i[4], pvt_j[4]; /* Locations of pivot elements */ + Lib3dsFloat pvt_val; /* Value of current pivot element */ + Lib3dsFloat hold; /* Temporary storage */ + Lib3dsFloat determinat; + + determinat = 1.0f; + for (k=0; k<4; k++) { + /* Locate k'th pivot element */ + pvt_val=m[k][k]; /* Initialize for search */ + pvt_i[k]=k; + pvt_j[k]=k; + for (i=k; i<4; i++) { + for (j=k; j<4; j++) { + if (fabs(m[i][j]) > fabs(pvt_val)) { + pvt_i[k]=i; + pvt_j[k]=j; + pvt_val=m[i][j]; + } + } + } + + /* Product of pivots, gives determinant when finished */ + determinat*=pvt_val; + if (fabs(determinat)<LIB3DS_EPSILON) { + return(LIB3DS_FALSE); /* Matrix is singular (zero determinant) */ + } + + /* "Interchange" rows (with sign change stuff) */ + i=pvt_i[k]; + if (i!=k) { /* If rows are different */ + for (j=0; j<4; j++) { + hold=-m[k][j]; + m[k][j]=m[i][j]; + m[i][j]=hold; + } + } + + /* "Interchange" columns */ + j=pvt_j[k]; + if (j!=k) { /* If columns are different */ + for (i=0; i<4; i++) { + hold=-m[i][k]; + m[i][k]=m[i][j]; + m[i][j]=hold; + } + } + + /* Divide column by minus pivot value */ + for (i=0; i<4; i++) { + if (i!=k) m[i][k]/=( -pvt_val) ; + } + + /* Reduce the matrix */ + for (i=0; i<4; i++) { + hold = m[i][k]; + for (j=0; j<4; j++) { + if (i!=k && j!=k) m[i][j]+=hold*m[k][j]; + } + } + + /* Divide row by pivot */ + for (j=0; j<4; j++) { + if (j!=k) m[k][j]/=pvt_val; + } + + /* Replace pivot by reciprocal (at last we can touch it). */ + m[k][k] = 1.0f/pvt_val; + } + + /* That was most of the work, one final pass of row/column interchange */ + /* to finish */ + for (k=4-2; k>=0; k--) { /* Don't need to work with 1 by 1 corner*/ + i=pvt_j[k]; /* Rows to swap correspond to pivot COLUMN */ + if (i!=k) { /* If rows are different */ + for (j=0; j<4; j++) { + hold = m[k][j]; + m[k][j]=-m[i][j]; + m[i][j]=hold; + } + } + + j=pvt_i[k]; /* Columns to swap correspond to pivot ROW */ + if (j!=k) /* If columns are different */ + for (i=0; i<4; i++) { + hold=m[i][k]; + m[i][k]=-m[i][j]; + m[i][j]=hold; + } + } + return(LIB3DS_TRUE); +} + + +/*! + * Apply a translation to a matrix. + * + * \ingroup matrix + */ +void +lib3ds_matrix_translate_xyz(Lib3dsMatrix m, Lib3dsFloat x, Lib3dsFloat y, Lib3dsFloat z) +{ + int i; + + for (i=0; i<3; i++) { + m[3][i]+= m[0][i]*x + m[1][i]*y + m[2][i]*z; + } +} + + +/*! + * Apply a translation to a matrix. + * + * \ingroup matrix + */ +void +lib3ds_matrix_translate(Lib3dsMatrix m, Lib3dsVector t) +{ + int i; + + for (i=0; i<3; i++) { + m[3][i]+= m[0][i]*t[0] + m[1][i]*t[1] + m[2][i]*t[2]; + } +} + + +/*! + * Apply scale factors to a matrix. + * + * \ingroup matrix + */ +void +lib3ds_matrix_scale_xyz(Lib3dsMatrix m, Lib3dsFloat x, Lib3dsFloat y, Lib3dsFloat z) +{ + int i; + + for (i=0; i<4; i++) { + m[0][i]*=x; + m[1][i]*=y; + m[2][i]*=z; + } +} + + +/*! + * Apply scale factors to a matrix. + * + * \ingroup matrix + */ +void +lib3ds_matrix_scale(Lib3dsMatrix m, Lib3dsVector s) +{ + int i; + + for (i=0; i<4; i++) { + m[0][i]*=s[0]; + m[1][i]*=s[1]; + m[2][i]*=s[2]; + } +} + + +/*! + * Apply a rotation about the x axis to a matrix. + * + * \ingroup matrix + */ +void +lib3ds_matrix_rotate_x(Lib3dsMatrix m, Lib3dsFloat phi) +{ + Lib3dsFloat SinPhi,CosPhi; + Lib3dsFloat a1[4],a2[4]; + + SinPhi=(Lib3dsFloat)sin(phi); + CosPhi=(Lib3dsFloat)cos(phi); + memcpy(a1,m[1],4*sizeof(Lib3dsFloat)); + memcpy(a2,m[2],4*sizeof(Lib3dsFloat)); + m[1][0]=CosPhi*a1[0]+SinPhi*a2[0]; + m[1][1]=CosPhi*a1[1]+SinPhi*a2[1]; + m[1][2]=CosPhi*a1[2]+SinPhi*a2[2]; + m[1][3]=CosPhi*a1[3]+SinPhi*a2[3]; + m[2][0]=-SinPhi*a1[0]+CosPhi*a2[0]; + m[2][1]=-SinPhi*a1[1]+CosPhi*a2[1]; + m[2][2]=-SinPhi*a1[2]+CosPhi*a2[2]; + m[2][3]=-SinPhi*a1[3]+CosPhi*a2[3]; +} + + +/*! + * Apply a rotation about the y axis to a matrix. + * + * \ingroup matrix + */ +void +lib3ds_matrix_rotate_y(Lib3dsMatrix m, Lib3dsFloat phi) +{ + Lib3dsFloat SinPhi,CosPhi; + Lib3dsFloat a0[4],a2[4]; + + SinPhi=(Lib3dsFloat)sin(phi); + CosPhi=(Lib3dsFloat)cos(phi); + memcpy(a0,m[0],4*sizeof(Lib3dsFloat)); + memcpy(a2,m[2],4*sizeof(Lib3dsFloat)); + m[0][0]=CosPhi*a0[0]-SinPhi*a2[0]; + m[0][1]=CosPhi*a0[1]-SinPhi*a2[1]; + m[0][2]=CosPhi*a0[2]-SinPhi*a2[2]; + m[0][3]=CosPhi*a0[3]-SinPhi*a2[3]; + m[2][0]=SinPhi*a0[0]+CosPhi*a2[0]; + m[2][1]=SinPhi*a0[1]+CosPhi*a2[1]; + m[2][2]=SinPhi*a0[2]+CosPhi*a2[2]; + m[2][3]=SinPhi*a0[3]+CosPhi*a2[3]; +} + + +/*! + * Apply a rotation about the z axis to a matrix. + * + * \ingroup matrix + */ +void +lib3ds_matrix_rotate_z(Lib3dsMatrix m, Lib3dsFloat phi) +{ + Lib3dsFloat SinPhi,CosPhi; + Lib3dsFloat a0[4],a1[4]; + + SinPhi=(Lib3dsFloat)sin(phi); + CosPhi=(Lib3dsFloat)cos(phi); + memcpy(a0,m[0],4*sizeof(Lib3dsFloat)); + memcpy(a1,m[1],4*sizeof(Lib3dsFloat)); + m[0][0]=CosPhi*a0[0]+SinPhi*a1[0]; + m[0][1]=CosPhi*a0[1]+SinPhi*a1[1]; + m[0][2]=CosPhi*a0[2]+SinPhi*a1[2]; + m[0][3]=CosPhi*a0[3]+SinPhi*a1[3]; + m[1][0]=-SinPhi*a0[0]+CosPhi*a1[0]; + m[1][1]=-SinPhi*a0[1]+CosPhi*a1[1]; + m[1][2]=-SinPhi*a0[2]+CosPhi*a1[2]; + m[1][3]=-SinPhi*a0[3]+CosPhi*a1[3]; +} + + +/*! + * Apply a rotation about an arbitrary axis to a matrix. + * + * \ingroup matrix + */ +void +lib3ds_matrix_rotate(Lib3dsMatrix m, Lib3dsQuat q) +{ + Lib3dsFloat s,xs,ys,zs,wx,wy,wz,xx,xy,xz,yy,yz,zz,l; + Lib3dsMatrix R; + + l=q[0]*q[0] + q[1]*q[1] + q[2]*q[2] + q[3]*q[3]; + if (fabs(l)<LIB3DS_EPSILON) { + s=1.0f; + } + else { + s=2.0f/l; + } + + xs = q[0] * s; ys = q[1] * s; zs = q[2] * s; + wx = q[3] * xs; wy = q[3] * ys; wz = q[3] * zs; + xx = q[0] * xs; xy = q[0] * ys; xz = q[0] * zs; + yy = q[1] * ys; yz = q[1] * zs; zz = q[2] * zs; + + R[0][0]=1.0f - (yy +zz); + R[1][0]=xy - wz; + R[2][0]=xz + wy; + R[0][1]=xy + wz; + R[1][1]=1.0f - (xx +zz); + R[2][1]=yz - wx; + R[0][2]=xz - wy; + R[1][2]=yz + wx; + R[2][2]=1.0f - (xx + yy); + R[3][0]=R[3][1]=R[3][2]=R[0][3]=R[1][3]=R[2][3]=0.0f; + R[3][3]=1.0f; + + lib3ds_matrix_mult(m,R); +} + + +/*! + * Apply a rotation about an arbitrary axis to a matrix. + * + * \ingroup matrix + */ +void +lib3ds_matrix_rotate_axis(Lib3dsMatrix m, Lib3dsVector axis, Lib3dsFloat angle) +{ + Lib3dsQuat q; + + lib3ds_quat_axis_angle(q,axis,angle); + lib3ds_matrix_rotate(m,q); +} + + +/*! + * Compute a camera matrix based on position, target and roll. + * + * Generates a translate/rotate matrix that maps world coordinates + * to camera coordinates. Resulting matrix does not include perspective + * transform. + * + * \param matrix Destination matrix. + * \param pos Camera position + * \param tgt Camera target + * \param roll Roll angle + * + * \ingroup matrix + */ +void +lib3ds_matrix_camera(Lib3dsMatrix matrix, Lib3dsVector pos, + Lib3dsVector tgt, Lib3dsFloat roll) +{ + Lib3dsMatrix M; + Lib3dsVector x, y, z; + + lib3ds_vector_sub(y, tgt, pos); + lib3ds_vector_normalize(y); + + if (y[0] != 0. || y[1] != 0) { + z[0] = 0; + z[1] = 0; + z[2] = 1.0; + } + else { /* Special case: looking straight up or down z axis */ + z[0] = -1.0; + z[1] = 0; + z[2] = 0; + } + + lib3ds_vector_cross(x, y, z); + lib3ds_vector_cross(z, x, y); + lib3ds_vector_normalize(x); + lib3ds_vector_normalize(z); + + lib3ds_matrix_identity(M); + M[0][0] = x[0]; + M[1][0] = x[1]; + M[2][0] = x[2]; + M[0][1] = y[0]; + M[1][1] = y[1]; + M[2][1] = y[2]; + M[0][2] = z[0]; + M[1][2] = z[1]; + M[2][2] = z[2]; + + lib3ds_matrix_identity(matrix); + lib3ds_matrix_rotate_y(matrix, roll); + lib3ds_matrix_mult(matrix, M); + lib3ds_matrix_translate_xyz(matrix, -pos[0],-pos[1],-pos[2]); +} + + +/*! + * \ingroup matrix + */ +void +lib3ds_matrix_dump(Lib3dsMatrix matrix) +{ + int i,j; + + for (i=0; i<4; ++i) { + for (j=0; j<4; ++j) { + printf("%f ", matrix[j][i]); + } + printf("\n"); + } +} + + + + + diff --git a/3rdparty/lib3ds/matrix.h b/3rdparty/lib3ds/matrix.h new file mode 100644 index 000000000..756b52d23 --- /dev/null +++ b/3rdparty/lib3ds/matrix.h @@ -0,0 +1,63 @@ +/* -*- c -*- */ +#ifndef INCLUDED_LIB3DS_MATRIX_H +#define INCLUDED_LIB3DS_MATRIX_H +/* + * The 3D Studio File Format Library + * Copyright (C) 1996-2007 by Jan Eric Kyprianidis <www.kyprianidis.com> + * 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: matrix.h,v 1.8 2007/06/18 06:11:32 jeh Exp $ + */ + +#ifndef INCLUDED_LIB3DS_TYPES_H +#include <lib3ds/types.h> +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +extern LIB3DSAPI void lib3ds_matrix_zero(Lib3dsMatrix m); +extern LIB3DSAPI void lib3ds_matrix_identity(Lib3dsMatrix m); +extern LIB3DSAPI void lib3ds_matrix_copy(Lib3dsMatrix dest, Lib3dsMatrix src); +extern LIB3DSAPI void lib3ds_matrix_neg(Lib3dsMatrix m); +extern LIB3DSAPI void lib3ds_matrix_abs(Lib3dsMatrix m); +extern LIB3DSAPI void lib3ds_matrix_transpose(Lib3dsMatrix m); +extern LIB3DSAPI void _lib3ds_matrix_add(Lib3dsMatrix m, Lib3dsMatrix a, Lib3dsMatrix b); +extern LIB3DSAPI void _lib3ds_matrix_sub(Lib3dsMatrix m, Lib3dsMatrix a, Lib3dsMatrix b); +extern LIB3DSAPI void lib3ds_matrix_mult(Lib3dsMatrix m, Lib3dsMatrix n); +extern LIB3DSAPI void lib3ds_matrix_scalar(Lib3dsMatrix m, Lib3dsFloat k); +extern LIB3DSAPI Lib3dsFloat lib3ds_matrix_det(Lib3dsMatrix m); +extern LIB3DSAPI void lib3ds_matrix_adjoint(Lib3dsMatrix m); +extern LIB3DSAPI Lib3dsBool lib3ds_matrix_inv(Lib3dsMatrix m); +extern LIB3DSAPI void lib3ds_matrix_translate_xyz(Lib3dsMatrix m, Lib3dsFloat x, Lib3dsFloat y, Lib3dsFloat z); +extern LIB3DSAPI void lib3ds_matrix_translate(Lib3dsMatrix m, Lib3dsVector t); +extern LIB3DSAPI void lib3ds_matrix_scale_xyz(Lib3dsMatrix m, Lib3dsFloat x, Lib3dsFloat y, Lib3dsFloat z); +extern LIB3DSAPI void lib3ds_matrix_scale(Lib3dsMatrix m, Lib3dsVector s); +extern LIB3DSAPI void lib3ds_matrix_rotate_x(Lib3dsMatrix m, Lib3dsFloat phi); +extern LIB3DSAPI void lib3ds_matrix_rotate_y(Lib3dsMatrix m, Lib3dsFloat phi); +extern LIB3DSAPI void lib3ds_matrix_rotate_z(Lib3dsMatrix m, Lib3dsFloat phi); +extern LIB3DSAPI void lib3ds_matrix_rotate(Lib3dsMatrix m, Lib3dsQuat q); +extern LIB3DSAPI void lib3ds_matrix_rotate_axis(Lib3dsMatrix m, Lib3dsVector axis, Lib3dsFloat angle); +extern LIB3DSAPI void lib3ds_matrix_camera(Lib3dsMatrix matrix, Lib3dsVector pos, Lib3dsVector tgt, Lib3dsFloat roll); +extern LIB3DSAPI void lib3ds_matrix_dump(Lib3dsMatrix matrix); + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/3rdparty/lib3ds/mesh.c b/3rdparty/lib3ds/mesh.c new file mode 100644 index 000000000..6ff655544 --- /dev/null +++ b/3rdparty/lib3ds/mesh.c @@ -0,0 +1,1056 @@ +/* + * The 3D Studio File Format Library + * Copyright (C) 1996-2007 by Jan Eric Kyprianidis <www.kyprianidis.com> + * 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: mesh.c,v 1.29 2007/06/20 17:04:08 jeh Exp $ + */ +#include <lib3ds/mesh.h> +#include <lib3ds/io.h> +#include <lib3ds/chunk.h> +#include <lib3ds/vector.h> +#include <lib3ds/matrix.h> +#include <stdlib.h> +#include <string.h> +#include <math.h> +#include <float.h> + + +/*! + * \defgroup mesh Meshes + */ + + +static Lib3dsBool +face_array_read(Lib3dsMesh *mesh, Lib3dsIo *io) +{ + Lib3dsChunk c; + Lib3dsWord chunk; + int i; + int faces; + + if (!lib3ds_chunk_read_start(&c, LIB3DS_FACE_ARRAY, io)) { + return(LIB3DS_FALSE); + } + lib3ds_mesh_free_face_list(mesh); + + faces=lib3ds_io_read_word(io); + 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_io_read_word(io); + mesh->faceL[i].points[1]=lib3ds_io_read_word(io); + mesh->faceL[i].points[2]=lib3ds_io_read_word(io); + mesh->faceL[i].flags=lib3ds_io_read_word(io); + } + lib3ds_chunk_read_tell(&c, io); + + while ((chunk=lib3ds_chunk_read_next(&c, io))!=0) { + switch (chunk) { + case LIB3DS_SMOOTH_GROUP: + { + unsigned i; + + for (i=0; i<mesh->faces; ++i) { + mesh->faceL[i].smoothing=lib3ds_io_read_dword(io); + } + } + break; + case LIB3DS_MSH_MAT_GROUP: + { + char name[64]; + unsigned faces; + unsigned i; + unsigned index; + + if (!lib3ds_io_read_string(io, name, 64)) { + return(LIB3DS_FALSE); + } + faces=lib3ds_io_read_word(io); + for (i=0; i<faces; ++i) { + index=lib3ds_io_read_word(io); + ASSERT(index<mesh->faces); + strcpy(mesh->faceL[index].material, name); + } + } + break; + case LIB3DS_MSH_BOXMAP: + { + char name[64]; + + if (!lib3ds_io_read_string(io, name, 64)) { + return(LIB3DS_FALSE); + } + strcpy(mesh->box_map.front, name); + if (!lib3ds_io_read_string(io, name, 64)) { + return(LIB3DS_FALSE); + } + strcpy(mesh->box_map.back, name); + if (!lib3ds_io_read_string(io, name, 64)) { + return(LIB3DS_FALSE); + } + strcpy(mesh->box_map.left, name); + if (!lib3ds_io_read_string(io, name, 64)) { + return(LIB3DS_FALSE); + } + strcpy(mesh->box_map.right, name); + if (!lib3ds_io_read_string(io, name, 64)) { + return(LIB3DS_FALSE); + } + strcpy(mesh->box_map.top, name); + if (!lib3ds_io_read_string(io, name, 64)) { + return(LIB3DS_FALSE); + } + strcpy(mesh->box_map.bottom, name); + } + break; + default: + lib3ds_chunk_unknown(chunk); + } + } + + } + lib3ds_chunk_read_end(&c, io); + return(LIB3DS_TRUE); +} + + +/*! + * Create and return a new empty mesh object. + * + * Mesh is initialized with the name and an identity matrix; all + * other fields are zero. + * + * See Lib3dsFaceFlag for definitions of per-face flags. + * + * \param name Mesh name. Must not be NULL. Must be < 64 characters. + * + * \return mesh object or NULL on error. + * + * \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); +} + + +/*! + * Free a mesh object and all of its resources. + * + * \param mesh Mesh object to be freed. + * + * \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); +} + + +/*! + * Allocate point list in mesh object. + * + * This function frees the current point list, if any, and allocates + * a new one large enough to hold the specified number of points. + * + * \param mesh Mesh object for which points are to be allocated. + * \param points Number of points in the new point list. + * + * \return LIB3DS_TRUE on success, LIB3DS_FALSE on failure. + * + * \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=calloc(sizeof(Lib3dsPoint)*points,1); + if (!mesh->pointL) { + LIB3DS_ERROR_LOG; + return(LIB3DS_FALSE); + } + mesh->points=points; + return(LIB3DS_TRUE); +} + + +/*! + * Free point list in mesh object. + * + * The current point list is freed and set to NULL. mesh->points is + * set to zero. + * + * \param mesh Mesh object to be modified. + * + * \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); + } +} + + +/*! + * Allocate flag list in mesh object. + * + * This function frees the current flag list, if any, and allocates + * a new one large enough to hold the specified number of flags. + * All flags are initialized to 0 + * + * \param mesh Mesh object for which points are to be allocated. + * \param flags Number of flags in the new flag list. + * + * \return LIB3DS_TRUE on success, LIB3DS_FALSE on failure. + * + * \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=calloc(sizeof(Lib3dsWord)*flags,1); + if (!mesh->flagL) { + LIB3DS_ERROR_LOG; + return(LIB3DS_FALSE); + } + mesh->flags=flags; + return(LIB3DS_TRUE); +} + + +/*! + * Free flag list in mesh object. + * + * The current flag list is freed and set to NULL. mesh->flags is + * set to zero. + * + * \param mesh Mesh object to be modified. + * + * \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); + } +} + + +/*! + * Allocate texel list in mesh object. + * + * This function frees the current texel list, if any, and allocates + * a new one large enough to hold the specified number of texels. + * + * \param mesh Mesh object for which points are to be allocated. + * \param texels Number of texels in the new texel list. + * + * \return LIB3DS_TRUE on success, LIB3DS_FALSE on failure. + * + * \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=calloc(sizeof(Lib3dsTexel)*texels,1); + if (!mesh->texelL) { + LIB3DS_ERROR_LOG; + return(LIB3DS_FALSE); + } + mesh->texels=texels; + return(LIB3DS_TRUE); +} + + +/*! + * Free texel list in mesh object. + * + * The current texel list is freed and set to NULL. mesh->texels is + * set to zero. + * + * \param mesh Mesh object to be modified. + * + * \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); + } +} + + +/*! + * Allocate face list in mesh object. + * + * This function frees the current face list, if any, and allocates + * a new one large enough to hold the specified number of faces. + * + * \param mesh Mesh object for which points are to be allocated. + * \param faces Number of faces in the new face list. + * + * \return LIB3DS_TRUE on success, LIB3DS_FALSE on failure. + * + * \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=calloc(sizeof(Lib3dsFace)*faces,1); + if (!mesh->faceL) { + LIB3DS_ERROR_LOG; + return(LIB3DS_FALSE); + } + mesh->faces=faces; + return(LIB3DS_TRUE); +} + + +/*! + * Free face list in mesh object. + * + * The current face list is freed and set to NULL. mesh->faces is + * set to zero. + * + * \param mesh Mesh object to be modified. + * + * \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); + } +} + + +/*! + * Find the bounding box of a mesh object. + * + * \param mesh The mesh object + * \param bmin Returned bounding box + * \param bmax Returned bounding box + * + * \ingroup mesh + */ +void +lib3ds_mesh_bounding_box(Lib3dsMesh *mesh, Lib3dsVector bmin, Lib3dsVector bmax) +{ + unsigned i; + bmin[0] = bmin[1] = bmin[2] = FLT_MAX; + bmax[0] = bmax[1] = bmax[2] = FLT_MIN; + + for (i=0; i<mesh->points; ++i) { + lib3ds_vector_min(bmin, mesh->pointL[i].pos); + lib3ds_vector_max(bmax, mesh->pointL[i].pos); + } +} + + +typedef struct _Lib3dsFaces Lib3dsFaces; + +struct _Lib3dsFaces { + Lib3dsFaces *next; + Lib3dsFace *face; +}; + + +/*! + * 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 + * + * \ingroup mesh + */ +void +lib3ds_mesh_calculate_normals(Lib3dsMesh *mesh, Lib3dsVector *normalL) +{ + Lib3dsFaces **fl; + Lib3dsFaces *fa; + unsigned i,j,k; + + if (!mesh->faces) { + return; + } + + fl=calloc(sizeof(Lib3dsFaces*),mesh->points); + ASSERT(fl); + fa=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) { + // FIXME: static array needs at least check!! + Lib3dsVector n,N[128]; + 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 ( l >= 128 ) + printf("array N overflow: i=%d, j=%d, k=%d\n", i,j,k); + 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=%ld faces=%ld\n", + mesh->name, + (long)(mesh->points), + (long)(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->faces; ++i) { + printf (" %4d %4d %4d smoothing:%X flags:%X material:\"%s\"\n", + mesh->faceL[i].points[0], + mesh->faceL[i].points[1], + mesh->faceL[i].points[2], + (unsigned)mesh->faceL[i].smoothing, + mesh->faceL[i].flags, + mesh->faceL[i].material + ); + } +} + + +/*! + * \ingroup mesh + */ +Lib3dsBool +lib3ds_mesh_read(Lib3dsMesh *mesh, Lib3dsIo *io) +{ + Lib3dsChunk c; + Lib3dsWord chunk; + + if (!lib3ds_chunk_read_start(&c, LIB3DS_N_TRI_OBJECT, io)) { + return(LIB3DS_FALSE); + } + + while ((chunk=lib3ds_chunk_read_next(&c, io))!=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_io_read_float(io); + } + } + } + break; + case LIB3DS_MESH_COLOR: + { + mesh->color=lib3ds_io_read_byte(io); + } + break; + case LIB3DS_POINT_ARRAY: + { + unsigned i,j; + unsigned points; + + lib3ds_mesh_free_point_list(mesh); + points=lib3ds_io_read_word(io); + 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_io_read_float(io); + } + } + 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_io_read_word(io); + 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_io_read_word(io); + } + ASSERT((!mesh->points) || (mesh->flags==mesh->points)); + ASSERT((!mesh->texels) || (mesh->flags==mesh->texels)); + } + } + break; + case LIB3DS_FACE_ARRAY: + { + lib3ds_chunk_read_reset(&c, io); + if (!face_array_read(mesh, io)) { + return(LIB3DS_FALSE); + } + } + break; + case LIB3DS_MESH_TEXTURE_INFO: + { + int i,j; + + for (i=0; i<2; ++i) { + mesh->map_data.tile[i]=lib3ds_io_read_float(io); + } + for (i=0; i<3; ++i) { + mesh->map_data.pos[i]=lib3ds_io_read_float(io); + } + mesh->map_data.scale=lib3ds_io_read_float(io); + + 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_io_read_float(io); + } + } + for (i=0; i<2; ++i) { + mesh->map_data.planar_size[i]=lib3ds_io_read_float(io); + } + mesh->map_data.cylinder_height=lib3ds_io_read_float(io); + } + break; + case LIB3DS_TEX_VERTS: + { + unsigned i; + unsigned texels; + + lib3ds_mesh_free_texel_list(mesh); + texels=lib3ds_io_read_word(io); + 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_io_read_float(io); + mesh->texelL[i][1]=lib3ds_io_read_float(io); + } + 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 + ); + } + } + + if (lib3ds_matrix_det(mesh->matrix) < 0.0) + { + /* Flip X coordinate of vertices if mesh matrix + has negative determinant */ + Lib3dsMatrix inv_matrix, M; + Lib3dsVector tmp; + unsigned i; + + lib3ds_matrix_copy(inv_matrix, mesh->matrix); + lib3ds_matrix_inv(inv_matrix); + + lib3ds_matrix_copy(M, mesh->matrix); + lib3ds_matrix_scale_xyz(M, -1.0f, 1.0f, 1.0f); + lib3ds_matrix_mult(M, inv_matrix); + + for (i=0; i<mesh->points; ++i) { + lib3ds_vector_transform(tmp, M, mesh->pointL[i].pos); + lib3ds_vector_copy(mesh->pointL[i].pos, tmp); + } + } + + lib3ds_chunk_read_end(&c, io); + + return(LIB3DS_TRUE); +} + + +static Lib3dsBool +point_array_write(Lib3dsMesh *mesh, Lib3dsIo *io) +{ + 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, io); + + lib3ds_io_write_word(io, (Lib3dsWord)mesh->points); + + if (lib3ds_matrix_det(mesh->matrix) >= 0.0f) { + for (i=0; i<mesh->points; ++i) { + lib3ds_io_write_vector(io, mesh->pointL[i].pos); + } + } + else { + /* Flip X coordinate of vertices if mesh matrix + has negative determinant */ + Lib3dsMatrix inv_matrix, M; + Lib3dsVector tmp; + + lib3ds_matrix_copy(inv_matrix, mesh->matrix); + lib3ds_matrix_inv(inv_matrix); + lib3ds_matrix_copy(M, mesh->matrix); + lib3ds_matrix_scale_xyz(M, -1.0f, 1.0f, 1.0f); + lib3ds_matrix_mult(M, inv_matrix); + + for (i=0; i<mesh->points; ++i) { + lib3ds_vector_transform(tmp, M, mesh->pointL[i].pos); + lib3ds_io_write_vector(io, tmp); + } + } + + return(LIB3DS_TRUE); +} + + +static Lib3dsBool +flag_array_write(Lib3dsMesh *mesh, Lib3dsIo *io) +{ + 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, io); + + lib3ds_io_write_word(io, (Lib3dsWord)mesh->flags); + for (i=0; i<mesh->flags; ++i) { + lib3ds_io_write_word(io, mesh->flagL[i]); + } + return(LIB3DS_TRUE); +} + + +static Lib3dsBool +face_array_write(Lib3dsMesh *mesh, Lib3dsIo *io) +{ + 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, io)) { + return(LIB3DS_FALSE); + } + { + unsigned i; + + lib3ds_io_write_word(io, (Lib3dsWord)mesh->faces); + for (i=0; i<mesh->faces; ++i) { + lib3ds_io_write_word(io, mesh->faceL[i].points[0]); + lib3ds_io_write_word(io, mesh->faceL[i].points[1]); + lib3ds_io_write_word(io, mesh->faceL[i].points[2]); + lib3ds_io_write_word(io, mesh->faceL[i].flags); + } + } + + { /*---- MSH_MAT_GROUP ----*/ + Lib3dsChunk c; + unsigned i,j; + Lib3dsWord num; + char *matf=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+ (Lib3dsDword)strlen(mesh->faceL[i].material)+1 +2+2*num; + lib3ds_chunk_write(&c, io); + lib3ds_io_write_string(io, mesh->faceL[i].material); + lib3ds_io_write_word(io, num); + lib3ds_io_write_word(io, (Lib3dsWord)i); + + for (j=i+1; j<mesh->faces; ++j) { + if (strcmp(mesh->faceL[i].material, mesh->faceL[j].material)==0) { + lib3ds_io_write_word(io, (Lib3dsWord)j); + 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, io); + + for (i=0; i<mesh->faces; ++i) { + lib3ds_io_write_dword(io, mesh->faceL[i].smoothing); + } + } + + { /*---- 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, io)) { + return(LIB3DS_FALSE); + } + + lib3ds_io_write_string(io, mesh->box_map.front); + lib3ds_io_write_string(io, mesh->box_map.back); + lib3ds_io_write_string(io, mesh->box_map.left); + lib3ds_io_write_string(io, mesh->box_map.right); + lib3ds_io_write_string(io, mesh->box_map.top); + lib3ds_io_write_string(io, mesh->box_map.bottom); + + if (!lib3ds_chunk_write_end(&c, io)) { + return(LIB3DS_FALSE); + } + } + } + + if (!lib3ds_chunk_write_end(&c, io)) { + return(LIB3DS_FALSE); + } + return(LIB3DS_TRUE); +} + + +static Lib3dsBool +texel_array_write(Lib3dsMesh *mesh, Lib3dsIo *io) +{ + 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, io); + + lib3ds_io_write_word(io, (Lib3dsWord)mesh->texels); + for (i=0; i<mesh->texels; ++i) { + lib3ds_io_write_float(io, mesh->texelL[i][0]); + lib3ds_io_write_float(io, mesh->texelL[i][1]); + } + return(LIB3DS_TRUE); +} + + +/*! + * \ingroup mesh + */ +Lib3dsBool +lib3ds_mesh_write(Lib3dsMesh *mesh, Lib3dsIo *io) +{ + Lib3dsChunk c; + + c.chunk=LIB3DS_N_TRI_OBJECT; + if (!lib3ds_chunk_write_start(&c,io)) { + return(LIB3DS_FALSE); + } + if (!point_array_write(mesh, io)) { + return(LIB3DS_FALSE); + } + if (!texel_array_write(mesh, io)) { + 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,io)) { + return(LIB3DS_FALSE); + } + + lib3ds_io_write_word(io, mesh->map_data.maptype); + + for (i=0; i<2; ++i) { + lib3ds_io_write_float(io, mesh->map_data.tile[i]); + } + for (i=0; i<3; ++i) { + lib3ds_io_write_float(io, mesh->map_data.pos[i]); + } + lib3ds_io_write_float(io, mesh->map_data.scale); + + for (i=0; i<4; i++) { + for (j=0; j<3; j++) { + lib3ds_io_write_float(io, mesh->map_data.matrix[i][j]); + } + } + for (i=0; i<2; ++i) { + lib3ds_io_write_float(io, mesh->map_data.planar_size[i]); + } + lib3ds_io_write_float(io, mesh->map_data.cylinder_height); + } + + if (!flag_array_write(mesh, io)) { + return(LIB3DS_FALSE); + } + { /*---- LIB3DS_MESH_MATRIX ----*/ + Lib3dsChunk c; + int i,j; + + c.chunk=LIB3DS_MESH_MATRIX; + c.size=54; + if (!lib3ds_chunk_write(&c,io)) { + return(LIB3DS_FALSE); + } + for (i=0; i<4; i++) { + for (j=0; j<3; j++) { + lib3ds_io_write_float(io, mesh->matrix[i][j]); + } + } + } + + if (mesh->color) { /*---- LIB3DS_MESH_COLOR ----*/ + Lib3dsChunk c; + + c.chunk=LIB3DS_MESH_COLOR; + c.size=7; + if (!lib3ds_chunk_write(&c,io)) { + return(LIB3DS_FALSE); + } + lib3ds_io_write_byte(io, mesh->color); + } + if (!face_array_write(mesh, io)) { + return(LIB3DS_FALSE); + } + + if (!lib3ds_chunk_write_end(&c,io)) { + return(LIB3DS_FALSE); + } + return(LIB3DS_TRUE); +} + diff --git a/3rdparty/lib3ds/mesh.h b/3rdparty/lib3ds/mesh.h new file mode 100644 index 000000000..66282e267 --- /dev/null +++ b/3rdparty/lib3ds/mesh.h @@ -0,0 +1,157 @@ +/* -*- c -*- */ +#ifndef INCLUDED_LIB3DS_MESH_H +#define INCLUDED_LIB3DS_MESH_H +/* + * The 3D Studio File Format Library + * Copyright (C) 1996-2007 by Jan Eric Kyprianidis <www.kyprianidis.com> + * 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: mesh.h,v 1.20 2007/06/20 17:04:08 jeh Exp $ + */ + +#ifndef INCLUDED_LIB3DS_TYPES_H +#include <lib3ds/types.h> +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Triangular mesh point + * \ingroup mesh + */ +typedef struct Lib3dsPoint { + Lib3dsVector pos; +} Lib3dsPoint; + +/** + * Triangular mesh face + * \ingroup mesh + * \sa Lib3dsFaceFlag + */ +struct Lib3dsFace { + Lib3dsUserData user; /*! Arbitrary user data */ + char material[64]; /*! Material name */ + Lib3dsWord points[3]; /*! Indices into mesh points list */ + Lib3dsWord flags; /*! See Lib3dsFaceFlag, below */ + Lib3dsDword smoothing; /*! Bitmask; each bit identifies a group */ + Lib3dsVector normal; +}; + + +/** + * Vertex flags + * Meaning of _Lib3dsFace::flags. ABC are points of the current face + * (A: is 1st vertex, B is 2nd vertex, C is 3rd vertex) + */ +typedef enum { + LIB3DS_FACE_FLAG_VIS_AC = 0x1, /*!< Bit 0: Edge visibility AC */ + LIB3DS_FACE_FLAG_VIS_BC = 0x2, /*!< Bit 1: Edge visibility BC */ + LIB3DS_FACE_FLAG_VIS_AB = 0x4, /*!< Bit 2: Edge visibility AB */ + LIB3DS_FACE_FLAG_WRAP_U = 0x8, /*!< Bit 3: Face is at tex U wrap seam */ + LIB3DS_FACE_FLAG_WRAP_V = 0x10, /*!< Bit 4: Face is at tex V wrap seam */ + LIB3DS_FACE_FLAG_UNK7 = 0x80, /* Bit 5-8: Unused ? */ + LIB3DS_FACE_FLAG_UNK10 = 0x400, /* Bit 9-10: Random ? */ + /* Bit 11-12: Unused ? */ + LIB3DS_FACE_FLAG_SELECT_3 = (1<<13), /*!< Bit 13: Selection of the face in selection 3*/ + LIB3DS_FACE_FLAG_SELECT_2 = (1<<14), /*!< Bit 14: Selection of the face in selection 2*/ + LIB3DS_FACE_FLAG_SELECT_1 = (1<<15), /*!< Bit 15: Selection of the face in selection 1*/ +} Lib3dsFaceFlag; + +/** + * Triangular mesh box mapping settings + * \ingroup mesh + */ +struct Lib3dsBoxMap { + char front[64]; + char back[64]; + char left[64]; + char right[64]; + char top[64]; + char bottom[64]; +}; + +/** + * Texture projection type + * \ingroup tracks + */ +typedef enum { + LIB3DS_MAP_NONE =0xFFFF, + LIB3DS_MAP_PLANAR =0, + LIB3DS_MAP_CYLINDRICAL =1, + LIB3DS_MAP_SPHERICAL =2 +} Lib3dsMapType; + +/** + * Triangular mesh texture mapping data + * \ingroup mesh + */ +struct Lib3dsMapData { + Lib3dsWord maptype; + Lib3dsVector pos; + Lib3dsMatrix matrix; + Lib3dsFloat scale; + Lib3dsFloat tile[2]; + Lib3dsFloat planar_size[2]; + Lib3dsFloat cylinder_height; +}; + +/** + * Triangular mesh object + * \ingroup mesh + */ +struct Lib3dsMesh { + Lib3dsUserData user; /*< Arbitrary user data */ + Lib3dsMesh *next; + char name[64]; /*< Mesh name. Don't use more than 8 characters */ + Lib3dsDword object_flags; /*< @see Lib3dsObjectFlags */ + Lib3dsByte color; + Lib3dsMatrix matrix; /*< Transformation matrix for mesh data */ + Lib3dsDword points; /*< Number of points in point list */ + Lib3dsPoint *pointL; /*< Point list */ + Lib3dsDword flags; /*< Number of flags in per-point flags list */ + Lib3dsWord *flagL; /*< Per-point flags list */ + Lib3dsDword texels; /*< Number of U-V texture coordinates */ + Lib3dsTexel *texelL; /*< U-V texture coordinates */ + Lib3dsDword faces; /*< Number of faces in face list */ + Lib3dsFace *faceL; /*< Face list */ + Lib3dsBoxMap box_map; + Lib3dsMapData map_data; +}; + +extern LIB3DSAPI Lib3dsMesh* lib3ds_mesh_new(const char *name); +extern LIB3DSAPI void lib3ds_mesh_free(Lib3dsMesh *mesh); +extern LIB3DSAPI Lib3dsBool lib3ds_mesh_new_point_list(Lib3dsMesh *mesh, Lib3dsDword points); +extern LIB3DSAPI void lib3ds_mesh_free_point_list(Lib3dsMesh *mesh); +extern LIB3DSAPI Lib3dsBool lib3ds_mesh_new_flag_list(Lib3dsMesh *mesh, Lib3dsDword flags); +extern LIB3DSAPI void lib3ds_mesh_free_flag_list(Lib3dsMesh *mesh); +extern LIB3DSAPI Lib3dsBool lib3ds_mesh_new_texel_list(Lib3dsMesh *mesh, Lib3dsDword texels); +extern LIB3DSAPI void lib3ds_mesh_free_texel_list(Lib3dsMesh *mesh); +extern LIB3DSAPI Lib3dsBool lib3ds_mesh_new_face_list(Lib3dsMesh *mesh, Lib3dsDword flags); +extern LIB3DSAPI void lib3ds_mesh_free_face_list(Lib3dsMesh *mesh); +extern LIB3DSAPI void lib3ds_mesh_bounding_box(Lib3dsMesh *mesh, Lib3dsVector bmin, Lib3dsVector bmax); +extern LIB3DSAPI void lib3ds_mesh_calculate_normals(Lib3dsMesh *mesh, Lib3dsVector *normalL); +extern LIB3DSAPI void lib3ds_mesh_dump(Lib3dsMesh *mesh); +extern LIB3DSAPI Lib3dsBool lib3ds_mesh_read(Lib3dsMesh *mesh, Lib3dsIo *io); +extern LIB3DSAPI Lib3dsBool lib3ds_mesh_write(Lib3dsMesh *mesh, Lib3dsIo *io); + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/3rdparty/lib3ds/node.c b/3rdparty/lib3ds/node.c new file mode 100644 index 000000000..58f8a3971 --- /dev/null +++ b/3rdparty/lib3ds/node.c @@ -0,0 +1,1089 @@ +/* + * The 3D Studio File Format Library + * Copyright (C) 1996-2007 by Jan Eric Kyprianidis <www.kyprianidis.com> + * 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: node.c,v 1.20 2007/06/20 17:04:08 jeh Exp $ + */ +#include <lib3ds/node.h> +#include <lib3ds/file.h> +#include <lib3ds/io.h> +#include <lib3ds/chunk.h> +#include <lib3ds/matrix.h> +#include <stdlib.h> +#include <string.h> +#include <math.h> + + +/*! + * \defgroup node Animation Nodes + */ + + +/*! + * Create and return a new ambient node. + * + * The node is returned with an identity matrix. All other fields + * are zero. + * + * \return Lib3dsNode + * + * \ingroup node + */ +Lib3dsNode* +lib3ds_node_new_ambient() +{ + Lib3dsNode *node=(Lib3dsNode*)calloc(sizeof(Lib3dsNode), 1); + node->type=LIB3DS_AMBIENT_NODE; + lib3ds_matrix_identity(node->matrix); + return(node); +} + + +/*! + * Create and return a new object node. + * + * The node is returned with an identity matrix. All other fields + * are zero. + * + * \return Lib3dsNode + * + * \ingroup node + */ +Lib3dsNode* +lib3ds_node_new_object() +{ + Lib3dsNode *node=(Lib3dsNode*)calloc(sizeof(Lib3dsNode), 1); + node->type=LIB3DS_OBJECT_NODE; + lib3ds_matrix_identity(node->matrix); + return(node); +} + + +/*! + * Create and return a new camera node. + * + * The node is returned with an identity matrix. All other fields + * are zero. + * + * \return Lib3dsNode + * + * \ingroup node + */ +Lib3dsNode* +lib3ds_node_new_camera() +{ + Lib3dsNode *node=(Lib3dsNode*)calloc(sizeof(Lib3dsNode), 1); + node->type=LIB3DS_CAMERA_NODE; + lib3ds_matrix_identity(node->matrix); + return(node); +} + + +/*! + * Create and return a new target node. + * + * The node is returned with an identity matrix. All other fields + * are zero. + * + * \return Lib3dsNode + * + * \ingroup node + */ +Lib3dsNode* +lib3ds_node_new_target() +{ + Lib3dsNode *node=(Lib3dsNode*)calloc(sizeof(Lib3dsNode), 1); + node->type=LIB3DS_TARGET_NODE; + lib3ds_matrix_identity(node->matrix); + return(node); +} + + +/*! + * Create and return a new light node. + * + * The node is returned with an identity matrix. All other fields + * are zero. + * + * \return Lib3dsNode + * + * \ingroup node + */ +Lib3dsNode* +lib3ds_node_new_light() +{ + Lib3dsNode *node=(Lib3dsNode*)calloc(sizeof(Lib3dsNode), 1); + node->type=LIB3DS_LIGHT_NODE; + lib3ds_matrix_identity(node->matrix); + return(node); +} + + +/*! + * Create and return a new spot node. + * + * The node is returned with an identity matrix. All other fields + * are zero. + * + * \return Lib3dsNode + * + * \ingroup node + */ +Lib3dsNode* +lib3ds_node_new_spot() +{ + Lib3dsNode *node=(Lib3dsNode*)calloc(sizeof(Lib3dsNode), 1); + node->type=LIB3DS_SPOT_NODE; + lib3ds_matrix_identity(node->matrix); + return(node); +} + + +static void +free_node_and_childs(Lib3dsNode *node) +{ + ASSERT(node); + switch (node->type) { + case LIB3DS_UNKNOWN_NODE: + break; + case LIB3DS_AMBIENT_NODE: + { + Lib3dsAmbientData *n=&node->data.ambient; + lib3ds_lin3_track_free_keys(&n->col_track); + } + break; + case LIB3DS_OBJECT_NODE: + { + Lib3dsObjectData *n=&node->data.object; + + lib3ds_lin3_track_free_keys(&n->pos_track); + lib3ds_quat_track_free_keys(&n->rot_track); + lib3ds_lin3_track_free_keys(&n->scl_track); + lib3ds_bool_track_free_keys(&n->hide_track); + lib3ds_morph_track_free_keys(&n->morph_track); + } + break; + case LIB3DS_CAMERA_NODE: + { + Lib3dsCameraData *n=&node->data.camera; + lib3ds_lin3_track_free_keys(&n->pos_track); + lib3ds_lin1_track_free_keys(&n->fov_track); + lib3ds_lin1_track_free_keys(&n->roll_track); + } + break; + case LIB3DS_TARGET_NODE: + { + Lib3dsTargetData *n=&node->data.target; + lib3ds_lin3_track_free_keys(&n->pos_track); + } + break; + case LIB3DS_LIGHT_NODE: + { + Lib3dsLightData *n=&node->data.light; + lib3ds_lin3_track_free_keys(&n->pos_track); + lib3ds_lin3_track_free_keys(&n->col_track); + lib3ds_lin1_track_free_keys(&n->hotspot_track); + lib3ds_lin1_track_free_keys(&n->falloff_track); + lib3ds_lin1_track_free_keys(&n->roll_track); + } + break; + case LIB3DS_SPOT_NODE: + { + Lib3dsSpotData *n=&node->data.spot; + lib3ds_lin3_track_free_keys(&n->pos_track); + } + break; + } + { + Lib3dsNode *p,*q; + for (p=node->childs; p; p=q) { + q=p->next; + free_node_and_childs(p); + } + } + node->type=LIB3DS_UNKNOWN_NODE; + free(node); +} + + +/*! + * Free a node and all of its resources. + * + * \param node Lib3dsNode object to be freed. + * + * \ingroup node + */ +void +lib3ds_node_free(Lib3dsNode *node) +{ + ASSERT(node); + free_node_and_childs(node); +} + + +/*! + * Evaluate an animation node. + * + * Recursively sets node and its children to their appropriate values + * for this point in the animation. + * + * \param node Node to be evaluated. + * \param t time value, between 0. and file->frames + * + * \ingroup node + */ +void +lib3ds_node_eval(Lib3dsNode *node, Lib3dsFloat t) +{ + ASSERT(node); + switch (node->type) { + case LIB3DS_UNKNOWN_NODE: + { + ASSERT(LIB3DS_FALSE); + } + break; + case LIB3DS_AMBIENT_NODE: + { + Lib3dsAmbientData *n=&node->data.ambient; + if (node->parent) { + lib3ds_matrix_copy(node->matrix, node->parent->matrix); + } + else { + lib3ds_matrix_identity(node->matrix); + } + lib3ds_lin3_track_eval(&n->col_track, n->col, t); + } + break; + case LIB3DS_OBJECT_NODE: + { + Lib3dsMatrix M; + Lib3dsObjectData *n=&node->data.object; + + lib3ds_lin3_track_eval(&n->pos_track, n->pos, t); + lib3ds_quat_track_eval(&n->rot_track, n->rot, t); + if (n->scl_track.keyL) { + lib3ds_lin3_track_eval(&n->scl_track, n->scl, t); + } + else { + n->scl[0] = n->scl[1] = n->scl[2] = 1.0f; + } + lib3ds_bool_track_eval(&n->hide_track, &n->hide, t); + lib3ds_morph_track_eval(&n->morph_track, n->morph, t); + + lib3ds_matrix_identity(M); + lib3ds_matrix_translate(M, n->pos); + lib3ds_matrix_rotate(M, n->rot); + lib3ds_matrix_scale(M, n->scl); + + if (node->parent) { + lib3ds_matrix_copy(node->matrix, node->parent->matrix); + lib3ds_matrix_mult(node->matrix, M); + } + else { + lib3ds_matrix_copy(node->matrix, M); + } + } + break; + case LIB3DS_CAMERA_NODE: + { + Lib3dsCameraData *n=&node->data.camera; + lib3ds_lin3_track_eval(&n->pos_track, n->pos, t); + lib3ds_lin1_track_eval(&n->fov_track, &n->fov, t); + lib3ds_lin1_track_eval(&n->roll_track, &n->roll, t); + if (node->parent) { + lib3ds_matrix_copy(node->matrix, node->parent->matrix); + } + else { + lib3ds_matrix_identity(node->matrix); + } + lib3ds_matrix_translate(node->matrix, n->pos); + } + break; + case LIB3DS_TARGET_NODE: + { + Lib3dsTargetData *n=&node->data.target; + lib3ds_lin3_track_eval(&n->pos_track, n->pos, t); + if (node->parent) { + lib3ds_matrix_copy(node->matrix, node->parent->matrix); + } + else { + lib3ds_matrix_identity(node->matrix); + } + lib3ds_matrix_translate(node->matrix, n->pos); + } + break; + case LIB3DS_LIGHT_NODE: + { + Lib3dsLightData *n=&node->data.light; + lib3ds_lin3_track_eval(&n->pos_track, n->pos, t); + lib3ds_lin3_track_eval(&n->col_track, n->col, t); + lib3ds_lin1_track_eval(&n->hotspot_track, &n->hotspot, t); + lib3ds_lin1_track_eval(&n->falloff_track, &n->falloff, t); + lib3ds_lin1_track_eval(&n->roll_track, &n->roll, t); + if (node->parent) { + lib3ds_matrix_copy(node->matrix, node->parent->matrix); + } + else { + lib3ds_matrix_identity(node->matrix); + } + lib3ds_matrix_translate(node->matrix, n->pos); + } + break; + case LIB3DS_SPOT_NODE: + { + Lib3dsSpotData *n=&node->data.spot; + lib3ds_lin3_track_eval(&n->pos_track, n->pos, t); + if (node->parent) { + lib3ds_matrix_copy(node->matrix, node->parent->matrix); + } + else { + lib3ds_matrix_identity(node->matrix); + } + lib3ds_matrix_translate(node->matrix, n->pos); + } + break; + } + { + Lib3dsNode *p; + + for (p=node->childs; p!=0; p=p->next) { + lib3ds_node_eval(p, t); + } + } +} + + +/*! + * Return a node object by name and type. + * + * This function performs a recursive search for the specified node. + * Both name and type must match. + * + * \param node The parent node for the search + * \param name The target node name. + * \param type The target node type + * + * \return A pointer to the first matching node, or NULL if not found. + * + * \ingroup node + */ +Lib3dsNode* +lib3ds_node_by_name(Lib3dsNode *node, const char* name, Lib3dsNodeTypes type) +{ + Lib3dsNode *p,*q; + + for (p=node->childs; p!=0; p=p->next) { + if ((p->type==type) && (strcmp(p->name, name)==0)) { + return(p); + } + q=lib3ds_node_by_name(p, name, type); + if (q) { + return(q); + } + } + return(0); +} + + +/*! + * Return a node object by id. + * + * This function performs a recursive search for the specified node. + * + * \param node The parent node for the search + * \param node_id The target node id. + * + * \return A pointer to the first matching node, or NULL if not found. + * + * \ingroup node + */ +Lib3dsNode* +lib3ds_node_by_id(Lib3dsNode *node, Lib3dsWord node_id) +{ + Lib3dsNode *p,*q; + + for (p=node->childs; p!=0; p=p->next) { + if (p->node_id==node_id) { + return(p); + } + q=lib3ds_node_by_id(p, node_id); + if (q) { + return(q); + } + } + return(0); +} + + +static const char* node_names_table[]= { + "***Unknown***", + "Ambient", + "Object", + "Camera", + "Target", + "Light", + "Spot" +}; + + +/*! + * Dump node and all descendants recursively. + * + * \param node The top-level node to be dumped. + * \param level current recursion depth + * + * \ingroup node + */ +void +lib3ds_node_dump(Lib3dsNode *node, Lib3dsIntd level) +{ + Lib3dsNode *p; + char l[128]; + + ASSERT(node); + memset(l, ' ', 2*level); + l[2*level]=0; + + if (node->type==LIB3DS_OBJECT_NODE) { + printf("%s%s [%s] (%s)\n", + l, + node->name, + node->data.object.instance, + node_names_table[node->type] + ); + } + else { + printf("%s%s (%s)\n", + l, + node->name, + node_names_table[node->type] + ); + } + + for (p=node->childs; p!=0; p=p->next) { + lib3ds_node_dump(p, level+1); + } +} + + +/*! + * \ingroup node + */ +Lib3dsBool +lib3ds_node_read(Lib3dsNode *node, Lib3dsFile *file, Lib3dsIo *io) +{ + Lib3dsChunk c; + Lib3dsWord chunk; + LIB3DS_UNUSED(file); + + ASSERT(node); + if (!lib3ds_chunk_read_start(&c, 0, io)) { + return(LIB3DS_FALSE); + } + switch (c.chunk) { + case LIB3DS_AMBIENT_NODE_TAG: + case LIB3DS_OBJECT_NODE_TAG: + case LIB3DS_CAMERA_NODE_TAG: + case LIB3DS_TARGET_NODE_TAG: + case LIB3DS_LIGHT_NODE_TAG: + case LIB3DS_SPOTLIGHT_NODE_TAG: + case LIB3DS_L_TARGET_NODE_TAG: + break; + default: + return(LIB3DS_FALSE); + } + + while ((chunk=lib3ds_chunk_read_next(&c, io))!=0) { + switch (chunk) { + case LIB3DS_NODE_ID: + { + node->node_id=lib3ds_io_read_word(io); + lib3ds_chunk_dump_info(" ID = %d", (short)node->node_id); + } + break; + case LIB3DS_NODE_HDR: + { + if (!lib3ds_io_read_string(io, node->name, 64)) { + return(LIB3DS_FALSE); + } + node->flags1=lib3ds_io_read_word(io); + node->flags2=lib3ds_io_read_word(io); + node->parent_id=lib3ds_io_read_word(io); + lib3ds_chunk_dump_info(" NAME =%s", node->name); + lib3ds_chunk_dump_info(" PARENT=%d", (short)node->parent_id); + } + break; + case LIB3DS_PIVOT: + { + if (node->type==LIB3DS_OBJECT_NODE) { + int i; + for (i=0; i<3; ++i) { + node->data.object.pivot[i]=lib3ds_io_read_float(io); + } + } + else { + lib3ds_chunk_unknown(chunk); + } + } + break; + case LIB3DS_INSTANCE_NAME: + { + if (node->type==LIB3DS_OBJECT_NODE) { + if (!lib3ds_io_read_string(io, node->data.object.instance, 64)) { + return(LIB3DS_FALSE); + } + } + else { + lib3ds_chunk_unknown(chunk); + } + } + break; + case LIB3DS_BOUNDBOX: + { + if (node->type==LIB3DS_OBJECT_NODE) { + int i; + for (i=0; i<3; ++i) { + node->data.object.bbox_min[i]=lib3ds_io_read_float(io); + } + for (i=0; i<3; ++i) { + node->data.object.bbox_max[i]=lib3ds_io_read_float(io); + } + } + else { + lib3ds_chunk_unknown(chunk); + } + } + break; + case LIB3DS_COL_TRACK_TAG: + { + Lib3dsBool result=LIB3DS_TRUE; + + switch (node->type) { + case LIB3DS_AMBIENT_NODE: + result=lib3ds_lin3_track_read(&node->data.ambient.col_track, io); + break; + case LIB3DS_LIGHT_NODE: + result=lib3ds_lin3_track_read(&node->data.light.col_track, io); + break; + default: + lib3ds_chunk_unknown(chunk); + } + if (!result) { + return(LIB3DS_FALSE); + } + } + break; + case LIB3DS_POS_TRACK_TAG: + { + Lib3dsBool result=LIB3DS_TRUE; + + switch (node->type) { + case LIB3DS_OBJECT_NODE: + result=lib3ds_lin3_track_read(&node->data.object.pos_track, io); + break; + case LIB3DS_CAMERA_NODE: + result=lib3ds_lin3_track_read(&node->data.camera.pos_track, io); + break; + case LIB3DS_TARGET_NODE: + result=lib3ds_lin3_track_read(&node->data.target.pos_track, io); + break; + case LIB3DS_LIGHT_NODE: + result=lib3ds_lin3_track_read(&node->data.light.pos_track, io); + break; + case LIB3DS_SPOT_NODE: + result=lib3ds_lin3_track_read(&node->data.spot.pos_track, io); + break; + default: + lib3ds_chunk_unknown(chunk); + } + if (!result) { + return(LIB3DS_FALSE); + } + } + break; + case LIB3DS_ROT_TRACK_TAG: + { + if (node->type==LIB3DS_OBJECT_NODE) { + if (!lib3ds_quat_track_read(&node->data.object.rot_track, io)) { + return(LIB3DS_FALSE); + } + } + else { + lib3ds_chunk_unknown(chunk); + } + } + break; + case LIB3DS_SCL_TRACK_TAG: + { + if (node->type==LIB3DS_OBJECT_NODE) { + if (!lib3ds_lin3_track_read(&node->data.object.scl_track, io)) { + return(LIB3DS_FALSE); + } + } + else { + lib3ds_chunk_unknown(chunk); + } + } + break; + case LIB3DS_FOV_TRACK_TAG: + { + if (node->type==LIB3DS_CAMERA_NODE) { + if (!lib3ds_lin1_track_read(&node->data.camera.fov_track, io)) { + return(LIB3DS_FALSE); + } + } + else { + lib3ds_chunk_unknown(chunk); + } + } + break; + case LIB3DS_HOT_TRACK_TAG: + { + if (node->type==LIB3DS_LIGHT_NODE) { + if (!lib3ds_lin1_track_read(&node->data.light.hotspot_track, io)) { + return(LIB3DS_FALSE); + } + } + else { + lib3ds_chunk_unknown(chunk); + } + } + break; + case LIB3DS_FALL_TRACK_TAG: + { + if (node->type==LIB3DS_LIGHT_NODE) { + if (!lib3ds_lin1_track_read(&node->data.light.falloff_track, io)) { + return(LIB3DS_FALSE); + } + } + else { + lib3ds_chunk_unknown(chunk); + } + } + break; + case LIB3DS_ROLL_TRACK_TAG: + { + Lib3dsBool result=LIB3DS_TRUE; + + switch (node->type) { + case LIB3DS_CAMERA_NODE: + result=lib3ds_lin1_track_read(&node->data.camera.roll_track, io); + break; + case LIB3DS_LIGHT_NODE: + result=lib3ds_lin1_track_read(&node->data.light.roll_track, io); + break; + default: + lib3ds_chunk_unknown(chunk); + } + if (!result) { + return(LIB3DS_FALSE); + } + } + break; + case LIB3DS_HIDE_TRACK_TAG: + { + if (node->type==LIB3DS_OBJECT_NODE) { + if (!lib3ds_bool_track_read(&node->data.object.hide_track, io)) { + return(LIB3DS_FALSE); + } + } + else { + lib3ds_chunk_unknown(chunk); + } + } + break; + case LIB3DS_MORPH_SMOOTH: + { + if (node->type==LIB3DS_OBJECT_NODE) { + node->data.object.morph_smooth=lib3ds_io_read_float(io); + } + else { + lib3ds_chunk_unknown(chunk); + } + } + break; + case LIB3DS_MORPH_TRACK_TAG: + { + if (node->type==LIB3DS_OBJECT_NODE) { + if (!lib3ds_morph_track_read(&node->data.object.morph_track, io)) { + return(LIB3DS_FALSE); + } + } + else { + lib3ds_chunk_unknown(chunk); + } + } + break; + default: + lib3ds_chunk_unknown(chunk); + } + } + + lib3ds_chunk_read_end(&c, io); + return(LIB3DS_TRUE); +} + + +/*! + * \ingroup node + */ +Lib3dsBool +lib3ds_node_write(Lib3dsNode *node, Lib3dsFile *file, Lib3dsIo *io) +{ + Lib3dsChunk c; + + switch (node->type) { + case LIB3DS_AMBIENT_NODE: + c.chunk=LIB3DS_AMBIENT_NODE_TAG; + break; + case LIB3DS_OBJECT_NODE: + c.chunk=LIB3DS_OBJECT_NODE_TAG; + break; + case LIB3DS_CAMERA_NODE: + c.chunk=LIB3DS_CAMERA_NODE_TAG; + break; + case LIB3DS_TARGET_NODE: + c.chunk=LIB3DS_TARGET_NODE_TAG; + break; + case LIB3DS_LIGHT_NODE: + if (lib3ds_file_node_by_name(file, node->name, LIB3DS_SPOT_NODE)) { + c.chunk=LIB3DS_SPOTLIGHT_NODE_TAG; + } + else { + c.chunk=LIB3DS_LIGHT_NODE_TAG; + } + break; + case LIB3DS_SPOT_NODE: + c.chunk=LIB3DS_L_TARGET_NODE_TAG; + break; + default: + return(LIB3DS_FALSE); + } + if (!lib3ds_chunk_write_start(&c,io)) { + return(LIB3DS_FALSE); + } + + { /*---- LIB3DS_NODE_ID ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_NODE_ID; + c.size=8; + lib3ds_chunk_write(&c,io); + lib3ds_io_write_intw(io, node->node_id); + } + + { /*---- LIB3DS_NODE_HDR ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_NODE_HDR; + c.size=6+ 1+(Lib3dsDword)strlen(node->name) +2+2+2; + lib3ds_chunk_write(&c,io); + lib3ds_io_write_string(io, node->name); + lib3ds_io_write_word(io, node->flags1); + lib3ds_io_write_word(io, node->flags2); + lib3ds_io_write_word(io, node->parent_id); + } + + switch (c.chunk) { + case LIB3DS_AMBIENT_NODE_TAG: + { /*---- LIB3DS_COL_TRACK_TAG ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_COL_TRACK_TAG; + if (!lib3ds_chunk_write_start(&c,io)) { + return(LIB3DS_FALSE); + } + if (!lib3ds_lin3_track_write(&node->data.ambient.col_track,io)) { + return(LIB3DS_FALSE); + } + if (!lib3ds_chunk_write_end(&c,io)) { + return(LIB3DS_FALSE); + } + } + break; + case LIB3DS_OBJECT_NODE_TAG: + { /*---- LIB3DS_PIVOT ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_PIVOT; + c.size=18; + lib3ds_chunk_write(&c,io); + lib3ds_io_write_vector(io, node->data.object.pivot); + } + { /*---- LIB3DS_INSTANCE_NAME ----*/ + Lib3dsChunk c; + const char *name; + if (strlen(node->data.object.instance)) { + name=node->data.object.instance; + + c.chunk=LIB3DS_INSTANCE_NAME; + c.size=6+1+(Lib3dsDword)strlen(name); + lib3ds_chunk_write(&c,io); + lib3ds_io_write_string(io, name); + } + } + { + int i; + for (i=0; i<3; ++i) { + if ((fabs(node->data.object.bbox_min[i])>LIB3DS_EPSILON) || + (fabs(node->data.object.bbox_max[i])>LIB3DS_EPSILON)) { + break; + } + } + + if (i<3) { /*---- LIB3DS_BOUNDBOX ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_BOUNDBOX; + c.size=30; + lib3ds_chunk_write(&c,io); + lib3ds_io_write_vector(io, node->data.object.bbox_min); + lib3ds_io_write_vector(io, node->data.object.bbox_max); + } + } + { /*---- LIB3DS_POS_TRACK_TAG ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_POS_TRACK_TAG; + if (!lib3ds_chunk_write_start(&c,io)) { + return(LIB3DS_FALSE); + } + if (!lib3ds_lin3_track_write(&node->data.object.pos_track,io)) { + return(LIB3DS_FALSE); + } + if (!lib3ds_chunk_write_end(&c,io)) { + return(LIB3DS_FALSE); + } + } + { /*---- LIB3DS_ROT_TRACK_TAG ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_ROT_TRACK_TAG; + if (!lib3ds_chunk_write_start(&c,io)) { + return(LIB3DS_FALSE); + } + if (!lib3ds_quat_track_write(&node->data.object.rot_track,io)) { + return(LIB3DS_FALSE); + } + if (!lib3ds_chunk_write_end(&c,io)) { + return(LIB3DS_FALSE); + } + } + { /*---- LIB3DS_SCL_TRACK_TAG ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_SCL_TRACK_TAG; + if (!lib3ds_chunk_write_start(&c,io)) { + return(LIB3DS_FALSE); + } + if (!lib3ds_lin3_track_write(&node->data.object.scl_track,io)) { + return(LIB3DS_FALSE); + } + if (!lib3ds_chunk_write_end(&c,io)) { + return(LIB3DS_FALSE); + } + } + if (node->data.object.hide_track.keyL) { /*---- LIB3DS_HIDE_TRACK_TAG ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_HIDE_TRACK_TAG; + if (!lib3ds_chunk_write_start(&c,io)) { + return(LIB3DS_FALSE); + } + if (!lib3ds_bool_track_write(&node->data.object.hide_track,io)) { + return(LIB3DS_FALSE); + } + if (!lib3ds_chunk_write_end(&c,io)) { + return(LIB3DS_FALSE); + } + } + if (fabs(node->data.object.morph_smooth)>LIB3DS_EPSILON){ /*---- LIB3DS_MORPH_SMOOTH ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_MORPH_SMOOTH; + c.size=10; + lib3ds_chunk_write(&c,io); + lib3ds_io_write_float(io, node->data.object.morph_smooth); + } + break; + case LIB3DS_CAMERA_NODE_TAG: + { /*---- LIB3DS_POS_TRACK_TAG ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_POS_TRACK_TAG; + if (!lib3ds_chunk_write_start(&c,io)) { + return(LIB3DS_FALSE); + } + if (!lib3ds_lin3_track_write(&node->data.camera.pos_track,io)) { + return(LIB3DS_FALSE); + } + if (!lib3ds_chunk_write_end(&c,io)) { + return(LIB3DS_FALSE); + } + } + { /*---- LIB3DS_FOV_TRACK_TAG ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_FOV_TRACK_TAG; + if (!lib3ds_chunk_write_start(&c,io)) { + return(LIB3DS_FALSE); + } + if (!lib3ds_lin1_track_write(&node->data.camera.fov_track,io)) { + return(LIB3DS_FALSE); + } + if (!lib3ds_chunk_write_end(&c,io)) { + return(LIB3DS_FALSE); + } + } + { /*---- LIB3DS_ROLL_TRACK_TAG ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_ROLL_TRACK_TAG; + if (!lib3ds_chunk_write_start(&c,io)) { + return(LIB3DS_FALSE); + } + if (!lib3ds_lin1_track_write(&node->data.camera.roll_track,io)) { + return(LIB3DS_FALSE); + } + if (!lib3ds_chunk_write_end(&c,io)) { + return(LIB3DS_FALSE); + } + } + break; + case LIB3DS_TARGET_NODE_TAG: + { /*---- LIB3DS_POS_TRACK_TAG ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_POS_TRACK_TAG; + if (!lib3ds_chunk_write_start(&c,io)) { + return(LIB3DS_FALSE); + } + if (!lib3ds_lin3_track_write(&node->data.target.pos_track,io)) { + return(LIB3DS_FALSE); + } + if (!lib3ds_chunk_write_end(&c,io)) { + return(LIB3DS_FALSE); + } + } + break; + case LIB3DS_LIGHT_NODE_TAG: + { /*---- LIB3DS_POS_TRACK_TAG ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_POS_TRACK_TAG; + if (!lib3ds_chunk_write_start(&c,io)) { + return(LIB3DS_FALSE); + } + if (!lib3ds_lin3_track_write(&node->data.light.pos_track,io)) { + return(LIB3DS_FALSE); + } + if (!lib3ds_chunk_write_end(&c,io)) { + return(LIB3DS_FALSE); + } + } + { /*---- LIB3DS_COL_TRACK_TAG ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_COL_TRACK_TAG; + if (!lib3ds_chunk_write_start(&c,io)) { + return(LIB3DS_FALSE); + } + if (!lib3ds_lin3_track_write(&node->data.light.col_track,io)) { + return(LIB3DS_FALSE); + } + if (!lib3ds_chunk_write_end(&c,io)) { + return(LIB3DS_FALSE); + } + } + break; + case LIB3DS_SPOTLIGHT_NODE_TAG: + { /*---- LIB3DS_POS_TRACK_TAG ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_POS_TRACK_TAG; + if (!lib3ds_chunk_write_start(&c,io)) { + return(LIB3DS_FALSE); + } + if (!lib3ds_lin3_track_write(&node->data.light.pos_track,io)) { + return(LIB3DS_FALSE); + } + if (!lib3ds_chunk_write_end(&c,io)) { + return(LIB3DS_FALSE); + } + } + { /*---- LIB3DS_COL_TRACK_TAG ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_COL_TRACK_TAG; + if (!lib3ds_chunk_write_start(&c,io)) { + return(LIB3DS_FALSE); + } + if (!lib3ds_lin3_track_write(&node->data.light.col_track,io)) { + return(LIB3DS_FALSE); + } + if (!lib3ds_chunk_write_end(&c,io)) { + return(LIB3DS_FALSE); + } + } + { /*---- LIB3DS_HOT_TRACK_TAG ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_HOT_TRACK_TAG; + if (!lib3ds_chunk_write_start(&c,io)) { + return(LIB3DS_FALSE); + } + if (!lib3ds_lin1_track_write(&node->data.light.hotspot_track,io)) { + return(LIB3DS_FALSE); + } + if (!lib3ds_chunk_write_end(&c,io)) { + return(LIB3DS_FALSE); + } + } + { /*---- LIB3DS_FALL_TRACK_TAG ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_FALL_TRACK_TAG; + if (!lib3ds_chunk_write_start(&c,io)) { + return(LIB3DS_FALSE); + } + if (!lib3ds_lin1_track_write(&node->data.light.falloff_track,io)) { + return(LIB3DS_FALSE); + } + if (!lib3ds_chunk_write_end(&c,io)) { + return(LIB3DS_FALSE); + } + } + { /*---- LIB3DS_ROLL_TRACK_TAG ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_ROLL_TRACK_TAG; + if (!lib3ds_chunk_write_start(&c,io)) { + return(LIB3DS_FALSE); + } + if (!lib3ds_lin1_track_write(&node->data.light.roll_track,io)) { + return(LIB3DS_FALSE); + } + if (!lib3ds_chunk_write_end(&c,io)) { + return(LIB3DS_FALSE); + } + } + break; + case LIB3DS_L_TARGET_NODE_TAG: + { /*---- LIB3DS_POS_TRACK_TAG ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_POS_TRACK_TAG; + if (!lib3ds_chunk_write_start(&c,io)) { + return(LIB3DS_FALSE); + } + if (!lib3ds_lin3_track_write(&node->data.spot.pos_track,io)) { + return(LIB3DS_FALSE); + } + if (!lib3ds_chunk_write_end(&c,io)) { + return(LIB3DS_FALSE); + } + } + break; + default: + return(LIB3DS_FALSE); + } + + if (!lib3ds_chunk_write_end(&c,io)) { + return(LIB3DS_FALSE); + } + return(LIB3DS_TRUE); +} + diff --git a/3rdparty/lib3ds/node.h b/3rdparty/lib3ds/node.h new file mode 100644 index 000000000..2b7de9af4 --- /dev/null +++ b/3rdparty/lib3ds/node.h @@ -0,0 +1,188 @@ +/* -*- c -*- */ +#ifndef INCLUDED_LIB3DS_NODE_H +#define INCLUDED_LIB3DS_NODE_H +/* + * The 3D Studio File Format Library + * Copyright (C) 1996-2007 by Jan Eric Kyprianidis <www.kyprianidis.com> + * 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: node.h,v 1.12 2007/06/20 17:04:09 jeh Exp $ + */ + +#ifndef INCLUDED_LIB3DS_TRACKS_H +#include <lib3ds/tracks.h> +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Scene graph ambient color node data + * \ingroup node + */ +typedef struct Lib3dsAmbientData { + Lib3dsRgb col; + Lib3dsLin3Track col_track; +} Lib3dsAmbientData; + +/** + * Scene graph object instance node data + * \ingroup node + */ +typedef struct Lib3dsObjectData { + Lib3dsVector pivot; + char instance[64]; + Lib3dsVector bbox_min; + Lib3dsVector bbox_max; + Lib3dsVector pos; + Lib3dsLin3Track pos_track; + Lib3dsQuat rot; + Lib3dsQuatTrack rot_track; + Lib3dsVector scl; + Lib3dsLin3Track scl_track; + Lib3dsFloat morph_smooth; + char morph[64]; + Lib3dsMorphTrack morph_track; + Lib3dsBool hide; + Lib3dsBoolTrack hide_track; +} Lib3dsObjectData; + +/** + * Scene graph camera node data + * \ingroup node + */ +typedef struct Lib3dsCameraData { + Lib3dsVector pos; + Lib3dsLin3Track pos_track; + Lib3dsFloat fov; + Lib3dsLin1Track fov_track; + Lib3dsFloat roll; + Lib3dsLin1Track roll_track; +} Lib3dsCameraData; + +/** + * Scene graph camera target node data + * \ingroup node + */ +typedef struct Lib3dsTargetData { + Lib3dsVector pos; + Lib3dsLin3Track pos_track; +} Lib3dsTargetData; + +/** + * Scene graph light node data + * \ingroup node + */ +typedef struct Lib3dsLightData { + Lib3dsVector pos; + Lib3dsLin3Track pos_track; + Lib3dsRgb col; + Lib3dsLin3Track col_track; + Lib3dsFloat hotspot; + Lib3dsLin1Track hotspot_track; + Lib3dsFloat falloff; + Lib3dsLin1Track falloff_track; + Lib3dsFloat roll; + Lib3dsLin1Track roll_track; +} Lib3dsLightData; + +/** + * Scene graph spotlight target node data + * \ingroup node + */ +typedef struct Lib3dsSpotData { + Lib3dsVector pos; + Lib3dsLin3Track pos_track; +} Lib3dsSpotData; + +/** + * Scene graph node data union + * \ingroup node + */ +typedef union Lib3dsNodeData { + Lib3dsAmbientData ambient; + Lib3dsObjectData object; + Lib3dsCameraData camera; + Lib3dsTargetData target; + Lib3dsLightData light; + Lib3dsSpotData spot; +} Lib3dsNodeData; + +/*! + * \ingroup node + */ +#define LIB3DS_NO_PARENT 65535 + +/** + * Scene graph node + * \ingroup node + */ +struct Lib3dsNode { + Lib3dsUserData user; + Lib3dsNode *next; + Lib3dsNode *childs; + Lib3dsNode *parent; + Lib3dsNodeTypes type; + Lib3dsWord node_id; + char name[64]; + Lib3dsWord flags1; + Lib3dsWord flags2; + Lib3dsWord parent_id; + Lib3dsMatrix matrix; + Lib3dsNodeData data; +}; + +/** + * Node flags #1 + * \ingroup node + */ +typedef enum { + LIB3DS_HIDDEN = 0x800 +} Lib3dsNodeFlags1; + +/** + * Node flags #2 + * \ingroup node + */ +typedef enum { + LIB3DS_SHOW_PATH = 0x1, + LIB3DS_SMOOTHING = 0x2, + LIB3DS_MOTION_BLUR = 0x10, + LIB3DS_MORPH_MATERIALS = 0x40 +} Lib3dsNodeFlags2; + +extern LIB3DSAPI Lib3dsNode* lib3ds_node_new_ambient(); +extern LIB3DSAPI Lib3dsNode* lib3ds_node_new_object(); +extern LIB3DSAPI Lib3dsNode* lib3ds_node_new_camera(); +extern LIB3DSAPI Lib3dsNode* lib3ds_node_new_target(); +extern LIB3DSAPI Lib3dsNode* lib3ds_node_new_light(); +extern LIB3DSAPI Lib3dsNode* lib3ds_node_new_spot(); +extern LIB3DSAPI void lib3ds_node_free(Lib3dsNode *node); +extern LIB3DSAPI void lib3ds_node_eval(Lib3dsNode *node, Lib3dsFloat t); +extern LIB3DSAPI Lib3dsNode* lib3ds_node_by_name(Lib3dsNode *node, const char* name, + Lib3dsNodeTypes type); +extern LIB3DSAPI Lib3dsNode* lib3ds_node_by_id(Lib3dsNode *node, Lib3dsWord node_id); +extern LIB3DSAPI void lib3ds_node_dump(Lib3dsNode *node, Lib3dsIntd level); +extern LIB3DSAPI Lib3dsBool lib3ds_node_read(Lib3dsNode *node, Lib3dsFile *file, Lib3dsIo *io); +extern LIB3DSAPI Lib3dsBool lib3ds_node_write(Lib3dsNode *node, Lib3dsFile *file, Lib3dsIo *io); + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/3rdparty/lib3ds/quat.c b/3rdparty/lib3ds/quat.c new file mode 100644 index 000000000..3553a95fc --- /dev/null +++ b/3rdparty/lib3ds/quat.c @@ -0,0 +1,418 @@ +/* + * The 3D Studio File Format Library + * Copyright (C) 1996-2007 by Jan Eric Kyprianidis <www.kyprianidis.com> + * 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: quat.c,v 1.9 2007/06/20 17:04:09 jeh Exp $ + */ +#include <lib3ds/quat.h> +#include <math.h> + + +/*! + * \defgroup quat Quaternion Mathematics + */ + + +/*! +* \typedef Lib3dsQuat +* \ingroup quat +*/ + + +/*! + * Clear a quaternion. + * \ingroup quat + */ +void +lib3ds_quat_zero(Lib3dsQuat c) +{ + c[0]=c[1]=c[2]=c[3]=0.0f; +} + + +/*! + * Set a quaternion to Identity + * \ingroup quat + */ +void +lib3ds_quat_identity(Lib3dsQuat c) +{ + c[0]=c[1]=c[2]=0.0f; + c[3]=1.0f; +} + + +/*! + * Copy a quaternion. + * \ingroup quat + */ +void +lib3ds_quat_copy(Lib3dsQuat dest, Lib3dsQuat src) +{ + int i; + for (i=0; i<4; ++i) { + dest[i]=src[i]; + } +} + + +/*! + * Compute a quaternion from axis and angle. + * + * \param c Computed quaternion + * \param axis Rotation axis + * \param angle Angle of rotation, radians. + * + * \ingroup quat + */ +void +lib3ds_quat_axis_angle(Lib3dsQuat c, Lib3dsVector axis, Lib3dsFloat angle) +{ + Lib3dsDouble omega,s; + Lib3dsDouble l; + + l=sqrt(axis[0]*axis[0] + axis[1]*axis[1] + axis[2]*axis[2]); + if (l<LIB3DS_EPSILON) { + c[0]=c[1]=c[2]=0.0f; + c[3]=1.0f; + } + else { + omega=-0.5*angle; + s=sin(omega)/l; + c[0]=(Lib3dsFloat)s*axis[0]; + c[1]=(Lib3dsFloat)s*axis[1]; + c[2]=(Lib3dsFloat)s*axis[2]; + c[3]=(Lib3dsFloat)cos(omega); + } +} + + +/*! + * Negate a quaternion + * + * \ingroup quat + */ +void +lib3ds_quat_neg(Lib3dsQuat c) +{ + int i; + for (i=0; i<4; ++i) { + c[i]=-c[i]; + } +} + + +/*! + * Compute the absolute value of a quaternion + * + * \ingroup quat + */ +void +lib3ds_quat_abs(Lib3dsQuat c) +{ + int i; + for (i=0; i<4; ++i) { + c[i]=(Lib3dsFloat)fabs(c[i]); + } +} + + +/*! + * Compute the conjugate of a quaternion + * + * \ingroup quat + */ +void +lib3ds_quat_cnj(Lib3dsQuat c) +{ + int i; + for (i=0; i<3; ++i) { + c[i]=-c[i]; + } +} + + +/*! + * Multiply two quaternions. + * + * \param c Result + * \param a,b Inputs + * \ingroup quat + */ +void +lib3ds_quat_mul(Lib3dsQuat c, Lib3dsQuat a, Lib3dsQuat b) +{ + c[0]=a[3]*b[0] + a[0]*b[3] + a[1]*b[2] - a[2]*b[1]; + c[1]=a[3]*b[1] + a[1]*b[3] + a[2]*b[0] - a[0]*b[2]; + c[2]=a[3]*b[2] + a[2]*b[3] + a[0]*b[1] - a[1]*b[0]; + c[3]=a[3]*b[3] - a[0]*b[0] - a[1]*b[1] - a[2]*b[2]; +} + + +/*! + * Multiply a quaternion by a scalar. + * + * \ingroup quat + */ +void +lib3ds_quat_scalar(Lib3dsQuat c, Lib3dsFloat k) +{ + int i; + for (i=0; i<4; ++i) { + c[i]*=k; + } +} + + +/*! + * Normalize a quaternion. + * + * \ingroup quat + */ +void +lib3ds_quat_normalize(Lib3dsQuat c) +{ + Lib3dsDouble l,m; + + l=sqrt(c[0]*c[0] + c[1]*c[1] + c[2]*c[2] + c[3]*c[3]); + if (fabs(l)<LIB3DS_EPSILON) { + c[0]=c[1]=c[2]=0.0f; + c[3]=1.0f; + } + else { + int i; + m=1.0f/l; + for (i=0; i<4; ++i) { + c[i]=(Lib3dsFloat)(c[i]*m); + } + } +} + + +/*! + * Compute the inverse of a quaternion. + * + * \ingroup quat + */ +void +lib3ds_quat_inv(Lib3dsQuat c) +{ + Lib3dsDouble l,m; + + l=sqrt(c[0]*c[0] + c[1]*c[1] + c[2]*c[2] + c[3]*c[3]); + if (fabs(l)<LIB3DS_EPSILON) { + c[0]=c[1]=c[2]=0.0f; + c[3]=1.0f; + } + else { + m=1.0f/l; + c[0]=(Lib3dsFloat)(-c[0]*m); + c[1]=(Lib3dsFloat)(-c[1]*m); + c[2]=(Lib3dsFloat)(-c[2]*m); + c[3]=(Lib3dsFloat)(c[3]*m); + } +} + + +/*! + * Compute the dot-product of a quaternion. + * + * \ingroup quat + */ +Lib3dsFloat +lib3ds_quat_dot(Lib3dsQuat a, Lib3dsQuat b) +{ + return(a[0]*b[0] + a[1]*b[1] + a[2]*b[2] + a[3]*b[3]); +} + + +/*! + * \ingroup quat + */ +Lib3dsFloat +lib3ds_quat_squared(Lib3dsQuat c) +{ + return(c[0]*c[0] + c[1]*c[1] + c[2]*c[2] + c[3]*c[3]); +} + + +/*! + * \ingroup quat + */ +Lib3dsFloat +lib3ds_quat_length(Lib3dsQuat c) +{ + return((Lib3dsFloat)sqrt(c[0]*c[0] + c[1]*c[1] + c[2]*c[2] + c[3]*c[3])); +} + + +/*! + * \ingroup quat + */ +void +lib3ds_quat_ln(Lib3dsQuat c) +{ + Lib3dsDouble om,s,t; + + s=sqrt(c[0]*c[0] + c[1]*c[1] + c[2]*c[2]); + om=atan2(s,c[3]); + if (fabs(s)<LIB3DS_EPSILON) { + t=0.0f; + } + else { + t=om/s; + } + { + int i; + for (i=0; i<3; ++i) { + c[i]=(Lib3dsFloat)(c[i]*t); + } + c[3]=0.0f; + } +} + + +/*! + * \ingroup quat + */ +void +lib3ds_quat_ln_dif(Lib3dsQuat c, Lib3dsQuat a, Lib3dsQuat b) +{ + Lib3dsQuat invp; + + lib3ds_quat_copy(invp, a); + lib3ds_quat_inv(invp); + lib3ds_quat_mul(c, invp, b); + lib3ds_quat_ln(c); +} + + +/*! + * \ingroup quat + */ +void +lib3ds_quat_exp(Lib3dsQuat c) +{ + Lib3dsDouble om,sinom; + + om=sqrt(c[0]*c[0] + c[1]*c[1] + c[2]*c[2]); + if (fabs(om)<LIB3DS_EPSILON) { + sinom=1.0f; + } + else { + sinom=sin(om)/om; + } + { + int i; + for (i=0; i<3; ++i) { + c[i]=(Lib3dsFloat)(c[i]*sinom); + } + c[3]=(Lib3dsFloat)cos(om); + } +} + + +/*! + * \ingroup quat + */ +void +lib3ds_quat_slerp(Lib3dsQuat c, Lib3dsQuat a, Lib3dsQuat b, Lib3dsFloat t) +{ + Lib3dsDouble l; + Lib3dsDouble om,sinom; + Lib3dsDouble sp,sq; + Lib3dsQuat q; + + l=a[0]*b[0] + a[1]*b[1] + a[2]*b[2] + a[3]*b[3]; + if ((1.0+l)>LIB3DS_EPSILON) { + if (fabs(l)>1.0f) l/=fabs(l); + om=acos(l); + sinom=sin(om); + if (fabs(sinom)>LIB3DS_EPSILON) { + sp=sin((1.0f-t)*om)/sinom; + sq=sin(t*om)/sinom; + } + else { + sp=1.0f-t; + sq=t; + } + c[0]=(Lib3dsFloat)(sp*a[0] + sq*b[0]); + c[1]=(Lib3dsFloat)(sp*a[1] + sq*b[1]); + c[2]=(Lib3dsFloat)(sp*a[2] + sq*b[2]); + c[3]=(Lib3dsFloat)(sp*a[3] + sq*b[3]); + } + else { + q[0]=-a[1]; + q[1]=a[0]; + q[2]=-a[3]; + q[3]=a[2]; + sp=sin((1.0-t)*LIB3DS_HALFPI); + sq=sin(t*LIB3DS_HALFPI); + c[0]=(Lib3dsFloat)(sp*a[0] + sq*q[0]); + c[1]=(Lib3dsFloat)(sp*a[1] + sq*q[1]); + c[2]=(Lib3dsFloat)(sp*a[2] + sq*q[2]); + c[3]=(Lib3dsFloat)(sp*a[3] + sq*q[3]); + } +} + + +/*! + * \ingroup quat + */ +void +lib3ds_quat_squad(Lib3dsQuat c, Lib3dsQuat a, Lib3dsQuat p, Lib3dsQuat q, + Lib3dsQuat b, Lib3dsFloat t) +{ + Lib3dsQuat ab; + Lib3dsQuat pq; + + lib3ds_quat_slerp(ab,a,b,t); + lib3ds_quat_slerp(pq,p,q,t); + lib3ds_quat_slerp(c,ab,pq,2*t*(1-t)); +} + + +/*! + * \ingroup quat + */ +void +lib3ds_quat_tangent(Lib3dsQuat c, Lib3dsQuat p, Lib3dsQuat q, Lib3dsQuat n) +{ + Lib3dsQuat dn,dp,x; + int i; + + lib3ds_quat_ln_dif(dn, q, n); + lib3ds_quat_ln_dif(dp, q, p); + + for (i=0; i<4; i++) { + x[i]=-1.0f/4.0f*(dn[i]+dp[i]); + } + lib3ds_quat_exp(x); + lib3ds_quat_mul(c,q,x); +} + + +/*! + * \ingroup quat + */ +void +lib3ds_quat_dump(Lib3dsQuat q) +{ + printf("%f %f %f %f\n", q[0], q[1], q[2], q[3]); +} + diff --git a/3rdparty/lib3ds/quat.h b/3rdparty/lib3ds/quat.h new file mode 100644 index 000000000..28912829d --- /dev/null +++ b/3rdparty/lib3ds/quat.h @@ -0,0 +1,61 @@ +/* -*- c -*- */ +#ifndef INCLUDED_LIB3DS_QUAT_H +#define INCLUDED_LIB3DS_QUAT_H +/* + * The 3D Studio File Format Library + * Copyright (C) 1996-2007 by Jan Eric Kyprianidis <www.kyprianidis.com> + * 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: quat.h,v 1.7 2007/06/14 09:59:10 jeh Exp $ + */ + +#ifndef INCLUDED_LIB3DS_TYPES_H +#include <lib3ds/types.h> +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +extern LIB3DSAPI void lib3ds_quat_zero(Lib3dsQuat c); +extern LIB3DSAPI void lib3ds_quat_identity(Lib3dsQuat c); +extern LIB3DSAPI void lib3ds_quat_copy(Lib3dsQuat dest, Lib3dsQuat src); +extern LIB3DSAPI void lib3ds_quat_axis_angle(Lib3dsQuat c, Lib3dsVector axis, Lib3dsFloat angle); +extern LIB3DSAPI void lib3ds_quat_neg(Lib3dsQuat c); +extern LIB3DSAPI void lib3ds_quat_abs(Lib3dsQuat c); +extern LIB3DSAPI void lib3ds_quat_cnj(Lib3dsQuat c); +extern LIB3DSAPI void lib3ds_quat_mul(Lib3dsQuat c, Lib3dsQuat a, Lib3dsQuat b); +extern LIB3DSAPI void lib3ds_quat_scalar(Lib3dsQuat c, Lib3dsFloat k); +extern LIB3DSAPI void lib3ds_quat_normalize(Lib3dsQuat c); +extern LIB3DSAPI void lib3ds_quat_inv(Lib3dsQuat c); +extern LIB3DSAPI Lib3dsFloat lib3ds_quat_dot(Lib3dsQuat a, Lib3dsQuat b); +extern LIB3DSAPI Lib3dsFloat lib3ds_quat_squared(Lib3dsQuat c); +extern LIB3DSAPI Lib3dsFloat lib3ds_quat_length(Lib3dsQuat c); +extern LIB3DSAPI void lib3ds_quat_ln(Lib3dsQuat c); +extern LIB3DSAPI void lib3ds_quat_ln_dif(Lib3dsQuat c, Lib3dsQuat a, Lib3dsQuat b); +extern LIB3DSAPI void lib3ds_quat_exp(Lib3dsQuat c); +extern LIB3DSAPI void lib3ds_quat_slerp(Lib3dsQuat c, Lib3dsQuat a, Lib3dsQuat b, Lib3dsFloat t); +extern LIB3DSAPI void lib3ds_quat_squad(Lib3dsQuat c, Lib3dsQuat a, Lib3dsQuat p, Lib3dsQuat q, + Lib3dsQuat b, Lib3dsFloat t); +extern LIB3DSAPI void lib3ds_quat_tangent(Lib3dsQuat c, Lib3dsQuat p, Lib3dsQuat q, Lib3dsQuat n); +extern LIB3DSAPI void lib3ds_quat_dump(Lib3dsQuat q); + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/3rdparty/lib3ds/shadow.c b/3rdparty/lib3ds/shadow.c new file mode 100644 index 000000000..601dd3786 --- /dev/null +++ b/3rdparty/lib3ds/shadow.c @@ -0,0 +1,149 @@ +/* + * The 3D Studio File Format Library + * Copyright (C) 1996-2007 by Jan Eric Kyprianidis <www.kyprianidis.com> + * 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: shadow.c,v 1.11 2007/06/20 17:04:09 jeh Exp $ + */ +#include <lib3ds/shadow.h> +#include <lib3ds/chunk.h> +#include <lib3ds/io.h> +#include <math.h> + + +/*! + * \defgroup shadow Shadow Map Settings + */ + + +/*! + * \ingroup shadow + */ +Lib3dsBool +lib3ds_shadow_read(Lib3dsShadow *shadow, Lib3dsIo *io) +{ + Lib3dsChunk c; + + if (!lib3ds_chunk_read(&c, io)) { + return(LIB3DS_FALSE); + } + + switch (c.chunk) { + case LIB3DS_SHADOW_MAP_SIZE: + { + shadow->map_size=lib3ds_io_read_intw(io); + } + break; + case LIB3DS_LO_SHADOW_BIAS: + { + shadow->lo_bias=lib3ds_io_read_float(io); + } + break; + case LIB3DS_HI_SHADOW_BIAS: + { + shadow->hi_bias=lib3ds_io_read_float(io); + } + break; + case LIB3DS_SHADOW_SAMPLES: + { + shadow->samples=lib3ds_io_read_intw(io); + } + break; + case LIB3DS_SHADOW_RANGE: + { + shadow->range=lib3ds_io_read_intd(io); + } + break; + case LIB3DS_SHADOW_FILTER: + { + shadow->filter=lib3ds_io_read_float(io); + } + break; + case LIB3DS_RAY_BIAS: + { + shadow->ray_bias=lib3ds_io_read_float(io); + } + break; + } + + return(LIB3DS_TRUE); +} + + +/*! + * \ingroup shadow + */ +Lib3dsBool +lib3ds_shadow_write(Lib3dsShadow *shadow, Lib3dsIo *io) +{ + if (fabs(shadow->lo_bias)>LIB3DS_EPSILON) { /*---- LIB3DS_LO_SHADOW_BIAS ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_LO_SHADOW_BIAS; + c.size=10; + lib3ds_chunk_write(&c,io); + lib3ds_io_write_float(io, shadow->lo_bias); + } + + if (fabs(shadow->hi_bias)>LIB3DS_EPSILON) { /*---- LIB3DS_HI_SHADOW_BIAS ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_HI_SHADOW_BIAS; + c.size=10; + lib3ds_chunk_write(&c,io); + lib3ds_io_write_float(io, shadow->hi_bias); + } + + if (shadow->map_size) { /*---- LIB3DS_SHADOW_MAP_SIZE ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_SHADOW_MAP_SIZE; + c.size=8; + lib3ds_chunk_write(&c,io); + lib3ds_io_write_intw(io, shadow->map_size); + } + + if (shadow->samples) { /*---- LIB3DS_SHADOW_SAMPLES ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_SHADOW_SAMPLES; + c.size=8; + lib3ds_chunk_write(&c,io); + lib3ds_io_write_intw(io, shadow->samples); + } + + if (shadow->range) { /*---- LIB3DS_SHADOW_RANGE ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_SHADOW_RANGE; + c.size=10; + lib3ds_chunk_write(&c,io); + lib3ds_io_write_intd(io, shadow->range); + } + + if (fabs(shadow->filter)>LIB3DS_EPSILON) { /*---- LIB3DS_SHADOW_FILTER ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_SHADOW_FILTER; + c.size=10; + lib3ds_chunk_write(&c,io); + lib3ds_io_write_float(io, shadow->filter); + } + if (fabs(shadow->ray_bias)>LIB3DS_EPSILON) { /*---- LIB3DS_RAY_BIAS ----*/ + Lib3dsChunk c; + c.chunk=LIB3DS_RAY_BIAS; + c.size=10; + lib3ds_chunk_write(&c,io); + lib3ds_io_write_float(io, shadow->ray_bias); + } + return(LIB3DS_TRUE); +} + diff --git a/3rdparty/lib3ds/shadow.h b/3rdparty/lib3ds/shadow.h new file mode 100644 index 000000000..cc31ba956 --- /dev/null +++ b/3rdparty/lib3ds/shadow.h @@ -0,0 +1,59 @@ +/* -*- c -*- */ +#ifndef INCLUDED_LIB3DS_SHADOW_H +#define INCLUDED_LIB3DS_SHADOW_H +/* + * The 3D Studio File Format Library + * Copyright (C) 1996-2007 by Jan Eric Kyprianidis <www.kyprianidis.com> + * 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: shadow.h,v 1.11 2007/06/20 17:04:09 jeh Exp $ + */ + +#ifndef INCLUDED_LIB3DS_TYPES_H +#include <lib3ds/types.h> +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Shadow map settings + * \ingroup shadow + */ +struct Lib3dsShadow { + Lib3dsIntw map_size; + Lib3dsFloat lo_bias; + Lib3dsFloat hi_bias; + Lib3dsIntw samples; + Lib3dsIntd range; + Lib3dsFloat filter; + Lib3dsFloat ray_bias; +}; + +extern LIB3DSAPI Lib3dsBool lib3ds_shadow_read(Lib3dsShadow *shadow, Lib3dsIo *io); +extern LIB3DSAPI Lib3dsBool lib3ds_shadow_write(Lib3dsShadow *shadow, Lib3dsIo *io); + +#ifdef __cplusplus +} +#endif +#endif + + + + + diff --git a/3rdparty/lib3ds/tcb.c b/3rdparty/lib3ds/tcb.c new file mode 100644 index 000000000..b1a0cac2b --- /dev/null +++ b/3rdparty/lib3ds/tcb.c @@ -0,0 +1,136 @@ +/* + * The 3D Studio File Format Library + * Copyright (C) 1996-2007 by Jan Eric Kyprianidis <www.kyprianidis.com> + * 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: tcb.c,v 1.11 2007/06/15 09:33:19 jeh Exp $ + */ +#include <lib3ds/tcb.h> +#include <lib3ds/io.h> +#include <math.h> + + +/*! + * \defgroup tcb Tension/Continuity/Bias Splines + */ + + +/*! + * \ingroup tcb + */ +void +lib3ds_tcb(Lib3dsTcb *p, Lib3dsTcb *pc, Lib3dsTcb *c, Lib3dsTcb *nc, Lib3dsTcb *n, + Lib3dsFloat *ksm, Lib3dsFloat *ksp, Lib3dsFloat *kdm, Lib3dsFloat *kdp) +{ + Lib3dsFloat tm,cm,cp,bm,bp,tmcm,tmcp,cc; + Lib3dsFloat dt,fp,fn; + + if (!pc) { + pc=c; + } + if (!nc) { + nc=c; + } + + fp=fn=1.0f; + if (p&&n) { + dt=0.5f*(Lib3dsFloat)(pc->frame-p->frame+n->frame-nc->frame); + fp=((Lib3dsFloat)(pc->frame-p->frame))/dt; + fn=((Lib3dsFloat)(n->frame-nc->frame))/dt; + cc=(Lib3dsFloat)fabs(c->cont); + fp=fp+cc-cc*fp; + fn=fn+cc-cc*fn; + } + + cm=1.0f-c->cont; + tm=0.5f*(1.0f-c->tens); + cp=2.0f-cm; + bm=1.0f-c->bias; + bp=2.0f-bm; + tmcm=tm*cm; + tmcp=tm*cp; + *ksm=tmcm*bp*fp; + *ksp=tmcp*bm*fp; + *kdm=tmcp*bp*fn; + *kdp=tmcm*bm*fn; +} + + +/*! + * \ingroup tcb + */ +Lib3dsBool +lib3ds_tcb_read(Lib3dsTcb *tcb, Lib3dsIo *io) +{ + Lib3dsWord flags; + + tcb->frame=lib3ds_io_read_intd(io); + tcb->flags=flags=lib3ds_io_read_word(io); + if (flags&LIB3DS_USE_TENSION) { + tcb->tens=lib3ds_io_read_float(io); + } + if (flags&LIB3DS_USE_CONTINUITY) { + tcb->cont=lib3ds_io_read_float(io); + } + if (flags&LIB3DS_USE_BIAS) { + tcb->bias=lib3ds_io_read_float(io); + } + if (flags&LIB3DS_USE_EASE_TO) { + tcb->ease_to=lib3ds_io_read_float(io); + } + if (flags&LIB3DS_USE_EASE_FROM) { + tcb->ease_from=lib3ds_io_read_float(io); + } + if (lib3ds_io_error(io)) { + return(LIB3DS_FALSE); + } + return(LIB3DS_TRUE); +} + + +/*! + * \ingroup tcb + */ +Lib3dsBool +lib3ds_tcb_write(Lib3dsTcb *tcb, Lib3dsIo *io) +{ + lib3ds_io_write_intd(io, tcb->frame); + lib3ds_io_write_word(io, tcb->flags); + if (tcb->flags&LIB3DS_USE_TENSION) { + lib3ds_io_write_float(io, tcb->tens); + } + if (tcb->flags&LIB3DS_USE_CONTINUITY) { + lib3ds_io_write_float(io, tcb->cont); + } + if (tcb->flags&LIB3DS_USE_BIAS) { + lib3ds_io_write_float(io, tcb->bias); + } + if (tcb->flags&LIB3DS_USE_EASE_TO) { + lib3ds_io_write_float(io, tcb->ease_to); + } + if (tcb->flags&LIB3DS_USE_EASE_FROM) { + lib3ds_io_write_float(io, tcb->ease_from); + } + if (lib3ds_io_error(io)) { + return(LIB3DS_FALSE); + } + return(LIB3DS_TRUE); +} + + + + diff --git a/3rdparty/lib3ds/tcb.h b/3rdparty/lib3ds/tcb.h new file mode 100644 index 000000000..3d8e3f63a --- /dev/null +++ b/3rdparty/lib3ds/tcb.h @@ -0,0 +1,62 @@ +/* -*- c -*- */ +#ifndef INCLUDED_LIB3DS_TCB_H +#define INCLUDED_LIB3DS_TCB_H +/* + * The 3D Studio File Format Library + * Copyright (C) 1996-2007 by Jan Eric Kyprianidis <www.kyprianidis.com> + * 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: tcb.h,v 1.11 2007/06/20 17:04:09 jeh Exp $ + */ + +#ifndef INCLUDED_LIB3DS_TYPES_H +#include <lib3ds/types.h> +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum Lib3dsTcbFlags{ + LIB3DS_USE_TENSION =0x0001, + LIB3DS_USE_CONTINUITY =0x0002, + LIB3DS_USE_BIAS =0x0004, + LIB3DS_USE_EASE_TO =0x0008, + LIB3DS_USE_EASE_FROM =0x0010 +} Lib3dsTcbFlags; + +typedef struct Lib3dsTcb { + Lib3dsIntd frame; + Lib3dsWord flags; + Lib3dsFloat tens; + Lib3dsFloat cont; + Lib3dsFloat bias; + Lib3dsFloat ease_to; + Lib3dsFloat ease_from; +} Lib3dsTcb; + +extern LIB3DSAPI void lib3ds_tcb(Lib3dsTcb *p, Lib3dsTcb *pc, Lib3dsTcb *c, + Lib3dsTcb *nc, Lib3dsTcb *n, Lib3dsFloat *ksm, Lib3dsFloat *ksp, + Lib3dsFloat *kdm, Lib3dsFloat *kdp); +extern LIB3DSAPI Lib3dsBool lib3ds_tcb_read(Lib3dsTcb *tcb, Lib3dsIo *io); +extern LIB3DSAPI Lib3dsBool lib3ds_tcb_write(Lib3dsTcb *tcb, Lib3dsIo *io); + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/3rdparty/lib3ds/tracks.c b/3rdparty/lib3ds/tracks.c new file mode 100644 index 000000000..cc24455a2 --- /dev/null +++ b/3rdparty/lib3ds/tracks.c @@ -0,0 +1,1556 @@ +/* + * The 3D Studio File Format Library + * Copyright (C) 1996-2007 by Jan Eric Kyprianidis <www.kyprianidis.com> + * 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: tracks.c,v 1.20 2007/06/15 09:33:19 jeh Exp $ + */ +#include <lib3ds/tracks.h> +#include <lib3ds/io.h> +#include <lib3ds/chunk.h> +#include <lib3ds/vector.h> +#include <lib3ds/quat.h> +#include <lib3ds/node.h> +#include <stdlib.h> +#include <string.h> +#include <math.h> + + +/*! + * \defgroup tracks Keyframing Tracks + */ + + +/*! + * \ingroup tracks + */ +Lib3dsBoolKey* +lib3ds_bool_key_new() +{ + Lib3dsBoolKey* k; + k=(Lib3dsBoolKey*)calloc(sizeof(Lib3dsBoolKey), 1); + return(k); +} + + +/*! + * \ingroup tracks + */ +void +lib3ds_bool_key_free(Lib3dsBoolKey *key) +{ + ASSERT(key); + free(key); +} + + +/*! + * \ingroup tracks + */ +void +lib3ds_bool_track_free_keys(Lib3dsBoolTrack *track) +{ + Lib3dsBoolKey *p,*q; + + ASSERT(track); + for (p=track->keyL; p; p=q) { + q=p->next; + lib3ds_bool_key_free(p); + } +} + + +/*! + * \ingroup tracks + */ +void +lib3ds_bool_track_insert(Lib3dsBoolTrack *track, Lib3dsBoolKey *key) +{ + ASSERT(track); + ASSERT(key); + ASSERT(!key->next); + + if (!track->keyL) { + track->keyL=key; + key->next=0; + } + else { + Lib3dsBoolKey *k,*p; + + for (p=0,k=track->keyL; k!=0; p=k, k=k->next) { + if (k->tcb.frame>key->tcb.frame) { + break; + } + } + if (!p) { + key->next=track->keyL; + track->keyL=key; + } + else { + key->next=k; + p->next=key; + } + + if (k && (key->tcb.frame==k->tcb.frame)) { + key->next=k->next; + lib3ds_bool_key_free(k); + } + } +} + + +/*! + * \ingroup tracks + */ +void +lib3ds_bool_track_remove(Lib3dsBoolTrack *track, Lib3dsIntd frame) +{ + Lib3dsBoolKey *k,*p; + + ASSERT(track); + if (!track->keyL) { + return; + } + for (p=0,k=track->keyL; k!=0; p=k, k=k->next) { + if (k->tcb.frame==frame) { + if (!p) { + track->keyL=track->keyL->next; + } + else { + p->next=k->next; + } + lib3ds_bool_key_free(k); + break; + } + } +} + + +/*! + * \ingroup tracks + */ +void +lib3ds_bool_track_eval(Lib3dsBoolTrack *track, Lib3dsBool *p, Lib3dsFloat t) +{ + Lib3dsBoolKey *k; + Lib3dsBool result; + + ASSERT(p); + if (!track->keyL) { + *p=LIB3DS_FALSE; + return; + } + if (!track->keyL->next) { + *p = LIB3DS_TRUE; + return; + } + + result=LIB3DS_FALSE; + k=track->keyL; + while ((t<(Lib3dsFloat)k->tcb.frame) && (t>=(Lib3dsFloat)k->next->tcb.frame)) { + if (result) { + result=LIB3DS_FALSE; + } + else { + result=LIB3DS_TRUE; + } + if (!k->next) { + if (track->flags&LIB3DS_REPEAT) { + t-=(Lib3dsFloat)k->tcb.frame; + k=track->keyL; + } + else { + break; + } + } + else { + k=k->next; + } + } + *p=result; +} + + +/*! + * \ingroup tracks + */ +Lib3dsBool +lib3ds_bool_track_read(Lib3dsBoolTrack *track, Lib3dsIo *io) +{ + int keys; + int i; + Lib3dsBoolKey *k; + + track->flags=lib3ds_io_read_word(io); + lib3ds_io_read_dword(io); + lib3ds_io_read_dword(io); + keys=lib3ds_io_read_intd(io); + + for (i=0; i<keys; ++i) { + k=lib3ds_bool_key_new(); + if (!lib3ds_tcb_read(&k->tcb, io)) { + return(LIB3DS_FALSE); + } + lib3ds_bool_track_insert(track, k); + } + + return(LIB3DS_TRUE); +} + + +/*! + * \ingroup tracks + */ +Lib3dsBool +lib3ds_bool_track_write(Lib3dsBoolTrack *track, Lib3dsIo *io) +{ + Lib3dsBoolKey *k; + Lib3dsDword num=0; + for (k=track->keyL; k; k=k->next) { + ++num; + } + lib3ds_io_write_word(io, (Lib3dsWord)track->flags); + lib3ds_io_write_dword(io, 0); + lib3ds_io_write_dword(io, 0); + lib3ds_io_write_dword(io, num); + + for (k=track->keyL; k; k=k->next) { + if (!lib3ds_tcb_write(&k->tcb,io)) { + return(LIB3DS_FALSE); + } + } + return(LIB3DS_TRUE); +} + + +/*! + * \ingroup tracks + */ +Lib3dsLin1Key* +lib3ds_lin1_key_new() +{ + Lib3dsLin1Key* k; + k=(Lib3dsLin1Key*)calloc(sizeof(Lib3dsLin1Key), 1); + return(k); +} + + +/*! + * \ingroup tracks + */ +void +lib3ds_lin1_key_free(Lib3dsLin1Key *key) +{ + ASSERT(key); + free(key); +} + + +/*! + * \ingroup tracks + */ +void +lib3ds_lin1_track_free_keys(Lib3dsLin1Track *track) +{ + Lib3dsLin1Key *p,*q; + + ASSERT(track); + for (p=track->keyL; p; p=q) { + q=p->next; + lib3ds_lin1_key_free(p); + } +} + + +/*! + * \ingroup tracks + */ +void +lib3ds_lin1_key_setup(Lib3dsLin1Key *p, Lib3dsLin1Key *cp, Lib3dsLin1Key *c, + Lib3dsLin1Key *cn, Lib3dsLin1Key *n) +{ + Lib3dsFloat np,nn; + Lib3dsFloat ksm,ksp,kdm,kdp; + + ASSERT(c); + if (!cp) { + cp=c; + } + if (!cn) { + cn=c; + } + if (!p && !n) { + c->ds=0; + c->dd=0; + return; + } + + if (n && p) { + lib3ds_tcb(&p->tcb, &cp->tcb, &c->tcb, &cn->tcb, &n->tcb, &ksm, &ksp, &kdm, &kdp); + np = c->value - p->value; + nn = n->value - c->value; + + c->ds=ksm*np + ksp*nn; + c->dd=kdm*np + kdp*nn; + } + else { + if (p) { + np = c->value - p->value; + c->ds = np; + c->dd = np; + } + if (n) { + nn = n->value - c->value; + c->ds = nn; + c->dd = nn; + } + } +} + + +/*! + * \ingroup tracks + */ +void +lib3ds_lin1_track_setup(Lib3dsLin1Track *track) +{ + Lib3dsLin1Key *pp,*pc,*pn,*pl; + + ASSERT(track); + pc=track->keyL; + if (!pc) { + return; + } + if (!pc->next) { + pc->ds=0; + pc->dd=0; + return; + } + + if (track->flags&LIB3DS_SMOOTH) { + for (pl=track->keyL; pl->next->next; pl=pl->next); + lib3ds_lin1_key_setup(pl, pl->next, pc, 0, pc->next); + } + else { + lib3ds_lin1_key_setup(0, 0, pc, 0, pc->next); + } + for (;;) { + pp=pc; + pc=pc->next; + pn=pc->next; + if (!pn) { + break; + } + lib3ds_lin1_key_setup(pp, 0, pc, 0, pn); + } + + if (track->flags&LIB3DS_SMOOTH) { + lib3ds_lin1_key_setup(pp, 0, pc, track->keyL, track->keyL->next); + } + else { + lib3ds_lin1_key_setup(pp, 0, pc, 0, 0); + } +} + + +/*! + * \ingroup tracks + */ +void +lib3ds_lin1_track_insert(Lib3dsLin1Track *track, Lib3dsLin1Key *key) +{ + ASSERT(track); + ASSERT(key); + ASSERT(!key->next); + + if (!track->keyL) { + track->keyL=key; + key->next=0; + } + else { + Lib3dsLin1Key *k,*p; + + for (p=0,k=track->keyL; k!=0; p=k, k=k->next) { + if (k->tcb.frame>key->tcb.frame) { + break; + } + } + if (!p) { + key->next=track->keyL; + track->keyL=key; + } + else { + key->next=k; + p->next=key; + } + + if (k && (key->tcb.frame==k->tcb.frame)) { + key->next=k->next; + lib3ds_lin1_key_free(k); + } + } +} + + +/*! + * \ingroup tracks + */ +void +lib3ds_lin1_track_remove(Lib3dsLin1Track *track, Lib3dsIntd frame) +{ + Lib3dsLin1Key *k,*p; + + ASSERT(track); + if (!track->keyL) { + return; + } + for (p=0,k=track->keyL; k!=0; p=k, k=k->next) { + if (k->tcb.frame==frame) { + if (!p) { + track->keyL=track->keyL->next; + } + else { + p->next=k->next; + } + lib3ds_lin1_key_free(k); + break; + } + } +} + + +static Lib3dsFloat +lib3ds_float_cubic(Lib3dsFloat a, Lib3dsFloat p, Lib3dsFloat q, Lib3dsFloat b, Lib3dsFloat t) +{ + Lib3dsDouble x,y,z,w; + + x=2*t*t*t - 3*t*t + 1; + y=-2*t*t*t + 3*t*t; + z=t*t*t - 2*t*t + t; + w=t*t*t - t*t; + return((Lib3dsFloat)(x*a + y*b + z*p + w*q)); +} + + +/*! + * \ingroup tracks + */ +void +lib3ds_lin1_track_eval(Lib3dsLin1Track *track, Lib3dsFloat *p, Lib3dsFloat t) +{ + Lib3dsLin1Key *k; + Lib3dsFloat nt; + Lib3dsFloat u; + + ASSERT(p); + if (!track->keyL) { + *p=0; + return; + } + if (!track->keyL->next || ((t<track->keyL->tcb.frame) && ((track->flags&LIB3DS_REPEAT) != 0))) { + *p = track->keyL->value; + return; + } + + for (k=track->keyL; k->next!=0; k=k->next) { + if ((t>=(Lib3dsFloat)k->tcb.frame) && (t<(Lib3dsFloat)k->next->tcb.frame)) { + break; + } + } + if (!k->next) { + if (track->flags&LIB3DS_REPEAT) { + nt=(Lib3dsFloat)fmod(t - track->keyL->tcb.frame, k->tcb.frame - track->keyL->tcb.frame) + track->keyL->tcb.frame; + for (k=track->keyL; k->next!=0; k=k->next) { + if ((nt>=(Lib3dsFloat)k->tcb.frame) && (nt<(Lib3dsFloat)k->next->tcb.frame)) { + break; + } + } + ASSERT(k->next); + } + else { + *p = k->value; + return; + } + } + else { + nt=t; + } + u=nt - (Lib3dsFloat)k->tcb.frame; + u/=(Lib3dsFloat)(k->next->tcb.frame - k->tcb.frame); + + *p = lib3ds_float_cubic( + k->value, + k->dd, + k->next->ds, + k->next->value, + u + ); +} + + +/*! + * \ingroup tracks + */ +Lib3dsBool +lib3ds_lin1_track_read(Lib3dsLin1Track *track, Lib3dsIo *io) +{ + int keys; + int i; + Lib3dsLin1Key *k; + + track->flags=lib3ds_io_read_word(io); + lib3ds_io_read_dword(io); + lib3ds_io_read_dword(io); + keys=lib3ds_io_read_intd(io); + + for (i=0; i<keys; ++i) { + k=lib3ds_lin1_key_new(); + if (!lib3ds_tcb_read(&k->tcb, io)) { + return(LIB3DS_FALSE); + } + k->value=lib3ds_io_read_float(io); + lib3ds_lin1_track_insert(track, k); + } + lib3ds_lin1_track_setup(track); + return(LIB3DS_TRUE); +} + + +/*! + * \ingroup tracks + */ +Lib3dsBool +lib3ds_lin1_track_write(Lib3dsLin1Track *track, Lib3dsIo *io) +{ + Lib3dsLin1Key *k; + Lib3dsDword num=0; + for (k=track->keyL; k; k=k->next) { + ++num; + } + lib3ds_io_write_word(io, (Lib3dsWord)track->flags); + lib3ds_io_write_dword(io, 0); + lib3ds_io_write_dword(io, 0); + lib3ds_io_write_dword(io, num); + + for (k=track->keyL; k; k=k->next) { + if (!lib3ds_tcb_write(&k->tcb,io)) { + return(LIB3DS_FALSE); + } + lib3ds_io_write_float(io, k->value); + } + return(LIB3DS_TRUE); +} + + +/*! + * Create and return one keyframe in a Lin3 track. All values are + * initialized to zero. + * + * \ingroup tracks + */ +Lib3dsLin3Key* +lib3ds_lin3_key_new() +{ + Lib3dsLin3Key* k; + k=(Lib3dsLin3Key*)calloc(sizeof(Lib3dsLin3Key), 1); + return(k); +} + + +/*! + * Free a Lin3 keyframe. + * + * \ingroup tracks + */ +void +lib3ds_lin3_key_free(Lib3dsLin3Key *key) +{ + ASSERT(key); + free(key); +} + + +/*! + * Free all keyframes in a Lin3 track. + * + * \ingroup tracks + */ +void +lib3ds_lin3_track_free_keys(Lib3dsLin3Track *track) +{ + Lib3dsLin3Key *p,*q; + + ASSERT(track); + for (p=track->keyL; p; p=q) { + q=p->next; + lib3ds_lin3_key_free(p); + } +} + + +/*! + * \ingroup tracks + */ +void +lib3ds_lin3_key_setup(Lib3dsLin3Key *p, Lib3dsLin3Key *cp, Lib3dsLin3Key *c, + Lib3dsLin3Key *cn, Lib3dsLin3Key *n) +{ + Lib3dsVector np,nn; + Lib3dsFloat ksm,ksp,kdm,kdp; + int i; + + ASSERT(c); + if (!cp) { + cp=c; + } + if (!cn) { + cn=c; + } + if (!p && !n) { + lib3ds_vector_zero(c->ds); + lib3ds_vector_zero(c->dd); + return; + } + + if (n && p) { + lib3ds_tcb(&p->tcb, &cp->tcb, &c->tcb, &cn->tcb, &n->tcb, &ksm, &ksp, &kdm, &kdp); + lib3ds_vector_sub(np, c->value, p->value); + lib3ds_vector_sub(nn, n->value, c->value); + + for (i=0; i<3; ++i) { + c->ds[i]=ksm*np[i] + ksp*nn[i]; + c->dd[i]=kdm*np[i] + kdp*nn[i]; + } + } + else { + if (p) { + lib3ds_vector_sub(np, c->value, p->value); + lib3ds_vector_copy(c->ds, np); + lib3ds_vector_copy(c->dd, np); + } + if (n) { + lib3ds_vector_sub(nn, n->value, c->value); + lib3ds_vector_copy(c->ds, nn); + lib3ds_vector_copy(c->dd, nn); + } + } +} + + +/*! + * \ingroup tracks + */ +void +lib3ds_lin3_track_setup(Lib3dsLin3Track *track) +{ + Lib3dsLin3Key *pp,*pc,*pn,*pl; + + ASSERT(track); + pc=track->keyL; + if (!pc) { + return; + } + if (!pc->next) { + lib3ds_vector_zero(pc->ds); + lib3ds_vector_zero(pc->dd); + return; + } + + if (track->flags&LIB3DS_SMOOTH) { + for (pl=track->keyL; pl->next->next; pl=pl->next); + lib3ds_lin3_key_setup(pl, pl->next, pc, 0, pc->next); + } + else { + lib3ds_lin3_key_setup(0, 0, pc, 0, pc->next); + } + for (;;) { + pp=pc; + pc=pc->next; + pn=pc->next; + if (!pn) { + break; + } + lib3ds_lin3_key_setup(pp, 0, pc, 0, pn); + } + + if (track->flags&LIB3DS_SMOOTH) { + lib3ds_lin3_key_setup(pp, 0, pc, track->keyL, track->keyL->next); + } + else { + lib3ds_lin3_key_setup(pp, 0, pc, 0, 0); + } +} + + +/*! + * \ingroup tracks + */ +void +lib3ds_lin3_track_insert(Lib3dsLin3Track *track, Lib3dsLin3Key *key) +{ + ASSERT(track); + ASSERT(key); + ASSERT(!key->next); + + if (!track->keyL) { + track->keyL=key; + key->next=0; + } + else { + Lib3dsLin3Key *k,*p; + + for (p=0,k=track->keyL; k!=0; p=k, k=k->next) { + if (k->tcb.frame>key->tcb.frame) { + break; + } + } + if (!p) { + key->next=track->keyL; + track->keyL=key; + } + else { + key->next=k; + p->next=key; + } + + if (k && (key->tcb.frame==k->tcb.frame)) { + key->next=k->next; + lib3ds_lin3_key_free(k); + } + } +} + + +/*! + * \ingroup tracks + */ +void +lib3ds_lin3_track_remove(Lib3dsLin3Track *track, Lib3dsIntd frame) +{ + Lib3dsLin3Key *k,*p; + + ASSERT(track); + if (!track->keyL) { + return; + } + for (p=0,k=track->keyL; k!=0; p=k, k=k->next) { + if (k->tcb.frame==frame) { + if (!p) { + track->keyL=track->keyL->next; + } + else { + p->next=k->next; + } + lib3ds_lin3_key_free(k); + break; + } + } +} + + +/*! + * \ingroup tracks + */ +void +lib3ds_lin3_track_eval(Lib3dsLin3Track *track, Lib3dsVector p, Lib3dsFloat t) +{ + Lib3dsLin3Key *k; + Lib3dsFloat nt; + Lib3dsFloat u; + + if (!track->keyL) { + lib3ds_vector_zero(p); + return; + } + if (!track->keyL->next || ((t<track->keyL->tcb.frame) && ((track->flags&LIB3DS_REPEAT) != 0))) { + lib3ds_vector_copy(p, track->keyL->value); + return; + } + + for (k=track->keyL; k->next!=0; k=k->next) { + if ((t>=(Lib3dsFloat)k->tcb.frame) && (t<(Lib3dsFloat)k->next->tcb.frame)) { + break; + } + } + if (!k->next) { + if (track->flags&LIB3DS_REPEAT) { + nt=(Lib3dsFloat)fmod(t - track->keyL->tcb.frame, k->tcb.frame - track->keyL->tcb.frame) + track->keyL->tcb.frame; + for (k=track->keyL; k->next!=0; k=k->next) { + if ((nt>=(Lib3dsFloat)k->tcb.frame) && (nt<(Lib3dsFloat)k->next->tcb.frame)) { + break; + } + } + ASSERT(k->next); + } + else { + lib3ds_vector_copy(p, k->value); + return; + } + } + else { + nt=t; + } + u=nt - (Lib3dsFloat)k->tcb.frame; + u/=(Lib3dsFloat)(k->next->tcb.frame - k->tcb.frame); + + lib3ds_vector_cubic( + p, + k->value, + k->dd, + k->next->ds, + k->next->value, + u + ); +} + + +/*! + * \ingroup tracks + */ +Lib3dsBool +lib3ds_lin3_track_read(Lib3dsLin3Track *track, Lib3dsIo *io) +{ + int keys; + int i,j; + Lib3dsLin3Key *k; + + track->flags=lib3ds_io_read_word(io); + lib3ds_io_read_dword(io); + lib3ds_io_read_dword(io); + keys=lib3ds_io_read_intd(io); + + for (i=0; i<keys; ++i) { + k=lib3ds_lin3_key_new(); + if (!lib3ds_tcb_read(&k->tcb, io)) { + return(LIB3DS_FALSE); + } + for (j=0; j<3; ++j) { + k->value[j]=lib3ds_io_read_float(io); + } + lib3ds_lin3_track_insert(track, k); + } + lib3ds_lin3_track_setup(track); + return(LIB3DS_TRUE); +} + + +/*! + * \ingroup tracks + */ +Lib3dsBool +lib3ds_lin3_track_write(Lib3dsLin3Track *track, Lib3dsIo *io) +{ + Lib3dsLin3Key *k; + Lib3dsDword num=0; + for (k=track->keyL; k; k=k->next) { + ++num; + } + lib3ds_io_write_word(io, (Lib3dsWord)track->flags); + lib3ds_io_write_dword(io, 0); + lib3ds_io_write_dword(io, 0); + lib3ds_io_write_dword(io, num); + + for (k=track->keyL; k; k=k->next) { + if (!lib3ds_tcb_write(&k->tcb,io)) { + return(LIB3DS_FALSE); + } + lib3ds_io_write_vector(io, k->value); + } + return(LIB3DS_TRUE); +} + + +/*! + * \ingroup tracks + */ +Lib3dsQuatKey* +lib3ds_quat_key_new() +{ + Lib3dsQuatKey* k; + k=(Lib3dsQuatKey*)calloc(sizeof(Lib3dsQuatKey), 1); + return(k); +} + + +/*! + * \ingroup tracks + */ +void +lib3ds_quat_key_free(Lib3dsQuatKey *key) +{ + ASSERT(key); + free(key); +} + + +/*! + * \ingroup tracks + */ +void +lib3ds_quat_track_free_keys(Lib3dsQuatTrack *track) +{ + Lib3dsQuatKey *p,*q; + + ASSERT(track); + for (p=track->keyL; p; p=q) { + q=p->next; + lib3ds_quat_key_free(p); + } +} + + +/*! + * \ingroup tracks + */ +void +lib3ds_quat_key_setup(Lib3dsQuatKey *p, Lib3dsQuatKey *cp, Lib3dsQuatKey *c, + Lib3dsQuatKey *cn, Lib3dsQuatKey *n) +{ + Lib3dsFloat ksm,ksp,kdm,kdp; + Lib3dsQuat q,qp,qn,qa,qb; + int i; + + ASSERT(c); + if (!cp) { + cp=c; + } + if (!cn) { + cn=c; + } + if (!p || !n) { + lib3ds_quat_copy(c->ds, c->q); + lib3ds_quat_copy(c->dd, c->q); + return; + } + + if (p) { + if (p->angle>LIB3DS_TWOPI-LIB3DS_EPSILON) { + lib3ds_quat_axis_angle(qp, p->axis, 0.0f); + lib3ds_quat_ln(qp); + } + else { + lib3ds_quat_copy(q, p->q); + if (lib3ds_quat_dot(q,c->q)<0) lib3ds_quat_neg(q); + + lib3ds_quat_ln_dif(qp, q, c->q); + } + } + if (n) { + if (n->angle>LIB3DS_TWOPI-LIB3DS_EPSILON) { + lib3ds_quat_axis_angle(qn, n->axis, 0.0f); + lib3ds_quat_ln(qn); + } + else { + lib3ds_quat_copy(q, n->q); + if (lib3ds_quat_dot(q,c->q)<0) lib3ds_quat_neg(q); + lib3ds_quat_ln_dif(qn, c->q, q); + } + } + + if (n && p) { + lib3ds_tcb(&p->tcb, &cp->tcb, &c->tcb, &cn->tcb, &n->tcb, &ksm, &ksp, &kdm, &kdp); + for (i=0; i<4; i++) { + qa[i]=0.5f*(kdm*qp[i]+(kdp-1.f)*qn[i]); + qb[i]=0.5f*((1.f-ksm)*qp[i]-ksp*qn[i]); + } + lib3ds_quat_exp(qa); + lib3ds_quat_exp(qb); + + lib3ds_quat_mul(c->ds, c->q, qb); + lib3ds_quat_mul(c->dd, c->q, qa); + } + else { + if (p) { + lib3ds_quat_exp(qp); + lib3ds_quat_mul(c->ds, c->q, qp); + lib3ds_quat_mul(c->dd, c->q, qp); + } + if (n) { + lib3ds_quat_exp(qn); + lib3ds_quat_mul(c->ds, c->q, qn); + lib3ds_quat_mul(c->dd, c->q, qn); + } + } +} + + +/*! + * \ingroup tracks + */ +void +lib3ds_quat_track_setup(Lib3dsQuatTrack *track) +{ + Lib3dsQuatKey *pp,*pc,*pn,*pl; + Lib3dsQuat q; + + ASSERT(track); + for (pp=0,pc=track->keyL; pc; pp=pc,pc=pc->next) { + lib3ds_quat_axis_angle(q, pc->axis, pc->angle); + if (pp) { + lib3ds_quat_mul(pc->q, q, pp->q); + } + else { + lib3ds_quat_copy(pc->q, q); + } + } + + pc=track->keyL; + if (!pc) { + return; + } + if (!pc->next) { + lib3ds_quat_copy(pc->ds, pc->q); + lib3ds_quat_copy(pc->dd, pc->q); + return; + } + + if (track->flags&LIB3DS_SMOOTH) { + for (pl=track->keyL; pl->next->next; pl=pl->next); + lib3ds_quat_key_setup(pl, pl->next, pc, 0, pc->next); + } + else { + lib3ds_quat_key_setup(0, 0, pc, 0, pc->next); + } + for (;;) { + pp=pc; + pc=pc->next; + pn=pc->next; + if (!pn) { + break; + } + lib3ds_quat_key_setup(pp, 0, pc, 0, pn); + } + + if (track->flags&LIB3DS_SMOOTH) { + lib3ds_quat_key_setup(pp, 0, pc, track->keyL, track->keyL->next); + } + else { + lib3ds_quat_key_setup(pp, 0, pc, 0, 0); + } +} + + +/*! + * \ingroup tracks + */ +void +lib3ds_quat_track_insert(Lib3dsQuatTrack *track, Lib3dsQuatKey *key) +{ + ASSERT(track); + ASSERT(key); + ASSERT(!key->next); + + if (!track->keyL) { + track->keyL=key; + key->next=0; + } + else { + Lib3dsQuatKey *k,*p; + + for (p=0,k=track->keyL; k!=0; p=k, k=k->next) { + if (k->tcb.frame>key->tcb.frame) { + break; + } + } + if (!p) { + key->next=track->keyL; + track->keyL=key; + } + else { + key->next=k; + p->next=key; + } + + if (k && (key->tcb.frame==k->tcb.frame)) { + key->next=k->next; + lib3ds_quat_key_free(k); + } + } +} + + +/*! + * \ingroup tracks + */ +void +lib3ds_quat_track_remove(Lib3dsQuatTrack *track, Lib3dsIntd frame) +{ + Lib3dsQuatKey *k,*p; + + ASSERT(track); + if (!track->keyL) { + return; + } + for (p=0,k=track->keyL; k!=0; p=k, k=k->next) { + if (k->tcb.frame==frame) { + if (!p) { + track->keyL=track->keyL->next; + } + else { + p->next=k->next; + } + lib3ds_quat_key_free(k); + break; + } + } +} + + +/*! + * \ingroup tracks + */ +void +lib3ds_quat_track_eval(Lib3dsQuatTrack *track, Lib3dsQuat q, Lib3dsFloat t) +{ + Lib3dsQuatKey *k; + Lib3dsFloat nt; + Lib3dsFloat u; + + if (!track->keyL) { + lib3ds_quat_identity(q); + return; + } + if (!track->keyL->next || ((t<track->keyL->tcb.frame) && ((track->flags&LIB3DS_REPEAT) != 0))) { + lib3ds_quat_copy(q, track->keyL->q); + return; + } + + for (k=track->keyL; k->next!=0; k=k->next) { + if ((t>=k->tcb.frame) && (t<k->next->tcb.frame)) { + break; + } + } + if (!k->next) { + if (track->flags&LIB3DS_REPEAT) { + nt=(Lib3dsFloat)fmod(t - track->keyL->tcb.frame, k->tcb.frame - track->keyL->tcb.frame) + track->keyL->tcb.frame; + for (k=track->keyL; k->next!=0; k=k->next) { + if ((nt>=k->tcb.frame) && (nt<k->next->tcb.frame)) { + break; + } + } + ASSERT(k->next); + } + else { + lib3ds_quat_copy(q, k->q); + return; + } + } + else { + nt=t; + } + u=nt - k->tcb.frame; + u/=(k->next->tcb.frame - k->tcb.frame); + + lib3ds_quat_squad( + q, + k->q, + k->dd, + k->next->ds, + k->next->q, + u + ); +} + + +/*! + * \ingroup tracks + */ +Lib3dsBool +lib3ds_quat_track_read(Lib3dsQuatTrack *track, Lib3dsIo *io) +{ + int keys; + int i,j; + Lib3dsQuatKey *p,*k; + + track->flags=lib3ds_io_read_word(io); + lib3ds_io_read_dword(io); + lib3ds_io_read_dword(io); + keys=lib3ds_io_read_intd(io); + + for (p=0,i=0; i<keys; p=k,++i) { + k=lib3ds_quat_key_new(); + if (!lib3ds_tcb_read(&k->tcb, io)) { + return(LIB3DS_FALSE); + } + k->angle=lib3ds_io_read_float(io); + for (j=0; j<3; ++j) { + k->axis[j]=lib3ds_io_read_float(io); + } + lib3ds_quat_track_insert(track, k); + } + lib3ds_quat_track_setup(track); + return(LIB3DS_TRUE); +} + + +/*! + * \ingroup tracks + */ +Lib3dsBool +lib3ds_quat_track_write(Lib3dsQuatTrack *track, Lib3dsIo *io) +{ + Lib3dsQuatKey *k; + Lib3dsDword num=0; + for (k=track->keyL; k; k=k->next) { + ++num; + } + lib3ds_io_write_word(io, (Lib3dsWord)track->flags); + lib3ds_io_write_dword(io, 0); + lib3ds_io_write_dword(io, 0); + lib3ds_io_write_dword(io, num); + + for (k=track->keyL; k; k=k->next) { + if (!lib3ds_tcb_write(&k->tcb,io)) { + return(LIB3DS_FALSE); + } + lib3ds_io_write_float(io, k->angle); + lib3ds_io_write_vector(io, k->axis); + } + return(LIB3DS_TRUE); +} + + +/*! + * \ingroup tracks + */ +Lib3dsMorphKey* +lib3ds_morph_key_new() +{ + Lib3dsMorphKey* k; + k=(Lib3dsMorphKey*)calloc(sizeof(Lib3dsMorphKey), 1); + return(k); +} + + +/*! + * \ingroup tracks + */ +void +lib3ds_morph_key_free(Lib3dsMorphKey *key) +{ + ASSERT(key); + free(key); +} + + +/*! + * \ingroup tracks + */ +void +lib3ds_morph_track_free_keys(Lib3dsMorphTrack *track) +{ + Lib3dsMorphKey *p,*q; + + ASSERT(track); + for (p=track->keyL; p; p=q) { + q=p->next; + lib3ds_morph_key_free(p); + } +} + + +/*! + * \ingroup tracks + */ +void +lib3ds_morph_track_insert(Lib3dsMorphTrack *track, Lib3dsMorphKey *key) +{ + ASSERT(track); + ASSERT(key); + ASSERT(!key->next); + + if (!track->keyL) { + track->keyL=key; + key->next=0; + } + else { + Lib3dsMorphKey *k,*p; + + for (p=0,k=track->keyL; k!=0; p=k, k=k->next) { + if (k->tcb.frame>key->tcb.frame) { + break; + } + } + if (!p) { + key->next=track->keyL; + track->keyL=key; + } + else { + key->next=k; + p->next=key; + } + + if (k && (key->tcb.frame==k->tcb.frame)) { + key->next=k->next; + lib3ds_morph_key_free(k); + } + } +} + + +/*! + * \ingroup tracks + */ +void +lib3ds_morph_track_remove(Lib3dsMorphTrack *track, Lib3dsIntd frame) +{ + Lib3dsMorphKey *k,*p; + + ASSERT(track); + if (!track->keyL) { + return; + } + for (p=0,k=track->keyL; k!=0; p=k, k=k->next) { + if (k->tcb.frame==frame) { + if (!p) { + track->keyL=track->keyL->next; + } + else { + p->next=k->next; + } + lib3ds_morph_key_free(k); + break; + } + } +} + + +/*! + * \ingroup tracks + */ +void +lib3ds_morph_track_eval(Lib3dsMorphTrack *track, char *p, Lib3dsFloat t) +{ + Lib3dsMorphKey *k; + char* result; + + ASSERT(p); + if (!track->keyL) { + strcpy(p,""); + return; + } + if (!track->keyL->next) { + strcpy(p,track->keyL->name); + return; + } + + + /* TODO: this function finds the mesh frame that corresponds to this + * timeframe. It would be better to actually interpolate the mesh. + */ + + result=0; + + for (k = track->keyL; + k->next != NULL && t >= k->next->tcb.frame; + k = k->next); + + result=k->name; + + if (result) { + strcpy(p,result); + } + else { + strcpy(p,""); + } +} + + +/*! + * \ingroup tracks + */ +Lib3dsBool +lib3ds_morph_track_read(Lib3dsMorphTrack *track, Lib3dsIo *io) +{ + /* This function was written by Stephane Denis on 5-18-04 */ + int i; + Lib3dsMorphKey *k, *pk = 0; + int keys; + track->flags=lib3ds_io_read_word(io); + lib3ds_io_read_dword(io); + lib3ds_io_read_dword(io); + keys=lib3ds_io_read_intd(io); + + for (i=0; i<keys; ++i) { + k=lib3ds_morph_key_new(); + if (!lib3ds_tcb_read(&k->tcb, io)) { + return(LIB3DS_FALSE); + } + if (!lib3ds_io_read_string(io, k->name, 11)) { + return(LIB3DS_FALSE); + } + if (!track->keyL) + track->keyL = k; + else + pk->next = k; + pk = k; + } + return(LIB3DS_TRUE); +} + + +/*! + * \ingroup tracks + */ +Lib3dsBool +lib3ds_morph_track_write(Lib3dsMorphTrack *track, Lib3dsIo *io) +{ + /* FIXME: */ + ASSERT(0); + LIB3DS_UNUSED(track); + LIB3DS_UNUSED(io); + return(LIB3DS_FALSE); +} + + + +void +tcb_dump(Lib3dsTcb *tcb) +{ + printf(" tcb: frame=%d, flags=%04x, tens=%g, cont=%g, ", + tcb->frame, tcb->flags, tcb->tens, tcb->cont); + printf("bias=%g, ease_to=%g, ease_from=%g\n", + tcb->bias, tcb->ease_to, tcb->ease_from); +} + + +void +lib3ds_boolTrack_dump(Lib3dsBoolTrack *track) +{ + Lib3dsBoolKey *key; + printf("flags: %08x, keys:\n", track->flags); + for ( key = track->keyL; key != NULL; key = key->next) + { + tcb_dump(&key->tcb); + } +} + + +void +lib3ds_lin1Track_dump(Lib3dsLin1Track *track) +{ + Lib3dsLin1Key *key; + printf("flags: %08x, keys:\n", track->flags); + for ( key = track->keyL; key != NULL; key = key->next) + { + tcb_dump(&key->tcb); + printf(" value = %g, dd=%g, ds=%g\n", + key->value, key->dd, key->ds); + } +} + + +void +lib3ds_lin3Track_dump(Lib3dsLin3Track *track) +{ + Lib3dsLin3Key *key; + printf("flags: %08x, keys:\n", track->flags); + for ( key = track->keyL; key != NULL; key = key->next) + { + tcb_dump(&key->tcb); + printf(" value = %g,%g,%g, dd=%g,%g,%g, ds=%g,%g,%g\n", + key->value[0], key->value[1], key->value[2], + key->dd[0], key->dd[1], key->dd[2], + key->ds[0], key->ds[1], key->ds[2]); + } +} + + +void +lib3ds_quatTrack_dump(Lib3dsQuatTrack *track) +{ + Lib3dsQuatKey *key; + printf("flags: %08x, keys:\n", track->flags); + for ( key = track->keyL; key != NULL; key = key->next) + { + tcb_dump(&key->tcb); + printf(" axis = %g,%g,%g, angle=%g, q=%g,%g,%g,%g\n", + key->axis[0], key->axis[1], key->axis[2], key->angle, + key->q[0], key->q[1], key->q[2], key->q[3]); + printf(" dd = %g,%g,%g,%g, ds=%g,%g,%g,%g\n", + key->dd[0], key->dd[1], key->dd[2], key->dd[3], + key->ds[0], key->ds[1], key->ds[2], key->ds[3]); + } +} + + +void +lib3ds_morphTrack_dump(Lib3dsMorphTrack *track) +{ + Lib3dsMorphKey *key; + printf("flags: %08x, keys:\n", track->flags); + for ( key = track->keyL; key != NULL; key = key->next) + { + tcb_dump(&key->tcb); + printf(" name = %s\n", key->name); + } +} + + + +void +lib3ds_dump_tracks(Lib3dsNode *node) +{ + switch( node->type ) { + case LIB3DS_AMBIENT_NODE: + printf("ambient: "); + lib3ds_lin3Track_dump(&node->data.ambient.col_track); + break; + case LIB3DS_OBJECT_NODE: + printf("pos: "); + lib3ds_lin3Track_dump(&node->data.object.pos_track); + printf("rot: "); + lib3ds_quatTrack_dump(&node->data.object.rot_track); + printf("scl: "); + lib3ds_lin3Track_dump(&node->data.object.scl_track); + printf("morph: "); + lib3ds_morphTrack_dump(&node->data.object.morph_track); + printf("hide: "); + lib3ds_boolTrack_dump(&node->data.object.hide_track); + break; + case LIB3DS_CAMERA_NODE: + printf("pos: "); + lib3ds_lin3Track_dump(&node->data.camera.pos_track); + printf("fov: "); + lib3ds_lin1Track_dump(&node->data.camera.fov_track); + printf("roll: "); + lib3ds_lin1Track_dump(&node->data.camera.roll_track); + break; + case LIB3DS_TARGET_NODE: + printf("pos: "); + lib3ds_lin3Track_dump(&node->data.target.pos_track); + break; + case LIB3DS_LIGHT_NODE: + printf("pos: "); + lib3ds_lin3Track_dump(&node->data.light.pos_track); + printf("col: "); + lib3ds_lin3Track_dump(&node->data.light.col_track); + printf("hotspot: "); + lib3ds_lin1Track_dump(&node->data.light.hotspot_track); + printf("falloff: "); + lib3ds_lin1Track_dump(&node->data.light.falloff_track); + printf("roll: "); + lib3ds_lin1Track_dump(&node->data.light.roll_track); + break; + case LIB3DS_SPOT_NODE: + printf("pos: "); + lib3ds_lin3Track_dump(&node->data.spot.pos_track); + break; + default: + break; + } +} diff --git a/3rdparty/lib3ds/tracks.h b/3rdparty/lib3ds/tracks.h new file mode 100644 index 000000000..7783e51c5 --- /dev/null +++ b/3rdparty/lib3ds/tracks.h @@ -0,0 +1,209 @@ +/* -*- c -*- */ +#ifndef INCLUDED_LIB3DS_TRACKS_H +#define INCLUDED_LIB3DS_TRACKS_H +/* + * The 3D Studio File Format Library + * Copyright (C) 1996-2007 by Jan Eric Kyprianidis <www.kyprianidis.com> + * 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: tracks.h,v 1.11 2007/06/20 17:04:09 jeh Exp $ + */ + +#ifndef INCLUDED_LIB3DS_TCB_H +#include <lib3ds/tcb.h> +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Track flags + * \ingroup tracks + */ +typedef enum { + LIB3DS_REPEAT =0x0001, + LIB3DS_SMOOTH =0x0002, + LIB3DS_LOCK_X =0x0008, + LIB3DS_LOCK_Y =0x0010, + LIB3DS_LOCK_Z =0x0020, + LIB3DS_UNLINK_X =0x0100, + LIB3DS_UNLINK_Y =0x0200, + LIB3DS_UNLINK_Z =0x0400 +} Lib3dsTrackFlags; + +/** + * Boolean track key + * \ingroup tracks + */ +struct Lib3dsBoolKey { + Lib3dsTcb tcb; + Lib3dsBoolKey *next; +}; + +/** + * Boolean track + * \ingroup tracks + */ +struct Lib3dsBoolTrack { + Lib3dsDword flags; + Lib3dsBoolKey *keyL; +}; + +/** + * Floating-point track key + * \ingroup tracks + */ +struct Lib3dsLin1Key { + Lib3dsTcb tcb; + Lib3dsLin1Key *next; + Lib3dsFloat value; + Lib3dsFloat dd; + Lib3dsFloat ds; +}; + +/** + * Floating-point track + * \ingroup tracks + */ +struct Lib3dsLin1Track { + Lib3dsDword flags; + Lib3dsLin1Key *keyL; +}; + +/** + * Vector track key + * \ingroup tracks + */ +struct Lib3dsLin3Key { + Lib3dsTcb tcb; + Lib3dsLin3Key *next; + Lib3dsVector value; + Lib3dsVector dd; + Lib3dsVector ds; +}; + +/** + * Vector track + * \ingroup tracks + */ +struct Lib3dsLin3Track { + Lib3dsDword flags; + Lib3dsLin3Key *keyL; +}; + +/** + * Rotation track key + * \ingroup tracks + */ +struct Lib3dsQuatKey { + Lib3dsTcb tcb; + Lib3dsQuatKey *next; + Lib3dsVector axis; + Lib3dsFloat angle; + Lib3dsQuat q; + Lib3dsQuat dd; + Lib3dsQuat ds; +}; + +/** + * Rotation track + * \ingroup tracks + */ +struct Lib3dsQuatTrack { + Lib3dsDword flags; + Lib3dsQuatKey *keyL; +}; + +/** + * Morph track key + * \ingroup tracks + */ +struct Lib3dsMorphKey { + Lib3dsTcb tcb; + Lib3dsMorphKey *next; + char name[64]; +}; + +/** + * Morph track + * \ingroup tracks + */ +struct Lib3dsMorphTrack { + Lib3dsDword flags; + Lib3dsMorphKey *keyL; +}; + +extern LIB3DSAPI Lib3dsBoolKey* lib3ds_bool_key_new(); +extern LIB3DSAPI void lib3ds_bool_key_free(Lib3dsBoolKey* key); +extern LIB3DSAPI void lib3ds_bool_track_free_keys(Lib3dsBoolTrack *track); +extern LIB3DSAPI void lib3ds_bool_track_insert(Lib3dsBoolTrack *track, Lib3dsBoolKey* key); +extern LIB3DSAPI void lib3ds_bool_track_remove(Lib3dsBoolTrack *track, Lib3dsIntd frame); +extern LIB3DSAPI void lib3ds_bool_track_eval(Lib3dsBoolTrack *track, Lib3dsBool *p, Lib3dsFloat t); +extern LIB3DSAPI Lib3dsBool lib3ds_bool_track_read(Lib3dsBoolTrack *track, Lib3dsIo *io); +extern LIB3DSAPI Lib3dsBool lib3ds_bool_track_write(Lib3dsBoolTrack *track, Lib3dsIo *io); + +extern LIB3DSAPI Lib3dsLin1Key* lib3ds_lin1_key_new(); +extern LIB3DSAPI void lib3ds_lin1_key_free(Lib3dsLin1Key* key); +extern LIB3DSAPI void lib3ds_lin1_track_free_keys(Lib3dsLin1Track *track); +extern LIB3DSAPI void lib3ds_lin1_key_setup(Lib3dsLin1Key *p, Lib3dsLin1Key *cp, Lib3dsLin1Key *c, + Lib3dsLin1Key *cn, Lib3dsLin1Key *n); +extern LIB3DSAPI void lib3ds_lin1_track_setup(Lib3dsLin1Track *track); +extern LIB3DSAPI void lib3ds_lin1_track_insert(Lib3dsLin1Track *track, Lib3dsLin1Key *key); +extern LIB3DSAPI void lib3ds_lin1_track_remove(Lib3dsLin1Track *track, Lib3dsIntd frame); +extern LIB3DSAPI void lib3ds_lin1_track_eval(Lib3dsLin1Track *track, Lib3dsFloat *p, Lib3dsFloat t); +extern LIB3DSAPI Lib3dsBool lib3ds_lin1_track_read(Lib3dsLin1Track *track, Lib3dsIo *io); +extern LIB3DSAPI Lib3dsBool lib3ds_lin1_track_write(Lib3dsLin1Track *track, Lib3dsIo *io); + +extern LIB3DSAPI Lib3dsLin3Key* lib3ds_lin3_key_new(); +extern LIB3DSAPI void lib3ds_lin3_key_free(Lib3dsLin3Key* key); +extern LIB3DSAPI void lib3ds_lin3_track_free_keys(Lib3dsLin3Track *track); +extern LIB3DSAPI void lib3ds_lin3_key_setup(Lib3dsLin3Key *p, Lib3dsLin3Key *cp, Lib3dsLin3Key *c, + Lib3dsLin3Key *cn, Lib3dsLin3Key *n); +extern LIB3DSAPI void lib3ds_lin3_track_setup(Lib3dsLin3Track *track); +extern LIB3DSAPI void lib3ds_lin3_track_insert(Lib3dsLin3Track *track, Lib3dsLin3Key *key); +extern LIB3DSAPI void lib3ds_lin3_track_remove(Lib3dsLin3Track *track, Lib3dsIntd frame); +extern LIB3DSAPI void lib3ds_lin3_track_eval(Lib3dsLin3Track *track, Lib3dsVector p, Lib3dsFloat t); +extern LIB3DSAPI Lib3dsBool lib3ds_lin3_track_read(Lib3dsLin3Track *track, Lib3dsIo *io); +extern LIB3DSAPI Lib3dsBool lib3ds_lin3_track_write(Lib3dsLin3Track *track, Lib3dsIo *io); + +extern LIB3DSAPI Lib3dsQuatKey* lib3ds_quat_key_new(); +extern LIB3DSAPI void lib3ds_quat_key_free(Lib3dsQuatKey* key); +extern LIB3DSAPI void lib3ds_quat_track_free_keys(Lib3dsQuatTrack *track); +extern LIB3DSAPI void lib3ds_quat_key_setup(Lib3dsQuatKey *p, Lib3dsQuatKey *cp, Lib3dsQuatKey *c, + Lib3dsQuatKey *cn, Lib3dsQuatKey *n); +extern LIB3DSAPI void lib3ds_quat_track_setup(Lib3dsQuatTrack *track); +extern LIB3DSAPI void lib3ds_quat_track_insert(Lib3dsQuatTrack *track, Lib3dsQuatKey *key); +extern LIB3DSAPI void lib3ds_quat_track_remove(Lib3dsQuatTrack *track, Lib3dsIntd frame); +extern LIB3DSAPI void lib3ds_quat_track_eval(Lib3dsQuatTrack *track, Lib3dsQuat p, Lib3dsFloat t); +extern LIB3DSAPI Lib3dsBool lib3ds_quat_track_read(Lib3dsQuatTrack *track, Lib3dsIo *io); +extern LIB3DSAPI Lib3dsBool lib3ds_quat_track_write(Lib3dsQuatTrack *track, Lib3dsIo *io); + +extern LIB3DSAPI Lib3dsMorphKey* lib3ds_morph_key_new(); +extern LIB3DSAPI void lib3ds_morph_key_free(Lib3dsMorphKey* key); +extern LIB3DSAPI void lib3ds_morph_track_free_keys(Lib3dsMorphTrack *track); +extern LIB3DSAPI void lib3ds_morph_track_insert(Lib3dsMorphTrack *track, Lib3dsMorphKey *key); +extern LIB3DSAPI void lib3ds_morph_track_remove(Lib3dsMorphTrack *track, Lib3dsIntd frame); +extern LIB3DSAPI void lib3ds_morph_track_eval(Lib3dsMorphTrack *track, char *p, Lib3dsFloat t); +extern LIB3DSAPI Lib3dsBool lib3ds_morph_track_read(Lib3dsMorphTrack *track, Lib3dsIo *io); +extern LIB3DSAPI Lib3dsBool lib3ds_morph_track_write(Lib3dsMorphTrack *track, Lib3dsIo *io); + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/3rdparty/lib3ds/types.h b/3rdparty/lib3ds/types.h new file mode 100644 index 000000000..77fe00c72 --- /dev/null +++ b/3rdparty/lib3ds/types.h @@ -0,0 +1,159 @@ +/* -*- c -*- */ +#ifndef INCLUDED_LIB3DS_TYPES_H +#define INCLUDED_LIB3DS_TYPES_H +/* + * The 3D Studio File Format Library + * Copyright (C) 1996-2007 by Jan Eric Kyprianidis <www.kyprianidis.com> + * 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: types.h,v 1.25 2007/06/21 08:36:41 jeh Exp $ + */ +#ifdef __cplusplus +extern "C" { +#endif + +/*! +#ifdef _MSC_VER +#ifdef LIB3DS_EXPORTS +#define LIB3DSAPI __declspec(dllexport) +#else +#define LIB3DSAPI __declspec(dllimport) +#endif +#else +#define LIB3DSAPI +#endif +*/ +#define LIB3DSAPI +#define LIB3DS_UNUSED(x) (void)x + +#define LIB3DS_TRUE 1 +#define LIB3DS_FALSE 0 + +#ifdef _MSC_VER +typedef __int32 Lib3dsBool; +typedef unsigned __int8 Lib3dsByte; +typedef unsigned __int16 Lib3dsWord; +typedef unsigned __int32 Lib3dsDword; +typedef signed __int8 Lib3dsIntb; +typedef signed __int16 Lib3dsIntw; +typedef signed __int16 Lib3dsIntd; +#else +#include <stdint.h> +typedef int32_t Lib3dsBool; +typedef uint8_t Lib3dsByte; +typedef uint16_t Lib3dsWord; +typedef uint32_t Lib3dsDword; +typedef int8_t Lib3dsIntb; +typedef int16_t Lib3dsIntw; +typedef int32_t Lib3dsIntd; +#endif + +typedef float Lib3dsFloat; +typedef double Lib3dsDouble; + +typedef float Lib3dsVector[3]; +typedef float Lib3dsTexel[2]; +typedef float Lib3dsQuat[4]; +typedef float Lib3dsMatrix[4][4]; +typedef float Lib3dsRgb[3]; +typedef float Lib3dsRgba[4]; + +#define LIB3DS_EPSILON (1e-8) +#define LIB3DS_PI 3.14159265358979323846 +#define LIB3DS_TWOPI (2.0*LIB3DS_PI) +#define LIB3DS_HALFPI (LIB3DS_PI/2.0) +#define LIB3DS_RAD_TO_DEG(x) ((180.0/LIB3DS_PI)*(x)) +#define LIB3DS_DEG_TO_RAD(x) ((LIB3DS_PI/180.0)*(x)) + +#include <stdio.h> + +#ifdef _DEBUG + #ifndef ASSERT + #include <assert.h> + #define ASSERT(__expr) assert(__expr) + #endif + #define LIB3DS_ERROR_LOG \ + {printf("\t***LIB3DS_ERROR_LOG*** %s : %d\n", __FILE__, __LINE__);} +#else + #ifndef ASSERT + #define ASSERT(__expr) + #endif + #define LIB3DS_ERROR_LOG +#endif + +typedef struct Lib3dsIo Lib3dsIo; +typedef struct Lib3dsFile Lib3dsFile; +typedef struct Lib3dsBackground Lib3dsBackground; +typedef struct Lib3dsAtmosphere Lib3dsAtmosphere; +typedef struct Lib3dsShadow Lib3dsShadow; +typedef struct Lib3dsViewport Lib3dsViewport; +typedef struct Lib3dsMaterial Lib3dsMaterial; +typedef struct Lib3dsFace Lib3dsFace; +typedef struct Lib3dsBoxMap Lib3dsBoxMap; +typedef struct Lib3dsMapData Lib3dsMapData; +typedef struct Lib3dsMesh Lib3dsMesh; +typedef struct Lib3dsCamera Lib3dsCamera; +typedef struct Lib3dsLight Lib3dsLight; +typedef struct Lib3dsBoolKey Lib3dsBoolKey; +typedef struct Lib3dsBoolTrack Lib3dsBoolTrack; +typedef struct Lib3dsLin1Key Lib3dsLin1Key; +typedef struct Lib3dsLin1Track Lib3dsLin1Track; +typedef struct Lib3dsLin3Key Lib3dsLin3Key; +typedef struct Lib3dsLin3Track Lib3dsLin3Track; +typedef struct Lib3dsQuatKey Lib3dsQuatKey; +typedef struct Lib3dsQuatTrack Lib3dsQuatTrack; +typedef struct Lib3dsMorphKey Lib3dsMorphKey; +typedef struct Lib3dsMorphTrack Lib3dsMorphTrack; + +typedef enum Lib3dsNodeTypes { + LIB3DS_UNKNOWN_NODE =0, + LIB3DS_AMBIENT_NODE =1, + LIB3DS_OBJECT_NODE =2, + LIB3DS_CAMERA_NODE =3, + LIB3DS_TARGET_NODE =4, + LIB3DS_LIGHT_NODE =5, + LIB3DS_SPOT_NODE =6 +} Lib3dsNodeTypes; + +typedef struct Lib3dsNode Lib3dsNode; + +typedef enum Lib3dsObjectFlags { + LIB3DS_OBJECT_HIDDEN =0x01, + LIB3DS_OBJECT_VIS_LOFTER =0x02, + LIB3DS_OBJECT_DOESNT_CAST =0x04, + LIB3DS_OBJECT_MATTE =0x08, + LIB3DS_OBJECT_DONT_RCVSHADOW =0x10, + LIB3DS_OBJECT_FAST =0x20, + LIB3DS_OBJECT_FROZEN =0x40 +} Lib3dsObjectFlags; + +typedef union Lib3dsUserData { + void *p; + Lib3dsIntd i; + Lib3dsDword d; + Lib3dsFloat f; + Lib3dsMaterial *material; + Lib3dsMesh *mesh; + Lib3dsCamera *camera; + Lib3dsLight *light; + Lib3dsNode *node; +} Lib3dsUserData; + +#ifdef __cplusplus +} +#endif +#endif diff --git a/3rdparty/lib3ds/types.txt b/3rdparty/lib3ds/types.txt new file mode 100644 index 000000000..08d654410 --- /dev/null +++ b/3rdparty/lib3ds/types.txt @@ -0,0 +1,96 @@ +/* + * The 3D Studio File Format Library + * Copyright (C) 1996-2007 by Jan Eric Kyprianidis <www.kyprianidis.com> + * 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: types.txt,v 1.3 2007/06/20 17:04:09 jeh Exp $ + */ +/*! + +\defgroup types General Types + +*/ +/*! + +\typedef Lib3dsBool + \ingroup types + Bool Typedef + +*/ +/*! + +\typedef Lib3dsByte + \ingroup types + Byte (== 8bit unsigned int) Typedef + +*/ +/*! + +\typedef Lib3dsWord + \ingroup types + Word (== 16bit unsigned int) Typedef + +*/ +/*! + +\typedef Lib3dsDword + \ingroup types + Double-Word (== 32bit unsigned int) Typedef + +*/ +/*! + +\typedef Lib3dsIntb + \ingroup types + Signed Byte (== 8bit signed int) Typedef + +*/ +/*! + +\typedef Lib3dsIntw + \ingroup types + Signed Word (== 16bit signed int) Typedef + +*/ +/*! + +\typedef Lib3dsIntd + \ingroup types + Signed Double-Word (== 32bit signed int) Typedef + +*/ +/*! + +\typedef Lib3dsRgb + \ingroup types + Red, Green, Blue color Typedef + +*/ +/*! + +\typedef Lib3dsRgba + \ingroup types + Red, Green, Blue, Alpha color Typedef + +*/ +/*! + +\typedef Lib3dsTexel + \ingroup types + UV texture coordinates + +*/ diff --git a/3rdparty/lib3ds/vector.c b/3rdparty/lib3ds/vector.c new file mode 100644 index 000000000..46f48f205 --- /dev/null +++ b/3rdparty/lib3ds/vector.c @@ -0,0 +1,376 @@ +/* + * The 3D Studio File Format Library + * Copyright (C) 1996-2007 by Jan Eric Kyprianidis <www.kyprianidis.com> + * 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: vector.c,v 1.12 2007/06/20 17:04:09 jeh Exp $ + */ +#include <lib3ds/vector.h> +#include <math.h> + + +/*! + * \defgroup vector Vector Mathematics + */ + + +/*! + * \typedef Lib3dsVector + * \ingroup vector + */ + + +/*! + * Clear a vector to zero. + * + * \param c Vector to clear. + * + * \ingroup vector + */ +void +lib3ds_vector_zero(Lib3dsVector c) +{ + int i; + for (i=0; i<3; ++i) { + c[i]=0.0f; + } +} + + +/*! + * Copy a vector. + * + * \param dest Destination vector. + * \param src Source vector. + * + * \ingroup vector + */ +void +lib3ds_vector_copy(Lib3dsVector dest, Lib3dsVector src) +{ + int i; + for (i=0; i<3; ++i) { + dest[i]=src[i]; + } +} + + +/*! + * Negate a vector. + * + * \param c Vector to negate. + * + * \ingroup vector + */ +void +lib3ds_vector_neg(Lib3dsVector c) +{ + int i; + for (i=0; i<3; ++i) { + c[i]=-c[i]; + } +} + + +/*! + * Add two vectors. + * + * \param c Result. + * \param a First addend. + * \param b Second addend. + * + * \ingroup vector + */ +void +lib3ds_vector_add(Lib3dsVector c, Lib3dsVector a, Lib3dsVector b) +{ + int i; + for (i=0; i<3; ++i) { + c[i]=a[i]+b[i]; + } +} + + +/*! + * Subtract two vectors. + * + * \param c Result. + * \param a Addend. + * \param b Minuend. + * + * \ingroup vector + */ +void +lib3ds_vector_sub(Lib3dsVector c, Lib3dsVector a, Lib3dsVector b) +{ + int i; + for (i=0; i<3; ++i) { + c[i]=a[i]-b[i]; + } +} + + +/*! + * Multiply a vector by a scalar. + * + * \param c Vector to be multiplied. + * \param k Scalar. + * + * \ingroup vector + */ +void +lib3ds_vector_scalar(Lib3dsVector c, Lib3dsFloat k) +{ + int i; + for (i=0; i<3; ++i) { + c[i]*=k; + } +} + + +/*! + * Compute cross product. + * + * \param c Result. + * \param a First vector. + * \param b Second vector. + * + * \ingroup vector + */ +void +lib3ds_vector_cross(Lib3dsVector c, Lib3dsVector a, Lib3dsVector b) +{ + c[0]=a[1]*b[2] - a[2]*b[1]; + c[1]=a[2]*b[0] - a[0]*b[2]; + c[2]=a[0]*b[1] - a[1]*b[0]; +} + + +/*! + * Compute dot product. + * + * \param a First vector. + * \param b Second vector. + * + * \return Dot product. + * + * \ingroup vector + */ +Lib3dsFloat +lib3ds_vector_dot(Lib3dsVector a, Lib3dsVector b) +{ + return(a[0]*b[0] + a[1]*b[1] + a[2]*b[2]); +} + + +/*! + * Compute square of vector. + * + * Computes x*x + y*y + z*z. + * + * \param c Vector to square. + * + * \return Square of vector. + * + * \ingroup vector + */ +Lib3dsFloat +lib3ds_vector_squared(Lib3dsVector c) +{ + return(c[0]*c[0] + c[1]*c[1] + c[2]*c[2]); +} + + +/*! + * Compute length of vector. + * + * Computes |c| = sqrt(x*x + y*y + z*z) + * + * \param c Vector to compute. + * + * \return Length of vector. + * + * \ingroup vector + */ +Lib3dsFloat +lib3ds_vector_length(Lib3dsVector c) +{ + return((Lib3dsFloat)sqrt(c[0]*c[0] + c[1]*c[1] + c[2]*c[2])); +} + + +/*! + * Normalize a vector. + * + * Scales a vector so that its length is 1.0. + * + * \param c Vector to normalize. + * + * \ingroup vector + */ +void +lib3ds_vector_normalize(Lib3dsVector c) +{ + Lib3dsFloat l,m; + + l=(Lib3dsFloat)sqrt(c[0]*c[0] + c[1]*c[1] + c[2]*c[2]); + if (fabs(l)<LIB3DS_EPSILON) { + if ((c[0]>=c[1]) && (c[0]>=c[2])) { + c[0]=1.0f; + c[1]=c[2]=0.0f; + } + else + if (c[1]>=c[2]) { + c[1]=1.0f; + c[0]=c[2]=0.0f; + } + else { + c[2]=1.0f; + c[0]=c[1]=0.0f; + } + } + else { + m=1.0f/l; + c[0]*=m; + c[1]*=m; + c[2]*=m; + } +} + + +/*! + * Compute a vector normal to two line segments. + * + * Computes the normal vector to the lines b-a and b-c. + * + * \param n Returned normal vector. + * \param a Endpoint of first line. + * \param b Base point of both lines. + * \param c Endpoint of second line. + * + * \ingroup vector + */ +void +lib3ds_vector_normal(Lib3dsVector n, Lib3dsVector a, Lib3dsVector b, Lib3dsVector c) +{ + Lib3dsVector p,q; + + lib3ds_vector_sub(p,c,b); + lib3ds_vector_sub(q,a,b); + lib3ds_vector_cross(n,p,q); + lib3ds_vector_normalize(n); +} + + +/*! + * Multiply a point by a transformation matrix. + * + * Applies the given transformation matrix to the given point. With some + * transformation matrices, a vector may also be transformed. + * + * \param c Result. + * \param m Transformation matrix. + * \param a Input point. + * + * \ingroup vector + */ +void +lib3ds_vector_transform(Lib3dsVector c, Lib3dsMatrix m, Lib3dsVector a) +{ + c[0]= m[0][0]*a[0] + m[1][0]*a[1] + m[2][0]*a[2] + m[3][0]; + c[1]= m[0][1]*a[0] + m[1][1]*a[1] + m[2][1]*a[2] + m[3][1]; + c[2]= m[0][2]*a[0] + m[1][2]*a[1] + m[2][2]*a[2] + m[3][2]; +} + + +/*! + * Compute a point on a cubic spline. + * + * Computes a point on a parametric Bezier spline. + * + * \param c Result. + * \param a First endpoint of the spline. + * \param p First tangent vector of the spline. + * \param q Second tangent vector of the spline. + * \param b Second endpoint of the spline. + * \param t Spline parameter [0. 1.] + * + * \ingroup vector + */ +void +lib3ds_vector_cubic(Lib3dsVector c, Lib3dsVector a, Lib3dsVector p, Lib3dsVector q, + Lib3dsVector b, Lib3dsFloat t) +{ + Lib3dsDouble x,y,z,w; + + x=2*t*t*t - 3*t*t + 1; + y=-2*t*t*t + 3*t*t; + z=t*t*t - 2*t*t + t; + w=t*t*t - t*t; + c[0]=(Lib3dsFloat)(x*a[0] + y*b[0] + z*p[0] + w*q[0]); + c[1]=(Lib3dsFloat)(x*a[1] + y*b[1] + z*p[1] + w*q[1]); + c[2]=(Lib3dsFloat)(x*a[2] + y*b[2] + z*p[2] + w*q[2]); +} + + +/*! + * c[i] = min(c[i], a[i]); + * + * Computes minimum values of x,y,z independently. + * + * \ingroup vector + */ +void +lib3ds_vector_min(Lib3dsVector c, Lib3dsVector a) +{ + int i; + for (i=0; i<3; ++i) { + if (a[i]<c[i]) { + c[i] = a[i]; + } + } +} + + +/*! + * c[i] = max(c[i], a[i]); + * + * Computes maximum values of x,y,z independently. + * + * \ingroup vector + */ +void +lib3ds_vector_max(Lib3dsVector c, Lib3dsVector a) +{ + int i; + for (i=0; i<3; ++i) { + if (a[i]>c[i]) { + c[i] = a[i]; + } + } +} + + +/*! + * \ingroup vector + */ +void +lib3ds_vector_dump(Lib3dsVector c) +{ + fprintf(stderr, "%f %f %f\n", c[0], c[1], c[2]); +} + diff --git a/3rdparty/lib3ds/vector.h b/3rdparty/lib3ds/vector.h new file mode 100644 index 000000000..00f273b23 --- /dev/null +++ b/3rdparty/lib3ds/vector.h @@ -0,0 +1,58 @@ +/* -*- c -*- */ +#ifndef INCLUDED_LIB3DS_VECTOR_H +#define INCLUDED_LIB3DS_VECTOR_H +/* + * The 3D Studio File Format Library + * Copyright (C) 1996-2007 by Jan Eric Kyprianidis <www.kyprianidis.com> + * 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: vector.h,v 1.7 2007/06/14 09:59:10 jeh Exp $ + */ + +#ifndef INCLUDED_LIB3DS_TYPES_H +#include <lib3ds/types.h> +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +extern LIB3DSAPI void lib3ds_vector_zero(Lib3dsVector c); +extern LIB3DSAPI void lib3ds_vector_copy(Lib3dsVector dest, Lib3dsVector src); +extern LIB3DSAPI void lib3ds_vector_neg(Lib3dsVector c); +extern LIB3DSAPI void lib3ds_vector_add(Lib3dsVector c, Lib3dsVector a, Lib3dsVector b); +extern LIB3DSAPI void lib3ds_vector_sub(Lib3dsVector c, Lib3dsVector a, Lib3dsVector b); +extern LIB3DSAPI void lib3ds_vector_scalar(Lib3dsVector c, Lib3dsFloat k); +extern LIB3DSAPI void lib3ds_vector_cross(Lib3dsVector c, Lib3dsVector a, Lib3dsVector b); +extern LIB3DSAPI Lib3dsFloat lib3ds_vector_dot(Lib3dsVector a, Lib3dsVector b); +extern LIB3DSAPI Lib3dsFloat lib3ds_vector_squared(Lib3dsVector c); +extern LIB3DSAPI Lib3dsFloat lib3ds_vector_length(Lib3dsVector c); +extern LIB3DSAPI void lib3ds_vector_normalize(Lib3dsVector c); +extern LIB3DSAPI void lib3ds_vector_normal(Lib3dsVector n, Lib3dsVector a, + Lib3dsVector b, Lib3dsVector c); +extern LIB3DSAPI void lib3ds_vector_transform(Lib3dsVector c, Lib3dsMatrix m, Lib3dsVector a); +extern LIB3DSAPI void lib3ds_vector_cubic(Lib3dsVector c, Lib3dsVector a, Lib3dsVector p, + Lib3dsVector q, Lib3dsVector b, Lib3dsFloat t); +extern LIB3DSAPI void lib3ds_vector_min(Lib3dsVector c, Lib3dsVector a); +extern LIB3DSAPI void lib3ds_vector_max(Lib3dsVector c, Lib3dsVector a); +extern LIB3DSAPI void lib3ds_vector_dump(Lib3dsVector c); + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/3rdparty/lib3ds/viewport.c b/3rdparty/lib3ds/viewport.c new file mode 100644 index 000000000..270caf8fd --- /dev/null +++ b/3rdparty/lib3ds/viewport.c @@ -0,0 +1,413 @@ +/* + * The 3D Studio File Format Library + * Copyright (C) 1996-2007 by Jan Eric Kyprianidis <www.kyprianidis.com> + * 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: viewport.c,v 1.11 2007/06/20 17:04:09 jeh Exp $ + */ +#include <lib3ds/viewport.h> +#include <lib3ds/chunk.h> +#include <lib3ds/io.h> +#include <stdlib.h> +#include <string.h> + + +/*! + * \defgroup viewport Viewport and default view settings + */ + + +/*! + * \ingroup viewport + */ +Lib3dsBool +lib3ds_viewport_read(Lib3dsViewport *viewport, Lib3dsIo *io) +{ + Lib3dsChunk c; + Lib3dsWord chunk; + + if (!lib3ds_chunk_read_start(&c, 0, io)) { + return(LIB3DS_FALSE); + } + + switch (c.chunk) { + case LIB3DS_VIEWPORT_LAYOUT: + { + int cur=0; + viewport->layout.style=lib3ds_io_read_word(io); + viewport->layout.active=lib3ds_io_read_intw(io); + lib3ds_io_read_intw(io); + viewport->layout.swap=lib3ds_io_read_intw(io); + lib3ds_io_read_intw(io); + viewport->layout.swap_prior=lib3ds_io_read_intw(io); + viewport->layout.swap_view=lib3ds_io_read_intw(io); + lib3ds_chunk_read_tell(&c, io); + while ((chunk=lib3ds_chunk_read_next(&c, io))!=0) { + switch (chunk) { + case LIB3DS_VIEWPORT_SIZE: + { + viewport->layout.position[0]=lib3ds_io_read_word(io); + viewport->layout.position[1]=lib3ds_io_read_word(io); + viewport->layout.size[0]=lib3ds_io_read_word(io); + viewport->layout.size[1]=lib3ds_io_read_word(io); + } + break; + case LIB3DS_VIEWPORT_DATA_3: + { + lib3ds_viewport_set_views(viewport,cur+1); + lib3ds_io_read_intw(io); + viewport->layout.viewL[cur].axis_lock=lib3ds_io_read_word(io); + viewport->layout.viewL[cur].position[0]=lib3ds_io_read_intw(io); + viewport->layout.viewL[cur].position[1]=lib3ds_io_read_intw(io); + viewport->layout.viewL[cur].size[0]=lib3ds_io_read_intw(io); + viewport->layout.viewL[cur].size[1]=lib3ds_io_read_intw(io); + viewport->layout.viewL[cur].type=lib3ds_io_read_word(io); + viewport->layout.viewL[cur].zoom=lib3ds_io_read_float(io); + lib3ds_io_read_vector(io, viewport->layout.viewL[cur].center); + viewport->layout.viewL[cur].horiz_angle=lib3ds_io_read_float(io); + viewport->layout.viewL[cur].vert_angle=lib3ds_io_read_float(io); + lib3ds_io_read(io, viewport->layout.viewL[cur].camera, 11); + ++cur; + } + break; + case LIB3DS_VIEWPORT_DATA: + /* 3DS R2 & R3 chunk + unsupported */ + break; + default: + lib3ds_chunk_unknown(chunk); + } + } + } + break; + case LIB3DS_DEFAULT_VIEW: + { + memset(&viewport->default_view,0,sizeof(Lib3dsDefaultView)); + while ((chunk=lib3ds_chunk_read_next(&c, io))!=0) { + switch (chunk) { + case LIB3DS_VIEW_TOP: + { + viewport->default_view.type=LIB3DS_VIEW_TYPE_TOP; + lib3ds_io_read_vector(io, viewport->default_view.position); + viewport->default_view.width=lib3ds_io_read_float(io); + } + break; + case LIB3DS_VIEW_BOTTOM: + { + viewport->default_view.type=LIB3DS_VIEW_TYPE_BOTTOM; + lib3ds_io_read_vector(io, viewport->default_view.position); + viewport->default_view.width=lib3ds_io_read_float(io); + } + break; + case LIB3DS_VIEW_LEFT: + { + viewport->default_view.type=LIB3DS_VIEW_TYPE_LEFT; + lib3ds_io_read_vector(io, viewport->default_view.position); + viewport->default_view.width=lib3ds_io_read_float(io); + } + break; + case LIB3DS_VIEW_RIGHT: + { + viewport->default_view.type=LIB3DS_VIEW_TYPE_RIGHT; + lib3ds_io_read_vector(io, viewport->default_view.position); + viewport->default_view.width=lib3ds_io_read_float(io); + } + break; + case LIB3DS_VIEW_FRONT: + { + viewport->default_view.type=LIB3DS_VIEW_TYPE_FRONT; + lib3ds_io_read_vector(io, viewport->default_view.position); + viewport->default_view.width=lib3ds_io_read_float(io); + } + break; + case LIB3DS_VIEW_BACK: + { + viewport->default_view.type=LIB3DS_VIEW_TYPE_BACK; + lib3ds_io_read_vector(io, viewport->default_view.position); + viewport->default_view.width=lib3ds_io_read_float(io); + } + break; + case LIB3DS_VIEW_USER: + { + viewport->default_view.type=LIB3DS_VIEW_TYPE_USER; + lib3ds_io_read_vector(io, viewport->default_view.position); + viewport->default_view.width=lib3ds_io_read_float(io); + viewport->default_view.horiz_angle=lib3ds_io_read_float(io); + viewport->default_view.vert_angle=lib3ds_io_read_float(io); + viewport->default_view.roll_angle=lib3ds_io_read_float(io); + } + break; + case LIB3DS_VIEW_CAMERA: + { + viewport->default_view.type=LIB3DS_VIEW_TYPE_CAMERA; + lib3ds_io_read(io, viewport->default_view.camera, 11); + } + break; + default: + lib3ds_chunk_unknown(chunk); + } + } + } + break; + } + + lib3ds_chunk_read_end(&c, io); + return(LIB3DS_TRUE); +} + + +/*! + * \ingroup viewport + */ +void +lib3ds_viewport_set_views(Lib3dsViewport *viewport, Lib3dsDword views) +{ + ASSERT(viewport); + if (viewport->layout.views) { + if (views) { + viewport->layout.views=views; + viewport->layout.viewL=(Lib3dsView*)realloc(viewport->layout.viewL, sizeof(Lib3dsView)*views); + } + else { + free(viewport->layout.viewL); + viewport->layout.views=0; + viewport->layout.viewL=0; + } + } + else { + if (views) { + viewport->layout.views=views; + viewport->layout.viewL=(Lib3dsView*)calloc(sizeof(Lib3dsView),views); + } + } +} + + +/*! + * \ingroup viewport + */ +Lib3dsBool +lib3ds_viewport_write(Lib3dsViewport *viewport, Lib3dsIo *io) +{ + if (viewport->layout.views) { + Lib3dsChunk c; + unsigned i; + + c.chunk=LIB3DS_VIEWPORT_LAYOUT; + if (!lib3ds_chunk_write_start(&c,io)) { + return(LIB3DS_FALSE); + } + + lib3ds_io_write_word(io, viewport->layout.style); + lib3ds_io_write_intw(io, viewport->layout.active); + lib3ds_io_write_intw(io, 0); + lib3ds_io_write_intw(io, viewport->layout.swap); + lib3ds_io_write_intw(io, 0); + lib3ds_io_write_intw(io, viewport->layout.swap_prior); + lib3ds_io_write_intw(io, viewport->layout.swap_view); + + { + Lib3dsChunk c; + c.chunk=LIB3DS_VIEWPORT_SIZE; + c.size=14; + lib3ds_chunk_write(&c,io); + lib3ds_io_write_intw(io, viewport->layout.position[0]); + lib3ds_io_write_intw(io, viewport->layout.position[1]); + lib3ds_io_write_intw(io, viewport->layout.size[0]); + lib3ds_io_write_intw(io, viewport->layout.size[1]); + } + + for (i=0; i<viewport->layout.views; ++i) { + Lib3dsChunk c; + c.chunk=LIB3DS_VIEWPORT_DATA_3; + c.size=55; + lib3ds_chunk_write(&c,io); + + lib3ds_io_write_intw(io, 0); + lib3ds_io_write_word(io, viewport->layout.viewL[i].axis_lock); + lib3ds_io_write_intw(io, viewport->layout.viewL[i].position[0]); + lib3ds_io_write_intw(io, viewport->layout.viewL[i].position[1]); + lib3ds_io_write_intw(io, viewport->layout.viewL[i].size[0]); + lib3ds_io_write_intw(io, viewport->layout.viewL[i].size[1]); + lib3ds_io_write_word(io, viewport->layout.viewL[i].type); + lib3ds_io_write_float(io, viewport->layout.viewL[i].zoom); + lib3ds_io_write_vector(io, viewport->layout.viewL[i].center); + lib3ds_io_write_float(io, viewport->layout.viewL[i].horiz_angle); + lib3ds_io_write_float(io, viewport->layout.viewL[i].vert_angle); + lib3ds_io_write(io, viewport->layout.viewL[i].camera,11); + } + + if (!lib3ds_chunk_write_end(&c,io)) { + return(LIB3DS_FALSE); + } + } + + if (viewport->default_view.type) { + Lib3dsChunk c; + + c.chunk=LIB3DS_DEFAULT_VIEW; + if (!lib3ds_chunk_write_start(&c,io)) { + return(LIB3DS_FALSE); + } + + switch (viewport->default_view.type) { + case LIB3DS_VIEW_TYPE_TOP: + { + Lib3dsChunk c; + c.chunk=LIB3DS_VIEW_TOP; + c.size=22; + lib3ds_chunk_write(&c,io); + lib3ds_io_write_vector(io, viewport->default_view.position); + lib3ds_io_write_float(io, viewport->default_view.width); + } + break; + case LIB3DS_VIEW_TYPE_BOTTOM: + { + Lib3dsChunk c; + c.chunk=LIB3DS_VIEW_BOTTOM; + c.size=22; + lib3ds_chunk_write(&c,io); + lib3ds_io_write_vector(io, viewport->default_view.position); + lib3ds_io_write_float(io, viewport->default_view.width); + } + break; + case LIB3DS_VIEW_TYPE_LEFT: + { + Lib3dsChunk c; + c.chunk=LIB3DS_VIEW_LEFT; + c.size=22; + lib3ds_chunk_write(&c,io); + lib3ds_io_write_vector(io, viewport->default_view.position); + lib3ds_io_write_float(io, viewport->default_view.width); + } + break; + case LIB3DS_VIEW_TYPE_RIGHT: + { + Lib3dsChunk c; + c.chunk=LIB3DS_VIEW_RIGHT; + c.size=22; + lib3ds_chunk_write(&c,io); + lib3ds_io_write_vector(io, viewport->default_view.position); + lib3ds_io_write_float(io, viewport->default_view.width); + } + break; + case LIB3DS_VIEW_TYPE_FRONT: + { + Lib3dsChunk c; + c.chunk=LIB3DS_VIEW_FRONT; + c.size=22; + lib3ds_chunk_write(&c,io); + lib3ds_io_write_vector(io, viewport->default_view.position); + lib3ds_io_write_float(io, viewport->default_view.width); + } + break; + case LIB3DS_VIEW_TYPE_BACK: + { + Lib3dsChunk c; + c.chunk=LIB3DS_VIEW_BACK; + c.size=22; + lib3ds_chunk_write(&c,io); + lib3ds_io_write_vector(io, viewport->default_view.position); + lib3ds_io_write_float(io, viewport->default_view.width); + } + break; + case LIB3DS_VIEW_TYPE_USER: + { + Lib3dsChunk c; + c.chunk=LIB3DS_VIEW_USER; + c.size=34; + lib3ds_chunk_write(&c,io); + lib3ds_io_write_vector(io, viewport->default_view.position); + lib3ds_io_write_float(io, viewport->default_view.width); + lib3ds_io_write_float(io, viewport->default_view.horiz_angle); + lib3ds_io_write_float(io, viewport->default_view.vert_angle); + lib3ds_io_write_float(io, viewport->default_view.roll_angle); + } + break; + case LIB3DS_VIEW_TYPE_CAMERA: + { + Lib3dsChunk c; + c.chunk=LIB3DS_VIEW_CAMERA; + c.size=17; + lib3ds_chunk_write(&c, io); + lib3ds_io_write(io, viewport->default_view.camera, 11); + } + break; + } + + if (!lib3ds_chunk_write_end(&c, io)) { + return(LIB3DS_FALSE); + } + } + return(LIB3DS_TRUE); +} + + +/*! + * Dump viewport. + * + * \param vp The viewport to be dumped. + * + * \ingroup node + */ +void +lib3ds_viewport_dump(Lib3dsViewport *vp) +{ + Lib3dsView *view; + unsigned i; + ASSERT(vp); + + printf(" viewport:\n"); + printf(" layout:\n"); + printf(" style: %d\n", vp->layout.style); + printf(" active: %d\n", vp->layout.active); + printf(" swap: %d\n", vp->layout.swap); + printf(" swap_prior: %d\n", vp->layout.swap_prior); + printf(" position: %d,%d\n", + vp->layout.position[0], vp->layout.position[1]); + printf(" size: %d,%d\n", vp->layout.size[0], vp->layout.size[1]); + printf(" views: %ld\n", (long)(vp->layout.views)); + if (vp->layout.views > 0 && vp->layout.viewL != NULL) { + for (i=0, view=vp->layout.viewL; i < vp->layout.views; ++i, ++view) { + printf(" view %d:\n", i); + printf(" type: %d\n", view->type); + printf(" axis_lock: %d\n", view->axis_lock); + printf(" position: (%d,%d)\n", + view->position[0], view->position[1]); + printf(" size: (%d,%d)\n", view->size[0], view->size[1]); + printf(" zoom: %g\n", view->zoom); + printf(" center: (%g,%g,%g)\n", + view->center[0], view->center[1], view->center[2]); + printf(" horiz_angle: %g\n", view->horiz_angle); + printf(" vert_angle: %g\n", view->vert_angle); + printf(" camera: %s\n", view->camera); + } + } + + printf(" default_view:\n"); + printf(" type: %d\n", vp->default_view.type); + printf(" position: (%g,%g,%g)\n", + vp->default_view.position[0], + vp->default_view.position[1], + vp->default_view.position[2]); + printf(" width: %g\n", vp->default_view.width); + printf(" horiz_angle: %g\n", vp->default_view.horiz_angle); + printf(" vert_angle: %g\n", vp->default_view.vert_angle); + printf(" roll_angle: %g\n", vp->default_view.roll_angle); + printf(" camera: %s\n", vp->default_view.camera); +} + diff --git a/3rdparty/lib3ds/viewport.h b/3rdparty/lib3ds/viewport.h new file mode 100644 index 000000000..03faa1844 --- /dev/null +++ b/3rdparty/lib3ds/viewport.h @@ -0,0 +1,137 @@ +/* -*- c -*- */ +#ifndef INCLUDED_LIB3DS_VIEWPORT_H +#define INCLUDED_LIB3DS_VIEWPORT_H +/* + * The 3D Studio File Format Library + * Copyright (C) 1996-2007 by Jan Eric Kyprianidis <www.kyprianidis.com> + * 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: viewport.h,v 1.8 2007/06/20 17:04:09 jeh Exp $ + */ + +#ifndef INCLUDED_LIB3DS_TYPES_H +#include <lib3ds/types.h> +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Layout view types + * \ingroup viewport + */ +typedef enum Lib3dsViewType { + LIB3DS_VIEW_TYPE_NOT_USED =0, + LIB3DS_VIEW_TYPE_TOP =1, + LIB3DS_VIEW_TYPE_BOTTOM =2, + LIB3DS_VIEW_TYPE_LEFT =3, + LIB3DS_VIEW_TYPE_RIGHT =4, + LIB3DS_VIEW_TYPE_FRONT =5, + LIB3DS_VIEW_TYPE_BACK =6, + LIB3DS_VIEW_TYPE_USER =7, + LIB3DS_VIEW_TYPE_SPOTLIGHT =18, + LIB3DS_VIEW_TYPE_CAMERA =65535 +} Lib3dsViewType; + +/** + * Layout view settings + * \ingroup viewport + */ +typedef struct Lib3dsView { + Lib3dsWord type; + Lib3dsWord axis_lock; + Lib3dsIntw position[2]; + Lib3dsIntw size[2]; + Lib3dsFloat zoom; + Lib3dsVector center; + Lib3dsFloat horiz_angle; + Lib3dsFloat vert_angle; + char camera[11]; +} Lib3dsView; + +/** + * Layout styles + * \ingroup viewport + */ +typedef enum Lib3dsLayoutStyle { + LIB3DS_LAYOUT_SINGLE =0, + LIB3DS_LAYOUT_TWO_PANE_VERT_SPLIT =1, + LIB3DS_LAYOUT_TWO_PANE_HORIZ_SPLIT =2, + LIB3DS_LAYOUT_FOUR_PANE =3, + LIB3DS_LAYOUT_THREE_PANE_LEFT_SPLIT =4, + LIB3DS_LAYOUT_THREE_PANE_BOTTOM_SPLIT =5, + LIB3DS_LAYOUT_THREE_PANE_RIGHT_SPLIT =6, + LIB3DS_LAYOUT_THREE_PANE_TOP_SPLIT =7, + LIB3DS_LAYOUT_THREE_PANE_VERT_SPLIT =8, + LIB3DS_LAYOUT_THREE_PANE_HORIZ_SPLIT =9, + LIB3DS_LAYOUT_FOUR_PANE_LEFT_SPLIT =10, + LIB3DS_LAYOUT_FOUR_PANE_RIGHT_SPLIT =11 +} Lib3dsLayoutStyle; + +/** + * Viewport layout settings + * \ingroup viewport + */ +typedef struct Lib3dsLayout { + Lib3dsWord style; + Lib3dsIntw active; + Lib3dsIntw swap; + Lib3dsIntw swap_prior; + Lib3dsIntw swap_view; + Lib3dsWord position[2]; + Lib3dsWord size[2]; + Lib3dsDword views; + Lib3dsView *viewL; +} Lib3dsLayout; + +/** + * Default view settings + * \ingroup viewport + */ +typedef struct Lib3dsDefaultView { + Lib3dsWord type; + Lib3dsVector position; + Lib3dsFloat width; + Lib3dsFloat horiz_angle; + Lib3dsFloat vert_angle; + Lib3dsFloat roll_angle; + char camera[64]; +} Lib3dsDefaultView; + +/** + * Viewport and default view settings + * \ingroup viewport + */ +struct Lib3dsViewport { + Lib3dsLayout layout; + Lib3dsDefaultView default_view; +}; + +extern LIB3DSAPI Lib3dsBool lib3ds_viewport_read(Lib3dsViewport *viewport, Lib3dsIo *io); +extern LIB3DSAPI void lib3ds_viewport_set_views(Lib3dsViewport *viewport, Lib3dsDword views); +extern LIB3DSAPI Lib3dsBool lib3ds_viewport_write(Lib3dsViewport *viewport, Lib3dsIo *io); +extern LIB3DSAPI void lib3ds_viewport_dump(Lib3dsViewport *viewport); + +#ifdef __cplusplus +} +#endif +#endif + + + + |