summaryrefslogtreecommitdiff
path: root/source/gl_world.c
diff options
context:
space:
mode:
Diffstat (limited to 'source/gl_world.c')
-rw-r--r--source/gl_world.c440
1 files changed, 192 insertions, 248 deletions
diff --git a/source/gl_world.c b/source/gl_world.c
index a585dc4..7a38d69 100644
--- a/source/gl_world.c
+++ b/source/gl_world.c
@@ -22,159 +22,63 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
vec3_t modelViewOrigin; // viewer origin in model space
-static vec3_t lightcolor;
-
-static qboolean GL_LightPoint_r( bspNode_t *node, vec3_t start, vec3_t end ) {
- vec_t startFrac, endFrac, midFrac;
- vec3_t _start, mid;
- int side;
- qboolean ret;
- bspSurface_t *surf;
- bspTexinfo_t *texinfo;
- int i, pitch;
- int s, t;
+qboolean GL_LightPoint( vec3_t origin, vec3_t color ) {
+ bsp_t *bsp = gl_static.world.cache;
+ mface_t *surf;
+ int s, t;
byte *b1, *b2, *b3, *b4;
int fracu, fracv;
int w1, w2, w3, w4;
- int color[3];
-
- VectorCopy( start, _start );
- while( node->plane ) {
- // calculate distancies
- startFrac = PlaneDiffFast( _start, node->plane );
- endFrac = PlaneDiffFast( end, node->plane );
- side = ( startFrac < 0 );
-
- if( ( endFrac < 0 ) == side ) {
- // both points are one the same side
- node = node->children[side];
- continue;
- }
-
- // find crossing point
- midFrac = startFrac / ( startFrac - endFrac );
- LerpVector( _start, end, midFrac, mid );
-
- // check near side
- ret = GL_LightPoint_r( node->children[side], _start, mid );
- if( ret ) {
- return ret;
- }
-
- for( i = 0, surf = node->firstFace; i < node->numFaces; i++, surf++ ) {
- texinfo = surf->texinfo;
- if( texinfo->flags & (SURF_WARP|SURF_SKY) ) {
- continue;
- }
- if( !surf->lightmap ) {
- continue;
- }
- s = DotProduct( texinfo->axis[0], mid ) + texinfo->offset[0];
- t = DotProduct( texinfo->axis[1], mid ) + texinfo->offset[1];
+ byte temp[3];
+ int pitch;
+ vec3_t point;
- s -= surf->texturemins[0];
- t -= surf->texturemins[1];
- if( s < 0 || t < 0 ) {
- continue;
- }
- if( s > surf->extents[0] || t > surf->extents[1] ) {
- continue;
- }
-
- fracu = s & 15;
- fracv = t & 15;
-
- s >>= 4;
- t >>= 4;
-
- pitch = ( surf->extents[0] >> 4 ) + 1;
- b1 = &surf->lightmap[3 * ( ( t + 0 ) * pitch + ( s + 0 ) )];
- b2 = &surf->lightmap[3 * ( ( t + 0 ) * pitch + ( s + 1 ) )];
- b3 = &surf->lightmap[3 * ( ( t + 1 ) * pitch + ( s + 1 ) )];
- b4 = &surf->lightmap[3 * ( ( t + 1 ) * pitch + ( s + 0 ) )];
-
- w1 = ( 16 - fracu ) * ( 16 - fracv );
- w2 = fracu * ( 16 - fracv );
- w3 = fracu * fracv;
- w4 = ( 16 - fracu ) * fracv;
-
- color[0] = ( w1 * b1[0] + w2 * b2[0] + w3 * b3[0] + w4 * b4[0] ) >> 8;
- color[1] = ( w1 * b1[1] + w2 * b2[1] + w3 * b3[1] + w4 * b4[1] ) >> 8;
- color[2] = ( w1 * b1[2] + w2 * b2[2] + w3 * b3[2] + w4 * b4[2] ) >> 8;
-
- VectorMA( lightcolor, 1.0f / 255, color, lightcolor );
-
- return qtrue;
- }
-
- // check far side
- VectorCopy( mid, _start );
- node = node->children[side^1];
+ if( !bsp || !bsp->lightmap ) {
+ return qfalse;
}
- return qfalse;
-}
-
-void GL_LightPoint( vec3_t origin, vec3_t dest ) {
- extern cvar_t *gl_modulate_hack;
- vec3_t point;
-#if USE_DYNAMIC
- dlight_t *light;
- vec3_t dir;
- vec_t dist, f;
-#endif
- int i;
-
- if( !r_world.name[0] || gl_fullbright->integer ) {
- VectorSet( dest, 1, 1, 1 );
- return;
- }
-
point[0] = origin[0];
point[1] = origin[1];
point[2] = origin[2] - 8192;
-
- VectorClear( lightcolor );
- if( !r_world.lightmap || !GL_LightPoint_r( r_world.nodes, origin, point ) ) {
- VectorSet( lightcolor, 1, 1, 1 );
+
+ surf = BSP_LightPoint( bsp->nodes, origin, point, &s, &t );
+ if( !surf ) {
+ return qfalse;
}
- if( gl_modulate_hack && gl_modulate_hack->integer ) {
- VectorScale( lightcolor, gl_modulate->value, lightcolor );
- }
+ fracu = s & 15;
+ fracv = t & 15;
-#if USE_DYNAMIC
- for( i = 0, light = glr.fd.dlights; i < glr.fd.num_dlights; i++, light++ ) {
- VectorSubtract( light->origin, origin, dir );
- dist = VectorLength( dir );
- if( dist > light->intensity ) {
- continue;
- }
- f = 1.0f - dist / light->intensity;
- VectorMA( lightcolor, f, light->color, lightcolor );
- }
-#endif
+ s >>= 4;
+ t >>= 4;
- /* apply modulate twice to mimic original ref_gl behavior */
- VectorScale( lightcolor, gl_modulate->value, lightcolor );
+ pitch = ( surf->extents[0] >> 4 ) + 1;
+ b1 = &surf->lightmap[3 * ( ( t + 0 ) * pitch + ( s + 0 ) )];
+ b2 = &surf->lightmap[3 * ( ( t + 0 ) * pitch + ( s + 1 ) )];
+ b3 = &surf->lightmap[3 * ( ( t + 1 ) * pitch + ( s + 1 ) )];
+ b4 = &surf->lightmap[3 * ( ( t + 1 ) * pitch + ( s + 0 ) )];
+
+ w1 = ( 16 - fracu ) * ( 16 - fracv );
+ w2 = fracu * ( 16 - fracv );
+ w3 = fracu * fracv;
+ w4 = ( 16 - fracu ) * fracv;
- for( i = 0; i < 3; i++ ) {
- if( lightcolor[i] > 1 ) {
- lightcolor[i] = 1;
- } else if( lightcolor[i] < 0 ) {
- lightcolor[i] = 0;
- }
- }
+ temp[0] = ( w1 * b1[0] + w2 * b2[0] + w3 * b3[0] + w4 * b4[0] ) >> 8;
+ temp[1] = ( w1 * b1[1] + w2 * b2[1] + w3 * b3[1] + w4 * b4[1] ) >> 8;
+ temp[2] = ( w1 * b1[2] + w2 * b2[2] + w3 * b3[2] + w4 * b4[2] ) >> 8;
+
+ GL_AdjustColor( temp, temp, 2 );
- VectorCopy( lightcolor, dest );
+ VectorScale( temp, 1.0f / 255, color );
+ return qtrue;
}
#if USE_DYNAMIC
-static void GL_MarkLights_r( bspNode_t *node, dlight_t *light ) {
+static void GL_MarkLights_r( mnode_t *node, dlight_t *light ) {
vec_t dot;
int count;
- bspSurface_t *face;
+ mface_t *face;
int lightbit = 1 << light->index;
while( node->plane ) {
@@ -215,19 +119,16 @@ void GL_MarkLights( void ) {
for( i = 0, light = glr.fd.dlights; i < glr.fd.num_dlights; i++, light++ ) {
light->index = i;
VectorCopy( light->origin, light->transformed );
- GL_MarkLights_r( r_world.nodes, light );
+ GL_MarkLights_r( gl_static.world.cache->nodes, light );
}
}
-static void GL_TransformLights( bspSubmodel_t *model ) {
+static void GL_TransformLights( mmodel_t *model ) {
int i;
dlight_t *light;
vec3_t temp;
if( !model->headnode ) {
- // this happens on some maps
- // could lead to a crash of the original ref_gl
- //Com_WPrintf( "GL_TransformLights: NULL headnode\n" );
return;
}
@@ -239,22 +140,68 @@ static void GL_TransformLights( bspSubmodel_t *model ) {
light->transformed[2] = DotProduct( temp, glr.entaxis[2] );
GL_MarkLights_r( model->headnode, light );
-
}
}
+
+void GL_AddLights( vec3_t origin, vec3_t color ) {
+ dlight_t *light;
+ vec3_t dir;
+ vec_t dist, f;
+ int i;
+
+ for( i = 0, light = glr.fd.dlights; i < glr.fd.num_dlights; i++, light++ ) {
+ VectorSubtract( light->origin, origin, dir );
+ dist = VectorLength( dir );
+ if( dist > light->intensity ) {
+ continue;
+ }
+ f = 1.0f - dist / light->intensity;
+ VectorMA( color, f, light->color, color );
+ }
+}
+#endif
+
+void R_LightPoint( vec3_t origin, vec3_t color ) {
+ int i;
+
+ if( gl_fullbright->integer ) {
+ VectorSet( color, 1, 1, 1 );
+ return;
+ }
+
+ // get lighting from world
+ if( !GL_LightPoint( origin, color ) ) {
+ VectorSet( color, 1, 1, 1 );
+ }
+
+#if USE_DYNAMIC
+ if( gl_dynamic->integer ) {
+ // add dynamic lights
+ GL_AddLights( origin, color );
+ }
#endif
+ // apply modulate twice to mimic original ref_gl behavior
+ VectorScale( color, gl_modulate->value, color );
+
+ for( i = 0; i < 3; i++ ) {
+ clamp( color[i], 0, 1 );
+ }
+}
+
void GL_MarkLeaves( void ) {
- byte fatvis[MAX_MAP_LEAFS/8];
- bspLeaf_t *leaf, *lastleaf;
- bspNode_t *node, *lastnode;
- byte *vis1, *vis2;
- uint32_t *dst, *src1, *src2;
+ static int lastNodesVisible;
+ byte vis1[MAX_MAP_VIS];
+ byte vis2[MAX_MAP_VIS];
+ mleaf_t *leaf;
+ mnode_t *node;
+ uint32_t *src1, *src2;
int cluster1, cluster2, longs;
vec3_t tmp;
- static int lastNodesVisible;
+ int i;
+ bsp_t *bsp = gl_static.world.cache;
- leaf = Bsp_FindLeaf( glr.fd.vieworg );
+ leaf = BSP_PointLeaf( bsp->nodes, glr.fd.vieworg );
cluster1 = cluster2 = leaf->cluster;
VectorCopy( glr.fd.vieworg, tmp );
if( !leaf->contents ) {
@@ -262,7 +209,7 @@ void GL_MarkLeaves( void ) {
} else {
tmp[2] += 16;
}
- leaf = Bsp_FindLeaf( tmp );
+ leaf = BSP_PointLeaf( bsp->nodes, tmp );
if( !( leaf->contents & CONTENTS_SOLID ) ) {
cluster2 = leaf->cluster;
}
@@ -275,55 +222,43 @@ void GL_MarkLeaves( void ) {
goto finish;
}
- vis1 = vis2 = Bsp_ClusterPVS( cluster1 );
- if( cluster1 != cluster2 ) {
- vis2 = Bsp_ClusterPVS( cluster2 );
- if( !vis1 ) {
- vis1 = vis2;
- } else if( !vis2 ) {
- vis2 = vis1;
- }
- }
glr.visframe++;
- lastNodesVisible = 0;
glr.viewcluster1 = cluster1;
glr.viewcluster2 = cluster2;
- if( !vis1 || gl_novis->integer ) {
- /* mark everything visible */
- lastleaf = r_world.leafs + r_world.numLeafs;
- for( leaf = r_world.leafs; leaf != lastleaf; leaf++ ) {
- leaf->visframe = glr.visframe;
+ if( !bsp->vis || gl_novis->integer || cluster1 == -1 ) {
+ // mark everything visible
+ for( i = 0; i < bsp->numnodes; i++ ) {
+ bsp->nodes[i].visframe = glr.visframe;
}
- lastnode = r_world.nodes + r_world.numNodes;
- for( node = r_world.nodes; node != lastnode; node++ ) {
- node->visframe = glr.visframe;
+ for( i = 0; i < bsp->numleafs; i++ ) {
+ bsp->leafs[i].visframe = glr.visframe;
}
- lastNodesVisible = r_world.numNodes;
+ lastNodesVisible = bsp->numnodes;
goto finish;
}
- if( vis1 != vis2 ) {
- longs = ( r_world.numClusters + 31 ) >> 5;
+ BSP_ClusterVis( bsp, vis1, cluster1, DVIS_PVS );
+ if( cluster1 != cluster2 ) {
+ BSP_ClusterVis( bsp, vis2, cluster2, DVIS_PVS );
+ longs = ( bsp->visrowsize + 31 ) >> 5;
src1 = ( uint32_t * )vis1;
src2 = ( uint32_t * )vis2;
- dst = ( uint32_t * )fatvis;
while( longs-- ) {
- *dst++ = *src1++ | *src2++;
+ *src1++ |= *src2++;
}
- vis1 = fatvis;
}
-
- lastleaf = r_world.leafs + r_world.numLeafs;
- for( leaf = r_world.leafs; leaf != lastleaf; leaf++ ) {
+
+ lastNodesVisible = 0;
+ for( i = 0, leaf = bsp->leafs; i < bsp->numleafs; i++, leaf++ ) {
cluster1 = leaf->cluster;
if( cluster1 == -1 ) {
continue;
}
if( Q_IsBitSet( vis1, cluster1 ) ) {
- node = ( bspNode_t * )leaf;
+ node = ( mnode_t * )leaf;
- /* mark parent nodes visible */
+ // mark parent nodes visible
do {
if( node->visframe == glr.visframe ) {
break;
@@ -340,40 +275,16 @@ finish:
}
-#define NODE_CLIPPED 0
-#define NODE_UNCLIPPED 15
-
-static inline qboolean GL_ClipNodeToFrustum( bspNode_t *node, int *clipflags ) {
- int flags = *clipflags;
- int i, bits, mask;
-
- for( i = 0, mask = 1; i < 4; i++, mask <<= 1 ) {
- if( flags & mask ) {
- continue;
- }
- bits = BoxOnPlaneSide( node->mins, node->maxs,
- &glr.frustumPlanes[i] );
- if( bits == BOX_BEHIND ) {
- return qfalse;
- }
- if( bits == BOX_INFRONT ) {
- flags |= mask;
- }
- }
-
- *clipflags = flags;
-
- return qtrue;
-}
#define BACKFACE_EPSILON 0.001f
-#define SIDE_FRONT 0
-#define SIDE_BACK 1
+#define BSP_CullFace( face, dot ) \
+ ( ( (dot) < -BACKFACE_EPSILON && !( (face)->drawflags & DSURF_PLANEBACK ) ) || \
+ ( (dot) > BACKFACE_EPSILON && ( (face)->drawflags & DSURF_PLANEBACK ) ) )
-void GL_DrawBspModel( bspSubmodel_t *model ) {
- bspSurface_t *face;
+void GL_DrawBspModel( mmodel_t *model ) {
+ mface_t *face;
int count;
vec3_t bounds[2];
vec_t dot;
@@ -429,13 +340,11 @@ void GL_DrawBspModel( bspSubmodel_t *model ) {
/* draw visible faces */
/* FIXME: go by headnode instead? */
- face = model->firstFace;
- count = model->numFaces;
+ face = model->firstface;
+ count = model->numfaces;
while( count-- ) {
dot = PlaneDiffFast( modelViewOrigin, face->plane );
- if( ( dot < -BACKFACE_EPSILON && face->side == SIDE_FRONT ) ||
- ( dot > BACKFACE_EPSILON && face->side == SIDE_BACK ) )
- {
+ if( BSP_CullFace( face, dot ) ) {
c.facesCulled++;
} else {
/* FIXME: trans surfaces are not supported on inline models */
@@ -449,61 +358,95 @@ void GL_DrawBspModel( bspSubmodel_t *model ) {
qglPopMatrix();
}
-static void GL_WorldNode_r( bspNode_t *node, int clipflags ) {
- bspLeaf_t *leaf;
- bspSurface_t **leafFace, *face;
- int count, side, area;
+#define NODE_CLIPPED 0
+#define NODE_UNCLIPPED 15
+
+static inline qboolean GL_ClipNode( mnode_t *node, int *clipflags ) {
+ int flags = *clipflags;
+ int i, bits, mask;
+
+ if( flags == NODE_UNCLIPPED ) {
+ return qtrue;
+ }
+ for( i = 0, mask = 1; i < 4; i++, mask <<= 1 ) {
+ if( flags & mask ) {
+ continue;
+ }
+ bits = BoxOnPlaneSide( node->mins, node->maxs,
+ &glr.frustumPlanes[i] );
+ if( bits == BOX_BEHIND ) {
+ return qfalse;
+ }
+ if( bits == BOX_INFRONT ) {
+ flags |= mask;
+ }
+ }
+
+ *clipflags = flags;
+
+ return qtrue;
+}
+
+static inline void GL_DrawLeaf( mleaf_t *leaf ) {
+ mface_t **face, **last;
+
+ if( leaf->contents == CONTENTS_SOLID ) {
+ return; // solid leaf
+ }
+ if( glr.fd.areabits && !Q_IsBitSet( glr.fd.areabits, leaf->area ) ) {
+ return; // door blocks sight
+ }
+ last = leaf->firstleafface + leaf->numleaffaces;
+ for( face = leaf->firstleafface; face < last; face++ ) {
+ (*face)->drawframe = glr.drawframe;
+ }
+}
+
+static inline void GL_DrawNode( mnode_t *node, vec_t dot ) {
+ mface_t *face, *last = node->firstface + node->numfaces;
+
+ for( face = node->firstface; face < last; face++ ) {
+ if( face->drawframe != glr.drawframe ) {
+ continue;
+ }
+ if( BSP_CullFace( face, dot ) ) {
+ c.facesCulled++;
+ } else {
+ GL_AddFace( face );
+ }
+ }
+
+ c.nodesDrawn++;
+}
+
+static void GL_WorldNode_r( mnode_t *node, int clipflags ) {
+ int side;
vec_t dot;
-
+
while( node->visframe == glr.visframe ) {
- if( gl_cull_nodes->integer && clipflags != NODE_UNCLIPPED &&
- GL_ClipNodeToFrustum( node, &clipflags ) == qfalse )
- {
+ if( !GL_ClipNode( node, &clipflags ) ) {
c.nodesCulled++;
break;
}
if( !node->plane ) {
- /* found a leaf */
- leaf = ( bspLeaf_t * )node;
- if( leaf->contents == CONTENTS_SOLID ) {
- break;
- }
- area = leaf->area;
- if( !glr.fd.areabits || Q_IsBitSet( glr.fd.areabits, area ) ) {
- leafFace = leaf->firstLeafFace;
- count = leaf->numLeafFaces;
- while( count-- ) {
- face = *leafFace++;
- face->drawframe = glr.drawframe;
- }
- }
+ GL_DrawLeaf( ( mleaf_t * )node );
break;
}
dot = PlaneDiffFast( modelViewOrigin, node->plane );
- side = ( dot < 0 );
+ if( dot < 0 ) {
+ side = 1;
+ } else {
+ side = 0;
+ }
GL_WorldNode_r( node->children[side], clipflags );
- face = node->firstFace;
- count = node->numFaces;
- while( count-- ) {
- if( face->drawframe == glr.drawframe ) {
- if( face->side == side ) {
- GL_AddFace( face );
- } else {
- c.facesCulled++;
- }
- }
- face++;
- }
-
- c.nodesDrawn++;
+ GL_DrawNode( node, dot );
node = node->children[ side ^ 1 ];
}
-
}
void GL_DrawWorld( void ) {
@@ -519,7 +462,8 @@ void GL_DrawWorld( void ) {
VectorCopy( glr.fd.vieworg, modelViewOrigin );
- GL_WorldNode_r( r_world.nodes, NODE_CLIPPED );
+ GL_WorldNode_r( gl_static.world.cache->nodes,
+ gl_cull_nodes->integer ? NODE_CLIPPED : NODE_UNCLIPPED );
GL_DrawSolidFaces();