* picomodel: do some guessings about shader paths to handle more cases out of the...
authorGarux <garux@mail.ru>
Sat, 29 Sep 2018 11:39:10 +0000 (14:39 +0300)
committerThomas Debesse <dev@illwieckz.net>
Tue, 27 Apr 2021 01:45:03 +0000 (03:45 +0200)
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

12 files changed:
libs/picomodel/picointernal.c
libs/picomodel/picointernal.h
libs/picomodel/picomodel.c
libs/picomodel/pm_3ds.c
libs/picomodel/pm_ase.c
libs/picomodel/pm_fm.c
libs/picomodel/pm_lwo.c
libs/picomodel/pm_md2.c
libs/picomodel/pm_md3.c
libs/picomodel/pm_mdc.c
libs/picomodel/pm_obj.c
libs/picomodel/pm_terrain.c

index 19950c1deeaae55300de80e05580a04cbd8092d9..614d7c53b04a7ee43a9b6e9b935d7dfa7f99aa59 100644 (file)
@@ -694,6 +694,60 @@ int _pico_getline( char *buf, int bufsize, char *dest, int destsize ){
        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:
  *  skips white spaces in current pico parser, sets *hasLFs
  *  to 1 if linefeeds were skipped, and either returns the
index 4ffae1b5370faa883f0d6e22f51addb5f7c5439d..312cc64324ca7d99a08adb23ffb36eec22794759 100644 (file)
@@ -136,10 +136,11 @@ void            _pico_printf( int level, const char *format, ... );
 const char      *_pico_stristr( const char *str, const char *substr );
 void            _pico_unixify( char *path );
 int             _pico_nofname( const char *path, char *dest, int destSize );
-const char *_pico_nopath( const char *path );
+const char      *_pico_nopath( const char *path );
 char            *_pico_setfext( char *path, const char *ext );
 int             _pico_getline( char *buf, int bufsize, char *dest, int destsize );
 char            *_pico_strlwr( char *str );
+void            _pico_deduce_shadernames( picoModel_t *model );
 
 /* vectors */
 void            _pico_zero_bounds( picoVec3_t mins, picoVec3_t maxs );
index 79655ce842689a4eaf7b4db4a746184f7e57ae60..7d53683ae535688b2556f5bbd3a2fd65718e425a 100644 (file)
@@ -173,6 +173,8 @@ picoModel_t *PicoModuleLoadModel( const picoModule_t* pm, const char* fileName,
                        }
                }
 
+               _pico_deduce_shadernames( model );
+
                return model;
        }
 
