From 2d0248ed96aa968179e55a08849a493e7257d65d Mon Sep 17 00:00:00 2001 From: Rudolf Polzer Date: Wed, 23 Feb 2011 10:35:42 +0100 Subject: [PATCH] fixes to .obj format in picomodel from NetRadiant --- libs/picomodel/pm_obj.c | 121 +++++++++++++++++++++++++++++++--------- 1 file changed, 95 insertions(+), 26 deletions(-) diff --git a/libs/picomodel/pm_obj.c b/libs/picomodel/pm_obj.c index 95bc68a5..a3c18d9b 100644 --- a/libs/picomodel/pm_obj.c +++ b/libs/picomodel/pm_obj.c @@ -87,7 +87,7 @@ static int _obj_canload( PM_PARAMS_CANLOAD ) /* appearing at the beginning of wavefront objects */ /* alllocate a new pico parser */ - p = _pico_new_parser( (picoByte_t *)buffer,bufSize ); + p = _pico_new_parser( (const picoByte_t *)buffer,bufSize ); if (p == NULL) return PICO_PMV_ERROR_MEMORY; @@ -215,10 +215,9 @@ static void FreeObjVertexData( TObjVertexData *vertexData ) } } -#if 0 static int _obj_mtl_load( picoModel_t *model ) { - //picoShader_t *curShader = NULL; + picoShader_t *curShader = NULL; picoParser_t *p; picoByte_t *mtlBuffer; int mtlBufSize; @@ -241,7 +240,7 @@ static int _obj_mtl_load( picoModel_t *model ) return 0; \ } /* alloc copy of model file name */ - fileName = _pico_clone_alloc( model->fileName,-1 ); + fileName = _pico_clone_alloc( model->fileName ); if (fileName == NULL) return 0; @@ -308,6 +307,7 @@ static int _obj_mtl_load( picoModel_t *model ) else if (!_pico_stricmp(p->token,"map_kd")) { char *mapName; + picoShader_t *shader; /* pointer to current shader must be valid */ if (curShader == NULL) @@ -322,6 +322,10 @@ static int _obj_mtl_load( picoModel_t *model ) _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) + _obj_mtl_error_return; /* set shader map name */ PicoSetShaderMapName( shader,mapName ); } @@ -478,7 +482,6 @@ static int _obj_mtl_load( picoModel_t *model ) /* return with success */ return 1; } -#endif /* _obj_load: * loads a wavefront obj model file. @@ -497,8 +500,33 @@ static picoModel_t *_obj_load( PM_PARAMS_LOAD ) 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 ); \ +} + /* 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 ); \ @@ -507,7 +535,7 @@ static picoModel_t *_obj_load( PM_PARAMS_LOAD ) return NULL; \ } /* alllocate a new pico parser */ - p = _pico_new_parser( (picoByte_t *)buffer,bufSize ); + p = _pico_new_parser( (const picoByte_t *)buffer,bufSize ); if (p == NULL) return NULL; /* create a new pico model */ @@ -523,7 +551,7 @@ static picoModel_t *_obj_load( PM_PARAMS_LOAD ) PicoSetModelFileName( model,fileName ); /* try loading the materials; we don't handle the result */ -#if 0 +#if 1 _obj_mtl_load( model ); #endif @@ -613,7 +641,6 @@ static picoModel_t *_obj_load( PM_PARAMS_LOAD ) /* new group (for us this means a new surface) */ else if (!_pico_stricmp(p->token,"g")) { - picoSurface_t *newSurface; char *groupName; /* get first group name (ignore 2nd,3rd,etc.) */ @@ -629,22 +656,15 @@ static picoModel_t *_obj_load( PM_PARAMS_LOAD ) _obj_error_return("Invalid or missing group name"); #endif } - /* allocate a pico surface */ - newSurface = PicoNewSurface( model ); - if (newSurface == NULL) - _obj_error_return("Error allocating surface"); - /* reset face index for surface */ - curFace = 0; - - /* set ptr to current surface */ - curSurface = newSurface; - - /* we use triangle meshes */ - PicoSetSurfaceType( newSurface,PICO_TRIANGLES ); - - /* set surface name */ - PicoSetSurfaceName( newSurface,groupName ); + if(curFace == 0) + { + PicoSetSurfaceName( curSurface,groupName ); + } + else + { + NEW_SURFACE(groupName); + } #ifdef DEBUG_PM_OBJ_EX printf("Group: '%s'\n",groupName); @@ -668,10 +688,17 @@ static picoModel_t *_obj_load( PM_PARAMS_LOAD ) int ivt[ 4 ], has_vt = 0; int ivn[ 4 ], has_vn = 0; int have_quad = 0; - int slashcount; - int doubleslash; + int slashcount = 0; + 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); + } + /* group defs *must* come before faces */ if (curSurface == NULL) _obj_error_return("No group defined for faces"); @@ -832,6 +859,48 @@ static picoModel_t *_obj_load( PM_PARAMS_LOAD ) curVertex += max; } } + 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); + } + + /* validate material name */ + 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); + + /* create a new pico shader */ + shader = PicoNewShader( model ); + if (shader != NULL) + { + PicoSetShaderName( shader,name ); + PicoSetShaderMapName( shader,name ); + PicoSetSurfaceShader( curSurface, shader ); + } + } + else + { + PicoSetSurfaceShader( curSurface, shader ); + } + } + } /* skip unparsed rest of line and continue */ _pico_parse_skip_rest( p ); } -- 2.39.2