* picomodel: do some guessings about shader paths to handle more cases out of the box; ones are based on material and diffuse map names:

name w/o path: assume textures are in the folder, where model file is
		absolute path or with ..: try to cut at "/models/" or "/textures/" (as if leading to game folders); do previous case, if not
		strip extensions and turn slashes to forward ones anytime
	* picomodel::obj: fix diffuse map paths loading from .mtl
This commit is contained in:
Garux 2018-09-29 14:39:10 +03:00
parent cf885ea4ea
commit 86904473bb
12 changed files with 85 additions and 75 deletions

View File

@ -694,6 +694,60 @@ int _pico_getline( char *buf, int bufsize, char *dest, int destsize ){
return pos; return pos;
} }
/* expecting fileName to be relative vfs model path */
void _pico_deduce_shadername( const char* fileName, const char* srcName, picoShader_t* shader ){
if( srcName == NULL || fileName == NULL )
return;
char name[strlen( srcName ) + 1];
strcpy( name, srcName );
_pico_unixify( name );
_pico_setfext( name, NULL );
char path[strlen( fileName ) + strlen( name ) + 1];
_pico_nofname( fileName, path, strlen( fileName ) + strlen( name ) + 1 );
_pico_unixify( path );
if( !strchr( name , '/' ) ){ /* texture is likely in the folder, where model is */
strcat( path, name );
}
else if( name[0] == '/' || ( name[0] != '\0' && name[1] == ':' ) || strstr( name, ".." ) ){ /* absolute path or with .. */
const char* p = name;
for (; *p != '\0'; ++p )
if ( _pico_strnicmp( p, "/models/", 8 ) == 0 || _pico_strnicmp( p, "/textures/", 10 ) == 0 )
break;
if( *p != '\0' ){
strcpy( path, p + 1 );
}
else{
p = _pico_nopath( name );
strcat( path, p );
}
}
else{
PicoSetShaderName( shader, name );
return;
}
_pico_printf( PICO_NORMAL, "PICO: substituting shader name: %s -> %s", srcName, path );
PicoSetShaderName( shader, path );
}
/* deduce shadernames from bitmap or shadername paths */
void _pico_deduce_shadernames( picoModel_t *model ){
for ( int i = 0; i < model->numShaders; ++i ){
/* skip null shaders */
if ( model->shader[i] == NULL )
continue;
const char* mapname = model->shader[i]->mapName;
const char* shadername = model->shader[i]->name;
if( mapname && *mapname )
_pico_deduce_shadername( model->fileName, mapname, model->shader[i] );
else if( shadername && *shadername )
_pico_deduce_shadername( model->fileName, shadername, model->shader[i] );
}
}
/* _pico_parse_skip_white: /* _pico_parse_skip_white:
* skips white spaces in current pico parser, sets *hasLFs * skips white spaces in current pico parser, sets *hasLFs
* to 1 if linefeeds were skipped, and either returns the * to 1 if linefeeds were skipped, and either returns the

View File

@ -138,6 +138,7 @@ const char *_pico_nopath( const char *path );
char *_pico_setfext( char *path, const char *ext ); char *_pico_setfext( char *path, const char *ext );
int _pico_getline( char *buf, int bufsize, char *dest, int destsize ); int _pico_getline( char *buf, int bufsize, char *dest, int destsize );
char *_pico_strlwr( char *str ); char *_pico_strlwr( char *str );
void _pico_deduce_shadernames( picoModel_t *model );
/* vectors */ /* vectors */
void _pico_zero_bounds( picoVec3_t mins, picoVec3_t maxs ); void _pico_zero_bounds( picoVec3_t mins, picoVec3_t maxs );

View File

