]> de.git.xonotic.org Git - xonotic/netradiant.git/blobdiff - tools/quake3/q3map2/model.c
mark two shader checks nullable
[xonotic/netradiant.git] / tools / quake3 / q3map2 / model.c
index 58fb1849bb0d79723f4254ca5e88ebc2ae873cf9..2b3bb7ed5f0059d5c1cc18862c65e47517b36f08 100644 (file)
@@ -78,9 +78,9 @@ PicoLoadFileFunc()
 callback for picomodel.lib
 */
 
-void PicoLoadFileFunc( char *name, byte **buffer, int *bufSize )
+void PicoLoadFileFunc( const char *name, byte **buffer, int *bufSize )
 {
-       *bufSize = vfsLoadFile( (const char*) name, (void**) buffer, 0 );
+       *bufSize = vfsLoadFile( name, (void**) buffer, 0 );
 }
 
 
@@ -90,7 +90,7 @@ FindModel() - ydnar
 finds an existing picoModel and returns a pointer to the picoModel_t struct or NULL if not found
 */
 
-picoModel_t *FindModel( char *name, int frame )
+picoModel_t *FindModel( const char *name, int frame )
 {
        int                     i;
        
@@ -123,7 +123,7 @@ LoadModel() - ydnar
 loads a picoModel and returns a pointer to the picoModel_t struct or NULL if not found
 */
 
-picoModel_t *LoadModel( char *name, int frame )
+picoModel_t *LoadModel( const char *name, int frame )
 {
        int                             i;
        picoModel_t             *model, **pm;
@@ -158,7 +158,7 @@ picoModel_t *LoadModel( char *name, int frame )
                Error( "MAX_MODELS (%d) exceeded, there are too many model files referenced by the map.", MAX_MODELS );
        
        /* attempt to parse model */
-       *pm = PicoLoadModel( (char*) name, frame );
+       *pm = PicoLoadModel( name, frame );
        
        /* if loading failed, make a bogus model to silence the rest of the warnings */
        if( *pm == NULL )
@@ -206,9 +206,9 @@ InsertModel() - ydnar
 adds a picomodel into the bsp
 */
 
-void InsertModel( char *name, int frame, m4x4_t transform, remap_t *remap, shaderInfo_t *celShader, int eNum, int castShadows, int recvShadows, int spawnFlags, float lightmapScale )
+void InsertModel( const char *name, int skin, int frame, m4x4_t transform, remap_t *remap, shaderInfo_t *celShader, int eNum, int castShadows, int recvShadows, int spawnFlags, float lightmapScale, int lightmapSampleSize, float shadeAngle )
 {
-       int                                     i, j, k, s, numSurfaces;
+       int                                     i, j, s, numSurfaces;
        m4x4_t                          identity, nTransform;
        picoModel_t                     *model;
        picoShader_t            *shader;
@@ -222,14 +222,76 @@ void InsertModel( char *name, int frame, m4x4_t transform, remap_t *remap, shade
        byte                            *color;
        picoIndex_t                     *indexes;
        remap_t                         *rm, *glob;
+       skinfile_t                      *sf, *sf2;
        double                          normalEpsilon_save;
        double                          distanceEpsilon_save;
+       char                            skinfilename[ MAX_QPATH ];
+       char                            *skinfilecontent;
+       int                                     skinfilesize;
+       char                            *skinfileptr, *skinfilenextptr;
        
        
        /* get model */
        model = LoadModel( name, frame );
        if( model == NULL )
                return;
+
+       /* load skin file */
+       snprintf(skinfilename, sizeof(skinfilename), "%s_%d.skin", name, skin);
+       skinfilename[sizeof(skinfilename)-1] = 0;
+       skinfilesize = vfsLoadFile(skinfilename, (void**) &skinfilecontent, 0);
+       if(skinfilesize < 0 && skin != 0)
+       {
+               /* fallback to skin 0 if invalid */
+               snprintf(skinfilename, sizeof(skinfilename), "%s_0.skin", name);
+               skinfilename[sizeof(skinfilename)-1] = 0;
+               skinfilesize = vfsLoadFile(skinfilename, (void**) &skinfilecontent, 0);
+               if(skinfilesize >= 0)
+                       Sys_Printf( "Skin %d of %s does not exist, using 0 instead\n", skin, name );
+       }
+       sf = NULL;
+       if(skinfilesize >= 0)
+       {
+               Sys_Printf( "Using skin %d of %s\n", skin, name );
+               int pos;
+               for(skinfileptr = skinfilecontent; *skinfileptr; skinfileptr = skinfilenextptr)
+               {
+                       // for fscanf
+                       char format[64];
+
+                       skinfilenextptr = strchr(skinfileptr, '\r');
+                       if(skinfilenextptr)
+                       {
+                               *skinfilenextptr++ = 0;
+                       }
+                       else
+                       {
+                               skinfilenextptr = strchr(skinfileptr, '\n');
+                               if(skinfilenextptr)
+                                       *skinfilenextptr++ = 0;
+                               else
+                                       skinfilenextptr = skinfileptr + strlen(skinfileptr);
+                       }
+
+                       /* create new item */
+                       sf2 = sf;
+                       sf = safe_malloc( sizeof( *sf ) );
+                       sf->next = sf2;
+
+                       sprintf(format, "replace %%%ds %%%ds", (int)sizeof(sf->name)-1, (int)sizeof(sf->to)-1);
+                       if(sscanf(skinfileptr, format, sf->name, sf->to) == 2)
+                               continue;
+                       sprintf(format, " %%%d[^,       ] ,%%%ds", (int)sizeof(sf->name)-1, (int)sizeof(sf->to)-1);
+                       if((pos = sscanf(skinfileptr, format, sf->name, sf->to)) == 2)
+                               continue;
+
+                       /* invalid input line -> discard sf struct */
+                       Sys_Printf( "Discarding skin directive in %s: %s\n", skinfilename, skinfileptr );
+                       free(sf);
+                       sf = sf2;
+               }
+               free(skinfilecontent);
+       }
        
        /* handle null matrix */
        if( transform == NULL )
@@ -252,6 +314,10 @@ void InsertModel( char *name, int frame, m4x4_t transform, remap_t *remap, shade
        /* fix bogus lightmap scale */
        if( lightmapScale <= 0.0f )
                lightmapScale = 1.0f;
+
+       /* fix bogus shade angle */
+       if( shadeAngle <= 0.0f )
+               shadeAngle = 0.0f;
        
        /* each surface on the model will become a new map drawsurface */
        numSurfaces = PicoGetModelNumSurfaces( model );
@@ -267,22 +333,33 @@ void InsertModel( char *name, int frame, m4x4_t transform, remap_t *remap, shade
                if( PicoGetSurfaceType( surface ) != PICO_TRIANGLES )
                        continue;
                
-               /* fix the surface's normals */
-               PicoFixSurfaceNormals( surface ); /* why did vortex comment this out? FIXME */
-               
-               /* allocate a surface (ydnar: gs mods) */
-               ds = AllocDrawSurface( SURFACE_TRIANGLES );
-               ds->entityNum = eNum;
-               ds->castShadows = castShadows;
-               ds->recvShadows = recvShadows;
-               
                /* get shader name */
         shader = PicoGetSurfaceShader( surface );
                if( shader == NULL )
                        picoShaderName = "";
                else
                        picoShaderName = PicoGetShaderName( shader );
-               
+
+               /* handle .skin file */
+               if(sf)
+               {
+                       picoShaderName = NULL;
+                       for(sf2 = sf; sf2 != NULL; sf2 = sf2->next)
+                       {
+                               if( !Q_stricmp( surface->name, sf2->name ) )
+                               {
+                                       Sys_FPrintf( SYS_VRB, "Skin file: mapping %s to %s\n", surface->name, sf2->to );
+                                       picoShaderName = sf2->to;
+                                       break;
+                               }
+                       }
+                       if(!picoShaderName)
+                       {
+                               Sys_FPrintf( SYS_VRB, "Skin file: not mapping %s\n", surface->name );
+                               continue;
+                       }
+               }
+
                /* handle shader remapping */
                glob = NULL;
                for( rm = remap; rm != NULL; rm = rm->next )
@@ -318,15 +395,34 @@ void InsertModel( char *name, int frame, m4x4_t transform, remap_t *remap, shade
                else
                        si = ShaderInfoForShader( picoShaderName );
                
+               /* allocate a surface (ydnar: gs mods) */
+               ds = AllocDrawSurface( SURFACE_TRIANGLES );
+               ds->entityNum = eNum;
+               ds->castShadows = castShadows;
+               ds->recvShadows = recvShadows;
+
                /* set shader */
                ds->shaderInfo = si;
-               
-               /* set lightmap scale */
-               ds->lightmapScale = lightmapScale;
-               
+
                /* force to meta? */
                if( (si != NULL && si->forceMeta) || (spawnFlags & 4) ) /* 3rd bit */
                        ds->type = SURFACE_FORCED_META;
+
+               /* fix the surface's normals (jal: conditioned by shader info) */
+               if( !(spawnFlags & 64) && ( shadeAngle == 0.0f || ds->type != SURFACE_FORCED_META ) )
+                       PicoFixSurfaceNormals( surface );
+
+               /* set sample size */
+               if( lightmapSampleSize > 0.0f )
+                       ds->sampleSize = lightmapSampleSize;
+               
+               /* set lightmap scale */
+               if( lightmapScale > 0.0f )
+                       ds->lightmapScale = lightmapScale;
+
+               /* set shading angle */
+               if( shadeAngle > 0.0f )
+                       ds->shadeAngleDegrees = shadeAngle;
                
                /* set particulars */
                ds->numVerts = PicoGetSurfaceNumVertexes( surface );
@@ -382,10 +478,20 @@ void InsertModel( char *name, int frame, m4x4_t transform, remap_t *remap, shade
                        {
                                dv->lightmap[ j ][ 0 ] = 0.0f;
                                dv->lightmap[ j ][ 1 ] = 0.0f;
-                               dv->color[ j ][ 0 ] = color[ 0 ];
-                               dv->color[ j ][ 1 ] = color[ 1 ];
-                               dv->color[ j ][ 2 ] = color[ 2 ];
-                               dv->color[ j ][ 3 ] = color[ 3 ];
+                               if(spawnFlags & 32) // spawnflag 32: model color -> alpha hack
+                               {
+                                       dv->color[ j ][ 0 ] = 255.0f;
+                                       dv->color[ j ][ 1 ] = 255.0f;
+                                       dv->color[ j ][ 2 ] = 255.0f;
+                                       dv->color[ j ][ 3 ] = RGBTOGRAY( color );
+                               }
+                               else
+                               {
+                                       dv->color[ j ][ 0 ] = color[ 0 ];
+                                       dv->color[ j ][ 1 ] = color[ 1 ];
+                                       dv->color[ j ][ 2 ] = color[ 2 ];
+                                       dv->color[ j ][ 3 ] = color[ 3 ];
+                               }
                        }
                }
                
@@ -405,8 +511,7 @@ void InsertModel( char *name, int frame, m4x4_t transform, remap_t *remap, shade
                        
                        
                        /* temp hack */
-                       if( !si->clipModel &&
-                               ((si->compileFlags & C_TRANSLUCENT) || !(si->compileFlags & C_SOLID)) )
+                       if( !si->clipModel && !(si->compileFlags & C_SOLID) )
                                continue;
                        
                        /* walk triangle list */
@@ -423,19 +528,6 @@ void InsertModel( char *name, int frame, m4x4_t transform, remap_t *remap, shade
                                        
                                        /* copy xyz */
                                        VectorCopy( dv->xyz, points[ j ] );
-                                       VectorCopy( dv->xyz, backs[ j ] );
-                                       
-                                       /* find nearest axial to normal and push back points opposite */
-                                       /* note: this doesn't work as well as simply using the plane of the triangle, below */
-                                       for( k = 0; k < 3; k++ )
-                                       {
-                                               if( fabs( dv->normal[ k ] ) >= fabs( dv->normal[ (k + 1) % 3 ] ) &&
-                                                       fabs( dv->normal[ k ] ) >= fabs( dv->normal[ (k + 2) % 3 ] ) )
-                                               {
-                                                       backs[ j ][ k ] += dv->normal[ k ] < 0.0f ? 64.0f : -64.0f;
-                                                       break;
-                                               }
-                                       }
                                }
 
                                VectorCopy( points[0], points[3] ); // for cyclic usage
@@ -580,13 +672,15 @@ adds misc_model surfaces to the bsp
 
 void AddTriangleModels( entity_t *e )
 {
-       int                             num, frame, castShadows, recvShadows, spawnFlags;
+       int                             num, frame, skin, castShadows, recvShadows, spawnFlags;
        entity_t                *e2;
        const char              *targetName;
        const char              *target, *model, *value;
        char                    shader[ MAX_QPATH ];
        shaderInfo_t    *celShader;
        float                   temp, baseLightmapScale, lightmapScale;
+       float                   shadeAngle;
+       int                             lightmapSampleSize;
        vec3_t                  origin, scale, angles;
        m4x4_t                  transform;
        epair_t                 *ep;
@@ -611,11 +705,22 @@ void AddTriangleModels( entity_t *e )
        
        /* get lightmap scale */
        /* vortex: added _ls key (short name of lightmapscale) */
-       baseLightmapScale = FloatForKey( e, "_lightmapscale" );
-       if( baseLightmapScale <= 0.0f )
-               baseLightmapScale = FloatForKey( e, "_ls" );
-       if( baseLightmapScale <= 0.0f )
-               baseLightmapScale = 0.0f;
+       baseLightmapScale = 0.0f;
+       if( strcmp( "", ValueForKey( e, "lightmapscale" ) ) ||
+               strcmp( "", ValueForKey( e, "_lightmapscale" ) ) || 
+               strcmp( "", ValueForKey( e, "_ls" ) ) )
+       {
+               baseLightmapScale = FloatForKey( e, "lightmapscale" );
+               if( baseLightmapScale <= 0.0f )
+                       baseLightmapScale = FloatForKey( e, "_lightmapscale" );
+               if( baseLightmapScale <= 0.0f )
+                       baseLightmapScale = FloatForKey( e, "_ls" );
+               if( baseLightmapScale < 0.0f )
+                       baseLightmapScale = 0.0f;
+               if( baseLightmapScale > 0.0f )
+                       Sys_Printf( "World Entity has lightmap scale of %.4f\n", baseLightmapScale );
+       }
+       
        
        /* walk the entity list */
        for( num = 1; num < numEntities; num++ )
@@ -642,7 +747,11 @@ void AddTriangleModels( entity_t *e )
                }
                
                /* get model frame */
-               frame = IntForKey( e2, "_frame" );
+               frame = 0;
+               if(strcmp("", ValueForKey( e2, "_frame")))
+                       frame = IntForKey(e2, "_frame");
+               else if(strcmp("", ValueForKey( e2, "frame")))
+                       frame = IntForKey(e2, "frame");
                
                /* worldspawn (and func_groups) default to cast/recv shadows in worldspawn group */
                if( e == entities )
@@ -733,17 +842,64 @@ void AddTriangleModels( entity_t *e )
                }
                else
                        celShader = *globalCelShader ? ShaderInfoForShader(globalCelShader) : NULL;
-               
+
+               /* jal : entity based _samplesize */
+               lightmapSampleSize = 0;
+               if ( strcmp( "", ValueForKey( e2, "_lightmapsamplesize" ) ) )
+                       lightmapSampleSize = IntForKey( e2, "_lightmapsamplesize" );
+               else if ( strcmp( "", ValueForKey( e2, "_samplesize" ) ) )
+                       lightmapSampleSize = IntForKey( e2, "_samplesize" );
+
+               if( lightmapSampleSize < 0 )
+                       lightmapSampleSize = 0;
+
+               if( lightmapSampleSize > 0.0f )
+                       Sys_Printf( "misc_model has lightmap sample size of %.d\n", lightmapSampleSize );
+
                /* get lightmap scale */
                /* vortex: added _ls key (short name of lightmapscale) */
-               lightmapScale = FloatForKey( e2, "_lightmapscale" );
-               if( lightmapScale <= 0.0f )
-                       lightmapScale = FloatForKey( e2, "_ls" );
-               if( lightmapScale <= 0.0f )
-                       lightmapScale = baseLightmapScale;
-               
+               lightmapScale = 0.0f;
+               if( strcmp( "", ValueForKey( e2, "lightmapscale" ) ) ||
+                       strcmp( "", ValueForKey( e2, "_lightmapscale" ) ) || 
+                       strcmp( "", ValueForKey( e2, "_ls" ) ) )
+               {
+                       lightmapScale = FloatForKey( e2, "lightmapscale" );
+                       if( lightmapScale <= 0.0f )
+                               lightmapScale = FloatForKey( e2, "_lightmapscale" );
+                       if( lightmapScale <= 0.0f )
+                               lightmapScale = FloatForKey( e2, "_ls" );
+                       if( lightmapScale < 0.0f )
+                               lightmapScale = 0.0f;
+                       if( lightmapScale > 0.0f )
+                               Sys_Printf( "misc_model has lightmap scale of %.4f\n", lightmapScale );
+               }
+
+               /* jal : entity based _shadeangle */
+               shadeAngle = 0.0f;
+               if ( strcmp( "", ValueForKey( e2, "_shadeangle" ) ) )
+                       shadeAngle = FloatForKey( e2, "_shadeangle" );
+               /* vortex' aliases */
+               else if ( strcmp( "", ValueForKey( e2, "_smoothnormals" ) ) )
+                       shadeAngle = FloatForKey( e2, "_smoothnormals" );
+               else if ( strcmp( "", ValueForKey( e2, "_sn" ) ) )
+                       shadeAngle = FloatForKey( e2, "_sn" );
+               else if ( strcmp( "", ValueForKey( e2, "_smooth" ) ) )
+                       shadeAngle = FloatForKey( e2, "_smooth" );
+
+               if( shadeAngle < 0.0f )
+                       shadeAngle = 0.0f;
+
+               if( shadeAngle > 0.0f )
+                       Sys_Printf( "misc_model has shading angle of %.4f\n", shadeAngle );
+
+               skin = 0;
+               if(strcmp("", ValueForKey( e2, "_skin")))
+                       skin = IntForKey(e2, "_skin");
+               else if(strcmp("", ValueForKey( e2, "skin")))
+                       skin = IntForKey(e2, "skin");
+
                /* insert the model */
-               InsertModel( (char*) model, frame, transform, remap, celShader, mapEntityNum, castShadows, recvShadows, spawnFlags, lightmapScale );
+               InsertModel( model, skin, frame, transform, remap, celShader, mapEntityNum, castShadows, recvShadows, spawnFlags, lightmapScale, lightmapSampleSize, shadeAngle );
                
                /* free shader remappings */
                while( remap != NULL )