Exemple #1
0
/**
 * @brief Recurse down the bsp tree and mark surfaces that are visible (not culled)
 * for being rendered
 * @sa R_DrawWorld
 * @sa R_RecurseWorld
 * @sa R_RecursiveVisibleWorldNode
 * @param[in] node The bsp node to check
 * @param[in] tile The maptile (map assembly)
 */
static void R_RecursiveWorldNode (const mBspNode_t* node, int tile)
{
	int i;
	int cullState;
	mBspSurface_t* surf;

	/* if a leaf node, nothing to mark */
	if (node->contents > CONTENTS_NODE)
		return;

	cullState = R_CullBox(node->minmaxs, node->minmaxs + 3);

	if (cullState == PSIDE_BACK)
		return;					/* culled out */

	/* pathfinding nodes are invalid here */
	assert(node->plane);

	surf = r_mapTiles[tile]->bsp.surfaces + node->firstsurface;
	for (i = 0; i < node->numsurfaces; i++, surf++)
		surf->frame = r_locals.frame;

	/* recurse down the children */
	/** @todo avoid being too precise, it's a waste of CPU time; possibly, granularity of 256x256x256 should be enough */
	if (cullState == PSIDE_FRONT) {
		/* completely inside the frustum - no need to do any further checks */
		R_RecursiveVisibleWorldNode(node->children[0], tile);
		R_RecursiveVisibleWorldNode(node->children[1], tile);
	} else {
		/* partially clipped by frustum - recurse to do finer checks */
		R_RecursiveWorldNode(node->children[0], tile);
		R_RecursiveWorldNode(node->children[1], tile);
	}
}
bool R_CullModelForEntity(entity_t *e)
{
	vec3_t mins, maxs;

	if(e == &cl.viewent)
		return false;

	if(e->angles[PITCH] || e->angles[ROLL])
	{
		Math_VectorAdd (e->origin, e->model->rmins, mins);
		Math_VectorAdd (e->origin, e->model->rmaxs, maxs);
	}
	else if(e->angles[YAW])
	{
		Math_VectorAdd (e->origin, e->model->ymins, mins);
		Math_VectorAdd (e->origin, e->model->ymaxs, maxs);
	}
	else //no rotation
	{
		Math_VectorAdd(e->origin,e->model->mins,mins);
		Math_VectorAdd(e->origin,e->model->maxs,maxs);
	}

	return R_CullBox(mins, maxs);
}
Exemple #3
0
/*
================
CL_CullTracer

check tracer bbox
================
*/
static qboolean CL_CullTracer( const vec3_t start, const vec3_t end )
{
	vec3_t	mins, maxs;
	int	i;

	// compute the bounding box
	for( i = 0; i < 3; i++ )
	{
		if( start[i] < end[i] )
		{
			mins[i] = start[i];
			maxs[i] = end[i];
		}
		else
		{
			mins[i] = end[i];
			maxs[i] = start[i];
		}
		
		// don't let it be zero sized
		if( mins[i] == maxs[i] )
		{
			maxs[i] += 1;
		}
	}

	// check bbox
	return R_CullBox( mins, maxs, RI.clipFlags );
}
void R_SetupBrushInstantForLight(entity_t *e)
{
	brushlightinstant_t *brushlightinstant;
	vec3_t	mins, maxs;
	qboolean	update;

	brushlightinstant = R_AllocateBrushLightInstant(e);

	VectorAdd (e->origin,e->model->mins, mins);
	VectorAdd (e->origin,e->model->maxs, maxs);

	if (R_CullBox (mins, maxs))
		brushlightinstant->shadowonly = true;
	else
		brushlightinstant->shadowonly = false;

	e->brushlightinstant = brushlightinstant;

	R_SetupBrushObjectSpace(e, brushlightinstant);

	update = CheckBrushLightUpdate(e, brushlightinstant);
	if (update)
	{
		R_CalcBrushVolumeVerts(e, brushlightinstant);
		
		if (!brushlightinstant->shadowonly) {
			if ( gl_cardtype == GENERIC || gl_cardtype == GEFORCE ) {//PA:
				R_CalcBrushAttenCoords(e,  brushlightinstant);
			}
			//R_SetupBrushLightHAV(e, brushlightinstant);
		}

		//make sure that we can compare the next frame
		VectorCopy(e->origin, brushlightinstant->lasteorg);
		VectorCopy(currentshadowlight->origin, brushlightinstant->lastlorg);
		VectorCopy(e->angles, brushlightinstant->lasteangles);
		brushlightinstant->lastlradius = currentshadowlight->radius;
		brushlightinstant->lastlight = currentshadowlight;
		brushlightinstant->lastent = e;
		brushlightinstant->lastshadowonly = brushlightinstant->shadowonly;
	}

	brushCacheRequests++;
	//Half angles only change when the viewer changes his position
	//this happens a lot so recalculate only this.
	if ((update) || CheckBrushHalfAngle(brushlightinstant)) {
		if (!brushlightinstant->shadowonly)
			R_SetupBrushLightHAV(e, brushlightinstant);
		VectorCopy(r_refdef.vieworg,brushlightinstant->lastvorg);

		if(!update) brushPartialCacheHits++;
	} else {
		brushFullCacheHits++;
	}

	//lock it for this frame
	brushlightinstant->lockframe = r_framecount;
}
Exemple #5
0
/*
* R_CullModelEntity
*/
int R_CullModelEntity( const entity_t *e, vec3_t mins, vec3_t maxs, float radius, bool sphereCull, bool pvsCull )
{
	if( e->flags & RF_NOSHADOW )
	{
		if( rn.renderFlags & RF_SHADOWMAPVIEW )
			return 3;
	}

	if( e->flags & RF_WEAPONMODEL )
	{
		if( rn.renderFlags & RF_NONVIEWERREF )
			return 1;
		return 0;
	}

	if( e->flags & RF_VIEWERMODEL )
	{
		//if( !(rn.renderFlags & RF_NONVIEWERREF) )
		if( !( rn.renderFlags & ( RF_MIRRORVIEW|RF_SHADOWMAPVIEW ) ) )
			return 1;
	}

	if( e->flags & RF_NODEPTHTEST )
		return 0;

	// account for possible outlines
	if( e->outlineHeight )
		radius += e->outlineHeight * r_outlines_scale->value * 1.73/*sqrt(3)*/;

	if( sphereCull )
	{
		if( R_CullSphere( e->origin, radius, rn.clipFlags ) )
			return 1;
	}
	else
	{
		if( R_CullBox( mins, maxs, rn.clipFlags ) )
			return 1;
	}

	if( pvsCull )
	{
		if( sphereCull )
		{
			if( R_VisCullSphere( e->origin, radius ) )
				return 2;
		}
		else
		{
			if( R_VisCullBox( mins, maxs ) )
				return 2;
		}
	}

	return 0;
}
Exemple #6
0
/*
* R_CullSurface
*/
qboolean R_CullSurface( const entity_t *e, const msurface_t *surf, unsigned int clipflags )
{
	const shader_t *shader = surf->shader;

	if( r_nocull->integer )
		return qfalse;
	if( ( shader->flags & SHADER_ALLDETAIL ) && !r_detailtextures->integer )
		return qtrue;

	return ( clipflags && R_CullBox( surf->mins, surf->maxs, clipflags ) );
}
//-----------------------------------------------------------------------------
// Do we have reflective glass in view?
//-----------------------------------------------------------------------------
bool IsReflectiveGlassInView( const CViewSetup& view, cplane_t &plane )
{
	// Early out if no cameras
	C_FuncReflectiveGlass *pReflectiveGlass = GetReflectiveGlassList();
	if ( !pReflectiveGlass )
		return false;

	Frustum_t frustum;
	GeneratePerspectiveFrustum( view.origin, view.angles, view.zNear, view.zFar, view.fov, view.m_flAspectRatio, frustum );

	cplane_t localPlane;
	Vector vecOrigin, vecWorld, vecDelta, vecForward;
	AngleVectors( view.angles, &vecForward, NULL, NULL );

	for ( ; pReflectiveGlass != NULL; pReflectiveGlass = pReflectiveGlass->m_pNext )
	{
		if ( pReflectiveGlass->IsDormant() )
			continue;

		Vector vecMins, vecMaxs;
		pReflectiveGlass->GetRenderBoundsWorldspace( vecMins, vecMaxs );
		if ( R_CullBox( vecMins, vecMaxs, frustum ) )
			continue;

		const model_t *pModel = pReflectiveGlass->GetModel();
		const matrix3x4_t& mat = pReflectiveGlass->EntityToWorldTransform();

		int nCount = modelinfo->GetBrushModelPlaneCount( pModel );
		for ( int i = 0; i < nCount; ++i )
		{
			modelinfo->GetBrushModelPlane( pModel, i, localPlane, &vecOrigin );

			MatrixTransformPlane( mat, localPlane, plane );			// Transform to world space
			VectorTransform( vecOrigin, mat, vecWorld );
					 
			if ( view.origin.Dot( plane.normal ) <= plane.dist )	// Check for view behind plane
				continue;
			
			VectorSubtract( vecWorld, view.origin, vecDelta );		// Backface cull
			if ( vecDelta.Dot( plane.normal ) >= 0 )
				continue;

			return true;
		}
	}

	return false;
}
/*
=============
R_CullIQM
=============
*/
static void R_CullIQM( trRefEntity_t *ent ) {
	vec3_t     localBounds[ 2 ];
	float      scale = ent->e.skeleton.scale;
	IQModel_t *model = tr.currentModel->iqm;
	IQAnim_t  *anim = model->anims;
	float     *bounds;

	// use the bounding box by the model
	bounds = model->bounds[0];
	VectorCopy( bounds, localBounds[ 0 ] );
	VectorCopy( bounds + 3, localBounds[ 1 ] );

	if ( anim && ( bounds = anim->bounds ) ) {
		// merge bounding box provided by the animation
		BoundsAdd( localBounds[ 0 ], localBounds[ 1 ],
			   bounds, bounds + 3 );
	}

	// merge bounding box provided by skeleton
	BoundsAdd( localBounds[ 0 ], localBounds[ 1 ],
		   ent->e.skeleton.bounds[ 0 ], ent->e.skeleton.bounds[ 1 ] );

	VectorScale( localBounds[0], scale, ent->localBounds[ 0 ] );
	VectorScale( localBounds[1], scale, ent->localBounds[ 1 ] );

	
	R_SetupEntityWorldBounds(ent);

	switch ( R_CullBox( ent->worldBounds ) )
	{
	case cullResult_t::CULL_IN:
		tr.pc.c_box_cull_md5_in++;
		ent->cull = cullResult_t::CULL_IN;
		return;
	case cullResult_t::CULL_CLIP:
		tr.pc.c_box_cull_md5_clip++;
		ent->cull = cullResult_t::CULL_CLIP;
		return;
	case cullResult_t::CULL_OUT:
	default:
		tr.pc.c_box_cull_md5_out++;
		ent->cull = cullResult_t::CULL_OUT;
		return;
	}
}
Exemple #9
0
/**
 * @brief Returns true if the specified entity is completely culled by the view
 * frustum, false otherwise.
 * @param[in] e The entity to check
 * @sa R_CullBox
 */