@ -180,6 +180,8 @@ picoModel_t *PicoModuleLoadModel( const picoModule_t* pm, const char* fileName,
} }
} }
_pico_deduce_shadernames( model );
return model; return model;
} }
@ -491,16 +493,13 @@ void PicoFreeShader( picoShader_t *shader ){
*/ */
picoShader_t *PicoFindShader( picoModel_t *model, char *name, int caseSensitive ){ picoShader_t *PicoFindShader( picoModel_t *model, char *name, int caseSensitive ){
int i;
/* sanity checks */ /* sanity checks */
if ( model == NULL || name == NULL ) { /* sea: null name fix */ if ( model == NULL || name == NULL ) { /* sea: null name fix */
return NULL; return NULL;
} }
/* walk list */ /* walk list */
for ( i = 0; i < model->numShaders; i++ ) for ( int i = 0; i < model->numShaders; i++ )
{ {
/* skip null shaders or shaders with null names */ /* skip null shaders or shaders with null names */
if ( model->shader[ i ] == NULL || if ( model->shader[ i ] == NULL ||

View File

@ -405,17 +405,15 @@ static int GetMeshShader( T3dsLoaderPers *pers ){
/* we've found a matching shader */ /* we've found a matching shader */
if ( ( shader != NULL ) && pers->surface ) { if ( ( shader != NULL ) && pers->surface ) {
char mapName[1024 + 1];
char *mapNamePtr;
memset( mapName,0,sizeof( mapName ) );
/* get ptr to shader's map name */ /* get ptr to shader's map name */
mapNamePtr = PicoGetShaderMapName( shader ); const char* mapNamePtr = PicoGetShaderMapName( shader );
/* we have a valid map name ptr */ /* we have a valid map name ptr */
if ( mapNamePtr != NULL ) { if ( mapNamePtr != NULL ) {
#if 0
char temp[128]; char temp[128];
const char *name; const char *name;
char mapName[1024 + 1];
memset( mapName,0,sizeof( mapName ) );
/* copy map name to local buffer */ /* copy map name to local buffer */
strcpy( mapName,mapNamePtr ); strcpy( mapName,mapNamePtr );
@ -425,7 +423,7 @@ static int GetMeshShader( T3dsLoaderPers *pers ){
strncpy( temp, name, sizeof( temp ) ); strncpy( temp, name, sizeof( temp ) );
/* remove file extension */ /* remove file extension */
/* name = _pico_setfext( name,"" ); */ /* name = _pico_setfext( name, NULL ); */
/* assign default name if no name available */ /* assign default name if no name available */
if ( strlen( temp ) < 1 ) { if ( strlen( temp ) < 1 ) {
@ -438,7 +436,7 @@ static int GetMeshShader( T3dsLoaderPers *pers ){
/* set shader name */ /* set shader name */
/* PicoSetShaderName( shader,mapName ); */ /* ydnar: this will screw up the named shader */ /* PicoSetShaderName( shader,mapName ); */ /* ydnar: this will screw up the named shader */
#endif
/* set surface's shader index */ /* set surface's shader index */
PicoSetSurfaceShader( pers->surface, shader ); PicoSetSurfaceShader( pers->surface, shader );
@ -732,7 +730,7 @@ static picoModel_t *_3ds_load( PM_PARAMS_LOAD ){
/* get model's base name (eg. jeep from c:\models\jeep.3ds) */ /* get model's base name (eg. jeep from c:\models\jeep.3ds) */
memset( basename,0,sizeof( basename ) ); memset( basename,0,sizeof( basename ) );
strncpy( basename,_pico_nopath( fileName ),sizeof( basename ) ); strncpy( basename,_pico_nopath( fileName ),sizeof( basename ) );
_pico_setfext( basename,"" ); _pico_setfext( basename, NULL );
/* initialize persistant vars (formerly static) */ /* initialize persistant vars (formerly static) */
pers.model = model; pers.model = model;

View File

@ -460,17 +460,6 @@ static void _ase_submit_triangles( picoModel_t* model, aseMaterial_t* materials,
} }
} }
static void shadername_convert( char* shaderName ){
/* unix-style path separators */
char* s = shaderName;
for (; *s != '\0'; ++s )
{
if ( *s == '\\' ) {
*s = '/';
}
}
}
/* _ase_load: /* _ase_load:
* loads a 3dsmax ase model file. * loads a 3dsmax ase model file.
@ -887,7 +876,7 @@ static picoModel_t *_ase_load( PM_PARAMS_LOAD ){
if ( level == subMaterialLevel ) { if ( level == subMaterialLevel ) {
/* set material name */ /* set material name */
_pico_first_token( materialName ); _pico_first_token( materialName );
shadername_convert( materialName ); _pico_unixify( materialName );
PicoSetShaderName( shader, materialName ); PicoSetShaderName( shader, materialName );
/* set shader's transparency */ /* set shader's transparency */
@ -1077,7 +1066,7 @@ static picoModel_t *_ase_load( PM_PARAMS_LOAD ){
} }
/* set material name */ /* set material name */
shadername_convert( materialName ); _pico_unixify( materialName );
PicoSetShaderName( shader,materialName ); PicoSetShaderName( shader,materialName );
/* set shader's transparency */ /* set shader's transparency */
@ -1101,34 +1090,6 @@ static picoModel_t *_ase_load( PM_PARAMS_LOAD ){
/* set material map name */ /* set material map name */
PicoSetShaderMapName( shader, mapname ); PicoSetShaderMapName( shader, mapname );
/* extract shadername from bitmap path */
if ( mapname != NULL ) {
char* p = mapname;
/* convert to shader-name format */
shadername_convert( mapname );
{
/* remove extension */
char* last_period = strrchr( p, '.' );
if ( last_period != NULL ) {
*last_period = '\0';
}
}
/* find shader path */
for (; *p != '\0'; ++p )
{
if ( _pico_strnicmp( p, "models/", 7 ) == 0 || _pico_strnicmp( p, "textures/", 9 ) == 0 ) {
break;
}
}
if ( *p != '\0' ) {
/* set material name */
PicoSetShaderName( shader,p );
}
}
/* this is just a material with 1 submaterial */ /* this is just a material with 1 submaterial */
subMaterial = _ase_add_submaterial( &materials, index, 0, shader ); subMaterial = _ase_add_submaterial( &materials, index, 0, shader );
} }

View File

@ -377,7 +377,7 @@ static picoModel_t *_fm_load( PM_PARAMS_LOAD ){
#endif #endif
// detox Skin name // detox Skin name
_pico_setfext( skinname, "" ); _pico_setfext( skinname, NULL );
_pico_unixify( skinname ); _pico_unixify( skinname );
/* create new pico model */ /* create new pico model */

View File

@ -236,7 +236,7 @@ static picoModel_t *_lwo_load( PM_PARAMS_LOAD ){
/* detox and set shader name */ /* detox and set shader name */
strncpy( name, surface->name, sizeof( name ) ); strncpy( name, surface->name, sizeof( name ) );
_pico_first_token( name ); _pico_first_token( name );
_pico_setfext( name, "" ); _pico_setfext( name, NULL );
_pico_unixify( name ); _pico_unixify( name );
PicoSetShaderName( picoShader, name ); PicoSetShaderName( picoShader, name );

View File

@ -432,7 +432,7 @@ static picoModel_t *_md2_load( PM_PARAMS_LOAD ){
_pico_printf( PICO_VERBOSE,"Skins: %d Verts: %d STs: %d Triangles: %d Frames: %d\nSkin Name \"%s\"\n", md2->numSkins, md2->numXYZ, md2->numST, md2->numTris, md2->numFrames, &skinname ); _pico_printf( PICO_VERBOSE,"Skins: %d Verts: %d STs: %d Triangles: %d Frames: %d\nSkin Name \"%s\"\n", md2->numSkins, md2->numXYZ, md2->numST, md2->numTris, md2->numFrames, &skinname );
// detox Skin name // detox Skin name
_pico_setfext( skinname, "" ); _pico_setfext( skinname, NULL );
_pico_unixify( skinname ); _pico_unixify( skinname );
/* create new pico model */ /* create new pico model */

View File

@ -347,7 +347,7 @@ static picoModel_t *_md3_load( PM_PARAMS_LOAD ){
/* detox and set shader name */ /* detox and set shader name */
shader = (md3Shader_t*) ( (picoByte_t*) surface + surface->ofsShaders ); shader = (md3Shader_t*) ( (picoByte_t*) surface + surface->ofsShaders );
_pico_setfext( shader->name, "" ); _pico_setfext( shader->name, NULL );
_pico_unixify( shader->name ); _pico_unixify( shader->name );
PicoSetShaderName( picoShader, shader->name ); PicoSetShaderName( picoShader, shader->name );

View File

@ -647,7 +647,7 @@ static picoModel_t *_mdc_load( PM_PARAMS_LOAD ){
/* detox and set shader name */ /* detox and set shader name */
shader = (mdcShader_t*) ( (picoByte_t*) surface + surface->ofsShaders ); shader = (mdcShader_t*) ( (picoByte_t*) surface + surface->ofsShaders );
_pico_setfext( shader->name, "" ); _pico_setfext( shader->name, NULL );
_pico_unixify( shader->name ); _pico_unixify( shader->name );
PicoSetShaderName( picoShader, shader->name ); PicoSetShaderName( picoShader, shader->name );

View File

@ -232,9 +232,12 @@ static int _obj_mtl_load( picoModel_t *model ){
return 0; 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 \ #define _obj_mtl_error_return \
{ \ { \
_obj_mtl_print_fail; \
_pico_free_parser( p ); \ _pico_free_parser( p ); \
_pico_free_file( mtlBuffer ); \ _pico_free_file( mtlBuffer ); \
_pico_free( fileName ); \ _pico_free( fileName ); \
@ -254,9 +257,11 @@ static int _obj_mtl_load( picoModel_t *model ){
/* check result */ /* check result */
if ( mtlBufSize == 0 ) { if ( mtlBufSize == 0 ) {
_obj_mtl_print_fail;
return 1; /* file is empty: no error */ return 1; /* file is empty: no error */
} }
if ( mtlBufSize < 0 ) { if ( mtlBufSize < 0 ) {
_obj_mtl_print_fail;
return 0; /* load failed: error */ return 0; /* load failed: error */
} }
@ -273,7 +278,6 @@ static int _obj_mtl_load( picoModel_t *model ){
if ( _pico_parse( p,1 ) == NULL ) { if ( _pico_parse( p,1 ) == NULL ) {
break; break;
} }
#if 1
/* skip empty lines */ /* skip empty lines */
if ( p->token == NULL || !strlen( p->token ) ) { if ( p->token == NULL || !strlen( p->token ) ) {
@ -313,7 +317,6 @@ static int _obj_mtl_load( picoModel_t *model ){
/* diffuse map name */ /* diffuse map name */
else if ( !_pico_stricmp( p->token,"map_kd" ) ) { else if ( !_pico_stricmp( p->token,"map_kd" ) ) {
char *mapName; char *mapName;
picoShader_t *shader;
/* pointer to current shader must be valid */ /* pointer to current shader must be valid */
if ( curShader == NULL ) { if ( curShader == NULL ) {
@ -328,13 +331,8 @@ static int _obj_mtl_load( picoModel_t *model ){
_pico_printf( PICO_ERROR,"Missing material map name in MTL, line %d.",p->curLine ); _pico_printf( PICO_ERROR,"Missing material map name in MTL, line %d.",p->curLine );
_obj_mtl_error_return; _obj_mtl_error_return;
} }
/* create a new pico shader */
shader = PicoNewShader( model );
if ( shader == NULL ) {
_obj_mtl_error_return;
}
/* set shader map name */ /* set shader map name */
PicoSetShaderMapName( shader,mapName ); PicoSetShaderMapName( curShader, mapName );
} }
/* dissolve factor (pseudo transparency 0..1) */ /* dissolve factor (pseudo transparency 0..1) */
/* where 0 means 100% transparent and 1 means opaque */ /* where 0 means 100% transparent and 1 means opaque */
@ -486,12 +484,12 @@ static int _obj_mtl_load( picoModel_t *model ){
/* set specular color */ /* set specular color */
PicoSetShaderSpecularColor( curShader,color ); PicoSetShaderSpecularColor( curShader,color );
} }
#endif
/* skip rest of line */ /* skip rest of line */
_pico_parse_skip_rest( p ); _pico_parse_skip_rest( p );
} }
/* free parser, file buffer, and file name */ /* free parser, file buffer, and file name */
_obj_mtl_print_ok;
_pico_free_parser( p ); _pico_free_parser( p );
_pico_free_file( mtlBuffer ); _pico_free_file( mtlBuffer );
_pico_free( fileName ); _pico_free( fileName );
@ -567,10 +565,8 @@ static picoModel_t *_obj_load( PM_PARAMS_LOAD ){
PicoSetModelName( model,fileName ); PicoSetModelName( model,fileName );
PicoSetModelFileName( model,fileName ); PicoSetModelFileName( model,fileName );
/* try loading the materials; we don't handle the result */ /* try loading the materials */
#if 1
_obj_mtl_load( model ); _obj_mtl_load( model );
#endif
/* parse obj line by line */ /* parse obj line by line */
while ( 1 ) while ( 1 )
@ -908,7 +904,7 @@ static picoModel_t *_obj_load( PM_PARAMS_LOAD ){
{ {
shader = PicoFindShader( model, name, 1 ); shader = PicoFindShader( model, name, 1 );
if ( shader == NULL ) { if ( shader == NULL ) {
_pico_printf( PICO_WARNING,"Undefined material name in OBJ, line %d. Making a default shader.",p->curLine ); _pico_printf( PICO_WARNING, "Undefined material name \"%s\" in OBJ, line %d. Making a default shader.", name, p->curLine );
/* create a new pico shader */ /* create a new pico shader */
shader = PicoNewShader( model ); shader = PicoNewShader( model );
@ -927,6 +923,7 @@ static picoModel_t *_obj_load( PM_PARAMS_LOAD ){
/* skip unparsed rest of line and continue */ /* skip unparsed rest of line and continue */
_pico_parse_skip_rest( p ); _pico_parse_skip_rest( p );
} }
/* free memory used by temporary vertexdata */ /* free memory used by temporary vertexdata */
FreeObjVertexData( vertexData ); FreeObjVertexData( vertexData );

View File

@ -502,7 +502,7 @@ static picoModel_t *_terrain_load( PM_PARAMS_LOAD ){
} }
/* detox and set shader name */ /* detox and set shader name */
_pico_setfext( shader, "" ); _pico_setfext( shader, NULL );
_pico_unixify( shader ); _pico_unixify( shader );
PicoSetShaderName( picoShader, shader ); PicoSetShaderName( picoShader, shader );
_pico_free( shader ); _pico_free( shader );