]> git.xonotic.org Git - xonotic/netradiant.git/blobdiff - tools/quake3/q3map2/map.c
support .skin files for models (modelname_<n>.skin) like Q3A and DP
[xonotic/netradiant.git] / tools / quake3 / q3map2 / map.c
index 18ab6b216fa8ee0066baa27f95f47aa19214604b..54f54441e3a04fb28192e94e1215a35672cb11d9 100644 (file)
@@ -44,7 +44,7 @@ several games based on the Quake III Arena engine, in the form of "Q3Map2."
 #define        USE_HASHING
 #define        PLANE_HASHES    8192
 
-plane_t                                        *planehash[ PLANE_HASHES ];
+int                                            planehash[ PLANE_HASHES ];
 
 int                                            c_boxbevels;
 int                                            c_edgebevels;
@@ -96,7 +96,7 @@ void AddPlaneToHash( plane_t *p )
        hash = (PLANE_HASHES - 1) & (int) fabs( p->dist );
 
        p->hash_chain = planehash[hash];
-       planehash[hash] = p;
+       planehash[hash] = p - mapplanes + 1;
 }
 
 /*
@@ -115,8 +115,7 @@ int CreateNewFloatPlane (vec3_t normal, vec_t dist)
        }
 
        // create a new plane
-       if (nummapplanes+2 > MAX_MAP_PLANES)
-               Error ("MAX_MAP_PLANES");
+       AUTOEXPAND_BY_REALLOC(mapplanes, nummapplanes+1, allocatedmapplanes, 1024);
 
        p = &mapplanes[nummapplanes];
        VectorCopy (normal, p->normal);
@@ -213,21 +212,24 @@ ydnar: changed to allow a number of test points to be supplied that
 must be within an epsilon distance of the plane
 */
 