bool R_CullBspModel (const entity_t* e)
{
	vec3_t mins, maxs;

	/* no surfaces */
	if (!e->model->bsp.nummodelsurfaces)
		return true;

	if (e->isOriginBrushModel) {
		int i;
		for (i = 0; i < 3; i++) {
			mins[i] = e->origin[i] - e->model->radius;
			maxs[i] = e->origin[i] + e->model->radius;
		}
	} else {
		e->model->modBox.shift(e->origin);
	}

	return R_CullBox(mins, maxs) == PSIDE_BACK;
}
/*
===============
R_CullModelForEntity -- johnfitz -- uses correct bounds based on rotation
===============
*/
qboolean R_CullModelForEntity (entity_t *e)
{
	vec3_t mins, maxs;

	if (e->angles[0] || e->angles[2]) //pitch or roll
	{
		VectorAdd (e->origin, e->model->rmins, mins);
		VectorAdd (e->origin, e->model->rmaxs, maxs);
	}
	else if (e->angles[1]) //yaw
	{
		VectorAdd (e->origin, e->model->ymins, mins);
		VectorAdd (e->origin, e->model->ymaxs, maxs);
	}
	else //no rotation
	{
		VectorAdd (e->origin, e->model->mins, mins);
		VectorAdd (e->origin, e->model->maxs, maxs);
	}

	return R_CullBox (mins, maxs);
}
Exemple #11
0
/*
* R_CullBrushModel
*/
qboolean R_CullBrushModel( entity_t *e )
{
	qboolean rotated;
	vec3_t mins, maxs;
	float radius;
	model_t	*model = e->model;
	mbrushmodel_t *bmodel = ( mbrushmodel_t * )model->extradata;

	if( bmodel->nummodelsurfaces == 0 )
		return qtrue;

	radius = R_BrushModelBBox( e, mins, maxs, &rotated );
	if( rotated )
	{
		if( R_CullSphere( e->origin, radius, ri.clipFlags ) )
			return qtrue;
	}
	else
	{
		if( R_CullBox( mins, maxs, ri.clipFlags ) )
			return qtrue;
	}

	if( ri.params & RP_PVSCULL )
	{
		if( rotated )
		{
			if( R_VisCullSphere( e->origin, radius ) )
				return qtrue;
		}
		else
		{
			if( R_VisCullBox( mins, maxs ) )
				return qtrue;
		}
	}

	return qfalse;
}
Exemple #12
0
void R_SetupAliasModel (entity_t *e)
{
    aliashdr_t	*paliashdr;
    int			anim;
    aliasstate_t	*state = &e->aliasstate;

    // initially not visible
    e->visframe = -1;

    // setup pose/lerp data -- do it first so we don't miss updates due to culling
    paliashdr = (aliashdr_t *) Mod_Extradata (e->model);
    R_SetupAliasFrame (e, paliashdr, e->frame, state);
    R_SetupEntityTransform (e, state);
    R_BBoxForEnt (e);

    // cull it (the viewmodel is never culled)
    if (r_shadows.value > 0.01f)
    {
        if (!(e->renderfx & RF_WEAPONMODEL))
        {
            if (R_CullBox (e->mins, e->maxs))
                e->visframe = -1;
            else
                e->visframe = r_framecount;
        }
    }
    else
    {
        if (!(e->renderfx & RF_WEAPONMODEL))
        {
            if (R_CullBox (e->mins, e->maxs))
                return;
        }

        // the ent is visible now
        e->visframe = r_framecount;
    }

    // set up lighting
    overbright = gl_overbright.value;
    rs_aliaspolys += paliashdr->numtris;
    R_SetupAliasLighting (e, state->shadelight);

    // store out the alpha value
    state->shadelight[3] = ((float) e->alpha / 255.0f);

    // set up textures
    anim = (int) (cl.time * 10) & 3;
    state->tx = paliashdr->gltextures[e->skinnum][anim];

    // ensure we have a valid texture
    if (!state->tx) state->tx = notexture;

    if (!gl_fullbrights.value)
        state->fb = NULL;
    else
        state->fb = paliashdr->fbtextures[e->skinnum][anim];

    if (e->colormap && (e->model->modhint == MOD_PLAYER || e->renderfx & RF_PLAYERMODEL) && !gl_nocolors.value)
        R_GetTranslatedPlayerSkin (e->colormap, &state->tx, &state->fb);
}
Exemple #13
0
/**
 * @brief R_CullMDV
 * @param[in] model
 * @param[in,out] ent
 */
