X-Git-Url: http://git.xonotic.org/?a=blobdiff_plain;f=libs%2Fpicomodel%2Fpm_obj.c;h=32bdbd258213588c314d24a5c2f374d090ac4f3b;hb=refs%2Fmerge-requests%2F107%2Fhead;hp=7f269faa009b1a23063041ad7e2cf166014c9d8a;hpb=5ec3a47e102a60270ba18049bc44c584cf1de118;p=xonotic%2Fnetradiant.git diff --git a/libs/picomodel/pm_obj.c b/libs/picomodel/pm_obj.c index 7f269faa..32bdbd25 100644 --- a/libs/picomodel/pm_obj.c +++ b/libs/picomodel/pm_obj.c @@ -1,47 +1,43 @@ /* ----------------------------------------------------------------------------- -PicoModel Library + PicoModel Library -Copyright (c) 2002, Randy Reddig & seaw0lf -All rights reserved. + Copyright (c) 2002, Randy Reddig & seaw0lf + All rights reserved. -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: -Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. + Redistributions of source code must retain the above copyright notice, this list + of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this -list of conditions and the following disclaimer in the documentation and/or -other materials provided with the distribution. + Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. -Neither the names of the copyright holders nor the names of its contributors may -be used to endorse or promote products derived from this software without -specific prior written permission. + Neither the names of the copyright holders nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ------------------------------------------------------------------------------ */ - - - -/* marker */ -#define PM_OBJ_C + ----------------------------------------------------------------------------- */ /* dependencies */ #include "picointernal.h" +#include "globaldefs.h" /* disable warnings */ -#ifdef WIN32 +#if GDEF_COMPILER_MSVC #pragma warning( disable:4100 ) /* unref param */ #endif @@ -58,28 +54,27 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /* this holds temporary vertex data read by parser */ typedef struct SObjVertexData { - picoVec3_t v; /* geometric vertices */ - picoVec2_t vt; /* texture vertices */ - picoVec3_t vn; /* vertex normals (optional) */ + picoVec3_t v; /* geometric vertices */ + picoVec2_t vt; /* texture vertices */ + picoVec3_t vn; /* vertex normals (optional) */ } TObjVertexData; /* _obj_canload: * validates a wavefront obj model file. */ -static int _obj_canload( PM_PARAMS_CANLOAD ) -{ +static int _obj_canload( PM_PARAMS_CANLOAD ){ picoParser_t *p; /* check data length */ - if (bufSize < 30) + if ( bufSize < 30 ) { return PICO_PMV_ERROR_SIZE; + } /* first check file extension. we have to do this for objs */ /* cause there is no good way to identify the contents */ - if (_pico_stristr(fileName,".obj") != NULL || - _pico_stristr(fileName,".wf" ) != NULL) - { + if ( _pico_stristr( fileName,".obj" ) != NULL || + _pico_stristr( fileName,".wf" ) != NULL ) { return PICO_PMV_OK; } /* if the extension check failed we parse through the first */ @@ -88,30 +83,33 @@ static int _obj_canload( PM_PARAMS_CANLOAD ) /* alllocate a new pico parser */ p = _pico_new_parser( (const picoByte_t *)buffer,bufSize ); - if (p == NULL) + if ( p == NULL ) { return PICO_PMV_ERROR_MEMORY; + } /* parse obj head line by line for type check */ - while( 1 ) + while ( 1 ) { /* get first token on line */ - if (_pico_parse_first( p ) == NULL) + if ( _pico_parse_first( p ) == NULL ) { break; + } /* we only parse the first few lines, say 80 */ - if (p->curLine > 80) + if ( p->curLine > 80 ) { break; + } /* skip empty lines */ - if (p->token == NULL || !strlen( p->token )) + if ( p->token == NULL || !strlen( p->token ) ) { continue; + } /* material library keywords are teh good */ - if (!_pico_stricmp(p->token,"usemtl") || - !_pico_stricmp(p->token,"mtllib") || - !_pico_stricmp(p->token,"g") || - !_pico_stricmp(p->token,"v")) /* v,g bit fishy, but uh... */ - { + if ( !_pico_stricmp( p->token,"usemtl" ) || + !_pico_stricmp( p->token,"mtllib" ) || + !_pico_stricmp( p->token,"g" ) || + !_pico_stricmp( p->token,"v" ) ) { /* v,g bit fishy, but uh... */ /* free the pico parser thing */ _pico_free_parser( p ); @@ -133,45 +131,45 @@ static int _obj_canload( PM_PARAMS_CANLOAD ) * allocates - and reallocates as soon as required - * my vertex data array in even steps. */ -#define SIZE_OBJ_STEP 4096 +const int SIZE_OBJ_STEP = 4096; static TObjVertexData *SizeObjVertexData( TObjVertexData *vertexData, int reqEntries, - int *entries, int *allocated) -{ + int *entries, int *allocated ){ int newAllocated; /* sanity checks */ - if (reqEntries < 1) + if ( reqEntries < 1 ) { return NULL; - if (entries == NULL || allocated == NULL) + } + if ( entries == NULL || allocated == NULL ) { return NULL; /* must have */ + } /* no need to grow yet */ - if (vertexData && (reqEntries < *allocated)) - { + if ( vertexData && ( reqEntries < *allocated ) ) { *entries = reqEntries; return vertexData; } /* given vertex data ptr not allocated yet */ - if (vertexData == NULL) - { + if ( vertexData == NULL ) { /* how many entries to allocate */ - newAllocated = (reqEntries > SIZE_OBJ_STEP) ? - reqEntries : SIZE_OBJ_STEP; + newAllocated = ( reqEntries > SIZE_OBJ_STEP ) ? + reqEntries : SIZE_OBJ_STEP; /* throw out an extended debug message */ #ifdef DEBUG_PM_OBJ_EX - printf("SizeObjVertexData: allocate (%d entries)\n", - newAllocated); + printf( "SizeObjVertexData: allocate (%d entries)\n", + newAllocated ); #endif /* first time allocation */ vertexData = (TObjVertexData *) - _pico_alloc( sizeof(TObjVertexData) * newAllocated ); + _pico_alloc( sizeof( TObjVertexData ) * newAllocated ); /* allocation failed */ - if (vertexData == NULL) + if ( vertexData == NULL ) { return NULL; + } /* allocation succeeded */ *allocated = newAllocated; @@ -179,24 +177,24 @@ static TObjVertexData *SizeObjVertexData( return vertexData; } /* given vertex data ptr needs to be resized */ - if (reqEntries == *allocated) - { - newAllocated = (*allocated + SIZE_OBJ_STEP); + if ( reqEntries == *allocated ) { + newAllocated = ( *allocated + SIZE_OBJ_STEP ); /* throw out an extended debug message */ #ifdef DEBUG_PM_OBJ_EX - printf("SizeObjVertexData: reallocate (%d entries)\n", - newAllocated); + printf( "SizeObjVertexData: reallocate (%d entries)\n", + newAllocated ); #endif /* try to reallocate */ vertexData = (TObjVertexData *) - _pico_realloc( (void *)&vertexData, - sizeof(TObjVertexData) * (*allocated), - sizeof(TObjVertexData) * (newAllocated)); + _pico_realloc( (void *)&vertexData, + sizeof( TObjVertexData ) * ( *allocated ), + sizeof( TObjVertexData ) * ( newAllocated ) ); /* reallocation failed */ - if (vertexData == NULL) + if ( vertexData == NULL ) { return NULL; + } /* reallocation succeeded */ *allocated = newAllocated; @@ -207,42 +205,42 @@ static TObjVertexData *SizeObjVertexData( return NULL; } -static void FreeObjVertexData( TObjVertexData *vertexData ) -{ - if (vertexData != NULL) - { +static void FreeObjVertexData( TObjVertexData *vertexData ){ + if ( vertexData != NULL ) { free( (TObjVertexData *)vertexData ); } } -static int _obj_mtl_load( picoModel_t *model ) -{ +static int _obj_mtl_load( picoModel_t *model ){ picoShader_t *curShader = NULL; picoParser_t *p; picoByte_t *mtlBuffer; - int mtlBufSize; - char *fileName; + int mtlBufSize; + char *fileName; /* sanity checks */ - if( model == NULL || model->fileName == NULL ) + if ( model == NULL || model->fileName == NULL ) { return 0; + } /* skip if we have a zero length model file name */ - if (!strlen( model->fileName )) + if ( !strlen( model->fileName ) ) { return 0; + } /* helper */ #define _obj_mtl_error_return \ { \ - _pico_free_parser( p ); \ + _pico_free_parser( p ); \ _pico_free_file( mtlBuffer ); \ - _pico_free( fileName ); \ + _pico_free( fileName ); \ return 0; \ } /* alloc copy of model file name */ fileName = _pico_clone_alloc( model->fileName ); - if (fileName == NULL) + if ( fileName == NULL ) { return 0; + } /* change extension of model file to .mtl */ _pico_setfext( fileName, "mtl" ); @@ -251,35 +249,40 @@ static int _obj_mtl_load( picoModel_t *model ) _pico_load_file( fileName,&mtlBuffer,&mtlBufSize ); /* check result */ - if (mtlBufSize == 0) return 1; /* file is empty: no error */ - if (mtlBufSize < 0) return 0; /* load failed: error */ + if ( mtlBufSize == 0 ) { + return 1; /* file is empty: no error */ + } + if ( mtlBufSize < 0 ) { + return 0; /* load failed: error */ + } /* create a new pico parser */ p = _pico_new_parser( mtlBuffer, mtlBufSize ); - if (p == NULL) + if ( p == NULL ) { _obj_mtl_error_return; - + } + /* doo teh .mtl parse */ - while( 1 ) + while ( 1 ) { /* get next token in material file */ - if (_pico_parse( p,1 ) == NULL) + if ( _pico_parse( p,1 ) == NULL ) { break; + } #if 1 /* skip empty lines */ - if (p->token == NULL || !strlen( p->token )) + if ( p->token == NULL || !strlen( p->token ) ) { continue; + } /* skip comment lines */ - if (p->token[0] == '#') - { + if ( p->token[0] == '#' ) { _pico_parse_skip_rest( p ); continue; } /* new material */ - if (!_pico_stricmp(p->token,"newmtl")) - { + if ( !_pico_stricmp( p->token,"newmtl" ) ) { picoShader_t *shader; char *name; @@ -287,15 +290,15 @@ static int _obj_mtl_load( picoModel_t *model ) name = _pico_parse( p,0 ); /* validate material name */ - if (name == NULL || !strlen(name)) - { - _pico_printf( PICO_ERROR,"Missing material name in MTL, line %d.",p->curLine); + if ( name == NULL || !strlen( name ) ) { + _pico_printf( PICO_ERROR,"Missing material name in MTL, line %d.",p->curLine ); _obj_mtl_error_return; } /* create a new pico shader */ shader = PicoNewShader( model ); - if (shader == NULL) + if ( shader == NULL ) { _obj_mtl_error_return; + } /* set shader name */ PicoSetShaderName( shader,name ); @@ -304,42 +307,42 @@ static int _obj_mtl_load( picoModel_t *model ) curShader = shader; } /* diffuse map name */ - else if (!_pico_stricmp(p->token,"map_kd")) - { + else if ( !_pico_stricmp( p->token,"map_kd" ) ) { char *mapName; picoShader_t *shader; /* pointer to current shader must be valid */ - if (curShader == NULL) + if ( curShader == NULL ) { _obj_mtl_error_return; + } /* get material's diffuse map name */ mapName = _pico_parse( p,0 ); /* validate map name */ - if (mapName == NULL || !strlen(mapName)) - { - _pico_printf( PICO_ERROR,"Missing material map name in MTL, line %d.",p->curLine); + if ( mapName == NULL || !strlen( mapName ) ) { + _pico_printf( PICO_ERROR,"Missing material map name in MTL, line %d.",p->curLine ); _obj_mtl_error_return; } /* create a new pico shader */ shader = PicoNewShader( model ); - if (shader == NULL) + if ( shader == NULL ) { _obj_mtl_error_return; + } /* set shader map name */ PicoSetShaderMapName( shader,mapName ); } /* dissolve factor (pseudo transparency 0..1) */ /* where 0 means 100% transparent and 1 means opaque */ - else if (!_pico_stricmp(p->token,"d")) - { + else if ( !_pico_stricmp( p->token,"d" ) ) { picoByte_t *diffuse; float value; /* get dissolve factor */ - if (!_pico_parse_float( p,&value )) + if ( !_pico_parse_float( p,&value ) ) { _obj_mtl_error_return; + } /* set shader transparency */ PicoSetShaderTransparency( curShader,value ); @@ -354,8 +357,7 @@ static int _obj_mtl_load( picoModel_t *model ) PicoSetShaderDiffuseColor( curShader,diffuse ); } /* shininess (phong specular component) */ - else if (!_pico_stricmp(p->token,"ns")) - { + else if ( !_pico_stricmp( p->token,"ns" ) ) { /* remark: * - well, this is some major obj spec fuckup once again. some * apps store this in 0..1 range, others use 0..100 range, @@ -367,52 +369,61 @@ static int _obj_mtl_load( picoModel_t *model ) float value; /* pointer to current shader must be valid */ - if (curShader == NULL) + if ( curShader == NULL ) { _obj_mtl_error_return; + } /* get totally screwed up shininess (a random value in fact ;) */ - if (!_pico_parse_float( p,&value )) + if ( !_pico_parse_float( p,&value ) ) { _obj_mtl_error_return; + } /* okay, there is no way to set this correctly, so we simply */ /* try to guess a few ranges (most common ones i have seen) */ /* assume 0..2048 range */ - if (value > 1000) - value = 128.0 * (value / 2048.0); + if ( value > 1000 ) { + value = 128.0 * ( value / 2048.0 ); + } /* assume 0..1000 range */ - else if (value > 200) - value = 128.0 * (value / 1000.0); + else if ( value > 200 ) { + value = 128.0 * ( value / 1000.0 ); + } /* assume 0..200 range */ - else if (value > 100) - value = 128.0 * (value / 200.0); + else if ( value > 100 ) { + value = 128.0 * ( value / 200.0 ); + } /* assume 0..100 range */ - else if (value > 1) - value = 128.0 * (value / 100.0); + else if ( value > 1 ) { + value = 128.0 * ( value / 100.0 ); + } /* assume 0..1 range */ else { value *= 128.0; } /* negative shininess is bad (yes, i have seen it...) */ - if (value < 0.0) value = 0.0; + if ( value < 0.0 ) { + value = 0.0; + } /* set the pico shininess value in range 0..127 */ /* geez, .obj is such a mess... */ PicoSetShaderShininess( curShader,value ); } /* kol0r ambient (wut teh fuk does "ka" stand for?) */ - else if (!_pico_stricmp(p->token,"ka")) - { + else if ( !_pico_stricmp( p->token,"ka" ) ) { picoColor_t color; - picoVec3_t v; + picoVec3_t v; /* pointer to current shader must be valid */ - if (curShader == NULL) + if ( curShader == NULL ) { _obj_mtl_error_return; + } /* get color vector */ - if (!_pico_parse_vec( p,v )) + if ( !_pico_parse_vec( p,v ) ) { _obj_mtl_error_return; + } /* scale to byte range */ color[ 0 ] = (picoByte_t)( v[ 0 ] * 255 ); @@ -424,18 +435,19 @@ static int _obj_mtl_load( picoModel_t *model ) PicoSetShaderAmbientColor( curShader,color ); } /* kol0r diffuse */ - else if (!_pico_stricmp(p->token,"kd")) - { + else if ( !_pico_stricmp( p->token,"kd" ) ) { picoColor_t color; - picoVec3_t v; + picoVec3_t v; /* pointer to current shader must be valid */ - if (curShader == NULL) + if ( curShader == NULL ) { _obj_mtl_error_return; + } /* get color vector */ - if (!_pico_parse_vec( p,v )) + if ( !_pico_parse_vec( p,v ) ) { _obj_mtl_error_return; + } /* scale to byte range */ color[ 0 ] = (picoByte_t)( v[ 0 ] * 255 ); @@ -447,18 +459,19 @@ static int _obj_mtl_load( picoModel_t *model ) PicoSetShaderDiffuseColor( curShader,color ); } /* kol0r specular */ - else if (!_pico_stricmp(p->token,"ks")) - { + else if ( !_pico_stricmp( p->token,"ks" ) ) { picoColor_t color; - picoVec3_t v; + picoVec3_t v; /* pointer to current shader must be valid */ - if (curShader == NULL) + if ( curShader == NULL ) { _obj_mtl_error_return; + } /* get color vector */ - if (!_pico_parse_vec( p,v )) + if ( !_pico_parse_vec( p,v ) ) { _obj_mtl_error_return; + } /* scale to byte range */ color[ 0 ] = (picoByte_t)( v[ 0 ] * 255 ); @@ -485,63 +498,64 @@ static int _obj_mtl_load( picoModel_t *model ) /* _obj_load: * loads a wavefront obj model file. -*/ -static picoModel_t *_obj_load( PM_PARAMS_LOAD ) -{ + */ +static picoModel_t *_obj_load( PM_PARAMS_LOAD ){ TObjVertexData *vertexData = NULL; picoModel_t *model; picoSurface_t *curSurface = NULL; picoParser_t *p; - int allocated; - int entries; - int numVerts = 0; - int numNormals = 0; - int numUVs = 0; - int curVertex = 0; - int curFace = 0; + int allocated; + int entries; + int numVerts = 0; + int numNormals = 0; + int numUVs = 0; + int curVertex = 0; + int curFace = 0; int autoGroupNumber = 0; char autoGroupNameBuf[64]; -#define AUTO_GROUPNAME(namebuf) \ - sprintf(namebuf, "__autogroup_%d", autoGroupNumber++) -#define NEW_SURFACE(name) \ -{ \ - picoSurface_t *newSurface; \ - /* allocate a pico surface */ \ - newSurface = PicoNewSurface( model ); \ - if (newSurface == NULL) \ - _obj_error_return("Error allocating surface"); \ - /* reset face index for surface */ \ - curFace = 0; \ - /* if we can, assign the previous shader to this surface */ \ - if(curSurface) \ - PicoSetSurfaceShader(newSurface, curSurface->shader); \ - /* set ptr to current surface */ \ - curSurface = newSurface; \ - /* we use triangle meshes */ \ - PicoSetSurfaceType( newSurface,PICO_TRIANGLES ); \ - /* set surface name */ \ - PicoSetSurfaceName( newSurface,name ); \ -} +#define AUTO_GROUPNAME( namebuf ) \ + sprintf( namebuf, "__autogroup_%d", autoGroupNumber++ ) +#define NEW_SURFACE( name ) \ + { \ + picoSurface_t *newSurface; \ + /* allocate a pico surface */ \ + newSurface = PicoNewSurface( model ); \ + if ( newSurface == NULL ) { \ + _obj_error_return( "Error allocating surface" ); } \ + /* reset face index and vertex index for surface */ \ + curFace = 0; \ + curVertex = 0; \ + /* if we can, assign the previous shader to this surface */ \ + if ( curSurface ) { \ + PicoSetSurfaceShader( newSurface, curSurface->shader ); } \ + /* set ptr to current surface */ \ + curSurface = newSurface; \ + /* we use triangle meshes */ \ + PicoSetSurfaceType( newSurface,PICO_TRIANGLES ); \ + /* set surface name */ \ + PicoSetSurfaceName( newSurface,name ); \ + } /* helper */ -#define _obj_error_return(m) \ +#define _obj_error_return( m ) \ { \ - _pico_printf( PICO_ERROR,"%s in OBJ, line %d.",m,p->curLine); \ - _pico_free_parser( p ); \ + _pico_printf( PICO_ERROR, "%s in OBJ %s, line %d.", m, model->fileName, p->curLine ); \ + _pico_free_parser( p ); \ FreeObjVertexData( vertexData ); \ - PicoFreeModel( model ); \ + PicoFreeModel( model ); \ return NULL; \ } /* alllocate a new pico parser */ p = _pico_new_parser( (const picoByte_t *)buffer,bufSize ); - if (p == NULL) return NULL; + if ( p == NULL ) { + return NULL; + } /* create a new pico model */ model = PicoNewModel(); - if (model == NULL) - { + if ( model == NULL ) { _pico_free_parser( p ); return NULL; } @@ -556,123 +570,123 @@ static picoModel_t *_obj_load( PM_PARAMS_LOAD ) #endif /* parse obj line by line */ - while( 1 ) + while ( 1 ) { /* get first token on line */ - if (_pico_parse_first( p ) == NULL) + if ( _pico_parse_first( p ) == NULL ) { break; + } /* skip empty lines */ - if (p->token == NULL || !strlen( p->token )) + if ( p->token == NULL || !strlen( p->token ) ) { continue; + } /* skip comment lines */ - if (p->token[0] == '#') - { + if ( p->token[0] == '#' ) { _pico_parse_skip_rest( p ); continue; } /* vertex */ - if (!_pico_stricmp(p->token,"v")) - { + if ( !_pico_stricmp( p->token,"v" ) ) { TObjVertexData *data; picoVec3_t v; - vertexData = SizeObjVertexData( vertexData,numVerts+1,&entries,&allocated ); - if (vertexData == NULL) - _obj_error_return("Realloc of vertex data failed (1)"); + vertexData = SizeObjVertexData( vertexData,numVerts + 1,&entries,&allocated ); + if ( vertexData == NULL ) { + _obj_error_return( "Realloc of vertex data failed (1)" ); + } data = &vertexData[ numVerts++ ]; /* get and copy vertex */ - if (!_pico_parse_vec( p,v )) - _obj_error_return("Vertex parse error"); + if ( !_pico_parse_vec( p,v ) ) { + _obj_error_return( "Vertex parse error" ); + } _pico_copy_vec( v,data->v ); #ifdef DEBUG_PM_OBJ_EX - printf("Vertex: x: %f y: %f z: %f\n",v[0],v[1],v[2]); + printf( "Vertex: x: %f y: %f z: %f\n",v[0],v[1],v[2] ); #endif } /* uv coord */ - else if (!_pico_stricmp(p->token,"vt")) - { + else if ( !_pico_stricmp( p->token,"vt" ) ) { TObjVertexData *data; picoVec2_t coord; - vertexData = SizeObjVertexData( vertexData,numUVs+1,&entries,&allocated ); - if (vertexData == NULL) - _obj_error_return("Realloc of vertex data failed (2)"); + vertexData = SizeObjVertexData( vertexData,numUVs + 1,&entries,&allocated ); + if ( vertexData == NULL ) { + _obj_error_return( "Realloc of vertex data failed (2)" ); + } data = &vertexData[ numUVs++ ]; /* get and copy tex coord */ - if (!_pico_parse_vec2( p,coord )) - _obj_error_return("UV coord parse error"); + if ( !_pico_parse_vec2( p,coord ) ) { + _obj_error_return( "UV coord parse error" ); + } _pico_copy_vec2( coord,data->vt ); #ifdef DEBUG_PM_OBJ_EX - printf("TexCoord: u: %f v: %f\n",coord[0],coord[1]); + printf( "TexCoord: u: %f v: %f\n",coord[0],coord[1] ); #endif } /* vertex normal */ - else if (!_pico_stricmp(p->token,"vn")) - { + else if ( !_pico_stricmp( p->token,"vn" ) ) { TObjVertexData *data; picoVec3_t n; - vertexData = SizeObjVertexData( vertexData,numNormals+1,&entries,&allocated ); - if (vertexData == NULL) - _obj_error_return("Realloc of vertex data failed (3)"); + vertexData = SizeObjVertexData( vertexData,numNormals + 1,&entries,&allocated ); + if ( vertexData == NULL ) { + _obj_error_return( "Realloc of vertex data failed (3)" ); + } data = &vertexData[ numNormals++ ]; /* get and copy vertex normal */ - if (!_pico_parse_vec( p,n )) - _obj_error_return("Vertex normal parse error"); + if ( !_pico_parse_vec( p,n ) ) { + _obj_error_return( "Vertex normal parse error" ); + } _pico_copy_vec( n,data->vn ); #ifdef DEBUG_PM_OBJ_EX - printf("Normal: x: %f y: %f z: %f\n",n[0],n[1],n[2]); + printf( "Normal: x: %f y: %f z: %f\n",n[0],n[1],n[2] ); #endif } /* new group (for us this means a new surface) */ - else if (!_pico_stricmp(p->token,"g")) - { + else if ( !_pico_stricmp( p->token,"g" ) ) { char *groupName; /* get first group name (ignore 2nd,3rd,etc.) */ groupName = _pico_parse( p,0 ); - if (groupName == NULL || !strlen(groupName)) - { + if ( groupName == NULL || !strlen( groupName ) ) { /* some obj exporters feel like they don't need to */ /* supply a group name. so we gotta handle it here */ #if 1 strcpy( p->token,"default" ); groupName = p->token; #else - _obj_error_return("Invalid or missing group name"); + _obj_error_return( "Invalid or missing group name" ); #endif } - if(curFace == 0) - { + if ( curFace == 0 && curSurface != NULL ) { PicoSetSurfaceName( curSurface,groupName ); } else { - NEW_SURFACE(groupName); + NEW_SURFACE( groupName ); } #ifdef DEBUG_PM_OBJ_EX - printf("Group: '%s'\n",groupName); + printf( "Group: '%s'\n",groupName ); #endif } /* face (oh jesus, hopefully this will do the job right ;) */ - else if (!_pico_stricmp(p->token,"f")) - { + else if ( !_pico_stricmp( p->token,"f" ) ) { /* okay, this is a mess. some 3d apps seem to try being unique, */ /* hello cinema4d & 3d exploration, feel good today?, and save */ /* this crap in tons of different formats. gah, those screwed */ @@ -692,65 +706,63 @@ static picoModel_t *_obj_load( PM_PARAMS_LOAD ) int doubleslash = 0; int i; - if(curSurface == NULL) - { - _pico_printf( PICO_ERROR,"No group defined for faces, so creating an autoSurface in OBJ, line %d.",p->curLine); - AUTO_GROUPNAME(autoGroupNameBuf); - NEW_SURFACE(autoGroupNameBuf); + if ( curSurface == NULL ) { + _pico_printf( PICO_WARNING,"No group defined for faces, so creating an autoSurface in OBJ, line %d.",p->curLine ); + AUTO_GROUPNAME( autoGroupNameBuf ); + NEW_SURFACE( autoGroupNameBuf ); } /* group defs *must* come before faces */ - if (curSurface == NULL) - _obj_error_return("No group defined for faces"); + if ( curSurface == NULL ) { + _obj_error_return( "No group defined for faces" ); + } #ifdef DEBUG_PM_OBJ_EX - printf("Face: "); + printf( "Face: " ); #endif /* read vertex/uv/normal indices for the first three face */ /* vertices (cause we only support triangles) into 'i*[]' */ /* store the actual vertex/uv/normal data in three arrays */ /* called 'verts','coords' and 'normals'. */ - for (i=0; i<4; i++) + for ( i = 0; i < 4; i++ ) { char *str; /* get next vertex index string (different */ /* formats are handled below) */ str = _pico_parse( p,0 ); - if (str == NULL) - { + if ( str == NULL ) { /* just break for quads */ - if (i == 3) break; + if ( i == 3 ) { + break; + } /* error otherwise */ - _obj_error_return("Face parse error"); + _obj_error_return( "Face parse error" ); } /* if this is the fourth index string we're */ /* parsing we assume that we have a quad */ - if (i == 3) + if ( i == 3 ) { have_quad = 1; + } /* get slash count once */ - if (i == 0) - { + if ( i == 0 ) { slashcount = _pico_strchcount( str,'/' ); - doubleslash = strstr(str,"//") != NULL; + doubleslash = strstr( str,"//" ) != NULL; } /* handle format 'v//vn' */ - if (doubleslash && (slashcount == 2)) - { + if ( doubleslash && ( slashcount == 2 ) ) { has_v = has_vn = 1; sscanf( str,"%d//%d",&iv[ i ],&ivn[ i ] ); } /* handle format 'v/vt/vn' */ - else if (!doubleslash && (slashcount == 2)) - { + else if ( !doubleslash && ( slashcount == 2 ) ) { has_v = has_vt = has_vn = 1; sscanf( str,"%d/%d/%d",&iv[ i ],&ivt[ i ],&ivn[ i ] ); } /* handle format 'v/vt' (non-standard fuckage) */ - else if (!doubleslash && (slashcount == 1)) - { + else if ( !doubleslash && ( slashcount == 1 ) ) { has_v = has_vt = 1; sscanf( str,"%d/%d",&iv[ i ],&ivt[ i ] ); } @@ -762,29 +774,36 @@ static picoModel_t *_obj_load( PM_PARAMS_LOAD ) iv[ i ] = atoi( str ); /* either invalid face format or out of range */ - if (iv[ i ] == 0) - _obj_error_return("Invalid face format"); + if ( iv[ i ] == 0 ) { + _obj_error_return( "Invalid face format" ); + } } /* fix useless back references */ /* todo: check if this works as it is supposed to */ /* assign new indices */ - if (iv [ i ] < 0) iv [ i ] = (numVerts - iv [ i ]); - if (ivt[ i ] < 0) ivt[ i ] = (numUVs - ivt[ i ]); - if (ivn[ i ] < 0) ivn[ i ] = (numNormals - ivn[ i ]); + if ( iv [ i ] < 0 ) { + iv [ i ] = ( numVerts - iv [ i ] ); + } + if ( ivt[ i ] < 0 ) { + ivt[ i ] = ( numUVs - ivt[ i ] ); + } + if ( ivn[ i ] < 0 ) { + ivn[ i ] = ( numNormals - ivn[ i ] ); + } /* validate indices */ /* - commented out. index range checks will trigger - if (iv [ i ] < 1) iv [ i ] = 1; - if (ivt[ i ] < 1) ivt[ i ] = 1; - if (ivn[ i ] < 1) ivn[ i ] = 1; - */ + if (iv [ i ] < 1) iv [ i ] = 1; + if (ivt[ i ] < 1) ivt[ i ] = 1; + if (ivn[ i ] < 1) ivn[ i ] = 1; + */ /* set vertex origin */ - if (has_v) - { + if ( has_v ) { /* check vertex index range */ - if (iv[ i ] < 1 || iv[ i ] > numVerts) - _obj_error_return("Vertex index out of range"); + if ( iv[ i ] < 1 || iv[ i ] > numVerts ) { + _obj_error_return( "Vertex index out of range" ); + } /* get vertex data */ verts[ i ][ 0 ] = vertexData[ iv[ i ] - 1 ].v[ 0 ]; @@ -792,11 +811,11 @@ static picoModel_t *_obj_load( PM_PARAMS_LOAD ) verts[ i ][ 2 ] = vertexData[ iv[ i ] - 1 ].v[ 2 ]; } /* set vertex normal */ - if (has_vn) - { + if ( has_vn ) { /* check normal index range */ - if (ivn[ i ] < 1 || ivn[ i ] > numNormals) - _obj_error_return("Normal index out of range"); + if ( ivn[ i ] < 1 || ivn[ i ] > numNormals ) { + _obj_error_return( "Normal index out of range" ); + } /* get normal data */ normals[ i ][ 0 ] = vertexData[ ivn[ i ] - 1 ].vn[ 0 ]; @@ -804,11 +823,11 @@ static picoModel_t *_obj_load( PM_PARAMS_LOAD ) normals[ i ][ 2 ] = vertexData[ ivn[ i ] - 1 ].vn[ 2 ]; } /* set texture coordinate */ - if (has_vt) - { + if ( has_vt ) { /* check uv index range */ - if (ivt[ i ] < 1 || ivt[ i ] > numUVs) - _obj_error_return("UV coord index out of range"); + if ( ivt[ i ] < 1 || ivt[ i ] > numUVs ) { + _obj_error_return( "UV coord index out of range" ); + } /* get uv coord data */ coords[ i ][ 0 ] = vertexData[ ivt[ i ] - 1 ].vt[ 0 ]; @@ -816,80 +835,79 @@ static picoModel_t *_obj_load( PM_PARAMS_LOAD ) coords[ i ][ 1 ] = -coords[ i ][ 1 ]; } #ifdef DEBUG_PM_OBJ_EX - printf("(%4d",iv[ i ]); - if (has_vt) printf(" %4d",ivt[ i ]); - if (has_vn) printf(" %4d",ivn[ i ]); - printf(") "); + printf( "(%4d",iv[ i ] ); + if ( has_vt ) { + printf( " %4d",ivt[ i ] ); + } + if ( has_vn ) { + printf( " %4d",ivn[ i ] ); + } + printf( ") " ); #endif } #ifdef DEBUG_PM_OBJ_EX - printf("\n"); + printf( "\n" ); #endif /* now that we have extracted all the indices and have */ /* read the actual data we need to assign all the crap */ /* to our current pico surface */ - if (has_v) - { + if ( has_v ) { int max = 3; - if (have_quad) max = 4; + if ( have_quad ) { + max = 4; + } /* assign all surface information */ - for (i=0; itoken,"usemtl")) - { + else if ( !_pico_stricmp( p->token,"usemtl" ) ) { picoShader_t *shader; char *name; /* get material name */ name = _pico_parse( p,0 ); - if(curFace != 0 || curSurface == NULL) - { - _pico_printf( PICO_ERROR,"No group defined for usemtl, so creating an autoSurface in OBJ, line %d.",p->curLine); - AUTO_GROUPNAME(autoGroupNameBuf); - NEW_SURFACE(autoGroupNameBuf); + if ( curFace != 0 || curSurface == NULL ) { + _pico_printf( PICO_WARNING,"No group defined for usemtl, so creating an autoSurface in OBJ, line %d.",p->curLine ); + AUTO_GROUPNAME( autoGroupNameBuf ); + NEW_SURFACE( autoGroupNameBuf ); } /* validate material name */ - if (name == NULL || !strlen(name)) - { - _pico_printf( PICO_ERROR,"Missing material name in OBJ, line %d.",p->curLine); + if ( name == NULL || !strlen( name ) ) { + _pico_printf( PICO_ERROR,"Missing material name in OBJ, line %d.",p->curLine ); } else { shader = PicoFindShader( model, name, 1 ); - if (shader == NULL) - { - _pico_printf( PICO_ERROR,"Undefined material name in OBJ, line %d. Making a default shader.",p->curLine); + if ( shader == NULL ) { + _pico_printf( PICO_WARNING,"Undefined material name in OBJ, line %d. Making a default shader.",p->curLine ); /* create a new pico shader */ shader = PicoNewShader( model ); - if (shader != NULL) - { + if ( shader != NULL ) { PicoSetShaderName( shader,name ); PicoSetShaderMapName( shader,name ); PicoSetSurfaceShader( curSurface, shader ); @@ -915,15 +933,15 @@ static picoModel_t *_obj_load( PM_PARAMS_LOAD ) /* pico file format module definition */ const picoModule_t picoModuleOBJ = { - "0.6-b", /* module version string */ - "Wavefront ASCII", /* module display name */ - "seaw0lf", /* author's name */ - "2002 seaw0lf", /* module copyright */ + "0.6-b", /* module version string */ + "Wavefront ASCII", /* module display name */ + "seaw0lf", /* author's name */ + "2002 seaw0lf", /* module copyright */ { - "obj",NULL,NULL,NULL /* default extensions to use */ + "obj",NULL,NULL,NULL /* default extensions to use */ }, - _obj_canload, /* validation routine */ - _obj_load, /* load routine */ - NULL, /* save validation routine */ - NULL /* save routine */ + _obj_canload, /* validation routine */ + _obj_load, /* load routine */ + NULL, /* save validation routine */ + NULL /* save routine */ };