Beispiel #1
0
static bool R_UpdateShadowOrigin (entity_t *e)
{
	vec3_t start, end;

	if (e->lighting == NULL)
		return false;

	if (e->lighting->state == LIGHTING_READY)
		return true;

	VectorCopy(e->origin, start);
	VectorCopy(e->origin, end);

	end[2] = start[2] - MESH_SHADOW_MAX_DISTANCE;

	/* do the trace */
	R_Trace(start, end, 0.0, MASK_SOLID);

	/* resolve the shadow origin and direction */
	if (refdef.trace.leafnum) {
		/* hit something */
		VectorCopy(refdef.trace.endpos, e->lighting->shadowOrigin);
		e->lighting->state = LIGHTING_READY;
		return true;
	}

	return false;
}
Beispiel #2
0
/*
 * Cl_LocationThere
 *
 * Returns the description of the location nearest the client's crosshair.
 */
const char *Cl_LocationThere(void) {
	vec3_t dest;

	// project vector from view position and angle
	VectorMA(r_view.origin, 8192.0, r_view.forward, dest);

	// and trace to world model
	R_Trace(r_view.origin, dest, 0, MASK_SHOT);

	return Cl_Location(r_view.trace.end);
}
Beispiel #3
0
/** @todo bad implementation -- copying light pointers every frame is a very wrong idea
 * @brief Recalculate active lights list for the given entity; R_CalcTransform(ent) should be called before this
 * @note to accelerate math, the diagonal of aabb is used to approximate max distance from entity's origin to its most distant point
 * while this is a gross exaggeration for many models, the sole purpose of it is to be used for filtering out distant lights,
 * so nothing is broken by it.
 * @param[in] ent Entity to recalculate lights for
 * @sa R_AddLightToEntity
 */
