diff --git a/src/osgPlugins/3ds/lib3ds/lib3ds_atmosphere.c b/src/osgPlugins/3ds/lib3ds/lib3ds_atmosphere.c index cefeed9ff..2d15f4c29 100644 --- a/src/osgPlugins/3ds/lib3ds/lib3ds_atmosphere.c +++ b/src/osgPlugins/3ds/lib3ds/lib3ds_atmosphere.c @@ -1,253 +1,253 @@ -/* - Copyright (C) 1996-2008 by Jan Eric Kyprianidis - 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. - - Thisprogram 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, see . -*/ -#include "lib3ds_impl.h" - - -static void -fog_read(Lib3dsAtmosphere *at, Lib3dsIo *io) { - Lib3dsChunk c; - uint16_t chunk; - - lib3ds_chunk_read_start(&c, CHK_FOG, io); - - at->fog_near_plane = lib3ds_io_read_float(io); - at->fog_near_density = lib3ds_io_read_float(io); - at->fog_far_plane = lib3ds_io_read_float(io); - at->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 CHK_LIN_COLOR_F: { - int i; - for (i = 0; i < 3; ++i) { - at->fog_color[i] = lib3ds_io_read_float(io); - } - } - break; - - case CHK_COLOR_F: - break; - - case CHK_FOG_BGND: { - at->fog_background = TRUE; - } - break; - - default: - lib3ds_chunk_unknown(chunk, io); - } - } - - lib3ds_chunk_read_end(&c, io); -} - - -static void -layer_fog_read(Lib3dsAtmosphere *at, Lib3dsIo *io) { - Lib3dsChunk c; - uint16_t chunk; - int have_lin = FALSE; - - lib3ds_chunk_read_start(&c, CHK_LAYER_FOG, io); - - at->layer_fog_near_y = lib3ds_io_read_float(io); - at->layer_fog_far_y = lib3ds_io_read_float(io); - at->layer_fog_density = lib3ds_io_read_float(io); - at->layer_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 CHK_LIN_COLOR_F: - lib3ds_io_read_rgb(io, at->layer_fog_color); - have_lin = TRUE; - break; - - case CHK_COLOR_F: - lib3ds_io_read_rgb(io, at->layer_fog_color); - break; - - default: - lib3ds_chunk_unknown(chunk, io); - } - } - - lib3ds_chunk_read_end(&c, io); -} - - -static void -distance_cue_read(Lib3dsAtmosphere *at, Lib3dsIo *io) { - Lib3dsChunk c; - uint16_t chunk; - - lib3ds_chunk_read_start(&c, CHK_DISTANCE_CUE, io); - - at->dist_cue_near_plane = lib3ds_io_read_float(io); - at->dist_cue_near_dimming = lib3ds_io_read_float(io); - at->dist_cue_far_plane = lib3ds_io_read_float(io); - at->dist_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 CHK_DCUE_BGND: { - at->dist_cue_background = TRUE; - } - break; - - default: - lib3ds_chunk_unknown(chunk, io); - } - } - - lib3ds_chunk_read_end(&c, io); -} - - -void -lib3ds_atmosphere_read(Lib3dsAtmosphere *atmosphere, Lib3dsIo *io) { - Lib3dsChunk c; - - lib3ds_chunk_read(&c, io); - switch (c.chunk) { - case CHK_FOG: { - lib3ds_chunk_read_reset(&c, io); - fog_read(atmosphere, io); - break; - } - - case CHK_LAYER_FOG: { - lib3ds_chunk_read_reset(&c, io); - layer_fog_read(atmosphere, io); - break; - } - - case CHK_DISTANCE_CUE: { - lib3ds_chunk_read_reset(&c, io); - distance_cue_read(atmosphere, io); - break; - } - - case CHK_USE_FOG: { - atmosphere->use_fog = TRUE; - break; - } - - case CHK_USE_LAYER_FOG: { - atmosphere->use_layer_fog = TRUE; - break; - } - - case CHK_USE_DISTANCE_CUE: { - atmosphere->use_dist_cue = TRUE; - break; - } - } -} - - -void -lib3ds_atmosphere_write(Lib3dsAtmosphere *atmosphere, Lib3dsIo *io) { - if (atmosphere->use_fog) { /*---- LIB3DS_FOG ----*/ - Lib3dsChunk c; - c.chunk = CHK_FOG; - lib3ds_chunk_write_start(&c, io); - - 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 = CHK_COLOR_F; - c.size = 18; - lib3ds_chunk_write(&c, io); - lib3ds_io_write_rgb(io, atmosphere->fog_color); - } - if (atmosphere->fog_background) { - Lib3dsChunk c; - c.chunk = CHK_FOG_BGND; - c.size = 6; - lib3ds_chunk_write(&c, io); - } - - lib3ds_chunk_write_end(&c, io); - } - - if (atmosphere->use_layer_fog) { /*---- LIB3DS_LAYER_FOG ----*/ - Lib3dsChunk c; - c.chunk = CHK_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 = CHK_COLOR_F; - c.size = 18; - lib3ds_chunk_write(&c, io); - lib3ds_io_write_rgb(io, atmosphere->fog_color); - } - } - - if (atmosphere->use_dist_cue) { /*---- LIB3DS_DISTANCE_CUE ----*/ - Lib3dsChunk c; - c.chunk = CHK_DISTANCE_CUE; - lib3ds_chunk_write_start(&c, io); - - 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_background) { - Lib3dsChunk c; - c.chunk = CHK_DCUE_BGND; - c.size = 6; - lib3ds_chunk_write(&c, io); - } - - lib3ds_chunk_write_end(&c, io); - } - - if (atmosphere->use_fog) { /*---- LIB3DS_USE_FOG ----*/ - Lib3dsChunk c; - c.chunk = CHK_USE_FOG; - c.size = 6; - lib3ds_chunk_write(&c, io); - } - - if (atmosphere->use_layer_fog) { /*---- LIB3DS_USE_LAYER_FOG ----*/ - Lib3dsChunk c; - c.chunk = CHK_USE_LAYER_FOG; - c.size = 6; - lib3ds_chunk_write(&c, io); - } - - if (atmosphere->use_dist_cue) { /*---- LIB3DS_USE_DISTANCE_CUE ----*/ - Lib3dsChunk c; - c.chunk = CHK_USE_V_GRADIENT; - c.size = 6; - lib3ds_chunk_write(&c, io); - } -} - - +/* + Copyright (C) 1996-2008 by Jan Eric Kyprianidis + 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. + + Thisprogram 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, see . +*/ +#include "lib3ds_impl.h" + + +static void +fog_read(Lib3dsAtmosphere *at, Lib3dsIo *io) { + Lib3dsChunk c; + uint16_t chunk; + + lib3ds_chunk_read_start(&c, CHK_FOG, io); + + at->fog_near_plane = lib3ds_io_read_float(io); + at->fog_near_density = lib3ds_io_read_float(io); + at->fog_far_plane = lib3ds_io_read_float(io); + at->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 CHK_LIN_COLOR_F: { + int i; + for (i = 0; i < 3; ++i) { + at->fog_color[i] = lib3ds_io_read_float(io); + } + } + break; + + case CHK_COLOR_F: + break; + + case CHK_FOG_BGND: { + at->fog_background = TRUE; + } + break; + + default: + lib3ds_chunk_unknown(chunk, io); + } + } + + lib3ds_chunk_read_end(&c, io); +} + + +static void +layer_fog_read(Lib3dsAtmosphere *at, Lib3dsIo *io) { + Lib3dsChunk c; + uint16_t chunk; + int have_lin = FALSE; + + lib3ds_chunk_read_start(&c, CHK_LAYER_FOG, io); + + at->layer_fog_near_y = lib3ds_io_read_float(io); + at->layer_fog_far_y = lib3ds_io_read_float(io); + at->layer_fog_density = lib3ds_io_read_float(io); + at->layer_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 CHK_LIN_COLOR_F: + lib3ds_io_read_rgb(io, at->layer_fog_color); + have_lin = TRUE; + break; + + case CHK_COLOR_F: + lib3ds_io_read_rgb(io, at->layer_fog_color); + break; + + default: + lib3ds_chunk_unknown(chunk, io); + } + } + + lib3ds_chunk_read_end(&c, io); +} + + +static void +distance_cue_read(Lib3dsAtmosphere *at, Lib3dsIo *io) { + Lib3dsChunk c; + uint16_t chunk; + + lib3ds_chunk_read_start(&c, CHK_DISTANCE_CUE, io); + + at->dist_cue_near_plane = lib3ds_io_read_float(io); + at->dist_cue_near_dimming = lib3ds_io_read_float(io); + at->dist_cue_far_plane = lib3ds_io_read_float(io); + at->dist_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 CHK_DCUE_BGND: { + at->dist_cue_background = TRUE; + } + break; + + default: + lib3ds_chunk_unknown(chunk, io); + } + } + + lib3ds_chunk_read_end(&c, io); +} + + +void +lib3ds_atmosphere_read(Lib3dsAtmosphere *atmosphere, Lib3dsIo *io) { + Lib3dsChunk c; + + lib3ds_chunk_read(&c, io); + switch (c.chunk) { + case CHK_FOG: { + lib3ds_chunk_read_reset(&c, io); + fog_read(atmosphere, io); + break; + } + + case CHK_LAYER_FOG: { + lib3ds_chunk_read_reset(&c, io); + layer_fog_read(atmosphere, io); + break; + } + + case CHK_DISTANCE_CUE: { + lib3ds_chunk_read_reset(&c, io); + distance_cue_read(atmosphere, io); + break; + } + + case CHK_USE_FOG: { + atmosphere->use_fog = TRUE; + break; + } + + case CHK_USE_LAYER_FOG: { + atmosphere->use_layer_fog = TRUE; + break; + } + + case CHK_USE_DISTANCE_CUE: { + atmosphere->use_dist_cue = TRUE; + break; + } + } +} + + +void +lib3ds_atmosphere_write(Lib3dsAtmosphere *atmosphere, Lib3dsIo *io) { + if (atmosphere->use_fog) { /*---- LIB3DS_FOG ----*/ + Lib3dsChunk c; + c.chunk = CHK_FOG; + lib3ds_chunk_write_start(&c, io); + + 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 = CHK_COLOR_F; + c.size = 18; + lib3ds_chunk_write(&c, io); + lib3ds_io_write_rgb(io, atmosphere->fog_color); + } + if (atmosphere->fog_background) { + Lib3dsChunk c; + c.chunk = CHK_FOG_BGND; + c.size = 6; + lib3ds_chunk_write(&c, io); + } + + lib3ds_chunk_write_end(&c, io); + } + + if (atmosphere->use_layer_fog) { /*---- LIB3DS_LAYER_FOG ----*/ + Lib3dsChunk c; + c.chunk = CHK_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 = CHK_COLOR_F; + c.size = 18; + lib3ds_chunk_write(&c, io); + lib3ds_io_write_rgb(io, atmosphere->fog_color); + } + } + + if (atmosphere->use_dist_cue) { /*---- LIB3DS_DISTANCE_CUE ----*/ + Lib3dsChunk c; + c.chunk = CHK_DISTANCE_CUE; + lib3ds_chunk_write_start(&c, io); + + 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_background) { + Lib3dsChunk c; + c.chunk = CHK_DCUE_BGND; + c.size = 6; + lib3ds_chunk_write(&c, io); + } + + lib3ds_chunk_write_end(&c, io); + } + + if (atmosphere->use_fog) { /*---- LIB3DS_USE_FOG ----*/ + Lib3dsChunk c; + c.chunk = CHK_USE_FOG; + c.size = 6; + lib3ds_chunk_write(&c, io); + } + + if (atmosphere->use_layer_fog) { /*---- LIB3DS_USE_LAYER_FOG ----*/ + Lib3dsChunk c; + c.chunk = CHK_USE_LAYER_FOG; + c.size = 6; + lib3ds_chunk_write(&c, io); + } + + if (atmosphere->use_dist_cue) { /*---- LIB3DS_USE_DISTANCE_CUE ----*/ + Lib3dsChunk c; + c.chunk = CHK_USE_V_GRADIENT; + c.size = 6; + lib3ds_chunk_write(&c, io); + } +} + + diff --git a/src/osgPlugins/3ds/lib3ds/lib3ds_background.c b/src/osgPlugins/3ds/lib3ds/lib3ds_background.c index c5930c462..3e33517d5 100644 --- a/src/osgPlugins/3ds/lib3ds/lib3ds_background.c +++ b/src/osgPlugins/3ds/lib3ds/lib3ds_background.c @@ -1,213 +1,213 @@ -/* - Copyright (C) 1996-2008 by Jan Eric Kyprianidis - 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. - - Thisprogram 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, see . -*/ -#include "lib3ds_impl.h" - - -static void -solid_bgnd_read(Lib3dsBackground *background, Lib3dsIo *io) { - Lib3dsChunk c; - uint16_t chunk; - int have_lin = FALSE; - - lib3ds_chunk_read_start(&c, CHK_SOLID_BGND, io); - - while ((chunk = lib3ds_chunk_read_next(&c, io)) != 0) { - switch (chunk) { - case CHK_LIN_COLOR_F: - lib3ds_io_read_rgb(io, background->solid_color); - have_lin = TRUE; - break; - - case CHK_COLOR_F: - lib3ds_io_read_rgb(io, background->solid_color); - break; - - default: - lib3ds_chunk_unknown(chunk, io); - } - } - - lib3ds_chunk_read_end(&c, io); -} - - -static void -v_gradient_read(Lib3dsBackground *background, Lib3dsIo *io) { - Lib3dsChunk c; - uint16_t chunk; - int index[2]; - float col[2][3][3]; - int have_lin = 0; - - lib3ds_chunk_read_start(&c, CHK_V_GRADIENT, io); - - 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 CHK_COLOR_F: - lib3ds_io_read_rgb(io, col[0][index[0]]); - index[0]++; - break; - - case CHK_LIN_COLOR_F: - lib3ds_io_read_rgb(io, col[1][index[1]]); - index[1]++; - have_lin = 1; - break; - - default: - lib3ds_chunk_unknown(chunk, io); - } - } - { - 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); -} - - -void -lib3ds_background_read(Lib3dsBackground *background, Lib3dsIo *io) { - Lib3dsChunk c; - - lib3ds_chunk_read(&c, io); - switch (c.chunk) { - case CHK_BIT_MAP: { - lib3ds_io_read_string(io, background->bitmap_name, 64); - break; - } - - case CHK_SOLID_BGND: { - lib3ds_chunk_read_reset(&c, io); - solid_bgnd_read(background, io); - break; - } - - case CHK_V_GRADIENT: { - lib3ds_chunk_read_reset(&c, io); - v_gradient_read(background, io); - break; - } - - case CHK_USE_BIT_MAP: { - background->use_bitmap = TRUE; - break; - } - - case CHK_USE_SOLID_BGND: { - background->use_solid = TRUE; - break; - } - - case CHK_USE_V_GRADIENT: { - background->use_gradient = TRUE; - break; - } - } -} - - -static void -colorf_write(float rgb[3], Lib3dsIo *io) { - Lib3dsChunk c; - - c.chunk = CHK_COLOR_F; - c.size = 18; - lib3ds_chunk_write(&c, io); - lib3ds_io_write_rgb(io, rgb); - - c.chunk = CHK_LIN_COLOR_F; - c.size = 18; - lib3ds_chunk_write(&c, io); - lib3ds_io_write_rgb(io, rgb); -} - - -static int -colorf_defined(float rgb[3]) { - int i; - for (i = 0; i < 3; ++i) { - if (fabs(rgb[i]) > LIB3DS_EPSILON) { - break; - } - } - return(i < 3); -} - - -void -lib3ds_background_write(Lib3dsBackground *background, Lib3dsIo *io) { - if (strlen(background->bitmap_name)) { /*---- LIB3DS_BIT_MAP ----*/ - Lib3dsChunk c; - c.chunk = CHK_BIT_MAP; - c.size = 6 + 1 + (uint32_t)strlen(background->bitmap_name); - lib3ds_chunk_write(&c, io); - lib3ds_io_write_string(io, background->bitmap_name); - } - - if (colorf_defined(background->solid_color)) { /*---- LIB3DS_SOLID_BGND ----*/ - Lib3dsChunk c; - c.chunk = CHK_SOLID_BGND; - c.size = 42; - lib3ds_chunk_write(&c, io); - colorf_write(background->solid_color, io); - } - - if (colorf_defined(background->gradient_top) || - colorf_defined(background->gradient_middle) || - colorf_defined(background->gradient_bottom)) { /*---- LIB3DS_V_GRADIENT ----*/ - Lib3dsChunk c; - c.chunk = CHK_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->use_bitmap) { /*---- LIB3DS_USE_BIT_MAP ----*/ - Lib3dsChunk c; - c.chunk = CHK_USE_BIT_MAP; - c.size = 6; - lib3ds_chunk_write(&c, io); - } - - if (background->use_solid) { /*---- LIB3DS_USE_SOLID_BGND ----*/ - Lib3dsChunk c; - c.chunk = CHK_USE_SOLID_BGND; - c.size = 6; - lib3ds_chunk_write(&c, io); - } - - if (background->use_gradient) { /*---- LIB3DS_USE_V_GRADIENT ----*/ - Lib3dsChunk c; - c.chunk = CHK_USE_V_GRADIENT; - c.size = 6; - lib3ds_chunk_write(&c, io); - } -} - +/* + Copyright (C) 1996-2008 by Jan Eric Kyprianidis + 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. + + Thisprogram 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, see . +*/ +#include "lib3ds_impl.h" + + +static void +solid_bgnd_read(Lib3dsBackground *background, Lib3dsIo *io) { + Lib3dsChunk c; + uint16_t chunk; + int have_lin = FALSE; + + lib3ds_chunk_read_start(&c, CHK_SOLID_BGND, io); + + while ((chunk = lib3ds_chunk_read_next(&c, io)) != 0) { + switch (chunk) { + case CHK_LIN_COLOR_F: + lib3ds_io_read_rgb(io, background->solid_color); + have_lin = TRUE; + break; + + case CHK_COLOR_F: + lib3ds_io_read_rgb(io, background->solid_color); + break; + + default: + lib3ds_chunk_unknown(chunk, io); + } + } + + lib3ds_chunk_read_end(&c, io); +} + + +static void +v_gradient_read(Lib3dsBackground *background, Lib3dsIo *io) { + Lib3dsChunk c; + uint16_t chunk; + int index[2]; + float col[2][3][3]; + int have_lin = 0; + + lib3ds_chunk_read_start(&c, CHK_V_GRADIENT, io); + + 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 CHK_COLOR_F: + lib3ds_io_read_rgb(io, col[0][index[0]]); + index[0]++; + break; + + case CHK_LIN_COLOR_F: + lib3ds_io_read_rgb(io, col[1][index[1]]); + index[1]++; + have_lin = 1; + break; + + default: + lib3ds_chunk_unknown(chunk, io); + } + } + { + 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); +} + + +void +lib3ds_background_read(Lib3dsBackground *background, Lib3dsIo *io) { + Lib3dsChunk c; + + lib3ds_chunk_read(&c, io); + switch (c.chunk) { + case CHK_BIT_MAP: { + lib3ds_io_read_string(io, background->bitmap_name, 64); + break; + } + + case CHK_SOLID_BGND: { + lib3ds_chunk_read_reset(&c, io); + solid_bgnd_read(background, io); + break; + } + + case CHK_V_GRADIENT: { + lib3ds_chunk_read_reset(&c, io); + v_gradient_read(background, io); + break; + } + + case CHK_USE_BIT_MAP: { + background->use_bitmap = TRUE; + break; + } + + case CHK_USE_SOLID_BGND: { + background->use_solid = TRUE; + break; + } + + case CHK_USE_V_GRADIENT: { + background->use_gradient = TRUE; + break; + } + } +} + + +static void +colorf_write(float rgb[3], Lib3dsIo *io) { + Lib3dsChunk c; + + c.chunk = CHK_COLOR_F; + c.size = 18; + lib3ds_chunk_write(&c, io); + lib3ds_io_write_rgb(io, rgb); + + c.chunk = CHK_LIN_COLOR_F; + c.size = 18; + lib3ds_chunk_write(&c, io); + lib3ds_io_write_rgb(io, rgb); +} + + +static int +colorf_defined(float rgb[3]) { + int i; + for (i = 0; i < 3; ++i) { + if (fabs(rgb[i]) > LIB3DS_EPSILON) { + break; + } + } + return(i < 3); +} + + +void +lib3ds_background_write(Lib3dsBackground *background, Lib3dsIo *io) { + if (strlen(background->bitmap_name)) { /*---- LIB3DS_BIT_MAP ----*/ + Lib3dsChunk c; + c.chunk = CHK_BIT_MAP; + c.size = 6 + 1 + (uint32_t)strlen(background->bitmap_name); + lib3ds_chunk_write(&c, io); + lib3ds_io_write_string(io, background->bitmap_name); + } + + if (colorf_defined(background->solid_color)) { /*---- LIB3DS_SOLID_BGND ----*/ + Lib3dsChunk c; + c.chunk = CHK_SOLID_BGND; + c.size = 42; + lib3ds_chunk_write(&c, io); + colorf_write(background->solid_color, io); + } + + if (colorf_defined(background->gradient_top) || + colorf_defined(background->gradient_middle) || + colorf_defined(background->gradient_bottom)) { /*---- LIB3DS_V_GRADIENT ----*/ + Lib3dsChunk c; + c.chunk = CHK_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->use_bitmap) { /*---- LIB3DS_USE_BIT_MAP ----*/ + Lib3dsChunk c; + c.chunk = CHK_USE_BIT_MAP; + c.size = 6; + lib3ds_chunk_write(&c, io); + } + + if (background->use_solid) { /*---- LIB3DS_USE_SOLID_BGND ----*/ + Lib3dsChunk c; + c.chunk = CHK_USE_SOLID_BGND; + c.size = 6; + lib3ds_chunk_write(&c, io); + } + + if (background->use_gradient) { /*---- LIB3DS_USE_V_GRADIENT ----*/ + Lib3dsChunk c; + c.chunk = CHK_USE_V_GRADIENT; + c.size = 6; + lib3ds_chunk_write(&c, io); + } +} + diff --git a/src/osgPlugins/3ds/lib3ds/lib3ds_camera.c b/src/osgPlugins/3ds/lib3ds/lib3ds_camera.c index 62f84cdaa..24a753c33 100644 --- a/src/osgPlugins/3ds/lib3ds/lib3ds_camera.c +++ b/src/osgPlugins/3ds/lib3ds/lib3ds_camera.c @@ -1,165 +1,165 @@ -/* - Copyright (C) 1996-2008 by Jan Eric Kyprianidis - 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. - - Thisprogram 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, see . -*/ -#include "lib3ds_impl.h" - - -/*! - * 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. - */ -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. - */ -void -lib3ds_camera_free(Lib3dsCamera *camera) { - memset(camera, 0, sizeof(Lib3dsCamera)); - free(camera); -} - - -/*! - * 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. - * - * \see lib3ds_file_read - */ -void -lib3ds_camera_read(Lib3dsCamera *camera, Lib3dsIo *io) { - Lib3dsChunk c; - uint16_t chunk; - - lib3ds_chunk_read_start(&c, CHK_N_CAMERA, io); - - { - 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 CHK_CAM_SEE_CONE: { - camera->see_cone = TRUE; - } - break; - - case CHK_CAM_RANGES: { - camera->near_range = lib3ds_io_read_float(io); - camera->far_range = lib3ds_io_read_float(io); - } - break; - - default: - lib3ds_chunk_unknown(chunk, io); - } - } - - lib3ds_chunk_read_end(&c, io); -} - - -/*! - * 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. - * - * \see lib3ds_file_write - */ -void -lib3ds_camera_write(Lib3dsCamera *camera, Lib3dsIo *io) { - Lib3dsChunk c; - - c.chunk = CHK_N_CAMERA; - lib3ds_chunk_write_start(&c, io); - - 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 = CHK_CAM_SEE_CONE; - c.size = 6; - lib3ds_chunk_write(&c, io); - } - { - Lib3dsChunk c; - c.chunk = CHK_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); - } - - lib3ds_chunk_write_end(&c, io); -} - +/* + Copyright (C) 1996-2008 by Jan Eric Kyprianidis + 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. + + Thisprogram 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, see . +*/ +#include "lib3ds_impl.h" + + +/*! + * 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. + */ +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. + */ +void +lib3ds_camera_free(Lib3dsCamera *camera) { + memset(camera, 0, sizeof(Lib3dsCamera)); + free(camera); +} + + +/*! + * 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. + * + * \see lib3ds_file_read + */ +void +lib3ds_camera_read(Lib3dsCamera *camera, Lib3dsIo *io) { + Lib3dsChunk c; + uint16_t chunk; + + lib3ds_chunk_read_start(&c, CHK_N_CAMERA, io); + + { + 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 CHK_CAM_SEE_CONE: { + camera->see_cone = TRUE; + } + break; + + case CHK_CAM_RANGES: { + camera->near_range = lib3ds_io_read_float(io); + camera->far_range = lib3ds_io_read_float(io); + } + break; + + default: + lib3ds_chunk_unknown(chunk, io); + } + } + + lib3ds_chunk_read_end(&c, io); +} + + +/*! + * 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. + * + * \see lib3ds_file_write + */ +void +lib3ds_camera_write(Lib3dsCamera *camera, Lib3dsIo *io) { + Lib3dsChunk c; + + c.chunk = CHK_N_CAMERA; + lib3ds_chunk_write_start(&c, io); + + 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 = CHK_CAM_SEE_CONE; + c.size = 6; + lib3ds_chunk_write(&c, io); + } + { + Lib3dsChunk c; + c.chunk = CHK_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); + } + + lib3ds_chunk_write_end(&c, io); +} + diff --git a/src/osgPlugins/3ds/lib3ds/lib3ds_chunk.c b/src/osgPlugins/3ds/lib3ds/lib3ds_chunk.c index 2fba72083..c95c04cab 100644 --- a/src/osgPlugins/3ds/lib3ds/lib3ds_chunk.c +++ b/src/osgPlugins/3ds/lib3ds/lib3ds_chunk.c @@ -1,146 +1,146 @@ -/* - Copyright (C) 1996-2008 by Jan Eric Kyprianidis - 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. - - Thisprogram 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, see . -*/ -#include "lib3ds_impl.h" - - -/*#define LIB3DS_CHUNK_DEBUG*/ -/*#define LIB3DS_CHUNK_WARNING*/ - - -/*! - * 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. - */ -void -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 (c->size < 6) { - lib3ds_io_log(io, LIB3DS_LOG_ERROR, "Invalid chunk header."); - } - -} - - -void -lib3ds_chunk_read_start(Lib3dsChunk *c, uint16_t chunk, Lib3dsIo *io) { - assert(c); - assert(io); - lib3ds_chunk_read(c, io); - if ((chunk != 0) && (c->chunk != chunk)) { - lib3ds_io_log(io, LIB3DS_LOG_ERROR, "Unexpected chunk found."); - } - ((Lib3dsIoImpl*)io->impl)->log_indent++; -} - - -void -lib3ds_chunk_read_tell(Lib3dsChunk *c, Lib3dsIo *io) { - c->cur = lib3ds_io_tell(io); -} - - -uint16_t -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); - c->cur += d.size; - - if (io->log_func) { - lib3ds_io_log(io, LIB3DS_LOG_INFO, "%s (0x%X) size=%lu", lib3ds_chunk_name(d.chunk), d.chunk, d.size); - } - - return d.chunk; -} - - -void -lib3ds_chunk_read_reset(Lib3dsChunk *c, Lib3dsIo *io) { - lib3ds_io_seek(io, -6, LIB3DS_SEEK_CUR); -} - - -void -lib3ds_chunk_read_end(Lib3dsChunk *c, Lib3dsIo *io) { - ((Lib3dsIoImpl*)io->impl)->log_indent--; - lib3ds_io_seek(io, c->end, LIB3DS_SEEK_SET); -} - - -/*! - * 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. - */ -void -lib3ds_chunk_write(Lib3dsChunk *c, Lib3dsIo *io) { - assert(c); - lib3ds_io_write_word(io, c->chunk); - lib3ds_io_write_dword(io, c->size); -} - - -void -lib3ds_chunk_write_start(Lib3dsChunk *c, Lib3dsIo *io) { - assert(c); - c->size = 0; - c->cur = lib3ds_io_tell(io); - lib3ds_io_write_word(io, c->chunk); - lib3ds_io_write_dword(io, c->size); -} - - -void -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); - lib3ds_io_write_dword(io, c->size); - c->cur += c->size; - lib3ds_io_seek(io, c->cur, LIB3DS_SEEK_SET); -} - - -void -lib3ds_chunk_unknown(uint16_t chunk, Lib3dsIo *io) { - if (io->log_func) { - lib3ds_io_log(io, LIB3DS_LOG_WARN, "Unknown Chunk: %s (0x%X)", lib3ds_chunk_name(chunk), chunk); - } -} - - +/* + Copyright (C) 1996-2008 by Jan Eric Kyprianidis + 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. + + Thisprogram 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, see . +*/ +#include "lib3ds_impl.h" + + +/*#define LIB3DS_CHUNK_DEBUG*/ +/*#define LIB3DS_CHUNK_WARNING*/ + + +/*! + * 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. + */ +void +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 (c->size < 6) { + lib3ds_io_log(io, LIB3DS_LOG_ERROR, "Invalid chunk header."); + } + +} + + +void +lib3ds_chunk_read_start(Lib3dsChunk *c, uint16_t chunk, Lib3dsIo *io) { + assert(c); + assert(io); + lib3ds_chunk_read(c, io); + if ((chunk != 0) && (c->chunk != chunk)) { + lib3ds_io_log(io, LIB3DS_LOG_ERROR, "Unexpected chunk found."); + } + ((Lib3dsIoImpl*)io->impl)->log_indent++; +} + + +void +lib3ds_chunk_read_tell(Lib3dsChunk *c, Lib3dsIo *io) { + c->cur = lib3ds_io_tell(io); +} + + +uint16_t +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); + c->cur += d.size; + + if (io->log_func) { + lib3ds_io_log(io, LIB3DS_LOG_INFO, "%s (0x%X) size=%lu", lib3ds_chunk_name(d.chunk), d.chunk, d.size); + } + + return d.chunk; +} + + +void +lib3ds_chunk_read_reset(Lib3dsChunk *c, Lib3dsIo *io) { + lib3ds_io_seek(io, -6, LIB3DS_SEEK_CUR); +} + + +void +lib3ds_chunk_read_end(Lib3dsChunk *c, Lib3dsIo *io) { + ((Lib3dsIoImpl*)io->impl)->log_indent--; + lib3ds_io_seek(io, c->end, LIB3DS_SEEK_SET); +} + + +/*! + * 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. + */ +void +lib3ds_chunk_write(Lib3dsChunk *c, Lib3dsIo *io) { + assert(c); + lib3ds_io_write_word(io, c->chunk); + lib3ds_io_write_dword(io, c->size); +} + + +void +lib3ds_chunk_write_start(Lib3dsChunk *c, Lib3dsIo *io) { + assert(c); + c->size = 0; + c->cur = lib3ds_io_tell(io); + lib3ds_io_write_word(io, c->chunk); + lib3ds_io_write_dword(io, c->size); +} + + +void +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); + lib3ds_io_write_dword(io, c->size); + c->cur += c->size; + lib3ds_io_seek(io, c->cur, LIB3DS_SEEK_SET); +} + + +void +lib3ds_chunk_unknown(uint16_t chunk, Lib3dsIo *io) { + if (io->log_func) { + lib3ds_io_log(io, LIB3DS_LOG_WARN, "Unknown Chunk: %s (0x%X)", lib3ds_chunk_name(chunk), chunk); + } +} + + diff --git a/src/osgPlugins/3ds/lib3ds/lib3ds_chunktable.c b/src/osgPlugins/3ds/lib3ds/lib3ds_chunktable.c index bbfe7a254..dcf13084e 100644 --- a/src/osgPlugins/3ds/lib3ds/lib3ds_chunktable.c +++ b/src/osgPlugins/3ds/lib3ds/lib3ds_chunktable.c @@ -1,259 +1,259 @@ -/* - Copyright (C) 1996-2008 by Jan Eric Kyprianidis - 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. - - Thisprogram 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, see . -*/ -#include "lib3ds_impl.h" - - -typedef struct Lib3dsChunkTable { - uint32_t chunk; - const char* name; -} Lib3dsChunkTable; - - -static Lib3dsChunkTable lib3ds_chunk_table[] = { - {CHK_NULL_CHUNK, "NULL_CHUNK"}, - {CHK_M3DMAGIC, "M3DMAGIC"}, - {CHK_SMAGIC, "SMAGIC"}, - {CHK_LMAGIC, "LMAGIC"}, - {CHK_MLIBMAGIC, "MLIBMAGIC"}, - {CHK_MATMAGIC, "MATMAGIC"}, - {CHK_CMAGIC, "CMAGIC"}, - {CHK_M3D_VERSION, "M3D_VERSION"}, - {CHK_M3D_KFVERSION, "M3D_KFVERSION"}, - {CHK_COLOR_F, "COLOR_F"}, - {CHK_COLOR_24, "COLOR_24"}, - {CHK_LIN_COLOR_24, "LIN_COLOR_24"}, - {CHK_LIN_COLOR_F, "LIN_COLOR_F"}, - {CHK_INT_PERCENTAGE, "INT_PERCENTAGE"}, - {CHK_FLOAT_PERCENTAGE, "FLOAT_PERCENTAGE"}, - {CHK_MDATA, "MDATA"}, - {CHK_MESH_VERSION, "MESH_VERSION"}, - {CHK_MASTER_SCALE, "MASTER_SCALE"}, - {CHK_LO_SHADOW_BIAS, "LO_SHADOW_BIAS"}, - {CHK_HI_SHADOW_BIAS, "HI_SHADOW_BIAS"}, - {CHK_SHADOW_MAP_SIZE, "SHADOW_MAP_SIZE"}, - {CHK_SHADOW_SAMPLES, "SHADOW_SAMPLES"}, - {CHK_SHADOW_RANGE, "SHADOW_RANGE"}, - {CHK_SHADOW_FILTER, "SHADOW_FILTER"}, - {CHK_RAY_BIAS, "RAY_BIAS"}, - {CHK_O_CONSTS, "O_CONSTS"}, - {CHK_AMBIENT_LIGHT, "AMBIENT_LIGHT"}, - {CHK_BIT_MAP, "BIT_MAP"}, - {CHK_SOLID_BGND, "SOLID_BGND"}, - {CHK_V_GRADIENT, "V_GRADIENT"}, - {CHK_USE_BIT_MAP, "USE_BIT_MAP"}, - {CHK_USE_SOLID_BGND, "USE_SOLID_BGND"}, - {CHK_USE_V_GRADIENT, "USE_V_GRADIENT"}, - {CHK_FOG, "FOG"}, - {CHK_FOG_BGND, "FOG_BGND"}, - {CHK_LAYER_FOG, "LAYER_FOG"}, - {CHK_DISTANCE_CUE, "DISTANCE_CUE"}, - {CHK_DCUE_BGND, "DCUE_BGND"}, - {CHK_USE_FOG, "USE_FOG"}, - {CHK_USE_LAYER_FOG, "USE_LAYER_FOG"}, - {CHK_USE_DISTANCE_CUE, "USE_DISTANCE_CUE"}, - {CHK_MAT_ENTRY, "MAT_ENTRY"}, - {CHK_MAT_NAME, "MAT_NAME"}, - {CHK_MAT_AMBIENT, "MAT_AMBIENT"}, - {CHK_MAT_DIFFUSE, "MAT_DIFFUSE"}, - {CHK_MAT_SPECULAR, "MAT_SPECULAR"}, - {CHK_MAT_SHININESS, "MAT_SHININESS"}, - {CHK_MAT_SHIN2PCT, "MAT_SHIN2PCT"}, - {CHK_MAT_TRANSPARENCY, "MAT_TRANSPARENCY"}, - {CHK_MAT_XPFALL, "MAT_XPFALL"}, - {CHK_MAT_USE_XPFALL, "MAT_USE_XPFALL"}, - {CHK_MAT_REFBLUR, "MAT_REFBLUR"}, - {CHK_MAT_SHADING, "MAT_SHADING"}, - {CHK_MAT_USE_REFBLUR, "MAT_USE_REFBLUR"}, - {CHK_MAT_SELF_ILLUM, "MAT_SELF_ILLUM"}, - {CHK_MAT_TWO_SIDE, "MAT_TWO_SIDE"}, - {CHK_MAT_DECAL, "MAT_DECAL"}, - {CHK_MAT_ADDITIVE, "MAT_ADDITIVE"}, - {CHK_MAT_SELF_ILPCT, "MAT_SELF_ILPCT"}, - {CHK_MAT_WIRE, "MAT_WIRE"}, - {CHK_MAT_FACEMAP, "MAT_FACEMAP"}, - {CHK_MAT_PHONGSOFT, "MAT_PHONGSOFT"}, - {CHK_MAT_WIREABS, "MAT_WIREABS"}, - {CHK_MAT_WIRE_SIZE, "MAT_WIRE_SIZE"}, - {CHK_MAT_TEXMAP, "MAT_TEXMAP"}, - {CHK_MAT_SXP_TEXT_DATA, "MAT_SXP_TEXT_DATA"}, - {CHK_MAT_TEXMASK, "MAT_TEXMASK"}, - {CHK_MAT_SXP_TEXTMASK_DATA, "MAT_SXP_TEXTMASK_DATA"}, - {CHK_MAT_TEX2MAP, "MAT_TEX2MAP"}, - {CHK_MAT_SXP_TEXT2_DATA, "MAT_SXP_TEXT2_DATA"}, - {CHK_MAT_TEX2MASK, "MAT_TEX2MASK"}, - {CHK_MAT_SXP_TEXT2MASK_DATA, "MAT_SXP_TEXT2MASK_DATA"}, - {CHK_MAT_OPACMAP, "MAT_OPACMAP"}, - {CHK_MAT_SXP_OPAC_DATA, "MAT_SXP_OPAC_DATA"}, - {CHK_MAT_OPACMASK, "MAT_OPACMASK"}, - {CHK_MAT_SXP_OPACMASK_DATA, "MAT_SXP_OPACMASK_DATA"}, - {CHK_MAT_BUMPMAP, "MAT_BUMPMAP"}, - {CHK_MAT_SXP_BUMP_DATA, "MAT_SXP_BUMP_DATA"}, - {CHK_MAT_BUMPMASK, "MAT_BUMPMASK"}, - {CHK_MAT_SXP_BUMPMASK_DATA, "MAT_SXP_BUMPMASK_DATA"}, - {CHK_MAT_SPECMAP, "MAT_SPECMAP"}, - {CHK_MAT_SXP_SPEC_DATA, "MAT_SXP_SPEC_DATA"}, - {CHK_MAT_SPECMASK, "MAT_SPECMASK"}, - {CHK_MAT_SXP_SPECMASK_DATA, "MAT_SXP_SPECMASK_DATA"}, - {CHK_MAT_SHINMAP, "MAT_SHINMAP"}, - {CHK_MAT_SXP_SHIN_DATA, "MAT_SXP_SHIN_DATA"}, - {CHK_MAT_SHINMASK, "MAT_SHINMASK"}, - {CHK_MAT_SXP_SHINMASK_DATA, "MAT_SXP_SHINMASK_DATA"}, - {CHK_MAT_SELFIMAP, "MAT_SELFIMAP"}, - {CHK_MAT_SXP_SELFI_DATA, "MAT_SXP_SELFI_DATA"}, - {CHK_MAT_SELFIMASK, "MAT_SELFIMASK"}, - {CHK_MAT_SXP_SELFIMASK_DATA, "MAT_SXP_SELFIMASK_DATA"}, - {CHK_MAT_REFLMAP, "MAT_REFLMAP"}, - {CHK_MAT_REFLMASK, "MAT_REFLMASK"}, - {CHK_MAT_SXP_REFLMASK_DATA, "MAT_SXP_REFLMASK_DATA"}, - {CHK_MAT_ACUBIC, "MAT_ACUBIC"}, - {CHK_MAT_MAPNAME, "MAT_MAPNAME"}, - {CHK_MAT_MAP_TILING, "MAT_MAP_TILING"}, - {CHK_MAT_MAP_TEXBLUR, "MAT_MAP_TEXBLUR"}, - {CHK_MAT_MAP_USCALE, "MAT_MAP_USCALE"}, - {CHK_MAT_MAP_VSCALE, "MAT_MAP_VSCALE"}, - {CHK_MAT_MAP_UOFFSET, "MAT_MAP_UOFFSET"}, - {CHK_MAT_MAP_VOFFSET, "MAT_MAP_VOFFSET"}, - {CHK_MAT_MAP_ANG, "MAT_MAP_ANG"}, - {CHK_MAT_MAP_COL1, "MAT_MAP_COL1"}, - {CHK_MAT_MAP_COL2, "MAT_MAP_COL2"}, - {CHK_MAT_MAP_RCOL, "MAT_MAP_RCOL"}, - {CHK_MAT_MAP_GCOL, "MAT_MAP_GCOL"}, - {CHK_MAT_MAP_BCOL, "MAT_MAP_BCOL"}, - {CHK_NAMED_OBJECT, "NAMED_OBJECT"}, - {CHK_N_DIRECT_LIGHT, "N_DIRECT_LIGHT"}, - {CHK_DL_OFF, "DL_OFF"}, - {CHK_DL_OUTER_RANGE, "DL_OUTER_RANGE"}, - {CHK_DL_INNER_RANGE, "DL_INNER_RANGE"}, - {CHK_DL_MULTIPLIER, "DL_MULTIPLIER"}, - {CHK_DL_EXCLUDE, "DL_EXCLUDE"}, - {CHK_DL_ATTENUATE, "DL_ATTENUATE"}, - {CHK_DL_SPOTLIGHT, "DL_SPOTLIGHT"}, - {CHK_DL_SPOT_ROLL, "DL_SPOT_ROLL"}, - {CHK_DL_SHADOWED, "DL_SHADOWED"}, - {CHK_DL_LOCAL_SHADOW2, "DL_LOCAL_SHADOW2"}, - {CHK_DL_SEE_CONE, "DL_SEE_CONE"}, - {CHK_DL_SPOT_RECTANGULAR, "DL_SPOT_RECTANGULAR"}, - {CHK_DL_SPOT_ASPECT, "DL_SPOT_ASPECT"}, - {CHK_DL_SPOT_PROJECTOR, "DL_SPOT_PROJECTOR"}, - {CHK_DL_SPOT_OVERSHOOT, "DL_SPOT_OVERSHOOT"}, - {CHK_DL_RAY_BIAS, "DL_RAY_BIAS"}, - {CHK_DL_RAYSHAD, "DL_RAYSHAD"}, - {CHK_N_CAMERA, "N_CAMERA"}, - {CHK_CAM_SEE_CONE, "CAM_SEE_CONE"}, - {CHK_CAM_RANGES, "CAM_RANGES"}, - {CHK_OBJ_HIDDEN, "OBJ_HIDDEN"}, - {CHK_OBJ_VIS_LOFTER, "OBJ_VIS_LOFTER"}, - {CHK_OBJ_DOESNT_CAST, "OBJ_DOESNT_CAST"}, - {CHK_OBJ_DONT_RCVSHADOW, "OBJ_DONT_RCVSHADOW"}, - {CHK_OBJ_MATTE, "OBJ_MATTE"}, - {CHK_OBJ_FAST, "OBJ_FAST"}, - {CHK_OBJ_PROCEDURAL, "OBJ_PROCEDURAL"}, - {CHK_OBJ_FROZEN, "OBJ_FROZEN"}, - {CHK_N_TRI_OBJECT, "N_TRI_OBJECT"}, - {CHK_POINT_ARRAY, "POINT_ARRAY"}, - {CHK_POINT_FLAG_ARRAY, "POINT_FLAG_ARRAY"}, - {CHK_FACE_ARRAY, "FACE_ARRAY"}, - {CHK_MSH_MAT_GROUP, "MSH_MAT_GROUP"}, - {CHK_SMOOTH_GROUP, "SMOOTH_GROUP"}, - {CHK_MSH_BOXMAP, "MSH_BOXMAP"}, - {CHK_TEX_VERTS, "TEX_VERTS"}, - {CHK_MESH_MATRIX, "MESH_MATRIX"}, - {CHK_MESH_COLOR, "MESH_COLOR"}, - {CHK_MESH_TEXTURE_INFO, "MESH_TEXTURE_INFO"}, - {CHK_KFDATA, "KFDATA"}, - {CHK_KFHDR, "KFHDR"}, - {CHK_KFSEG, "KFSEG"}, - {CHK_KFCURTIME, "KFCURTIME"}, - {CHK_AMBIENT_NODE_TAG, "AMBIENT_NODE_TAG"}, - {CHK_OBJECT_NODE_TAG, "OBJECT_NODE_TAG"}, - {CHK_CAMERA_NODE_TAG, "CAMERA_NODE_TAG"}, - {CHK_TARGET_NODE_TAG, "TARGET_NODE_TAG"}, - {CHK_LIGHT_NODE_TAG, "LIGHT_NODE_TAG"}, - {CHK_L_TARGET_NODE_TAG, "L_TARGET_NODE_TAG"}, - {CHK_SPOTLIGHT_NODE_TAG, "SPOTLIGHT_NODE_TAG"}, - {CHK_NODE_ID, "NODE_ID"}, - {CHK_NODE_HDR, "NODE_HDR"}, - {CHK_PIVOT, "PIVOT"}, - {CHK_INSTANCE_NAME, "INSTANCE_NAME"}, - {CHK_MORPH_SMOOTH, "MORPH_SMOOTH"}, - {CHK_BOUNDBOX, "BOUNDBOX"}, - {CHK_POS_TRACK_TAG, "POS_TRACK_TAG"}, - {CHK_COL_TRACK_TAG, "COL_TRACK_TAG"}, - {CHK_ROT_TRACK_TAG, "ROT_TRACK_TAG"}, - {CHK_SCL_TRACK_TAG, "SCL_TRACK_TAG"}, - {CHK_MORPH_TRACK_TAG, "MORPH_TRACK_TAG"}, - {CHK_FOV_TRACK_TAG, "FOV_TRACK_TAG"}, - {CHK_ROLL_TRACK_TAG, "ROLL_TRACK_TAG"}, - {CHK_HOT_TRACK_TAG, "HOT_TRACK_TAG"}, - {CHK_FALL_TRACK_TAG, "FALL_TRACK_TAG"}, - {CHK_HIDE_TRACK_TAG, "HIDE_TRACK_TAG"}, - {CHK_POLY_2D, "POLY_2D"}, - {CHK_SHAPE_OK, "SHAPE_OK"}, - {CHK_SHAPE_NOT_OK, "SHAPE_NOT_OK"}, - {CHK_SHAPE_HOOK, "SHAPE_HOOK"}, - {CHK_PATH_3D, "PATH_3D"}, - {CHK_PATH_MATRIX, "PATH_MATRIX"}, - {CHK_SHAPE_2D, "SHAPE_2D"}, - {CHK_M_SCALE, "M_SCALE"}, - {CHK_M_TWIST, "M_TWIST"}, - {CHK_M_TEETER, "M_TEETER"}, - {CHK_M_FIT, "M_FIT"}, - {CHK_M_BEVEL, "M_BEVEL"}, - {CHK_XZ_CURVE, "XZ_CURVE"}, - {CHK_YZ_CURVE, "YZ_CURVE"}, - {CHK_INTERPCT, "INTERPCT"}, - {CHK_DEFORM_LIMIT, "DEFORM_LIMIT"}, - {CHK_USE_CONTOUR, "USE_CONTOUR"}, - {CHK_USE_TWEEN, "USE_TWEEN"}, - {CHK_USE_SCALE, "USE_SCALE"}, - {CHK_USE_TWIST, "USE_TWIST"}, - {CHK_USE_TEETER, "USE_TEETER"}, - {CHK_USE_FIT, "USE_FIT"}, - {CHK_USE_BEVEL, "USE_BEVEL"}, - {CHK_DEFAULT_VIEW, "DEFAULT_VIEW"}, - {CHK_VIEW_TOP, "VIEW_TOP"}, - {CHK_VIEW_BOTTOM, "VIEW_BOTTOM"}, - {CHK_VIEW_LEFT, "VIEW_LEFT"}, - {CHK_VIEW_RIGHT, "VIEW_RIGHT"}, - {CHK_VIEW_FRONT, "VIEW_FRONT"}, - {CHK_VIEW_BACK, "VIEW_BACK"}, - {CHK_VIEW_USER, "VIEW_USER"}, - {CHK_VIEW_CAMERA, "VIEW_CAMERA"}, - {CHK_VIEW_WINDOW, "VIEW_WINDOW"}, - {CHK_VIEWPORT_LAYOUT_OLD, "VIEWPORT_LAYOUT_OLD"}, - {CHK_VIEWPORT_DATA_OLD, "VIEWPORT_DATA_OLD"}, - {CHK_VIEWPORT_LAYOUT, "VIEWPORT_LAYOUT"}, - {CHK_VIEWPORT_DATA, "VIEWPORT_DATA"}, - {CHK_VIEWPORT_DATA_3, "VIEWPORT_DATA_3"}, - {CHK_VIEWPORT_SIZE, "VIEWPORT_SIZE"}, - {CHK_NETWORK_VIEW, "NETWORK_VIEW"}, - {0, 0} -}; - - -const char* -lib3ds_chunk_name(uint16_t chunk) { - Lib3dsChunkTable *p; - - for (p = lib3ds_chunk_table; p->name != 0; ++p) { - if (p->chunk == chunk) { - return(p->name); - } - } - return("***UNKNOWN***"); -} +/* + Copyright (C) 1996-2008 by Jan Eric Kyprianidis + 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. + + Thisprogram 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, see . +*/ +#include "lib3ds_impl.h" + + +typedef struct Lib3dsChunkTable { + uint32_t chunk; + const char* name; +} Lib3dsChunkTable; + + +static Lib3dsChunkTable lib3ds_chunk_table[] = { + {CHK_NULL_CHUNK, "NULL_CHUNK"}, + {CHK_M3DMAGIC, "M3DMAGIC"}, + {CHK_SMAGIC, "SMAGIC"}, + {CHK_LMAGIC, "LMAGIC"}, + {CHK_MLIBMAGIC, "MLIBMAGIC"}, + {CHK_MATMAGIC, "MATMAGIC"}, + {CHK_CMAGIC, "CMAGIC"}, + {CHK_M3D_VERSION, "M3D_VERSION"}, + {CHK_M3D_KFVERSION, "M3D_KFVERSION"}, + {CHK_COLOR_F, "COLOR_F"}, + {CHK_COLOR_24, "COLOR_24"}, + {CHK_LIN_COLOR_24, "LIN_COLOR_24"}, + {CHK_LIN_COLOR_F, "LIN_COLOR_F"}, + {CHK_INT_PERCENTAGE, "INT_PERCENTAGE"}, + {CHK_FLOAT_PERCENTAGE, "FLOAT_PERCENTAGE"}, + {CHK_MDATA, "MDATA"}, + {CHK_MESH_VERSION, "MESH_VERSION"}, + {CHK_MASTER_SCALE, "MASTER_SCALE"}, + {CHK_LO_SHADOW_BIAS, "LO_SHADOW_BIAS"}, + {CHK_HI_SHADOW_BIAS, "HI_SHADOW_BIAS"}, + {CHK_SHADOW_MAP_SIZE, "SHADOW_MAP_SIZE"}, + {CHK_SHADOW_SAMPLES, "SHADOW_SAMPLES"}, + {CHK_SHADOW_RANGE, "SHADOW_RANGE"}, + {CHK_SHADOW_FILTER, "SHADOW_FILTER"}, + {CHK_RAY_BIAS, "RAY_BIAS"}, + {CHK_O_CONSTS, "O_CONSTS"}, + {CHK_AMBIENT_LIGHT, "AMBIENT_LIGHT"}, + {CHK_BIT_MAP, "BIT_MAP"}, + {CHK_SOLID_BGND, "SOLID_BGND"}, + {CHK_V_GRADIENT, "V_GRADIENT"}, + {CHK_USE_BIT_MAP, "USE_BIT_MAP"}, + {CHK_USE_SOLID_BGND, "USE_SOLID_BGND"}, + {CHK_USE_V_GRADIENT, "USE_V_GRADIENT"}, + {CHK_FOG, "FOG"}, + {CHK_FOG_BGND, "FOG_BGND"}, + {CHK_LAYER_FOG, "LAYER_FOG"}, + {CHK_DISTANCE_CUE, "DISTANCE_CUE"}, + {CHK_DCUE_BGND, "DCUE_BGND"}, + {CHK_USE_FOG, "USE_FOG"}, + {CHK_USE_LAYER_FOG, "USE_LAYER_FOG"}, + {CHK_USE_DISTANCE_CUE, "USE_DISTANCE_CUE"}, + {CHK_MAT_ENTRY, "MAT_ENTRY"}, + {CHK_MAT_NAME, "MAT_NAME"}, + {CHK_MAT_AMBIENT, "MAT_AMBIENT"}, + {CHK_MAT_DIFFUSE, "MAT_DIFFUSE"}, + {CHK_MAT_SPECULAR, "MAT_SPECULAR"}, + {CHK_MAT_SHININESS, "MAT_SHININESS"}, + {CHK_MAT_SHIN2PCT, "MAT_SHIN2PCT"}, + {CHK_MAT_TRANSPARENCY, "MAT_TRANSPARENCY"}, + {CHK_MAT_XPFALL, "MAT_XPFALL"}, + {CHK_MAT_USE_XPFALL, "MAT_USE_XPFALL"}, + {CHK_MAT_REFBLUR, "MAT_REFBLUR"}, + {CHK_MAT_SHADING, "MAT_SHADING"}, + {CHK_MAT_USE_REFBLUR, "MAT_USE_REFBLUR"}, + {CHK_MAT_SELF_ILLUM, "MAT_SELF_ILLUM"}, + {CHK_MAT_TWO_SIDE, "MAT_TWO_SIDE"}, + {CHK_MAT_DECAL, "MAT_DECAL"}, + {CHK_MAT_ADDITIVE, "MAT_ADDITIVE"}, + {CHK_MAT_SELF_ILPCT, "MAT_SELF_ILPCT"}, + {CHK_MAT_WIRE, "MAT_WIRE"}, + {CHK_MAT_FACEMAP, "MAT_FACEMAP"}, + {CHK_MAT_PHONGSOFT, "MAT_PHONGSOFT"}, + {CHK_MAT_WIREABS, "MAT_WIREABS"}, + {CHK_MAT_WIRE_SIZE, "MAT_WIRE_SIZE"}, + {CHK_MAT_TEXMAP, "MAT_TEXMAP"}, + {CHK_MAT_SXP_TEXT_DATA, "MAT_SXP_TEXT_DATA"}, + {CHK_MAT_TEXMASK, "MAT_TEXMASK"}, + {CHK_MAT_SXP_TEXTMASK_DATA, "MAT_SXP_TEXTMASK_DATA"}, + {CHK_MAT_TEX2MAP, "MAT_TEX2MAP"}, + {CHK_MAT_SXP_TEXT2_DATA, "MAT_SXP_TEXT2_DATA"}, + {CHK_MAT_TEX2MASK, "MAT_TEX2MASK"}, + {CHK_MAT_SXP_TEXT2MASK_DATA, "MAT_SXP_TEXT2MASK_DATA"}, + {CHK_MAT_OPACMAP, "MAT_OPACMAP"}, + {CHK_MAT_SXP_OPAC_DATA, "MAT_SXP_OPAC_DATA"}, + {CHK_MAT_OPACMASK, "MAT_OPACMASK"}, + {CHK_MAT_SXP_OPACMASK_DATA, "MAT_SXP_OPACMASK_DATA"}, + {CHK_MAT_BUMPMAP, "MAT_BUMPMAP"}, + {CHK_MAT_SXP_BUMP_DATA, "MAT_SXP_BUMP_DATA"}, + {CHK_MAT_BUMPMASK, "MAT_BUMPMASK"}, + {CHK_MAT_SXP_BUMPMASK_DATA, "MAT_SXP_BUMPMASK_DATA"}, + {CHK_MAT_SPECMAP, "MAT_SPECMAP"}, + {CHK_MAT_SXP_SPEC_DATA, "MAT_SXP_SPEC_DATA"}, + {CHK_MAT_SPECMASK, "MAT_SPECMASK"}, + {CHK_MAT_SXP_SPECMASK_DATA, "MAT_SXP_SPECMASK_DATA"}, + {CHK_MAT_SHINMAP, "MAT_SHINMAP"}, + {CHK_MAT_SXP_SHIN_DATA, "MAT_SXP_SHIN_DATA"}, + {CHK_MAT_SHINMASK, "MAT_SHINMASK"}, + {CHK_MAT_SXP_SHINMASK_DATA, "MAT_SXP_SHINMASK_DATA"}, + {CHK_MAT_SELFIMAP, "MAT_SELFIMAP"}, + {CHK_MAT_SXP_SELFI_DATA, "MAT_SXP_SELFI_DATA"}, + {CHK_MAT_SELFIMASK, "MAT_SELFIMASK"}, + {CHK_MAT_SXP_SELFIMASK_DATA, "MAT_SXP_SELFIMASK_DATA"}, + {CHK_MAT_REFLMAP, "MAT_REFLMAP"}, + {CHK_MAT_REFLMASK, "MAT_REFLMASK"}, + {CHK_MAT_SXP_REFLMASK_DATA, "MAT_SXP_REFLMASK_DATA"}, + {CHK_MAT_ACUBIC, "MAT_ACUBIC"}, + {CHK_MAT_MAPNAME, "MAT_MAPNAME"}, + {CHK_MAT_MAP_TILING, "MAT_MAP_TILING"}, + {CHK_MAT_MAP_TEXBLUR, "MAT_MAP_TEXBLUR"}, + {CHK_MAT_MAP_USCALE, "MAT_MAP_USCALE"}, + {CHK_MAT_MAP_VSCALE, "MAT_MAP_VSCALE"}, + {CHK_MAT_MAP_UOFFSET, "MAT_MAP_UOFFSET"}, + {CHK_MAT_MAP_VOFFSET, "MAT_MAP_VOFFSET"}, + {CHK_MAT_MAP_ANG, "MAT_MAP_ANG"}, + {CHK_MAT_MAP_COL1, "MAT_MAP_COL1"}, + {CHK_MAT_MAP_COL2, "MAT_MAP_COL2"}, + {CHK_MAT_MAP_RCOL, "MAT_MAP_RCOL"}, + {CHK_MAT_MAP_GCOL, "MAT_MAP_GCOL"}, + {CHK_MAT_MAP_BCOL, "MAT_MAP_BCOL"}, + {CHK_NAMED_OBJECT, "NAMED_OBJECT"}, + {CHK_N_DIRECT_LIGHT, "N_DIRECT_LIGHT"}, + {CHK_DL_OFF, "DL_OFF"}, + {CHK_DL_OUTER_RANGE, "DL_OUTER_RANGE"}, + {CHK_DL_INNER_RANGE, "DL_INNER_RANGE"}, + {CHK_DL_MULTIPLIER, "DL_MULTIPLIER"}, + {CHK_DL_EXCLUDE, "DL_EXCLUDE"}, + {CHK_DL_ATTENUATE, "DL_ATTENUATE"}, + {CHK_DL_SPOTLIGHT, "DL_SPOTLIGHT"}, + {CHK_DL_SPOT_ROLL, "DL_SPOT_ROLL"}, + {CHK_DL_SHADOWED, "DL_SHADOWED"}, + {CHK_DL_LOCAL_SHADOW2, "DL_LOCAL_SHADOW2"}, + {CHK_DL_SEE_CONE, "DL_SEE_CONE"}, + {CHK_DL_SPOT_RECTANGULAR, "DL_SPOT_RECTANGULAR"}, + {CHK_DL_SPOT_ASPECT, "DL_SPOT_ASPECT"}, + {CHK_DL_SPOT_PROJECTOR, "DL_SPOT_PROJECTOR"}, + {CHK_DL_SPOT_OVERSHOOT, "DL_SPOT_OVERSHOOT"}, + {CHK_DL_RAY_BIAS, "DL_RAY_BIAS"}, + {CHK_DL_RAYSHAD, "DL_RAYSHAD"}, + {CHK_N_CAMERA, "N_CAMERA"}, + {CHK_CAM_SEE_CONE, "CAM_SEE_CONE"}, + {CHK_CAM_RANGES, "CAM_RANGES"}, + {CHK_OBJ_HIDDEN, "OBJ_HIDDEN"}, + {CHK_OBJ_VIS_LOFTER, "OBJ_VIS_LOFTER"}, + {CHK_OBJ_DOESNT_CAST, "OBJ_DOESNT_CAST"}, + {CHK_OBJ_DONT_RCVSHADOW, "OBJ_DONT_RCVSHADOW"}, + {CHK_OBJ_MATTE, "OBJ_MATTE"}, + {CHK_OBJ_FAST, "OBJ_FAST"}, + {CHK_OBJ_PROCEDURAL, "OBJ_PROCEDURAL"}, + {CHK_OBJ_FROZEN, "OBJ_FROZEN"}, + {CHK_N_TRI_OBJECT, "N_TRI_OBJECT"}, + {CHK_POINT_ARRAY, "POINT_ARRAY"}, + {CHK_POINT_FLAG_ARRAY, "POINT_FLAG_ARRAY"}, + {CHK_FACE_ARRAY, "FACE_ARRAY"}, + {CHK_MSH_MAT_GROUP, "MSH_MAT_GROUP"}, + {CHK_SMOOTH_GROUP, "SMOOTH_GROUP"}, + {CHK_MSH_BOXMAP, "MSH_BOXMAP"}, + {CHK_TEX_VERTS, "TEX_VERTS"}, + {CHK_MESH_MATRIX, "MESH_MATRIX"}, + {CHK_MESH_COLOR, "MESH_COLOR"}, + {CHK_MESH_TEXTURE_INFO, "MESH_TEXTURE_INFO"}, + {CHK_KFDATA, "KFDATA"}, + {CHK_KFHDR, "KFHDR"}, + {CHK_KFSEG, "KFSEG"}, + {CHK_KFCURTIME, "KFCURTIME"}, + {CHK_AMBIENT_NODE_TAG, "AMBIENT_NODE_TAG"}, + {CHK_OBJECT_NODE_TAG, "OBJECT_NODE_TAG"}, + {CHK_CAMERA_NODE_TAG, "CAMERA_NODE_TAG"}, + {CHK_TARGET_NODE_TAG, "TARGET_NODE_TAG"}, + {CHK_LIGHT_NODE_TAG, "LIGHT_NODE_TAG"}, + {CHK_L_TARGET_NODE_TAG, "L_TARGET_NODE_TAG"}, + {CHK_SPOTLIGHT_NODE_TAG, "SPOTLIGHT_NODE_TAG"}, + {CHK_NODE_ID, "NODE_ID"}, + {CHK_NODE_HDR, "NODE_HDR"}, + {CHK_PIVOT, "PIVOT"}, + {CHK_INSTANCE_NAME, "INSTANCE_NAME"}, + {CHK_MORPH_SMOOTH, "MORPH_SMOOTH"}, + {CHK_BOUNDBOX, "BOUNDBOX"}, + {CHK_POS_TRACK_TAG, "POS_TRACK_TAG"}, + {CHK_COL_TRACK_TAG, "COL_TRACK_TAG"}, + {CHK_ROT_TRACK_TAG, "ROT_TRACK_TAG"}, + {CHK_SCL_TRACK_TAG, "SCL_TRACK_TAG"}, + {CHK_MORPH_TRACK_TAG, "MORPH_TRACK_TAG"}, + {CHK_FOV_TRACK_TAG, "FOV_TRACK_TAG"}, + {CHK_ROLL_TRACK_TAG, "ROLL_TRACK_TAG"}, + {CHK_HOT_TRACK_TAG, "HOT_TRACK_TAG"}, + {CHK_FALL_TRACK_TAG, "FALL_TRACK_TAG"}, + {CHK_HIDE_TRACK_TAG, "HIDE_TRACK_TAG"}, + {CHK_POLY_2D, "POLY_2D"}, + {CHK_SHAPE_OK, "SHAPE_OK"}, + {CHK_SHAPE_NOT_OK, "SHAPE_NOT_OK"}, + {CHK_SHAPE_HOOK, "SHAPE_HOOK"}, + {CHK_PATH_3D, "PATH_3D"}, + {CHK_PATH_MATRIX, "PATH_MATRIX"}, + {CHK_SHAPE_2D, "SHAPE_2D"}, + {CHK_M_SCALE, "M_SCALE"}, + {CHK_M_TWIST, "M_TWIST"}, + {CHK_M_TEETER, "M_TEETER"}, + {CHK_M_FIT, "M_FIT"}, + {CHK_M_BEVEL, "M_BEVEL"}, + {CHK_XZ_CURVE, "XZ_CURVE"}, + {CHK_YZ_CURVE, "YZ_CURVE"}, + {CHK_INTERPCT, "INTERPCT"}, + {CHK_DEFORM_LIMIT, "DEFORM_LIMIT"}, + {CHK_USE_CONTOUR, "USE_CONTOUR"}, + {CHK_USE_TWEEN, "USE_TWEEN"}, + {CHK_USE_SCALE, "USE_SCALE"}, + {CHK_USE_TWIST, "USE_TWIST"}, + {CHK_USE_TEETER, "USE_TEETER"}, + {CHK_USE_FIT, "USE_FIT"}, + {CHK_USE_BEVEL, "USE_BEVEL"}, + {CHK_DEFAULT_VIEW, "DEFAULT_VIEW"}, + {CHK_VIEW_TOP, "VIEW_TOP"}, + {CHK_VIEW_BOTTOM, "VIEW_BOTTOM"}, + {CHK_VIEW_LEFT, "VIEW_LEFT"}, + {CHK_VIEW_RIGHT, "VIEW_RIGHT"}, + {CHK_VIEW_FRONT, "VIEW_FRONT"}, + {CHK_VIEW_BACK, "VIEW_BACK"}, + {CHK_VIEW_USER, "VIEW_USER"}, + {CHK_VIEW_CAMERA, "VIEW_CAMERA"}, + {CHK_VIEW_WINDOW, "VIEW_WINDOW"}, + {CHK_VIEWPORT_LAYOUT_OLD, "VIEWPORT_LAYOUT_OLD"}, + {CHK_VIEWPORT_DATA_OLD, "VIEWPORT_DATA_OLD"}, + {CHK_VIEWPORT_LAYOUT, "VIEWPORT_LAYOUT"}, + {CHK_VIEWPORT_DATA, "VIEWPORT_DATA"}, + {CHK_VIEWPORT_DATA_3, "VIEWPORT_DATA_3"}, + {CHK_VIEWPORT_SIZE, "VIEWPORT_SIZE"}, + {CHK_NETWORK_VIEW, "NETWORK_VIEW"}, + {0, 0} +}; + + +const char* +lib3ds_chunk_name(uint16_t chunk) { + Lib3dsChunkTable *p; + + for (p = lib3ds_chunk_table; p->name != 0; ++p) { + if (p->chunk == chunk) { + return(p->name); + } + } + return("***UNKNOWN***"); +} diff --git a/src/osgPlugins/3ds/lib3ds/lib3ds_file.c b/src/osgPlugins/3ds/lib3ds/lib3ds_file.c index 4a54f0539..ff57bccbd 100644 --- a/src/osgPlugins/3ds/lib3ds/lib3ds_file.c +++ b/src/osgPlugins/3ds/lib3ds/lib3ds_file.c @@ -1,1426 +1,1426 @@ -/* - Copyright (C) 1996-2008 by Jan Eric Kyprianidis - 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. - - Thisprogram 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, see . -*/ -#include "lib3ds_impl.h" - - -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 - */ -Lib3dsFile* -lib3ds_file_open(const char *filename) { - FILE *f; - Lib3dsFile *file; - Lib3dsIo io; - - f = fopen(filename, "rb"); - if (!f) { - return NULL; - } - file = lib3ds_file_new(); - if (!file) { - fclose(f); - return NULL; - } - - memset(&io, 0, sizeof(io)); - io.self = f; - io.seek_func = fileio_seek_func; - io.tell_func = fileio_tell_func; - io.read_func = fileio_read_func; - io.write_func = fileio_write_func; - io.log_func = NULL; - - if (!lib3ds_file_read(file, &io)) { - fclose(f); - free(file); - return NULL; - } - - 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_open - */ -int -lib3ds_file_save(Lib3dsFile *file, const char *filename) { - FILE *f; - Lib3dsIo io; - int result; - - f = fopen(filename, "wb"); - if (!f) { - return FALSE; - } - - memset(&io, 0, sizeof(io)); - io.self = f; - io.seek_func = fileio_seek_func; - io.tell_func = fileio_tell_func; - io.read_func = fileio_read_func; - io.write_func = fileio_write_func; - io.log_func = NULL; - - result = lib3ds_file_write(file, &io); - fclose(f); - 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. - */ -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. - */ -void -lib3ds_file_free(Lib3dsFile* file) { - assert(file); - lib3ds_file_reserve_materials(file, 0, TRUE); - lib3ds_file_reserve_cameras(file, 0, TRUE); - lib3ds_file_reserve_lights(file, 0, TRUE); - lib3ds_file_reserve_meshes(file, 0, TRUE); - { - 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 - */ -void -lib3ds_file_eval(Lib3dsFile *file, float t) { - Lib3dsNode *p; - - for (p = file->nodes; p != 0; p = p->next) { - lib3ds_node_eval(p, t); - } -} - - -static void -named_object_read(Lib3dsFile *file, Lib3dsIo *io) { - Lib3dsChunk c; - char name[64]; - uint16_t chunk; - Lib3dsMesh *mesh = NULL; - Lib3dsCamera *camera = NULL; - Lib3dsLight *light = NULL; - uint32_t object_flags; - - lib3ds_chunk_read_start(&c, CHK_NAMED_OBJECT, io); - - lib3ds_io_read_string(io, name, 64); - lib3ds_io_log(io, LIB3DS_LOG_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 CHK_N_TRI_OBJECT: { - mesh = lib3ds_mesh_new(name); - lib3ds_file_insert_mesh(file, mesh, -1); - lib3ds_chunk_read_reset(&c, io); - lib3ds_mesh_read(file, mesh, io); - break; - } - - case CHK_N_CAMERA: { - camera = lib3ds_camera_new(name); - lib3ds_file_insert_camera(file, camera, -1); - lib3ds_chunk_read_reset(&c, io); - lib3ds_camera_read(camera, io); - break; - } - - case CHK_N_DIRECT_LIGHT: { - light = lib3ds_light_new(name); - lib3ds_file_insert_light(file, light, -1); - lib3ds_chunk_read_reset(&c, io); - lib3ds_light_read(light, io); - break; - } - - case CHK_OBJ_HIDDEN: - object_flags |= LIB3DS_OBJECT_HIDDEN; - break; - - case CHK_OBJ_DOESNT_CAST: - object_flags |= LIB3DS_OBJECT_DOESNT_CAST; - break; - - case CHK_OBJ_VIS_LOFTER: - object_flags |= LIB3DS_OBJECT_VIS_LOFTER; - break; - - case CHK_OBJ_MATTE: - object_flags |= LIB3DS_OBJECT_MATTE; - break; - - case CHK_OBJ_DONT_RCVSHADOW: - object_flags |= LIB3DS_OBJECT_DONT_RCVSHADOW; - break; - - case CHK_OBJ_FAST: - object_flags |= LIB3DS_OBJECT_FAST; - break; - - case CHK_OBJ_FROZEN: - object_flags |= LIB3DS_OBJECT_FROZEN; - break; - - default: - lib3ds_chunk_unknown(chunk, io); - } - } - - 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); -} - - -static void -ambient_read(Lib3dsFile *file, Lib3dsIo *io) { - Lib3dsChunk c; - uint16_t chunk; - int have_lin = FALSE; - - lib3ds_chunk_read_start(&c, CHK_AMBIENT_LIGHT, io); - - while ((chunk = lib3ds_chunk_read_next(&c, io)) != 0) { - switch (chunk) { - case CHK_LIN_COLOR_F: { - int i; - for (i = 0; i < 3; ++i) { - file->ambient[i] = lib3ds_io_read_float(io); - } - have_lin = TRUE; - break; - } - - case CHK_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, io); - } - } - - lib3ds_chunk_read_end(&c, io); -} - - -static void -mdata_read(Lib3dsFile *file, Lib3dsIo *io) { - Lib3dsChunk c; - uint16_t chunk; - - lib3ds_chunk_read_start(&c, CHK_MDATA, io); - - while ((chunk = lib3ds_chunk_read_next(&c, io)) != 0) { - switch (chunk) { - case CHK_MESH_VERSION: { - file->mesh_version = lib3ds_io_read_intd(io); - break; - } - - case CHK_MASTER_SCALE: { - file->master_scale = lib3ds_io_read_float(io); - break; - } - - case CHK_SHADOW_MAP_SIZE: - case CHK_LO_SHADOW_BIAS: - case CHK_HI_SHADOW_BIAS: - case CHK_SHADOW_SAMPLES: - case CHK_SHADOW_RANGE: - case CHK_SHADOW_FILTER: - case CHK_RAY_BIAS: { - lib3ds_chunk_read_reset(&c, io); - lib3ds_shadow_read(&file->shadow, io); - break; - } - - case CHK_VIEWPORT_LAYOUT: - case CHK_DEFAULT_VIEW: { - lib3ds_chunk_read_reset(&c, io); - lib3ds_viewport_read(&file->viewport, io); - break; - } - - case CHK_O_CONSTS: { - int i; - for (i = 0; i < 3; ++i) { - file->construction_plane[i] = lib3ds_io_read_float(io); - } - break; - } - - case CHK_AMBIENT_LIGHT: { - lib3ds_chunk_read_reset(&c, io); - ambient_read(file, io); - break; - } - - case CHK_BIT_MAP: - case CHK_SOLID_BGND: - case CHK_V_GRADIENT: - case CHK_USE_BIT_MAP: - case CHK_USE_SOLID_BGND: - case CHK_USE_V_GRADIENT: { - lib3ds_chunk_read_reset(&c, io); - lib3ds_background_read(&file->background, io); - break; - } - - case CHK_FOG: - case CHK_LAYER_FOG: - case CHK_DISTANCE_CUE: - case CHK_USE_FOG: - case CHK_USE_LAYER_FOG: - case CHK_USE_DISTANCE_CUE: { - lib3ds_chunk_read_reset(&c, io); - lib3ds_atmosphere_read(&file->atmosphere, io); - break; - } - - case CHK_MAT_ENTRY: { - Lib3dsMaterial *material = lib3ds_material_new(NULL); - lib3ds_file_insert_material(file, material, -1); - lib3ds_chunk_read_reset(&c, io); - lib3ds_material_read(material, io); - break; - } - - case CHK_NAMED_OBJECT: { - lib3ds_chunk_read_reset(&c, io); - named_object_read(file, io); - break; - } - - default: - lib3ds_chunk_unknown(chunk, io); - } - } - - lib3ds_chunk_read_end(&c, io); -} - - -static int -compare_node_id( const void *a, const void *b ) { - return (*((Lib3dsNode**)a))->node_id - (*((Lib3dsNode**)b))->node_id; -} - - -static int -compare_node_id2( const void *a, const void *b ) { - return *((unsigned short*)a) - (*((Lib3dsNode**)b))->node_id; -} - - -static void -kfdata_read(Lib3dsFile *file, Lib3dsIo *io) { - Lib3dsChunk c; - uint16_t chunk; - unsigned num_nodes = 0; - //Lib3dsIoImpl *impl = (Lib3dsIoImpl*)io->impl; - Lib3dsNode *last = NULL; - - lib3ds_chunk_read_start(&c, CHK_KFDATA, io); - - while ((chunk = lib3ds_chunk_read_next(&c, io)) != 0) { - switch (chunk) { - case CHK_KFHDR: { - file->keyf_revision = lib3ds_io_read_word(io); - lib3ds_io_read_string(io, file->name, 12 + 1); - file->frames = lib3ds_io_read_intd(io); - break; - } - - case CHK_KFSEG: { - file->segment_from = lib3ds_io_read_intd(io); - file->segment_to = lib3ds_io_read_intd(io); - break; - } - - case CHK_KFCURTIME: { - file->current_frame = lib3ds_io_read_intd(io); - break; - } - - case CHK_VIEWPORT_LAYOUT: - case CHK_DEFAULT_VIEW: { - lib3ds_chunk_read_reset(&c, io); - lib3ds_viewport_read(&file->viewport_keyf, io); - break; - } - - case CHK_AMBIENT_NODE_TAG: - case CHK_OBJECT_NODE_TAG: - case CHK_CAMERA_NODE_TAG: - case CHK_TARGET_NODE_TAG: - case CHK_LIGHT_NODE_TAG: - case CHK_SPOTLIGHT_NODE_TAG: - case CHK_L_TARGET_NODE_TAG: { - Lib3dsNodeType type = 0; - Lib3dsNode *node; - - switch (chunk) { - case CHK_AMBIENT_NODE_TAG: - type = LIB3DS_NODE_AMBIENT_COLOR; - break; - case CHK_OBJECT_NODE_TAG: - type = LIB3DS_NODE_MESH_INSTANCE; - break; - case CHK_CAMERA_NODE_TAG: - type = LIB3DS_NODE_CAMERA; - break; - case CHK_TARGET_NODE_TAG: - type = LIB3DS_NODE_CAMERA_TARGET; - break; - case CHK_LIGHT_NODE_TAG: - type = LIB3DS_NODE_OMNILIGHT; - break; - case CHK_SPOTLIGHT_NODE_TAG: - type = LIB3DS_NODE_SPOTLIGHT; - break; - case CHK_L_TARGET_NODE_TAG: - type = LIB3DS_NODE_SPOTLIGHT_TARGET; - break; - } - - node = lib3ds_node_new(type); - node->node_id = (unsigned short)(num_nodes++); - if (last) { - last->next = node; - } else { - file->nodes = node; - } - node->user_ptr = last; - last = node; - lib3ds_chunk_read_reset(&c, io); - lib3ds_node_read(node, io); - break; - } - - default: - lib3ds_chunk_unknown(chunk, io); - } - } - - { - Lib3dsNode **nodes = (Lib3dsNode **)malloc(num_nodes * sizeof(Lib3dsNode*)); - unsigned i; - Lib3dsNode *p, *q, *parent; - - p = file->nodes; - for (i = 0; i < num_nodes; ++i) { - nodes[i] = p; - p = p->next; - } - qsort(nodes, num_nodes, sizeof(Lib3dsNode*), compare_node_id); - - p = last; - while (p) { - q = (Lib3dsNode *)p->user_ptr; - if (p->user_id != 65535) { - parent = *(Lib3dsNode**)bsearch(&p->user_id, nodes, num_nodes, sizeof(Lib3dsNode*), compare_node_id2); - if (parent) { - q->next = p->next; - p->next = parent->childs; - p->parent = parent; - parent->childs = p; - } else { - /* TODO: warning */ - } - } - p->user_id = 0; - p->user_ptr = NULL; - p = q; - } - free(nodes); - } - - lib3ds_chunk_read_end(&c, io); -} - - -/*! - * 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. - */ -int -lib3ds_file_read(Lib3dsFile *file, Lib3dsIo *io) { - Lib3dsChunk c; - uint16_t chunk; - Lib3dsIoImpl *impl; - - lib3ds_io_setup(io); - impl = (Lib3dsIoImpl*)io->impl; - - if (setjmp(impl->jmpbuf) != 0) { - lib3ds_io_cleanup(io); - return FALSE; - } - - lib3ds_chunk_read_start(&c, 0, io); - switch (c.chunk) { - case CHK_MDATA: { - lib3ds_chunk_read_reset(&c, io); - mdata_read(file, io); - break; - } - - case CHK_M3DMAGIC: - case CHK_MLIBMAGIC: - case CHK_CMAGIC: { - while ((chunk = lib3ds_chunk_read_next(&c, io)) != 0) { - switch (chunk) { - case CHK_M3D_VERSION: { - file->mesh_version = lib3ds_io_read_dword(io); - break; - } - - case CHK_MDATA: { - lib3ds_chunk_read_reset(&c, io); - mdata_read(file, io); - break; - } - - case CHK_KFDATA: { - lib3ds_chunk_read_reset(&c, io); - kfdata_read(file, io); - break; - } - - default: - lib3ds_chunk_unknown(chunk, io); - } - } - break; - } - - default: - lib3ds_chunk_unknown(c.chunk, io); - return FALSE; - } - - lib3ds_chunk_read_end(&c, io); - - memset(impl->jmpbuf, 0, sizeof(impl->jmpbuf)); - lib3ds_io_cleanup(io); - return TRUE; -} - - -static void -colorf_write(float rgb[3], Lib3dsIo *io) { - Lib3dsChunk c; - - c.chunk = CHK_COLOR_F; - c.size = 18; - lib3ds_chunk_write(&c, io); - lib3ds_io_write_rgb(io, rgb); - - c.chunk = CHK_LIN_COLOR_F; - c.size = 18; - lib3ds_chunk_write(&c, io); - lib3ds_io_write_rgb(io, rgb); -} - - -static void -object_flags_write(uint32_t flags, Lib3dsIo *io) { - if (flags) { - Lib3dsChunk c; - c.size = 6; - - if (flags & LIB3DS_OBJECT_HIDDEN) { - c.chunk = CHK_OBJ_HIDDEN; - lib3ds_chunk_write(&c, io); - } - if (flags & LIB3DS_OBJECT_VIS_LOFTER) { - c.chunk = CHK_OBJ_VIS_LOFTER; - lib3ds_chunk_write(&c, io); - } - if (flags & LIB3DS_OBJECT_DOESNT_CAST) { - c.chunk = CHK_OBJ_DOESNT_CAST; - lib3ds_chunk_write(&c, io); - } - if (flags & LIB3DS_OBJECT_MATTE) { - c.chunk = CHK_OBJ_MATTE; - lib3ds_chunk_write(&c, io); - } - if (flags & LIB3DS_OBJECT_DONT_RCVSHADOW) { - c.chunk = CHK_OBJ_DOESNT_CAST; - lib3ds_chunk_write(&c, io); - } - if (flags & LIB3DS_OBJECT_FAST) { - c.chunk = CHK_OBJ_FAST; - lib3ds_chunk_write(&c, io); - } - if (flags & LIB3DS_OBJECT_FROZEN) { - c.chunk = CHK_OBJ_FROZEN; - lib3ds_chunk_write(&c, io); - } - } -} - - -static void -mdata_write(Lib3dsFile *file, Lib3dsIo *io) { - Lib3dsChunk c; - - c.chunk = CHK_MDATA; - lib3ds_chunk_write_start(&c, io); - - { /*---- LIB3DS_MESH_VERSION ----*/ - Lib3dsChunk c; - c.chunk = CHK_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 = CHK_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 = CHK_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 = CHK_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); - { - int i; - for (i = 0; i < file->nmaterials; ++i) { - lib3ds_material_write(file->materials[i], io); - } - } - { - Lib3dsChunk c; - int i; - - for (i = 0; i < file->ncameras; ++i) { - c.chunk = CHK_NAMED_OBJECT; - lib3ds_chunk_write_start(&c, io); - lib3ds_io_write_string(io, file->cameras[i]->name); - lib3ds_camera_write(file->cameras[i], io); - object_flags_write(file->cameras[i]->object_flags, io); - lib3ds_chunk_write_end(&c, io); - } - } - { - Lib3dsChunk c; - int i; - - for (i = 0; i < file->nlights; ++i) { - c.chunk = CHK_NAMED_OBJECT; - lib3ds_chunk_write_start(&c, io); - lib3ds_io_write_string(io, file->lights[i]->name); - lib3ds_light_write(file->lights[i], io); - object_flags_write(file->lights[i]->object_flags, io); - lib3ds_chunk_write_end(&c, io); - } - } - { - Lib3dsChunk c; - int i; - - for (i = 0; i < file->nmeshes; ++i) { - c.chunk = CHK_NAMED_OBJECT; - lib3ds_chunk_write_start(&c, io); - lib3ds_io_write_string(io, file->meshes[i]->name); - lib3ds_mesh_write(file, file->meshes[i], io); - object_flags_write(file->meshes[i]->object_flags, io); - lib3ds_chunk_write_end(&c, io); - } - } - - lib3ds_chunk_write_end(&c, io); -} - - - -static void -nodes_write(Lib3dsNode *first_node, uint16_t *default_id, uint16_t parent_id, Lib3dsIo *io) { - Lib3dsNode *p; - for (p = first_node; p != NULL; p = p->next) { - uint16_t node_id; - if ((p->type == LIB3DS_NODE_AMBIENT_COLOR) || (p->node_id != 65535)) { - node_id = p->node_id; - } else { - node_id = *default_id; - } - ++(*default_id); - lib3ds_node_write(p, node_id, parent_id, io); - - nodes_write(p->childs, default_id, node_id, io); - } -} - - -static void -kfdata_write(Lib3dsFile *file, Lib3dsIo *io) { - Lib3dsChunk c; - - if (!file->nodes) { - return; - } - - c.chunk = CHK_KFDATA; - lib3ds_chunk_write_start(&c, io); - - { /*---- LIB3DS_KFHDR ----*/ - Lib3dsChunk c; - c.chunk = CHK_KFHDR; - c.size = 6 + 2 + (uint32_t)strlen(file->name) + 1 + 4; - lib3ds_chunk_write(&c, io); - lib3ds_io_write_intw(io, (int16_t)file->keyf_revision); - lib3ds_io_write_string(io, file->name); - lib3ds_io_write_intd(io, file->frames); - } - { /*---- LIB3DS_KFSEG ----*/ - Lib3dsChunk c; - c.chunk = CHK_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 = CHK_KFCURTIME; - c.size = 10; - lib3ds_chunk_write(&c, io); - lib3ds_io_write_intd(io, file->current_frame); - } - lib3ds_viewport_write(&file->viewport_keyf, io); - - { - uint16_t default_id = 0; - nodes_write(file->nodes, &default_id, 65535, io); - } - - lib3ds_chunk_write_end(&c, io); -} - - -/*! - * 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. - */ -int -lib3ds_file_write(Lib3dsFile *file, Lib3dsIo *io) { - Lib3dsChunk c; - Lib3dsIoImpl *impl; - - lib3ds_io_setup(io); - impl = (Lib3dsIoImpl*)io->impl; - - if (setjmp(impl->jmpbuf) != 0) { - lib3ds_io_cleanup(io); - return FALSE; - } - - c.chunk = CHK_M3DMAGIC; - lib3ds_chunk_write_start(&c, io); - - { /*---- LIB3DS_M3D_VERSION ----*/ - Lib3dsChunk c; - - c.chunk = CHK_M3D_VERSION; - c.size = 10; - lib3ds_chunk_write(&c, io); - lib3ds_io_write_dword(io, file->mesh_version); - } - - mdata_write(file, io); - kfdata_write(file, io); - - lib3ds_chunk_write_end(&c, io); - - memset(impl->jmpbuf, 0, sizeof(impl->jmpbuf)); - lib3ds_io_cleanup(io); - return TRUE; -} - - -void lib3ds_file_reserve_materials(Lib3dsFile *file, int size, int force) { - assert(file); - lib3ds_util_reserve_array((void***)&file->materials, &file->nmaterials, &file->materials_size, - size, force, (Lib3dsFreeFunc)lib3ds_material_free); -} - - -void -lib3ds_file_insert_material(Lib3dsFile *file, Lib3dsMaterial *material, int index) { - assert(file); - lib3ds_util_insert_array((void***)&file->materials, &file->nmaterials, &file->materials_size, material, index); -} - - -void -lib3ds_file_remove_material(Lib3dsFile *file, int index) { - assert(file); - lib3ds_util_remove_array((void***)&file->materials, &file->nmaterials, index, (Lib3dsFreeFunc)lib3ds_material_free); -} - - -int -lib3ds_file_material_by_name(Lib3dsFile *file, const char *name) { - int i; - - assert(file); - for (i = 0; i < file->nmaterials; ++i) { - if (strcmp(file->materials[i]->name, name) == 0) { - return(i); - } - } - return -1; -} - - -void -lib3ds_file_reserve_cameras(Lib3dsFile *file, int size, int force) { - assert(file); - lib3ds_util_reserve_array((void***)&file->cameras, &file->ncameras, &file->cameras_size, - size, force, (Lib3dsFreeFunc)lib3ds_camera_free); -} - - -void -lib3ds_file_insert_camera(Lib3dsFile *file, Lib3dsCamera *camera, int index) { - assert(file); - lib3ds_util_insert_array((void***)&file->cameras, &file->ncameras, &file->cameras_size, camera, index); -} - - -void -lib3ds_file_remove_camera(Lib3dsFile *file, int index) { - assert(file); - lib3ds_util_remove_array((void***)&file->cameras, &file->ncameras, index, (Lib3dsFreeFunc)lib3ds_camera_free); -} - - -int -lib3ds_file_camera_by_name(Lib3dsFile *file, const char *name) { - int i; - - assert(file); - for (i = 0; i < file->ncameras; ++i) { - if (strcmp(file->cameras[i]->name, name) == 0) { - return(i); - } - } - return -1; -} - - -void -lib3ds_file_reserve_lights(Lib3dsFile *file, int size, int force) { - assert(file); - lib3ds_util_reserve_array((void***)&file->lights, &file->nlights, &file->lights_size, - size, force, (Lib3dsFreeFunc)lib3ds_light_free); -} - - -void -lib3ds_file_insert_light(Lib3dsFile *file, Lib3dsLight *light, int index) { - assert(file); - lib3ds_util_insert_array((void***)&file->lights, &file->nlights, &file->lights_size, light, index); -} - - -void -lib3ds_file_remove_light(Lib3dsFile *file, int index) { - assert(file); - lib3ds_util_remove_array((void***)&file->lights, &file->nlights, index, (Lib3dsFreeFunc)lib3ds_light_free); -} - - -int -lib3ds_file_light_by_name(Lib3dsFile *file, const char *name) { - int i; - - assert(file); - for (i = 0; i < file->nlights; ++i) { - if (strcmp(file->lights[i]->name, name) == 0) { - return(i); - } - } - return -1; -} - - -void -lib3ds_file_reserve_meshes(Lib3dsFile *file, int size, int force) { - assert(file); - lib3ds_util_reserve_array((void***)&file->meshes, &file->nmeshes, &file->meshes_size, - size, force, (Lib3dsFreeFunc)lib3ds_mesh_free); -} - - -void -lib3ds_file_insert_mesh(Lib3dsFile *file, Lib3dsMesh *mesh, int index) { - assert(file); - lib3ds_util_insert_array((void***)&file->meshes, &file->nmeshes, &file->meshes_size, mesh, index); -} - - -void -lib3ds_file_remove_mesh(Lib3dsFile *file, int index) { - assert(file); - lib3ds_util_remove_array((void***)&file->meshes, &file->nmeshes, index, (Lib3dsFreeFunc)lib3ds_mesh_free); -} - - -int -lib3ds_file_mesh_by_name(Lib3dsFile *file, const char *name) { - int i; - - assert(file); - for (i = 0; i < file->nmeshes; ++i) { - if (strcmp(file->meshes[i]->name, name) == 0) { - return(i); - } - } - return -1; -} - - -Lib3dsMesh* -lib3ds_file_mesh_for_node(Lib3dsFile *file, Lib3dsNode *node) { - int index; - Lib3dsMeshInstanceNode *n; - - if (node->type != LIB3DS_NODE_MESH_INSTANCE) - return NULL; - n = (Lib3dsMeshInstanceNode*)node; - - index = lib3ds_file_mesh_by_name(file, node->name); - - return (index >= 0)? file->meshes[index] : NULL; -} - - -/*! - * 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 - */ -Lib3dsNode* -lib3ds_file_node_by_name(Lib3dsFile *file, const char* name, Lib3dsNodeType 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 - */ -Lib3dsNode* -lib3ds_file_node_by_id(Lib3dsFile *file, uint16_t 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); -} - - -void -lib3ds_file_append_node(Lib3dsFile *file, Lib3dsNode *node, Lib3dsNode *parent) { - Lib3dsNode *p; - - assert(file); - assert(node); - p = parent? parent->childs : file->nodes; - if (p) { - while (p->next) { - p = p->next; - } - p->next = node; - } else { - if (parent) { - parent->childs = node; - } else { - file->nodes = node; - } - } - node->parent = parent; - node->next = NULL; -} - - -void -lib3ds_file_insert_node(Lib3dsFile *file, Lib3dsNode *node, Lib3dsNode *before) { - Lib3dsNode *p, *q; - - assert(node); - assert(file); - - if (before) { - p = before->parent? before->parent->childs : file->nodes; - assert(p); - q = NULL; - while (p != before) { - q = p; - p = p->next; - } - if (q) { - node->next = q->next; - q->next = node; - } else { - node->next = file->nodes; - file->nodes = node; - } - node->parent = before->parent; - } else { - node->next = file->nodes; - node->parent = NULL; - file->nodes = node; - } -} - - -/*! - * 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 - */ -void -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; - } - - 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; - } - - if (!p) { - file->nodes = n->next; - } else { - p->next = n->next; - } - } -} - - -static void -file_minmax_node_id_impl(Lib3dsFile *file, Lib3dsNode *node, uint16_t *min_id, uint16_t *max_id) { - Lib3dsNode *p; - - if (min_id && (*min_id > node->node_id)) - *min_id = node->node_id; - if (max_id && (*max_id < node->node_id)) - *max_id = node->node_id; - - p = node->childs; - while (p) { - file_minmax_node_id_impl(file, p, min_id, max_id); - p = p->next; - } -} - - -void -lib3ds_file_minmax_node_id(Lib3dsFile *file, uint16_t *min_id, uint16_t *max_id) { - Lib3dsNode *p; - - if (min_id) - *min_id = 65535; - if (max_id) - *max_id = 0; - - p = file->nodes; - while (p) { - file_minmax_node_id_impl(file, p, min_id, max_id); - p = p->next; - } -} - - -void -lib3ds_file_bounding_box_of_objects(Lib3dsFile *file, int - include_meshes, int include_cameras, int include_lights, - float bmin[3], float bmax[3]) { - bmin[0] = bmin[1] = bmin[2] = FLT_MAX; - bmax[0] = bmax[1] = bmax[2] = -FLT_MAX; - - if (include_meshes) { - float lmin[3], lmax[3]; - int i; - for (i = 0; i < file->nmeshes; ++i) { - lib3ds_mesh_bounding_box(file->meshes[i], lmin, lmax); - lib3ds_vector_min(bmin, lmin); - lib3ds_vector_max(bmax, lmax); - } - } - if (include_cameras) { - int i; - for (i = 0; i < file->ncameras; ++i) { - lib3ds_vector_min(bmin, file->cameras[i]->position); - lib3ds_vector_max(bmax, file->cameras[i]->position); - lib3ds_vector_min(bmin, file->cameras[i]->target); - lib3ds_vector_max(bmax, file->cameras[i]->target); - } - } - if (include_lights) { - int i; - for (i = 0; i < file->ncameras; ++i) { - lib3ds_vector_min(bmin, file->lights[i]->position); - lib3ds_vector_max(bmax, file->lights[i]->position); - if (file->lights[i]->spot_light) { - lib3ds_vector_min(bmin, file->lights[i]->target); - lib3ds_vector_max(bmax, file->lights[i]->target); - } - } - } -} - - -static void -file_bounding_box_of_nodes_impl(Lib3dsNode *node, Lib3dsFile *file, - int include_meshes, int include_cameras, int include_lights, - float bmin[3], float bmax[3], float matrix[4][4]) { - switch (node->type) { - case LIB3DS_NODE_MESH_INSTANCE: - if (include_meshes) { - int index; - Lib3dsMeshInstanceNode *n = (Lib3dsMeshInstanceNode*)node; - - index = lib3ds_file_mesh_by_name(file, n->instance_name); - if (index < 0) - index = lib3ds_file_mesh_by_name(file, node->name); - if (index >= 0) { - Lib3dsMesh *mesh; - float inv_matrix[4][4], M[4][4]; - float v[3]; - int i; - - mesh = file->meshes[index]; - lib3ds_matrix_copy(inv_matrix, mesh->matrix); - lib3ds_matrix_inv(inv_matrix); - lib3ds_matrix_mult(M, matrix, node->matrix); - lib3ds_matrix_translate(M, -n->pivot[0], -n->pivot[1], -n->pivot[2]); - lib3ds_matrix_mult(M, M, inv_matrix); - - for (i = 0; i < mesh->nvertices; ++i) { - lib3ds_vector_transform(v, M, mesh->vertices[i]); - lib3ds_vector_min(bmin, v); - lib3ds_vector_max(bmax, v); - } - } - } - break; - - case LIB3DS_NODE_CAMERA: - case LIB3DS_NODE_CAMERA_TARGET: - if (include_cameras) { - float z[3], v[3]; - float M[4][4]; - lib3ds_matrix_mult(M, matrix, node->matrix); - lib3ds_vector_zero(z); - lib3ds_vector_transform(v, M, z); - lib3ds_vector_min(bmin, v); - lib3ds_vector_max(bmax, v); - } - break; - - case LIB3DS_NODE_OMNILIGHT: - case LIB3DS_NODE_SPOTLIGHT: - case LIB3DS_NODE_SPOTLIGHT_TARGET: - if (include_lights) { - float z[3], v[3]; - float M[4][4]; - lib3ds_matrix_mult(M, matrix, node->matrix); - lib3ds_vector_zero(z); - lib3ds_vector_transform(v, M, z); - lib3ds_vector_min(bmin, v); - lib3ds_vector_max(bmax, v); - } - break; - } - { - Lib3dsNode *p = node->childs; - while (p) { - file_bounding_box_of_nodes_impl(p, file, include_meshes, include_cameras, include_lights, bmin, bmax, matrix); - p = p->next; - } - } -} - - -void -lib3ds_file_bounding_box_of_nodes(Lib3dsFile *file, - int include_meshes, int include_cameras,int include_lights, - float bmin[3], float bmax[3], float matrix[4][4]) { - Lib3dsNode *p; - float M[4][4]; - - if (matrix) { - lib3ds_matrix_copy(M, matrix); - } else { - lib3ds_matrix_identity(M); - } - - bmin[0] = bmin[1] = bmin[2] = FLT_MAX; - bmax[0] = bmax[1] = bmax[2] = -FLT_MAX; - p = file->nodes; - while (p) { - file_bounding_box_of_nodes_impl(p, file, include_meshes, include_cameras, include_lights, bmin, bmax, M); - p = p->next; - } -} - - -void -lib3ds_file_create_nodes_for_meshes(Lib3dsFile *file) { - Lib3dsNode *p; - int i; - for (i = 0; i < file->nmeshes; ++i) { - Lib3dsMesh *mesh = file->meshes[i]; - p = lib3ds_node_new(LIB3DS_NODE_MESH_INSTANCE); - strcpy(p->name, mesh->name); - lib3ds_file_insert_node(file, p, NULL); - } -} +/* + Copyright (C) 1996-2008 by Jan Eric Kyprianidis + 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. + + Thisprogram 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, see . +*/ +#include "lib3ds_impl.h" + + +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 + */ +Lib3dsFile* +lib3ds_file_open(const char *filename) { + FILE *f; + Lib3dsFile *file; + Lib3dsIo io; + + f = fopen(filename, "rb"); + if (!f) { + return NULL; + } + file = lib3ds_file_new(); + if (!file) { + fclose(f); + return NULL; + } + + memset(&io, 0, sizeof(io)); + io.self = f; + io.seek_func = fileio_seek_func; + io.tell_func = fileio_tell_func; + io.read_func = fileio_read_func; + io.write_func = fileio_write_func; + io.log_func = NULL; + + if (!lib3ds_file_read(file, &io)) { + fclose(f); + free(file); + return NULL; + } + + 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_open + */ +int +lib3ds_file_save(Lib3dsFile *file, const char *filename) { + FILE *f; + Lib3dsIo io; + int result; + + f = fopen(filename, "wb"); + if (!f) { + return FALSE; + } + + memset(&io, 0, sizeof(io)); + io.self = f; + io.seek_func = fileio_seek_func; + io.tell_func = fileio_tell_func; + io.read_func = fileio_read_func; + io.write_func = fileio_write_func; + io.log_func = NULL; + + result = lib3ds_file_write(file, &io); + fclose(f); + 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. + */ +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. + */ +void +lib3ds_file_free(Lib3dsFile* file) { + assert(file); + lib3ds_file_reserve_materials(file, 0, TRUE); + lib3ds_file_reserve_cameras(file, 0, TRUE); + lib3ds_file_reserve_lights(file, 0, TRUE); + lib3ds_file_reserve_meshes(file, 0, TRUE); + { + 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 + */ +void +lib3ds_file_eval(Lib3dsFile *file, float t) { + Lib3dsNode *p; + + for (p = file->nodes; p != 0; p = p->next) { + lib3ds_node_eval(p, t); + } +} + + +static void +named_object_read(Lib3dsFile *file, Lib3dsIo *io) { + Lib3dsChunk c; + char name[64]; + uint16_t chunk; + Lib3dsMesh *mesh = NULL; + Lib3dsCamera *camera = NULL; + Lib3dsLight *light = NULL; + uint32_t object_flags; + + lib3ds_chunk_read_start(&c, CHK_NAMED_OBJECT, io); + + lib3ds_io_read_string(io, name, 64); + lib3ds_io_log(io, LIB3DS_LOG_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 CHK_N_TRI_OBJECT: { + mesh = lib3ds_mesh_new(name); + lib3ds_file_insert_mesh(file, mesh, -1); + lib3ds_chunk_read_reset(&c, io); + lib3ds_mesh_read(file, mesh, io); + break; + } + + case CHK_N_CAMERA: { + camera = lib3ds_camera_new(name); + lib3ds_file_insert_camera(file, camera, -1); + lib3ds_chunk_read_reset(&c, io); + lib3ds_camera_read(camera, io); + break; + } + + case CHK_N_DIRECT_LIGHT: { + light = lib3ds_light_new(name); + lib3ds_file_insert_light(file, light, -1); + lib3ds_chunk_read_reset(&c, io); + lib3ds_light_read(light, io); + break; + } + + case CHK_OBJ_HIDDEN: + object_flags |= LIB3DS_OBJECT_HIDDEN; + break; + + case CHK_OBJ_DOESNT_CAST: + object_flags |= LIB3DS_OBJECT_DOESNT_CAST; + break; + + case CHK_OBJ_VIS_LOFTER: + object_flags |= LIB3DS_OBJECT_VIS_LOFTER; + break; + + case CHK_OBJ_MATTE: + object_flags |= LIB3DS_OBJECT_MATTE; + break; + + case CHK_OBJ_DONT_RCVSHADOW: + object_flags |= LIB3DS_OBJECT_DONT_RCVSHADOW; + break; + + case CHK_OBJ_FAST: + object_flags |= LIB3DS_OBJECT_FAST; + break; + + case CHK_OBJ_FROZEN: + object_flags |= LIB3DS_OBJECT_FROZEN; + break; + + default: + lib3ds_chunk_unknown(chunk, io); + } + } + + 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); +} + + +static void +ambient_read(Lib3dsFile *file, Lib3dsIo *io) { + Lib3dsChunk c; + uint16_t chunk; + int have_lin = FALSE; + + lib3ds_chunk_read_start(&c, CHK_AMBIENT_LIGHT, io); + + while ((chunk = lib3ds_chunk_read_next(&c, io)) != 0) { + switch (chunk) { + case CHK_LIN_COLOR_F: { + int i; + for (i = 0; i < 3; ++i) { + file->ambient[i] = lib3ds_io_read_float(io); + } + have_lin = TRUE; + break; + } + + case CHK_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, io); + } + } + + lib3ds_chunk_read_end(&c, io); +} + + +static void +mdata_read(Lib3dsFile *file, Lib3dsIo *io) { + Lib3dsChunk c; + uint16_t chunk; + + lib3ds_chunk_read_start(&c, CHK_MDATA, io); + + while ((chunk = lib3ds_chunk_read_next(&c, io)) != 0) { + switch (chunk) { + case CHK_MESH_VERSION: { + file->mesh_version = lib3ds_io_read_intd(io); + break; + } + + case CHK_MASTER_SCALE: { + file->master_scale = lib3ds_io_read_float(io); + break; + } + + case CHK_SHADOW_MAP_SIZE: + case CHK_LO_SHADOW_BIAS: + case CHK_HI_SHADOW_BIAS: + case CHK_SHADOW_SAMPLES: + case CHK_SHADOW_RANGE: + case CHK_SHADOW_FILTER: + case CHK_RAY_BIAS: { + lib3ds_chunk_read_reset(&c, io); + lib3ds_shadow_read(&file->shadow, io); + break; + } + + case CHK_VIEWPORT_LAYOUT: + case CHK_DEFAULT_VIEW: { + lib3ds_chunk_read_reset(&c, io); + lib3ds_viewport_read(&file->viewport, io); + break; + } + + case CHK_O_CONSTS: { + int i; + for (i = 0; i < 3; ++i) { + file->construction_plane[i] = lib3ds_io_read_float(io); + } + break; + } + + case CHK_AMBIENT_LIGHT: { + lib3ds_chunk_read_reset(&c, io); + ambient_read(file, io); + break; + } + + case CHK_BIT_MAP: + case CHK_SOLID_BGND: + case CHK_V_GRADIENT: + case CHK_USE_BIT_MAP: + case CHK_USE_SOLID_BGND: + case CHK_USE_V_GRADIENT: { + lib3ds_chunk_read_reset(&c, io); + lib3ds_background_read(&file->background, io); + break; + } + + case CHK_FOG: + case CHK_LAYER_FOG: + case CHK_DISTANCE_CUE: + case CHK_USE_FOG: + case CHK_USE_LAYER_FOG: + case CHK_USE_DISTANCE_CUE: { + lib3ds_chunk_read_reset(&c, io); + lib3ds_atmosphere_read(&file->atmosphere, io); + break; + } + + case CHK_MAT_ENTRY: { + Lib3dsMaterial *material = lib3ds_material_new(NULL); + lib3ds_file_insert_material(file, material, -1); + lib3ds_chunk_read_reset(&c, io); + lib3ds_material_read(material, io); + break; + } + + case CHK_NAMED_OBJECT: { + lib3ds_chunk_read_reset(&c, io); + named_object_read(file, io); + break; + } + + default: + lib3ds_chunk_unknown(chunk, io); + } + } + + lib3ds_chunk_read_end(&c, io); +} + + +static int +compare_node_id( const void *a, const void *b ) { + return (*((Lib3dsNode**)a))->node_id - (*((Lib3dsNode**)b))->node_id; +} + + +static int +compare_node_id2( const void *a, const void *b ) { + return *((unsigned short*)a) - (*((Lib3dsNode**)b))->node_id; +} + + +static void +kfdata_read(Lib3dsFile *file, Lib3dsIo *io) { + Lib3dsChunk c; + uint16_t chunk; + unsigned num_nodes = 0; + //Lib3dsIoImpl *impl = (Lib3dsIoImpl*)io->impl; + Lib3dsNode *last = NULL; + + lib3ds_chunk_read_start(&c, CHK_KFDATA, io); + + while ((chunk = lib3ds_chunk_read_next(&c, io)) != 0) { + switch (chunk) { + case CHK_KFHDR: { + file->keyf_revision = lib3ds_io_read_word(io); + lib3ds_io_read_string(io, file->name, 12 + 1); + file->frames = lib3ds_io_read_intd(io); + break; + } + + case CHK_KFSEG: { + file->segment_from = lib3ds_io_read_intd(io); + file->segment_to = lib3ds_io_read_intd(io); + break; + } + + case CHK_KFCURTIME: { + file->current_frame = lib3ds_io_read_intd(io); + break; + } + + case CHK_VIEWPORT_LAYOUT: + case CHK_DEFAULT_VIEW: { + lib3ds_chunk_read_reset(&c, io); + lib3ds_viewport_read(&file->viewport_keyf, io); + break; + } + + case CHK_AMBIENT_NODE_TAG: + case CHK_OBJECT_NODE_TAG: + case CHK_CAMERA_NODE_TAG: + case CHK_TARGET_NODE_TAG: + case CHK_LIGHT_NODE_TAG: + case CHK_SPOTLIGHT_NODE_TAG: + case CHK_L_TARGET_NODE_TAG: { + Lib3dsNodeType type = 0; + Lib3dsNode *node; + + switch (chunk) { + case CHK_AMBIENT_NODE_TAG: + type = LIB3DS_NODE_AMBIENT_COLOR; + break; + case CHK_OBJECT_NODE_TAG: + type = LIB3DS_NODE_MESH_INSTANCE; + break; + case CHK_CAMERA_NODE_TAG: + type = LIB3DS_NODE_CAMERA; + break; + case CHK_TARGET_NODE_TAG: + type = LIB3DS_NODE_CAMERA_TARGET; + break; + case CHK_LIGHT_NODE_TAG: + type = LIB3DS_NODE_OMNILIGHT; + break; + case CHK_SPOTLIGHT_NODE_TAG: + type = LIB3DS_NODE_SPOTLIGHT; + break; + case CHK_L_TARGET_NODE_TAG: + type = LIB3DS_NODE_SPOTLIGHT_TARGET; + break; + } + + node = lib3ds_node_new(type); + node->node_id = (unsigned short)(num_nodes++); + if (last) { + last->next = node; + } else { + file->nodes = node; + } + node->user_ptr = last; + last = node; + lib3ds_chunk_read_reset(&c, io); + lib3ds_node_read(node, io); + break; + } + + default: + lib3ds_chunk_unknown(chunk, io); + } + } + + { + Lib3dsNode **nodes = (Lib3dsNode **)malloc(num_nodes * sizeof(Lib3dsNode*)); + unsigned i; + Lib3dsNode *p, *q, *parent; + + p = file->nodes; + for (i = 0; i < num_nodes; ++i) { + nodes[i] = p; + p = p->next; + } + qsort(nodes, num_nodes, sizeof(Lib3dsNode*), compare_node_id); + + p = last; + while (p) { + q = (Lib3dsNode *)p->user_ptr; + if (p->user_id != 65535) { + parent = *(Lib3dsNode**)bsearch(&p->user_id, nodes, num_nodes, sizeof(Lib3dsNode*), compare_node_id2); + if (parent) { + q->next = p->next; + p->next = parent->childs; + p->parent = parent; + parent->childs = p; + } else { + /* TODO: warning */ + } + } + p->user_id = 0; + p->user_ptr = NULL; + p = q; + } + free(nodes); + } + + lib3ds_chunk_read_end(&c, io); +} + + +/*! + * 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. + */ +int +lib3ds_file_read(Lib3dsFile *file, Lib3dsIo *io) { + Lib3dsChunk c; + uint16_t chunk; + Lib3dsIoImpl *impl; + + lib3ds_io_setup(io); + impl = (Lib3dsIoImpl*)io->impl; + + if (setjmp(impl->jmpbuf) != 0) { + lib3ds_io_cleanup(io); + return FALSE; + } + + lib3ds_chunk_read_start(&c, 0, io); + switch (c.chunk) { + case CHK_MDATA: { + lib3ds_chunk_read_reset(&c, io); + mdata_read(file, io); + break; + } + + case CHK_M3DMAGIC: + case CHK_MLIBMAGIC: + case CHK_CMAGIC: { + while ((chunk = lib3ds_chunk_read_next(&c, io)) != 0) { + switch (chunk) { + case CHK_M3D_VERSION: { + file->mesh_version = lib3ds_io_read_dword(io); + break; + } + + case CHK_MDATA: { + lib3ds_chunk_read_reset(&c, io); + mdata_read(file, io); + break; + } + + case CHK_KFDATA: { + lib3ds_chunk_read_reset(&c, io); + kfdata_read(file, io); + break; + } + + default: + lib3ds_chunk_unknown(chunk, io); + } + } + break; + } + + default: + lib3ds_chunk_unknown(c.chunk, io); + return FALSE; + } + + lib3ds_chunk_read_end(&c, io); + + memset(impl->jmpbuf, 0, sizeof(impl->jmpbuf)); + lib3ds_io_cleanup(io); + return TRUE; +} + + +static void +colorf_write(float rgb[3], Lib3dsIo *io) { + Lib3dsChunk c; + + c.chunk = CHK_COLOR_F; + c.size = 18; + lib3ds_chunk_write(&c, io); + lib3ds_io_write_rgb(io, rgb); + + c.chunk = CHK_LIN_COLOR_F; + c.size = 18; + lib3ds_chunk_write(&c, io); + lib3ds_io_write_rgb(io, rgb); +} + + +static void +object_flags_write(uint32_t flags, Lib3dsIo *io) { + if (flags) { + Lib3dsChunk c; + c.size = 6; + + if (flags & LIB3DS_OBJECT_HIDDEN) { + c.chunk = CHK_OBJ_HIDDEN; + lib3ds_chunk_write(&c, io); + } + if (flags & LIB3DS_OBJECT_VIS_LOFTER) { + c.chunk = CHK_OBJ_VIS_LOFTER; + lib3ds_chunk_write(&c, io); + } + if (flags & LIB3DS_OBJECT_DOESNT_CAST) { + c.chunk = CHK_OBJ_DOESNT_CAST; + lib3ds_chunk_write(&c, io); + } + if (flags & LIB3DS_OBJECT_MATTE) { + c.chunk = CHK_OBJ_MATTE; + lib3ds_chunk_write(&c, io); + } + if (flags & LIB3DS_OBJECT_DONT_RCVSHADOW) { + c.chunk = CHK_OBJ_DOESNT_CAST; + lib3ds_chunk_write(&c, io); + } + if (flags & LIB3DS_OBJECT_FAST) { + c.chunk = CHK_OBJ_FAST; + lib3ds_chunk_write(&c, io); + } + if (flags & LIB3DS_OBJECT_FROZEN) { + c.chunk = CHK_OBJ_FROZEN; + lib3ds_chunk_write(&c, io); + } + } +} + + +static void +mdata_write(Lib3dsFile *file, Lib3dsIo *io) { + Lib3dsChunk c; + + c.chunk = CHK_MDATA; + lib3ds_chunk_write_start(&c, io); + + { /*---- LIB3DS_MESH_VERSION ----*/ + Lib3dsChunk c; + c.chunk = CHK_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 = CHK_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 = CHK_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 = CHK_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); + { + int i; + for (i = 0; i < file->nmaterials; ++i) { + lib3ds_material_write(file->materials[i], io); + } + } + { + Lib3dsChunk c; + int i; + + for (i = 0; i < file->ncameras; ++i) { + c.chunk = CHK_NAMED_OBJECT; + lib3ds_chunk_write_start(&c, io); + lib3ds_io_write_string(io, file->cameras[i]->name); + lib3ds_camera_write(file->cameras[i], io); + object_flags_write(file->cameras[i]->object_flags, io); + lib3ds_chunk_write_end(&c, io); + } + } + { + Lib3dsChunk c; + int i; + + for (i = 0; i < file->nlights; ++i) { + c.chunk = CHK_NAMED_OBJECT; + lib3ds_chunk_write_start(&c, io); + lib3ds_io_write_string(io, file->lights[i]->name); + lib3ds_light_write(file->lights[i], io); + object_flags_write(file->lights[i]->object_flags, io); + lib3ds_chunk_write_end(&c, io); + } + } + { + Lib3dsChunk c; + int i; + + for (i = 0; i < file->nmeshes; ++i) { + c.chunk = CHK_NAMED_OBJECT; + lib3ds_chunk_write_start(&c, io); + lib3ds_io_write_string(io, file->meshes[i]->name); + lib3ds_mesh_write(file, file->meshes[i], io); + object_flags_write(file->meshes[i]->object_flags, io); + lib3ds_chunk_write_end(&c, io); + } + } + + lib3ds_chunk_write_end(&c, io); +} + + + +static void +nodes_write(Lib3dsNode *first_node, uint16_t *default_id, uint16_t parent_id, Lib3dsIo *io) { + Lib3dsNode *p; + for (p = first_node; p != NULL; p = p->next) { + uint16_t node_id; + if ((p->type == LIB3DS_NODE_AMBIENT_COLOR) || (p->node_id != 65535)) { + node_id = p->node_id; + } else { + node_id = *default_id; + } + ++(*default_id); + lib3ds_node_write(p, node_id, parent_id, io); + + nodes_write(p->childs, default_id, node_id, io); + } +} + + +static void +kfdata_write(Lib3dsFile *file, Lib3dsIo *io) { + Lib3dsChunk c; + + if (!file->nodes) { + return; + } + + c.chunk = CHK_KFDATA; + lib3ds_chunk_write_start(&c, io); + + { /*---- LIB3DS_KFHDR ----*/ + Lib3dsChunk c; + c.chunk = CHK_KFHDR; + c.size = 6 + 2 + (uint32_t)strlen(file->name) + 1 + 4; + lib3ds_chunk_write(&c, io); + lib3ds_io_write_intw(io, (int16_t)file->keyf_revision); + lib3ds_io_write_string(io, file->name); + lib3ds_io_write_intd(io, file->frames); + } + { /*---- LIB3DS_KFSEG ----*/ + Lib3dsChunk c; + c.chunk = CHK_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 = CHK_KFCURTIME; + c.size = 10; + lib3ds_chunk_write(&c, io); + lib3ds_io_write_intd(io, file->current_frame); + } + lib3ds_viewport_write(&file->viewport_keyf, io); + + { + uint16_t default_id = 0; + nodes_write(file->nodes, &default_id, 65535, io); + } + + lib3ds_chunk_write_end(&c, io); +} + + +/*! + * 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. + */ +int +lib3ds_file_write(Lib3dsFile *file, Lib3dsIo *io) { + Lib3dsChunk c; + Lib3dsIoImpl *impl; + + lib3ds_io_setup(io); + impl = (Lib3dsIoImpl*)io->impl; + + if (setjmp(impl->jmpbuf) != 0) { + lib3ds_io_cleanup(io); + return FALSE; + } + + c.chunk = CHK_M3DMAGIC; + lib3ds_chunk_write_start(&c, io); + + { /*---- LIB3DS_M3D_VERSION ----*/ + Lib3dsChunk c; + + c.chunk = CHK_M3D_VERSION; + c.size = 10; + lib3ds_chunk_write(&c, io); + lib3ds_io_write_dword(io, file->mesh_version); + } + + mdata_write(file, io); + kfdata_write(file, io); + + lib3ds_chunk_write_end(&c, io); + + memset(impl->jmpbuf, 0, sizeof(impl->jmpbuf)); + lib3ds_io_cleanup(io); + return TRUE; +} + + +void lib3ds_file_reserve_materials(Lib3dsFile *file, int size, int force) { + assert(file); + lib3ds_util_reserve_array((void***)&file->materials, &file->nmaterials, &file->materials_size, + size, force, (Lib3dsFreeFunc)lib3ds_material_free); +} + + +void +lib3ds_file_insert_material(Lib3dsFile *file, Lib3dsMaterial *material, int index) { + assert(file); + lib3ds_util_insert_array((void***)&file->materials, &file->nmaterials, &file->materials_size, material, index); +} + + +void +lib3ds_file_remove_material(Lib3dsFile *file, int index) { + assert(file); + lib3ds_util_remove_array((void***)&file->materials, &file->nmaterials, index, (Lib3dsFreeFunc)lib3ds_material_free); +} + + +int +lib3ds_file_material_by_name(Lib3dsFile *file, const char *name) { + int i; + + assert(file); + for (i = 0; i < file->nmaterials; ++i) { + if (strcmp(file->materials[i]->name, name) == 0) { + return(i); + } + } + return -1; +} + + +void +lib3ds_file_reserve_cameras(Lib3dsFile *file, int size, int force) { + assert(file); + lib3ds_util_reserve_array((void***)&file->cameras, &file->ncameras, &file->cameras_size, + size, force, (Lib3dsFreeFunc)lib3ds_camera_free); +} + + +void +lib3ds_file_insert_camera(Lib3dsFile *file, Lib3dsCamera *camera, int index) { + assert(file); + lib3ds_util_insert_array((void***)&file->cameras, &file->ncameras, &file->cameras_size, camera, index); +} + + +void +lib3ds_file_remove_camera(Lib3dsFile *file, int index) { + assert(file); + lib3ds_util_remove_array((void***)&file->cameras, &file->ncameras, index, (Lib3dsFreeFunc)lib3ds_camera_free); +} + + +int +lib3ds_file_camera_by_name(Lib3dsFile *file, const char *name) { + int i; + + assert(file); + for (i = 0; i < file->ncameras; ++i) { + if (strcmp(file->cameras[i]->name, name) == 0) { + return(i); + } + } + return -1; +} + + +void +lib3ds_file_reserve_lights(Lib3dsFile *file, int size, int force) { + assert(file); + lib3ds_util_reserve_array((void***)&file->lights, &file->nlights, &file->lights_size, + size, force, (Lib3dsFreeFunc)lib3ds_light_free); +} + + +void +lib3ds_file_insert_light(Lib3dsFile *file, Lib3dsLight *light, int index) { + assert(file); + lib3ds_util_insert_array((void***)&file->lights, &file->nlights, &file->lights_size, light, index); +} + + +void +lib3ds_file_remove_light(Lib3dsFile *file, int index) { + assert(file); + lib3ds_util_remove_array((void***)&file->lights, &file->nlights, index, (Lib3dsFreeFunc)lib3ds_light_free); +} + + +int +lib3ds_file_light_by_name(Lib3dsFile *file, const char *name) { + int i; + + assert(file); + for (i = 0; i < file->nlights; ++i) { + if (strcmp(file->lights[i]->name, name) == 0) { + return(i); + } + } + return -1; +} + + +void +lib3ds_file_reserve_meshes(Lib3dsFile *file, int size, int force) { + assert(file); + lib3ds_util_reserve_array((void***)&file->meshes, &file->nmeshes, &file->meshes_size, + size, force, (Lib3dsFreeFunc)lib3ds_mesh_free); +} + + +void +lib3ds_file_insert_mesh(Lib3dsFile *file, Lib3dsMesh *mesh, int index) { + assert(file); + lib3ds_util_insert_array((void***)&file->meshes, &file->nmeshes, &file->meshes_size, mesh, index); +} + + +void +lib3ds_file_remove_mesh(Lib3dsFile *file, int index) { + assert(file); + lib3ds_util_remove_array((void***)&file->meshes, &file->nmeshes, index, (Lib3dsFreeFunc)lib3ds_mesh_free); +} + + +int +lib3ds_file_mesh_by_name(Lib3dsFile *file, const char *name) { + int i; + + assert(file); + for (i = 0; i < file->nmeshes; ++i) { + if (strcmp(file->meshes[i]->name, name) == 0) { + return(i); + } + } + return -1; +} + + +Lib3dsMesh* +lib3ds_file_mesh_for_node(Lib3dsFile *file, Lib3dsNode *node) { + int index; + Lib3dsMeshInstanceNode *n; + + if (node->type != LIB3DS_NODE_MESH_INSTANCE) + return NULL; + n = (Lib3dsMeshInstanceNode*)node; + + index = lib3ds_file_mesh_by_name(file, node->name); + + return (index >= 0)? file->meshes[index] : NULL; +} + + +/*! + * 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 + */ +Lib3dsNode* +lib3ds_file_node_by_name(Lib3dsFile *file, const char* name, Lib3dsNodeType 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 + */ +Lib3dsNode* +lib3ds_file_node_by_id(Lib3dsFile *file, uint16_t 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); +} + + +void +lib3ds_file_append_node(Lib3dsFile *file, Lib3dsNode *node, Lib3dsNode *parent) { + Lib3dsNode *p; + + assert(file); + assert(node); + p = parent? parent->childs : file->nodes; + if (p) { + while (p->next) { + p = p->next; + } + p->next = node; + } else { + if (parent) { + parent->childs = node; + } else { + file->nodes = node; + } + } + node->parent = parent; + node->next = NULL; +} + + +void +lib3ds_file_insert_node(Lib3dsFile *file, Lib3dsNode *node, Lib3dsNode *before) { + Lib3dsNode *p, *q; + + assert(node); + assert(file); + + if (before) { + p = before->parent? before->parent->childs : file->nodes; + assert(p); + q = NULL; + while (p != before) { + q = p; + p = p->next; + } + if (q) { + node->next = q->next; + q->next = node; + } else { + node->next = file->nodes; + file->nodes = node; + } + node->parent = before->parent; + } else { + node->next = file->nodes; + node->parent = NULL; + file->nodes = node; + } +} + + +/*! + * 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 + */ +void +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; + } + + 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; + } + + if (!p) { + file->nodes = n->next; + } else { + p->next = n->next; + } + } +} + + +static void +file_minmax_node_id_impl(Lib3dsFile *file, Lib3dsNode *node, uint16_t *min_id, uint16_t *max_id) { + Lib3dsNode *p; + + if (min_id && (*min_id > node->node_id)) + *min_id = node->node_id; + if (max_id && (*max_id < node->node_id)) + *max_id = node->node_id; + + p = node->childs; + while (p) { + file_minmax_node_id_impl(file, p, min_id, max_id); + p = p->next; + } +} + + +void +lib3ds_file_minmax_node_id(Lib3dsFile *file, uint16_t *min_id, uint16_t *max_id) { + Lib3dsNode *p; + + if (min_id) + *min_id = 65535; + if (max_id) + *max_id = 0; + + p = file->nodes; + while (p) { + file_minmax_node_id_impl(file, p, min_id, max_id); + p = p->next; + } +} + + +void +lib3ds_file_bounding_box_of_objects(Lib3dsFile *file, int + include_meshes, int include_cameras, int include_lights, + float bmin[3], float bmax[3]) { + bmin[0] = bmin[1] = bmin[2] = FLT_MAX; + bmax[0] = bmax[1] = bmax[2] = -FLT_MAX; + + if (include_meshes) { + float lmin[3], lmax[3]; + int i; + for (i = 0; i < file->nmeshes; ++i) { + lib3ds_mesh_bounding_box(file->meshes[i], lmin, lmax); + lib3ds_vector_min(bmin, lmin); + lib3ds_vector_max(bmax, lmax); + } + } + if (include_cameras) { + int i; + for (i = 0; i < file->ncameras; ++i) { + lib3ds_vector_min(bmin, file->cameras[i]->position); + lib3ds_vector_max(bmax, file->cameras[i]->position); + lib3ds_vector_min(bmin, file->cameras[i]->target); + lib3ds_vector_max(bmax, file->cameras[i]->target); + } + } + if (include_lights) { + int i; + for (i = 0; i < file->ncameras; ++i) { + lib3ds_vector_min(bmin, file->lights[i]->position); + lib3ds_vector_max(bmax, file->lights[i]->position); + if (file->lights[i]->spot_light) { + lib3ds_vector_min(bmin, file->lights[i]->target); + lib3ds_vector_max(bmax, file->lights[i]->target); + } + } + } +} + + +static void +file_bounding_box_of_nodes_impl(Lib3dsNode *node, Lib3dsFile *file, + int include_meshes, int include_cameras, int include_lights, + float bmin[3], float bmax[3], float matrix[4][4]) { + switch (node->type) { + case LIB3DS_NODE_MESH_INSTANCE: + if (include_meshes) { + int index; + Lib3dsMeshInstanceNode *n = (Lib3dsMeshInstanceNode*)node; + + index = lib3ds_file_mesh_by_name(file, n->instance_name); + if (index < 0) + index = lib3ds_file_mesh_by_name(file, node->name); + if (index >= 0) { + Lib3dsMesh *mesh; + float inv_matrix[4][4], M[4][4]; + float v[3]; + int i; + + mesh = file->meshes[index]; + lib3ds_matrix_copy(inv_matrix, mesh->matrix); + lib3ds_matrix_inv(inv_matrix); + lib3ds_matrix_mult(M, matrix, node->matrix); + lib3ds_matrix_translate(M, -n->pivot[0], -n->pivot[1], -n->pivot[2]); + lib3ds_matrix_mult(M, M, inv_matrix); + + for (i = 0; i < mesh->nvertices; ++i) { + lib3ds_vector_transform(v, M, mesh->vertices[i]); + lib3ds_vector_min(bmin, v); + lib3ds_vector_max(bmax, v); + } + } + } + break; + + case LIB3DS_NODE_CAMERA: + case LIB3DS_NODE_CAMERA_TARGET: + if (include_cameras) { + float z[3], v[3]; + float M[4][4]; + lib3ds_matrix_mult(M, matrix, node->matrix); + lib3ds_vector_zero(z); + lib3ds_vector_transform(v, M, z); + lib3ds_vector_min(bmin, v); + lib3ds_vector_max(bmax, v); + } + break; + + case LIB3DS_NODE_OMNILIGHT: + case LIB3DS_NODE_SPOTLIGHT: + case LIB3DS_NODE_SPOTLIGHT_TARGET: + if (include_lights) { + float z[3], v[3]; + float M[4][4]; + lib3ds_matrix_mult(M, matrix, node->matrix); + lib3ds_vector_zero(z); + lib3ds_vector_transform(v, M, z); + lib3ds_vector_min(bmin, v); + lib3ds_vector_max(bmax, v); + } + break; + } + { + Lib3dsNode *p = node->childs; + while (p) { + file_bounding_box_of_nodes_impl(p, file, include_meshes, include_cameras, include_lights, bmin, bmax, matrix); + p = p->next; + } + } +} + + +void +lib3ds_file_bounding_box_of_nodes(Lib3dsFile *file, + int include_meshes, int include_cameras,int include_lights, + float bmin[3], float bmax[3], float matrix[4][4]) { + Lib3dsNode *p; + float M[4][4]; + + if (matrix) { + lib3ds_matrix_copy(M, matrix); + } else { + lib3ds_matrix_identity(M); + } + + bmin[0] = bmin[1] = bmin[2] = FLT_MAX; + bmax[0] = bmax[1] = bmax[2] = -FLT_MAX; + p = file->nodes; + while (p) { + file_bounding_box_of_nodes_impl(p, file, include_meshes, include_cameras, include_lights, bmin, bmax, M); + p = p->next; + } +} + + +void +lib3ds_file_create_nodes_for_meshes(Lib3dsFile *file) { + Lib3dsNode *p; + int i; + for (i = 0; i < file->nmeshes; ++i) { + Lib3dsMesh *mesh = file->meshes[i]; + p = lib3ds_node_new(LIB3DS_NODE_MESH_INSTANCE); + strcpy(p->name, mesh->name); + lib3ds_file_insert_node(file, p, NULL); + } +} diff --git a/src/osgPlugins/3ds/lib3ds/lib3ds_io.c b/src/osgPlugins/3ds/lib3ds/lib3ds_io.c index a3b1fa317..8cf681185 100644 --- a/src/osgPlugins/3ds/lib3ds/lib3ds_io.c +++ b/src/osgPlugins/3ds/lib3ds/lib3ds_io.c @@ -1,521 +1,521 @@ -/* - Copyright (C) 1996-2008 by Jan Eric Kyprianidis - 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. - - Thisprogram 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, see . -*/ -#include "lib3ds_impl.h" - -/* --- Code for OpenSceneGraph --- */ -#include "lib3ds.h" // For setByteOrder() -#include - -static bool s_requiresByteSwap = false; -extern LIB3DSAPI void setByteOrder() -{ - s_requiresByteSwap = osg::getCpuByteOrder()==osg::BigEndian; -} -/* --- (end) Code for OpenSceneGraph --- */ - -typedef union { - uint32_t dword_value; - float float_value; -} Lib3dsDwordFloat; - - -void -lib3ds_io_setup(Lib3dsIo *io) { - assert(io); - io->impl = calloc(sizeof(Lib3dsIoImpl), 1); -} - - -void -lib3ds_io_cleanup(Lib3dsIo *io) { - Lib3dsIoImpl *impl; - assert(io); - impl = (Lib3dsIoImpl*)io->impl; - if (impl->tmp_mem) { - free(impl->tmp_mem); - impl->tmp_mem = NULL; - } - if (impl->tmp_node) { - lib3ds_node_free(impl->tmp_node); - impl->tmp_node = NULL; - } - free(impl); -} - - -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); -} - - -static void -lib3ds_io_log_str(Lib3dsIo *io, Lib3dsLogLevel level, const char *str) { - if (!io || !io->log_func) - return; - (*io->log_func)(io->self, level, ((Lib3dsIoImpl*)io->impl)->log_indent, str); -} - - -void -lib3ds_io_log(Lib3dsIo *io, Lib3dsLogLevel level, const char *format, ...) { - va_list args; - /* FIXME */ char str[1024]; - - assert(io); - if (!io || !io->log_func) - return; - - va_start(args, format); - /* FIXME: */ vsprintf(str, format, args); - lib3ds_io_log_str(io, level, str); - - if (level == LIB3DS_LOG_ERROR) { - longjmp(((Lib3dsIoImpl*)io->impl)->jmpbuf, 1); - } -} - - -void -lib3ds_io_log_indent(Lib3dsIo *io, int indent) { - assert(io); - if (!io) - return; - ((Lib3dsIoImpl*)io->impl)->log_indent += indent; -} - - -void -lib3ds_io_read_error(Lib3dsIo *io) { - lib3ds_io_log(io, LIB3DS_LOG_ERROR, "Reading from input stream failed."); -} - - -void -lib3ds_io_write_error(Lib3dsIo *io) { - lib3ds_io_log(io, LIB3DS_LOG_ERROR, "Writing to output stream failed."); -} - - -/*! - * Read a byte from a file stream. - */ -uint8_t -lib3ds_io_read_byte(Lib3dsIo *io) { - uint8_t b; - - assert(io); - lib3ds_io_read(io, &b, 1); - return(b); -} - - -/** - * Read a word from a file stream in little endian format. - */ -uint16_t -lib3ds_io_read_word(Lib3dsIo *io) { - uint8_t b[2]; - uint16_t w; - - assert(io); - lib3ds_io_read(io, b, 2); - w = ((uint16_t)b[1] << 8) | - ((uint16_t)b[0]); - /* --- Code for OpenSceneGraph --- */ - if (s_requiresByteSwap) - { - osg::swapBytes2((char*)&w); - } - /* --- (end) Code for OpenSceneGraph --- */ - return(w); -} - - -/*! - * Read a dword from file a stream in little endian format. - */ -uint32_t -lib3ds_io_read_dword(Lib3dsIo *io) { - uint8_t b[4]; - uint32_t d; - - assert(io); - lib3ds_io_read(io, b, 4); - d = ((uint32_t)b[3] << 24) | - ((uint32_t)b[2] << 16) | - ((uint32_t)b[1] << 8) | - ((uint32_t)b[0]); - /* --- Code for OpenSceneGraph --- */ - if (s_requiresByteSwap) - { - osg::swapBytes4((char*)&d); - } - /* --- (end) Code for OpenSceneGraph --- */ - return(d); -} - - -/*! - * Read a signed byte from a file stream. - */ -int8_t -lib3ds_io_read_intb(Lib3dsIo *io) { - int8_t b; - - assert(io); - lib3ds_io_read(io, &b, 1); - return(b); -} - - -/*! - * Read a signed word from a file stream in little endian format. - */ -int16_t -lib3ds_io_read_intw(Lib3dsIo *io) { - uint8_t b[2]; - uint16_t w; - - assert(io); - lib3ds_io_read(io, b, 2); - w = ((uint16_t)b[1] << 8) | - ((uint16_t)b[0]); - /* --- Code for OpenSceneGraph --- */ - if (s_requiresByteSwap) - { - osg::swapBytes2((char*)&w); - } - /* --- (end) Code for OpenSceneGraph --- */ - return((int16_t)w); -} - - -/*! - * Read a signed dword a from file stream in little endian format. - */ -int32_t -lib3ds_io_read_intd(Lib3dsIo *io) { - uint8_t b[4]; - uint32_t d; - - assert(io); - lib3ds_io_read(io, b, 4); - d = ((uint32_t)b[3] << 24) | - ((uint32_t)b[2] << 16) | - ((uint32_t)b[1] << 8) | - ((uint32_t)b[0]); - /* --- Code for OpenSceneGraph --- */ - if (s_requiresByteSwap) - { - osg::swapBytes4((char*)&d); - } - /* --- (end) Code for OpenSceneGraph --- */ - return((int32_t)d); -} - - -/*! - * Read a float from a file stream in little endian format. - */ -float -lib3ds_io_read_float(Lib3dsIo *io) { - uint8_t b[4]; - Lib3dsDwordFloat d; - - assert(io); - lib3ds_io_read(io, b, 4); - d.dword_value = ((uint32_t)b[3] << 24) | - ((uint32_t)b[2] << 16) | - ((uint32_t)b[1] << 8) | - ((uint32_t)b[0]); - /* --- Code for OpenSceneGraph --- */ - if (s_requiresByteSwap) - { - osg::swapBytes4((char*)&(d.dword_value)); - } - /* --- (end) Code for OpenSceneGraph --- */ - return d.float_value; -} - - -/*! - * Read a vector from a file stream in little endian format. - * - * \param io IO input handle. - * \param v The vector to store the data. - */ -void -lib3ds_io_read_vector(Lib3dsIo *io, float v[3]) { - assert(io); - v[0] = lib3ds_io_read_float(io); - v[1] = lib3ds_io_read_float(io); - v[2] = lib3ds_io_read_float(io); -} - - -void -lib3ds_io_read_rgb(Lib3dsIo *io, float rgb[3]) { - assert(io); - rgb[0] = lib3ds_io_read_float(io); - rgb[1] = lib3ds_io_read_float(io); - rgb[2] = lib3ds_io_read_float(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. - */ -void -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) { - lib3ds_io_read_error(io); - } - *s++ = c; - if (!c) { - break; - } - ++k; - if (k >= buflen) { - lib3ds_io_log(io, LIB3DS_LOG_ERROR, "Invalid string in input stream."); - } - } -} - - -/*! - * Writes a byte into a file stream. - */ -void -lib3ds_io_write_byte(Lib3dsIo *io, uint8_t b) { - assert(io); - if (lib3ds_io_write(io, &b, 1) != 1) { - lib3ds_io_write_error(io); - } -} - - -/*! - * Writes a word into a little endian file stream. - */ -void -lib3ds_io_write_word(Lib3dsIo *io, uint16_t w) { - /* --- Code for OpenSceneGraph --- */ - if (s_requiresByteSwap) - { - osg::swapBytes2((char*)&w); - } - /* --- (end) Code for OpenSceneGraph --- */ - - uint8_t b[2]; - - assert(io); - b[1] = ((uint16_t)w & 0xFF00) >> 8; - b[0] = ((uint16_t)w & 0x00FF); - if (lib3ds_io_write(io, b, 2) != 2) { - lib3ds_io_write_error(io); - } -} - - -/*! - * Writes a dword into a little endian file stream. - */ -void -lib3ds_io_write_dword(Lib3dsIo *io, uint32_t d) { - /* --- Code for OpenSceneGraph --- */ - if (s_requiresByteSwap) - { - osg::swapBytes4((char*)&d); - } - /* --- (end) Code for OpenSceneGraph --- */ - uint8_t b[4]; - - assert(io); - b[3] = (uint8_t)(((uint32_t)d & 0xFF000000) >> 24); - b[2] = (uint8_t)(((uint32_t)d & 0x00FF0000) >> 16); - b[1] = (uint8_t)(((uint32_t)d & 0x0000FF00) >> 8); - b[0] = (uint8_t)(((uint32_t)d & 0x000000FF)); - if (lib3ds_io_write(io, b, 4) != 4) { - lib3ds_io_write_error(io); - } -} - - -/*! - * Writes a signed byte in a file stream. - */ -void -lib3ds_io_write_intb(Lib3dsIo *io, int8_t b) { - assert(io); - if (lib3ds_io_write(io, &b, 1) != 1) { - lib3ds_io_write_error(io); - } -} - - -/*! - * Writes a signed word into a little endian file stream. - */ -void -lib3ds_io_write_intw(Lib3dsIo *io, int16_t w) { - /* --- Code for OpenSceneGraph --- */ - if (s_requiresByteSwap) - { - osg::swapBytes2((char*)&w); - } - /* --- (end) Code for OpenSceneGraph --- */ - uint8_t b[2]; - - assert(io); - b[1] = ((uint16_t)w & 0xFF00) >> 8; - b[0] = ((uint16_t)w & 0x00FF); - if (lib3ds_io_write(io, b, 2) != 2) { - lib3ds_io_write_error(io); - } -} - - -/*! - * Writes a signed dword into a little endian file stream. - */ -void -lib3ds_io_write_intd(Lib3dsIo *io, int32_t d) { - /* --- Code for OpenSceneGraph --- */ - if (s_requiresByteSwap) - { - osg::swapBytes4((char*)&d); - } - /* --- (end) Code for OpenSceneGraph --- */ - uint8_t b[4]; - - assert(io); - b[3] = (uint8_t)(((uint32_t)d & 0xFF000000) >> 24); - b[2] = (uint8_t)(((uint32_t)d & 0x00FF0000) >> 16); - b[1] = (uint8_t)(((uint32_t)d & 0x0000FF00) >> 8); - b[0] = (uint8_t)(((uint32_t)d & 0x000000FF)); - if (lib3ds_io_write(io, b, 4) != 4) { - lib3ds_io_write_error(io); - } -} - - -/*! - * Writes a float into a little endian file stream. - */ -void -lib3ds_io_write_float(Lib3dsIo *io, float l) { - uint8_t b[4]; - Lib3dsDwordFloat d; - - assert(io); - d.float_value = l; - /* --- Code for OpenSceneGraph --- */ - if (s_requiresByteSwap) - { - osg::swapBytes4((char*)&d.dword_value); - } - /* --- (end) Code for OpenSceneGraph --- */ - b[3] = (uint8_t)(((uint32_t)d.dword_value & 0xFF000000) >> 24); - b[2] = (uint8_t)(((uint32_t)d.dword_value & 0x00FF0000) >> 16); - b[1] = (uint8_t)(((uint32_t)d.dword_value & 0x0000FF00) >> 8); - b[0] = (uint8_t)(((uint32_t)d.dword_value & 0x000000FF)); - if (lib3ds_io_write(io, b, 4) != 4) { - lib3ds_io_write_error(io); - } -} - - -/*! - * Writes a vector into a file stream in little endian format. - */ -void -lib3ds_io_write_vector(Lib3dsIo *io, float v[3]) { - int i; - for (i = 0; i < 3; ++i) { - lib3ds_io_write_float(io, v[i]); - } -} - - -void -lib3ds_io_write_rgb(Lib3dsIo *io, float rgb[3]) { - int i; - for (i = 0; i < 3; ++i) { - lib3ds_io_write_float(io, rgb[i]); - } -} - - -/*! - * Writes a zero-terminated string into a file stream. - */ -void -lib3ds_io_write_string(Lib3dsIo *io, const char *s) { - size_t len; - assert(io && s); - len = strlen(s); - if (lib3ds_io_write(io, s, len + 1) != len +1) { - lib3ds_io_write_error(io); - } -} +/* + Copyright (C) 1996-2008 by Jan Eric Kyprianidis + 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. + + Thisprogram 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, see . +*/ +#include "lib3ds_impl.h" + +/* --- Code for OpenSceneGraph --- */ +#include "lib3ds.h" // For setByteOrder() +#include + +static bool s_requiresByteSwap = false; +extern LIB3DSAPI void setByteOrder() +{ + s_requiresByteSwap = osg::getCpuByteOrder()==osg::BigEndian; +} +/* --- (end) Code for OpenSceneGraph --- */ + +typedef union { + uint32_t dword_value; + float float_value; +} Lib3dsDwordFloat; + + +void +lib3ds_io_setup(Lib3dsIo *io) { + assert(io); + io->impl = calloc(sizeof(Lib3dsIoImpl), 1); +} + + +void +lib3ds_io_cleanup(Lib3dsIo *io) { + Lib3dsIoImpl *impl; + assert(io); + impl = (Lib3dsIoImpl*)io->impl; + if (impl->tmp_mem) { + free(impl->tmp_mem); + impl->tmp_mem = NULL; + } + if (impl->tmp_node) { + lib3ds_node_free(impl->tmp_node); + impl->tmp_node = NULL; + } + free(impl); +} + + +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); +} + + +static void +lib3ds_io_log_str(Lib3dsIo *io, Lib3dsLogLevel level, const char *str) { + if (!io || !io->log_func) + return; + (*io->log_func)(io->self, level, ((Lib3dsIoImpl*)io->impl)->log_indent, str); +} + + +void +lib3ds_io_log(Lib3dsIo *io, Lib3dsLogLevel level, const char *format, ...) { + va_list args; + /* FIXME */ char str[1024]; + + assert(io); + if (!io || !io->log_func) + return; + + va_start(args, format); + /* FIXME: */ vsprintf(str, format, args); + lib3ds_io_log_str(io, level, str); + + if (level == LIB3DS_LOG_ERROR) { + longjmp(((Lib3dsIoImpl*)io->impl)->jmpbuf, 1); + } +} + + +void +lib3ds_io_log_indent(Lib3dsIo *io, int indent) { + assert(io); + if (!io) + return; + ((Lib3dsIoImpl*)io->impl)->log_indent += indent; +} + + +void +lib3ds_io_read_error(Lib3dsIo *io) { + lib3ds_io_log(io, LIB3DS_LOG_ERROR, "Reading from input stream failed."); +} + + +void +lib3ds_io_write_error(Lib3dsIo *io) { + lib3ds_io_log(io, LIB3DS_LOG_ERROR, "Writing to output stream failed."); +} + + +/*! + * Read a byte from a file stream. + */ +uint8_t +lib3ds_io_read_byte(Lib3dsIo *io) { + uint8_t b; + + assert(io); + lib3ds_io_read(io, &b, 1); + return(b); +} + + +/** + * Read a word from a file stream in little endian format. + */ +uint16_t +lib3ds_io_read_word(Lib3dsIo *io) { + uint8_t b[2]; + uint16_t w; + + assert(io); + lib3ds_io_read(io, b, 2); + w = ((uint16_t)b[1] << 8) | + ((uint16_t)b[0]); + /* --- Code for OpenSceneGraph --- */ + if (s_requiresByteSwap) + { + osg::swapBytes2((char*)&w); + } + /* --- (end) Code for OpenSceneGraph --- */ + return(w); +} + + +/*! + * Read a dword from file a stream in little endian format. + */ +uint32_t +lib3ds_io_read_dword(Lib3dsIo *io) { + uint8_t b[4]; + uint32_t d; + + assert(io); + lib3ds_io_read(io, b, 4); + d = ((uint32_t)b[3] << 24) | + ((uint32_t)b[2] << 16) | + ((uint32_t)b[1] << 8) | + ((uint32_t)b[0]); + /* --- Code for OpenSceneGraph --- */ + if (s_requiresByteSwap) + { + osg::swapBytes4((char*)&d); + } + /* --- (end) Code for OpenSceneGraph --- */ + return(d); +} + + +/*! + * Read a signed byte from a file stream. + */ +int8_t +lib3ds_io_read_intb(Lib3dsIo *io) { + int8_t b; + + assert(io); + lib3ds_io_read(io, &b, 1); + return(b); +} + + +/*! + * Read a signed word from a file stream in little endian format. + */ +int16_t +lib3ds_io_read_intw(Lib3dsIo *io) { + uint8_t b[2]; + uint16_t w; + + assert(io); + lib3ds_io_read(io, b, 2); + w = ((uint16_t)b[1] << 8) | + ((uint16_t)b[0]); + /* --- Code for OpenSceneGraph --- */ + if (s_requiresByteSwap) + { + osg::swapBytes2((char*)&w); + } + /* --- (end) Code for OpenSceneGraph --- */ + return((int16_t)w); +} + + +/*! + * Read a signed dword a from file stream in little endian format. + */ +int32_t +lib3ds_io_read_intd(Lib3dsIo *io) { + uint8_t b[4]; + uint32_t d; + + assert(io); + lib3ds_io_read(io, b, 4); + d = ((uint32_t)b[3] << 24) | + ((uint32_t)b[2] << 16) | + ((uint32_t)b[1] << 8) | + ((uint32_t)b[0]); + /* --- Code for OpenSceneGraph --- */ + if (s_requiresByteSwap) + { + osg::swapBytes4((char*)&d); + } + /* --- (end) Code for OpenSceneGraph --- */ + return((int32_t)d); +} + + +/*! + * Read a float from a file stream in little endian format. + */ +float +lib3ds_io_read_float(Lib3dsIo *io) { + uint8_t b[4]; + Lib3dsDwordFloat d; + + assert(io); + lib3ds_io_read(io, b, 4); + d.dword_value = ((uint32_t)b[3] << 24) | + ((uint32_t)b[2] << 16) | + ((uint32_t)b[1] << 8) | + ((uint32_t)b[0]); + /* --- Code for OpenSceneGraph --- */ + if (s_requiresByteSwap) + { + osg::swapBytes4((char*)&(d.dword_value)); + } + /* --- (end) Code for OpenSceneGraph --- */ + return d.float_value; +} + + +/*! + * Read a vector from a file stream in little endian format. + * + * \param io IO input handle. + * \param v The vector to store the data. + */ +void +lib3ds_io_read_vector(Lib3dsIo *io, float v[3]) { + assert(io); + v[0] = lib3ds_io_read_float(io); + v[1] = lib3ds_io_read_float(io); + v[2] = lib3ds_io_read_float(io); +} + + +void +lib3ds_io_read_rgb(Lib3dsIo *io, float rgb[3]) { + assert(io); + rgb[0] = lib3ds_io_read_float(io); + rgb[1] = lib3ds_io_read_float(io); + rgb[2] = lib3ds_io_read_float(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. + */ +void +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) { + lib3ds_io_read_error(io); + } + *s++ = c; + if (!c) { + break; + } + ++k; + if (k >= buflen) { + lib3ds_io_log(io, LIB3DS_LOG_ERROR, "Invalid string in input stream."); + } + } +} + + +/*! + * Writes a byte into a file stream. + */ +void +lib3ds_io_write_byte(Lib3dsIo *io, uint8_t b) { + assert(io); + if (lib3ds_io_write(io, &b, 1) != 1) { + lib3ds_io_write_error(io); + } +} + + +/*! + * Writes a word into a little endian file stream. + */ +void +lib3ds_io_write_word(Lib3dsIo *io, uint16_t w) { + /* --- Code for OpenSceneGraph --- */ + if (s_requiresByteSwap) + { + osg::swapBytes2((char*)&w); + } + /* --- (end) Code for OpenSceneGraph --- */ + + uint8_t b[2]; + + assert(io); + b[1] = ((uint16_t)w & 0xFF00) >> 8; + b[0] = ((uint16_t)w & 0x00FF); + if (lib3ds_io_write(io, b, 2) != 2) { + lib3ds_io_write_error(io); + } +} + + +/*! + * Writes a dword into a little endian file stream. + */ +void +lib3ds_io_write_dword(Lib3dsIo *io, uint32_t d) { + /* --- Code for OpenSceneGraph --- */ + if (s_requiresByteSwap) + { + osg::swapBytes4((char*)&d); + } + /* --- (end) Code for OpenSceneGraph --- */ + uint8_t b[4]; + + assert(io); + b[3] = (uint8_t)(((uint32_t)d & 0xFF000000) >> 24); + b[2] = (uint8_t)(((uint32_t)d & 0x00FF0000) >> 16); + b[1] = (uint8_t)(((uint32_t)d & 0x0000FF00) >> 8); + b[0] = (uint8_t)(((uint32_t)d & 0x000000FF)); + if (lib3ds_io_write(io, b, 4) != 4) { + lib3ds_io_write_error(io); + } +} + + +/*! + * Writes a signed byte in a file stream. + */ +void +lib3ds_io_write_intb(Lib3dsIo *io, int8_t b) { + assert(io); + if (lib3ds_io_write(io, &b, 1) != 1) { + lib3ds_io_write_error(io); + } +} + + +/*! + * Writes a signed word into a little endian file stream. + */ +void +lib3ds_io_write_intw(Lib3dsIo *io, int16_t w) { + /* --- Code for OpenSceneGraph --- */ + if (s_requiresByteSwap) + { + osg::swapBytes2((char*)&w); + } + /* --- (end) Code for OpenSceneGraph --- */ + uint8_t b[2]; + + assert(io); + b[1] = ((uint16_t)w & 0xFF00) >> 8; + b[0] = ((uint16_t)w & 0x00FF); + if (lib3ds_io_write(io, b, 2) != 2) { + lib3ds_io_write_error(io); + } +} + + +/*! + * Writes a signed dword into a little endian file stream. + */ +void +lib3ds_io_write_intd(Lib3dsIo *io, int32_t d) { + /* --- Code for OpenSceneGraph --- */ + if (s_requiresByteSwap) + { + osg::swapBytes4((char*)&d); + } + /* --- (end) Code for OpenSceneGraph --- */ + uint8_t b[4]; + + assert(io); + b[3] = (uint8_t)(((uint32_t)d & 0xFF000000) >> 24); + b[2] = (uint8_t)(((uint32_t)d & 0x00FF0000) >> 16); + b[1] = (uint8_t)(((uint32_t)d & 0x0000FF00) >> 8); + b[0] = (uint8_t)(((uint32_t)d & 0x000000FF)); + if (lib3ds_io_write(io, b, 4) != 4) { + lib3ds_io_write_error(io); + } +} + + +/*! + * Writes a float into a little endian file stream. + */ +void +lib3ds_io_write_float(Lib3dsIo *io, float l) { + uint8_t b[4]; + Lib3dsDwordFloat d; + + assert(io); + d.float_value = l; + /* --- Code for OpenSceneGraph --- */ + if (s_requiresByteSwap) + { + osg::swapBytes4((char*)&d.dword_value); + } + /* --- (end) Code for OpenSceneGraph --- */ + b[3] = (uint8_t)(((uint32_t)d.dword_value & 0xFF000000) >> 24); + b[2] = (uint8_t)(((uint32_t)d.dword_value & 0x00FF0000) >> 16); + b[1] = (uint8_t)(((uint32_t)d.dword_value & 0x0000FF00) >> 8); + b[0] = (uint8_t)(((uint32_t)d.dword_value & 0x000000FF)); + if (lib3ds_io_write(io, b, 4) != 4) { + lib3ds_io_write_error(io); + } +} + + +/*! + * Writes a vector into a file stream in little endian format. + */ +void +lib3ds_io_write_vector(Lib3dsIo *io, float v[3]) { + int i; + for (i = 0; i < 3; ++i) { + lib3ds_io_write_float(io, v[i]); + } +} + + +void +lib3ds_io_write_rgb(Lib3dsIo *io, float rgb[3]) { + int i; + for (i = 0; i < 3; ++i) { + lib3ds_io_write_float(io, rgb[i]); + } +} + + +/*! + * Writes a zero-terminated string into a file stream. + */ +void +lib3ds_io_write_string(Lib3dsIo *io, const char *s) { + size_t len; + assert(io && s); + len = strlen(s); + if (lib3ds_io_write(io, s, len + 1) != len +1) { + lib3ds_io_write_error(io); + } +} diff --git a/src/osgPlugins/3ds/lib3ds/lib3ds_light.c b/src/osgPlugins/3ds/lib3ds/lib3ds_light.c index bdbdeb3cd..939b220a6 100644 --- a/src/osgPlugins/3ds/lib3ds/lib3ds_light.c +++ b/src/osgPlugins/3ds/lib3ds/lib3ds_light.c @@ -1,323 +1,323 @@ -/* - Copyright (C) 1996-2008 by Jan Eric Kyprianidis - 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. - - Thisprogram 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, see . -*/ -#include "lib3ds_impl.h" - - -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); -} - - -void -lib3ds_light_free(Lib3dsLight *light) { - memset(light, 0, sizeof(Lib3dsLight)); - free(light); -} - - -static void -spotlight_read(Lib3dsLight *light, Lib3dsIo *io) { - Lib3dsChunk c; - uint16_t chunk; - int i; - - lib3ds_chunk_read_start(&c, CHK_DL_SPOTLIGHT, io); - - light->spot_light = TRUE; - for (i = 0; i < 3; ++i) { - light->target[i] = lib3ds_io_read_float(io); - } - light->hotspot = lib3ds_io_read_float(io); - light->falloff = lib3ds_io_read_float(io); - lib3ds_chunk_read_tell(&c, io); - - while ((chunk = lib3ds_chunk_read_next(&c, io)) != 0) { - switch (chunk) { - case CHK_DL_SPOT_ROLL: - light->roll = lib3ds_io_read_float(io); - break; - - case CHK_DL_SHADOWED: { - light->shadowed = TRUE; - break; - } - - case CHK_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 CHK_DL_SEE_CONE: { - light->see_cone = TRUE; - break; - } - - case CHK_DL_SPOT_RECTANGULAR: { - light->rectangular_spot = TRUE; - break; - } - - case CHK_DL_SPOT_ASPECT: { - light->spot_aspect = lib3ds_io_read_float(io); - break; - } - - case CHK_DL_SPOT_PROJECTOR: { - light->use_projector = TRUE; - lib3ds_io_read_string(io, light->projector, 64); - break; - } - - case CHK_DL_SPOT_OVERSHOOT: { - light->spot_overshoot = TRUE; - break; - } - - case CHK_DL_RAY_BIAS: { - light->ray_bias = lib3ds_io_read_float(io); - break; - } - - case CHK_DL_RAYSHAD: { - light->ray_shadows = TRUE; - break; - } - - default: - lib3ds_chunk_unknown(chunk, io); - } - } - - lib3ds_chunk_read_end(&c, io); -} - - -void -lib3ds_light_read(Lib3dsLight *light, Lib3dsIo *io) { - Lib3dsChunk c; - uint16_t chunk; - - lib3ds_chunk_read_start(&c, CHK_N_DIRECT_LIGHT, io); - - { - 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 CHK_COLOR_F: { - int i; - for (i = 0; i < 3; ++i) { - light->color[i] = lib3ds_io_read_float(io); - } - break; - } - - case CHK_DL_OFF: - light->off = TRUE; - break; - - case CHK_DL_OUTER_RANGE: - light->outer_range = lib3ds_io_read_float(io); - break; - - case CHK_DL_INNER_RANGE: - light->inner_range = lib3ds_io_read_float(io); - break; - - case CHK_DL_MULTIPLIER: - light->multiplier = lib3ds_io_read_float(io); - break; - - case CHK_DL_EXCLUDE: { - /* FIXME: */ - lib3ds_chunk_unknown(chunk, io); - break; - } - - case CHK_DL_ATTENUATE: - light->attenuation = lib3ds_io_read_float(io); - break; - - case CHK_DL_SPOTLIGHT: { - lib3ds_chunk_read_reset(&c, io); - spotlight_read(light, io); - break; - } - - default: - lib3ds_chunk_unknown(chunk, io); - } - } - - lib3ds_chunk_read_end(&c, io); -} - - -void -lib3ds_light_write(Lib3dsLight *light, Lib3dsIo *io) { - Lib3dsChunk c; - - c.chunk = CHK_N_DIRECT_LIGHT; - lib3ds_chunk_write_start(&c, io); - - lib3ds_io_write_vector(io, light->position); - { /*---- LIB3DS_COLOR_F ----*/ - Lib3dsChunk c; - c.chunk = CHK_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 = CHK_DL_OFF; - c.size = 6; - lib3ds_chunk_write(&c, io); - } - { /*---- LIB3DS_DL_OUTER_RANGE ----*/ - Lib3dsChunk c; - c.chunk = CHK_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 = CHK_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 = CHK_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 = CHK_DL_ATTENUATE; - c.size = 6; - lib3ds_chunk_write(&c, io); - } - - if (light->spot_light) { - Lib3dsChunk c; - - c.chunk = CHK_DL_SPOTLIGHT; - lib3ds_chunk_write_start(&c, io); - - lib3ds_io_write_vector(io, light->target); - lib3ds_io_write_float(io, light->hotspot); - lib3ds_io_write_float(io, light->falloff); - - { /*---- LIB3DS_DL_SPOT_ROLL ----*/ - Lib3dsChunk c; - c.chunk = CHK_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 = CHK_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 = CHK_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, (int16_t)light->shadow_size); - } - if (light->see_cone) { /*---- LIB3DS_DL_SEE_CONE ----*/ - Lib3dsChunk c; - c.chunk = CHK_DL_SEE_CONE; - c.size = 6; - lib3ds_chunk_write(&c, io); - } - if (light->rectangular_spot) { /*---- LIB3DS_DL_SPOT_RECTANGULAR ----*/ - Lib3dsChunk c; - c.chunk = CHK_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 = CHK_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 = CHK_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 = CHK_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 = CHK_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 = CHK_DL_RAYSHAD; - c.size = 6; - lib3ds_chunk_write(&c, io); - } - lib3ds_chunk_write_end(&c, io); - } - - lib3ds_chunk_write_end(&c, io); -} - - +/* + Copyright (C) 1996-2008 by Jan Eric Kyprianidis + 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. + + Thisprogram 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, see . +*/ +#include "lib3ds_impl.h" + + +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); +} + + +void +lib3ds_light_free(Lib3dsLight *light) { + memset(light, 0, sizeof(Lib3dsLight)); + free(light); +} + + +static void +spotlight_read(Lib3dsLight *light, Lib3dsIo *io) { + Lib3dsChunk c; + uint16_t chunk; + int i; + + lib3ds_chunk_read_start(&c, CHK_DL_SPOTLIGHT, io); + + light->spot_light = TRUE; + for (i = 0; i < 3; ++i) { + light->target[i] = lib3ds_io_read_float(io); + } + light->hotspot = lib3ds_io_read_float(io); + light->falloff = lib3ds_io_read_float(io); + lib3ds_chunk_read_tell(&c, io); + + while ((chunk = lib3ds_chunk_read_next(&c, io)) != 0) { + switch (chunk) { + case CHK_DL_SPOT_ROLL: + light->roll = lib3ds_io_read_float(io); + break; + + case CHK_DL_SHADOWED: { + light->shadowed = TRUE; + break; + } + + case CHK_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 CHK_DL_SEE_CONE: { + light->see_cone = TRUE; + break; + } + + case CHK_DL_SPOT_RECTANGULAR: { + light->rectangular_spot = TRUE; + break; + } + + case CHK_DL_SPOT_ASPECT: { + light->spot_aspect = lib3ds_io_read_float(io); + break; + } + + case CHK_DL_SPOT_PROJECTOR: { + light->use_projector = TRUE; + lib3ds_io_read_string(io, light->projector, 64); + break; + } + + case CHK_DL_SPOT_OVERSHOOT: { + light->spot_overshoot = TRUE; + break; + } + + case CHK_DL_RAY_BIAS: { + light->ray_bias = lib3ds_io_read_float(io); + break; + } + + case CHK_DL_RAYSHAD: { + light->ray_shadows = TRUE; + break; + } + + default: + lib3ds_chunk_unknown(chunk, io); + } + } + + lib3ds_chunk_read_end(&c, io); +} + + +void +lib3ds_light_read(Lib3dsLight *light, Lib3dsIo *io) { + Lib3dsChunk c; + uint16_t chunk; + + lib3ds_chunk_read_start(&c, CHK_N_DIRECT_LIGHT, io); + + { + 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 CHK_COLOR_F: { + int i; + for (i = 0; i < 3; ++i) { + light->color[i] = lib3ds_io_read_float(io); + } + break; + } + + case CHK_DL_OFF: + light->off = TRUE; + break; + + case CHK_DL_OUTER_RANGE: + light->outer_range = lib3ds_io_read_float(io); + break; + + case CHK_DL_INNER_RANGE: + light->inner_range = lib3ds_io_read_float(io); + break; + + case CHK_DL_MULTIPLIER: + light->multiplier = lib3ds_io_read_float(io); + break; + + case CHK_DL_EXCLUDE: { + /* FIXME: */ + lib3ds_chunk_unknown(chunk, io); + break; + } + + case CHK_DL_ATTENUATE: + light->attenuation = lib3ds_io_read_float(io); + break; + + case CHK_DL_SPOTLIGHT: { + lib3ds_chunk_read_reset(&c, io); + spotlight_read(light, io); + break; + } + + default: + lib3ds_chunk_unknown(chunk, io); + } + } + + lib3ds_chunk_read_end(&c, io); +} + + +void +lib3ds_light_write(Lib3dsLight *light, Lib3dsIo *io) { + Lib3dsChunk c; + + c.chunk = CHK_N_DIRECT_LIGHT; + lib3ds_chunk_write_start(&c, io); + + lib3ds_io_write_vector(io, light->position); + { /*---- LIB3DS_COLOR_F ----*/ + Lib3dsChunk c; + c.chunk = CHK_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 = CHK_DL_OFF; + c.size = 6; + lib3ds_chunk_write(&c, io); + } + { /*---- LIB3DS_DL_OUTER_RANGE ----*/ + Lib3dsChunk c; + c.chunk = CHK_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 = CHK_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 = CHK_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 = CHK_DL_ATTENUATE; + c.size = 6; + lib3ds_chunk_write(&c, io); + } + + if (light->spot_light) { + Lib3dsChunk c; + + c.chunk = CHK_DL_SPOTLIGHT; + lib3ds_chunk_write_start(&c, io); + + lib3ds_io_write_vector(io, light->target); + lib3ds_io_write_float(io, light->hotspot); + lib3ds_io_write_float(io, light->falloff); + + { /*---- LIB3DS_DL_SPOT_ROLL ----*/ + Lib3dsChunk c; + c.chunk = CHK_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 = CHK_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 = CHK_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, (int16_t)light->shadow_size); + } + if (light->see_cone) { /*---- LIB3DS_DL_SEE_CONE ----*/ + Lib3dsChunk c; + c.chunk = CHK_DL_SEE_CONE; + c.size = 6; + lib3ds_chunk_write(&c, io); + } + if (light->rectangular_spot) { /*---- LIB3DS_DL_SPOT_RECTANGULAR ----*/ + Lib3dsChunk c; + c.chunk = CHK_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 = CHK_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 = CHK_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 = CHK_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 = CHK_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 = CHK_DL_RAYSHAD; + c.size = 6; + lib3ds_chunk_write(&c, io); + } + lib3ds_chunk_write_end(&c, io); + } + + lib3ds_chunk_write_end(&c, io); +} + + diff --git a/src/osgPlugins/3ds/lib3ds/lib3ds_material.c b/src/osgPlugins/3ds/lib3ds/lib3ds_material.c index e0b58e4a2..bb5ffc803 100644 --- a/src/osgPlugins/3ds/lib3ds/lib3ds_material.c +++ b/src/osgPlugins/3ds/lib3ds/lib3ds_material.c @@ -1,861 +1,861 @@ -/* - Copyright (C) 1996-2008 by Jan Eric Kyprianidis - 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. - - Thisprogram 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, see . -*/ -#include "lib3ds_impl.h" - - -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. - */ -Lib3dsMaterial* -lib3ds_material_new(const char* name) { - Lib3dsMaterial *mat; - - mat = (Lib3dsMaterial*)calloc(sizeof(Lib3dsMaterial), 1); - if (!mat) { - return(0); - } - - if (name) { - strcpy(mat->name, name); - } - 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); -} - - -void -lib3ds_material_free(Lib3dsMaterial *material) { - memset(material, 0, sizeof(Lib3dsMaterial)); - free(material); -} - - -static void -color_read(float rgb[3], Lib3dsIo *io) { - Lib3dsChunk c; - uint16_t chunk; - int have_lin = FALSE; - - lib3ds_chunk_read_start(&c, 0, io); - - while ((chunk = lib3ds_chunk_read_next(&c, io)) != 0) { - switch (chunk) { - case CHK_LIN_COLOR_24: { - int i; - for (i = 0; i < 3; ++i) { - rgb[i] = 1.0f * lib3ds_io_read_byte(io) / 255.0f; - } - have_lin = TRUE; - break; - } - - case CHK_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; - } - } - break; - } - - case CHK_LIN_COLOR_F: { - int i; - for (i = 0; i < 3; ++i) { - rgb[i] = lib3ds_io_read_float(io); - } - have_lin = TRUE; - break; - } - - case CHK_COLOR_F: { - if (!have_lin) { - int i; - for (i = 0; i < 3; ++i) { - rgb[i] = lib3ds_io_read_float(io); - } - } - break; - } - - default: - lib3ds_chunk_unknown(chunk, io); - } - } - - lib3ds_chunk_read_end(&c, io); -} - - -static void -int_percentage_read(float *p, Lib3dsIo *io) { - Lib3dsChunk c; - uint16_t chunk; - - lib3ds_chunk_read_start(&c, 0, io); - - while ((chunk = lib3ds_chunk_read_next(&c, io)) != 0) { - switch (chunk) { - case CHK_INT_PERCENTAGE: { - int16_t i = lib3ds_io_read_intw(io); - *p = (float)(1.0 * i / 100.0); - break; - } - - default: - lib3ds_chunk_unknown(chunk, io); - } - } - - lib3ds_chunk_read_end(&c, io); -} - - -static void -texture_map_read(Lib3dsTextureMap *map, Lib3dsIo *io) { - Lib3dsChunk c; - uint16_t chunk; - - lib3ds_chunk_read_start(&c, 0, io); - - while ((chunk = lib3ds_chunk_read_next(&c, io)) != 0) { - switch (chunk) { - case CHK_INT_PERCENTAGE: { - map->percent = 1.0f * lib3ds_io_read_intw(io) / 100.0f; - break; - } - - case CHK_MAT_MAPNAME: { - lib3ds_io_read_string(io, map->name, 64); - lib3ds_io_log(io, LIB3DS_LOG_INFO, " NAME=%s", map->name); - break; - } - - case CHK_MAT_MAP_TILING: { - map->flags = lib3ds_io_read_word(io); - break; - } - - case CHK_MAT_MAP_TEXBLUR: - map->blur = lib3ds_io_read_float(io); - break; - - case CHK_MAT_MAP_USCALE: - map->scale[0] = lib3ds_io_read_float(io); - break; - - case CHK_MAT_MAP_VSCALE: { - map->scale[1] = lib3ds_io_read_float(io); - break; - } - case CHK_MAT_MAP_UOFFSET: { - map->offset[0] = lib3ds_io_read_float(io); - break; - } - - case CHK_MAT_MAP_VOFFSET: { - map->offset[1] = lib3ds_io_read_float(io); - break; - } - - case CHK_MAT_MAP_ANG: { - map->rotation = lib3ds_io_read_float(io); - break; - } - - case CHK_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 CHK_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 CHK_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 CHK_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 CHK_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,io); - } - } - - lib3ds_chunk_read_end(&c, io); -} - - -void -lib3ds_material_read(Lib3dsMaterial *material, Lib3dsIo *io) { - Lib3dsChunk c; - uint16_t chunk; - - assert(material); - lib3ds_chunk_read_start(&c, CHK_MAT_ENTRY, io); - - while ((chunk = lib3ds_chunk_read_next(&c, io)) != 0) { - switch (chunk) { - case CHK_MAT_NAME: { - lib3ds_io_read_string(io, material->name, 64); - lib3ds_io_log(io, LIB3DS_LOG_INFO, " NAME=%s", material->name); - break; - } - - case CHK_MAT_AMBIENT: { - lib3ds_chunk_read_reset(&c, io); - color_read(material->ambient, io); - break; - } - - case CHK_MAT_DIFFUSE: { - lib3ds_chunk_read_reset(&c, io); - color_read(material->diffuse, io); - break; - } - - case CHK_MAT_SPECULAR: { - lib3ds_chunk_read_reset(&c, io); - color_read(material->specular, io); - break; - } - - case CHK_MAT_SHININESS: { - lib3ds_chunk_read_reset(&c, io); - int_percentage_read(&material->shininess, io); - break; - } - - case CHK_MAT_SHIN2PCT: { - lib3ds_chunk_read_reset(&c, io); - int_percentage_read(&material->shin_strength, io); - break; - } - - case CHK_MAT_TRANSPARENCY: { - lib3ds_chunk_read_reset(&c, io); - int_percentage_read(&material->transparency, io); - break; - } - - case CHK_MAT_XPFALL: { - lib3ds_chunk_read_reset(&c, io); - int_percentage_read(&material->falloff, io); - break; - } - - case CHK_MAT_SELF_ILPCT: { - lib3ds_chunk_read_reset(&c, io); - int_percentage_read(&material->self_illum, io); - break; - } - - case CHK_MAT_USE_XPFALL: { - material->use_falloff = TRUE; - break; - } - - case CHK_MAT_REFBLUR: { - lib3ds_chunk_read_reset(&c, io); - int_percentage_read(&material->blur, io); - break; - } - - case CHK_MAT_USE_REFBLUR: { - material->use_blur = TRUE; - break; - } - - case CHK_MAT_SHADING: { - material->shading = lib3ds_io_read_intw(io); - break; - } - - case CHK_MAT_SELF_ILLUM: { - material->self_illum_flag = TRUE; - break; - } - - case CHK_MAT_TWO_SIDE: { - material->two_sided = TRUE; - break; - } - - case CHK_MAT_DECAL: { - material->map_decal = TRUE; - break; - } - - case CHK_MAT_ADDITIVE: { - material->is_additive = TRUE; - break; - } - - case CHK_MAT_FACEMAP: { - material->face_map = TRUE; - break; - } - - case CHK_MAT_PHONGSOFT: { - material->soften = TRUE; - break; - } - - case CHK_MAT_WIRE: { - material->use_wire = TRUE; - break; - } - - case CHK_MAT_WIREABS: { - material->use_wire_abs = TRUE; - break; - } - case CHK_MAT_WIRE_SIZE: { - material->wire_size = lib3ds_io_read_float(io); - break; - } - - case CHK_MAT_TEXMAP: { - lib3ds_chunk_read_reset(&c, io); - texture_map_read(&material->texture1_map, io); - break; - } - - case CHK_MAT_TEXMASK: { - lib3ds_chunk_read_reset(&c, io); - texture_map_read(&material->texture1_mask, io); - break; - } - - case CHK_MAT_TEX2MAP: { - lib3ds_chunk_read_reset(&c, io); - texture_map_read(&material->texture2_map, io); - break; - } - - case CHK_MAT_TEX2MASK: { - lib3ds_chunk_read_reset(&c, io); - texture_map_read(&material->texture2_mask, io); - break; - } - - case CHK_MAT_OPACMAP: { - lib3ds_chunk_read_reset(&c, io); - texture_map_read(&material->opacity_map, io); - break; - } - - case CHK_MAT_OPACMASK: { - lib3ds_chunk_read_reset(&c, io); - texture_map_read(&material->opacity_mask, io); - break; - } - - case CHK_MAT_BUMPMAP: { - lib3ds_chunk_read_reset(&c, io); - texture_map_read(&material->bump_map, io); - break; - } - case CHK_MAT_BUMPMASK: { - lib3ds_chunk_read_reset(&c, io); - texture_map_read(&material->bump_mask, io); - break; - } - case CHK_MAT_SPECMAP: { - lib3ds_chunk_read_reset(&c, io); - texture_map_read(&material->specular_map, io); - break; - } - - case CHK_MAT_SPECMASK: { - lib3ds_chunk_read_reset(&c, io); - texture_map_read(&material->specular_mask, io); - break; - } - - case CHK_MAT_SHINMAP: { - lib3ds_chunk_read_reset(&c, io); - texture_map_read(&material->shininess_map, io); - break; - } - - case CHK_MAT_SHINMASK: { - lib3ds_chunk_read_reset(&c, io); - texture_map_read(&material->shininess_mask, io); - break; - } - - case CHK_MAT_SELFIMAP: { - lib3ds_chunk_read_reset(&c, io); - texture_map_read(&material->self_illum_map, io); - break; - } - - case CHK_MAT_SELFIMASK: { - lib3ds_chunk_read_reset(&c, io); - texture_map_read(&material->self_illum_mask, io); - break; - } - - case CHK_MAT_REFLMAP: { - lib3ds_chunk_read_reset(&c, io); - texture_map_read(&material->reflection_map, io); - break; - } - - case CHK_MAT_REFLMASK: { - lib3ds_chunk_read_reset(&c, io); - texture_map_read(&material->reflection_mask, io); - break; - } - - case CHK_MAT_ACUBIC: { - lib3ds_io_read_intb(io); - material->autorefl_map_anti_alias = 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, io); - } - } - - lib3ds_chunk_read_end(&c, io); -} - - -static void -color_write(float rgb[3], Lib3dsIo *io) { - Lib3dsChunk c; - - c.chunk = CHK_COLOR_24; - c.size = 9; - lib3ds_chunk_write(&c, io); - lib3ds_io_write_byte(io, (uint8_t)floor(255.0*rgb[0] + 0.5)); - lib3ds_io_write_byte(io, (uint8_t)floor(255.0*rgb[1] + 0.5)); - lib3ds_io_write_byte(io, (uint8_t)floor(255.0*rgb[2] + 0.5)); - - c.chunk = CHK_LIN_COLOR_24; - c.size = 9; - lib3ds_chunk_write(&c, io); - lib3ds_io_write_byte(io, (uint8_t)floor(255.0*rgb[0] + 0.5)); - lib3ds_io_write_byte(io, (uint8_t)floor(255.0*rgb[1] + 0.5)); - lib3ds_io_write_byte(io, (uint8_t)floor(255.0*rgb[2] + 0.5)); -} - - -static void -int_percentage_write(float p, Lib3dsIo *io) { - Lib3dsChunk c; - - c.chunk = CHK_INT_PERCENTAGE; - c.size = 8; - lib3ds_chunk_write(&c, io); - lib3ds_io_write_intw(io, (uint8_t)floor(100.0*p + 0.5)); -} - - -static void -texture_map_write(uint16_t chunk, Lib3dsTextureMap *map, Lib3dsIo *io) { - Lib3dsChunk c; - - if (strlen(map->name) == 0) { - return; - } - c.chunk = chunk; - lib3ds_chunk_write_start(&c, io); - - int_percentage_write(map->percent, io); - - { /*---- CHK_MAT_MAPNAME ----*/ - Lib3dsChunk c; - c.chunk = CHK_MAT_MAPNAME; - c.size = 6 + (uint32_t)strlen(map->name) + 1; - lib3ds_chunk_write(&c, io); - lib3ds_io_write_string(io, map->name); - } - - { /*---- CHK_MAT_MAP_TILING ----*/ - Lib3dsChunk c; - c.chunk = CHK_MAT_MAP_TILING; - c.size = 8; - lib3ds_chunk_write(&c, io); - lib3ds_io_write_word(io, (uint16_t)map->flags); - } - - { /*---- CHK_MAT_MAP_TEXBLUR ----*/ - Lib3dsChunk c; - c.chunk = CHK_MAT_MAP_TEXBLUR; - c.size = 10; - lib3ds_chunk_write(&c, io); - lib3ds_io_write_float(io, map->blur); - } - - { /*---- CHK_MAT_MAP_USCALE ----*/ - Lib3dsChunk c; - c.chunk = CHK_MAT_MAP_USCALE; - c.size = 10; - lib3ds_chunk_write(&c, io); - lib3ds_io_write_float(io, map->scale[0]); - } - - { /*---- CHK_MAT_MAP_VSCALE ----*/ - Lib3dsChunk c; - c.chunk = CHK_MAT_MAP_VSCALE; - c.size = 10; - lib3ds_chunk_write(&c, io); - lib3ds_io_write_float(io, map->scale[1]); - } - - { /*---- CHK_MAT_MAP_UOFFSET ----*/ - Lib3dsChunk c; - c.chunk = CHK_MAT_MAP_UOFFSET; - c.size = 10; - lib3ds_chunk_write(&c, io); - lib3ds_io_write_float(io, map->offset[0]); - } - - { /*---- CHK_MAT_MAP_VOFFSET ----*/ - Lib3dsChunk c; - c.chunk = CHK_MAT_MAP_VOFFSET; - c.size = 10; - lib3ds_chunk_write(&c, io); - lib3ds_io_write_float(io, map->offset[1]); - } - - { /*---- CHK_MAT_MAP_ANG ----*/ - Lib3dsChunk c; - c.chunk = CHK_MAT_MAP_ANG; - c.size = 10; - lib3ds_chunk_write(&c, io); - lib3ds_io_write_float(io, map->rotation); - } - - { /*---- CHK_MAT_MAP_COL1 ----*/ - Lib3dsChunk c; - c.chunk = CHK_MAT_MAP_COL1; - c.size = 9; - lib3ds_chunk_write(&c, io); - lib3ds_io_write_byte(io, (uint8_t)floor(255.0*map->tint_1[0] + 0.5)); - lib3ds_io_write_byte(io, (uint8_t)floor(255.0*map->tint_1[1] + 0.5)); - lib3ds_io_write_byte(io, (uint8_t)floor(255.0*map->tint_1[2] + 0.5)); - } - - { /*---- CHK_MAT_MAP_COL2 ----*/ - Lib3dsChunk c; - c.chunk = CHK_MAT_MAP_COL2; - c.size = 9; - lib3ds_chunk_write(&c, io); - lib3ds_io_write_byte(io, (uint8_t)floor(255.0*map->tint_2[0] + 0.5)); - lib3ds_io_write_byte(io, (uint8_t)floor(255.0*map->tint_2[1] + 0.5)); - lib3ds_io_write_byte(io, (uint8_t)floor(255.0*map->tint_2[2] + 0.5)); - } - - { /*---- CHK_MAT_MAP_RCOL ----*/ - Lib3dsChunk c; - c.chunk = CHK_MAT_MAP_RCOL; - c.size = 9; - lib3ds_chunk_write(&c, io); - lib3ds_io_write_byte(io, (uint8_t)floor(255.0*map->tint_r[0] + 0.5)); - lib3ds_io_write_byte(io, (uint8_t)floor(255.0*map->tint_r[1] + 0.5)); - lib3ds_io_write_byte(io, (uint8_t)floor(255.0*map->tint_r[2] + 0.5)); - } - - { /*---- CHK_MAT_MAP_GCOL ----*/ - Lib3dsChunk c; - c.chunk = CHK_MAT_MAP_GCOL; - c.size = 9; - lib3ds_chunk_write(&c, io); - lib3ds_io_write_byte(io, (uint8_t)floor(255.0*map->tint_g[0] + 0.5)); - lib3ds_io_write_byte(io, (uint8_t)floor(255.0*map->tint_g[1] + 0.5)); - lib3ds_io_write_byte(io, (uint8_t)floor(255.0*map->tint_g[2] + 0.5)); - } - - { /*---- CHK_MAT_MAP_BCOL ----*/ - Lib3dsChunk c; - c.chunk = CHK_MAT_MAP_BCOL; - c.size = 9; - lib3ds_chunk_write(&c, io); - lib3ds_io_write_byte(io, (uint8_t)floor(255.0*map->tint_b[0] + 0.5)); - lib3ds_io_write_byte(io, (uint8_t)floor(255.0*map->tint_b[1] + 0.5)); - lib3ds_io_write_byte(io, (uint8_t)floor(255.0*map->tint_b[2] + 0.5)); - } - - lib3ds_chunk_write_end(&c, io); -} - - -void -lib3ds_material_write(Lib3dsMaterial *material, Lib3dsIo *io) { - Lib3dsChunk c; - - c.chunk = CHK_MAT_ENTRY; - lib3ds_chunk_write_start(&c, io); - - { /*---- CHK_MAT_NAME ----*/ - Lib3dsChunk c; - c.chunk = CHK_MAT_NAME; - c.size = 6 + (uint32_t)strlen(material->name) + 1; - lib3ds_chunk_write(&c, io); - lib3ds_io_write_string(io, material->name); - } - - { /*---- CHK_MAT_AMBIENT ----*/ - Lib3dsChunk c; - c.chunk = CHK_MAT_AMBIENT; - c.size = 24; - lib3ds_chunk_write(&c, io); - color_write(material->ambient, io); - } - - { /*---- CHK_MAT_DIFFUSE ----*/ - Lib3dsChunk c; - c.chunk = CHK_MAT_DIFFUSE; - c.size = 24; - lib3ds_chunk_write(&c, io); - color_write(material->diffuse, io); - } - - { /*---- CHK_MAT_SPECULAR ----*/ - Lib3dsChunk c; - c.chunk = CHK_MAT_SPECULAR; - c.size = 24; - lib3ds_chunk_write(&c, io); - color_write(material->specular, io); - } - - { /*---- CHK_MAT_SHININESS ----*/ - Lib3dsChunk c; - c.chunk = CHK_MAT_SHININESS; - c.size = 14; - lib3ds_chunk_write(&c, io); - int_percentage_write(material->shininess, io); - } - - { /*---- CHK_MAT_SHIN2PCT ----*/ - Lib3dsChunk c; - c.chunk = CHK_MAT_SHIN2PCT; - c.size = 14; - lib3ds_chunk_write(&c, io); - int_percentage_write(material->shin_strength, io); - } - - { /*---- CHK_MAT_TRANSPARENCY ----*/ - Lib3dsChunk c; - c.chunk = CHK_MAT_TRANSPARENCY; - c.size = 14; - lib3ds_chunk_write(&c, io); - int_percentage_write(material->transparency, io); - } - - { /*---- CHK_MAT_XPFALL ----*/ - Lib3dsChunk c; - c.chunk = CHK_MAT_XPFALL; - c.size = 14; - lib3ds_chunk_write(&c, io); - int_percentage_write(material->falloff, io); - } - - if (material->use_falloff) { /*---- CHK_MAT_USE_XPFALL ----*/ - Lib3dsChunk c; - c.chunk = CHK_MAT_USE_XPFALL; - c.size = 6; - lib3ds_chunk_write(&c, io); - } - - { /*---- CHK_MAT_SHADING ----*/ - Lib3dsChunk c; - c.chunk = CHK_MAT_SHADING; - c.size = 8; - lib3ds_chunk_write(&c, io); - lib3ds_io_write_intw(io, (int16_t)material->shading); - } - - { /*---- CHK_MAT_REFBLUR ----*/ - Lib3dsChunk c; - c.chunk = CHK_MAT_REFBLUR; - c.size = 14; - lib3ds_chunk_write(&c, io); - int_percentage_write(material->blur, io); - } - - if (material->use_blur) { /*---- CHK_MAT_USE_REFBLUR ----*/ - Lib3dsChunk c; - c.chunk = CHK_MAT_USE_REFBLUR; - c.size = 6; - lib3ds_chunk_write(&c, io); - } - - if (material->self_illum_flag) { /*---- CHK_MAT_SELF_ILLUM ----*/ - Lib3dsChunk c; - c.chunk = CHK_MAT_SELF_ILLUM; - c.size = 6; - lib3ds_chunk_write(&c, io); - } - - if (material->two_sided) { /*---- CHK_MAT_TWO_SIDE ----*/ - Lib3dsChunk c; - c.chunk = CHK_MAT_TWO_SIDE; - c.size = 6; - lib3ds_chunk_write(&c, io); - } - - if (material->map_decal) { /*---- CHK_MAT_DECAL ----*/ - Lib3dsChunk c; - c.chunk = CHK_MAT_DECAL; - c.size = 6; - lib3ds_chunk_write(&c, io); - } - - if (material->is_additive) { /*---- CHK_MAT_ADDITIVE ----*/ - Lib3dsChunk c; - c.chunk = CHK_MAT_ADDITIVE; - c.size = 6; - lib3ds_chunk_write(&c, io); - } - - if (material->use_wire) { /*---- CHK_MAT_WIRE ----*/ - Lib3dsChunk c; - c.chunk = CHK_MAT_WIRE; - c.size = 6; - lib3ds_chunk_write(&c, io); - } - - if (material->use_wire_abs) { /*---- CHK_MAT_WIREABS ----*/ - Lib3dsChunk c; - c.chunk = CHK_MAT_WIREABS; - c.size = 6; - lib3ds_chunk_write(&c, io); - } - - { /*---- CHK_MAT_WIRE_SIZE ----*/ - Lib3dsChunk c; - c.chunk = CHK_MAT_WIRE_SIZE; - c.size = 10; - lib3ds_chunk_write(&c, io); - lib3ds_io_write_float(io, material->wire_size); - } - - if (material->face_map) { /*---- CHK_MAT_FACEMAP ----*/ - Lib3dsChunk c; - c.chunk = CHK_MAT_FACEMAP; - c.size = 6; - lib3ds_chunk_write(&c, io); - } - - if (material->soften) { /*---- CHK_MAT_PHONGSOFT ----*/ - Lib3dsChunk c; - c.chunk = CHK_MAT_PHONGSOFT; - c.size = 6; - lib3ds_chunk_write(&c, io); - } - - texture_map_write(CHK_MAT_TEXMAP, &material->texture1_map, io); - texture_map_write(CHK_MAT_TEXMASK, &material->texture1_mask, io); - texture_map_write(CHK_MAT_TEX2MAP, &material->texture2_map, io); - texture_map_write(CHK_MAT_TEX2MASK, &material->texture2_mask, io); - texture_map_write(CHK_MAT_OPACMAP, &material->opacity_map, io); - texture_map_write(CHK_MAT_OPACMASK, &material->opacity_mask, io); - texture_map_write(CHK_MAT_BUMPMAP, &material->bump_map, io); - texture_map_write(CHK_MAT_BUMPMASK, &material->bump_mask, io); - texture_map_write(CHK_MAT_SPECMAP, &material->specular_map, io); - texture_map_write(CHK_MAT_SPECMASK, &material->specular_mask, io); - texture_map_write(CHK_MAT_SHINMAP, &material->shininess_map, io); - texture_map_write(CHK_MAT_SHINMASK, &material->shininess_mask, io); - texture_map_write(CHK_MAT_SELFIMAP, &material->self_illum_map, io); - texture_map_write(CHK_MAT_SELFIMASK, &material->self_illum_mask, io); - texture_map_write(CHK_MAT_REFLMAP, &material->reflection_map, io); - texture_map_write(CHK_MAT_REFLMASK, &material->reflection_mask, io); - - { /*---- CHK_MAT_ACUBIC ----*/ - Lib3dsChunk c; - c.chunk = CHK_MAT_ACUBIC; - c.size = 18; - lib3ds_chunk_write(&c, io); - lib3ds_io_write_intb(io, 0); - lib3ds_io_write_intb(io, (int8_t)material->autorefl_map_anti_alias); - lib3ds_io_write_intw(io, (int16_t)material->autorefl_map_flags); - lib3ds_io_write_intd(io, material->autorefl_map_size); - lib3ds_io_write_intd(io, material->autorefl_map_frame_step); - } - - lib3ds_chunk_write_end(&c, io); -} +/* + Copyright (C) 1996-2008 by Jan Eric Kyprianidis + 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. + + Thisprogram 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, see . +*/ +#include "lib3ds_impl.h" + + +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. + */ +Lib3dsMaterial* +lib3ds_material_new(const char* name) { + Lib3dsMaterial *mat; + + mat = (Lib3dsMaterial*)calloc(sizeof(Lib3dsMaterial), 1); + if (!mat) { + return(0); + } + + if (name) { + strcpy(mat->name, name); + } + 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); +} + + +void +lib3ds_material_free(Lib3dsMaterial *material) { + memset(material, 0, sizeof(Lib3dsMaterial)); + free(material); +} + + +static void +color_read(float rgb[3], Lib3dsIo *io) { + Lib3dsChunk c; + uint16_t chunk; + int have_lin = FALSE; + + lib3ds_chunk_read_start(&c, 0, io); + + while ((chunk = lib3ds_chunk_read_next(&c, io)) != 0) { + switch (chunk) { + case CHK_LIN_COLOR_24: { + int i; + for (i = 0; i < 3; ++i) { + rgb[i] = 1.0f * lib3ds_io_read_byte(io) / 255.0f; + } + have_lin = TRUE; + break; + } + + case CHK_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; + } + } + break; + } + + case CHK_LIN_COLOR_F: { + int i; + for (i = 0; i < 3; ++i) { + rgb[i] = lib3ds_io_read_float(io); + } + have_lin = TRUE; + break; + } + + case CHK_COLOR_F: { + if (!have_lin) { + int i; + for (i = 0; i < 3; ++i) { + rgb[i] = lib3ds_io_read_float(io); + } + } + break; + } + + default: + lib3ds_chunk_unknown(chunk, io); + } + } + + lib3ds_chunk_read_end(&c, io); +} + + +static void +int_percentage_read(float *p, Lib3dsIo *io) { + Lib3dsChunk c; + uint16_t chunk; + + lib3ds_chunk_read_start(&c, 0, io); + + while ((chunk = lib3ds_chunk_read_next(&c, io)) != 0) { + switch (chunk) { + case CHK_INT_PERCENTAGE: { + int16_t i = lib3ds_io_read_intw(io); + *p = (float)(1.0 * i / 100.0); + break; + } + + default: + lib3ds_chunk_unknown(chunk, io); + } + } + + lib3ds_chunk_read_end(&c, io); +} + + +static void +texture_map_read(Lib3dsTextureMap *map, Lib3dsIo *io) { + Lib3dsChunk c; + uint16_t chunk; + + lib3ds_chunk_read_start(&c, 0, io); + + while ((chunk = lib3ds_chunk_read_next(&c, io)) != 0) { + switch (chunk) { + case CHK_INT_PERCENTAGE: { + map->percent = 1.0f * lib3ds_io_read_intw(io) / 100.0f; + break; + } + + case CHK_MAT_MAPNAME: { + lib3ds_io_read_string(io, map->name, 64); + lib3ds_io_log(io, LIB3DS_LOG_INFO, " NAME=%s", map->name); + break; + } + + case CHK_MAT_MAP_TILING: { + map->flags = lib3ds_io_read_word(io); + break; + } + + case CHK_MAT_MAP_TEXBLUR: + map->blur = lib3ds_io_read_float(io); + break; + + case CHK_MAT_MAP_USCALE: + map->scale[0] = lib3ds_io_read_float(io); + break; + + case CHK_MAT_MAP_VSCALE: { + map->scale[1] = lib3ds_io_read_float(io); + break; + } + case CHK_MAT_MAP_UOFFSET: { + map->offset[0] = lib3ds_io_read_float(io); + break; + } + + case CHK_MAT_MAP_VOFFSET: { + map->offset[1] = lib3ds_io_read_float(io); + break; + } + + case CHK_MAT_MAP_ANG: { + map->rotation = lib3ds_io_read_float(io); + break; + } + + case CHK_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 CHK_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 CHK_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 CHK_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 CHK_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,io); + } + } + + lib3ds_chunk_read_end(&c, io); +} + + +void +lib3ds_material_read(Lib3dsMaterial *material, Lib3dsIo *io) { + Lib3dsChunk c; + uint16_t chunk; + + assert(material); + lib3ds_chunk_read_start(&c, CHK_MAT_ENTRY, io); + + while ((chunk = lib3ds_chunk_read_next(&c, io)) != 0) { + switch (chunk) { + case CHK_MAT_NAME: { + lib3ds_io_read_string(io, material->name, 64); + lib3ds_io_log(io, LIB3DS_LOG_INFO, " NAME=%s", material->name); + break; + } + + case CHK_MAT_AMBIENT: { + lib3ds_chunk_read_reset(&c, io); + color_read(material->ambient, io); + break; + } + + case CHK_MAT_DIFFUSE: { + lib3ds_chunk_read_reset(&c, io); + color_read(material->diffuse, io); + break; + } + + case CHK_MAT_SPECULAR: { + lib3ds_chunk_read_reset(&c, io); + color_read(material->specular, io); + break; + } + + case CHK_MAT_SHININESS: { + lib3ds_chunk_read_reset(&c, io); + int_percentage_read(&material->shininess, io); + break; + } + + case CHK_MAT_SHIN2PCT: { + lib3ds_chunk_read_reset(&c, io); + int_percentage_read(&material->shin_strength, io); + break; + } + + case CHK_MAT_TRANSPARENCY: { + lib3ds_chunk_read_reset(&c, io); + int_percentage_read(&material->transparency, io); + break; + } + + case CHK_MAT_XPFALL: { + lib3ds_chunk_read_reset(&c, io); + int_percentage_read(&material->falloff, io); + break; + } + + case CHK_MAT_SELF_ILPCT: { + lib3ds_chunk_read_reset(&c, io); + int_percentage_read(&material->self_illum, io); + break; + } + + case CHK_MAT_USE_XPFALL: { + material->use_falloff = TRUE; + break; + } + + case CHK_MAT_REFBLUR: { + lib3ds_chunk_read_reset(&c, io); + int_percentage_read(&material->blur, io); + break; + } + + case CHK_MAT_USE_REFBLUR: { + material->use_blur = TRUE; + break; + } + + case CHK_MAT_SHADING: { + material->shading = lib3ds_io_read_intw(io); + break; + } + + case CHK_MAT_SELF_ILLUM: { + material->self_illum_flag = TRUE; + break; + } + + case CHK_MAT_TWO_SIDE: { + material->two_sided = TRUE; + break; + } + + case CHK_MAT_DECAL: { + material->map_decal = TRUE; + break; + } + + case CHK_MAT_ADDITIVE: { + material->is_additive = TRUE; + break; + } + + case CHK_MAT_FACEMAP: { + material->face_map = TRUE; + break; + } + + case CHK_MAT_PHONGSOFT: { + material->soften = TRUE; + break; + } + + case CHK_MAT_WIRE: { + material->use_wire = TRUE; + break; + } + + case CHK_MAT_WIREABS: { + material->use_wire_abs = TRUE; + break; + } + case CHK_MAT_WIRE_SIZE: { + material->wire_size = lib3ds_io_read_float(io); + break; + } + + case CHK_MAT_TEXMAP: { + lib3ds_chunk_read_reset(&c, io); + texture_map_read(&material->texture1_map, io); + break; + } + + case CHK_MAT_TEXMASK: { + lib3ds_chunk_read_reset(&c, io); + texture_map_read(&material->texture1_mask, io); + break; + } + + case CHK_MAT_TEX2MAP: { + lib3ds_chunk_read_reset(&c, io); + texture_map_read(&material->texture2_map, io); + break; + } + + case CHK_MAT_TEX2MASK: { + lib3ds_chunk_read_reset(&c, io); + texture_map_read(&material->texture2_mask, io); + break; + } + + case CHK_MAT_OPACMAP: { + lib3ds_chunk_read_reset(&c, io); + texture_map_read(&material->opacity_map, io); + break; + } + + case CHK_MAT_OPACMASK: { + lib3ds_chunk_read_reset(&c, io); + texture_map_read(&material->opacity_mask, io); + break; + } + + case CHK_MAT_BUMPMAP: { + lib3ds_chunk_read_reset(&c, io); + texture_map_read(&material->bump_map, io); + break; + } + case CHK_MAT_BUMPMASK: { + lib3ds_chunk_read_reset(&c, io); + texture_map_read(&material->bump_mask, io); + break; + } + case CHK_MAT_SPECMAP: { + lib3ds_chunk_read_reset(&c, io); + texture_map_read(&material->specular_map, io); + break; + } + + case CHK_MAT_SPECMASK: { + lib3ds_chunk_read_reset(&c, io); + texture_map_read(&material->specular_mask, io); + break; + } + + case CHK_MAT_SHINMAP: { + lib3ds_chunk_read_reset(&c, io); + texture_map_read(&material->shininess_map, io); + break; + } + + case CHK_MAT_SHINMASK: { + lib3ds_chunk_read_reset(&c, io); + texture_map_read(&material->shininess_mask, io); + break; + } + + case CHK_MAT_SELFIMAP: { + lib3ds_chunk_read_reset(&c, io); + texture_map_read(&material->self_illum_map, io); + break; + } + + case CHK_MAT_SELFIMASK: { + lib3ds_chunk_read_reset(&c, io); + texture_map_read(&material->self_illum_mask, io); + break; + } + + case CHK_MAT_REFLMAP: { + lib3ds_chunk_read_reset(&c, io); + texture_map_read(&material->reflection_map, io); + break; + } + + case CHK_MAT_REFLMASK: { + lib3ds_chunk_read_reset(&c, io); + texture_map_read(&material->reflection_mask, io); + break; + } + + case CHK_MAT_ACUBIC: { + lib3ds_io_read_intb(io); + material->autorefl_map_anti_alias = 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, io); + } + } + + lib3ds_chunk_read_end(&c, io); +} + + +static void +color_write(float rgb[3], Lib3dsIo *io) { + Lib3dsChunk c; + + c.chunk = CHK_COLOR_24; + c.size = 9; + lib3ds_chunk_write(&c, io); + lib3ds_io_write_byte(io, (uint8_t)floor(255.0*rgb[0] + 0.5)); + lib3ds_io_write_byte(io, (uint8_t)floor(255.0*rgb[1] + 0.5)); + lib3ds_io_write_byte(io, (uint8_t)floor(255.0*rgb[2] + 0.5)); + + c.chunk = CHK_LIN_COLOR_24; + c.size = 9; + lib3ds_chunk_write(&c, io); + lib3ds_io_write_byte(io, (uint8_t)floor(255.0*rgb[0] + 0.5)); + lib3ds_io_write_byte(io, (uint8_t)floor(255.0*rgb[1] + 0.5)); + lib3ds_io_write_byte(io, (uint8_t)floor(255.0*rgb[2] + 0.5)); +} + + +static void +int_percentage_write(float p, Lib3dsIo *io) { + Lib3dsChunk c; + + c.chunk = CHK_INT_PERCENTAGE; + c.size = 8; + lib3ds_chunk_write(&c, io); + lib3ds_io_write_intw(io, (uint8_t)floor(100.0*p + 0.5)); +} + + +static void +texture_map_write(uint16_t chunk, Lib3dsTextureMap *map, Lib3dsIo *io) { + Lib3dsChunk c; + + if (strlen(map->name) == 0) { + return; + } + c.chunk = chunk; + lib3ds_chunk_write_start(&c, io); + + int_percentage_write(map->percent, io); + + { /*---- CHK_MAT_MAPNAME ----*/ + Lib3dsChunk c; + c.chunk = CHK_MAT_MAPNAME; + c.size = 6 + (uint32_t)strlen(map->name) + 1; + lib3ds_chunk_write(&c, io); + lib3ds_io_write_string(io, map->name); + } + + { /*---- CHK_MAT_MAP_TILING ----*/ + Lib3dsChunk c; + c.chunk = CHK_MAT_MAP_TILING; + c.size = 8; + lib3ds_chunk_write(&c, io); + lib3ds_io_write_word(io, (uint16_t)map->flags); + } + + { /*---- CHK_MAT_MAP_TEXBLUR ----*/ + Lib3dsChunk c; + c.chunk = CHK_MAT_MAP_TEXBLUR; + c.size = 10; + lib3ds_chunk_write(&c, io); + lib3ds_io_write_float(io, map->blur); + } + + { /*---- CHK_MAT_MAP_USCALE ----*/ + Lib3dsChunk c; + c.chunk = CHK_MAT_MAP_USCALE; + c.size = 10; + lib3ds_chunk_write(&c, io); + lib3ds_io_write_float(io, map->scale[0]); + } + + { /*---- CHK_MAT_MAP_VSCALE ----*/ + Lib3dsChunk c; + c.chunk = CHK_MAT_MAP_VSCALE; + c.size = 10; + lib3ds_chunk_write(&c, io); + lib3ds_io_write_float(io, map->scale[1]); + } + + { /*---- CHK_MAT_MAP_UOFFSET ----*/ + Lib3dsChunk c; + c.chunk = CHK_MAT_MAP_UOFFSET; + c.size = 10; + lib3ds_chunk_write(&c, io); + lib3ds_io_write_float(io, map->offset[0]); + } + + { /*---- CHK_MAT_MAP_VOFFSET ----*/ + Lib3dsChunk c; + c.chunk = CHK_MAT_MAP_VOFFSET; + c.size = 10; + lib3ds_chunk_write(&c, io); + lib3ds_io_write_float(io, map->offset[1]); + } + + { /*---- CHK_MAT_MAP_ANG ----*/ + Lib3dsChunk c; + c.chunk = CHK_MAT_MAP_ANG; + c.size = 10; + lib3ds_chunk_write(&c, io); + lib3ds_io_write_float(io, map->rotation); + } + + { /*---- CHK_MAT_MAP_COL1 ----*/ + Lib3dsChunk c; + c.chunk = CHK_MAT_MAP_COL1; + c.size = 9; + lib3ds_chunk_write(&c, io); + lib3ds_io_write_byte(io, (uint8_t)floor(255.0*map->tint_1[0] + 0.5)); + lib3ds_io_write_byte(io, (uint8_t)floor(255.0*map->tint_1[1] + 0.5)); + lib3ds_io_write_byte(io, (uint8_t)floor(255.0*map->tint_1[2] + 0.5)); + } + + { /*---- CHK_MAT_MAP_COL2 ----*/ + Lib3dsChunk c; + c.chunk = CHK_MAT_MAP_COL2; + c.size = 9; + lib3ds_chunk_write(&c, io); + lib3ds_io_write_byte(io, (uint8_t)floor(255.0*map->tint_2[0] + 0.5)); + lib3ds_io_write_byte(io, (uint8_t)floor(255.0*map->tint_2[1] + 0.5)); + lib3ds_io_write_byte(io, (uint8_t)floor(255.0*map->tint_2[2] + 0.5)); + } + + { /*---- CHK_MAT_MAP_RCOL ----*/ + Lib3dsChunk c; + c.chunk = CHK_MAT_MAP_RCOL; + c.size = 9; + lib3ds_chunk_write(&c, io); + lib3ds_io_write_byte(io, (uint8_t)floor(255.0*map->tint_r[0] + 0.5)); + lib3ds_io_write_byte(io, (uint8_t)floor(255.0*map->tint_r[1] + 0.5)); + lib3ds_io_write_byte(io, (uint8_t)floor(255.0*map->tint_r[2] + 0.5)); + } + + { /*---- CHK_MAT_MAP_GCOL ----*/ + Lib3dsChunk c; + c.chunk = CHK_MAT_MAP_GCOL; + c.size = 9; + lib3ds_chunk_write(&c, io); + lib3ds_io_write_byte(io, (uint8_t)floor(255.0*map->tint_g[0] + 0.5)); + lib3ds_io_write_byte(io, (uint8_t)floor(255.0*map->tint_g[1] + 0.5)); + lib3ds_io_write_byte(io, (uint8_t)floor(255.0*map->tint_g[2] + 0.5)); + } + + { /*---- CHK_MAT_MAP_BCOL ----*/ + Lib3dsChunk c; + c.chunk = CHK_MAT_MAP_BCOL; + c.size = 9; + lib3ds_chunk_write(&c, io); + lib3ds_io_write_byte(io, (uint8_t)floor(255.0*map->tint_b[0] + 0.5)); + lib3ds_io_write_byte(io, (uint8_t)floor(255.0*map->tint_b[1] + 0.5)); + lib3ds_io_write_byte(io, (uint8_t)floor(255.0*map->tint_b[2] + 0.5)); + } + + lib3ds_chunk_write_end(&c, io); +} + + +void +lib3ds_material_write(Lib3dsMaterial *material, Lib3dsIo *io) { + Lib3dsChunk c; + + c.chunk = CHK_MAT_ENTRY; + lib3ds_chunk_write_start(&c, io); + + { /*---- CHK_MAT_NAME ----*/ + Lib3dsChunk c; + c.chunk = CHK_MAT_NAME; + c.size = 6 + (uint32_t)strlen(material->name) + 1; + lib3ds_chunk_write(&c, io); + lib3ds_io_write_string(io, material->name); + } + + { /*---- CHK_MAT_AMBIENT ----*/ + Lib3dsChunk c; + c.chunk = CHK_MAT_AMBIENT; + c.size = 24; + lib3ds_chunk_write(&c, io); + color_write(material->ambient, io); + } + + { /*---- CHK_MAT_DIFFUSE ----*/ + Lib3dsChunk c; + c.chunk = CHK_MAT_DIFFUSE; + c.size = 24; + lib3ds_chunk_write(&c, io); + color_write(material->diffuse, io); + } + + { /*---- CHK_MAT_SPECULAR ----*/ + Lib3dsChunk c; + c.chunk = CHK_MAT_SPECULAR; + c.size = 24; + lib3ds_chunk_write(&c, io); + color_write(material->specular, io); + } + + { /*---- CHK_MAT_SHININESS ----*/ + Lib3dsChunk c; + c.chunk = CHK_MAT_SHININESS; + c.size = 14; + lib3ds_chunk_write(&c, io); + int_percentage_write(material->shininess, io); + } + + { /*---- CHK_MAT_SHIN2PCT ----*/ + Lib3dsChunk c; + c.chunk = CHK_MAT_SHIN2PCT; + c.size = 14; + lib3ds_chunk_write(&c, io); + int_percentage_write(material->shin_strength, io); + } + + { /*---- CHK_MAT_TRANSPARENCY ----*/ + Lib3dsChunk c; + c.chunk = CHK_MAT_TRANSPARENCY; + c.size = 14; + lib3ds_chunk_write(&c, io); + int_percentage_write(material->transparency, io); + } + + { /*---- CHK_MAT_XPFALL ----*/ + Lib3dsChunk c; + c.chunk = CHK_MAT_XPFALL; + c.size = 14; + lib3ds_chunk_write(&c, io); + int_percentage_write(material->falloff, io); + } + + if (material->use_falloff) { /*---- CHK_MAT_USE_XPFALL ----*/ + Lib3dsChunk c; + c.chunk = CHK_MAT_USE_XPFALL; + c.size = 6; + lib3ds_chunk_write(&c, io); + } + + { /*---- CHK_MAT_SHADING ----*/ + Lib3dsChunk c; + c.chunk = CHK_MAT_SHADING; + c.size = 8; + lib3ds_chunk_write(&c, io); + lib3ds_io_write_intw(io, (int16_t)material->shading); + } + + { /*---- CHK_MAT_REFBLUR ----*/ + Lib3dsChunk c; + c.chunk = CHK_MAT_REFBLUR; + c.size = 14; + lib3ds_chunk_write(&c, io); + int_percentage_write(material->blur, io); + } + + if (material->use_blur) { /*---- CHK_MAT_USE_REFBLUR ----*/ + Lib3dsChunk c; + c.chunk = CHK_MAT_USE_REFBLUR; + c.size = 6; + lib3ds_chunk_write(&c, io); + } + + if (material->self_illum_flag) { /*---- CHK_MAT_SELF_ILLUM ----*/ + Lib3dsChunk c; + c.chunk = CHK_MAT_SELF_ILLUM; + c.size = 6; + lib3ds_chunk_write(&c, io); + } + + if (material->two_sided) { /*---- CHK_MAT_TWO_SIDE ----*/ + Lib3dsChunk c; + c.chunk = CHK_MAT_TWO_SIDE; + c.size = 6; + lib3ds_chunk_write(&c, io); + } + + if (material->map_decal) { /*---- CHK_MAT_DECAL ----*/ + Lib3dsChunk c; + c.chunk = CHK_MAT_DECAL; + c.size = 6; + lib3ds_chunk_write(&c, io); + } + + if (material->is_additive) { /*---- CHK_MAT_ADDITIVE ----*/ + Lib3dsChunk c; + c.chunk = CHK_MAT_ADDITIVE; + c.size = 6; + lib3ds_chunk_write(&c, io); + } + + if (material->use_wire) { /*---- CHK_MAT_WIRE ----*/ + Lib3dsChunk c; + c.chunk = CHK_MAT_WIRE; + c.size = 6; + lib3ds_chunk_write(&c, io); + } + + if (material->use_wire_abs) { /*---- CHK_MAT_WIREABS ----*/ + Lib3dsChunk c; + c.chunk = CHK_MAT_WIREABS; + c.size = 6; + lib3ds_chunk_write(&c, io); + } + + { /*---- CHK_MAT_WIRE_SIZE ----*/ + Lib3dsChunk c; + c.chunk = CHK_MAT_WIRE_SIZE; + c.size = 10; + lib3ds_chunk_write(&c, io); + lib3ds_io_write_float(io, material->wire_size); + } + + if (material->face_map) { /*---- CHK_MAT_FACEMAP ----*/ + Lib3dsChunk c; + c.chunk = CHK_MAT_FACEMAP; + c.size = 6; + lib3ds_chunk_write(&c, io); + } + + if (material->soften) { /*---- CHK_MAT_PHONGSOFT ----*/ + Lib3dsChunk c; + c.chunk = CHK_MAT_PHONGSOFT; + c.size = 6; + lib3ds_chunk_write(&c, io); + } + + texture_map_write(CHK_MAT_TEXMAP, &material->texture1_map, io); + texture_map_write(CHK_MAT_TEXMASK, &material->texture1_mask, io); + texture_map_write(CHK_MAT_TEX2MAP, &material->texture2_map, io); + texture_map_write(CHK_MAT_TEX2MASK, &material->texture2_mask, io); + texture_map_write(CHK_MAT_OPACMAP, &material->opacity_map, io); + texture_map_write(CHK_MAT_OPACMASK, &material->opacity_mask, io); + texture_map_write(CHK_MAT_BUMPMAP, &material->bump_map, io); + texture_map_write(CHK_MAT_BUMPMASK, &material->bump_mask, io); + texture_map_write(CHK_MAT_SPECMAP, &material->specular_map, io); + texture_map_write(CHK_MAT_SPECMASK, &material->specular_mask, io); + texture_map_write(CHK_MAT_SHINMAP, &material->shininess_map, io); + texture_map_write(CHK_MAT_SHINMASK, &material->shininess_mask, io); + texture_map_write(CHK_MAT_SELFIMAP, &material->self_illum_map, io); + texture_map_write(CHK_MAT_SELFIMASK, &material->self_illum_mask, io); + texture_map_write(CHK_MAT_REFLMAP, &material->reflection_map, io); + texture_map_write(CHK_MAT_REFLMASK, &material->reflection_mask, io); + + { /*---- CHK_MAT_ACUBIC ----*/ + Lib3dsChunk c; + c.chunk = CHK_MAT_ACUBIC; + c.size = 18; + lib3ds_chunk_write(&c, io); + lib3ds_io_write_intb(io, 0); + lib3ds_io_write_intb(io, (int8_t)material->autorefl_map_anti_alias); + lib3ds_io_write_intw(io, (int16_t)material->autorefl_map_flags); + lib3ds_io_write_intd(io, material->autorefl_map_size); + lib3ds_io_write_intd(io, material->autorefl_map_frame_step); + } + + lib3ds_chunk_write_end(&c, io); +} diff --git a/src/osgPlugins/3ds/lib3ds/lib3ds_math.c b/src/osgPlugins/3ds/lib3ds/lib3ds_math.c index d9dd428e7..1d38f80d8 100644 --- a/src/osgPlugins/3ds/lib3ds/lib3ds_math.c +++ b/src/osgPlugins/3ds/lib3ds/lib3ds_math.c @@ -1,62 +1,62 @@ -/* - Copyright (C) 1996-2008 by Jan Eric Kyprianidis - 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. - - Thisprogram 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, see . -*/ -#include "lib3ds_impl.h" - - -float -lib3ds_math_ease(float fp, float fc, float fn, float ease_from, float ease_to) { - double s, step; - double tofrom; - double a; - - s = step = (float)(fc - fp) / (fn - fp); - tofrom = ease_to + ease_from; - if (tofrom != 0.0) { - if (tofrom > 1.0) { - ease_to = (float)(ease_to / tofrom); - ease_from = (float)(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((float)s); -} - - -void -lib3ds_math_cubic_interp(float *v, float *a, float *p, float *q, float *b, int n, float t) { - float x, y, z, w; - int i; - - 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; - for (i = 0; i < n; ++i) { - v[i] = x * a[i] + y * b[i] + z * p[i] + w * q[i]; - } -} +/* + Copyright (C) 1996-2008 by Jan Eric Kyprianidis + 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. + + Thisprogram 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, see . +*/ +#include "lib3ds_impl.h" + + +float +lib3ds_math_ease(float fp, float fc, float fn, float ease_from, float ease_to) { + double s, step; + double tofrom; + double a; + + s = step = (float)(fc - fp) / (fn - fp); + tofrom = ease_to + ease_from; + if (tofrom != 0.0) { + if (tofrom > 1.0) { + ease_to = (float)(ease_to / tofrom); + ease_from = (float)(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((float)s); +} + + +void +lib3ds_math_cubic_interp(float *v, float *a, float *p, float *q, float *b, int n, float t) { + float x, y, z, w; + int i; + + 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; + for (i = 0; i < n; ++i) { + v[i] = x * a[i] + y * b[i] + z * p[i] + w * q[i]; + } +} diff --git a/src/osgPlugins/3ds/lib3ds/lib3ds_matrix.c b/src/osgPlugins/3ds/lib3ds/lib3ds_matrix.c index 271550566..4d4af085b 100644 --- a/src/osgPlugins/3ds/lib3ds/lib3ds_matrix.c +++ b/src/osgPlugins/3ds/lib3ds/lib3ds_matrix.c @@ -1,466 +1,466 @@ -/* - Copyright (C) 1996-2008 by Jan Eric Kyprianidis - 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. - - Thisprogram 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, see . -*/ -#include "lib3ds_impl.h" - - -/*! - * Clear a matrix to all zeros. - * - * \param m Matrix to be cleared. - */ -void -lib3ds_matrix_zero(float m[4][4]) { - 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. - */ -void -lib3ds_matrix_identity(float m[4][4]) { - 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. - */ -void -lib3ds_matrix_copy(float dest[4][4], float src[4][4]) { - memcpy(dest, src, 16 * sizeof(float)); -} - - -/*! - * Negate a matrix -- all elements negated. - */ -void -lib3ds_matrix_neg(float m[4][4]) { - int i, j; - - for (j = 0; j < 4; j++) { - for (i = 0; i < 4; i++) { - m[j][i] = -m[j][i]; - } - } -} - - -/*! - * Transpose a matrix in place. - */ -void -lib3ds_matrix_transpose(float m[4][4]) { - int i, j; - float 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. - */ -void -lib3ds_matrix_add(float m[4][4], float a[4][4], float b[4][4]) { - 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. - */ -void -lib3ds_matrix_sub(float m[4][4], float a[4][4], float b[4][4]) { - 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). - */ -void -lib3ds_matrix_mult(float m[4][4], float a[4][4], float b[4][4]) { - float tmp[4][4]; - int i, j, k; - float ab; - - memcpy(tmp, a, 16 * sizeof(float)); - 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] * b[j][k]; - m[j][i] = ab; - } - } -} - - -/*! - * Multiply a matrix by a scalar. - * - * \param m Matrix to be set. - * \param k Scalar. - */ -void -lib3ds_matrix_scalar(float m[4][4], float k) { - int i, j; - - for (j = 0; j < 4; j++) { - for (i = 0; i < 4; i++) { - m[j][i] *= k; - } - } -} - - -static float -det2x2( - float a, float b, - float c, float d) { - return((a)*(d) - (b)*(c)); -} - - -static float -det3x3( - float a1, float a2, float a3, - float b1, float b2, float b3, - float c1, float c2, float 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. - */ -float -lib3ds_matrix_det(float m[4][4]) { - float 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) - ); -} - - -/*! - * Invert a matrix in place. - * - * \param m Matrix to invert. - * - * \return LIB3DS_TRUE on success, LIB3DS_FALSE on failure. - * - * GGemsII, K.Wu, Fast Matrix Inversion - */ -int -lib3ds_matrix_inv(float m[4][4]) { - int i, j, k; - int pvt_i[4], pvt_j[4]; /* Locations of pivot elements */ - float pvt_val; /* Value of current pivot element */ - float hold; /* Temporary storage */ - float 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(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(TRUE); -} - - -/*! - * Apply a translation to a matrix. - */ -void -lib3ds_matrix_translate(float m[4][4], float x, float y, float 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 scale factors to a matrix. - */ -void -lib3ds_matrix_scale(float m[4][4], float x, float y, float z) { - int i; - - for (i = 0; i < 4; i++) { - m[0][i] *= x; - m[1][i] *= y; - m[2][i] *= z; - } -} - - -/*! - * Apply a rotation about an arbitrary axis to a matrix. - */ -void -lib3ds_matrix_rotate_quat(float m[4][4], float q[4]) { - float s, xs, ys, zs, wx, wy, wz, xx, xy, xz, yy, yz, zz, l; - float R[4][4]; - - 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, m, R); -} - - -/*! - * Apply a rotation about an arbitrary axis to a matrix. - */ -void -lib3ds_matrix_rotate(float m[4][4], float angle, float ax, float ay, float az) { - float q[4]; - float axis[3]; - - lib3ds_vector_make(axis, ax, ay, az); - lib3ds_quat_axis_angle(q, axis, angle); - lib3ds_matrix_rotate_quat(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 - */ -void -lib3ds_matrix_camera(float matrix[4][4], float pos[3], float tgt[3], float roll) { - float M[4][4]; - float x[3], y[3], z[3]; - - 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(matrix, roll, 0, 1, 0); - lib3ds_matrix_mult(matrix, matrix, M); - lib3ds_matrix_translate(matrix, -pos[0], -pos[1], -pos[2]); -} - - - - - - +/* + Copyright (C) 1996-2008 by Jan Eric Kyprianidis + 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. + + Thisprogram 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, see . +*/ +#include "lib3ds_impl.h" + + +/*! + * Clear a matrix to all zeros. + * + * \param m Matrix to be cleared. + */ +void +lib3ds_matrix_zero(float m[4][4]) { + 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. + */ +void +lib3ds_matrix_identity(float m[4][4]) { + 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. + */ +void +lib3ds_matrix_copy(float dest[4][4], float src[4][4]) { + memcpy(dest, src, 16 * sizeof(float)); +} + + +/*! + * Negate a matrix -- all elements negated. + */ +void +lib3ds_matrix_neg(float m[4][4]) { + int i, j; + + for (j = 0; j < 4; j++) { + for (i = 0; i < 4; i++) { + m[j][i] = -m[j][i]; + } + } +} + + +/*! + * Transpose a matrix in place. + */ +void +lib3ds_matrix_transpose(float m[4][4]) { + int i, j; + float 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. + */ +void +lib3ds_matrix_add(float m[4][4], float a[4][4], float b[4][4]) { + 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. + */ +void +lib3ds_matrix_sub(float m[4][4], float a[4][4], float b[4][4]) { + 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). + */ +void +lib3ds_matrix_mult(float m[4][4], float a[4][4], float b[4][4]) { + float tmp[4][4]; + int i, j, k; + float ab; + + memcpy(tmp, a, 16 * sizeof(float)); + 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] * b[j][k]; + m[j][i] = ab; + } + } +} + + +/*! + * Multiply a matrix by a scalar. + * + * \param m Matrix to be set. + * \param k Scalar. + */ +void +lib3ds_matrix_scalar(float m[4][4], float k) { + int i, j; + + for (j = 0; j < 4; j++) { + for (i = 0; i < 4; i++) { + m[j][i] *= k; + } + } +} + + +static float +det2x2( + float a, float b, + float c, float d) { + return((a)*(d) - (b)*(c)); +} + + +static float +det3x3( + float a1, float a2, float a3, + float b1, float b2, float b3, + float c1, float c2, float 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. + */ +float +lib3ds_matrix_det(float m[4][4]) { + float 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) + ); +} + + +/*! + * Invert a matrix in place. + * + * \param m Matrix to invert. + * + * \return LIB3DS_TRUE on success, LIB3DS_FALSE on failure. + * + * GGemsII, K.Wu, Fast Matrix Inversion + */ +int +lib3ds_matrix_inv(float m[4][4]) { + int i, j, k; + int pvt_i[4], pvt_j[4]; /* Locations of pivot elements */ + float pvt_val; /* Value of current pivot element */ + float hold; /* Temporary storage */ + float 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(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(TRUE); +} + + +/*! + * Apply a translation to a matrix. + */ +void +lib3ds_matrix_translate(float m[4][4], float x, float y, float 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 scale factors to a matrix. + */ +void +lib3ds_matrix_scale(float m[4][4], float x, float y, float z) { + int i; + + for (i = 0; i < 4; i++) { + m[0][i] *= x; + m[1][i] *= y; + m[2][i] *= z; + } +} + + +/*! + * Apply a rotation about an arbitrary axis to a matrix. + */ +void +lib3ds_matrix_rotate_quat(float m[4][4], float q[4]) { + float s, xs, ys, zs, wx, wy, wz, xx, xy, xz, yy, yz, zz, l; + float R[4][4]; + + 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, m, R); +} + + +/*! + * Apply a rotation about an arbitrary axis to a matrix. + */ +void +lib3ds_matrix_rotate(float m[4][4], float angle, float ax, float ay, float az) { + float q[4]; + float axis[3]; + + lib3ds_vector_make(axis, ax, ay, az); + lib3ds_quat_axis_angle(q, axis, angle); + lib3ds_matrix_rotate_quat(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 + */ +void +lib3ds_matrix_camera(float matrix[4][4], float pos[3], float tgt[3], float roll) { + float M[4][4]; + float x[3], y[3], z[3]; + + 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(matrix, roll, 0, 1, 0); + lib3ds_matrix_mult(matrix, matrix, M); + lib3ds_matrix_translate(matrix, -pos[0], -pos[1], -pos[2]); +} + + + + + + diff --git a/src/osgPlugins/3ds/lib3ds/lib3ds_mesh.c b/src/osgPlugins/3ds/lib3ds/lib3ds_mesh.c index ae3433154..df2157a23 100644 --- a/src/osgPlugins/3ds/lib3ds/lib3ds_mesh.c +++ b/src/osgPlugins/3ds/lib3ds/lib3ds_mesh.c @@ -1,677 +1,677 @@ -/* - Copyright (C) 1996-2008 by Jan Eric Kyprianidis - 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. - - Thisprogram 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, see . -*/ -#include "lib3ds_impl.h" - - -/*! - * 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. - */ -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_type = LIB3DS_MAP_NONE; - return (mesh); -} - - -/*! - * Free a mesh object and all of its resources. - * - * \param mesh Mesh object to be freed. - */ -void -lib3ds_mesh_free(Lib3dsMesh *mesh) { - lib3ds_mesh_resize_vertices(mesh, 0, 0, 0); - lib3ds_mesh_resize_faces(mesh, 0); - memset(mesh, 0, sizeof(Lib3dsMesh)); - free(mesh); -} - - -void -lib3ds_mesh_resize_vertices(Lib3dsMesh *mesh, int nvertices, int use_texcos, int use_flags) { - assert(mesh); - mesh->vertices = (float (*)[3])lib3ds_util_realloc_array(mesh->vertices, mesh->nvertices, nvertices, 3 * sizeof(float)); - mesh->texcos = (float (*)[2])lib3ds_util_realloc_array( - mesh->texcos, - mesh->texcos? mesh->nvertices : 0, - use_texcos? nvertices : 0, - 2 * sizeof(float) - ); - mesh->vflags = (unsigned short*)lib3ds_util_realloc_array( - mesh->vflags, - mesh->vflags? mesh->nvertices : 0, - use_flags? nvertices : 0, - 2 * sizeof(float) - ); - mesh->nvertices = (unsigned short)nvertices; -} - - -void -lib3ds_mesh_resize_faces(Lib3dsMesh *mesh, int nfaces) { - int i; - assert(mesh); - mesh->faces = (Lib3dsFace *)lib3ds_util_realloc_array(mesh->faces, mesh->nfaces, nfaces, sizeof(Lib3dsFace)); - for (i = mesh->nfaces; i < nfaces; ++i) { - mesh->faces[i].material = -1; - } - mesh->nfaces = (unsigned short)nfaces; -} - - -/*! - * Find the bounding box of a mesh object. - * - * \param mesh The mesh object - * \param bmin Returned bounding box - * \param bmax Returned bounding box - */ -void -lib3ds_mesh_bounding_box(Lib3dsMesh *mesh, float bmin[3], float bmax[3]) { - int i; - bmin[0] = bmin[1] = bmin[2] = FLT_MAX; - bmax[0] = bmax[1] = bmax[2] = -FLT_MAX; - - for (i = 0; i < mesh->nvertices; ++i) { - lib3ds_vector_min(bmin, mesh->vertices[i]); - lib3ds_vector_max(bmax, mesh->vertices[i]); - } -} - - -void -lib3ds_mesh_calculate_face_normals(Lib3dsMesh *mesh, float (*face_normals)[3]) { - int i; - - if (!mesh->nfaces) { - return; - } - for (i = 0; i < mesh->nfaces; ++i) { - lib3ds_vector_normal( - face_normals[i], - mesh->vertices[mesh->faces[i].index[0]], - mesh->vertices[mesh->faces[i].index[1]], - mesh->vertices[mesh->faces[i].index[2]] - ); - } -} - - -typedef struct Lib3dsFaces { - struct Lib3dsFaces *next; - int index; - float normal[3]; -} Lib3dsFaces; - - -/*! - * 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 normals A pointer to a buffer to store the calculated - * normals. The buffer must have the size: - * 3*3*sizeof(float)*mesh->nfaces. - * - * To allocate the normal buffer do for example the following: - * \code - * Lib3dsVector *normals = malloc(3*3*sizeof(float)*mesh->nfaces); - * \endcode - * - * To access the normal of the i-th vertex of the j-th face do the - * following: - * \code - * normals[3*j+i] - * \endcode - */ -void -lib3ds_mesh_calculate_vertex_normals(Lib3dsMesh *mesh, float (*normals)[3]) { - Lib3dsFaces **fl; - Lib3dsFaces *fa; - int i, j; - - if (!mesh->nfaces) { - return; - } - - fl = (Lib3dsFaces**)calloc(sizeof(Lib3dsFaces*), mesh->nvertices); - fa = (Lib3dsFaces*)malloc(sizeof(Lib3dsFaces) * 3 * mesh->nfaces); - - for (i = 0; i < mesh->nfaces; ++i) { - for (j = 0; j < 3; ++j) { - Lib3dsFaces* l = &fa[3*i+j]; - float p[3], q[3], n[3]; - float len, weight; - - l->index = i; - l->next = fl[mesh->faces[i].index[j]]; - fl[mesh->faces[i].index[j]] = l; - - lib3ds_vector_sub(p, mesh->vertices[mesh->faces[i].index[j<2? j + 1 : 0]], mesh->vertices[mesh->faces[i].index[j]]); - lib3ds_vector_sub(q, mesh->vertices[mesh->faces[i].index[j>0? j - 1 : 2]], mesh->vertices[mesh->faces[i].index[j]]); - lib3ds_vector_cross(n, p, q); - len = lib3ds_vector_length(n); - if (len > 0) { - weight = (float)atan2(len, lib3ds_vector_dot(p, q)); - lib3ds_vector_scalar_mul(l->normal, n, weight / len); - } else { - lib3ds_vector_zero(l->normal); - } - } - } - - for (i = 0; i < mesh->nfaces; ++i) { - Lib3dsFace *f = &mesh->faces[i]; - for (j = 0; j < 3; ++j) { - float n[3]; - Lib3dsFaces *p; - Lib3dsFace *pf; - - assert(mesh->faces[i].index[j] < mesh->nvertices); - - if (f->smoothing_group) { - unsigned smoothing_group = f->smoothing_group; - - lib3ds_vector_zero(n); - for (p = fl[mesh->faces[i].index[j]]; p; p = p->next) { - pf = &mesh->faces[p->index]; - if (pf->smoothing_group & f->smoothing_group) - smoothing_group |= pf->smoothing_group; - } - - for (p = fl[mesh->faces[i].index[j]]; p; p = p->next) { - pf = &mesh->faces[p->index]; - if (smoothing_group & pf->smoothing_group) { - lib3ds_vector_add(n, n, p->normal); - } - } - } else { - lib3ds_vector_copy(n, fa[3*i+j].normal); - } - - lib3ds_vector_normalize(n); - lib3ds_vector_copy(normals[3*i+j], n); - } - } - - free(fa); - free(fl); -} - - -static void -face_array_read(Lib3dsFile *file, Lib3dsMesh *mesh, Lib3dsIo *io) { - Lib3dsChunk c; - uint16_t chunk; - int i; - uint16_t nfaces; - - lib3ds_chunk_read_start(&c, CHK_FACE_ARRAY, io); - - lib3ds_mesh_resize_faces(mesh, 0); - nfaces = lib3ds_io_read_word(io); - if (nfaces) { - lib3ds_mesh_resize_faces(mesh, nfaces); - for (i = 0; i < nfaces; ++i) { - mesh->faces[i].index[0] = lib3ds_io_read_word(io); - mesh->faces[i].index[1] = lib3ds_io_read_word(io); - mesh->faces[i].index[2] = lib3ds_io_read_word(io); - mesh->faces[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 CHK_MSH_MAT_GROUP: { - char name[64]; - unsigned n; - unsigned i; - int index; - int material; - - lib3ds_io_read_string(io, name, 64); - material = lib3ds_file_material_by_name(file, name); - - n = lib3ds_io_read_word(io); - for (i = 0; i < n; ++i) { - index = lib3ds_io_read_word(io); - if (index < mesh->nfaces) { - mesh->faces[index].material = material; - } else { - // TODO warning - } - } - break; - } - - case CHK_SMOOTH_GROUP: { - int i; - for (i = 0; i < mesh->nfaces; ++i) { - mesh->faces[i].smoothing_group = lib3ds_io_read_dword(io); - } - break; - } - - case CHK_MSH_BOXMAP: { - lib3ds_io_read_string(io, mesh->box_front, 64); - lib3ds_io_read_string(io, mesh->box_back, 64); - lib3ds_io_read_string(io, mesh->box_left, 64); - lib3ds_io_read_string(io, mesh->box_right, 64); - lib3ds_io_read_string(io, mesh->box_top, 64); - lib3ds_io_read_string(io, mesh->box_bottom, 64); - break; - } - - default: - lib3ds_chunk_unknown(chunk,io); - } - } - - } - lib3ds_chunk_read_end(&c, io); -} - - -void -lib3ds_mesh_read(Lib3dsFile *file, Lib3dsMesh *mesh, Lib3dsIo *io) { - Lib3dsChunk c; - uint16_t chunk; - - lib3ds_chunk_read_start(&c, CHK_N_TRI_OBJECT, io); - - while ((chunk = lib3ds_chunk_read_next(&c, io)) != 0) { - switch (chunk) { - case CHK_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 CHK_MESH_COLOR: { - mesh->color = lib3ds_io_read_byte(io); - break; - } - - case CHK_POINT_ARRAY: { - int i; - uint16_t nvertices = lib3ds_io_read_word(io); - lib3ds_mesh_resize_vertices(mesh, nvertices, mesh->texcos != NULL, mesh->vflags != NULL); - for (i = 0; i < mesh->nvertices; ++i) { - lib3ds_io_read_vector(io, mesh->vertices[i]); - } - break; - } - - case CHK_POINT_FLAG_ARRAY: { - int i; - uint16_t nflags = lib3ds_io_read_word(io); - uint16_t nvertices = (mesh->nvertices >= nflags)? mesh->nvertices : nflags; - lib3ds_mesh_resize_vertices(mesh, nvertices, mesh->texcos != NULL, 1); - for (i = 0; i < nflags; ++i) { - mesh->vflags[i] = lib3ds_io_read_word(io); - } - break; - } - - case CHK_FACE_ARRAY: { - lib3ds_chunk_read_reset(&c, io); - face_array_read(file, mesh, io); - break; - } - - case CHK_MESH_TEXTURE_INFO: { - int i, j; - - //FIXME: mesh->map_type = lib3ds_io_read_word(io); - - for (i = 0; i < 2; ++i) { - mesh->map_tile[i] = lib3ds_io_read_float(io); - } - for (i = 0; i < 3; ++i) { - mesh->map_pos[i] = lib3ds_io_read_float(io); - } - mesh->map_scale = lib3ds_io_read_float(io); - - lib3ds_matrix_identity(mesh->map_matrix); - for (i = 0; i < 4; i++) { - for (j = 0; j < 3; j++) { - mesh->map_matrix[i][j] = lib3ds_io_read_float(io); - } - } - for (i = 0; i < 2; ++i) { - mesh->map_planar_size[i] = lib3ds_io_read_float(io); - } - mesh->map_cylinder_height = lib3ds_io_read_float(io); - break; - } - - case CHK_TEX_VERTS: { - int i; - uint16_t ntexcos = lib3ds_io_read_word(io); - uint16_t nvertices = (mesh->nvertices >= ntexcos)? mesh->nvertices : ntexcos;; - if (!mesh->texcos) { - lib3ds_mesh_resize_vertices(mesh, nvertices, 1, mesh->vflags != NULL); - } - for (i = 0; i < ntexcos; ++i) { - mesh->texcos[i][0] = lib3ds_io_read_float(io); - mesh->texcos[i][1] = lib3ds_io_read_float(io); - } - break; - } - - default: - lib3ds_chunk_unknown(chunk, io); - } - } - - if (lib3ds_matrix_det(mesh->matrix) < 0.0) { - /* Flip X coordinate of vertices if mesh matrix - has negative determinant */ - float inv_matrix[4][4], M[4][4]; - float tmp[3]; - int i; - - lib3ds_matrix_copy(inv_matrix, mesh->matrix); - lib3ds_matrix_inv(inv_matrix); - - lib3ds_matrix_copy(M, mesh->matrix); - lib3ds_matrix_scale(M, -1.0f, 1.0f, 1.0f); - lib3ds_matrix_mult(M, M, inv_matrix); - - for (i = 0; i < mesh->nvertices; ++i) { - lib3ds_vector_transform(tmp, M, mesh->vertices[i]); - lib3ds_vector_copy(mesh->vertices[i], tmp); - } - } - - lib3ds_chunk_read_end(&c, io); -} - - -static void -point_array_write(Lib3dsMesh *mesh, Lib3dsIo *io) { - Lib3dsChunk c; - int i; - - c.chunk = CHK_POINT_ARRAY; - c.size = 8 + 12 * mesh->nvertices; - lib3ds_chunk_write(&c, io); - - lib3ds_io_write_word(io, (uint16_t) mesh->nvertices); - - if (lib3ds_matrix_det(mesh->matrix) >= 0.0f) { - for (i = 0; i < mesh->nvertices; ++i) { - lib3ds_io_write_vector(io, mesh->vertices[i]); - } - } else { - /* Flip X coordinate of vertices if mesh matrix - has negative determinant */ - float inv_matrix[4][4], M[4][4]; - float tmp[3]; - - lib3ds_matrix_copy(inv_matrix, mesh->matrix); - lib3ds_matrix_inv(inv_matrix); - lib3ds_matrix_copy(M, mesh->matrix); - lib3ds_matrix_scale(M, -1.0f, 1.0f, 1.0f); - lib3ds_matrix_mult(M, M, inv_matrix); - - for (i = 0; i < mesh->nvertices; ++i) { - lib3ds_vector_transform(tmp, M, mesh->vertices[i]); - lib3ds_io_write_vector(io, tmp); - } - } -} - - -static void -flag_array_write(Lib3dsMesh *mesh, Lib3dsIo *io) { - Lib3dsChunk c; - int i; - - if (!mesh->vflags) { - return; - } - - c.chunk = CHK_POINT_FLAG_ARRAY; - c.size = 8 + 2 * mesh->nvertices; - lib3ds_chunk_write(&c, io); - - lib3ds_io_write_word(io, (uint16_t) mesh->nvertices); - for (i = 0; i < mesh->nvertices; ++i) { - lib3ds_io_write_word(io, mesh->vflags[i]); - } -} - - -static void -face_array_write(Lib3dsFile *file, Lib3dsMesh *mesh, Lib3dsIo *io) { - Lib3dsChunk c; - - if (mesh->nfaces == 0) { - return; - } - c.chunk = CHK_FACE_ARRAY; - lib3ds_chunk_write_start(&c, io); - - { - int i; - - lib3ds_io_write_word(io, (uint16_t) mesh->nfaces); - for (i = 0; i < mesh->nfaces; ++i) { - lib3ds_io_write_word(io, mesh->faces[i].index[0]); - lib3ds_io_write_word(io, mesh->faces[i].index[1]); - lib3ds_io_write_word(io, mesh->faces[i].index[2]); - lib3ds_io_write_word(io, mesh->faces[i].flags); - } - } - - { - /*---- MSH_CHK_MAT_GROUP ----*/ - Lib3dsChunk c; - int i, j; - uint16_t num; - char *matf = (char*)calloc(sizeof(char), mesh->nfaces); - ((Lib3dsIoImpl*)io->impl)->tmp_mem = matf; - assert(matf); - - for (i = 0; i < mesh->nfaces; ++i) { - if (!matf[i] && (mesh->faces[i].material >= 0) && (mesh->faces[i].material < file->nmaterials)) { - matf[i] = 1; - num = 1; - - for (j = i + 1; j < mesh->nfaces; ++j) { - if (mesh->faces[i].material == mesh->faces[j].material) ++num; - } - - c.chunk = CHK_MSH_MAT_GROUP; - c.size = 6 + (uint32_t)strlen(file->materials[mesh->faces[i].material]->name) + 1 + 2 + 2 * num; - lib3ds_chunk_write(&c, io); - lib3ds_io_write_string(io, file->materials[mesh->faces[i].material]->name); - lib3ds_io_write_word(io, num); - lib3ds_io_write_word(io, (uint16_t) i); - - for (j = i + 1; j < mesh->nfaces; ++j) { - if (mesh->faces[i].material == mesh->faces[j].material) { - lib3ds_io_write_word(io, (uint16_t) j); - matf[j] = 1; - } - } - } - } - ((Lib3dsIoImpl*)io->impl)->tmp_mem = NULL; - free(matf); - } - - { - /*---- SMOOTH_GROUP ----*/ - Lib3dsChunk c; - int i; - - c.chunk = CHK_SMOOTH_GROUP; - c.size = 6 + 4 * mesh->nfaces; - lib3ds_chunk_write(&c, io); - - for (i = 0; i < mesh->nfaces; ++i) { - lib3ds_io_write_dword(io, mesh->faces[i].smoothing_group); - } - } - - { - /*---- MSH_BOXMAP ----*/ - Lib3dsChunk c; - - if (strlen(mesh->box_front) || - strlen(mesh->box_back) || - strlen(mesh->box_left) || - strlen(mesh->box_right) || - strlen(mesh->box_top) || - strlen(mesh->box_bottom)) { - - c.chunk = CHK_MSH_BOXMAP; - lib3ds_chunk_write_start(&c, io); - - lib3ds_io_write_string(io, mesh->box_front); - lib3ds_io_write_string(io, mesh->box_back); - lib3ds_io_write_string(io, mesh->box_left); - lib3ds_io_write_string(io, mesh->box_right); - lib3ds_io_write_string(io, mesh->box_top); - lib3ds_io_write_string(io, mesh->box_bottom); - - lib3ds_chunk_write_end(&c, io); - } - } - - lib3ds_chunk_write_end(&c, io); -} - - -static void -texco_array_write(Lib3dsMesh *mesh, Lib3dsIo *io) { - Lib3dsChunk c; - int i; - - if (!mesh->texcos) { - return; - } - - c.chunk = CHK_TEX_VERTS; - c.size = 8 + 8 * mesh->nvertices; - lib3ds_chunk_write(&c, io); - - lib3ds_io_write_word(io, mesh->nvertices); - for (i = 0; i < mesh->nvertices; ++i) { - lib3ds_io_write_float(io, mesh->texcos[i][0]); - lib3ds_io_write_float(io, mesh->texcos[i][1]); - } -} - - -void -lib3ds_mesh_write(Lib3dsFile *file, Lib3dsMesh *mesh, Lib3dsIo *io) { - Lib3dsChunk c; - - c.chunk = CHK_N_TRI_OBJECT; - lib3ds_chunk_write_start(&c, io); - - point_array_write(mesh, io); - texco_array_write(mesh, io); - - if (mesh->map_type != LIB3DS_MAP_NONE) { /*---- LIB3DS_MESH_TEXTURE_INFO ----*/ - Lib3dsChunk c; - int i, j; - - c.chunk = CHK_MESH_TEXTURE_INFO; - c.size = 92; - lib3ds_chunk_write(&c, io); - - lib3ds_io_write_word(io, (uint16_t)mesh->map_type); - - for (i = 0; i < 2; ++i) { - lib3ds_io_write_float(io, mesh->map_tile[i]); - } - lib3ds_io_write_vector(io, mesh->map_pos); - lib3ds_io_write_float(io, mesh->map_scale); - - for (i = 0; i < 4; i++) { - for (j = 0; j < 3; j++) { - lib3ds_io_write_float(io, mesh->map_matrix[i][j]); - } - } - for (i = 0; i < 2; ++i) { - lib3ds_io_write_float(io, mesh->map_planar_size[i]); - } - lib3ds_io_write_float(io, mesh->map_cylinder_height); - } - - flag_array_write(mesh, io); - - { - /*---- LIB3DS_MESH_MATRIX ----*/ - Lib3dsChunk c; - int i, j; - - c.chunk = CHK_MESH_MATRIX; - c.size = 54; - lib3ds_chunk_write(&c, io); - 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 = CHK_MESH_COLOR; - c.size = 7; - lib3ds_chunk_write(&c, io); - lib3ds_io_write_byte(io, (uint8_t)mesh->color); - } - - face_array_write(file, mesh, io); - - lib3ds_chunk_write_end(&c, io); -} - +/* + Copyright (C) 1996-2008 by Jan Eric Kyprianidis + 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. + + Thisprogram 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, see . +*/ +#include "lib3ds_impl.h" + + +/*! + * 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. + */ +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_type = LIB3DS_MAP_NONE; + return (mesh); +} + + +/*! + * Free a mesh object and all of its resources. + * + * \param mesh Mesh object to be freed. + */ +void +lib3ds_mesh_free(Lib3dsMesh *mesh) { + lib3ds_mesh_resize_vertices(mesh, 0, 0, 0); + lib3ds_mesh_resize_faces(mesh, 0); + memset(mesh, 0, sizeof(Lib3dsMesh)); + free(mesh); +} + + +void +lib3ds_mesh_resize_vertices(Lib3dsMesh *mesh, int nvertices, int use_texcos, int use_flags) { + assert(mesh); + mesh->vertices = (float (*)[3])lib3ds_util_realloc_array(mesh->vertices, mesh->nvertices, nvertices, 3 * sizeof(float)); + mesh->texcos = (float (*)[2])lib3ds_util_realloc_array( + mesh->texcos, + mesh->texcos? mesh->nvertices : 0, + use_texcos? nvertices : 0, + 2 * sizeof(float) + ); + mesh->vflags = (unsigned short*)lib3ds_util_realloc_array( + mesh->vflags, + mesh->vflags? mesh->nvertices : 0, + use_flags? nvertices : 0, + 2 * sizeof(float) + ); + mesh->nvertices = (unsigned short)nvertices; +} + + +void +lib3ds_mesh_resize_faces(Lib3dsMesh *mesh, int nfaces) { + int i; + assert(mesh); + mesh->faces = (Lib3dsFace *)lib3ds_util_realloc_array(mesh->faces, mesh->nfaces, nfaces, sizeof(Lib3dsFace)); + for (i = mesh->nfaces; i < nfaces; ++i) { + mesh->faces[i].material = -1; + } + mesh->nfaces = (unsigned short)nfaces; +} + + +/*! + * Find the bounding box of a mesh object. + * + * \param mesh The mesh object + * \param bmin Returned bounding box + * \param bmax Returned bounding box + */ +void +lib3ds_mesh_bounding_box(Lib3dsMesh *mesh, float bmin[3], float bmax[3]) { + int i; + bmin[0] = bmin[1] = bmin[2] = FLT_MAX; + bmax[0] = bmax[1] = bmax[2] = -FLT_MAX; + + for (i = 0; i < mesh->nvertices; ++i) { + lib3ds_vector_min(bmin, mesh->vertices[i]); + lib3ds_vector_max(bmax, mesh->vertices[i]); + } +} + + +void +lib3ds_mesh_calculate_face_normals(Lib3dsMesh *mesh, float (*face_normals)[3]) { + int i; + + if (!mesh->nfaces) { + return; + } + for (i = 0; i < mesh->nfaces; ++i) { + lib3ds_vector_normal( + face_normals[i], + mesh->vertices[mesh->faces[i].index[0]], + mesh->vertices[mesh->faces[i].index[1]], + mesh->vertices[mesh->faces[i].index[2]] + ); + } +} + + +typedef struct Lib3dsFaces { + struct Lib3dsFaces *next; + int index; + float normal[3]; +} Lib3dsFaces; + + +/*! + * 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 normals A pointer to a buffer to store the calculated + * normals. The buffer must have the size: + * 3*3*sizeof(float)*mesh->nfaces. + * + * To allocate the normal buffer do for example the following: + * \code + * Lib3dsVector *normals = malloc(3*3*sizeof(float)*mesh->nfaces); + * \endcode + * + * To access the normal of the i-th vertex of the j-th face do the + * following: + * \code + * normals[3*j+i] + * \endcode + */ +void +lib3ds_mesh_calculate_vertex_normals(Lib3dsMesh *mesh, float (*normals)[3]) { + Lib3dsFaces **fl; + Lib3dsFaces *fa; + int i, j; + + if (!mesh->nfaces) { + return; + } + + fl = (Lib3dsFaces**)calloc(sizeof(Lib3dsFaces*), mesh->nvertices); + fa = (Lib3dsFaces*)malloc(sizeof(Lib3dsFaces) * 3 * mesh->nfaces); + + for (i = 0; i < mesh->nfaces; ++i) { + for (j = 0; j < 3; ++j) { + Lib3dsFaces* l = &fa[3*i+j]; + float p[3], q[3], n[3]; + float len, weight; + + l->index = i; + l->next = fl[mesh->faces[i].index[j]]; + fl[mesh->faces[i].index[j]] = l; + + lib3ds_vector_sub(p, mesh->vertices[mesh->faces[i].index[j<2? j + 1 : 0]], mesh->vertices[mesh->faces[i].index[j]]); + lib3ds_vector_sub(q, mesh->vertices[mesh->faces[i].index[j>0? j - 1 : 2]], mesh->vertices[mesh->faces[i].index[j]]); + lib3ds_vector_cross(n, p, q); + len = lib3ds_vector_length(n); + if (len > 0) { + weight = (float)atan2(len, lib3ds_vector_dot(p, q)); + lib3ds_vector_scalar_mul(l->normal, n, weight / len); + } else { + lib3ds_vector_zero(l->normal); + } + } + } + + for (i = 0; i < mesh->nfaces; ++i) { + Lib3dsFace *f = &mesh->faces[i]; + for (j = 0; j < 3; ++j) { + float n[3]; + Lib3dsFaces *p; + Lib3dsFace *pf; + + assert(mesh->faces[i].index[j] < mesh->nvertices); + + if (f->smoothing_group) { + unsigned smoothing_group = f->smoothing_group; + + lib3ds_vector_zero(n); + for (p = fl[mesh->faces[i].index[j]]; p; p = p->next) { + pf = &mesh->faces[p->index]; + if (pf->smoothing_group & f->smoothing_group) + smoothing_group |= pf->smoothing_group; + } + + for (p = fl[mesh->faces[i].index[j]]; p; p = p->next) { + pf = &mesh->faces[p->index]; + if (smoothing_group & pf->smoothing_group) { + lib3ds_vector_add(n, n, p->normal); + } + } + } else { + lib3ds_vector_copy(n, fa[3*i+j].normal); + } + + lib3ds_vector_normalize(n); + lib3ds_vector_copy(normals[3*i+j], n); + } + } + + free(fa); + free(fl); +} + + +static void +face_array_read(Lib3dsFile *file, Lib3dsMesh *mesh, Lib3dsIo *io) { + Lib3dsChunk c; + uint16_t chunk; + int i; + uint16_t nfaces; + + lib3ds_chunk_read_start(&c, CHK_FACE_ARRAY, io); + + lib3ds_mesh_resize_faces(mesh, 0); + nfaces = lib3ds_io_read_word(io); + if (nfaces) { + lib3ds_mesh_resize_faces(mesh, nfaces); + for (i = 0; i < nfaces; ++i) { + mesh->faces[i].index[0] = lib3ds_io_read_word(io); + mesh->faces[i].index[1] = lib3ds_io_read_word(io); + mesh->faces[i].index[2] = lib3ds_io_read_word(io); + mesh->faces[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 CHK_MSH_MAT_GROUP: { + char name[64]; + unsigned n; + unsigned i; + int index; + int material; + + lib3ds_io_read_string(io, name, 64); + material = lib3ds_file_material_by_name(file, name); + + n = lib3ds_io_read_word(io); + for (i = 0; i < n; ++i) { + index = lib3ds_io_read_word(io); + if (index < mesh->nfaces) { + mesh->faces[index].material = material; + } else { + // TODO warning + } + } + break; + } + + case CHK_SMOOTH_GROUP: { + int i; + for (i = 0; i < mesh->nfaces; ++i) { + mesh->faces[i].smoothing_group = lib3ds_io_read_dword(io); + } + break; + } + + case CHK_MSH_BOXMAP: { + lib3ds_io_read_string(io, mesh->box_front, 64); + lib3ds_io_read_string(io, mesh->box_back, 64); + lib3ds_io_read_string(io, mesh->box_left, 64); + lib3ds_io_read_string(io, mesh->box_right, 64); + lib3ds_io_read_string(io, mesh->box_top, 64); + lib3ds_io_read_string(io, mesh->box_bottom, 64); + break; + } + + default: + lib3ds_chunk_unknown(chunk,io); + } + } + + } + lib3ds_chunk_read_end(&c, io); +} + + +void +lib3ds_mesh_read(Lib3dsFile *file, Lib3dsMesh *mesh, Lib3dsIo *io) { + Lib3dsChunk c; + uint16_t chunk; + + lib3ds_chunk_read_start(&c, CHK_N_TRI_OBJECT, io); + + while ((chunk = lib3ds_chunk_read_next(&c, io)) != 0) { + switch (chunk) { + case CHK_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 CHK_MESH_COLOR: { + mesh->color = lib3ds_io_read_byte(io); + break; + } + + case CHK_POINT_ARRAY: { + int i; + uint16_t nvertices = lib3ds_io_read_word(io); + lib3ds_mesh_resize_vertices(mesh, nvertices, mesh->texcos != NULL, mesh->vflags != NULL); + for (i = 0; i < mesh->nvertices; ++i) { + lib3ds_io_read_vector(io, mesh->vertices[i]); + } + break; + } + + case CHK_POINT_FLAG_ARRAY: { + int i; + uint16_t nflags = lib3ds_io_read_word(io); + uint16_t nvertices = (mesh->nvertices >= nflags)? mesh->nvertices : nflags; + lib3ds_mesh_resize_vertices(mesh, nvertices, mesh->texcos != NULL, 1); + for (i = 0; i < nflags; ++i) { + mesh->vflags[i] = lib3ds_io_read_word(io); + } + break; + } + + case CHK_FACE_ARRAY: { + lib3ds_chunk_read_reset(&c, io); + face_array_read(file, mesh, io); + break; + } + + case CHK_MESH_TEXTURE_INFO: { + int i, j; + + //FIXME: mesh->map_type = lib3ds_io_read_word(io); + + for (i = 0; i < 2; ++i) { + mesh->map_tile[i] = lib3ds_io_read_float(io); + } + for (i = 0; i < 3; ++i) { + mesh->map_pos[i] = lib3ds_io_read_float(io); + } + mesh->map_scale = lib3ds_io_read_float(io); + + lib3ds_matrix_identity(mesh->map_matrix); + for (i = 0; i < 4; i++) { + for (j = 0; j < 3; j++) { + mesh->map_matrix[i][j] = lib3ds_io_read_float(io); + } + } + for (i = 0; i < 2; ++i) { + mesh->map_planar_size[i] = lib3ds_io_read_float(io); + } + mesh->map_cylinder_height = lib3ds_io_read_float(io); + break; + } + + case CHK_TEX_VERTS: { + int i; + uint16_t ntexcos = lib3ds_io_read_word(io); + uint16_t nvertices = (mesh->nvertices >= ntexcos)? mesh->nvertices : ntexcos;; + if (!mesh->texcos) { + lib3ds_mesh_resize_vertices(mesh, nvertices, 1, mesh->vflags != NULL); + } + for (i = 0; i < ntexcos; ++i) { + mesh->texcos[i][0] = lib3ds_io_read_float(io); + mesh->texcos[i][1] = lib3ds_io_read_float(io); + } + break; + } + + default: + lib3ds_chunk_unknown(chunk, io); + } + } + + if (lib3ds_matrix_det(mesh->matrix) < 0.0) { + /* Flip X coordinate of vertices if mesh matrix + has negative determinant */ + float inv_matrix[4][4], M[4][4]; + float tmp[3]; + int i; + + lib3ds_matrix_copy(inv_matrix, mesh->matrix); + lib3ds_matrix_inv(inv_matrix); + + lib3ds_matrix_copy(M, mesh->matrix); + lib3ds_matrix_scale(M, -1.0f, 1.0f, 1.0f); + lib3ds_matrix_mult(M, M, inv_matrix); + + for (i = 0; i < mesh->nvertices; ++i) { + lib3ds_vector_transform(tmp, M, mesh->vertices[i]); + lib3ds_vector_copy(mesh->vertices[i], tmp); + } + } + + lib3ds_chunk_read_end(&c, io); +} + + +static void +point_array_write(Lib3dsMesh *mesh, Lib3dsIo *io) { + Lib3dsChunk c; + int i; + + c.chunk = CHK_POINT_ARRAY; + c.size = 8 + 12 * mesh->nvertices; + lib3ds_chunk_write(&c, io); + + lib3ds_io_write_word(io, (uint16_t) mesh->nvertices); + + if (lib3ds_matrix_det(mesh->matrix) >= 0.0f) { + for (i = 0; i < mesh->nvertices; ++i) { + lib3ds_io_write_vector(io, mesh->vertices[i]); + } + } else { + /* Flip X coordinate of vertices if mesh matrix + has negative determinant */ + float inv_matrix[4][4], M[4][4]; + float tmp[3]; + + lib3ds_matrix_copy(inv_matrix, mesh->matrix); + lib3ds_matrix_inv(inv_matrix); + lib3ds_matrix_copy(M, mesh->matrix); + lib3ds_matrix_scale(M, -1.0f, 1.0f, 1.0f); + lib3ds_matrix_mult(M, M, inv_matrix); + + for (i = 0; i < mesh->nvertices; ++i) { + lib3ds_vector_transform(tmp, M, mesh->vertices[i]); + lib3ds_io_write_vector(io, tmp); + } + } +} + + +static void +flag_array_write(Lib3dsMesh *mesh, Lib3dsIo *io) { + Lib3dsChunk c; + int i; + + if (!mesh->vflags) { + return; + } + + c.chunk = CHK_POINT_FLAG_ARRAY; + c.size = 8 + 2 * mesh->nvertices; + lib3ds_chunk_write(&c, io); + + lib3ds_io_write_word(io, (uint16_t) mesh->nvertices); + for (i = 0; i < mesh->nvertices; ++i) { + lib3ds_io_write_word(io, mesh->vflags[i]); + } +} + + +static void +face_array_write(Lib3dsFile *file, Lib3dsMesh *mesh, Lib3dsIo *io) { + Lib3dsChunk c; + + if (mesh->nfaces == 0) { + return; + } + c.chunk = CHK_FACE_ARRAY; + lib3ds_chunk_write_start(&c, io); + + { + int i; + + lib3ds_io_write_word(io, (uint16_t) mesh->nfaces); + for (i = 0; i < mesh->nfaces; ++i) { + lib3ds_io_write_word(io, mesh->faces[i].index[0]); + lib3ds_io_write_word(io, mesh->faces[i].index[1]); + lib3ds_io_write_word(io, mesh->faces[i].index[2]); + lib3ds_io_write_word(io, mesh->faces[i].flags); + } + } + + { + /*---- MSH_CHK_MAT_GROUP ----*/ + Lib3dsChunk c; + int i, j; + uint16_t num; + char *matf = (char*)calloc(sizeof(char), mesh->nfaces); + ((Lib3dsIoImpl*)io->impl)->tmp_mem = matf; + assert(matf); + + for (i = 0; i < mesh->nfaces; ++i) { + if (!matf[i] && (mesh->faces[i].material >= 0) && (mesh->faces[i].material < file->nmaterials)) { + matf[i] = 1; + num = 1; + + for (j = i + 1; j < mesh->nfaces; ++j) { + if (mesh->faces[i].material == mesh->faces[j].material) ++num; + } + + c.chunk = CHK_MSH_MAT_GROUP; + c.size = 6 + (uint32_t)strlen(file->materials[mesh->faces[i].material]->name) + 1 + 2 + 2 * num; + lib3ds_chunk_write(&c, io); + lib3ds_io_write_string(io, file->materials[mesh->faces[i].material]->name); + lib3ds_io_write_word(io, num); + lib3ds_io_write_word(io, (uint16_t) i); + + for (j = i + 1; j < mesh->nfaces; ++j) { + if (mesh->faces[i].material == mesh->faces[j].material) { + lib3ds_io_write_word(io, (uint16_t) j); + matf[j] = 1; + } + } + } + } + ((Lib3dsIoImpl*)io->impl)->tmp_mem = NULL; + free(matf); + } + + { + /*---- SMOOTH_GROUP ----*/ + Lib3dsChunk c; + int i; + + c.chunk = CHK_SMOOTH_GROUP; + c.size = 6 + 4 * mesh->nfaces; + lib3ds_chunk_write(&c, io); + + for (i = 0; i < mesh->nfaces; ++i) { + lib3ds_io_write_dword(io, mesh->faces[i].smoothing_group); + } + } + + { + /*---- MSH_BOXMAP ----*/ + Lib3dsChunk c; + + if (strlen(mesh->box_front) || + strlen(mesh->box_back) || + strlen(mesh->box_left) || + strlen(mesh->box_right) || + strlen(mesh->box_top) || + strlen(mesh->box_bottom)) { + + c.chunk = CHK_MSH_BOXMAP; + lib3ds_chunk_write_start(&c, io); + + lib3ds_io_write_string(io, mesh->box_front); + lib3ds_io_write_string(io, mesh->box_back); + lib3ds_io_write_string(io, mesh->box_left); + lib3ds_io_write_string(io, mesh->box_right); + lib3ds_io_write_string(io, mesh->box_top); + lib3ds_io_write_string(io, mesh->box_bottom); + + lib3ds_chunk_write_end(&c, io); + } + } + + lib3ds_chunk_write_end(&c, io); +} + + +static void +texco_array_write(Lib3dsMesh *mesh, Lib3dsIo *io) { + Lib3dsChunk c; + int i; + + if (!mesh->texcos) { + return; + } + + c.chunk = CHK_TEX_VERTS; + c.size = 8 + 8 * mesh->nvertices; + lib3ds_chunk_write(&c, io); + + lib3ds_io_write_word(io, mesh->nvertices); + for (i = 0; i < mesh->nvertices; ++i) { + lib3ds_io_write_float(io, mesh->texcos[i][0]); + lib3ds_io_write_float(io, mesh->texcos[i][1]); + } +} + + +void +lib3ds_mesh_write(Lib3dsFile *file, Lib3dsMesh *mesh, Lib3dsIo *io) { + Lib3dsChunk c; + + c.chunk = CHK_N_TRI_OBJECT; + lib3ds_chunk_write_start(&c, io); + + point_array_write(mesh, io); + texco_array_write(mesh, io); + + if (mesh->map_type != LIB3DS_MAP_NONE) { /*---- LIB3DS_MESH_TEXTURE_INFO ----*/ + Lib3dsChunk c; + int i, j; + + c.chunk = CHK_MESH_TEXTURE_INFO; + c.size = 92; + lib3ds_chunk_write(&c, io); + + lib3ds_io_write_word(io, (uint16_t)mesh->map_type); + + for (i = 0; i < 2; ++i) { + lib3ds_io_write_float(io, mesh->map_tile[i]); + } + lib3ds_io_write_vector(io, mesh->map_pos); + lib3ds_io_write_float(io, mesh->map_scale); + + for (i = 0; i < 4; i++) { + for (j = 0; j < 3; j++) { + lib3ds_io_write_float(io, mesh->map_matrix[i][j]); + } + } + for (i = 0; i < 2; ++i) { + lib3ds_io_write_float(io, mesh->map_planar_size[i]); + } + lib3ds_io_write_float(io, mesh->map_cylinder_height); + } + + flag_array_write(mesh, io); + + { + /*---- LIB3DS_MESH_MATRIX ----*/ + Lib3dsChunk c; + int i, j; + + c.chunk = CHK_MESH_MATRIX; + c.size = 54; + lib3ds_chunk_write(&c, io); + 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 = CHK_MESH_COLOR; + c.size = 7; + lib3ds_chunk_write(&c, io); + lib3ds_io_write_byte(io, (uint8_t)mesh->color); + } + + face_array_write(file, mesh, io); + + lib3ds_chunk_write_end(&c, io); +} + diff --git a/src/osgPlugins/3ds/lib3ds/lib3ds_node.c b/src/osgPlugins/3ds/lib3ds/lib3ds_node.c index 9db3c7487..1b1fdac6f 100644 --- a/src/osgPlugins/3ds/lib3ds/lib3ds_node.c +++ b/src/osgPlugins/3ds/lib3ds/lib3ds_node.c @@ -1,1062 +1,1062 @@ -/* - Copyright (C) 1996-2008 by Jan Eric Kyprianidis - 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. - - Thisprogram 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, see . -*/ -#include "lib3ds_impl.h" - - -/*! - * Create and return a new node object. - * - * The node is returned with an identity matrix. All other fields - * are zero. - * - * \return Lib3dsNode - */ -Lib3dsNode* -lib3ds_node_new(Lib3dsNodeType type) { - Lib3dsNode *node; - switch (type) { - case LIB3DS_NODE_AMBIENT_COLOR: { - Lib3dsAmbientColorNode *n = (Lib3dsAmbientColorNode*)calloc(sizeof(Lib3dsAmbientColorNode), 1); - node = (Lib3dsNode*)n; - strcpy(node->name, "$AMBIENT$"); - n->color_track.type = LIB3DS_TRACK_VECTOR; - break; - } - - case LIB3DS_NODE_MESH_INSTANCE: { - Lib3dsMeshInstanceNode *n = (Lib3dsMeshInstanceNode*)calloc(sizeof(Lib3dsMeshInstanceNode), 1); - node = (Lib3dsNode*)n; - strcpy(node->name, "$$$DUMMY"); - n->pos_track.type = LIB3DS_TRACK_VECTOR; - n->scl_track.type = LIB3DS_TRACK_VECTOR; - n->rot_track.type = LIB3DS_TRACK_QUAT; - n->hide_track.type = LIB3DS_TRACK_BOOL; - break; - } - - case LIB3DS_NODE_CAMERA: { - Lib3dsCameraNode *n = (Lib3dsCameraNode*)calloc(sizeof(Lib3dsCameraNode), 1); - node = (Lib3dsNode*)n; - n->pos_track.type = LIB3DS_TRACK_VECTOR; - n->fov_track.type = LIB3DS_TRACK_FLOAT; - n->roll_track.type = LIB3DS_TRACK_FLOAT; - break; - } - - case LIB3DS_NODE_CAMERA_TARGET: { - Lib3dsTargetNode *n = (Lib3dsTargetNode*)calloc(sizeof(Lib3dsTargetNode), 1); - node = (Lib3dsNode*)n; - n->pos_track.type = LIB3DS_TRACK_VECTOR; - break; - } - - case LIB3DS_NODE_OMNILIGHT: { - Lib3dsOmnilightNode *n = (Lib3dsOmnilightNode*)calloc(sizeof(Lib3dsOmnilightNode), 1); - node = (Lib3dsNode*)n; - n->pos_track.type = LIB3DS_TRACK_VECTOR; - n->color_track.type = LIB3DS_TRACK_VECTOR; - break; - } - - case LIB3DS_NODE_SPOTLIGHT: { - Lib3dsSpotlightNode *n = (Lib3dsSpotlightNode*)calloc(sizeof(Lib3dsSpotlightNode), 1); - node = (Lib3dsNode*)n; - n->pos_track.type = LIB3DS_TRACK_VECTOR; - n->color_track.type = LIB3DS_TRACK_VECTOR; - n->hotspot_track.type = LIB3DS_TRACK_FLOAT; - n->falloff_track.type = LIB3DS_TRACK_FLOAT; - n->roll_track.type = LIB3DS_TRACK_FLOAT; - break; - } - - case LIB3DS_NODE_SPOTLIGHT_TARGET: { - Lib3dsTargetNode *n = (Lib3dsTargetNode*)calloc(sizeof(Lib3dsTargetNode), 1); - node = (Lib3dsNode*)n; - n->pos_track.type = LIB3DS_TRACK_VECTOR; - break; - } - - default: - assert(0); - return NULL; - } - - node->type = type; - node->node_id = 65535; - node->user_id = 65535; - lib3ds_matrix_identity(node->matrix); - return node; -} - - -Lib3dsAmbientColorNode* -lib3ds_node_new_ambient_color(float color0[3]) { - Lib3dsNode *node; - Lib3dsAmbientColorNode *n; - - node = lib3ds_node_new(LIB3DS_NODE_AMBIENT_COLOR); - - n = (Lib3dsAmbientColorNode*)node; - lib3ds_track_resize(&n->color_track, 1); - if (color0) { - lib3ds_vector_copy(n->color_track.keys[0].value, color0); - } else { - lib3ds_vector_zero(n->color_track.keys[0].value); - } - - return n; -} - - -Lib3dsMeshInstanceNode* -lib3ds_node_new_mesh_instance(Lib3dsMesh *mesh, const char *instance_name, float pos0[3], float scl0[3], float rot0[4]) { - Lib3dsNode *node; - Lib3dsMeshInstanceNode *n; - int i; - - node = lib3ds_node_new(LIB3DS_NODE_MESH_INSTANCE); - if (mesh) { - strcpy(node->name, mesh->name); - } else { - strcpy(node->name, "$$$DUMMY"); - } - - n = (Lib3dsMeshInstanceNode*)node; - if (instance_name) { - strcpy(n->instance_name, instance_name); - } - - lib3ds_track_resize(&n->pos_track, 1); - if (pos0) { - lib3ds_vector_copy(n->pos_track.keys[0].value, pos0); - } - - lib3ds_track_resize(&n->scl_track, 1); - if (scl0) { - lib3ds_vector_copy(n->scl_track.keys[0].value, scl0); - } else { - lib3ds_vector_make(n->scl_track.keys[0].value, 1, 1, 1); - } - - lib3ds_track_resize(&n->rot_track, 1); - if (rot0) { - for (i = 0; i < 4; ++i) n->rot_track.keys[0].value[i] = rot0[i]; - } else { - for (i = 0; i < 4; ++i) n->rot_track.keys[0].value[i] = 0; - } - - return n; -} - - -Lib3dsCameraNode* -lib3ds_node_new_camera(Lib3dsCamera *camera) { - Lib3dsNode *node = lib3ds_node_new(LIB3DS_NODE_CAMERA); - Lib3dsCameraNode *n; - - assert(camera); - node = lib3ds_node_new(LIB3DS_NODE_CAMERA); - strcpy(node->name, camera->name); - - n = (Lib3dsCameraNode*)node; - lib3ds_track_resize(&n->pos_track, 1); - lib3ds_vector_copy(n->pos_track.keys[0].value, camera->position); - - lib3ds_track_resize(&n->fov_track, 1); - n->fov_track.keys[0].value[0] = camera->fov; - - lib3ds_track_resize(&n->roll_track, 1); - n->roll_track.keys[0].value[0] = camera->roll; - - return n; -} - - -Lib3dsTargetNode* -lib3ds_node_new_camera_target(Lib3dsCamera *camera) { - Lib3dsNode *node; - Lib3dsTargetNode *n; - - assert(camera); - node = lib3ds_node_new(LIB3DS_NODE_CAMERA_TARGET); - strcpy(node->name, camera->name); - - n = (Lib3dsTargetNode*)node; - lib3ds_track_resize(&n->pos_track, 1); - lib3ds_vector_copy(n->pos_track.keys[0].value, camera->target); - - return n; -} - - -Lib3dsOmnilightNode* -lib3ds_node_new_omnilight(Lib3dsLight *light) { - Lib3dsNode *node; - Lib3dsOmnilightNode *n; - - assert(light); - node = lib3ds_node_new(LIB3DS_NODE_OMNILIGHT); - strcpy(node->name, light->name); - - n = (Lib3dsOmnilightNode*)node; - lib3ds_track_resize(&n->pos_track, 1); - lib3ds_vector_copy(n->pos_track.keys[0].value, light->position); - - lib3ds_track_resize(&n->color_track, 1); - lib3ds_vector_copy(n->color_track.keys[0].value, light->color); - - return n; -} - - -Lib3dsSpotlightNode* -lib3ds_node_new_spotlight(Lib3dsLight *light) { - Lib3dsNode *node; - Lib3dsSpotlightNode *n; - - assert(light); - node = lib3ds_node_new(LIB3DS_NODE_SPOTLIGHT); - strcpy(node->name, light->name); - - n = (Lib3dsSpotlightNode*)node; - lib3ds_track_resize(&n->pos_track, 1); - lib3ds_vector_copy(n->pos_track.keys[0].value, light->position); - - lib3ds_track_resize(&n->color_track, 1); - lib3ds_vector_copy(n->color_track.keys[0].value, light->color); - - lib3ds_track_resize(&n->hotspot_track, 1); - n->hotspot_track.keys[0].value[0] = light->hotspot; - - lib3ds_track_resize(&n->falloff_track, 1); - n->falloff_track.keys[0].value[0] = light->falloff; - - lib3ds_track_resize(&n->roll_track, 1); - n->roll_track.keys[0].value[0] = light->roll; - - return n; -} - - -Lib3dsTargetNode* -lib3ds_node_new_spotligf_target(Lib3dsLight *light) { - Lib3dsNode *node; - Lib3dsTargetNode *n; - - assert(light); - node = lib3ds_node_new(LIB3DS_NODE_SPOTLIGHT_TARGET); - strcpy(node->name, light->name); - - n = (Lib3dsTargetNode*)node; - lib3ds_track_resize(&n->pos_track, 1); - lib3ds_vector_copy(n->pos_track.keys[0].value, light->target); - - return n; -} - - -static void -free_node_and_childs(Lib3dsNode *node) { - assert(node); - switch (node->type) { - case LIB3DS_NODE_AMBIENT_COLOR: { - Lib3dsAmbientColorNode *n = (Lib3dsAmbientColorNode*)node; - lib3ds_track_resize(&n->color_track, 0); - break; - } - - case LIB3DS_NODE_MESH_INSTANCE: { - Lib3dsMeshInstanceNode *n = (Lib3dsMeshInstanceNode*)node; - lib3ds_track_resize(&n->pos_track, 0); - lib3ds_track_resize(&n->rot_track, 0); - lib3ds_track_resize(&n->scl_track, 0); - lib3ds_track_resize(&n->hide_track, 0); - break; - } - - case LIB3DS_NODE_CAMERA: { - Lib3dsCameraNode *n = (Lib3dsCameraNode*)node; - lib3ds_track_resize(&n->pos_track, 0); - lib3ds_track_resize(&n->fov_track, 0); - lib3ds_track_resize(&n->roll_track, 0); - break; - } - - case LIB3DS_NODE_CAMERA_TARGET: { - Lib3dsTargetNode *n = (Lib3dsTargetNode*)node; - lib3ds_track_resize(&n->pos_track, 0); - break; - } - - case LIB3DS_NODE_OMNILIGHT: { - Lib3dsOmnilightNode *n = (Lib3dsOmnilightNode*)node; - lib3ds_track_resize(&n->pos_track, 0); - lib3ds_track_resize(&n->color_track, 0); - break; - } - - case LIB3DS_NODE_SPOTLIGHT: { - Lib3dsSpotlightNode *n = (Lib3dsSpotlightNode*)node; - lib3ds_track_resize(&n->pos_track, 0); - lib3ds_track_resize(&n->color_track, 0); - lib3ds_track_resize(&n->hotspot_track, 0); - lib3ds_track_resize(&n->falloff_track, 0); - lib3ds_track_resize(&n->roll_track, 0); - break; - } - - case LIB3DS_NODE_SPOTLIGHT_TARGET: { - Lib3dsTargetNode *n = (Lib3dsTargetNode*)node; - lib3ds_track_resize(&n->pos_track, 0); - break; - } - } - { - Lib3dsNode *p, *q; - for (p = node->childs; p; p = q) { - q = p->next; - free_node_and_childs(p); - } - } - free(node); -} - - -/*! - * Free a node and all of its resources. - * - * \param node Lib3dsNode object to be freed. - */ -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 - */ -void -lib3ds_node_eval(Lib3dsNode *node, float t) { - assert(node); - switch (node->type) { - case LIB3DS_NODE_AMBIENT_COLOR: { - Lib3dsAmbientColorNode *n = (Lib3dsAmbientColorNode*)node; - if (node->parent) { - lib3ds_matrix_copy(node->matrix, node->parent->matrix); - } else { - lib3ds_matrix_identity(node->matrix); - } - lib3ds_track_eval_vector(&n->color_track, n->color, t); - break; - } - - case LIB3DS_NODE_MESH_INSTANCE: { - float M[4][4]; - Lib3dsMeshInstanceNode *n = (Lib3dsMeshInstanceNode*)node; - - lib3ds_track_eval_vector(&n->pos_track, n->pos, t); - lib3ds_track_eval_quat(&n->rot_track, n->rot, t); - if (n->scl_track.nkeys) { - lib3ds_track_eval_vector(&n->scl_track, n->scl, t); - } else { - n->scl[0] = n->scl[1] = n->scl[2] = 1.0f; - } - lib3ds_track_eval_bool(&n->hide_track, &n->hide, t); - - lib3ds_matrix_identity(M); - lib3ds_matrix_translate(M, n->pos[0], n->pos[1], n->pos[2]); - lib3ds_matrix_rotate_quat(M, n->rot); - lib3ds_matrix_scale(M, n->scl[0], n->scl[1], n->scl[2]); - - if (node->parent) { - lib3ds_matrix_mult(node->matrix, node->parent->matrix, M); - } else { - lib3ds_matrix_copy(node->matrix, M); - } - break; - } - - case LIB3DS_NODE_CAMERA: { - Lib3dsCameraNode *n = (Lib3dsCameraNode*)node; - lib3ds_track_eval_vector(&n->pos_track, n->pos, t); - lib3ds_track_eval_float(&n->fov_track, &n->fov, t); - lib3ds_track_eval_float(&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[0], n->pos[1], n->pos[2]); - break; - } - - case LIB3DS_NODE_CAMERA_TARGET: { - Lib3dsTargetNode *n = (Lib3dsTargetNode*)node; - lib3ds_track_eval_vector(&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[0], n->pos[1], n->pos[2]); - break; - } - - case LIB3DS_NODE_OMNILIGHT: { - Lib3dsOmnilightNode *n = (Lib3dsOmnilightNode*)node; - lib3ds_track_eval_vector(&n->pos_track, n->pos, t); - lib3ds_track_eval_vector(&n->color_track, n->color, 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[0], n->pos[1], n->pos[2]); - break; - } - - case LIB3DS_NODE_SPOTLIGHT: { - Lib3dsSpotlightNode *n = (Lib3dsSpotlightNode*)node; - lib3ds_track_eval_vector(&n->pos_track, n->pos, t); - lib3ds_track_eval_vector(&n->color_track, n->color, t); - lib3ds_track_eval_float(&n->hotspot_track, &n->hotspot, t); - lib3ds_track_eval_float(&n->falloff_track, &n->falloff, t); - lib3ds_track_eval_float(&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[0], n->pos[1], n->pos[2]); - break; - } - - case LIB3DS_NODE_SPOTLIGHT_TARGET: { - Lib3dsTargetNode *n = (Lib3dsTargetNode*)node; - lib3ds_track_eval_vector(&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[0], n->pos[1], n->pos[2]); - 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. - */ -Lib3dsNode* -lib3ds_node_by_name(Lib3dsNode *node, const char* name, Lib3dsNodeType 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. - */ -Lib3dsNode* -lib3ds_node_by_id(Lib3dsNode *node, uint16_t 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); -} - - -void -lib3ds_node_read(Lib3dsNode *node, Lib3dsIo *io) { - Lib3dsChunk c; - uint16_t chunk; - - assert(node); - lib3ds_chunk_read_start(&c, 0, io); - - switch (c.chunk) { - case CHK_AMBIENT_NODE_TAG: - case CHK_OBJECT_NODE_TAG: - case CHK_CAMERA_NODE_TAG: - case CHK_TARGET_NODE_TAG: - case CHK_LIGHT_NODE_TAG: - case CHK_SPOTLIGHT_NODE_TAG: - case CHK_L_TARGET_NODE_TAG: - break; - default: - return; - } - - while ((chunk = lib3ds_chunk_read_next(&c, io)) != 0) { - switch (chunk) { - case CHK_NODE_ID: { - node->node_id = lib3ds_io_read_word(io); - lib3ds_io_log_indent(io, 1); - lib3ds_io_log(io, LIB3DS_LOG_INFO, "ID=%d", (short)node->node_id); - lib3ds_io_log_indent(io, -1); - break; - } - - case CHK_NODE_HDR: { - lib3ds_io_read_string(io, node->name, 64); - node->flags = lib3ds_io_read_word(io); - node->flags |= ((uint32_t)lib3ds_io_read_word(io)) << 16; - node->user_id = lib3ds_io_read_word(io); - - lib3ds_io_log_indent(io, 1); - lib3ds_io_log(io, LIB3DS_LOG_INFO, "NAME=%s", node->name); - lib3ds_io_log(io, LIB3DS_LOG_INFO, "PARENT=%d", (short)node->user_id); - lib3ds_io_log_indent(io, -1); - break; - } - - case CHK_PIVOT: { - if (node->type == LIB3DS_NODE_MESH_INSTANCE) { - Lib3dsMeshInstanceNode *n = (Lib3dsMeshInstanceNode*)node; - lib3ds_io_read_vector(io, n->pivot); - } else { - lib3ds_chunk_unknown(chunk, io); - } - break; - } - - case CHK_INSTANCE_NAME: { - if (node->type == LIB3DS_NODE_MESH_INSTANCE) { - Lib3dsMeshInstanceNode *n = (Lib3dsMeshInstanceNode*)node; - lib3ds_io_read_string(io, n->instance_name, 64); - } else { - lib3ds_chunk_unknown(chunk, io); - } - break; - } - - case CHK_BOUNDBOX: { - if (node->type == LIB3DS_NODE_MESH_INSTANCE) { - Lib3dsMeshInstanceNode *n = (Lib3dsMeshInstanceNode*)node; - lib3ds_io_read_vector(io, n->bbox_min); - lib3ds_io_read_vector(io, n->bbox_max); - } else { - lib3ds_chunk_unknown(chunk, io); - } - break; - } - - case CHK_COL_TRACK_TAG: { - Lib3dsTrack *track = 0; - switch (node->type) { - case LIB3DS_NODE_AMBIENT_COLOR: { - Lib3dsAmbientColorNode *n = (Lib3dsAmbientColorNode*)node; - track = &n->color_track; - break; - } - case LIB3DS_NODE_OMNILIGHT: { - Lib3dsOmnilightNode *n = (Lib3dsOmnilightNode*)node; - track = &n->color_track; - break; - } - case LIB3DS_NODE_SPOTLIGHT: { - Lib3dsSpotlightNode *n = (Lib3dsSpotlightNode*)node; - track = &n->color_track; - break; - } - default: - lib3ds_chunk_unknown(chunk, io); - } - if (track) { - lib3ds_track_read(track, io); - } - break; - } - - case CHK_POS_TRACK_TAG: { - Lib3dsTrack *track = 0; - switch (node->type) { - case LIB3DS_NODE_MESH_INSTANCE: { - Lib3dsMeshInstanceNode *n = (Lib3dsMeshInstanceNode*)node; - track = &n->pos_track; - break; - } - case LIB3DS_NODE_CAMERA: { - Lib3dsCameraNode *n = (Lib3dsCameraNode*)node; - track = &n->pos_track; - break; - } - case LIB3DS_NODE_CAMERA_TARGET: { - Lib3dsTargetNode *n = (Lib3dsTargetNode*)node; - track = &n->pos_track; - break; - } - case LIB3DS_NODE_OMNILIGHT: { - Lib3dsOmnilightNode *n = (Lib3dsOmnilightNode*)node; - track = &n->pos_track; - break; - } - case LIB3DS_NODE_SPOTLIGHT: { - Lib3dsSpotlightNode *n = (Lib3dsSpotlightNode*)node; - track = &n->pos_track; - break; - } - case LIB3DS_NODE_SPOTLIGHT_TARGET: { - Lib3dsTargetNode *n = (Lib3dsTargetNode*)node; - track = &n->pos_track; - break; - } - default: - lib3ds_chunk_unknown(chunk, io); - } - if (track) { - lib3ds_track_read(track, io); - } - break; - } - - case CHK_ROT_TRACK_TAG: { - if (node->type == LIB3DS_NODE_MESH_INSTANCE) { - Lib3dsMeshInstanceNode *n = (Lib3dsMeshInstanceNode*)node; - n->rot_track.type = LIB3DS_TRACK_QUAT; - lib3ds_track_read(&n->rot_track, io); - } else { - lib3ds_chunk_unknown(chunk, io); - } - break; - } - - case CHK_SCL_TRACK_TAG: { - if (node->type == LIB3DS_NODE_MESH_INSTANCE) { - Lib3dsMeshInstanceNode *n = (Lib3dsMeshInstanceNode*)node; - n->scl_track.type = LIB3DS_TRACK_VECTOR; - lib3ds_track_read(&n->scl_track, io); - } else { - lib3ds_chunk_unknown(chunk, io); - } - break; - } - - case CHK_FOV_TRACK_TAG: { - if (node->type == LIB3DS_NODE_CAMERA) { - Lib3dsCameraNode *n = (Lib3dsCameraNode*)node; - n->fov_track.type = LIB3DS_TRACK_FLOAT; - lib3ds_track_read(&n->fov_track, io); - } else { - lib3ds_chunk_unknown(chunk, io); - } - break; - } - - case CHK_HOT_TRACK_TAG: { - if (node->type == LIB3DS_NODE_SPOTLIGHT) { - Lib3dsSpotlightNode *n = (Lib3dsSpotlightNode*)node; - n->hotspot_track.type = LIB3DS_TRACK_FLOAT; - lib3ds_track_read(&n->hotspot_track, io); - } else { - lib3ds_chunk_unknown(chunk, io); - } - break; - } - - case CHK_FALL_TRACK_TAG: { - if (node->type == LIB3DS_NODE_SPOTLIGHT) { - Lib3dsSpotlightNode *n = (Lib3dsSpotlightNode*)node; - n->falloff_track.type= LIB3DS_TRACK_FLOAT; - lib3ds_track_read(&n->falloff_track, io); - } else { - lib3ds_chunk_unknown(chunk, io); - } - break; - } - - case CHK_ROLL_TRACK_TAG: { - switch (node->type) { - case LIB3DS_NODE_CAMERA: { - Lib3dsCameraNode *n = (Lib3dsCameraNode*)node; - n->roll_track.type = LIB3DS_TRACK_FLOAT; - lib3ds_track_read(&n->roll_track, io); - break; - } - case LIB3DS_NODE_SPOTLIGHT: { - Lib3dsSpotlightNode *n = (Lib3dsSpotlightNode*)node; - n->roll_track.type = LIB3DS_TRACK_FLOAT; - lib3ds_track_read(&n->roll_track, io); - break; - } - default: - lib3ds_chunk_unknown(chunk, io); - } - break; - } - - case CHK_HIDE_TRACK_TAG: { - if (node->type == LIB3DS_NODE_MESH_INSTANCE) { - Lib3dsMeshInstanceNode *n = (Lib3dsMeshInstanceNode*)node; - n->hide_track.type = LIB3DS_TRACK_BOOL; - lib3ds_track_read(&n->hide_track, io); - } else { - lib3ds_chunk_unknown(chunk, io); - } - break; - } - - case CHK_MORPH_SMOOTH: { - if (node->type == LIB3DS_NODE_MESH_INSTANCE) { - Lib3dsMeshInstanceNode *n = (Lib3dsMeshInstanceNode*)node; - n->morph_smooth = lib3ds_io_read_float(io); - } else { - lib3ds_chunk_unknown(chunk, io); - } - } - break; - - /* - case LIB3DS_MORPH_TRACK_TAG: { - if (node->type == LIB3DS_NODE_MESH_INSTANCE) { - Lib3dsMeshInstanceNode *n = (Lib3dsMeshInstanceNode*)node; - n->morph_track = lib3ds_track_new(node, LIB3DS_TRACK_MORPH, 0); - lib3ds_track_read(n->morph_track, io); - } else { - lib3ds_chunk_unknown(chunk, io); - } - } - break; - */ - - default: - lib3ds_chunk_unknown(chunk, io); - } - } - - lib3ds_chunk_read_end(&c, io); -} - - -void -lib3ds_node_write(Lib3dsNode *node, uint16_t node_id, uint16_t parent_id, Lib3dsIo *io) { - Lib3dsChunk c; - - switch (node->type) { - case LIB3DS_NODE_AMBIENT_COLOR: - c.chunk = CHK_AMBIENT_NODE_TAG; - break; - - case LIB3DS_NODE_MESH_INSTANCE: - c.chunk = CHK_OBJECT_NODE_TAG; - break; - - case LIB3DS_NODE_CAMERA: - c.chunk = CHK_CAMERA_NODE_TAG; - break; - - case LIB3DS_NODE_CAMERA_TARGET: - c.chunk = CHK_TARGET_NODE_TAG; - break; - - case LIB3DS_NODE_OMNILIGHT: - c.chunk = CHK_LIGHT_NODE_TAG; - break; - - case LIB3DS_NODE_SPOTLIGHT: - c.chunk = CHK_SPOTLIGHT_NODE_TAG; - break; - - case LIB3DS_NODE_SPOTLIGHT_TARGET: - c.chunk = CHK_L_TARGET_NODE_TAG; - break; - - default: - assert(0); - return; - } - - lib3ds_chunk_write_start(&c, io); - - { /*---- CHK_NODE_ID ----*/ - Lib3dsChunk c; - c.chunk = CHK_NODE_ID; - c.size = 8; - lib3ds_chunk_write(&c, io); - lib3ds_io_write_intw(io, node_id); - } - - { /*---- CHK_NODE_HDR ----*/ - Lib3dsChunk c; - c.chunk = CHK_NODE_HDR; - c.size = 6 + 1 + (uint32_t)strlen(node->name) + 2 + 2 + 2; - lib3ds_chunk_write(&c, io); - lib3ds_io_write_string(io, node->name); - lib3ds_io_write_word(io, node->flags & 0xffff); - lib3ds_io_write_word(io, (node->flags >> 16) & 0xffff); - lib3ds_io_write_word(io, parent_id); - } - - switch (c.chunk) { - case CHK_AMBIENT_NODE_TAG: { - Lib3dsAmbientColorNode *n = (Lib3dsAmbientColorNode*)node; - if (n->color_track.nkeys) { /*---- CHK_COL_TRACK_TAG ----*/ - Lib3dsChunk c; - c.chunk = CHK_COL_TRACK_TAG; - lib3ds_chunk_write_start(&c, io); - lib3ds_track_write(&n->color_track, io); - lib3ds_chunk_write_end(&c, io); - } - break; - } - - case CHK_OBJECT_NODE_TAG: { - Lib3dsMeshInstanceNode *n = (Lib3dsMeshInstanceNode*)node; - { /*---- CHK_PIVOT ----*/ - Lib3dsChunk c; - c.chunk = CHK_PIVOT; - c.size = 18; - lib3ds_chunk_write(&c, io); - lib3ds_io_write_vector(io, n->pivot); - } - - { /*---- CHK_INSTANCE_NAME ----*/ - Lib3dsChunk c; - const char *name; - if (strlen(n->instance_name)) { - name = n->instance_name; - - c.chunk = CHK_INSTANCE_NAME; - c.size = 6 + 1 + (uint32_t)strlen(name); - lib3ds_chunk_write(&c, io); - lib3ds_io_write_string(io, name); - } - } - { - int i; - for (i = 0; i < 3; ++i) { - if ((fabs(n->bbox_min[i]) > LIB3DS_EPSILON) || - (fabs(n->bbox_max[i]) > LIB3DS_EPSILON)) { - break; - } - } - - if (i < 3) { /*---- CHK_BOUNDBOX ----*/ - Lib3dsChunk c; - c.chunk = CHK_BOUNDBOX; - c.size = 30; - lib3ds_chunk_write(&c, io); - lib3ds_io_write_vector(io, n->bbox_min); - lib3ds_io_write_vector(io, n->bbox_max); - } - } - - if (n->pos_track.nkeys) { /*---- CHK_POS_TRACK_TAG ----*/ - Lib3dsChunk c; - c.chunk = CHK_POS_TRACK_TAG; - lib3ds_chunk_write_start(&c, io); - lib3ds_track_write(&n->pos_track, io); - lib3ds_chunk_write_end(&c, io); - } - if (n->rot_track.nkeys) { /*---- CHK_ROT_TRACK_TAG ----*/ - Lib3dsChunk c; - c.chunk = CHK_ROT_TRACK_TAG; - lib3ds_chunk_write_start(&c, io); - lib3ds_track_write(&n->rot_track, io); - lib3ds_chunk_write_end(&c, io); - } - if (n->scl_track.nkeys) { /*---- LIB3DS_SCL_TRACK_TAG ----*/ - Lib3dsChunk c; - c.chunk = CHK_SCL_TRACK_TAG; - lib3ds_chunk_write_start(&c, io); - lib3ds_track_write(&n->scl_track, io); - lib3ds_chunk_write_end(&c, io); - } - if (n->hide_track.nkeys) { /*---- CHK_HIDE_TRACK_TAG ----*/ - Lib3dsChunk c; - c.chunk = CHK_HIDE_TRACK_TAG; - lib3ds_chunk_write_start(&c, io); - lib3ds_track_write(&n->hide_track, io); - lib3ds_chunk_write_end(&c, io); - } - if (fabs(n->morph_smooth) > LIB3DS_EPSILON) { /*---- CHK_MORPH_SMOOTH ----*/ - Lib3dsChunk c; - c.chunk = CHK_MORPH_SMOOTH; - c.size = 10; - lib3ds_chunk_write(&c, io); - lib3ds_io_write_float(io, n->morph_smooth); - } - break; - } - - case CHK_CAMERA_NODE_TAG: { - Lib3dsCameraNode *n = (Lib3dsCameraNode*)node; - if (n->pos_track.nkeys) { /*---- CHK_POS_TRACK_TAG ----*/ - Lib3dsChunk c; - c.chunk = CHK_POS_TRACK_TAG; - lib3ds_chunk_write_start(&c, io); - lib3ds_track_write(&n->pos_track, io); - lib3ds_chunk_write_end(&c, io); - } - if (n->fov_track.nkeys) { /*---- CHK_FOV_TRACK_TAG ----*/ - Lib3dsChunk c; - c.chunk = CHK_FOV_TRACK_TAG; - lib3ds_chunk_write_start(&c, io); - lib3ds_track_write(&n->fov_track, io); - lib3ds_chunk_write_end(&c, io); - } - if (n->roll_track.nkeys) { /*---- CHK_ROLL_TRACK_TAG ----*/ - Lib3dsChunk c; - c.chunk = CHK_ROLL_TRACK_TAG; - lib3ds_chunk_write_start(&c, io); - lib3ds_track_write(&n->roll_track, io); - lib3ds_chunk_write_end(&c, io); - } - break; - } - - case CHK_TARGET_NODE_TAG: { - Lib3dsTargetNode *n = (Lib3dsTargetNode*)node; - if (n->pos_track.nkeys) { /*---- CHK_POS_TRACK_TAG ----*/ - Lib3dsChunk c; - c.chunk = CHK_POS_TRACK_TAG; - lib3ds_chunk_write_start(&c, io); - lib3ds_track_write(&n->pos_track, io); - lib3ds_chunk_write_end(&c, io); - } - break; - } - - case CHK_LIGHT_NODE_TAG: { - Lib3dsOmnilightNode *n = (Lib3dsOmnilightNode*)node; - if (n->pos_track.nkeys) { /*---- CHK_POS_TRACK_TAG ----*/ - Lib3dsChunk c; - c.chunk = CHK_POS_TRACK_TAG; - lib3ds_chunk_write_start(&c, io); - lib3ds_track_write(&n->pos_track, io); - lib3ds_chunk_write_end(&c, io); - } - if (n->color_track.nkeys) { /*---- CHK_COL_TRACK_TAG ----*/ - Lib3dsChunk c; - c.chunk = CHK_COL_TRACK_TAG; - lib3ds_chunk_write_start(&c, io); - lib3ds_track_write(&n->color_track, io); - lib3ds_chunk_write_end(&c, io); - } - break; - } - - case CHK_SPOTLIGHT_NODE_TAG: { - Lib3dsSpotlightNode *n = (Lib3dsSpotlightNode*)node; - if (n->pos_track.nkeys) { /*---- CHK_POS_TRACK_TAG ----*/ - Lib3dsChunk c; - c.chunk = CHK_POS_TRACK_TAG; - lib3ds_chunk_write_start(&c, io); - lib3ds_track_write(&n->pos_track, io); - lib3ds_chunk_write_end(&c, io); - } - if (n->color_track.nkeys) { /*---- CHK_COL_TRACK_TAG ----*/ - Lib3dsChunk c; - c.chunk = CHK_COL_TRACK_TAG; - lib3ds_chunk_write_start(&c, io); - lib3ds_track_write(&n->color_track, io); - lib3ds_chunk_write_end(&c, io); - } - if (n->hotspot_track.nkeys) { /*---- CHK_HOT_TRACK_TAG ----*/ - Lib3dsChunk c; - c.chunk = CHK_HOT_TRACK_TAG; - lib3ds_chunk_write_start(&c, io); - lib3ds_track_write(&n->hotspot_track, io); - lib3ds_chunk_write_end(&c, io); - } - if (n->falloff_track.nkeys) { /*---- CHK_FALL_TRACK_TAG ----*/ - Lib3dsChunk c; - c.chunk = CHK_FALL_TRACK_TAG; - lib3ds_chunk_write_start(&c, io); - lib3ds_track_write(&n->falloff_track, io); - lib3ds_chunk_write_end(&c, io); - } - if (n->roll_track.nkeys) { /*---- CHK_ROLL_TRACK_TAG ----*/ - Lib3dsChunk c; - c.chunk = CHK_ROLL_TRACK_TAG; - lib3ds_chunk_write_start(&c, io); - lib3ds_track_write(&n->roll_track, io); - lib3ds_chunk_write_end(&c, io); - } - break; - } - - case CHK_L_TARGET_NODE_TAG: { - Lib3dsTargetNode *n = (Lib3dsTargetNode*)node; - if (n->pos_track.nkeys) { /*---- CHK_POS_TRACK_TAG ----*/ - Lib3dsChunk c; - c.chunk = CHK_POS_TRACK_TAG; - lib3ds_chunk_write_start(&c, io); - lib3ds_track_write(&n->pos_track, io); - lib3ds_chunk_write_end(&c, io); - } - break; - } - - default: - break; - } - - lib3ds_chunk_write_end(&c, io); -} - +/* + Copyright (C) 1996-2008 by Jan Eric Kyprianidis + 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. + + Thisprogram 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, see . +*/ +#include "lib3ds_impl.h" + + +/*! + * Create and return a new node object. + * + * The node is returned with an identity matrix. All other fields + * are zero. + * + * \return Lib3dsNode + */ +Lib3dsNode* +lib3ds_node_new(Lib3dsNodeType type) { + Lib3dsNode *node; + switch (type) { + case LIB3DS_NODE_AMBIENT_COLOR: { + Lib3dsAmbientColorNode *n = (Lib3dsAmbientColorNode*)calloc(sizeof(Lib3dsAmbientColorNode), 1); + node = (Lib3dsNode*)n; + strcpy(node->name, "$AMBIENT$"); + n->color_track.type = LIB3DS_TRACK_VECTOR; + break; + } + + case LIB3DS_NODE_MESH_INSTANCE: { + Lib3dsMeshInstanceNode *n = (Lib3dsMeshInstanceNode*)calloc(sizeof(Lib3dsMeshInstanceNode), 1); + node = (Lib3dsNode*)n; + strcpy(node->name, "$$$DUMMY"); + n->pos_track.type = LIB3DS_TRACK_VECTOR; + n->scl_track.type = LIB3DS_TRACK_VECTOR; + n->rot_track.type = LIB3DS_TRACK_QUAT; + n->hide_track.type = LIB3DS_TRACK_BOOL; + break; + } + + case LIB3DS_NODE_CAMERA: { + Lib3dsCameraNode *n = (Lib3dsCameraNode*)calloc(sizeof(Lib3dsCameraNode), 1); + node = (Lib3dsNode*)n; + n->pos_track.type = LIB3DS_TRACK_VECTOR; + n->fov_track.type = LIB3DS_TRACK_FLOAT; + n->roll_track.type = LIB3DS_TRACK_FLOAT; + break; + } + + case LIB3DS_NODE_CAMERA_TARGET: { + Lib3dsTargetNode *n = (Lib3dsTargetNode*)calloc(sizeof(Lib3dsTargetNode), 1); + node = (Lib3dsNode*)n; + n->pos_track.type = LIB3DS_TRACK_VECTOR; + break; + } + + case LIB3DS_NODE_OMNILIGHT: { + Lib3dsOmnilightNode *n = (Lib3dsOmnilightNode*)calloc(sizeof(Lib3dsOmnilightNode), 1); + node = (Lib3dsNode*)n; + n->pos_track.type = LIB3DS_TRACK_VECTOR; + n->color_track.type = LIB3DS_TRACK_VECTOR; + break; + } + + case LIB3DS_NODE_SPOTLIGHT: { + Lib3dsSpotlightNode *n = (Lib3dsSpotlightNode*)calloc(sizeof(Lib3dsSpotlightNode), 1); + node = (Lib3dsNode*)n; + n->pos_track.type = LIB3DS_TRACK_VECTOR; + n->color_track.type = LIB3DS_TRACK_VECTOR; + n->hotspot_track.type = LIB3DS_TRACK_FLOAT; + n->falloff_track.type = LIB3DS_TRACK_FLOAT; + n->roll_track.type = LIB3DS_TRACK_FLOAT; + break; + } + + case LIB3DS_NODE_SPOTLIGHT_TARGET: { + Lib3dsTargetNode *n = (Lib3dsTargetNode*)calloc(sizeof(Lib3dsTargetNode), 1); + node = (Lib3dsNode*)n; + n->pos_track.type = LIB3DS_TRACK_VECTOR; + break; + } + + default: + assert(0); + return NULL; + } + + node->type = type; + node->node_id = 65535; + node->user_id = 65535; + lib3ds_matrix_identity(node->matrix); + return node; +} + + +Lib3dsAmbientColorNode* +lib3ds_node_new_ambient_color(float color0[3]) { + Lib3dsNode *node; + Lib3dsAmbientColorNode *n; + + node = lib3ds_node_new(LIB3DS_NODE_AMBIENT_COLOR); + + n = (Lib3dsAmbientColorNode*)node; + lib3ds_track_resize(&n->color_track, 1); + if (color0) { + lib3ds_vector_copy(n->color_track.keys[0].value, color0); + } else { + lib3ds_vector_zero(n->color_track.keys[0].value); + } + + return n; +} + + +Lib3dsMeshInstanceNode* +lib3ds_node_new_mesh_instance(Lib3dsMesh *mesh, const char *instance_name, float pos0[3], float scl0[3], float rot0[4]) { + Lib3dsNode *node; + Lib3dsMeshInstanceNode *n; + int i; + + node = lib3ds_node_new(LIB3DS_NODE_MESH_INSTANCE); + if (mesh) { + strcpy(node->name, mesh->name); + } else { + strcpy(node->name, "$$$DUMMY"); + } + + n = (Lib3dsMeshInstanceNode*)node; + if (instance_name) { + strcpy(n->instance_name, instance_name); + } + + lib3ds_track_resize(&n->pos_track, 1); + if (pos0) { + lib3ds_vector_copy(n->pos_track.keys[0].value, pos0); + } + + lib3ds_track_resize(&n->scl_track, 1); + if (scl0) { + lib3ds_vector_copy(n->scl_track.keys[0].value, scl0); + } else { + lib3ds_vector_make(n->scl_track.keys[0].value, 1, 1, 1); + } + + lib3ds_track_resize(&n->rot_track, 1); + if (rot0) { + for (i = 0; i < 4; ++i) n->rot_track.keys[0].value[i] = rot0[i]; + } else { + for (i = 0; i < 4; ++i) n->rot_track.keys[0].value[i] = 0; + } + + return n; +} + + +Lib3dsCameraNode* +lib3ds_node_new_camera(Lib3dsCamera *camera) { + Lib3dsNode *node = lib3ds_node_new(LIB3DS_NODE_CAMERA); + Lib3dsCameraNode *n; + + assert(camera); + node = lib3ds_node_new(LIB3DS_NODE_CAMERA); + strcpy(node->name, camera->name); + + n = (Lib3dsCameraNode*)node; + lib3ds_track_resize(&n->pos_track, 1); + lib3ds_vector_copy(n->pos_track.keys[0].value, camera->position); + + lib3ds_track_resize(&n->fov_track, 1); + n->fov_track.keys[0].value[0] = camera->fov; + + lib3ds_track_resize(&n->roll_track, 1); + n->roll_track.keys[0].value[0] = camera->roll; + + return n; +} + + +Lib3dsTargetNode* +lib3ds_node_new_camera_target(Lib3dsCamera *camera) { + Lib3dsNode *node; + Lib3dsTargetNode *n; + + assert(camera); + node = lib3ds_node_new(LIB3DS_NODE_CAMERA_TARGET); + strcpy(node->name, camera->name); + + n = (Lib3dsTargetNode*)node; + lib3ds_track_resize(&n->pos_track, 1); + lib3ds_vector_copy(n->pos_track.keys[0].value, camera->target); + + return n; +} + + +Lib3dsOmnilightNode* +lib3ds_node_new_omnilight(Lib3dsLight *light) { + Lib3dsNode *node; + Lib3dsOmnilightNode *n; + + assert(light); + node = lib3ds_node_new(LIB3DS_NODE_OMNILIGHT); + strcpy(node->name, light->name); + + n = (Lib3dsOmnilightNode*)node; + lib3ds_track_resize(&n->pos_track, 1); + lib3ds_vector_copy(n->pos_track.keys[0].value, light->position); + + lib3ds_track_resize(&n->color_track, 1); + lib3ds_vector_copy(n->color_track.keys[0].value, light->color); + + return n; +} + + +Lib3dsSpotlightNode* +lib3ds_node_new_spotlight(Lib3dsLight *light) { + Lib3dsNode *node; + Lib3dsSpotlightNode *n; + + assert(light); + node = lib3ds_node_new(LIB3DS_NODE_SPOTLIGHT); + strcpy(node->name, light->name); + + n = (Lib3dsSpotlightNode*)node; + lib3ds_track_resize(&n->pos_track, 1); + lib3ds_vector_copy(n->pos_track.keys[0].value, light->position); + + lib3ds_track_resize(&n->color_track, 1); + lib3ds_vector_copy(n->color_track.keys[0].value, light->color); + + lib3ds_track_resize(&n->hotspot_track, 1); + n->hotspot_track.keys[0].value[0] = light->hotspot; + + lib3ds_track_resize(&n->falloff_track, 1); + n->falloff_track.keys[0].value[0] = light->falloff; + + lib3ds_track_resize(&n->roll_track, 1); + n->roll_track.keys[0].value[0] = light->roll; + + return n; +} + + +Lib3dsTargetNode* +lib3ds_node_new_spotligf_target(Lib3dsLight *light) { + Lib3dsNode *node; + Lib3dsTargetNode *n; + + assert(light); + node = lib3ds_node_new(LIB3DS_NODE_SPOTLIGHT_TARGET); + strcpy(node->name, light->name); + + n = (Lib3dsTargetNode*)node; + lib3ds_track_resize(&n->pos_track, 1); + lib3ds_vector_copy(n->pos_track.keys[0].value, light->target); + + return n; +} + + +static void +free_node_and_childs(Lib3dsNode *node) { + assert(node); + switch (node->type) { + case LIB3DS_NODE_AMBIENT_COLOR: { + Lib3dsAmbientColorNode *n = (Lib3dsAmbientColorNode*)node; + lib3ds_track_resize(&n->color_track, 0); + break; + } + + case LIB3DS_NODE_MESH_INSTANCE: { + Lib3dsMeshInstanceNode *n = (Lib3dsMeshInstanceNode*)node; + lib3ds_track_resize(&n->pos_track, 0); + lib3ds_track_resize(&n->rot_track, 0); + lib3ds_track_resize(&n->scl_track, 0); + lib3ds_track_resize(&n->hide_track, 0); + break; + } + + case LIB3DS_NODE_CAMERA: { + Lib3dsCameraNode *n = (Lib3dsCameraNode*)node; + lib3ds_track_resize(&n->pos_track, 0); + lib3ds_track_resize(&n->fov_track, 0); + lib3ds_track_resize(&n->roll_track, 0); + break; + } + + case LIB3DS_NODE_CAMERA_TARGET: { + Lib3dsTargetNode *n = (Lib3dsTargetNode*)node; + lib3ds_track_resize(&n->pos_track, 0); + break; + } + + case LIB3DS_NODE_OMNILIGHT: { + Lib3dsOmnilightNode *n = (Lib3dsOmnilightNode*)node; + lib3ds_track_resize(&n->pos_track, 0); + lib3ds_track_resize(&n->color_track, 0); + break; + } + + case LIB3DS_NODE_SPOTLIGHT: { + Lib3dsSpotlightNode *n = (Lib3dsSpotlightNode*)node; + lib3ds_track_resize(&n->pos_track, 0); + lib3ds_track_resize(&n->color_track, 0); + lib3ds_track_resize(&n->hotspot_track, 0); + lib3ds_track_resize(&n->falloff_track, 0); + lib3ds_track_resize(&n->roll_track, 0); + break; + } + + case LIB3DS_NODE_SPOTLIGHT_TARGET: { + Lib3dsTargetNode *n = (Lib3dsTargetNode*)node; + lib3ds_track_resize(&n->pos_track, 0); + break; + } + } + { + Lib3dsNode *p, *q; + for (p = node->childs; p; p = q) { + q = p->next; + free_node_and_childs(p); + } + } + free(node); +} + + +/*! + * Free a node and all of its resources. + * + * \param node Lib3dsNode object to be freed. + */ +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 + */ +void +lib3ds_node_eval(Lib3dsNode *node, float t) { + assert(node); + switch (node->type) { + case LIB3DS_NODE_AMBIENT_COLOR: { + Lib3dsAmbientColorNode *n = (Lib3dsAmbientColorNode*)node; + if (node->parent) { + lib3ds_matrix_copy(node->matrix, node->parent->matrix); + } else { + lib3ds_matrix_identity(node->matrix); + } + lib3ds_track_eval_vector(&n->color_track, n->color, t); + break; + } + + case LIB3DS_NODE_MESH_INSTANCE: { + float M[4][4]; + Lib3dsMeshInstanceNode *n = (Lib3dsMeshInstanceNode*)node; + + lib3ds_track_eval_vector(&n->pos_track, n->pos, t); + lib3ds_track_eval_quat(&n->rot_track, n->rot, t); + if (n->scl_track.nkeys) { + lib3ds_track_eval_vector(&n->scl_track, n->scl, t); + } else { + n->scl[0] = n->scl[1] = n->scl[2] = 1.0f; + } + lib3ds_track_eval_bool(&n->hide_track, &n->hide, t); + + lib3ds_matrix_identity(M); + lib3ds_matrix_translate(M, n->pos[0], n->pos[1], n->pos[2]); + lib3ds_matrix_rotate_quat(M, n->rot); + lib3ds_matrix_scale(M, n->scl[0], n->scl[1], n->scl[2]); + + if (node->parent) { + lib3ds_matrix_mult(node->matrix, node->parent->matrix, M); + } else { + lib3ds_matrix_copy(node->matrix, M); + } + break; + } + + case LIB3DS_NODE_CAMERA: { + Lib3dsCameraNode *n = (Lib3dsCameraNode*)node; + lib3ds_track_eval_vector(&n->pos_track, n->pos, t); + lib3ds_track_eval_float(&n->fov_track, &n->fov, t); + lib3ds_track_eval_float(&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[0], n->pos[1], n->pos[2]); + break; + } + + case LIB3DS_NODE_CAMERA_TARGET: { + Lib3dsTargetNode *n = (Lib3dsTargetNode*)node; + lib3ds_track_eval_vector(&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[0], n->pos[1], n->pos[2]); + break; + } + + case LIB3DS_NODE_OMNILIGHT: { + Lib3dsOmnilightNode *n = (Lib3dsOmnilightNode*)node; + lib3ds_track_eval_vector(&n->pos_track, n->pos, t); + lib3ds_track_eval_vector(&n->color_track, n->color, 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[0], n->pos[1], n->pos[2]); + break; + } + + case LIB3DS_NODE_SPOTLIGHT: { + Lib3dsSpotlightNode *n = (Lib3dsSpotlightNode*)node; + lib3ds_track_eval_vector(&n->pos_track, n->pos, t); + lib3ds_track_eval_vector(&n->color_track, n->color, t); + lib3ds_track_eval_float(&n->hotspot_track, &n->hotspot, t); + lib3ds_track_eval_float(&n->falloff_track, &n->falloff, t); + lib3ds_track_eval_float(&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[0], n->pos[1], n->pos[2]); + break; + } + + case LIB3DS_NODE_SPOTLIGHT_TARGET: { + Lib3dsTargetNode *n = (Lib3dsTargetNode*)node; + lib3ds_track_eval_vector(&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[0], n->pos[1], n->pos[2]); + 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. + */ +Lib3dsNode* +lib3ds_node_by_name(Lib3dsNode *node, const char* name, Lib3dsNodeType 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. + */ +Lib3dsNode* +lib3ds_node_by_id(Lib3dsNode *node, uint16_t 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); +} + + +void +lib3ds_node_read(Lib3dsNode *node, Lib3dsIo *io) { + Lib3dsChunk c; + uint16_t chunk; + + assert(node); + lib3ds_chunk_read_start(&c, 0, io); + + switch (c.chunk) { + case CHK_AMBIENT_NODE_TAG: + case CHK_OBJECT_NODE_TAG: + case CHK_CAMERA_NODE_TAG: + case CHK_TARGET_NODE_TAG: + case CHK_LIGHT_NODE_TAG: + case CHK_SPOTLIGHT_NODE_TAG: + case CHK_L_TARGET_NODE_TAG: + break; + default: + return; + } + + while ((chunk = lib3ds_chunk_read_next(&c, io)) != 0) { + switch (chunk) { + case CHK_NODE_ID: { + node->node_id = lib3ds_io_read_word(io); + lib3ds_io_log_indent(io, 1); + lib3ds_io_log(io, LIB3DS_LOG_INFO, "ID=%d", (short)node->node_id); + lib3ds_io_log_indent(io, -1); + break; + } + + case CHK_NODE_HDR: { + lib3ds_io_read_string(io, node->name, 64); + node->flags = lib3ds_io_read_word(io); + node->flags |= ((uint32_t)lib3ds_io_read_word(io)) << 16; + node->user_id = lib3ds_io_read_word(io); + + lib3ds_io_log_indent(io, 1); + lib3ds_io_log(io, LIB3DS_LOG_INFO, "NAME=%s", node->name); + lib3ds_io_log(io, LIB3DS_LOG_INFO, "PARENT=%d", (short)node->user_id); + lib3ds_io_log_indent(io, -1); + break; + } + + case CHK_PIVOT: { + if (node->type == LIB3DS_NODE_MESH_INSTANCE) { + Lib3dsMeshInstanceNode *n = (Lib3dsMeshInstanceNode*)node; + lib3ds_io_read_vector(io, n->pivot); + } else { + lib3ds_chunk_unknown(chunk, io); + } + break; + } + + case CHK_INSTANCE_NAME: { + if (node->type == LIB3DS_NODE_MESH_INSTANCE) { + Lib3dsMeshInstanceNode *n = (Lib3dsMeshInstanceNode*)node; + lib3ds_io_read_string(io, n->instance_name, 64); + } else { + lib3ds_chunk_unknown(chunk, io); + } + break; + } + + case CHK_BOUNDBOX: { + if (node->type == LIB3DS_NODE_MESH_INSTANCE) { + Lib3dsMeshInstanceNode *n = (Lib3dsMeshInstanceNode*)node; + lib3ds_io_read_vector(io, n->bbox_min); + lib3ds_io_read_vector(io, n->bbox_max); + } else { + lib3ds_chunk_unknown(chunk, io); + } + break; + } + + case CHK_COL_TRACK_TAG: { + Lib3dsTrack *track = 0; + switch (node->type) { + case LIB3DS_NODE_AMBIENT_COLOR: { + Lib3dsAmbientColorNode *n = (Lib3dsAmbientColorNode*)node; + track = &n->color_track; + break; + } + case LIB3DS_NODE_OMNILIGHT: { + Lib3dsOmnilightNode *n = (Lib3dsOmnilightNode*)node; + track = &n->color_track; + break; + } + case LIB3DS_NODE_SPOTLIGHT: { + Lib3dsSpotlightNode *n = (Lib3dsSpotlightNode*)node; + track = &n->color_track; + break; + } + default: + lib3ds_chunk_unknown(chunk, io); + } + if (track) { + lib3ds_track_read(track, io); + } + break; + } + + case CHK_POS_TRACK_TAG: { + Lib3dsTrack *track = 0; + switch (node->type) { + case LIB3DS_NODE_MESH_INSTANCE: { + Lib3dsMeshInstanceNode *n = (Lib3dsMeshInstanceNode*)node; + track = &n->pos_track; + break; + } + case LIB3DS_NODE_CAMERA: { + Lib3dsCameraNode *n = (Lib3dsCameraNode*)node; + track = &n->pos_track; + break; + } + case LIB3DS_NODE_CAMERA_TARGET: { + Lib3dsTargetNode *n = (Lib3dsTargetNode*)node; + track = &n->pos_track; + break; + } + case LIB3DS_NODE_OMNILIGHT: { + Lib3dsOmnilightNode *n = (Lib3dsOmnilightNode*)node; + track = &n->pos_track; + break; + } + case LIB3DS_NODE_SPOTLIGHT: { + Lib3dsSpotlightNode *n = (Lib3dsSpotlightNode*)node; + track = &n->pos_track; + break; + } + case LIB3DS_NODE_SPOTLIGHT_TARGET: { + Lib3dsTargetNode *n = (Lib3dsTargetNode*)node; + track = &n->pos_track; + break; + } + default: + lib3ds_chunk_unknown(chunk, io); + } + if (track) { + lib3ds_track_read(track, io); + } + break; + } + + case CHK_ROT_TRACK_TAG: { + if (node->type == LIB3DS_NODE_MESH_INSTANCE) { + Lib3dsMeshInstanceNode *n = (Lib3dsMeshInstanceNode*)node; + n->rot_track.type = LIB3DS_TRACK_QUAT; + lib3ds_track_read(&n->rot_track, io); + } else { + lib3ds_chunk_unknown(chunk, io); + } + break; + } + + case CHK_SCL_TRACK_TAG: { + if (node->type == LIB3DS_NODE_MESH_INSTANCE) { + Lib3dsMeshInstanceNode *n = (Lib3dsMeshInstanceNode*)node; + n->scl_track.type = LIB3DS_TRACK_VECTOR; + lib3ds_track_read(&n->scl_track, io); + } else { + lib3ds_chunk_unknown(chunk, io); + } + break; + } + + case CHK_FOV_TRACK_TAG: { + if (node->type == LIB3DS_NODE_CAMERA) { + Lib3dsCameraNode *n = (Lib3dsCameraNode*)node; + n->fov_track.type = LIB3DS_TRACK_FLOAT; + lib3ds_track_read(&n->fov_track, io); + } else { + lib3ds_chunk_unknown(chunk, io); + } + break; + } + + case CHK_HOT_TRACK_TAG: { + if (node->type == LIB3DS_NODE_SPOTLIGHT) { + Lib3dsSpotlightNode *n = (Lib3dsSpotlightNode*)node; + n->hotspot_track.type = LIB3DS_TRACK_FLOAT; + lib3ds_track_read(&n->hotspot_track, io); + } else { + lib3ds_chunk_unknown(chunk, io); + } + break; + } + + case CHK_FALL_TRACK_TAG: { + if (node->type == LIB3DS_NODE_SPOTLIGHT) { + Lib3dsSpotlightNode *n = (Lib3dsSpotlightNode*)node; + n->falloff_track.type= LIB3DS_TRACK_FLOAT; + lib3ds_track_read(&n->falloff_track, io); + } else { + lib3ds_chunk_unknown(chunk, io); + } + break; + } + + case CHK_ROLL_TRACK_TAG: { + switch (node->type) { + case LIB3DS_NODE_CAMERA: { + Lib3dsCameraNode *n = (Lib3dsCameraNode*)node; + n->roll_track.type = LIB3DS_TRACK_FLOAT; + lib3ds_track_read(&n->roll_track, io); + break; + } + case LIB3DS_NODE_SPOTLIGHT: { + Lib3dsSpotlightNode *n = (Lib3dsSpotlightNode*)node; + n->roll_track.type = LIB3DS_TRACK_FLOAT; + lib3ds_track_read(&n->roll_track, io); + break; + } + default: + lib3ds_chunk_unknown(chunk, io); + } + break; + } + + case CHK_HIDE_TRACK_TAG: { + if (node->type == LIB3DS_NODE_MESH_INSTANCE) { + Lib3dsMeshInstanceNode *n = (Lib3dsMeshInstanceNode*)node; + n->hide_track.type = LIB3DS_TRACK_BOOL; + lib3ds_track_read(&n->hide_track, io); + } else { + lib3ds_chunk_unknown(chunk, io); + } + break; + } + + case CHK_MORPH_SMOOTH: { + if (node->type == LIB3DS_NODE_MESH_INSTANCE) { + Lib3dsMeshInstanceNode *n = (Lib3dsMeshInstanceNode*)node; + n->morph_smooth = lib3ds_io_read_float(io); + } else { + lib3ds_chunk_unknown(chunk, io); + } + } + break; + + /* + case LIB3DS_MORPH_TRACK_TAG: { + if (node->type == LIB3DS_NODE_MESH_INSTANCE) { + Lib3dsMeshInstanceNode *n = (Lib3dsMeshInstanceNode*)node; + n->morph_track = lib3ds_track_new(node, LIB3DS_TRACK_MORPH, 0); + lib3ds_track_read(n->morph_track, io); + } else { + lib3ds_chunk_unknown(chunk, io); + } + } + break; + */ + + default: + lib3ds_chunk_unknown(chunk, io); + } + } + + lib3ds_chunk_read_end(&c, io); +} + + +void +lib3ds_node_write(Lib3dsNode *node, uint16_t node_id, uint16_t parent_id, Lib3dsIo *io) { + Lib3dsChunk c; + + switch (node->type) { + case LIB3DS_NODE_AMBIENT_COLOR: + c.chunk = CHK_AMBIENT_NODE_TAG; + break; + + case LIB3DS_NODE_MESH_INSTANCE: + c.chunk = CHK_OBJECT_NODE_TAG; + break; + + case LIB3DS_NODE_CAMERA: + c.chunk = CHK_CAMERA_NODE_TAG; + break; + + case LIB3DS_NODE_CAMERA_TARGET: + c.chunk = CHK_TARGET_NODE_TAG; + break; + + case LIB3DS_NODE_OMNILIGHT: + c.chunk = CHK_LIGHT_NODE_TAG; + break; + + case LIB3DS_NODE_SPOTLIGHT: + c.chunk = CHK_SPOTLIGHT_NODE_TAG; + break; + + case LIB3DS_NODE_SPOTLIGHT_TARGET: + c.chunk = CHK_L_TARGET_NODE_TAG; + break; + + default: + assert(0); + return; + } + + lib3ds_chunk_write_start(&c, io); + + { /*---- CHK_NODE_ID ----*/ + Lib3dsChunk c; + c.chunk = CHK_NODE_ID; + c.size = 8; + lib3ds_chunk_write(&c, io); + lib3ds_io_write_intw(io, node_id); + } + + { /*---- CHK_NODE_HDR ----*/ + Lib3dsChunk c; + c.chunk = CHK_NODE_HDR; + c.size = 6 + 1 + (uint32_t)strlen(node->name) + 2 + 2 + 2; + lib3ds_chunk_write(&c, io); + lib3ds_io_write_string(io, node->name); + lib3ds_io_write_word(io, node->flags & 0xffff); + lib3ds_io_write_word(io, (node->flags >> 16) & 0xffff); + lib3ds_io_write_word(io, parent_id); + } + + switch (c.chunk) { + case CHK_AMBIENT_NODE_TAG: { + Lib3dsAmbientColorNode *n = (Lib3dsAmbientColorNode*)node; + if (n->color_track.nkeys) { /*---- CHK_COL_TRACK_TAG ----*/ + Lib3dsChunk c; + c.chunk = CHK_COL_TRACK_TAG; + lib3ds_chunk_write_start(&c, io); + lib3ds_track_write(&n->color_track, io); + lib3ds_chunk_write_end(&c, io); + } + break; + } + + case CHK_OBJECT_NODE_TAG: { + Lib3dsMeshInstanceNode *n = (Lib3dsMeshInstanceNode*)node; + { /*---- CHK_PIVOT ----*/ + Lib3dsChunk c; + c.chunk = CHK_PIVOT; + c.size = 18; + lib3ds_chunk_write(&c, io); + lib3ds_io_write_vector(io, n->pivot); + } + + { /*---- CHK_INSTANCE_NAME ----*/ + Lib3dsChunk c; + const char *name; + if (strlen(n->instance_name)) { + name = n->instance_name; + + c.chunk = CHK_INSTANCE_NAME; + c.size = 6 + 1 + (uint32_t)strlen(name); + lib3ds_chunk_write(&c, io); + lib3ds_io_write_string(io, name); + } + } + { + int i; + for (i = 0; i < 3; ++i) { + if ((fabs(n->bbox_min[i]) > LIB3DS_EPSILON) || + (fabs(n->bbox_max[i]) > LIB3DS_EPSILON)) { + break; + } + } + + if (i < 3) { /*---- CHK_BOUNDBOX ----*/ + Lib3dsChunk c; + c.chunk = CHK_BOUNDBOX; + c.size = 30; + lib3ds_chunk_write(&c, io); + lib3ds_io_write_vector(io, n->bbox_min); + lib3ds_io_write_vector(io, n->bbox_max); + } + } + + if (n->pos_track.nkeys) { /*---- CHK_POS_TRACK_TAG ----*/ + Lib3dsChunk c; + c.chunk = CHK_POS_TRACK_TAG; + lib3ds_chunk_write_start(&c, io); + lib3ds_track_write(&n->pos_track, io); + lib3ds_chunk_write_end(&c, io); + } + if (n->rot_track.nkeys) { /*---- CHK_ROT_TRACK_TAG ----*/ + Lib3dsChunk c; + c.chunk = CHK_ROT_TRACK_TAG; + lib3ds_chunk_write_start(&c, io); + lib3ds_track_write(&n->rot_track, io); + lib3ds_chunk_write_end(&c, io); + } + if (n->scl_track.nkeys) { /*---- LIB3DS_SCL_TRACK_TAG ----*/ + Lib3dsChunk c; + c.chunk = CHK_SCL_TRACK_TAG; + lib3ds_chunk_write_start(&c, io); + lib3ds_track_write(&n->scl_track, io); + lib3ds_chunk_write_end(&c, io); + } + if (n->hide_track.nkeys) { /*---- CHK_HIDE_TRACK_TAG ----*/ + Lib3dsChunk c; + c.chunk = CHK_HIDE_TRACK_TAG; + lib3ds_chunk_write_start(&c, io); + lib3ds_track_write(&n->hide_track, io); + lib3ds_chunk_write_end(&c, io); + } + if (fabs(n->morph_smooth) > LIB3DS_EPSILON) { /*---- CHK_MORPH_SMOOTH ----*/ + Lib3dsChunk c; + c.chunk = CHK_MORPH_SMOOTH; + c.size = 10; + lib3ds_chunk_write(&c, io); + lib3ds_io_write_float(io, n->morph_smooth); + } + break; + } + + case CHK_CAMERA_NODE_TAG: { + Lib3dsCameraNode *n = (Lib3dsCameraNode*)node; + if (n->pos_track.nkeys) { /*---- CHK_POS_TRACK_TAG ----*/ + Lib3dsChunk c; + c.chunk = CHK_POS_TRACK_TAG; + lib3ds_chunk_write_start(&c, io); + lib3ds_track_write(&n->pos_track, io); + lib3ds_chunk_write_end(&c, io); + } + if (n->fov_track.nkeys) { /*---- CHK_FOV_TRACK_TAG ----*/ + Lib3dsChunk c; + c.chunk = CHK_FOV_TRACK_TAG; + lib3ds_chunk_write_start(&c, io); + lib3ds_track_write(&n->fov_track, io); + lib3ds_chunk_write_end(&c, io); + } + if (n->roll_track.nkeys) { /*---- CHK_ROLL_TRACK_TAG ----*/ + Lib3dsChunk c; + c.chunk = CHK_ROLL_TRACK_TAG; + lib3ds_chunk_write_start(&c, io); + lib3ds_track_write(&n->roll_track, io); + lib3ds_chunk_write_end(&c, io); + } + break; + } + + case CHK_TARGET_NODE_TAG: { + Lib3dsTargetNode *n = (Lib3dsTargetNode*)node; + if (n->pos_track.nkeys) { /*---- CHK_POS_TRACK_TAG ----*/ + Lib3dsChunk c; + c.chunk = CHK_POS_TRACK_TAG; + lib3ds_chunk_write_start(&c, io); + lib3ds_track_write(&n->pos_track, io); + lib3ds_chunk_write_end(&c, io); + } + break; + } + + case CHK_LIGHT_NODE_TAG: { + Lib3dsOmnilightNode *n = (Lib3dsOmnilightNode*)node; + if (n->pos_track.nkeys) { /*---- CHK_POS_TRACK_TAG ----*/ + Lib3dsChunk c; + c.chunk = CHK_POS_TRACK_TAG; + lib3ds_chunk_write_start(&c, io); + lib3ds_track_write(&n->pos_track, io); + lib3ds_chunk_write_end(&c, io); + } + if (n->color_track.nkeys) { /*---- CHK_COL_TRACK_TAG ----*/ + Lib3dsChunk c; + c.chunk = CHK_COL_TRACK_TAG; + lib3ds_chunk_write_start(&c, io); + lib3ds_track_write(&n->color_track, io); + lib3ds_chunk_write_end(&c, io); + } + break; + } + + case CHK_SPOTLIGHT_NODE_TAG: { + Lib3dsSpotlightNode *n = (Lib3dsSpotlightNode*)node; + if (n->pos_track.nkeys) { /*---- CHK_POS_TRACK_TAG ----*/ + Lib3dsChunk c; + c.chunk = CHK_POS_TRACK_TAG; + lib3ds_chunk_write_start(&c, io); + lib3ds_track_write(&n->pos_track, io); + lib3ds_chunk_write_end(&c, io); + } + if (n->color_track.nkeys) { /*---- CHK_COL_TRACK_TAG ----*/ + Lib3dsChunk c; + c.chunk = CHK_COL_TRACK_TAG; + lib3ds_chunk_write_start(&c, io); + lib3ds_track_write(&n->color_track, io); + lib3ds_chunk_write_end(&c, io); + } + if (n->hotspot_track.nkeys) { /*---- CHK_HOT_TRACK_TAG ----*/ + Lib3dsChunk c; + c.chunk = CHK_HOT_TRACK_TAG; + lib3ds_chunk_write_start(&c, io); + lib3ds_track_write(&n->hotspot_track, io); + lib3ds_chunk_write_end(&c, io); + } + if (n->falloff_track.nkeys) { /*---- CHK_FALL_TRACK_TAG ----*/ + Lib3dsChunk c; + c.chunk = CHK_FALL_TRACK_TAG; + lib3ds_chunk_write_start(&c, io); + lib3ds_track_write(&n->falloff_track, io); + lib3ds_chunk_write_end(&c, io); + } + if (n->roll_track.nkeys) { /*---- CHK_ROLL_TRACK_TAG ----*/ + Lib3dsChunk c; + c.chunk = CHK_ROLL_TRACK_TAG; + lib3ds_chunk_write_start(&c, io); + lib3ds_track_write(&n->roll_track, io); + lib3ds_chunk_write_end(&c, io); + } + break; + } + + case CHK_L_TARGET_NODE_TAG: { + Lib3dsTargetNode *n = (Lib3dsTargetNode*)node; + if (n->pos_track.nkeys) { /*---- CHK_POS_TRACK_TAG ----*/ + Lib3dsChunk c; + c.chunk = CHK_POS_TRACK_TAG; + lib3ds_chunk_write_start(&c, io); + lib3ds_track_write(&n->pos_track, io); + lib3ds_chunk_write_end(&c, io); + } + break; + } + + default: + break; + } + + lib3ds_chunk_write_end(&c, io); +} + diff --git a/src/osgPlugins/3ds/lib3ds/lib3ds_quat.c b/src/osgPlugins/3ds/lib3ds/lib3ds_quat.c index d07766f2b..dd4736672 100644 --- a/src/osgPlugins/3ds/lib3ds/lib3ds_quat.c +++ b/src/osgPlugins/3ds/lib3ds/lib3ds_quat.c @@ -1,294 +1,294 @@ -/* - Copyright (C) 1996-2008 by Jan Eric Kyprianidis - 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. - - Thisprogram 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, see . -*/ -#include "lib3ds_impl.h" - - -/*! - * Set a quaternion to Identity - */ -void -lib3ds_quat_identity(float c[4]) { - c[0] = c[1] = c[2] = 0.0f; - c[3] = 1.0f; -} - - -/*! - * Copy a quaternion. - */ -void -lib3ds_quat_copy(float dest[4], float src[4]) { - 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. - */ -void -lib3ds_quat_axis_angle(float c[4], float axis[3], float angle) { - double omega, s; - double 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] = (float)s * axis[0]; - c[1] = (float)s * axis[1]; - c[2] = (float)s * axis[2]; - c[3] = (float)cos(omega); - } -} - - -/*! - * Negate a quaternion - */ -void -lib3ds_quat_neg(float c[4]) { - int i; - for (i = 0; i < 4; ++i) { - c[i] = -c[i]; - } -} - - -/*! - * Compute the conjugate of a quaternion - */ -void -lib3ds_quat_cnj(float c[4]) { - int i; - for (i = 0; i < 3; ++i) { - c[i] = -c[i]; - } -} - - -/*! - * Multiply two quaternions. - * - * \param c Result - * \param a,b Inputs - */ -void -lib3ds_quat_mul(float c[4], float a[4], float b[4]) { - float qa[4], qb[4]; - lib3ds_quat_copy(qa, a); - lib3ds_quat_copy(qb, b); - c[0] = qa[3] * qb[0] + qa[0] * qb[3] + qa[1] * qb[2] - qa[2] * qb[1]; - c[1] = qa[3] * qb[1] + qa[1] * qb[3] + qa[2] * qb[0] - qa[0] * qb[2]; - c[2] = qa[3] * qb[2] + qa[2] * qb[3] + qa[0] * qb[1] - qa[1] * qb[0]; - c[3] = qa[3] * qb[3] - qa[0] * qb[0] - qa[1] * qb[1] - qa[2] * qb[2]; -} - - -/*! - * Multiply a quaternion by a scalar. - */ -void -lib3ds_quat_scalar(float c[4], float k) { - int i; - for (i = 0; i < 4; ++i) { - c[i] *= k; - } -} - - -/*! - * Normalize a quaternion. - */ -void -lib3ds_quat_normalize(float c[4]) { - double 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] = (float)(c[i] * m); - } - } -} - - -/*! - * Compute the inverse of a quaternion. - */ -void -lib3ds_quat_inv(float c[4]) { - double 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] = (float)(-c[0] * m); - c[1] = (float)(-c[1] * m); - c[2] = (float)(-c[2] * m); - c[3] = (float)(c[3] * m); - } -} - - -/*! - * Compute the dot-product of a quaternion. - */ -float -lib3ds_quat_dot(float a[4], float b[4]) { - return(a[0]*b[0] + a[1]*b[1] + a[2]*b[2] + a[3]*b[3]); -} - - -float -lib3ds_quat_norm(float c[4]) { - return(c[0]*c[0] + c[1]*c[1] + c[2]*c[2] + c[3]*c[3]); -} - - -void -lib3ds_quat_ln(float c[4]) { - double om, s, t; - - s = sqrt(c[0] * c[0] + c[1] * c[1] + c[2] * c[2]); - om = atan2(s, (double)c[3]); - if (fabs(s) < LIB3DS_EPSILON) { - t = 0.0f; - } else { - t = om / s; - } - { - int i; - for (i = 0; i < 3; ++i) { - c[i] = (float)(c[i] * t); - } - c[3] = 0.0f; - } -} - - -void -lib3ds_quat_ln_dif(float c[4], float a[4], float b[4]) { - float invp[4]; - - lib3ds_quat_copy(invp, a); - lib3ds_quat_inv(invp); - lib3ds_quat_mul(c, invp, b); - lib3ds_quat_ln(c); -} - - -void -lib3ds_quat_exp(float c[4]) { - double 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] = (float)(c[i] * sinom); - } - c[3] = (float)cos(om); - } -} - - -void -lib3ds_quat_slerp(float c[4], float a[4], float b[4], float t) { - double l; - double om, sinom; - double sp, sq; - float flip = 1.0f; - int i; - - l = a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3]; - if (l < 0) { - flip = -1.0f; - l = -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; - } - sq *= flip; - for (i = 0; i < 4; ++i) { - c[i] = (float)(sp * a[i] + sq * b[i]); - } -} - - -void -lib3ds_quat_squad(float c[4], float a[4], float p[4], float q[4], float b[4], float t) { - float ab[4]; - float pq[4]; - - lib3ds_quat_slerp(ab, a, b, t); - lib3ds_quat_slerp(pq, p, q, t); - lib3ds_quat_slerp(c, ab, pq, 2*t*(1 - t)); -} - - -void -lib3ds_quat_tangent(float c[4], float p[4], float q[4], float n[4]) { - float dn[4], dp[4], x[4]; - 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); -} - - -void -lib3ds_quat_dump(float q[4]) { - printf("%f %f %f %f\n", q[0], q[1], q[2], q[3]); -} - +/* + Copyright (C) 1996-2008 by Jan Eric Kyprianidis + 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. + + Thisprogram 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, see . +*/ +#include "lib3ds_impl.h" + + +/*! + * Set a quaternion to Identity + */ +void +lib3ds_quat_identity(float c[4]) { + c[0] = c[1] = c[2] = 0.0f; + c[3] = 1.0f; +} + + +/*! + * Copy a quaternion. + */ +void +lib3ds_quat_copy(float dest[4], float src[4]) { + 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. + */ +void +lib3ds_quat_axis_angle(float c[4], float axis[3], float angle) { + double omega, s; + double 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] = (float)s * axis[0]; + c[1] = (float)s * axis[1]; + c[2] = (float)s * axis[2]; + c[3] = (float)cos(omega); + } +} + + +/*! + * Negate a quaternion + */ +void +lib3ds_quat_neg(float c[4]) { + int i; + for (i = 0; i < 4; ++i) { + c[i] = -c[i]; + } +} + + +/*! + * Compute the conjugate of a quaternion + */ +void +lib3ds_quat_cnj(float c[4]) { + int i; + for (i = 0; i < 3; ++i) { + c[i] = -c[i]; + } +} + + +/*! + * Multiply two quaternions. + * + * \param c Result + * \param a,b Inputs + */ +void +lib3ds_quat_mul(float c[4], float a[4], float b[4]) { + float qa[4], qb[4]; + lib3ds_quat_copy(qa, a); + lib3ds_quat_copy(qb, b); + c[0] = qa[3] * qb[0] + qa[0] * qb[3] + qa[1] * qb[2] - qa[2] * qb[1]; + c[1] = qa[3] * qb[1] + qa[1] * qb[3] + qa[2] * qb[0] - qa[0] * qb[2]; + c[2] = qa[3] * qb[2] + qa[2] * qb[3] + qa[0] * qb[1] - qa[1] * qb[0]; + c[3] = qa[3] * qb[3] - qa[0] * qb[0] - qa[1] * qb[1] - qa[2] * qb[2]; +} + + +/*! + * Multiply a quaternion by a scalar. + */ +void +lib3ds_quat_scalar(float c[4], float k) { + int i; + for (i = 0; i < 4; ++i) { + c[i] *= k; + } +} + + +/*! + * Normalize a quaternion. + */ +void +lib3ds_quat_normalize(float c[4]) { + double 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] = (float)(c[i] * m); + } + } +} + + +/*! + * Compute the inverse of a quaternion. + */ +void +lib3ds_quat_inv(float c[4]) { + double 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] = (float)(-c[0] * m); + c[1] = (float)(-c[1] * m); + c[2] = (float)(-c[2] * m); + c[3] = (float)(c[3] * m); + } +} + + +/*! + * Compute the dot-product of a quaternion. + */ +float +lib3ds_quat_dot(float a[4], float b[4]) { + return(a[0]*b[0] + a[1]*b[1] + a[2]*b[2] + a[3]*b[3]); +} + + +float +lib3ds_quat_norm(float c[4]) { + return(c[0]*c[0] + c[1]*c[1] + c[2]*c[2] + c[3]*c[3]); +} + + +void +lib3ds_quat_ln(float c[4]) { + double om, s, t; + + s = sqrt(c[0] * c[0] + c[1] * c[1] + c[2] * c[2]); + om = atan2(s, (double)c[3]); + if (fabs(s) < LIB3DS_EPSILON) { + t = 0.0f; + } else { + t = om / s; + } + { + int i; + for (i = 0; i < 3; ++i) { + c[i] = (float)(c[i] * t); + } + c[3] = 0.0f; + } +} + + +void +lib3ds_quat_ln_dif(float c[4], float a[4], float b[4]) { + float invp[4]; + + lib3ds_quat_copy(invp, a); + lib3ds_quat_inv(invp); + lib3ds_quat_mul(c, invp, b); + lib3ds_quat_ln(c); +} + + +void +lib3ds_quat_exp(float c[4]) { + double 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] = (float)(c[i] * sinom); + } + c[3] = (float)cos(om); + } +} + + +void +lib3ds_quat_slerp(float c[4], float a[4], float b[4], float t) { + double l; + double om, sinom; + double sp, sq; + float flip = 1.0f; + int i; + + l = a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3]; + if (l < 0) { + flip = -1.0f; + l = -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; + } + sq *= flip; + for (i = 0; i < 4; ++i) { + c[i] = (float)(sp * a[i] + sq * b[i]); + } +} + + +void +lib3ds_quat_squad(float c[4], float a[4], float p[4], float q[4], float b[4], float t) { + float ab[4]; + float pq[4]; + + lib3ds_quat_slerp(ab, a, b, t); + lib3ds_quat_slerp(pq, p, q, t); + lib3ds_quat_slerp(c, ab, pq, 2*t*(1 - t)); +} + + +void +lib3ds_quat_tangent(float c[4], float p[4], float q[4], float n[4]) { + float dn[4], dp[4], x[4]; + 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); +} + + +void +lib3ds_quat_dump(float q[4]) { + printf("%f %f %f %f\n", q[0], q[1], q[2], q[3]); +} + diff --git a/src/osgPlugins/3ds/lib3ds/lib3ds_shadow.c b/src/osgPlugins/3ds/lib3ds/lib3ds_shadow.c index 1380f939e..a00d22e70 100644 --- a/src/osgPlugins/3ds/lib3ds/lib3ds_shadow.c +++ b/src/osgPlugins/3ds/lib3ds/lib3ds_shadow.c @@ -1,96 +1,96 @@ -/* - Copyright (C) 1996-2008 by Jan Eric Kyprianidis - 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. - - Thisprogram 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, see . -*/ -#include "lib3ds_impl.h" - - -void -lib3ds_shadow_read(Lib3dsShadow *shadow, Lib3dsIo *io) { - Lib3dsChunk c; - - lib3ds_chunk_read(&c, io); - switch (c.chunk) { - case CHK_SHADOW_MAP_SIZE: { - shadow->map_size = lib3ds_io_read_intw(io); - break; - } - - case CHK_LO_SHADOW_BIAS: { - shadow->low_bias = lib3ds_io_read_float(io); - break; - } - - case CHK_HI_SHADOW_BIAS: { - shadow->hi_bias = lib3ds_io_read_float(io); - break; - } - - case CHK_SHADOW_FILTER: { - shadow->filter = lib3ds_io_read_float(io); - break; - } - - case CHK_RAY_BIAS: { - shadow->ray_bias = lib3ds_io_read_float(io); - break; - } - } -} - - -void -lib3ds_shadow_write(Lib3dsShadow *shadow, Lib3dsIo *io) { - if (fabs(shadow->low_bias) > LIB3DS_EPSILON) { /*---- CHK_LO_SHADOW_BIAS ----*/ - Lib3dsChunk c; - c.chunk = CHK_LO_SHADOW_BIAS; - c.size = 10; - lib3ds_chunk_write(&c, io); - lib3ds_io_write_float(io, shadow->low_bias); - } - - if (fabs(shadow->hi_bias) > LIB3DS_EPSILON) { /*---- CHK_HI_SHADOW_BIAS ----*/ - Lib3dsChunk c; - c.chunk = CHK_HI_SHADOW_BIAS; - c.size = 10; - lib3ds_chunk_write(&c, io); - lib3ds_io_write_float(io, shadow->hi_bias); - } - - if (shadow->map_size) { /*---- CHK_SHADOW_MAP_SIZE ----*/ - Lib3dsChunk c; - c.chunk = CHK_SHADOW_MAP_SIZE; - c.size = 8; - lib3ds_chunk_write(&c, io); - lib3ds_io_write_intw(io, shadow->map_size); - } - - if (fabs(shadow->filter) > LIB3DS_EPSILON) { /*---- CHK_SHADOW_FILTER ----*/ - Lib3dsChunk c; - c.chunk = CHK_SHADOW_FILTER; - c.size = 10; - lib3ds_chunk_write(&c, io); - lib3ds_io_write_float(io, shadow->filter); - } - if (fabs(shadow->ray_bias) > LIB3DS_EPSILON) { /*---- CHK_RAY_BIAS ----*/ - Lib3dsChunk c; - c.chunk = CHK_RAY_BIAS; - c.size = 10; - lib3ds_chunk_write(&c, io); - lib3ds_io_write_float(io, shadow->ray_bias); - } -} - +/* + Copyright (C) 1996-2008 by Jan Eric Kyprianidis + 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. + + Thisprogram 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, see . +*/ +#include "lib3ds_impl.h" + + +void +lib3ds_shadow_read(Lib3dsShadow *shadow, Lib3dsIo *io) { + Lib3dsChunk c; + + lib3ds_chunk_read(&c, io); + switch (c.chunk) { + case CHK_SHADOW_MAP_SIZE: { + shadow->map_size = lib3ds_io_read_intw(io); + break; + } + + case CHK_LO_SHADOW_BIAS: { + shadow->low_bias = lib3ds_io_read_float(io); + break; + } + + case CHK_HI_SHADOW_BIAS: { + shadow->hi_bias = lib3ds_io_read_float(io); + break; + } + + case CHK_SHADOW_FILTER: { + shadow->filter = lib3ds_io_read_float(io); + break; + } + + case CHK_RAY_BIAS: { + shadow->ray_bias = lib3ds_io_read_float(io); + break; + } + } +} + + +void +lib3ds_shadow_write(Lib3dsShadow *shadow, Lib3dsIo *io) { + if (fabs(shadow->low_bias) > LIB3DS_EPSILON) { /*---- CHK_LO_SHADOW_BIAS ----*/ + Lib3dsChunk c; + c.chunk = CHK_LO_SHADOW_BIAS; + c.size = 10; + lib3ds_chunk_write(&c, io); + lib3ds_io_write_float(io, shadow->low_bias); + } + + if (fabs(shadow->hi_bias) > LIB3DS_EPSILON) { /*---- CHK_HI_SHADOW_BIAS ----*/ + Lib3dsChunk c; + c.chunk = CHK_HI_SHADOW_BIAS; + c.size = 10; + lib3ds_chunk_write(&c, io); + lib3ds_io_write_float(io, shadow->hi_bias); + } + + if (shadow->map_size) { /*---- CHK_SHADOW_MAP_SIZE ----*/ + Lib3dsChunk c; + c.chunk = CHK_SHADOW_MAP_SIZE; + c.size = 8; + lib3ds_chunk_write(&c, io); + lib3ds_io_write_intw(io, shadow->map_size); + } + + if (fabs(shadow->filter) > LIB3DS_EPSILON) { /*---- CHK_SHADOW_FILTER ----*/ + Lib3dsChunk c; + c.chunk = CHK_SHADOW_FILTER; + c.size = 10; + lib3ds_chunk_write(&c, io); + lib3ds_io_write_float(io, shadow->filter); + } + if (fabs(shadow->ray_bias) > LIB3DS_EPSILON) { /*---- CHK_RAY_BIAS ----*/ + Lib3dsChunk c; + c.chunk = CHK_RAY_BIAS; + c.size = 10; + lib3ds_chunk_write(&c, io); + lib3ds_io_write_float(io, shadow->ray_bias); + } +} + diff --git a/src/osgPlugins/3ds/lib3ds/lib3ds_track.c b/src/osgPlugins/3ds/lib3ds/lib3ds_track.c index 83bfc71bd..467a0444d 100644 --- a/src/osgPlugins/3ds/lib3ds/lib3ds_track.c +++ b/src/osgPlugins/3ds/lib3ds/lib3ds_track.c @@ -1,551 +1,551 @@ -/* - Copyright (C) 1996-2008 by Jan Eric Kyprianidis - 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. - - Thisprogram 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, see . -*/ -#include "lib3ds_impl.h" - - -Lib3dsTrack* -lib3ds_track_new(Lib3dsTrackType type, int nkeys) { - Lib3dsTrack *track = (Lib3dsTrack*)calloc(sizeof(Lib3dsTrack), 1); - track->type = type; - lib3ds_track_resize(track, nkeys); - return track; -} - - -void -lib3ds_track_free(Lib3dsTrack *track) { - assert(track); - lib3ds_track_resize(track, 0); - memset(track, 0, sizeof(Lib3dsTrack)); - free(track); -} - - -void -lib3ds_track_resize(Lib3dsTrack *track, int nkeys) { - char *p; - - assert(track); - if (track->nkeys == nkeys) - return; - - p = (char*)realloc(track->keys, sizeof(Lib3dsKey) * nkeys); - if (nkeys > track->nkeys) { - memset(p + (sizeof(Lib3dsKey)*track->nkeys), 0, sizeof(Lib3dsKey)*(nkeys - track->nkeys)); - } - track->keys = (Lib3dsKey*)p; - track->nkeys = nkeys; -} - - -static void -pos_key_setup(int n, Lib3dsKey *pp, Lib3dsKey *pc, Lib3dsKey *pn, float *dd, float *ds) { - float tm, cm, cp, bm, bp, tmcm, tmcp, ksm, ksp, kdm, kdp, c; - float dt, fp, fn; - float delm[3], delp[3]; - int i; - - assert(pc); - fp = fn = 1.0f; - if (pp && pn) { - dt = 0.5f * (pn->frame - pp->frame); - fp = (float)(pc->frame - pp->frame) / dt; - fn = (float)(pn->frame - pc->frame) / dt; - c = (float)fabs(pc->cont); - fp = fp + c - c * fp; - fn = fn + c - c * fn; - } - - cm = 1.0f - pc->cont; - tm = 0.5f * (1.0f - pc->tens); - cp = 2.0f - cm; - bm = 1.0f - pc->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; - - for (i = 0; i < n; ++i) delm[i] = delp[i] = 0; - if (pp) { - for (i = 0; i < n; ++i) delm[i] = pc->value[i] - pp->value[i]; - } - if (pn) { - for (i = 0; i < n; ++i) delp[i] = pn->value[i] - pc->value[i]; - } - if (!pp) { - for (i = 0; i < n; ++i) delm[i] = delp[i]; - } - if (!pn) { - for (i = 0; i < n; ++i) delp[i] = delm[i]; - } - - for (i = 0; i < n; ++i) { - ds[i] = ksm * delm[i] + ksp * delp[i]; - dd[i] = kdm * delm[i] + kdp * delp[i]; - } -} - - -static void -rot_key_setup(Lib3dsKey *prev, Lib3dsKey *cur, Lib3dsKey *next, float a[4], float b[4]) { - float tm, cm, cp, bm, bp, tmcm, tmcp, ksm, ksp, kdm, kdp, c; - float dt, fp, fn; - float q[4], qm[4], qp[4], qa[4], qb[4]; - int i; - - assert(cur); - if (prev) { - if (cur->value[3] > LIB3DS_TWOPI - LIB3DS_EPSILON) { - lib3ds_quat_axis_angle(qm, cur->value, 0.0f); - lib3ds_quat_ln(qm); - } else { - lib3ds_quat_copy(q, prev->value); - if (lib3ds_quat_dot(q, cur->value) < 0) lib3ds_quat_neg(q); - lib3ds_quat_ln_dif(qm, q, cur->value); - } - } - if (next) { - if (next->value[3] > LIB3DS_TWOPI - LIB3DS_EPSILON) { - lib3ds_quat_axis_angle(qp, next->value, 0.0f); - lib3ds_quat_ln(qp); - } else { - lib3ds_quat_copy(q, next->value); - if (lib3ds_quat_dot(q, cur->value) < 0) lib3ds_quat_neg(q); - lib3ds_quat_ln_dif(qp, cur->value, q); - } - } - if (!prev) lib3ds_quat_copy(qm, qp); - if (!next) lib3ds_quat_copy(qp, qm); - - fp = fn = 1.0f; - cm = 1.0f - cur->cont; - if (prev && next) { - dt = 0.5f * (next->frame - prev->frame); - fp = (float)(cur->frame - prev->frame) / dt; - fn = (float)(next->frame - cur->frame) / dt; - c = (float)fabs(cur->cont); - fp = fp + c - c * fp; - fn = fn + c - c * fn; - } - - tm = 0.5f * (1.0f - cur->tens); - cp = 2.0f - cm; - bm = 1.0f - cur->bias; - bp = 2.0f - bm; - tmcm = tm * cm; - tmcp = tm * cp; - ksm = 1.0f - tmcm * bp * fp; - ksp = -tmcp * bm * fp; - kdm = tmcp * bp * fn; - kdp = tmcm * bm * fn - 1.0f; - - for (i = 0; i < 4; i++) { - qa[i] = 0.5f * (kdm * qm[i] + kdp * qp[i]); - qb[i] = 0.5f * (ksm * qm[i] + ksp * qp[i]); - } - lib3ds_quat_exp(qa); - lib3ds_quat_exp(qb); - - lib3ds_quat_mul(a, cur->value, qa); - lib3ds_quat_mul(b, cur->value, qb); -} - - -static void -quat_for_index(Lib3dsTrack *track, int index, float q[4]) { - float p[4]; - int i; - lib3ds_quat_identity(q); - for (i = 0; i <= index; ++i) { - lib3ds_quat_axis_angle(p, track->keys[i].value, track->keys[i].value[3]); - lib3ds_quat_mul(q, p, q); - } -} - - -static int -find_index(Lib3dsTrack *track, float t, float *u) { - int i; - float nt; - int t0, t1; - - assert(track); - assert(track->nkeys > 0); - - if (track->nkeys <= 1) - return -1; - - t0 = track->keys[0].frame; - t1 = track->keys[track->nkeys-1].frame; - if (track->flags & LIB3DS_TRACK_REPEAT) { - nt = (float)fmod(t - t0, t1 - t0) + t0; - } else { - nt = t; - } - - if (nt <= t0) { - return -1; - } - if (nt >= t1) { - return track->nkeys; - } - - for (i = 1; i < track->nkeys; ++i) { - if (nt < track->keys[i].frame) - break; - } - - *u = nt - (float)track->keys[i-1].frame; - *u /= (float)(track->keys[i].frame - track->keys[i-1].frame); - - assert((*u >= 0.0f) && (*u <= 1.0f)); - return i; -} - - -static void -setup_segment(Lib3dsTrack *track, int index, Lib3dsKey *pp, Lib3dsKey *p0, Lib3dsKey *p1, Lib3dsKey *pn) { - int ip, in; - - pp->frame = pn->frame = -1; - if (index >= 2) { - ip = index - 2; - *pp = track->keys[index - 2]; - } else { - if (track->flags & LIB3DS_TRACK_SMOOTH) { - ip = track->nkeys - 2; - *pp = track->keys[track->nkeys - 2]; - pp->frame = track->keys[track->nkeys - 2].frame - (track->keys[track->nkeys - 1].frame - track->keys[0].frame); - } - else ip = -1; // Avoids a compiler warning - } - - *p0 = track->keys[index - 1]; - *p1 = track->keys[index]; - - if (index < (int)track->nkeys - 1) { - in = index + 1; - *pn = track->keys[index + 1]; - } else { - if (track->flags & LIB3DS_TRACK_SMOOTH) { - in = 1; - *pn = track->keys[1]; - pn->frame = track->keys[1].frame + (track->keys[track->nkeys-1].frame - track->keys[0].frame); - } - } - - if (track->type == LIB3DS_TRACK_QUAT) { - float q[4]; - if (pp->frame >= 0) { - quat_for_index(track, ip, pp->value); - } else { - lib3ds_quat_identity(pp->value); - } - - quat_for_index(track, index - 1, p0->value); - lib3ds_quat_axis_angle(q, track->keys[index].value, track->keys[index].value[3]); - lib3ds_quat_mul(p1->value, q, p0->value); - - if (pn->frame >= 0) { - lib3ds_quat_axis_angle(q, track->keys[in].value, track->keys[in].value[3]); - lib3ds_quat_mul(pn->value, q, p1->value); - } else { - lib3ds_quat_identity(pn->value); - } - } -} - - -void -lib3ds_track_eval_bool(Lib3dsTrack *track, int *b, float t) { - *b = FALSE; - if (track) { - int index; - float u; - - assert(track->type == LIB3DS_TRACK_BOOL); - if (!track->nkeys) { - return; - } - - index = find_index(track, t, &u); - if (index < 0) { - *b = FALSE; - return; - } - if (index >= track->nkeys) { - *b = !(track->nkeys & 1); - return; - } - *b = !(index & 1); - } -} - - -static void -track_eval_linear(Lib3dsTrack *track, float *value, float t) { - Lib3dsKey pp, p0, p1, pn; - float u; - int index; - float dsp[3], ddp[3], dsn[3], ddn[3]; - - assert(track); - if (!track->nkeys) { - int i; - for (i = 0; i < track->type; ++i) value[i] = 0.0f; - return; - } - - index = find_index(track, t, &u); - - if (index < 0) { - int i; - for (i = 0; i < track->type; ++i) value[i] = track->keys[0].value[i]; - return; - } - if (index >= track->nkeys) { - int i; - for (i = 0; i < track->type; ++i) value[i] = track->keys[track->nkeys-1].value[i]; - return; - } - - setup_segment(track, index, &pp, &p0, &p1, &pn); - - pos_key_setup(track->type, pp.frame>=0? &pp : NULL, &p0, &p1, ddp, dsp); - pos_key_setup(track->type, &p0, &p1, pn.frame>=0? &pn : NULL, ddn, dsn); - - lib3ds_math_cubic_interp( - value, - p0.value, - ddp, - dsn, - p1.value, - track->type, - u - ); -} - - -void -lib3ds_track_eval_float(Lib3dsTrack *track, float *f, float t) { - *f = 0; - if (track) { - assert(track->type == LIB3DS_TRACK_FLOAT); - track_eval_linear(track, f, t); - } -} - - -void -lib3ds_track_eval_vector(Lib3dsTrack *track, float v[3], float t) { - lib3ds_vector_zero(v); - if (track) { - assert(track->type == LIB3DS_TRACK_VECTOR); - track_eval_linear(track, v, t); - } -} - - -void -lib3ds_track_eval_quat(Lib3dsTrack *track, float q[4], float t) { - lib3ds_quat_identity(q); - if (track) { - Lib3dsKey pp, p0, p1, pn; - float u; - int index; - float ap[4], bp[4], an[4], bn[4]; - - assert(track->type == LIB3DS_TRACK_QUAT); - if (!track->nkeys) { - return; - } - - index = find_index(track, t, &u); - if (index < 0) { - lib3ds_quat_axis_angle(q, track->keys[0].value, track->keys[0].value[3]); - return; - } - if (index >= track->nkeys) { - quat_for_index(track, track->nkeys - 1, q); - return; - } - - setup_segment(track, index, &pp, &p0, &p1, &pn); - - rot_key_setup(pp.frame>=0? &pp : NULL, &p0, &p1, ap, bp); - rot_key_setup(&p0, &p1, pn.frame>=0? &pn : NULL, an, bn); - - lib3ds_quat_squad(q, p0.value, ap, bn, p1.value, u); - } -} - - -static void -tcb_read(Lib3dsKey *key, Lib3dsIo *io) { - key->flags = lib3ds_io_read_word(io); - if (key->flags & LIB3DS_KEY_USE_TENS) { - key->tens = lib3ds_io_read_float(io); - } - if (key->flags & LIB3DS_KEY_USE_CONT) { - key->cont = lib3ds_io_read_float(io); - } - if (key->flags & LIB3DS_KEY_USE_BIAS) { - key->bias = lib3ds_io_read_float(io); - } - if (key->flags & LIB3DS_KEY_USE_EASE_TO) { - key->ease_to = lib3ds_io_read_float(io); - } - if (key->flags & LIB3DS_KEY_USE_EASE_FROM) { - key->ease_from = lib3ds_io_read_float(io); - } -} - - -void -lib3ds_track_read(Lib3dsTrack *track, Lib3dsIo *io) { - unsigned nkeys; - unsigned i; - - track->flags = lib3ds_io_read_word(io); - lib3ds_io_read_dword(io); - lib3ds_io_read_dword(io); - nkeys = lib3ds_io_read_intd(io); - lib3ds_track_resize(track, nkeys); - - switch (track->type) { - case LIB3DS_TRACK_BOOL: - for (i = 0; i < nkeys; ++i) { - track->keys[i].frame = lib3ds_io_read_intd(io); - tcb_read(&track->keys[i], io); - } - break; - - case LIB3DS_TRACK_FLOAT: - for (i = 0; i < nkeys; ++i) { - track->keys[i].frame = lib3ds_io_read_intd(io); - tcb_read(&track->keys[i], io); - track->keys[i].value[0] = lib3ds_io_read_float(io); - } - break; - - case LIB3DS_TRACK_VECTOR: - for (i = 0; i < nkeys; ++i) { - track->keys[i].frame = lib3ds_io_read_intd(io); - tcb_read(&track->keys[i], io); - lib3ds_io_read_vector(io, track->keys[i].value); - } - break; - - case LIB3DS_TRACK_QUAT: - for (i = 0; i < nkeys; ++i) { - track->keys[i].frame = lib3ds_io_read_intd(io); - tcb_read(&track->keys[i], io); - track->keys[i].value[3] = lib3ds_io_read_float(io); - lib3ds_io_read_vector(io, track->keys[i].value); - } - break; - - /*case LIB3DS_TRACK_MORPH: - for (i = 0; i < nkeys; ++i) { - track->keys[i].frame = lib3ds_io_read_intd(io); - tcb_read(&track->keys[i].tcb, io); - lib3ds_io_read_string(io, track->keys[i].data.m.name, 64); - } - break;*/ - - default: - break; - } -} - - -void -tcb_write(Lib3dsKey *key, Lib3dsIo *io) { - lib3ds_io_write_word(io, (uint16_t)key->flags); - if (key->flags & LIB3DS_KEY_USE_TENS) { - lib3ds_io_write_float(io, key->tens); - } - if (key->flags & LIB3DS_KEY_USE_CONT) { - lib3ds_io_write_float(io, key->cont); - } - if (key->flags & LIB3DS_KEY_USE_BIAS) { - lib3ds_io_write_float(io, key->bias); - } - if (key->flags & LIB3DS_KEY_USE_EASE_TO) { - lib3ds_io_write_float(io, key->ease_to); - } - if (key->flags & LIB3DS_KEY_USE_EASE_FROM) { - lib3ds_io_write_float(io, key->ease_from); - } -} - - -void -lib3ds_track_write(Lib3dsTrack *track, Lib3dsIo *io) { - int i; - - lib3ds_io_write_word(io, (uint16_t)track->flags); - lib3ds_io_write_dword(io, 0); - lib3ds_io_write_dword(io, 0); - lib3ds_io_write_dword(io, track->nkeys); - - switch (track->type) { - case LIB3DS_TRACK_BOOL: - for (i = 0; i < track->nkeys; ++i) { - lib3ds_io_write_intd(io, track->keys[i].frame); - tcb_write(&track->keys[i], io); - } - break; - - case LIB3DS_TRACK_FLOAT: - for (i = 0; i < track->nkeys; ++i) { - lib3ds_io_write_intd(io, track->keys[i].frame); - tcb_write(&track->keys[i], io); - lib3ds_io_write_float(io, track->keys[i].value[0]); - } - break; - - case LIB3DS_TRACK_VECTOR: - for (i = 0; i < track->nkeys; ++i) { - lib3ds_io_write_intd(io, track->keys[i].frame); - tcb_write(&track->keys[i], io); - lib3ds_io_write_vector(io, track->keys[i].value); - } - break; - - case LIB3DS_TRACK_QUAT: - for (i = 0; i < track->nkeys; ++i) { - lib3ds_io_write_intd(io, track->keys[i].frame); - tcb_write(&track->keys[i], io); - lib3ds_io_write_float(io, track->keys[i].value[3]); - lib3ds_io_write_vector(io, track->keys[i].value); - } - break; - - /*case LIB3DS_TRACK_MORPH: - for (i = 0; i < track->nkeys; ++i) { - lib3ds_io_write_intd(io, track->keys[i].frame); - tcb_write(&track->keys[i].tcb, io); - lib3ds_io_write_string(io, track->keys[i].data.m.name); - } - break;*/ - } -} +/* + Copyright (C) 1996-2008 by Jan Eric Kyprianidis + 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. + + Thisprogram 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, see . +*/ +#include "lib3ds_impl.h" + + +Lib3dsTrack* +lib3ds_track_new(Lib3dsTrackType type, int nkeys) { + Lib3dsTrack *track = (Lib3dsTrack*)calloc(sizeof(Lib3dsTrack), 1); + track->type = type; + lib3ds_track_resize(track, nkeys); + return track; +} + + +void +lib3ds_track_free(Lib3dsTrack *track) { + assert(track); + lib3ds_track_resize(track, 0); + memset(track, 0, sizeof(Lib3dsTrack)); + free(track); +} + + +void +lib3ds_track_resize(Lib3dsTrack *track, int nkeys) { + char *p; + + assert(track); + if (track->nkeys == nkeys) + return; + + p = (char*)realloc(track->keys, sizeof(Lib3dsKey) * nkeys); + if (nkeys > track->nkeys) { + memset(p + (sizeof(Lib3dsKey)*track->nkeys), 0, sizeof(Lib3dsKey)*(nkeys - track->nkeys)); + } + track->keys = (Lib3dsKey*)p; + track->nkeys = nkeys; +} + + +static void +pos_key_setup(int n, Lib3dsKey *pp, Lib3dsKey *pc, Lib3dsKey *pn, float *dd, float *ds) { + float tm, cm, cp, bm, bp, tmcm, tmcp, ksm, ksp, kdm, kdp, c; + float dt, fp, fn; + float delm[3], delp[3]; + int i; + + assert(pc); + fp = fn = 1.0f; + if (pp && pn) { + dt = 0.5f * (pn->frame - pp->frame); + fp = (float)(pc->frame - pp->frame) / dt; + fn = (float)(pn->frame - pc->frame) / dt; + c = (float)fabs(pc->cont); + fp = fp + c - c * fp; + fn = fn + c - c * fn; + } + + cm = 1.0f - pc->cont; + tm = 0.5f * (1.0f - pc->tens); + cp = 2.0f - cm; + bm = 1.0f - pc->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; + + for (i = 0; i < n; ++i) delm[i] = delp[i] = 0; + if (pp) { + for (i = 0; i < n; ++i) delm[i] = pc->value[i] - pp->value[i]; + } + if (pn) { + for (i = 0; i < n; ++i) delp[i] = pn->value[i] - pc->value[i]; + } + if (!pp) { + for (i = 0; i < n; ++i) delm[i] = delp[i]; + } + if (!pn) { + for (i = 0; i < n; ++i) delp[i] = delm[i]; + } + + for (i = 0; i < n; ++i) { + ds[i] = ksm * delm[i] + ksp * delp[i]; + dd[i] = kdm * delm[i] + kdp * delp[i]; + } +} + + +static void +rot_key_setup(Lib3dsKey *prev, Lib3dsKey *cur, Lib3dsKey *next, float a[4], float b[4]) { + float tm, cm, cp, bm, bp, tmcm, tmcp, ksm, ksp, kdm, kdp, c; + float dt, fp, fn; + float q[4], qm[4], qp[4], qa[4], qb[4]; + int i; + + assert(cur); + if (prev) { + if (cur->value[3] > LIB3DS_TWOPI - LIB3DS_EPSILON) { + lib3ds_quat_axis_angle(qm, cur->value, 0.0f); + lib3ds_quat_ln(qm); + } else { + lib3ds_quat_copy(q, prev->value); + if (lib3ds_quat_dot(q, cur->value) < 0) lib3ds_quat_neg(q); + lib3ds_quat_ln_dif(qm, q, cur->value); + } + } + if (next) { + if (next->value[3] > LIB3DS_TWOPI - LIB3DS_EPSILON) { + lib3ds_quat_axis_angle(qp, next->value, 0.0f); + lib3ds_quat_ln(qp); + } else { + lib3ds_quat_copy(q, next->value); + if (lib3ds_quat_dot(q, cur->value) < 0) lib3ds_quat_neg(q); + lib3ds_quat_ln_dif(qp, cur->value, q); + } + } + if (!prev) lib3ds_quat_copy(qm, qp); + if (!next) lib3ds_quat_copy(qp, qm); + + fp = fn = 1.0f; + cm = 1.0f - cur->cont; + if (prev && next) { + dt = 0.5f * (next->frame - prev->frame); + fp = (float)(cur->frame - prev->frame) / dt; + fn = (float)(next->frame - cur->frame) / dt; + c = (float)fabs(cur->cont); + fp = fp + c - c * fp; + fn = fn + c - c * fn; + } + + tm = 0.5f * (1.0f - cur->tens); + cp = 2.0f - cm; + bm = 1.0f - cur->bias; + bp = 2.0f - bm; + tmcm = tm * cm; + tmcp = tm * cp; + ksm = 1.0f - tmcm * bp * fp; + ksp = -tmcp * bm * fp; + kdm = tmcp * bp * fn; + kdp = tmcm * bm * fn - 1.0f; + + for (i = 0; i < 4; i++) { + qa[i] = 0.5f * (kdm * qm[i] + kdp * qp[i]); + qb[i] = 0.5f * (ksm * qm[i] + ksp * qp[i]); + } + lib3ds_quat_exp(qa); + lib3ds_quat_exp(qb); + + lib3ds_quat_mul(a, cur->value, qa); + lib3ds_quat_mul(b, cur->value, qb); +} + + +static void +quat_for_index(Lib3dsTrack *track, int index, float q[4]) { + float p[4]; + int i; + lib3ds_quat_identity(q); + for (i = 0; i <= index; ++i) { + lib3ds_quat_axis_angle(p, track->keys[i].value, track->keys[i].value[3]); + lib3ds_quat_mul(q, p, q); + } +} + + +static int +find_index(Lib3dsTrack *track, float t, float *u) { + int i; + float nt; + int t0, t1; + + assert(track); + assert(track->nkeys > 0); + + if (track->nkeys <= 1) + return -1; + + t0 = track->keys[0].frame; + t1 = track->keys[track->nkeys-1].frame; + if (track->flags & LIB3DS_TRACK_REPEAT) { + nt = (float)fmod(t - t0, t1 - t0) + t0; + } else { + nt = t; + } + + if (nt <= t0) { + return -1; + } + if (nt >= t1) { + return track->nkeys; + } + + for (i = 1; i < track->nkeys; ++i) { + if (nt < track->keys[i].frame) + break; + } + + *u = nt - (float)track->keys[i-1].frame; + *u /= (float)(track->keys[i].frame - track->keys[i-1].frame); + + assert((*u >= 0.0f) && (*u <= 1.0f)); + return i; +} + + +static void +setup_segment(Lib3dsTrack *track, int index, Lib3dsKey *pp, Lib3dsKey *p0, Lib3dsKey *p1, Lib3dsKey *pn) { + int ip, in; + + pp->frame = pn->frame = -1; + if (index >= 2) { + ip = index - 2; + *pp = track->keys[index - 2]; + } else { + if (track->flags & LIB3DS_TRACK_SMOOTH) { + ip = track->nkeys - 2; + *pp = track->keys[track->nkeys - 2]; + pp->frame = track->keys[track->nkeys - 2].frame - (track->keys[track->nkeys - 1].frame - track->keys[0].frame); + } + else ip = -1; // Avoids a compiler warning + } + + *p0 = track->keys[index - 1]; + *p1 = track->keys[index]; + + if (index < (int)track->nkeys - 1) { + in = index + 1; + *pn = track->keys[index + 1]; + } else { + if (track->flags & LIB3DS_TRACK_SMOOTH) { + in = 1; + *pn = track->keys[1]; + pn->frame = track->keys[1].frame + (track->keys[track->nkeys-1].frame - track->keys[0].frame); + } + } + + if (track->type == LIB3DS_TRACK_QUAT) { + float q[4]; + if (pp->frame >= 0) { + quat_for_index(track, ip, pp->value); + } else { + lib3ds_quat_identity(pp->value); + } + + quat_for_index(track, index - 1, p0->value); + lib3ds_quat_axis_angle(q, track->keys[index].value, track->keys[index].value[3]); + lib3ds_quat_mul(p1->value, q, p0->value); + + if (pn->frame >= 0) { + lib3ds_quat_axis_angle(q, track->keys[in].value, track->keys[in].value[3]); + lib3ds_quat_mul(pn->value, q, p1->value); + } else { + lib3ds_quat_identity(pn->value); + } + } +} + + +void +lib3ds_track_eval_bool(Lib3dsTrack *track, int *b, float t) { + *b = FALSE; + if (track) { + int index; + float u; + + assert(track->type == LIB3DS_TRACK_BOOL); + if (!track->nkeys) { + return; + } + + index = find_index(track, t, &u); + if (index < 0) { + *b = FALSE; + return; + } + if (index >= track->nkeys) { + *b = !(track->nkeys & 1); + return; + } + *b = !(index & 1); + } +} + + +static void +track_eval_linear(Lib3dsTrack *track, float *value, float t) { + Lib3dsKey pp, p0, p1, pn; + float u; + int index; + float dsp[3], ddp[3], dsn[3], ddn[3]; + + assert(track); + if (!track->nkeys) { + int i; + for (i = 0; i < track->type; ++i) value[i] = 0.0f; + return; + } + + index = find_index(track, t, &u); + + if (index < 0) { + int i; + for (i = 0; i < track->type; ++i) value[i] = track->keys[0].value[i]; + return; + } + if (index >= track->nkeys) { + int i; + for (i = 0; i < track->type; ++i) value[i] = track->keys[track->nkeys-1].value[i]; + return; + } + + setup_segment(track, index, &pp, &p0, &p1, &pn); + + pos_key_setup(track->type, pp.frame>=0? &pp : NULL, &p0, &p1, ddp, dsp); + pos_key_setup(track->type, &p0, &p1, pn.frame>=0? &pn : NULL, ddn, dsn); + + lib3ds_math_cubic_interp( + value, + p0.value, + ddp, + dsn, + p1.value, + track->type, + u + ); +} + + +void +lib3ds_track_eval_float(Lib3dsTrack *track, float *f, float t) { + *f = 0; + if (track) { + assert(track->type == LIB3DS_TRACK_FLOAT); + track_eval_linear(track, f, t); + } +} + + +void +lib3ds_track_eval_vector(Lib3dsTrack *track, float v[3], float t) { + lib3ds_vector_zero(v); + if (track) { + assert(track->type == LIB3DS_TRACK_VECTOR); + track_eval_linear(track, v, t); + } +} + + +void +lib3ds_track_eval_quat(Lib3dsTrack *track, float q[4], float t) { + lib3ds_quat_identity(q); + if (track) { + Lib3dsKey pp, p0, p1, pn; + float u; + int index; + float ap[4], bp[4], an[4], bn[4]; + + assert(track->type == LIB3DS_TRACK_QUAT); + if (!track->nkeys) { + return; + } + + index = find_index(track, t, &u); + if (index < 0) { + lib3ds_quat_axis_angle(q, track->keys[0].value, track->keys[0].value[3]); + return; + } + if (index >= track->nkeys) { + quat_for_index(track, track->nkeys - 1, q); + return; + } + + setup_segment(track, index, &pp, &p0, &p1, &pn); + + rot_key_setup(pp.frame>=0? &pp : NULL, &p0, &p1, ap, bp); + rot_key_setup(&p0, &p1, pn.frame>=0? &pn : NULL, an, bn); + + lib3ds_quat_squad(q, p0.value, ap, bn, p1.value, u); + } +} + + +static void +tcb_read(Lib3dsKey *key, Lib3dsIo *io) { + key->flags = lib3ds_io_read_word(io); + if (key->flags & LIB3DS_KEY_USE_TENS) { + key->tens = lib3ds_io_read_float(io); + } + if (key->flags & LIB3DS_KEY_USE_CONT) { + key->cont = lib3ds_io_read_float(io); + } + if (key->flags & LIB3DS_KEY_USE_BIAS) { + key->bias = lib3ds_io_read_float(io); + } + if (key->flags & LIB3DS_KEY_USE_EASE_TO) { + key->ease_to = lib3ds_io_read_float(io); + } + if (key->flags & LIB3DS_KEY_USE_EASE_FROM) { + key->ease_from = lib3ds_io_read_float(io); + } +} + + +void +lib3ds_track_read(Lib3dsTrack *track, Lib3dsIo *io) { + unsigned nkeys; + unsigned i; + + track->flags = lib3ds_io_read_word(io); + lib3ds_io_read_dword(io); + lib3ds_io_read_dword(io); + nkeys = lib3ds_io_read_intd(io); + lib3ds_track_resize(track, nkeys); + + switch (track->type) { + case LIB3DS_TRACK_BOOL: + for (i = 0; i < nkeys; ++i) { + track->keys[i].frame = lib3ds_io_read_intd(io); + tcb_read(&track->keys[i], io); + } + break; + + case LIB3DS_TRACK_FLOAT: + for (i = 0; i < nkeys; ++i) { + track->keys[i].frame = lib3ds_io_read_intd(io); + tcb_read(&track->keys[i], io); + track->keys[i].value[0] = lib3ds_io_read_float(io); + } + break; + + case LIB3DS_TRACK_VECTOR: + for (i = 0; i < nkeys; ++i) { + track->keys[i].frame = lib3ds_io_read_intd(io); + tcb_read(&track->keys[i], io); + lib3ds_io_read_vector(io, track->keys[i].value); + } + break; + + case LIB3DS_TRACK_QUAT: + for (i = 0; i < nkeys; ++i) { + track->keys[i].frame = lib3ds_io_read_intd(io); + tcb_read(&track->keys[i], io); + track->keys[i].value[3] = lib3ds_io_read_float(io); + lib3ds_io_read_vector(io, track->keys[i].value); + } + break; + + /*case LIB3DS_TRACK_MORPH: + for (i = 0; i < nkeys; ++i) { + track->keys[i].frame = lib3ds_io_read_intd(io); + tcb_read(&track->keys[i].tcb, io); + lib3ds_io_read_string(io, track->keys[i].data.m.name, 64); + } + break;*/ + + default: + break; + } +} + + +void +tcb_write(Lib3dsKey *key, Lib3dsIo *io) { + lib3ds_io_write_word(io, (uint16_t)key->flags); + if (key->flags & LIB3DS_KEY_USE_TENS) { + lib3ds_io_write_float(io, key->tens); + } + if (key->flags & LIB3DS_KEY_USE_CONT) { + lib3ds_io_write_float(io, key->cont); + } + if (key->flags & LIB3DS_KEY_USE_BIAS) { + lib3ds_io_write_float(io, key->bias); + } + if (key->flags & LIB3DS_KEY_USE_EASE_TO) { + lib3ds_io_write_float(io, key->ease_to); + } + if (key->flags & LIB3DS_KEY_USE_EASE_FROM) { + lib3ds_io_write_float(io, key->ease_from); + } +} + + +void +lib3ds_track_write(Lib3dsTrack *track, Lib3dsIo *io) { + int i; + + lib3ds_io_write_word(io, (uint16_t)track->flags); + lib3ds_io_write_dword(io, 0); + lib3ds_io_write_dword(io, 0); + lib3ds_io_write_dword(io, track->nkeys); + + switch (track->type) { + case LIB3DS_TRACK_BOOL: + for (i = 0; i < track->nkeys; ++i) { + lib3ds_io_write_intd(io, track->keys[i].frame); + tcb_write(&track->keys[i], io); + } + break; + + case LIB3DS_TRACK_FLOAT: + for (i = 0; i < track->nkeys; ++i) { + lib3ds_io_write_intd(io, track->keys[i].frame); + tcb_write(&track->keys[i], io); + lib3ds_io_write_float(io, track->keys[i].value[0]); + } + break; + + case LIB3DS_TRACK_VECTOR: + for (i = 0; i < track->nkeys; ++i) { + lib3ds_io_write_intd(io, track->keys[i].frame); + tcb_write(&track->keys[i], io); + lib3ds_io_write_vector(io, track->keys[i].value); + } + break; + + case LIB3DS_TRACK_QUAT: + for (i = 0; i < track->nkeys; ++i) { + lib3ds_io_write_intd(io, track->keys[i].frame); + tcb_write(&track->keys[i], io); + lib3ds_io_write_float(io, track->keys[i].value[3]); + lib3ds_io_write_vector(io, track->keys[i].value); + } + break; + + /*case LIB3DS_TRACK_MORPH: + for (i = 0; i < track->nkeys; ++i) { + lib3ds_io_write_intd(io, track->keys[i].frame); + tcb_write(&track->keys[i].tcb, io); + lib3ds_io_write_string(io, track->keys[i].data.m.name); + } + break;*/ + } +} diff --git a/src/osgPlugins/3ds/lib3ds/lib3ds_util.c b/src/osgPlugins/3ds/lib3ds/lib3ds_util.c index 738c834e3..f94878041 100644 --- a/src/osgPlugins/3ds/lib3ds/lib3ds_util.c +++ b/src/osgPlugins/3ds/lib3ds/lib3ds_util.c @@ -1,89 +1,89 @@ -/* - Copyright (C) 1996-2008 by Jan Eric Kyprianidis - 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. - - Thisprogram 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, see . -*/ -#include "lib3ds_impl.h" - - -void* lib3ds_util_realloc_array(void *ptr, int old_size, int new_size, int element_size) { - if (!ptr) - old_size = 0; - if (old_size != new_size) { - ptr = realloc(ptr, element_size * new_size); - if (old_size < new_size) { - memset((char*)ptr + element_size * old_size, 0, element_size * (new_size - old_size)); - } - } - return ptr; -} - - -void lib3ds_util_reserve_array(void ***ptr, int *n, int *size, int new_size, int force, Lib3dsFreeFunc free_func) { - assert(ptr && n && size); - if ((*size < new_size) || force) { - if (force && free_func) { - int i; - for (i = new_size; i < *n; ++i) { - free_func((*ptr)[i]); - (*ptr)[i] = 0; - } - } - *ptr = (void**)realloc(*ptr, sizeof(void*) * new_size); - *size = new_size; - if (*n > new_size) { - *n = new_size; - } - } -} - - -void lib3ds_util_insert_array(void ***ptr, int *n, int *size, void *element, int index) { - int i; - assert(ptr && n && size && element); - i = ((index >= 0) && (index < *n)) ? index : *n; - if (i >= *size) { - int new_size = 2 * (*size); - #ifdef _DEBUG - if (new_size < 1) { - new_size = 1; - } - #else - if (new_size < 32) { - new_size = 32; - } - #endif - lib3ds_util_reserve_array(ptr, n, size, new_size, FALSE, NULL); - } - assert(*ptr); - if (i < *n) { - memmove(&(*ptr)[i+1], &(*ptr)[i], sizeof(void*) * (*n - i)); - } - (*ptr)[i] = element; - *n = *n + 1; -} - - -void lib3ds_util_remove_array(void ***ptr, int *n, int index, Lib3dsFreeFunc free_func) { - assert(ptr && n); - if ((index >= 0) && (index < *n)) { - assert(*ptr); - free_func((*ptr)[index]); - if (index < *n - 1) { - memmove(&(*ptr)[index], &(*ptr)[index+1], sizeof(void*) * (*n - index - 1)); - } - *n = *n - 1; - } -} +/* + Copyright (C) 1996-2008 by Jan Eric Kyprianidis + 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. + + Thisprogram 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, see . +*/ +#include "lib3ds_impl.h" + + +void* lib3ds_util_realloc_array(void *ptr, int old_size, int new_size, int element_size) { + if (!ptr) + old_size = 0; + if (old_size != new_size) { + ptr = realloc(ptr, element_size * new_size); + if (old_size < new_size) { + memset((char*)ptr + element_size * old_size, 0, element_size * (new_size - old_size)); + } + } + return ptr; +} + + +void lib3ds_util_reserve_array(void ***ptr, int *n, int *size, int new_size, int force, Lib3dsFreeFunc free_func) { + assert(ptr && n && size); + if ((*size < new_size) || force) { + if (force && free_func) { + int i; + for (i = new_size; i < *n; ++i) { + free_func((*ptr)[i]); + (*ptr)[i] = 0; + } + } + *ptr = (void**)realloc(*ptr, sizeof(void*) * new_size); + *size = new_size; + if (*n > new_size) { + *n = new_size; + } + } +} + + +void lib3ds_util_insert_array(void ***ptr, int *n, int *size, void *element, int index) { + int i; + assert(ptr && n && size && element); + i = ((index >= 0) && (index < *n)) ? index : *n; + if (i >= *size) { + int new_size = 2 * (*size); + #ifdef _DEBUG + if (new_size < 1) { + new_size = 1; + } + #else + if (new_size < 32) { + new_size = 32; + } + #endif + lib3ds_util_reserve_array(ptr, n, size, new_size, FALSE, NULL); + } + assert(*ptr); + if (i < *n) { + memmove(&(*ptr)[i+1], &(*ptr)[i], sizeof(void*) * (*n - i)); + } + (*ptr)[i] = element; + *n = *n + 1; +} + + +void lib3ds_util_remove_array(void ***ptr, int *n, int index, Lib3dsFreeFunc free_func) { + assert(ptr && n); + if ((index >= 0) && (index < *n)) { + assert(*ptr); + free_func((*ptr)[index]); + if (index < *n - 1) { + memmove(&(*ptr)[index], &(*ptr)[index+1], sizeof(void*) * (*n - index - 1)); + } + *n = *n - 1; + } +} diff --git a/src/osgPlugins/3ds/lib3ds/lib3ds_vector.c b/src/osgPlugins/3ds/lib3ds/lib3ds_vector.c index c29a75c50..5f08186bc 100644 --- a/src/osgPlugins/3ds/lib3ds/lib3ds_vector.c +++ b/src/osgPlugins/3ds/lib3ds/lib3ds_vector.c @@ -1,246 +1,246 @@ -/* - Copyright (C) 1996-2008 by Jan Eric Kyprianidis - 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. - - Thisprogram 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, see . -*/ -#include "lib3ds_impl.h" - - -void -lib3ds_vector_make(float c[3], float x, float y, float z) { - c[0] = x; - c[1] = y; - c[2] = z; -} - - -void -lib3ds_vector_zero(float c[3]) { - int i; - for (i = 0; i < 3; ++i) { - c[i] = 0.0f; - } -} - - -void -lib3ds_vector_copy(float dst[3], float src[3]) { - int i; - for (i = 0; i < 3; ++i) { - dst[i] = src[i]; - } -} - - -/*! - * Add two vectors. - * - * \param c Result. - * \param a First addend. - * \param b Second addend. - */ -void -lib3ds_vector_add(float c[3], float a[3], float b[3]) { - 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. - */ -void -lib3ds_vector_sub(float c[3], float a[3], float b[3]) { - 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. - */ -void -lib3ds_vector_scalar_mul(float c[3], float a[3], float k) { - int i; - for (i = 0; i < 3; ++i) { - c[i] = a[i] * k; - } -} - - -/*! - * Compute cross product. - * - * \param c Result. - * \param a First vector. - * \param b Second vector. - */ -void -lib3ds_vector_cross(float c[3], float a[3], float b[3]) { - 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. - */ -float -lib3ds_vector_dot(float a[3], float b[3]) { - return(a[0]*b[0] + a[1]*b[1] + a[2]*b[2]); -} - - -/*! - * Compute length of vector. - * - * Computes |c| = sqrt(x*x + y*y + z*z) - * - * \param c Vector to compute. - * - * \return Length of vector. - */ -float -lib3ds_vector_length(float c[3]) { - return((float)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. - */ -void -lib3ds_vector_normalize(float c[3]) { - float l, m; - - l = (float)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. - */ -void -lib3ds_vector_normal(float n[3], float a[3], float b[3], float c[3]) { - float p[3], q[3]; - - 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. - */ -void -lib3ds_vector_transform(float c[3], float m[4][4], float a[3]) { - 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]; -} - - -/*! - * c[i] = min(c[i], a[i]); - * - * Computes minimum values of x,y,z independently. - */ -void -lib3ds_vector_min(float c[3], float a[3]) { - 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. - */ -void -lib3ds_vector_max(float c[3], float a[3]) { - int i; - for (i = 0; i < 3; ++i) { - if (a[i] > c[i]) { - c[i] = a[i]; - } - } -} - - -void -lib3ds_vector_dump(float c[3]) { - fprintf(stderr, "%f %f %f\n", c[0], c[1], c[2]); -} - +/* + Copyright (C) 1996-2008 by Jan Eric Kyprianidis + 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. + + Thisprogram 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, see . +*/ +#include "lib3ds_impl.h" + + +void +lib3ds_vector_make(float c[3], float x, float y, float z) { + c[0] = x; + c[1] = y; + c[2] = z; +} + + +void +lib3ds_vector_zero(float c[3]) { + int i; + for (i = 0; i < 3; ++i) { + c[i] = 0.0f; + } +} + + +void +lib3ds_vector_copy(float dst[3], float src[3]) { + int i; + for (i = 0; i < 3; ++i) { + dst[i] = src[i]; + } +} + + +/*! + * Add two vectors. + * + * \param c Result. + * \param a First addend. + * \param b Second addend. + */ +void +lib3ds_vector_add(float c[3], float a[3], float b[3]) { + 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. + */ +void +lib3ds_vector_sub(float c[3], float a[3], float b[3]) { + 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. + */ +void +lib3ds_vector_scalar_mul(float c[3], float a[3], float k) { + int i; + for (i = 0; i < 3; ++i) { + c[i] = a[i] * k; + } +} + + +/*! + * Compute cross product. + * + * \param c Result. + * \param a First vector. + * \param b Second vector. + */ +void +lib3ds_vector_cross(float c[3], float a[3], float b[3]) { + 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. + */ +float +lib3ds_vector_dot(float a[3], float b[3]) { + return(a[0]*b[0] + a[1]*b[1] + a[2]*b[2]); +} + + +/*! + * Compute length of vector. + * + * Computes |c| = sqrt(x*x + y*y + z*z) + * + * \param c Vector to compute. + * + * \return Length of vector. + */ +float +lib3ds_vector_length(float c[3]) { + return((float)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. + */ +void +lib3ds_vector_normalize(float c[3]) { + float l, m; + + l = (float)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. + */ +void +lib3ds_vector_normal(float n[3], float a[3], float b[3], float c[3]) { + float p[3], q[3]; + + 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. + */ +void +lib3ds_vector_transform(float c[3], float m[4][4], float a[3]) { + 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]; +} + + +/*! + * c[i] = min(c[i], a[i]); + * + * Computes minimum values of x,y,z independently. + */ +void +lib3ds_vector_min(float c[3], float a[3]) { + 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. + */ +void +lib3ds_vector_max(float c[3], float a[3]) { + int i; + for (i = 0; i < 3; ++i) { + if (a[i] > c[i]) { + c[i] = a[i]; + } + } +} + + +void +lib3ds_vector_dump(float c[3]) { + fprintf(stderr, "%f %f %f\n", c[0], c[1], c[2]); +} + diff --git a/src/osgPlugins/3ds/lib3ds/lib3ds_viewport.c b/src/osgPlugins/3ds/lib3ds/lib3ds_viewport.c index 1e96ab86f..cc71a7db7 100644 --- a/src/osgPlugins/3ds/lib3ds/lib3ds_viewport.c +++ b/src/osgPlugins/3ds/lib3ds/lib3ds_viewport.c @@ -1,296 +1,296 @@ -/* - Copyright (C) 1996-2008 by Jan Eric Kyprianidis - 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. - - Thisprogram 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, see . -*/ -#include "lib3ds_impl.h" - - -void -lib3ds_viewport_read(Lib3dsViewport *viewport, Lib3dsIo *io) { - Lib3dsChunk c; - uint16_t chunk; - - memset(viewport, 0, sizeof(*viewport)); - lib3ds_chunk_read_start(&c, 0, io); - switch (c.chunk) { - case CHK_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 CHK_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 CHK_VIEWPORT_DATA_3: { - if (cur < LIB3DS_LAYOUT_MAX_VIEWS) { - lib3ds_io_read_intw(io); - viewport->layout_views[cur].axis_lock = lib3ds_io_read_word(io); - viewport->layout_views[cur].position[0] = lib3ds_io_read_intw(io); - viewport->layout_views[cur].position[1] = lib3ds_io_read_intw(io); - viewport->layout_views[cur].size[0] = lib3ds_io_read_intw(io); - viewport->layout_views[cur].size[1] = lib3ds_io_read_intw(io); - viewport->layout_views[cur].type = lib3ds_io_read_word(io); - viewport->layout_views[cur].zoom = lib3ds_io_read_float(io); - lib3ds_io_read_vector(io, viewport->layout_views[cur].center); - viewport->layout_views[cur].horiz_angle = lib3ds_io_read_float(io); - viewport->layout_views[cur].vert_angle = lib3ds_io_read_float(io); - lib3ds_io_read(io, viewport->layout_views[cur].camera, 11); - ++cur; - } - break; - } - - case CHK_VIEWPORT_DATA: - /* 3DS R2 & R3 chunk unsupported */ - break; - - default: - lib3ds_chunk_unknown(chunk, io); - } - } - break; - } - - case CHK_DEFAULT_VIEW: { - while ((chunk = lib3ds_chunk_read_next(&c, io)) != 0) { - switch (chunk) { - case CHK_VIEW_TOP: { - viewport->default_type = LIB3DS_VIEW_TOP; - lib3ds_io_read_vector(io, viewport->default_position); - viewport->default_width = lib3ds_io_read_float(io); - break; - } - - case CHK_VIEW_BOTTOM: { - viewport->default_type = LIB3DS_VIEW_BOTTOM; - lib3ds_io_read_vector(io, viewport->default_position); - viewport->default_width = lib3ds_io_read_float(io); - break; - } - - case CHK_VIEW_LEFT: { - viewport->default_type = LIB3DS_VIEW_LEFT; - lib3ds_io_read_vector(io, viewport->default_position); - viewport->default_width = lib3ds_io_read_float(io); - break; - } - - case CHK_VIEW_RIGHT: { - viewport->default_type = LIB3DS_VIEW_RIGHT; - lib3ds_io_read_vector(io, viewport->default_position); - viewport->default_width = lib3ds_io_read_float(io); - break; - } - - case CHK_VIEW_FRONT: { - viewport->default_type = LIB3DS_VIEW_FRONT; - lib3ds_io_read_vector(io, viewport->default_position); - viewport->default_width = lib3ds_io_read_float(io); - break; - } - - case CHK_VIEW_BACK: { - viewport->default_type = LIB3DS_VIEW_BACK; - lib3ds_io_read_vector(io, viewport->default_position); - viewport->default_width = lib3ds_io_read_float(io); - break; - } - - case CHK_VIEW_USER: { - viewport->default_type = LIB3DS_VIEW_USER; - lib3ds_io_read_vector(io, viewport->default_position); - viewport->default_width = lib3ds_io_read_float(io); - viewport->default_horiz_angle = lib3ds_io_read_float(io); - viewport->default_vert_angle = lib3ds_io_read_float(io); - viewport->default_roll_angle = lib3ds_io_read_float(io); - break; - } - - case CHK_VIEW_CAMERA: { - viewport->default_type = LIB3DS_VIEW_CAMERA; - lib3ds_io_read(io, viewport->default_camera, 11); - break; - } - - default: - lib3ds_chunk_unknown(chunk, io); - } - } - break; - } - } - - lib3ds_chunk_read_end(&c, io); -} - - -void -lib3ds_viewport_write(Lib3dsViewport *viewport, Lib3dsIo *io) { - if (viewport->layout_nviews) { - Lib3dsChunk c; - int i; - - c.chunk = CHK_VIEWPORT_LAYOUT; - lib3ds_chunk_write_start(&c, io); - - lib3ds_io_write_word(io, (uint16_t)viewport->layout_style); - lib3ds_io_write_intw(io, (int16_t)viewport->layout_active); - lib3ds_io_write_intw(io, (int16_t)0); - lib3ds_io_write_intw(io, (int16_t)viewport->layout_swap); - lib3ds_io_write_intw(io, (int16_t)0); - lib3ds_io_write_intw(io, (int16_t)viewport->layout_swap_prior); - lib3ds_io_write_intw(io, (int16_t)viewport->layout_swap_view); - - { - Lib3dsChunk c; - c.chunk = CHK_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_nviews; ++i) { - Lib3dsChunk c; - c.chunk = CHK_VIEWPORT_DATA_3; - c.size = 55; - lib3ds_chunk_write(&c, io); - - lib3ds_io_write_intw(io, 0); - lib3ds_io_write_word(io, (uint16_t)viewport->layout_views[i].axis_lock); - lib3ds_io_write_intw(io, (int16_t)viewport->layout_views[i].position[0]); - lib3ds_io_write_intw(io, (int16_t)viewport->layout_views[i].position[1]); - lib3ds_io_write_intw(io, (int16_t)viewport->layout_views[i].size[0]); - lib3ds_io_write_intw(io, (int16_t)viewport->layout_views[i].size[1]); - lib3ds_io_write_word(io, (int16_t)viewport->layout_views[i].type); - lib3ds_io_write_float(io, viewport->layout_views[i].zoom); - lib3ds_io_write_vector(io, viewport->layout_views[i].center); - lib3ds_io_write_float(io, viewport->layout_views[i].horiz_angle); - lib3ds_io_write_float(io, viewport->layout_views[i].vert_angle); - lib3ds_io_write(io, viewport->layout_views[i].camera, 11); - } - - lib3ds_chunk_write_end(&c, io); - } - - if (viewport->default_type) { - Lib3dsChunk c; - - c.chunk = CHK_DEFAULT_VIEW; - lib3ds_chunk_write_start(&c, io); - - switch (viewport->default_type) { - case LIB3DS_VIEW_TOP: { - Lib3dsChunk c; - c.chunk = CHK_VIEW_TOP; - c.size = 22; - lib3ds_chunk_write(&c, io); - lib3ds_io_write_vector(io, viewport->default_position); - lib3ds_io_write_float(io, viewport->default_width); - break; - } - - case LIB3DS_VIEW_BOTTOM: { - Lib3dsChunk c; - c.chunk = CHK_VIEW_BOTTOM; - c.size = 22; - lib3ds_chunk_write(&c, io); - lib3ds_io_write_vector(io, viewport->default_position); - lib3ds_io_write_float(io, viewport->default_width); - break; - } - - case LIB3DS_VIEW_LEFT: { - Lib3dsChunk c; - c.chunk = CHK_VIEW_LEFT; - c.size = 22; - lib3ds_chunk_write(&c, io); - lib3ds_io_write_vector(io, viewport->default_position); - lib3ds_io_write_float(io, viewport->default_width); - break; - } - - case LIB3DS_VIEW_RIGHT: { - Lib3dsChunk c; - c.chunk = CHK_VIEW_RIGHT; - c.size = 22; - lib3ds_chunk_write(&c, io); - lib3ds_io_write_vector(io, viewport->default_position); - lib3ds_io_write_float(io, viewport->default_width); - break; - } - - case LIB3DS_VIEW_FRONT: { - Lib3dsChunk c; - c.chunk = CHK_VIEW_FRONT; - c.size = 22; - lib3ds_chunk_write(&c, io); - lib3ds_io_write_vector(io, viewport->default_position); - lib3ds_io_write_float(io, viewport->default_width); - break; - } - - case LIB3DS_VIEW_BACK: { - Lib3dsChunk c; - c.chunk = CHK_VIEW_BACK; - c.size = 22; - lib3ds_chunk_write(&c, io); - lib3ds_io_write_vector(io, viewport->default_position); - lib3ds_io_write_float(io, viewport->default_width); - break; - } - - case LIB3DS_VIEW_USER: { - Lib3dsChunk c; - c.chunk = CHK_VIEW_USER; - c.size = 34; - lib3ds_chunk_write(&c, io); - lib3ds_io_write_vector(io, viewport->default_position); - lib3ds_io_write_float(io, viewport->default_width); - lib3ds_io_write_float(io, viewport->default_horiz_angle); - lib3ds_io_write_float(io, viewport->default_vert_angle); - lib3ds_io_write_float(io, viewport->default_roll_angle); - break; - } - - case LIB3DS_VIEW_CAMERA: { - Lib3dsChunk c; - c.chunk = CHK_VIEW_CAMERA; - c.size = 17; - lib3ds_chunk_write(&c, io); - lib3ds_io_write(io, viewport->default_camera, 11); - break; - } - } - - lib3ds_chunk_write_end(&c, io); - } -} - +/* + Copyright (C) 1996-2008 by Jan Eric Kyprianidis + 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. + + Thisprogram 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, see . +*/ +#include "lib3ds_impl.h" + + +void +lib3ds_viewport_read(Lib3dsViewport *viewport, Lib3dsIo *io) { + Lib3dsChunk c; + uint16_t chunk; + + memset(viewport, 0, sizeof(*viewport)); + lib3ds_chunk_read_start(&c, 0, io); + switch (c.chunk) { + case CHK_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 CHK_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 CHK_VIEWPORT_DATA_3: { + if (cur < LIB3DS_LAYOUT_MAX_VIEWS) { + lib3ds_io_read_intw(io); + viewport->layout_views[cur].axis_lock = lib3ds_io_read_word(io); + viewport->layout_views[cur].position[0] = lib3ds_io_read_intw(io); + viewport->layout_views[cur].position[1] = lib3ds_io_read_intw(io); + viewport->layout_views[cur].size[0] = lib3ds_io_read_intw(io); + viewport->layout_views[cur].size[1] = lib3ds_io_read_intw(io); + viewport->layout_views[cur].type = lib3ds_io_read_word(io); + viewport->layout_views[cur].zoom = lib3ds_io_read_float(io); + lib3ds_io_read_vector(io, viewport->layout_views[cur].center); + viewport->layout_views[cur].horiz_angle = lib3ds_io_read_float(io); + viewport->layout_views[cur].vert_angle = lib3ds_io_read_float(io); + lib3ds_io_read(io, viewport->layout_views[cur].camera, 11); + ++cur; + } + break; + } + + case CHK_VIEWPORT_DATA: + /* 3DS R2 & R3 chunk unsupported */ + break; + + default: + lib3ds_chunk_unknown(chunk, io); + } + } + break; + } + + case CHK_DEFAULT_VIEW: { + while ((chunk = lib3ds_chunk_read_next(&c, io)) != 0) { + switch (chunk) { + case CHK_VIEW_TOP: { + viewport->default_type = LIB3DS_VIEW_TOP; + lib3ds_io_read_vector(io, viewport->default_position); + viewport->default_width = lib3ds_io_read_float(io); + break; + } + + case CHK_VIEW_BOTTOM: { + viewport->default_type = LIB3DS_VIEW_BOTTOM; + lib3ds_io_read_vector(io, viewport->default_position); + viewport->default_width = lib3ds_io_read_float(io); + break; + } + + case CHK_VIEW_LEFT: { + viewport->default_type = LIB3DS_VIEW_LEFT; + lib3ds_io_read_vector(io, viewport->default_position); + viewport->default_width = lib3ds_io_read_float(io); + break; + } + + case CHK_VIEW_RIGHT: { + viewport->default_type = LIB3DS_VIEW_RIGHT; + lib3ds_io_read_vector(io, viewport->default_position); + viewport->default_width = lib3ds_io_read_float(io); + break; + } + + case CHK_VIEW_FRONT: { + viewport->default_type = LIB3DS_VIEW_FRONT; + lib3ds_io_read_vector(io, viewport->default_position); + viewport->default_width = lib3ds_io_read_float(io); + break; + } + + case CHK_VIEW_BACK: { + viewport->default_type = LIB3DS_VIEW_BACK; + lib3ds_io_read_vector(io, viewport->default_position); + viewport->default_width = lib3ds_io_read_float(io); + break; + } + + case CHK_VIEW_USER: { + viewport->default_type = LIB3DS_VIEW_USER; + lib3ds_io_read_vector(io, viewport->default_position); + viewport->default_width = lib3ds_io_read_float(io); + viewport->default_horiz_angle = lib3ds_io_read_float(io); + viewport->default_vert_angle = lib3ds_io_read_float(io); + viewport->default_roll_angle = lib3ds_io_read_float(io); + break; + } + + case CHK_VIEW_CAMERA: { + viewport->default_type = LIB3DS_VIEW_CAMERA; + lib3ds_io_read(io, viewport->default_camera, 11); + break; + } + + default: + lib3ds_chunk_unknown(chunk, io); + } + } + break; + } + } + + lib3ds_chunk_read_end(&c, io); +} + + +void +lib3ds_viewport_write(Lib3dsViewport *viewport, Lib3dsIo *io) { + if (viewport->layout_nviews) { + Lib3dsChunk c; + int i; + + c.chunk = CHK_VIEWPORT_LAYOUT; + lib3ds_chunk_write_start(&c, io); + + lib3ds_io_write_word(io, (uint16_t)viewport->layout_style); + lib3ds_io_write_intw(io, (int16_t)viewport->layout_active); + lib3ds_io_write_intw(io, (int16_t)0); + lib3ds_io_write_intw(io, (int16_t)viewport->layout_swap); + lib3ds_io_write_intw(io, (int16_t)0); + lib3ds_io_write_intw(io, (int16_t)viewport->layout_swap_prior); + lib3ds_io_write_intw(io, (int16_t)viewport->layout_swap_view); + + { + Lib3dsChunk c; + c.chunk = CHK_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_nviews; ++i) { + Lib3dsChunk c; + c.chunk = CHK_VIEWPORT_DATA_3; + c.size = 55; + lib3ds_chunk_write(&c, io); + + lib3ds_io_write_intw(io, 0); + lib3ds_io_write_word(io, (uint16_t)viewport->layout_views[i].axis_lock); + lib3ds_io_write_intw(io, (int16_t)viewport->layout_views[i].position[0]); + lib3ds_io_write_intw(io, (int16_t)viewport->layout_views[i].position[1]); + lib3ds_io_write_intw(io, (int16_t)viewport->layout_views[i].size[0]); + lib3ds_io_write_intw(io, (int16_t)viewport->layout_views[i].size[1]); + lib3ds_io_write_word(io, (int16_t)viewport->layout_views[i].type); + lib3ds_io_write_float(io, viewport->layout_views[i].zoom); + lib3ds_io_write_vector(io, viewport->layout_views[i].center); + lib3ds_io_write_float(io, viewport->layout_views[i].horiz_angle); + lib3ds_io_write_float(io, viewport->layout_views[i].vert_angle); + lib3ds_io_write(io, viewport->layout_views[i].camera, 11); + } + + lib3ds_chunk_write_end(&c, io); + } + + if (viewport->default_type) { + Lib3dsChunk c; + + c.chunk = CHK_DEFAULT_VIEW; + lib3ds_chunk_write_start(&c, io); + + switch (viewport->default_type) { + case LIB3DS_VIEW_TOP: { + Lib3dsChunk c; + c.chunk = CHK_VIEW_TOP; + c.size = 22; + lib3ds_chunk_write(&c, io); + lib3ds_io_write_vector(io, viewport->default_position); + lib3ds_io_write_float(io, viewport->default_width); + break; + } + + case LIB3DS_VIEW_BOTTOM: { + Lib3dsChunk c; + c.chunk = CHK_VIEW_BOTTOM; + c.size = 22; + lib3ds_chunk_write(&c, io); + lib3ds_io_write_vector(io, viewport->default_position); + lib3ds_io_write_float(io, viewport->default_width); + break; + } + + case LIB3DS_VIEW_LEFT: { + Lib3dsChunk c; + c.chunk = CHK_VIEW_LEFT; + c.size = 22; + lib3ds_chunk_write(&c, io); + lib3ds_io_write_vector(io, viewport->default_position); + lib3ds_io_write_float(io, viewport->default_width); + break; + } + + case LIB3DS_VIEW_RIGHT: { + Lib3dsChunk c; + c.chunk = CHK_VIEW_RIGHT; + c.size = 22; + lib3ds_chunk_write(&c, io); + lib3ds_io_write_vector(io, viewport->default_position); + lib3ds_io_write_float(io, viewport->default_width); + break; + } + + case LIB3DS_VIEW_FRONT: { + Lib3dsChunk c; + c.chunk = CHK_VIEW_FRONT; + c.size = 22; + lib3ds_chunk_write(&c, io); + lib3ds_io_write_vector(io, viewport->default_position); + lib3ds_io_write_float(io, viewport->default_width); + break; + } + + case LIB3DS_VIEW_BACK: { + Lib3dsChunk c; + c.chunk = CHK_VIEW_BACK; + c.size = 22; + lib3ds_chunk_write(&c, io); + lib3ds_io_write_vector(io, viewport->default_position); + lib3ds_io_write_float(io, viewport->default_width); + break; + } + + case LIB3DS_VIEW_USER: { + Lib3dsChunk c; + c.chunk = CHK_VIEW_USER; + c.size = 34; + lib3ds_chunk_write(&c, io); + lib3ds_io_write_vector(io, viewport->default_position); + lib3ds_io_write_float(io, viewport->default_width); + lib3ds_io_write_float(io, viewport->default_horiz_angle); + lib3ds_io_write_float(io, viewport->default_vert_angle); + lib3ds_io_write_float(io, viewport->default_roll_angle); + break; + } + + case LIB3DS_VIEW_CAMERA: { + Lib3dsChunk c; + c.chunk = CHK_VIEW_CAMERA; + c.size = 17; + lib3ds_chunk_write(&c, io); + lib3ds_io_write(io, viewport->default_camera, 11); + break; + } + } + + lib3ds_chunk_write_end(&c, io); + } +} +