@@ -484,16 +486,13 @@ void PicoFreeShader( picoShader_t *shader ){
  */
 
 picoShader_t *PicoFindShader( picoModel_t *model, char *name, int caseSensitive ){
-       int i;
-
-
        /* sanity checks */
        if ( model == NULL || name == NULL ) { /* sea: null name fix */
                return NULL;
        }
 
        /* 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 */
                if ( model->shader[ i ] == NULL ||
index b802814accbf2205d1fcade246a91f0331369bff..c6ac1531eb8b656e7c8592ed7c23339cd82282a0 100644 (file)
@@ -400,17 +400,15 @@ static int GetMeshShader( T3dsLoaderPers *pers ){
 
        /* we've found a matching shader */
        if ( ( shader != NULL ) && pers->surface ) {
-               char mapName[1024 + 1];
-               char *mapNamePtr;
-               memset( mapName,0,sizeof( mapName ) );
-
                /* get ptr to shader's map name */
-               mapNamePtr = PicoGetShaderMapName( shader );
-
+               const char* mapNamePtr = PicoGetShaderMapName( shader );
                /* we have a valid map name ptr */
                if ( mapNamePtr != NULL ) {
+#if 0
                        char temp[128];
                        const char *name;
+                       char mapName[1024 + 1];
+                       memset( mapName,0,sizeof( mapName ) );
 
                        /* copy map name to local buffer */
                        strcpy( mapName,mapNamePtr );
@@ -420,7 +418,7 @@ static int GetMeshShader( T3dsLoaderPers *pers ){
                        strncpy( temp, name, sizeof( temp ) );
 
                        /* remove file extension */
-                       /* name = _pico_setfext( name,"" ); */
+                       /* name = _pico_setfext( name, NULL ); */
 
                        /* assign default name if no name available */
                        if ( strlen( temp ) < 1 ) {
@@ -433,7 +431,7 @@ static int GetMeshShader( T3dsLoaderPers *pers ){
 
                        /* set shader name */
                        /* PicoSetShaderName( shader,mapName ); */      /* ydnar: this will screw up the named shader */
-
+#endif
                        /* set surface's shader index */
                        PicoSetSurfaceShader( pers->surface, shader );
 
@@ -726,7 +724,7 @@ static picoModel_t *_3ds_load( PM_PARAMS_LOAD ){
        /* get model's base name (eg. jeep from c:\models\jeep.3ds) */
        memset( basename,0,sizeof( basename ) );
        strncpy( basename,_pico_nopath( fileName ),sizeof( basename ) );
-       _pico_setfext( basename,"" );
+       _pico_setfext( basename, NULL );
 
        /* initialize persistant vars (formerly static) */
        pers.model    =  model;
index 21c8e0801a78f8b742e9854fbb292233dce6e0db..1244eb353d4417569ceac257f0680e4c94130d47 100644 (file)
@@ -456,17 +456,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:
  *  loads a 3dsmax ase model file.
@@ -883,7 +872,7 @@ static picoModel_t *_ase_load( PM_PARAMS_LOAD ){
                                if ( level == subMaterialLevel ) {
                                        /* set material name */
                                        _pico_first_token( materialName );
-                                       shadername_convert( materialName );
+                                       _pico_unixify( materialName );
                                        PicoSetShaderName( shader, materialName );
 
                                        /* set shader's transparency */
@@ -1073,7 +1062,7 @@ static picoModel_t *_ase_load( PM_PARAMS_LOAD ){
                                }
 
                                /* set material name */
-                               shadername_convert( materialName );
+                               _pico_unixify( materialName );
                                PicoSetShaderName( shader,materialName );
 
                                /* set shader's transparency */
@@ -1097,34 +1086,6 @@ static picoModel_t *_ase_load( PM_PARAMS_LOAD ){
                                /* set material map name */
                                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 */
                                subMaterial = _ase_add_submaterial( &materials, index, 0, shader );
                        }
index 0df82a25c9698a7b66aed41fabd52e11f9b781a5..79fff8b991b42a7eb55c03e9578d86c7e1f39315 100644 (file)
@@ -374,7 +374,7 @@ static picoModel_t *_fm_load( PM_PARAMS_LOAD ){
 #endif
 
        // detox Skin name
-       _pico_setfext( skinname, "" );
+       _pico_setfext( skinname, NULL );
        _pico_unixify( skinname );
 
        /* create new pico model */
index 6cbf0f4c162d50916f4fec5674d42ef87011e423..37f2b60b1c602ed0b258dfac290a50648995ca95 100644 (file)
@@ -233,7 +233,7 @@ static picoModel_t *_lwo_load( PM_PARAMS_LOAD ){
                /* detox and set shader name */
                strncpy( name, surface->name, sizeof( name ) );
                _pico_first_token( name );
-               _pico_setfext( name, "" );
+               _pico_setfext( name, NULL );
                _pico_unixify( name );
                PicoSetShaderName( picoShader, name );
 
index 82975b887ff60213bc035c0543db805b2c1ac668..c984e42ebef2436e68f71501a43c7daca9e4dcf0 100644 (file)
@@ -424,7 +424,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 );
 
        // detox Skin name
-       _pico_setfext( skinname, "" );
+       _pico_setfext( skinname, NULL );
        _pico_unixify( skinname );
 
        /* create new pico model */
index 86742d734a643bb1f1f1a822b45650d70070db3b..1b93c7b4d93b2fe875638332fc32510df88a2cda 100644 (file)
@@ -340,7 +340,7 @@ static picoModel_t *_md3_load( PM_PARAMS_LOAD ){
 
                /* detox and set shader name */
                shader = (md3Shader_t*) ( (picoByte_t*) surface + surface->ofsShaders );
-               _pico_setfext( shader->name, "" );
+               _pico_setfext( shader->name, NULL );
                _pico_unixify( shader->name );
                PicoSetShaderName( picoShader, shader->name );
 
index be93e3382f32c63362843e6f7888993c1c40b9ff..ec40d5a9c842ae2fccb766505bf3dd52cee4d3ab 100644 (file)
@@ -640,7 +640,7 @@ static picoModel_t *_mdc_load( PM_PARAMS_LOAD ){
 
                /* detox and set shader name */
                shader = (mdcShader_t*) ( (picoByte_t*) surface + surface->ofsShaders );
-               _pico_setfext( shader->name, "" );
+               _pico_setfext( shader->name, NULL );
                _pico_unixify( shader->name );
                PicoSetShaderName( picoShader, shader->name );
 
index 6e11a1cdbaca6875bce3d01f474b0212a690f375..7a0ebd5f4068a788900bde501de28efbb09e0c48 100644 (file)
@@ -228,9 +228,12 @@ static int _obj_mtl_load( picoModel_t *model ){
                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 \
        { \
+               _obj_mtl_print_fail; \
                _pico_free_parser( p ); \
                _pico_free_file( mtlBuffer ); \
                _pico_free( fileName ); \
@@ -250,9 +253,11 @@ static int _obj_mtl_load( picoModel_t *model ){
 
        /* check result */
        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 */
 
        }
@@ -269,7 +274,6 @@ static int _obj_mtl_load( picoModel_t *model ){
                if ( _pico_parse( p,1 ) == NULL ) {
                        break;
                }
-#if 1
 
                /* skip empty lines */
                if ( p->token == NULL || !strlen( p->token ) ) {
@@ -309,7 +313,6 @@ static int _obj_mtl_load( picoModel_t *model ){
                /* diffuse map name */
                else if ( !_pico_stricmp( p->token,"map_kd" ) ) {
                        char *mapName;
-                       picoShader_t *shader;
 
                        /* pointer to current shader must be valid */
                        if ( curShader == NULL ) {
@@ -324,13 +327,8 @@ static int _obj_mtl_load( picoModel_t *model ){
                                _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 */
@@ -482,12 +480,12 @@ static int _obj_mtl_load( picoModel_t *model ){
                        /* 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 );
@@ -564,10 +562,8 @@ static picoModel_t *_obj_load( PM_PARAMS_LOAD ){
        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 )
@@ -903,7 +899,7 @@ static picoModel_t *_obj_load( PM_PARAMS_LOAD ){
                        {
                                shader = PicoFindShader( model, name, 1 );
                                if ( shader == NULL ) {
-                                       _pico_printf( PICO_WARNING,"Undefined material name \"%s\" in OBJ %s, line %d. Making a default shader.",name,model->fileName,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 */
                                        shader = PicoNewShader( model );
@@ -922,6 +918,7 @@ static picoModel_t *_obj_load( PM_PARAMS_LOAD ){
                /* skip unparsed rest of line and continue */
                _pico_parse_skip_rest( p );
        }
+
        /* free memory used by temporary vertexdata */
        FreeObjVertexData( vertexData );
 
index 039af0679a1ef324c187ab5b65318adf1d950437..fb8cd89d6a4616634cb58319c59d99c9b2f6b012 100644 (file)
@@ -495,7 +495,7 @@ static picoModel_t *_terrain_load( PM_PARAMS_LOAD ) {
        }
 
        /* detox and set shader name */
-       _pico_setfext( shader, "" );
+       _pico_setfext( shader, NULL );
        _pico_unixify( shader );
        PicoSetShaderName( picoShader, shader );
        _pico_free( shader );