void R_UpdateLightList (entity_t *ent)
{
	int i;
	vec_t *pos; /**< Worldspace position for which lighting is calculated */
	entity_t *rootEnt; /**< The root entitity of tagent tree, which holds the lighting data (af any) */
	lighting_t *ltng; /**< Lighting data for the entity being processed */
	vec3_t diametralVec; /** < conservative estimate of entity's bounding sphere diameter, in vector form */
	float diameter; /** < value of this entity's diameter (approx) */
	vec3_t fakeSunPos; /**< as if sun wasn't at infinite distance */
	bool cached = false;

	/* Find the root of tagent tree which actually owns the lighting data; it is assumed that there is no loops,
	 * since R_CalcTransform calls Com_Error on those */
	 for (rootEnt = ent; rootEnt->tagent; rootEnt = ent->tagent)
		;

	ltng = ent->lighting = rootEnt->lighting;

	if (!ltng) {
		/* Entity got no lighting data, so substitute defaults (no dynamic lights, but exposed to sunlight) */
		/** @todo Replace this hack with something more legit (hack can cause bizarre stencil shadows if enabled) */
		OBJZERO(fakeLightingData);
		ent->lighting = &fakeLightingData;
		return;
	}

	if (ltng->lastLitFrame == r_locals.frame)
		return; /* nothing to do, already calculated lighting for this frame */

	ltng->lastLitFrame = r_locals.frame;

	/* we have to use the offset from (accumulated) transform matrix, because entity origin is not necessarily the point where model is acually rendered */
	pos = ent->transform.matrix + 12; /* type system hack, sorry */

	VectorSubtract(ent->maxs, ent->mins, diametralVec); /** @todo what if origin is NOT inside aabb? then this estimate will not be conservative enough */
	diameter = VectorLength(diametralVec);

	/** @todo clear caches when r_dynamic_lights cvar is changed OR always keep maximal # of static lights in the cache */
	if (VectorDist(pos, ltng->lastCachePos) < CACHE_CLEAR_TRESHOLD) {
		cached = true;
	} else {
		ltng->numLights = 0; /* clear the list of lights */
		ltng->numCachedLights = 0;
		VectorCopy(pos, ltng->lastCachePos);
	}

	/* Check if origin of this entity is hit by sunlight (not the best test, but at least fast) */
	if (!cached) {
		if (ent->flags & RF_ACTOR) { /** @todo Hack to avoid dropships being shadowed by lightclips placed at them. Should be removed once correct global illumination model is done */
			VectorMA(pos, 8192.0, refdef.sunVector, fakeSunPos);
			R_Trace(pos, fakeSunPos, 0, MASK_SOLID);
			ltng->inShadow = refdef.trace.fraction != 1.0;
		} else {
			ltng->inShadow = false;
		}
	}

	if (!r_dynamic_lights->integer)
		return;

	if (!cached) {
		/* Rebuild list of static lights */
		for (i = 0; i < refdef.numStaticLights; i++) {
			light_t *light = &refdef.staticLights[i];
			const float distSqr = VectorDistSqr(pos, light->origin);

			if (distSqr > (diameter + light->radius) * (diameter + light->radius))
				continue;

			R_Trace(pos, light->origin, 0, MASK_SOLID);

			if (refdef.trace.fraction == 1.0)
				R_AddLightToEntity(pos, ltng, light, distSqr);
		}
		/* Save static lights to cache */
		for (i = 0; i < ltng->numLights; i++)
			ltng->cachedLights[i] = ltng->lights[i];
		ltng->numCachedLights = ltng->numLights;
	} else {
		/* Copy static lights from cache */
		for (i = 0; i < ltng->numCachedLights; i++)
			ltng->lights[i] = ltng->cachedLights[i];
		ltng->numLights = ltng->numCachedLights;
	}

	/* add dynamic lights, too */
	for (i = 0; i < refdef.numDynamicLights; i++) {
		light_t *light = &refdef.dynamicLights[i];
		const float distSqr = VectorDistSqr(pos, light->origin);

		if (distSqr > (diameter + light->radius) * (diameter + light->radius))
			continue;

		R_Trace(pos, light->origin, 0, MASK_SOLID);

		if (refdef.trace.fraction == 1.0)
			R_AddLightToEntity(pos, ltng, light, distSqr);
	}
}
Beispiel #4
0
/*
-----------------------------------------------------------------------------
 Function: 
 
 Parameters:
 
 Returns:
 
 Notes: 

-----------------------------------------------------------------------------
*/
PUBLIC void fire_lead( player_t *self )
{
	entity_t *closest;
	int damage;
	int dx, dy, dist;
	int d1, shot_dist, n;

	switch( self->weapon )
	{
		case WEAPON_PISTOL:
			Sound_StartSound( NULL, 0, CHAN_WEAPON, Sound_RegisterSound( "sfx/012.wav" ), 1, ATTN_NORM, 0 );
			break;

		case WEAPON_AUTO:
			Sound_StartSound( NULL, 0, CHAN_WEAPON, Sound_RegisterSound( "sfx/011.wav" ), 1, ATTN_NORM, 0 );
			break;

		case WEAPON_CHAIN:
			Sound_StartSound( NULL, 0, CHAN_WEAPON, Sound_RegisterSound( "sfx/013.wav" ), 1, ATTN_NORM, 0 );
			break;
	}
	self->madenoise = true;

	dist = 0x7fffffffl;
	closest = NULL;

	for( n = 0 ; n < NumGuards; ++n )
	{
		if( Guards[ n ].flags & FL_SHOOTABLE ) // && Guards[n].flags&FL_VISABLE
		{
			shot_dist = Point2LineDist( Guards[ n ].x - self->position.origin[ 0 ], Guards[ n ].y - self->position.origin[ 1 ], self->position.angle );			
			if( shot_dist > (2 * TILEGLOBAL / 3) )
			{
				continue; // miss
			}

			d1 = LineLen2Point( Guards[ n ].x - self->position.origin[ 0 ], Guards[ n ].y - self->position.origin[ 1 ], self->position.angle );
			if( d1 < 0 || d1 > dist )
			{
				continue;
			}
			
			if( ! Level_CheckLine( Guards[ n ].x, Guards[ n ].y, Player.position.origin[0], Player.position.origin[1], r_world ) )
			{
			//if( ! CheckLine( &Guards[ n ] ) )
				continue; // obscured
			}

			dist = d1;
			closest = &Guards[ n ];
		}
	}

	if( ! closest ) // missed
	{
		r_trace_t trace;

		trace.a = NormalizeAngle( self->position.angle - DEG2FINE( 2 ) + rand() % (DEG2FINE( 4 ) ) );
		trace.x = self->position.origin[ 0 ];
		trace.y = self->position.origin[ 1 ];
		trace.flags = TRACE_BULLET;
		trace.tile_vis = NULL;
		R_Trace( &trace, r_world );

		if( trace.flags & TRACE_HIT_DOOR )
		{
			Sound_StartSound( NULL, 0, CHAN_AUTO, Sound_RegisterSound( "lsfx/028.wav" ), 1, ATTN_NORM, 0 );
		}
		return;
	}

// hit something
	dx = ABS( closest->tilex - self->tilex );
	dy = ABS( closest->tiley - self->tiley );
	dist = max_of_2( dx, dy );

	if( dist < 2 )
	{
		damage = US_RndT() / 4;
	}
	else if( dist < 4 )
	{
		damage = US_RndT() / 6;
	}
	else
	{
		if( US_RndT() / 12 < dist ) 
		{
			return; // missed
		}

		damage = US_RndT() / 6;
	}

	A_DamageActor( closest, damage );
}
Beispiel #5
0
/**
 * @brief Flares are batched by their texture.  Usually, this means one draw operation
 * for all flares in view.  Flare visibility is calculated every few millis, and
 * flare alpha is ramped up or down depending on the results of the visibility
 * trace.  Flares are also faded according to the angle of their surface to the
 * view origin.
 */
