diff options
Diffstat (limited to 'source/gl_world.c')
-rw-r--r-- | source/gl_world.c | 440 |
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(); |