-int FindFloatPlane( vec3_t normal, vec_t dist, int numPoints, vec3_t *points ) // NOTE: this has a side effect on the normal. Good or bad?
+int FindFloatPlane( vec3_t innormal, vec_t dist, int numPoints, vec3_t *points ) // NOTE: this has a side effect on the normal. Good or bad?
 
 #ifdef USE_HASHING
 
 {
        int             i, j, hash, h;
+       int pidx;
        plane_t *p;
        vec_t   d;
        vec3_t centerofweight;
+       vec3_t normal;
 
        VectorClear(centerofweight);
        for(i = 0; i < numPoints; ++i)
                VectorMA(centerofweight, 1.0 / numPoints, points[i], centerofweight);
        
        /* hash the plane */
+       VectorCopy(innormal, normal);
        SnapPlane( normal, &dist, centerofweight );
        hash = (PLANE_HASHES - 1) & (int) fabs( dist );
        
@@ -235,8 +237,10 @@ int FindFloatPlane( vec3_t normal, vec_t dist, int numPoints, vec3_t *points ) /
        for( i = -1; i <= 1; i++ )
        {
                h = (hash + i) & (PLANE_HASHES - 1);
-               for( p = planehash[ h ]; p != NULL; p = p->hash_chain )
+               for( pidx = planehash[ h ] - 1; pidx != -1; pidx = mapplanes[pidx].hash_chain - 1 )
                {
+                       p = &mapplanes[pidx];
+
                        /* do standard plane compare */
                        if( !PlaneEqual( p, normal, dist ) )
                                continue;
@@ -267,6 +271,7 @@ int FindFloatPlane( vec3_t normal, vec_t dist, int numPoints, vec3_t *points ) /
 {
        int             i;
        plane_t *p;
+       vec3_t normal;
        
 
        vec3_t centerofweight;
@@ -275,6 +280,7 @@ int FindFloatPlane( vec3_t normal, vec_t dist, int numPoints, vec3_t *points ) /
        for(i = 0; i < numPoints; ++i)
                VectorMA(centerofweight, 1.0 / numPoints, points[i], centerofweight);
 
+       VectorCopy(innormal, normal);
        SnapPlane( normal, &dist, centerofweight );
        for( i = 0, p = mapplanes; i < nummapplanes; i++, p++ )
        {
@@ -343,6 +349,9 @@ void SetBrushContents( brush_t *b )
                        continue;
                if( s->contentFlags != contentFlags || s->compileFlags != compileFlags )
                        mixed = qtrue;
+
+               contentFlags |= s->contentFlags;
+               compileFlags |= s->compileFlags;
        }
        
        /* ydnar: getting rid of this stupid warning */
@@ -598,12 +607,15 @@ and links it to the current entity
 static void MergeOrigin(entity_t *ent, vec3_t origin)
 {
        vec3_t adjustment;
+       char string[128];
+
+       /* we have not parsed the brush completely yet... */
+       GetVectorForKey( ent, "origin", ent->origin );
 
        VectorMA(origin, -1, ent->originbrush_origin, adjustment);
        VectorAdd(adjustment, ent->origin, ent->origin);
        VectorCopy(origin, ent->originbrush_origin);
 
-       char string[128];
        sprintf(string, "%f %f %f", ent->origin[0], ent->origin[1], ent->origin[2]);
        SetKeyValue(ent, "origin", string);
 }
@@ -621,9 +633,11 @@ brush_t *FinishBrush( void )
           after the entire entity is parsed, the planenums and texinfos will be adjusted for the origin brush */
        if( buildBrush->compileFlags & C_ORIGIN )
        {
-               char    string[ 32 ];
                vec3_t  origin;
 
+               Sys_Printf( "Entity %i, Brush %i: origin brush detected\n", 
+                               mapEnt->mapEntityNum, entitySourceBrushes );
+
                if( numEntities == 1 )
                {
                        Sys_Printf( "Entity %i, Brush %i: origin brushes not allowed in world\n", 
@@ -1079,11 +1093,16 @@ adds them to the world's brush list
 (used by func_group)
 */
 
+void AdjustBrushesForOrigin( entity_t *ent );
 void MoveBrushesToWorld( entity_t *ent )
 {
        brush_t         *b, *next;
        parseMesh_t     *pm;
 
+       /* we need to undo the common/origin adjustment, and instead shift them by the entity key origin */
+       VectorScale(ent->origin, -1, ent->originbrush_origin);
+       AdjustBrushesForOrigin(ent);
+       VectorClear(ent->originbrush_origin);
        
        /* move brushes */
        for( b = ent->brushes; b != NULL; b = next )
@@ -1146,7 +1165,6 @@ void AdjustBrushesForOrigin( entity_t *ent )
        brush_t         *b;
        parseMesh_t     *p;
        
-       
        /* walk brush list */
        for( b = ent->brushes; b != NULL; b = b->next )
        {
@@ -1157,7 +1175,7 @@ void AdjustBrushesForOrigin( entity_t *ent )
                        s = &b->sides[ i ];
                        
                        /* offset side plane */
-                       newdist = mapplanes[ s->planenum ].dist - DotProduct( mapplanes[ s->planenum ].normal, ent->origin );
+                       newdist = mapplanes[ s->planenum ].dist - DotProduct( mapplanes[ s->planenum ].normal, ent->originbrush_origin );
                        
                        /* find a new plane */
                        s->planenum = FindFloatPlane( mapplanes[ s->planenum ].normal, newdist, 0, NULL );
@@ -1171,7 +1189,7 @@ void AdjustBrushesForOrigin( entity_t *ent )
        for( p = ent->patches; p != NULL; p = p->next )
        {
                for( i = 0; i < (p->mesh.width * p->mesh.height); i++ )
-                       VectorSubtract( p->mesh.verts[ i ].xyz, ent->origin, p->mesh.verts[ i ].xyz );
+                       VectorSubtract( p->mesh.verts[ i ].xyz, ent->originbrush_origin, p->mesh.verts[ i ].xyz );
        }
 }
 
@@ -1404,7 +1422,8 @@ static qboolean ParseMapEntity( qboolean onlyLights )
 {
        epair_t                 *ep;
        const char              *classname, *value;
-       float                   lightmapScale;
+       float                   lightmapScale, shadeAngle;
+       int                             lightmapSampleSize;
        char                    shader[ MAX_QPATH ];
        shaderInfo_t    *celShader = NULL;
        brush_t                 *brush;
@@ -1541,19 +1560,24 @@ static qboolean ParseMapEntity( qboolean onlyLights )
        /* get explicit shadow flags */
        GetEntityShadowFlags( mapEnt, NULL, &castShadows, &recvShadows );
        
+       /* vortex: added _ls key (short name of lightmapscale) */
        /* ydnar: get lightmap scaling value for this entity */
+       lightmapScale = 0.0f;
        if( strcmp( "", ValueForKey( mapEnt, "lightmapscale" ) ) ||
-               strcmp( "", ValueForKey( mapEnt, "_lightmapscale" ) ) )
+               strcmp( "", ValueForKey( mapEnt, "_lightmapscale" ) ) || 
+               strcmp( "", ValueForKey( mapEnt, "_ls" ) ) )
        {
                /* get lightmap scale from entity */
                lightmapScale = FloatForKey( mapEnt, "lightmapscale" );
                if( lightmapScale <= 0.0f )
                        lightmapScale = FloatForKey( mapEnt, "_lightmapscale" );
+               if( lightmapScale <= 0.0f )
+                       lightmapScale = FloatForKey( mapEnt, "_ls" );
+               if( lightmapScale < 0.0f )
+                       lightmapScale = 0.0f;
                if( lightmapScale > 0.0f )
                        Sys_Printf( "Entity %d (%s) has lightmap scale of %.4f\n", mapEnt->mapEntityNum, classname, lightmapScale );
        }
-       else
-               lightmapScale = 0.0f;
        
        /* ydnar: get cel shader :) for this entity */
        value = ValueForKey( mapEnt, "_celshader" );
@@ -1561,12 +1585,50 @@ static qboolean ParseMapEntity( qboolean onlyLights )
                value = ValueForKey( &entities[ 0 ], "_celshader" );
        if( value[ 0 ] != '\0' )
        {
-               sprintf( shader, "textures/%s", value );
-               celShader = ShaderInfoForShader( shader );
-               Sys_Printf( "Entity %d (%s) has cel shader %s\n", mapEnt->mapEntityNum, classname, celShader->shader );
+               if(strcmp(value, "none"))
+               {
+                       sprintf( shader, "textures/%s", value );
+                       celShader = ShaderInfoForShader( shader );
+                       Sys_Printf( "Entity %d (%s) has cel shader %s\n", mapEnt->mapEntityNum, classname, celShader->shader );
+               }
+               else
+               {
+                       celShader = NULL;
+               }
        }
        else
-               celShader = NULL;
+               celShader = (*globalCelShader ? ShaderInfoForShader(globalCelShader) : NULL);
+
+       /* jal : entity based _shadeangle */
+       shadeAngle = 0.0f;
+       if ( strcmp( "", ValueForKey( mapEnt, "_shadeangle" ) ) )
+               shadeAngle = FloatForKey( mapEnt, "_shadeangle" );
+       /* vortex' aliases */
+       else if ( strcmp( "", ValueForKey( mapEnt, "_smoothnormals" ) ) )
+               shadeAngle = FloatForKey( mapEnt, "_smoothnormals" );
+       else if ( strcmp( "", ValueForKey( mapEnt, "_sn" ) ) )
+               shadeAngle = FloatForKey( mapEnt, "_sn" );
+       else if ( strcmp( "", ValueForKey( mapEnt, "_smooth" ) ) )
+               shadeAngle = FloatForKey( mapEnt, "_smooth" );
+       
+       if( shadeAngle < 0.0f )
+               shadeAngle = 0.0f;
+
+       if( shadeAngle > 0.0f )
+               Sys_Printf( "Entity %d (%s) has shading angle of %.4f\n", mapEnt->mapEntityNum, classname, shadeAngle );
+       
+       /* jal : entity based _samplesize */
+       lightmapSampleSize = 0;
+       if ( strcmp( "", ValueForKey( mapEnt, "_lightmapsamplesize" ) ) )
+               lightmapSampleSize = IntForKey( mapEnt, "_lightmapsamplesize" );
+       else if ( strcmp( "", ValueForKey( mapEnt, "_samplesize" ) ) )
+               lightmapSampleSize = IntForKey( mapEnt, "_samplesize" );
+       
+       if( lightmapSampleSize < 0 )
+               lightmapSampleSize = 0;
+
+       if( lightmapSampleSize > 0 )
+               Sys_Printf( "Entity %d (%s) has lightmap sample size of %d\n", mapEnt->mapEntityNum, classname, lightmapSampleSize );
        
        /* attach stuff to everything in the entity */
        for( brush = mapEnt->brushes; brush != NULL; brush = brush->next )
@@ -1574,8 +1636,10 @@ static qboolean ParseMapEntity( qboolean onlyLights )
                brush->entityNum = mapEnt->mapEntityNum;
                brush->castShadows = castShadows;
                brush->recvShadows = recvShadows;
+               brush->lightmapSampleSize = lightmapSampleSize;
                brush->lightmapScale = lightmapScale;
                brush->celShader = celShader;
+               brush->shadeAngleDegrees = shadeAngle;
        }
        
        for( patch = mapEnt->patches; patch != NULL; patch = patch->next )
@@ -1583,6 +1647,7 @@ static qboolean ParseMapEntity( qboolean onlyLights )
                patch->entityNum = mapEnt->mapEntityNum;
                patch->castShadows = castShadows;
                patch->recvShadows = recvShadows;
+               patch->lightmapSampleSize = lightmapSampleSize;
                patch->lightmapScale = lightmapScale;
                patch->celShader = celShader;
        }
@@ -1595,7 +1660,7 @@ static qboolean ParseMapEntity( qboolean onlyLights )
        
        /* get entity origin and adjust brushes */
        GetVectorForKey( mapEnt, "origin", mapEnt->origin );
-       if( mapEnt->origin[ 0 ] || mapEnt->origin[ 1 ] || mapEnt->origin[ 2 ] )
+       if( mapEnt->originbrush_origin[ 0 ] || mapEnt->originbrush_origin[ 1 ] || mapEnt->originbrush_origin[ 2 ] )
                AdjustBrushesForOrigin( mapEnt );
 
        /* group_info entities are just for editor grouping (fixme: leak!) */