void R_DrawFlareSurfaces (const mBspSurfaces_t* surfs, glElementIndex_t* indexPtr)
{
	const image_t* image;
	int i, j, k, l, m;
	vec3_t view, verts[4];
	vec3_t right, up, upright, downright;
	float dot, dist, scale, alpha;
	bool visible;
	bool oldblend;

	if (!r_flares->integer)
		return;

	if (!surfs->count)
		return;

	oldblend = r_state.blend_enabled;

	R_EnableColorArray(true);

	R_ResetArrayState();

	/** @todo better GL state handling */
	glDisable(GL_DEPTH_TEST);
	R_EnableBlend(true);
	R_BlendFunc(GL_SRC_ALPHA, GL_ONE);

	image = r_flaretextures[0];
	R_BindTexture(image->texnum);

	j = k = l = 0;
	for (i = 0; i < surfs->count; i++) {
		mBspSurface_t* surf = surfs->surfaces[i];
		mBspFlare_t* f;

		if (surf->frame != r_locals.frame)
			continue;

		f = surf->flare;

		/* bind the flare's texture */
		if (f->image != image) {
			R_DrawArrays(0, l / 3);
			j = k = l = 0;

			refdef.batchCount++;

			image = f->image;
			R_BindTexture(image->texnum);
		}

		/* periodically test visibility to ramp alpha */
		if (refdef.time - f->time > 0.02) {
			if (refdef.time - f->time > 0.5) /* reset old flares */
				f->alpha = 0;

			R_Trace(refdef.viewOrigin, f->origin, 0, MASK_SOLID);
			visible = refdef.trace.fraction == 1.0;

			f->alpha += (visible ? 0.03 : -0.15); /* ramp */

			if (f->alpha > 0.75) /* clamp */
				f->alpha = 0.75;
			else if (f->alpha < 0)
				f->alpha = 0.0;

			f->time = refdef.time;
		}

		VectorSubtract(f->origin, refdef.viewOrigin, view);
		dist = VectorNormalize(view);

		/* fade according to angle */
		dot = DotProduct(surf->normal, view);
		if (dot > 0)
			continue;

		alpha = 0.1 + -dot * r_flares->value;

		if (alpha > 1.0)
			alpha = 1.0;

		alpha = f->alpha * alpha;

		/* scale according to distance */
		scale = f->radius + (f->radius * dist * .0005);

		VectorScale(r_locals.right, scale, right);
		VectorScale(r_locals.up, scale, up);

		VectorAdd(up, right, upright);
		VectorSubtract(right, up, downright);

		VectorSubtract(f->origin, downright, verts[0]);
		VectorAdd(f->origin, upright, verts[1]);
		VectorAdd(f->origin, downright, verts[2]);
		VectorSubtract(f->origin, upright, verts[3]);

		for (m = 0; m < 4; m++) { /* duplicate color data to all 4 verts */
			memcpy(&r_state.color_array[j], f->color, sizeof(vec3_t));
			r_state.color_array[j + 3] = alpha;
			j += 4;
		}

		/* copy texcoord info */
		memcpy(&texunit_diffuse.texcoord_array[k], default_texcoords, sizeof(vec2_t) * 4);
		k += sizeof(vec2_t) / sizeof(vec_t) * 4;

		/* and lastly copy the 4 verts */
		memcpy(&r_state.vertex_array_3d[l], verts, sizeof(vec3_t) * 4);
		l += sizeof(vec3_t) / sizeof(vec_t) * 4;
	}

	R_DrawArrays(0, l / 3);

	refdef.batchCount++;

	R_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	R_EnableBlend(oldblend);
	glEnable(GL_DEPTH_TEST);

	R_EnableColorArray(false);

	R_Color(nullptr);
}