]> de.git.xonotic.org Git - xonotic/netradiant.git/blobdiff - libs/picomodel/pm_obj.c
Fix compile on MSYS2
[xonotic/netradiant.git] / libs / picomodel / pm_obj.c
index 1c8c088f61fc8eadda6a70d78d9f337f589de65f..24f3ee8ac6ad7cc3e23046c377d586a70b4288cc 100644 (file)
 
    ----------------------------------------------------------------------------- */
 
-
-
-/* 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
 
@@ -86,7 +82,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;
        }
@@ -135,7 +131,7 @@ 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,
@@ -215,9 +211,8 @@ 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;
@@ -242,7 +237,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;
        }
@@ -274,7 +269,7 @@ static int _obj_mtl_load( picoModel_t *model ){
                if ( _pico_parse( p,1 ) == NULL ) {
                        break;
                }
-#if 0
+#if 1
 
                /* skip empty lines */
                if ( p->token == NULL || !strlen( p->token ) ) {
@@ -314,6 +309,7 @@ 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 ) {
@@ -328,6 +324,11 @@ 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 );
                }
@@ -494,7 +495,6 @@ static int _obj_mtl_load( picoModel_t *model ){
        /* return with success */
        return 1;
 }
-#endif
 
 /* _obj_load:
  *  loads a wavefront obj model file.
@@ -512,8 +512,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 ); \
@@ -522,7 +547,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;
        }
@@ -539,7 +564,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
 
@@ -632,7 +657,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.) */
@@ -647,23 +671,14 @@ 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 && curSurface != NULL ) {
+                               PicoSetSurfaceName( curSurface,groupName );
+                       }
+                       else
+                       {
+                               NEW_SURFACE( groupName );
+                       }
 
 #ifdef DEBUG_PM_OBJ_EX
                        printf( "Group: '%s'\n",groupName );
@@ -686,10 +701,16 @@ 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_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" );
@@ -860,6 +881,43 @@ 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_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 );
+                       }
+                       else
+                       {
+                               shader = PicoFindShader( model, name, 1 );
+                               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 ) {
+                                               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 );
        }