static void R_CullMDV(mdvModel_t *model, trRefEntity_t *ent)
{
	int    i;
	// compute frame pointers
	mdvFrame_t *newFrame = model->frames + ent->e.frame;
	mdvFrame_t *oldFrame = model->frames + ent->e.oldframe;

	// calculate a bounding box in the current coordinate system
	for (i = 0; i < 3; i++)
	{
		ent->localBounds[0][i] =
		    oldFrame->bounds[0][i] < newFrame->bounds[0][i] ? oldFrame->bounds[0][i] : newFrame->bounds[0][i];
		ent->localBounds[1][i] =
		    oldFrame->bounds[1][i] > newFrame->bounds[1][i] ? oldFrame->bounds[1][i] : newFrame->bounds[1][i];
	}

	// setup world bounds for intersection tests
	R_SetupEntityWorldBounds(ent);

	// cull bounding sphere ONLY if this is not an upscaled entity
	if (!ent->e.nonNormalizedAxes)
	{
		if (ent->e.frame == ent->e.oldframe)
		{
			switch (R_CullLocalPointAndRadius(newFrame->localOrigin, newFrame->radius))
			{
			case CULL_OUT:
				tr.pc.c_sphere_cull_mdx_out++;
				ent->cull = CULL_OUT;
				return;
			case CULL_IN:
				tr.pc.c_sphere_cull_mdx_in++;
				ent->cull = CULL_IN;
				return;
			case CULL_CLIP:
				tr.pc.c_sphere_cull_mdx_clip++;
				break;
			}
		}
		else
		{
			int sphereCull, sphereCullB;

			sphereCull = R_CullLocalPointAndRadius(newFrame->localOrigin, newFrame->radius);
			if (newFrame == oldFrame)
			{
				sphereCullB = sphereCull;
			}
			else
			{
				sphereCullB = R_CullLocalPointAndRadius(oldFrame->localOrigin, oldFrame->radius);
			}

			if (sphereCull == sphereCullB)
			{
				if (sphereCull == CULL_OUT)
				{
					tr.pc.c_sphere_cull_mdx_out++;
					ent->cull = CULL_OUT;
					return;
				}
				else if (sphereCull == CULL_IN)
				{
					tr.pc.c_sphere_cull_mdx_in++;
					ent->cull = CULL_IN;
					return;
				}
				else
				{
					tr.pc.c_sphere_cull_mdx_clip++;
				}
			}
		}
	}

	switch (R_CullBox(ent->worldBounds))
	{
	case CULL_IN:
		tr.pc.c_box_cull_mdx_in++;
		ent->cull = CULL_IN;
		return;
	case CULL_CLIP:
		tr.pc.c_box_cull_mdx_clip++;
		ent->cull = CULL_CLIP;
		return;
	case CULL_OUT:
	default:
		tr.pc.c_box_cull_mdx_out++;
		ent->cull = CULL_OUT;
		return;
	}
}
Exemple #14
0
/*
=================
R_ShadowPassDrawBrushModel
=================
*/
void R_ShadowPassDrawBrushModel( cl_entity_t *e, const plight_t *pl )
{
	Vector	mins, maxs;
	model_t	*clmodel;
	bool	rotated;

	clmodel = e->model;

	if( e->angles != g_vecZero )
	{
		for( int i = 0; i < 3; i++ )
		{
			mins[i] = e->origin[i] - clmodel->radius;
			maxs[i] = e->origin[i] + clmodel->radius;
		}
		rotated = true;
	}
	else
	{
		mins = e->origin + clmodel->mins;
		maxs = e->origin + clmodel->maxs;
		rotated = false;
	}

	if( R_CullBox( mins, maxs, RI.clipFlags ))
		return;

	if( RI.params & ( RP_SKYPORTALVIEW|RP_PORTALVIEW|RP_SCREENVIEW ))
	{
		if( rotated )
		{
			if( R_VisCullSphere( e->origin, clmodel->radius ))
				return;
		}
		else
		{
			if( R_VisCullBox( mins, maxs ))
				return;
		}
	}

	if( rotated ) R_RotateForEntity( e );
	else R_TranslateForEntity( e );

	if( rotated ) tr.modelorg = RI.objectMatrix.VectorITransform( RI.vieworg );
	else tr.modelorg = RI.vieworg - e->origin;

	// accumulate lit surfaces
	msurface_t *psurf = &clmodel->surfaces[clmodel->firstmodelsurface];
	for( int i = 0; i < clmodel->nummodelsurfaces; i++, psurf++ )
	{
		float *v;
		int k;

		if( psurf->flags & (SURF_DRAWTILED|SURF_PORTAL|SURF_REFLECT))
			continue;

		R_AddToGrassChain( psurf, pl->frustum, pl->clipflags, false );

		if( R_CullSurfaceExt( psurf, pl->frustum, 0 ))
			continue;

		// draw depth-mask on transparent textures
		if( psurf->flags & SURF_TRANSPARENT )
		{
			pglEnable( GL_ALPHA_TEST );
			pglEnable( GL_TEXTURE_2D );
			pglAlphaFunc( GL_GREATER, 0.0f );
			GL_Bind( GL_TEXTURE0, psurf->texinfo->texture->gl_texturenum );
		}

		pglBegin( GL_POLYGON );
		for( k = 0, v = psurf->polys->verts[0]; k < psurf->polys->numverts; k++, v += VERTEXSIZE )
		{
			if( psurf->flags & SURF_TRANSPARENT )
				pglTexCoord2f( v[3], v[4] );
			pglVertex3fv( v );
		}
		pglEnd();

		if( psurf->flags & SURF_TRANSPARENT )
		{
			pglDisable( GL_ALPHA_TEST );
			pglDisable( GL_TEXTURE_2D );
		}
	}

	R_LoadIdentity();	// restore worldmatrix
}
Exemple #15
0
/*
=================
R_DrawAliasModel

=================
*/
void R_DrawAliasModel (entity_t *e)
{
	int			i, j;
	int			lnum;
	vec3_t		dist;
	float		add;
	model_t		*clmodel;
	vec3_t		mins, maxs;
	aliashdr_t	*paliashdr;
	trivertx_t	*verts, *v;
	int			index;
	float		s, t, an;
	int			anim;

	clmodel = currententity->model;

	VectorAdd (currententity->origin, clmodel->mins, mins);
	VectorAdd (currententity->origin, clmodel->maxs, maxs);

	if (R_CullBox (mins, maxs))
		return;


	VectorCopy (currententity->origin, r_entorigin);
	VectorSubtract (r_origin, r_entorigin, modelorg);

	//
	// get lighting information
	//

	ambientlight = shadelight = R_LightPoint (currententity->origin);

	// allways give the gun some light
	if (e == &cl.viewent && ambientlight < 24)
		ambientlight = shadelight = 24;

	for (lnum=0 ; lnum<MAX_DLIGHTS ; lnum++)
	{
		if (cl_dlights[lnum].die >= cl.time)
		{
			VectorSubtract (currententity->origin,
							cl_dlights[lnum].origin,
							dist);
			add = cl_dlights[lnum].radius - Length(dist);

			if (add > 0) {
				ambientlight += add;
				//ZOID models should be affected by dlights as well
				shadelight += add;
			}
		}
	}

	// clamp lighting so it doesn't overbright as much
	if (ambientlight > 128)
		ambientlight = 128;
	if (ambientlight + shadelight > 192)
		shadelight = 192 - ambientlight;

	// ZOID: never allow players to go totally black
	i = currententity - cl_entities;
	if (i >= 1 && i<=cl.maxclients /* && !strcmp (currententity->model->name, "progs/player.mdl") */)
		if (ambientlight < 8)
			ambientlight = shadelight = 8;

	// HACK HACK HACK -- no fullbright colors, so make torches full light
	if (!strcmp (clmodel->name, "progs/flame2.mdl")
		|| !strcmp (clmodel->name, "progs/flame.mdl") )
		ambientlight = shadelight = 256;

	shadedots = r_avertexnormal_dots[((int)(e->angles[1] * (SHADEDOT_QUANT / 360.0))) & (SHADEDOT_QUANT - 1)];
	shadelight = shadelight / 200.0;
	
	an = e->angles[1]/180*M_PI;
	shadevector[0] = cos(-an);
	shadevector[1] = sin(-an);
	shadevector[2] = 1;
	VectorNormalize (shadevector);

	//
	// locate the proper data
	//
	paliashdr = (aliashdr_t *)Mod_Extradata (currententity->model);

	c_alias_polys += paliashdr->numtris;

	//
	// draw all the triangles
	//

	GL_DisableMultitexture();

    glPushMatrix ();
	R_RotateForEntity (e);

	if (!strcmp (clmodel->name, "progs/eyes.mdl") && gl_doubleeyes.value) {
		glTranslatef (paliashdr->scale_origin[0], paliashdr->scale_origin[1], paliashdr->scale_origin[2] - (22 + 8));
// double size of eyes, since they are really hard to see in gl
		glScalef (paliashdr->scale[0]*2, paliashdr->scale[1]*2, paliashdr->scale[2]*2);
	} else {
		glTranslatef (paliashdr->scale_origin[0], paliashdr->scale_origin[1], paliashdr->scale_origin[2]);
		glScalef (paliashdr->scale[0], paliashdr->scale[1], paliashdr->scale[2]);
	}

	anim = (int)(cl.time*10) & 3;
    GL_Bind(paliashdr->gl_texturenum[currententity->skinnum][anim]);

	// we can't dynamically colormap textures, so they are cached
	// seperately for the players.  Heads are just uncolored.
	if (currententity->colormap != vid.colormap && !gl_nocolors.value)
	{
		i = currententity - cl_entities;
		if (i >= 1 && i<=cl.maxclients /* && !strcmp (currententity->model->name, "progs/player.mdl") */)
		    GL_Bind(playertextures - 1 + i);
	}

	if (gl_smoothmodels.value)
		glShadeModel (GL_SMOOTH);
	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

	if (gl_affinemodels.value)
		glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);

	R_SetupAliasFrame (currententity->frame, paliashdr);

	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);

	glShadeModel (GL_FLAT);
	if (gl_affinemodels.value)
		glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);

	glPopMatrix ();

	if (r_shadows.value)
	{
		glPushMatrix ();
		R_RotateForEntity (e);
		glDisable (GL_TEXTURE_2D);
		glEnable (GL_BLEND);
		glColor4f (0,0,0,0.5);
		GL_DrawAliasShadow (paliashdr, lastposenum);
		glEnable (GL_TEXTURE_2D);
		glDisable (GL_BLEND);
		glColor4f (1,1,1,1);
		glPopMatrix ();
	}

}
Exemple #16
0
/*
=================
R_FindBmodelMirrors

Check all bmodel surfaces and make personal mirror chain
=================
*/
void R_FindBmodelMirrors( cl_entity_t *e, qboolean static_entity )
{
	mextrasurf_t	*extrasurf;
	vec3_t		mins, maxs;
	msurface_t	*psurf;
	model_t		*clmodel;
	qboolean		rotated;
	int		i, clipFlags;

	clmodel = e->model;

	if( static_entity )
	{
		Matrix4x4_LoadIdentity( RI.objectMatrix );

		if( R_CullBox( clmodel->mins, clmodel->maxs, RI.clipFlags ))
			return;

		VectorCopy( RI.cullorigin, tr.modelorg );
		clipFlags = RI.clipFlags;
	}
	else
	{
		if( !VectorIsNull( e->angles ))
		{
			for( i = 0; i < 3; i++ )
			{
				mins[i] = e->origin[i] - clmodel->radius;
				maxs[i] = e->origin[i] + clmodel->radius;
			}
			rotated = true;
		}
		else
		{
			VectorAdd( e->origin, clmodel->mins, mins );
			VectorAdd( e->origin, clmodel->maxs, maxs );
			rotated = false;
		}

		if( R_CullBox( mins, maxs, RI.clipFlags ))
			return;

		if( !VectorIsNull( e->origin ) || !VectorIsNull( e->angles ))
		{
			if( rotated ) Matrix4x4_CreateFromEntity( RI.objectMatrix, e->angles, e->origin, 1.0f );
			else Matrix4x4_CreateFromEntity( RI.objectMatrix, vec3_origin, e->origin, 1.0f );
		}
		else Matrix4x4_LoadIdentity( RI.objectMatrix );

		e->visframe = tr.framecount; // visible

		if( rotated ) Matrix4x4_VectorITransform( RI.objectMatrix, RI.cullorigin, tr.modelorg );
		else VectorSubtract( RI.cullorigin, e->origin, tr.modelorg );

		clipFlags = 0;
	}

	psurf = &clmodel->surfaces[clmodel->firstmodelsurface];
	for( i = 0; i < clmodel->nummodelsurfaces; i++, psurf++ )
	{
		if(!( psurf->flags & SURF_REFLECT ))
			continue;

		if( R_CullSurface( psurf, clipFlags ))
			continue;

		extrasurf = SURF_INFO( psurf, RI.currentmodel );
		extrasurf->mirrorchain = tr.mirror_entities[tr.num_mirror_entities].chain;
		tr.mirror_entities[tr.num_mirror_entities].chain = extrasurf;
	}

	// store new mirror entity
	if( !static_entity && tr.mirror_entities[tr.num_mirror_entities].chain != NULL )
	{
		tr.mirror_entities[tr.num_mirror_entities].ent = RI.currententity;
		tr.num_mirror_entities++;
	}
}
Exemple #17
0
void R_DrawBrushModel(entity_t *e) {
	int k;
	vec3_t mins, maxs;
	model_t *clmodel;
	bool rotated;
	int i;
	extern vec3_t lightcolor;
	int lnum;
	vec3_t dist;
	float add;
	float modelorg[3];

	clmodel = e->model;

	if (e->angles[0] || e->angles[1] || e->angles[2]) {
		rotated = true;
		for (i = 0; i < 3; i++) {
			mins[i] = e->origin[i] - clmodel->radius;
			maxs[i] = e->origin[i] + clmodel->radius;
		}
	} else {
		rotated = false;
		VectorAdd(e->origin, clmodel->mins, mins);
		VectorAdd(e->origin, clmodel->maxs, maxs);
	}

	if (R_CullBox(mins, maxs))
		return;

	//Lighting for model
	//dynamic lights for non lightmaped bmodels
	if (clmodel->firstmodelsurface == 0) {
		R_LightPoint(e->origin);
		for (lnum = 0; lnum < MAX_DLIGHTS; lnum++) {
			if (cl_dlights[lnum].die >= cl.time) {
				VectorSubtract(e->origin, cl_dlights[lnum].origin, dist);
				add = cl_dlights[lnum].radius - VectorLength(dist);
				if (add > 0) {
					lightcolor[0] += add * cl_dlights[lnum].colour[0];
					lightcolor[1] += add * cl_dlights[lnum].colour[1];
					lightcolor[2] += add * cl_dlights[lnum].colour[2];
				}
			}
		}
		VectorScale(lightcolor, 1.0f / 100.0f, lightcolor);

		if (gl_ammoflash.getBool()) {
			lightcolor[0] += sin(2 * cl.time * M_PI) / 4;
			lightcolor[1] += sin(2 * cl.time * M_PI) / 4;
			lightcolor[2] += sin(2 * cl.time * M_PI) / 4;
		}

		glColor3fv(lightcolor);
	} else {
		glColor3f(1.0, 1.0, 1.0);
		memset(lightmap_polys, 0, sizeof (lightmap_polys));
	}

	VectorSubtract(r_refdef.vieworg, e->origin, modelorg);
	if (rotated) {
		vec3_t temp;
		vec3_t forward, right, up;

		VectorCopy(modelorg, temp);
		AngleVectors(e->angles, forward, right, up);
		modelorg[0] = DotProduct(temp, forward);
		modelorg[1] = -DotProduct(temp, right);
		modelorg[2] = DotProduct(temp, up);
	}

	glPushMatrix();
	e->angles[0] = -e->angles[0]; // stupid quake bug
	R_RotateForEntity(e);
	e->angles[0] = -e->angles[0]; // stupid quake bug

	// calculate dynamic lighting for bmodel if it's not an
	// instanced model
	if (clmodel->firstmodelsurface != 0 && !gl_flashblend.getBool()) {
		for (k = 0; k < MAX_DLIGHTS; k++) {
			if ((cl_dlights[k].die < cl.time) ||
					(!cl_dlights[k].radius))
				continue;

			R_MarkLights(&cl_dlights[k], 1 << k,
					clmodel->nodes + clmodel->hulls[0].firstclipnode);
		}
	}

	R_DrawBrush(clmodel, &modelorg[0]);

	glPopMatrix();
}
Exemple #18
0
void R_RecursiveWorldNode(mnode_t *node, float *modelorg) {
	int c, side;
	mplane_t *plane;
	msurface_t *surf, **mark;
	mleaf_t *pleaf;
	double dot;

	//make sure we are still inside the world
	if (node->contents == CONTENTS_SOLID)
		return; // solid

	//is this node visable
	if (node->visframe != r_visframecount)
		return;

	//i think this checks if its on the screen and not behind the viewer
	if (R_CullBox(node->minmaxs, node->minmaxs + 3))
		return;

	// if a leaf node, draw stuff
	if (node->contents < 0) {
		pleaf = (mleaf_t *) node;

		mark = pleaf->firstmarksurface;
		c = pleaf->nummarksurfaces;

		if (c) {
			do {
				(*mark)->visframe = r_framecount;
				mark++;
			} while (--c);
		}

		// deal with model fragments in this leaf
		if (pleaf->efrags)
			R_StoreEfrags(&pleaf->efrags);

		return;
	}

	// node is just a decision point, so go down the apropriate sides
	// find which side of the node we are on
	plane = node->plane;

	switch (plane->type) {
		case PLANE_X:
			dot = modelorg[0] - plane->dist;
			break;
		case PLANE_Y:
			dot = modelorg[1] - plane->dist;
			break;
		case PLANE_Z:
			dot = modelorg[2] - plane->dist;
			break;
		default:
			dot = DotProduct(modelorg, plane->normal) - plane->dist;
			break;
	}

	if (dot >= 0)
		side = 0;
	else
		side = 1;

	// recurse down the children, front side first
	R_RecursiveWorldNode(node->children[side], modelorg);

	// recurse down the back side
	if (r_outline.getBool())
		R_RecursiveWorldNode(node->children[!side], modelorg);

	// draw stuff
	c = node->numsurfaces;

	if (c) {
		surf = cl.worldmodel->surfaces + node->firstsurface;

		{
			for (; c; c--, surf++) {
				if (surf->visframe != r_framecount)
					continue;

				if (surf->flags & SURF_DRAWSKY) {
					surf->texturechain = skychain;
					skychain = surf;
				} else if (surf->flags & SURF_DRAWTURB) {
					surf->texturechain = waterchain;
					waterchain = surf;
				} else {
					//add chain for drawing.
					surf->texturechain = surf->texinfo->texture->texturechain;
					surf->texinfo->texture->texturechain = surf;

					//setup eyecandy chain
					if ((surf->flags & SURF_UNDERWATER && gl_caustics.getBool()) ||
							(surf->flags & SURF_SHINY_METAL && gl_shiny.getBool()) ||
							(surf->flags & SURF_SHINY_GLASS && gl_shiny.getBool())) {
						surf->extra = extrachain;
						extrachain = surf;
					}

					if (r_outline.getBool()) {
						surf->outline = outlinechain;
						outlinechain = surf;
					}
				}
			}
		}
	}

	// recurse down the back side
	if (!r_outline.getBool())
		R_RecursiveWorldNode(node->children[!side], modelorg);
}
Exemple #19
0
void R_DrawAliasModel(entity_t *e) {
    extern void AddFire(vec3_t org, float size);

    int lnum;
    vec3_t dist;
    float add;
    model_t *clmodel;
    vec3_t mins, maxs;
    aliashdr_t *paliashdr;
    float an; //s, t,
    int anim;
    md2_t *pheader; // LH / muff
    int shell; //QMB :model shells

    //not implemented yet
    //	byte		c, *color;	//QMB :color map

    //does the model need a shell?
    if (cl.items & IT_QUAD && e == &cl.viewent)
        shell = true;
    else
        shell = false;

    //set get the model from the e
    clmodel = e->model;

    //work out its max and mins
    VectorAdd(e->origin, clmodel->mins, mins);
    VectorAdd(e->origin, clmodel->maxs, maxs);
    //make sure its in screen
    if (R_CullBox(mins, maxs) && e != &cl.viewent)
        return;

    //QMB: FIXME
    //should use a particle emitter linked to the model for its org
    //needs to be linked when the model is created and distroyed when
    //the entity is distroyed
    //check if its a fire and add the particle effect
    if (!strcmp(clmodel->name, "progs/flame.mdl"))
        AddFire(e->origin, 4);

    if (!strcmp(clmodel->name, "progs/flame2.mdl")) {
        AddFire(e->origin, 10);
        return; //do not draw the big fire model, its just a place holder for the particles
    }

    // get lighting information
    //QMB: FIXME
    //SHOULD CHANGE TO A PASSED VAR
    //get vertex normals (for lighting and shells)
    shadedots = r_avertexnormal_dots[((int) (e->angles[1] * (SHADEDOT_QUANT / 360.0))) & (SHADEDOT_QUANT - 1)];

    //make a default lighting direction
    an = e->angles[1] / 180 * M_PI;
    shadevector[0] = cos(-an);
    shadevector[1] = sin(-an);
    shadevector[2] = 1; //e->angles[0];
    VectorNormalize(shadevector);

    //get the light for the model
    R_LightPoint(e->origin); // LordHavoc: lightcolor is all that matters from this

    //work out lighting from the dynamic lights
    for (lnum = 0; lnum < MAX_DLIGHTS; lnum++) {
        //if the light is alive
        if (cl_dlights[lnum].die >= cl.time) {
            //work out the distance to the light
            VectorSubtract(e->origin, cl_dlights[lnum].origin, dist);
            add = cl_dlights[lnum].radius - VectorLength(dist);
            //if its close enough add light from it
            if (add > 0) {
                lightcolor[0] += add * cl_dlights[lnum].colour[0];
                lightcolor[1] += add * cl_dlights[lnum].colour[1];
                lightcolor[2] += add * cl_dlights[lnum].colour[2];
            }
        }
    }

    //scale lighting to floating point
    VectorScale(lightcolor, 1.0f / 200.0f, lightcolor);

    // locate the proper data
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

    if (gl_n_patches && gl_npatches.getBool()) {
        glEnable(GL_PN_TRIANGLES_ATI);
        glPNTrianglesiATI(GL_PN_TRIANGLES_TESSELATION_LEVEL_ATI, gl_npatches.getInt());

        if (true)
            glPNTrianglesiATI(GL_PN_TRIANGLES_POINT_MODE_ATI, GL_PN_TRIANGLES_POINT_MODE_CUBIC_ATI);
        else
            glPNTrianglesiATI(GL_PN_TRIANGLES_POINT_MODE_ATI, GL_PN_TRIANGLES_POINT_MODE_LINEAR_ATI);

        if (true)
            glPNTrianglesiATI(GL_PN_TRIANGLES_NORMAL_MODE_ATI, GL_PN_TRIANGLES_NORMAL_MODE_QUADRATIC_ATI);
        else
            glPNTrianglesiATI(GL_PN_TRIANGLES_NORMAL_MODE_ATI, GL_PN_TRIANGLES_NORMAL_MODE_LINEAR_ATI);
    }

    if (clmodel->aliastype == MD3IDHEADER) {
        //do nothing for testing
        if (!r_modeltexture.getBool()) {
            GL_DisableTMU(GL_TEXTURE0_ARB);
        }//disable texture if needed

        R_DrawQ3Model(e, false, false);

        if (!r_modeltexture.getBool()) {
            GL_EnableTMU(GL_TEXTURE0_ARB);
        }//enable texture if needed

        if (r_celshading.getBool() || r_outline.getBool()) {
            glCullFace(GL_BACK);
            glEnable(GL_BLEND);
            glPolygonMode(GL_FRONT, GL_LINE);

            if (e == &cl.viewent) {
                glLineWidth(1.0f);
            } else {
                glLineWidth(5.0f);
            }

            glEnable(GL_LINE_SMOOTH);

            GL_DisableTMU(GL_TEXTURE0_ARB);

            glColor3f(0.0, 0.0, 0.0);
            R_DrawQ3Model(e, false, true);
            glColor3f(1.0, 1.0, 1.0);

            GL_EnableTMU(GL_TEXTURE0_ARB);

            glPolygonMode(GL_FRONT, GL_FILL);
            glDisable(GL_BLEND);
            glCullFace(GL_FRONT);
        }

        if (shell) {
            glBindTexture(GL_TEXTURE_2D, quadtexture);
            glColor4f(1.0, 1.0, 1.0, 0.5);
            glEnable(GL_BLEND);
            R_DrawQ3Model(e, true, false);
            glDisable(GL_BLEND);
            glColor3f(1.0, 1.0, 1.0);
        }
    } else if (clmodel->aliastype != ALIASTYPE_MD2) {
        paliashdr = (aliashdr_t *) Mod_Extradata(e->model);
        c_alias_polys += paliashdr->numtris;

        glPushMatrix();

        //interpolate unless its the viewmodel
        if (e != &cl.viewent)
            R_BlendedRotateForEntity(e);
        else
            R_RotateForEntity(e);

        glTranslatef(paliashdr->scale_origin[0], paliashdr->scale_origin[1], paliashdr->scale_origin[2]);
        glScalef(paliashdr->scale[0], paliashdr->scale[1], paliashdr->scale[2]);

        anim = (int) (cl.time * 10) & 3;
        glBindTexture(GL_TEXTURE_2D, paliashdr->gl_texturenum[e->skinnum][anim]);

        // draw all the triangles
        if (!r_modeltexture.getBool()) {
            GL_DisableTMU(GL_TEXTURE0_ARB);
        } else {
            //highlighting test code
            if (0 && gl_textureunits > 2) {
                GL_EnableTMU(GL_TEXTURE1_ARB);

                glBindTexture(GL_TEXTURE_2D, TextureManager::highlighttexture);

                glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
                glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
                glEnable(GL_TEXTURE_GEN_S);
                glEnable(GL_TEXTURE_GEN_T);
                //need correct mode
                glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
                glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_ADD);
                glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, 1.0);

                //glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD);
            }
        }

        glColor3fv(lightcolor);
        R_SetupAliasBlendedFrame(e->frame, paliashdr, e, false, false);
        glDisable(GL_TEXTURE_1D);

        if (r_celshading.getBool() || r_outline.getBool()) {
            glColor3f(0.0, 0.0, 0.0);
            R_SetupAliasBlendedFrame(e->frame, paliashdr, e, false, true);
            glColor3f(1.0, 1.0, 1.0);
        }

        if (!r_modeltexture.getBool()) {
            GL_EnableTMU(GL_TEXTURE0_ARB);
        } else {
            if (0 && gl_textureunits > 2) {
                //highlighting test code
                glDisable(GL_TEXTURE_GEN_S);
                glDisable(GL_TEXTURE_GEN_T);
                GL_DisableTMU(GL_TEXTURE1_ARB);
                glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
            }
        }
        glActiveTexture(GL_TEXTURE0_ARB);

        //colour map code... not working yet...
        /*		if (e->colormap != vid.colormap && !gl_nocolors.value)
                {
                    if (paliashdr->gl_texturenumColorMap&&paliashdr->gl_texturenumColorMap){
                        glBindTexture(GL_TEXTURE_2D,paliashdr->gl_texturenumColorMap);
                        c = (byte)e->colormap & 0xF0;
                        c += (c >= 128 && c < 224) ? 4 : 12; // 128-224 are backwards ranges
                        color = (byte *) (&d_8to24table[c]);
                        //glColor3fv(color);
                        glColor3f(1.0,1.0,1.0);
                    }
                }*/
        if (shell) {
            glBindTexture(GL_TEXTURE_2D, quadtexture);
            glColor4f(1.0, 1.0, 1.0, 0.5);
            glEnable(GL_BLEND);
            R_SetupAliasBlendedFrame(e->frame, paliashdr, e, true, false);
            glDisable(GL_BLEND);
            glColor3f(1.0, 1.0, 1.0);
        }
        glPopMatrix();

    } else {
        pheader = (md2_t *) Mod_Extradata(e->model);
        c_alias_polys += pheader->num_tris;

        glBindTexture(GL_TEXTURE_2D, pheader->gl_texturenum[e->skinnum]);
        R_SetupQ2AliasFrame(e, pheader);
    }

    if (gl_n_patches && gl_npatches.getBool()) {
        glDisable(GL_PN_TRIANGLES_ATI);
    }

    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
}
Exemple #20
0
/*
* R_DrawWorld
*/
void R_DrawWorld( void )
{
	unsigned int i;
	int clipFlags, msec = 0;
	unsigned int dlightBits;
	unsigned int shadowBits;
	bool worldOutlines;

	if( !r_drawworld->integer )
		return;
	if( !rsh.worldModel )
		return;
	if( rn.renderFlags & RF_SHADOWMAPVIEW )
		return;

	VectorCopy( rn.refdef.vieworg, modelOrg );

	worldOutlines = mapConfig.forceWorldOutlines || ( rn.refdef.rdflags & RDF_WORLDOUTLINES );

	if( worldOutlines && (rf.viewcluster != -1) && r_outlines_scale->value > 0 )
		rsc.worldent->outlineHeight = max( 0.0f, r_outlines_world->value );
	else
		rsc.worldent->outlineHeight = 0;
	Vector4Copy( mapConfig.outlineColor, rsc.worldent->outlineColor );

	clipFlags = rn.clipFlags;
	dlightBits = 0;
	shadowBits = 0;

	if( r_nocull->integer )
		clipFlags = 0;

	// cull dynamic lights
	if( !( rn.renderFlags & RF_ENVVIEW ) ) {
		if( r_dynamiclight->integer == 1 && !r_fullbright->integer ) {
			for( i = 0; i < rsc.numDlights; i++ ) {
				if( R_CullSphere( rsc.dlights[i].origin, rsc.dlights[i].intensity, clipFlags ) ) {
					continue;
				}
				dlightBits |= 1<<i;
			}
		}
	}

	// cull shadowmaps
	if( !( rn.renderFlags & RF_ENVVIEW ) ) {
		for( i = 0; i < rsc.numShadowGroups; i++ ) {
			shadowGroup_t *grp = rsc.shadowGroups + i;
			if( R_CullBox( grp->visMins, grp->visMaxs, clipFlags ) ) {
				continue;
			}
			shadowBits |= grp->bit;
		}
	}

	rn.dlightBits = dlightBits;
	rn.shadowBits = shadowBits;

	if( r_speeds->integer )
		msec = ri.Sys_Milliseconds();

	R_RecursiveWorldNode( rsh.worldBrushModel->nodes, clipFlags, dlightBits, shadowBits );

	if( r_speeds->integer )
		rf.stats.t_world_node += ri.Sys_Milliseconds() - msec;
}