/* -----------------------------------------------------------------------------
-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
/* 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 */
/* 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 );
* 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;
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;
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 */
+ /* helpers */
+ #define _obj_mtl_print_ok _pico_printf( PICO_NORMAL, "PICO: loading %s...OK\n", fileName )
+ #define _obj_mtl_print_fail _pico_printf( PICO_WARNING, "PICO: loading %s...FAIL\n", fileName )
#define _obj_mtl_error_return \
{ \
- _pico_free_parser( p ); \
+ _obj_mtl_print_fail; \
+ _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" );
_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 ) {
+ _obj_mtl_print_fail;
+ return 1; /* file is empty: no error */
+ }
+ if ( mtlBufSize < 0 ) {
+ _obj_mtl_print_fail;
+ 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;
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 %s, line %d.",fileName,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 );
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 %s, line %d.",fileName,p->curLine );
_obj_mtl_error_return;
}
- /* create a new pico shader */
- shader = PicoNewShader( model );
- if (shader == NULL)
- _obj_mtl_error_return;
/* set shader map name */
- PicoSetShaderMapName( shader,mapName );
+ PicoSetShaderMapName( curShader, 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 );
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,
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 );
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 );
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 );
/* set specular color */
PicoSetShaderSpecularColor( curShader,color );
}
-#endif
/* skip rest of line */
_pico_parse_skip_rest( p );
}
/* free parser, file buffer, and file name */
+ _obj_mtl_print_ok;
_pico_free_parser( p );
_pico_free_file( mtlBuffer );
_pico_free( fileName );
/* _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;
}
PicoSetModelName( model,fileName );
PicoSetModelFileName( model,fileName );
- /* try loading the materials; we don't handle the result */
-#if 1
+ /* try loading the materials */
_obj_mtl_load( model );
-#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 */
int doubleslash = 0;
int i;
- 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);
+ if ( curSurface == NULL ) {
+ _pico_printf( PICO_WARNING,"No group defined for faces, so creating an autoSurface in OBJ %s, line %d.",model->fileName,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 ] );
}
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 ];
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 ];
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 ];
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; i<max; i++)
+ for ( i = 0; i < max; i++ )
{
- /*if( has_v )*/ PicoSetSurfaceXYZ ( curSurface, (curVertex + i), verts [ i ] );
- /*if( has_vt )*/ PicoSetSurfaceST ( curSurface,0,(curVertex + i), coords [ i ] );
- /*if( has_vn )*/ PicoSetSurfaceNormal( curSurface, (curVertex + i), normals[ i ] );
+ /*if( has_v )*/ PicoSetSurfaceXYZ( curSurface, ( curVertex + i ), verts [ i ] );
+ /*if( has_vt )*/ PicoSetSurfaceST( curSurface,0,( curVertex + i ), coords [ i ] );
+ /*if( has_vn )*/ PicoSetSurfaceNormal( curSurface, ( curVertex + i ), normals[ i ] );
}
/* add our triangle (A B C) */
- PicoSetSurfaceIndex( curSurface,(curFace * 3 + 2),(picoIndex_t)( curVertex + 0 ) );
- PicoSetSurfaceIndex( curSurface,(curFace * 3 + 1),(picoIndex_t)( curVertex + 1 ) );
- PicoSetSurfaceIndex( curSurface,(curFace * 3 + 0),(picoIndex_t)( curVertex + 2 ) );
+ PicoSetSurfaceIndex( curSurface,( curFace * 3 + 2 ),(picoIndex_t)( curVertex + 0 ) );
+ PicoSetSurfaceIndex( curSurface,( curFace * 3 + 1 ),(picoIndex_t)( curVertex + 1 ) );
+ PicoSetSurfaceIndex( curSurface,( curFace * 3 + 0 ),(picoIndex_t)( curVertex + 2 ) );
curFace++;
/* if we don't have a simple triangle, but a quad... */
- if (have_quad)
- {
+ if ( have_quad ) {
/* we have to add another triangle (2nd half of quad which is A C D) */
- PicoSetSurfaceIndex( curSurface,(curFace * 3 + 2),(picoIndex_t)( curVertex + 0 ) );
- PicoSetSurfaceIndex( curSurface,(curFace * 3 + 1),(picoIndex_t)( curVertex + 2 ) );
- PicoSetSurfaceIndex( curSurface,(curFace * 3 + 0),(picoIndex_t)( curVertex + 3 ) );
+ PicoSetSurfaceIndex( curSurface,( curFace * 3 + 2 ),(picoIndex_t)( curVertex + 0 ) );
+ PicoSetSurfaceIndex( curSurface,( curFace * 3 + 1 ),(picoIndex_t)( curVertex + 2 ) );
+ PicoSetSurfaceIndex( curSurface,( curFace * 3 + 0 ),(picoIndex_t)( curVertex + 3 ) );
curFace++;
}
/* increase vertex count */
curVertex += max;
}
}
- else if (!_pico_stricmp(p->token,"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_WARNING,"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 %s, line %d.",model->fileName,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 %s, line %d.",model->fileName,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 \"%s\" in OBJ, line %d. Making a default shader.", name, 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 );
/* skip unparsed rest of line and continue */
_pico_parse_skip_rest( p );
}
+
/* free memory used by temporary vertexdata */
FreeObjVertexData( vertexData );
/* 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 */
};