コード例 #1
0
ファイル: p_view.cpp プロジェクト: codetwister/qfusion
/*
* G_ClientAddDamageIndicatorImpact
*/
void G_ClientAddDamageIndicatorImpact( gclient_t *client, int damage, const vec3_t basedir )
{
	vec3_t dir;
	float frac;

	if( damage < 1 )
		return;

	if( !client || client - game.clients < 0 || client - game.clients >= gs.maxclients )
		return;

	if( !basedir )
	{
		VectorCopy( vec3_origin, dir );
	}
	else
	{
		VectorNormalize2( basedir, dir );

		//#define ACCENT_SCALE 2.0f
#ifdef ACCENT_SCALE
		// accent the vertical or horizontal aspect of the direction
		if( VectorLengthFast( tv( dir[0], dir[1], 0 ) ) > dir[2] )
		{
			dir[0] *= ACCENT_SCALE;
			dir[1] *= ACCENT_SCALE;
		}
		else
			dir[2] *= ACCENT_SCALE;

		VectorNormalizeFast( dir );
#endif
#undef ACCENT_SCALE
	}

	frac = (float)damage / ( damage + client->resp.snap.damageTaken );
	VectorLerp( client->resp.snap.damageTakenDir, frac, dir, client->resp.snap.damageTakenDir );
	client->resp.snap.damageTaken += damage;
}
static void RestoreEntityTo(CAI_BaseNPC *pEntity, const Vector &vWantedPos)
{
	// Try to move to the wanted position from our current position.
	trace_t tr;
	VPROF_BUDGET("RestoreEntityTo", "CLagCompensationManager");
	UTIL_TraceEntity(pEntity, vWantedPos, vWantedPos, MASK_NPCSOLID, pEntity, COLLISION_GROUP_NPC, &tr);
	if (tr.startsolid || tr.allsolid)
	{
		if (sv_unlag_debug.GetBool())
		{
			DevMsg("RestorepEntityTo() could not restore entity position for %s ( %.1f %.1f %.1f )\n",
				pEntity->GetClassname(), vWantedPos.x, vWantedPos.y, vWantedPos.z);
		}

		UTIL_TraceEntity(pEntity, pEntity->GetLocalOrigin(), vWantedPos, MASK_NPCSOLID, pEntity, COLLISION_GROUP_NPC, &tr);
		if (tr.startsolid || tr.allsolid)
		{
			// In this case, the guy got stuck back wherever we lag compensated him to. Nasty.

			if (sv_unlag_debug.GetBool())
				DevMsg(" restore failed entirely\n");
		}
		else
		{
			// We can get to a valid place, but not all the way back to where we were.
			Vector vPos;
			VectorLerp(pEntity->GetLocalOrigin(), vWantedPos, tr.fraction * g_flFractionScale, vPos);
			UTIL_SetOrigin(pEntity, vPos, true);

			if (sv_unlag_debug.GetBool())
				DevMsg(" restore got most of the way\n");
		}
	}
	else
	{
		// Cool, the entity can go back to whence he came.
		UTIL_SetOrigin(pEntity, tr.endpos, true);
	}
}
コード例 #3
0
ファイル: cg_entity.c プロジェクト: jayschwa/quake2world
/*
 * @brief Adds the specified client entity to the view.
 */
static void Cg_AddEntity(cl_entity_t *e) {
	r_entity_t ent;

	memset(&ent, 0, sizeof(ent));
	ent.scale = 1.0;

	// update the static lighting cache
	Cg_UpdateLighting(e, &ent);

	// resolve the origin so that we know where to add effects
	VectorLerp(e->prev.origin, e->current.origin, cgi.client->lerp, ent.origin);

	// add events
	Cg_EntityEvent(e);

	// add effects, augmenting the renderer entity
	Cg_EntityEffects(e, &ent);

	// if there's no model associated with the entity, we're done
	if (!e->current.model1)
		return;

	if (e->current.model1 == 0xff) { // add a player entity

		Cg_AddClientEntity(e, &ent);

		if (IS_SELF(e))
			Cg_AddWeapon(e, &ent);

		return;
	}

	// assign the model
	ent.model = cgi.client->model_precache[e->current.model1];

	// add to view list
	cgi.AddEntity(&ent);
}
コード例 #4
0
ファイル: gl_shader.c プロジェクト: DrLabman/Vengeance-r2
qboolean R_Shader_IsLightInScopeByLeaf( unsigned int lightIndex, mleaf_t *leaf ) {
	const R_ShaderLight *light = GetLightFromIndex( lightIndex );

	if( !light->active ) {
		return false;
	}

	if( !R_Shader_IsLightVisibleFromLeaf( light, leaf ) ) {
		return false;
	}

	// bounding sphere check
	{		
		vec3_t midPoint;
		float boundingSphereRadius;
		
		VectorLerp( &leaf->minmaxs[ 0 ], 0.5f, &leaf->minmaxs[ 3 ], midPoint );
		boundingSphereRadius = VectorDistance( &leaf->minmaxs[ 0 ], midPoint );
		if( VectorDistance( light->origin, midPoint ) > light->maxDistance + boundingSphereRadius ) {
			return false;
		}
	}
	return true;
}
コード例 #5
0
ファイル: npc_crow.cpp プロジェクト: Bubbasacs/FinalProj
//-----------------------------------------------------------------------------
// Purpose: Handles all flight movement.
// Input  : flInterval - Seconds to simulate.
//-----------------------------------------------------------------------------
void CNPC_Crow::MoveCrowFly( float flInterval )
{
	//
	// Bound interval so we don't get ludicrous motion when debugging
	// or when framerate drops catastrophically.  
	//
	if (flInterval > 1.0)
	{
		flInterval = 1.0;
	}

	m_flDangerSoundTime = gpGlobals->curtime + 5.0f;

	//
	// Determine the goal of our movement.
	//
	Vector vecMoveGoal = GetAbsOrigin();

	if ( GetNavigator()->IsGoalActive() )
	{
		vecMoveGoal = GetNavigator()->GetCurWaypointPos();

		if ( GetNavigator()->CurWaypointIsGoal() == false  )
		{
  			AI_ProgressFlyPathParams_t params( MASK_NPCSOLID );
			params.bTrySimplify = false;

			GetNavigator()->ProgressFlyPath( params ); // ignore result, crow handles completion directly

			// Fly towards the hint.
			if ( GetNavigator()->GetPath()->GetCurWaypoint() )
			{
				vecMoveGoal = GetNavigator()->GetCurWaypointPos();
			}
		}
	}
	else
	{
		// No movement goal.
		vecMoveGoal = GetAbsOrigin();
		SetAbsVelocity( vec3_origin );
		return;
	}

	Vector vecMoveDir = ( vecMoveGoal - GetAbsOrigin() );
	Vector vForward;
	AngleVectors( GetAbsAngles(), &vForward );
	
	//
	// Fly towards the movement goal.
	//
	float flDistance = ( vecMoveGoal - GetAbsOrigin() ).Length();

	if ( vecMoveGoal != m_vDesiredTarget )
	{
		m_vDesiredTarget = vecMoveGoal;
	}
	else
	{
		m_vCurrentTarget = ( m_vDesiredTarget - GetAbsOrigin() );
		VectorNormalize( m_vCurrentTarget );
	}

	float flLerpMod = 0.25f;

	if ( flDistance <= 256.0f )
	{
		flLerpMod = 1.0f - ( flDistance / 256.0f );
	}


	VectorLerp( vForward, m_vCurrentTarget, flLerpMod, vForward );


	if ( flDistance < CROW_AIRSPEED * flInterval )
	{
		if ( GetNavigator()->IsGoalActive() )
		{
			if ( GetNavigator()->CurWaypointIsGoal() )
			{
				m_bReachedMoveGoal = true;
			}
			else
			{
				GetNavigator()->AdvancePath();
			}
		}
		else
			m_bReachedMoveGoal = true;
	}

	if ( GetHintNode() )
	{
		AIMoveTrace_t moveTrace;
		GetMoveProbe()->MoveLimit( NAV_FLY, GetAbsOrigin(), GetNavigator()->GetCurWaypointPos(), MASK_NPCSOLID, GetNavTargetEntity(), &moveTrace );

		//See if it succeeded
		if ( IsMoveBlocked( moveTrace.fStatus ) )
		{
			Vector vNodePos = vecMoveGoal;
			GetHintNode()->GetPosition(this, &vNodePos);
			
			GetNavigator()->SetGoal( vNodePos );
		}
	}

	//
	// Look to see if we are going to hit anything.
	//
	VectorNormalize( vForward );
	Vector vecDeflect;
	if ( Probe( vForward, CROW_AIRSPEED * flInterval, vecDeflect ) )
	{
		vForward = vecDeflect;
		VectorNormalize( vForward );
	}

	SetAbsVelocity( vForward * CROW_AIRSPEED );

	if ( GetAbsVelocity().Length() > 0 && GetNavigator()->CurWaypointIsGoal() && flDistance < CROW_AIRSPEED )
	{
		SetIdealActivity( (Activity)ACT_CROW_LAND );
	}


	//Bank and set angles.
	Vector vRight;
	QAngle vRollAngle;
	
	VectorAngles( vForward, vRollAngle );
	vRollAngle.z = 0;

	AngleVectors( vRollAngle, NULL, &vRight, NULL );

	float flRoll = DotProduct( vRight, vecMoveDir ) * 45;
	flRoll = clamp( flRoll, -45, 45 );

	vRollAngle[ROLL] = flRoll;
	SetAbsAngles( vRollAngle );
}
コード例 #6
0
ファイル: keyframe.cpp プロジェクト: xxauroraxx/Source.Python
void CPositionInterpolator_Linear::InterpolatePosition( float time, Vector &vOut )
{
	VectorLerp( g_KeyFramePtr[0].vPos, g_KeyFramePtr[1].vPos, time, vOut );
}
コード例 #7
0
ファイル: cg_democams.cpp プロジェクト: Picmip/qfusion
/*
* CG_Democam_CalcView
*/
static int CG_Democam_CalcView( void ) {
	int i, viewType;
	float lerpfrac;
	vec3_t v;

	viewType = VIEWDEF_PLAYERVIEW;
	VectorClear( cam_velocity );

	if( currentcam ) {
		if( !nextcam ) {
			lerpfrac = 0;
		} else {
			lerpfrac = (float)( demo_time - currentcam->timeStamp ) / (float)( nextcam->timeStamp - currentcam->timeStamp );
		}

		switch( currentcam->type ) {
			case DEMOCAM_FIRSTPERSON:
				VectorCopy( cg.view.origin, cam_origin );
				VectorCopy( cg.view.angles, cam_angles );
				VectorCopy( cg.view.velocity, cam_velocity );
				cam_fov = cg.view.fov_y;
				break;

			case DEMOCAM_THIRDPERSON:
				VectorCopy( cg.view.origin, cam_origin );
				VectorCopy( cg.view.angles, cam_angles );
				VectorCopy( cg.view.velocity, cam_velocity );
				cam_fov = cg.view.fov_y;
				cam_3dPerson = true;
				break;

			case DEMOCAM_POSITIONAL:
				viewType = VIEWDEF_DEMOCAM;
				cam_POVent = 0;
				VectorCopy( currentcam->origin, cam_origin );
				if( !CG_DemoCam_LookAt( currentcam->trackEnt, cam_origin, cam_angles ) ) {
					VectorCopy( currentcam->angles, cam_angles );
				}
				cam_fov = currentcam->fov;
				break;

			case DEMOCAM_PATH_LINEAR:
				viewType = VIEWDEF_DEMOCAM;
				cam_POVent = 0;
				VectorCopy( cam_origin, v );

				if( !nextcam || nextcam->type == DEMOCAM_FIRSTPERSON || nextcam->type == DEMOCAM_THIRDPERSON ) {
					CG_Printf( "Warning: CG_DemoCam: path_linear cam without a valid next cam\n" );
					VectorCopy( currentcam->origin, cam_origin );
					if( !CG_DemoCam_LookAt( currentcam->trackEnt, cam_origin, cam_angles ) ) {
						VectorCopy( currentcam->angles, cam_angles );
					}
					cam_fov = currentcam->fov;
				} else {
					VectorLerp( currentcam->origin, lerpfrac, nextcam->origin, cam_origin );
					if( !CG_DemoCam_LookAt( currentcam->trackEnt, cam_origin, cam_angles ) ) {
						for( i = 0; i < 3; i++ ) cam_angles[i] = LerpAngle( currentcam->angles[i], nextcam->angles[i], lerpfrac );
					}
					cam_fov = (float)currentcam->fov + (float)( nextcam->fov - currentcam->fov ) * lerpfrac;
				}

				// set velocity
				VectorSubtract( cam_origin, v, cam_velocity );
				VectorScale( cam_velocity, 1.0f / (float)cg.frameTime, cam_velocity );
				break;

			case DEMOCAM_PATH_SPLINE:
				viewType = VIEWDEF_DEMOCAM;
				cam_POVent = 0;
				clamp( lerpfrac, 0, 1 );
				VectorCopy( cam_origin, v );

				if( !nextcam || nextcam->type == DEMOCAM_FIRSTPERSON || nextcam->type == DEMOCAM_THIRDPERSON ) {
					CG_Printf( "Warning: CG_DemoCam: path_spline cam without a valid next cam\n" );
					VectorCopy( currentcam->origin, cam_origin );
					if( !CG_DemoCam_LookAt( currentcam->trackEnt, cam_origin, cam_angles ) ) {
						VectorCopy( currentcam->angles, cam_angles );
					}
					cam_fov = currentcam->fov;
				} else {  // valid spline path
#define VectorHermiteInterp( a, at, b, bt, c, v )  ( ( v )[0] = ( 2 * pow( c, 3 ) - 3 * pow( c, 2 ) + 1 ) * a[0] + ( pow( c, 3 ) - 2 * pow( c, 2 ) + c ) * 2 * at[0] + ( -2 * pow( c, 3 ) + 3 * pow( c, 2 ) ) * b[0] + ( pow( c, 3 ) - pow( c, 2 ) ) * 2 * bt[0], ( v )[1] = ( 2 * pow( c, 3 ) - 3 * pow( c, 2 ) + 1 ) * a[1] + ( pow( c, 3 ) - 2 * pow( c, 2 ) + c ) * 2 * at[1] + ( -2 * pow( c, 3 ) + 3 * pow( c, 2 ) ) * b[1] + ( pow( c, 3 ) - pow( c, 2 ) ) * 2 * bt[1], ( v )[2] = ( 2 * pow( c, 3 ) - 3 * pow( c, 2 ) + 1 ) * a[2] + ( pow( c, 3 ) - 2 * pow( c, 2 ) + c ) * 2 * at[2] + ( -2 * pow( c, 3 ) + 3 * pow( c, 2 ) ) * b[2] + ( pow( c, 3 ) - pow( c, 2 ) ) * 2 * bt[2] )

					float lerpspline, A, B, C, n1, n2, n3;
					cg_democam_t *previouscam = NULL;
					cg_democam_t *secondnextcam = NULL;

					if( nextcam ) {
						secondnextcam = CG_Democam_FindNext( nextcam->timeStamp );
					}
					if( currentcam->timeStamp > 0 ) {
						previouscam = CG_Democam_FindCurrent( currentcam->timeStamp - 1 );
					}

					if( !previouscam && nextcam && !secondnextcam ) {
						lerpfrac = (float)( demo_time - currentcam->timeStamp ) / (float)( nextcam->timeStamp - currentcam->timeStamp );
						lerpspline = lerpfrac;
					} else if( !previouscam && nextcam && secondnextcam ) {
						n1 = nextcam->timeStamp - currentcam->timeStamp;
						n2 = secondnextcam->timeStamp - nextcam->timeStamp;
						A = n1 * ( n1 - n2 ) / ( pow( n1, 2 ) + n1 * n2 - n1 - n2 );
						B = ( 2 * n1 * n2 - n1 - n2 ) / ( pow( n1, 2 ) + n1 * n2 - n1 - n2 );
						lerpfrac = (float)( demo_time - currentcam->timeStamp ) / (float)( nextcam->timeStamp - currentcam->timeStamp );
						lerpspline = A * pow( lerpfrac, 2 ) + B * lerpfrac;
					} else if( previouscam && nextcam && !secondnextcam ) {
						n2 = currentcam->timeStamp - previouscam->timeStamp;
						n3 = nextcam->timeStamp - currentcam->timeStamp;
						A = n3 * ( n2 - n3 ) / ( -n2 - n3 + n2 * n3 + pow( n3, 2 ) );
						B = -1 / ( -n2 - n3 + n2 * n3 + pow( n3, 2 ) ) * ( n2 + n3 - 2 * pow( n3, 2 ) );
						lerpfrac = (float)( demo_time - currentcam->timeStamp ) / (float)( nextcam->timeStamp - currentcam->timeStamp );
						lerpspline = A * pow( lerpfrac, 2 ) + B * lerpfrac;
					} else if( previouscam && nextcam && secondnextcam ) {
						n1 = currentcam->timeStamp - previouscam->timeStamp;
						n2 = nextcam->timeStamp - currentcam->timeStamp;
						n3 = secondnextcam->timeStamp - nextcam->timeStamp;
						A = -2 * pow( n2, 2 ) * ( -pow( n2, 2 ) + n1 * n3 ) / ( 2 * n2 * n3 + pow( n2, 3 ) * n3 - 3 * pow( n2, 2 ) * n1 + n1 * pow( n2, 3 ) + 2 * n1 * n2 - 3 * pow( n2, 2 ) * n3 - 3 * pow( n2, 3 ) + 2 * pow( n2, 2 ) + pow( n2, 4 ) + n1 * pow( n2, 2 ) * n3 - 3 * n1 * n2 * n3 + 2 * n1 * n3 );
						B = pow( n2, 2 ) * ( -2 * n1 - 3 * pow( n2, 2 ) - n2 * n3 + 2 * n3 + 3 * n1 * n3 + n1 * n2 ) / ( 2 * n2 * n3 + pow( n2, 3 ) * n3 - 3 * pow( n2, 2 ) * n1 + n1 * pow( n2, 3 ) + 2 * n1 * n2 - 3 * pow( n2, 2 ) * n3 - 3 * pow( n2, 3 ) + 2 * pow( n2, 2 ) + pow( n2, 4 ) + n1 * pow( n2, 2 ) * n3 - 3 * n1 * n2 * n3 + 2 * n1 * n3 );
						C = -( pow( n2, 2 ) * n1 - 2 * n1 * n2 + 3 * n1 * n2 * n3 - 2 * n1 * n3 - 2 * pow( n2, 4 ) + 3 * pow( n2, 3 ) - 2 * pow( n2, 3 ) * n3 + 5 * pow( n2, 2 ) * n3 - 2 * pow( n2, 2 ) - 2 * n2 * n3 ) / ( 2 * n2 * n3 + pow( n2, 3 ) * n3 - 3 * pow( n2, 2 ) * n1 + n1 * pow( n2, 3 ) + 2 * n1 * n2 - 3 * pow( n2, 2 ) * n3 - 3 * pow( n2, 3 ) + 2 * pow( n2, 2 ) + pow( n2, 4 ) + n1 * pow( n2, 2 ) * n3 - 3 * n1 * n2 * n3 + 2 * n1 * n3 );
						lerpfrac = (float)( demo_time - currentcam->timeStamp ) / (float)( nextcam->timeStamp - currentcam->timeStamp );
						lerpspline = A * pow( lerpfrac, 3 ) + B * pow( lerpfrac, 2 ) + C * lerpfrac;
					} else {
						lerpfrac = 0;
						lerpspline = 0;
					}


					VectorHermiteInterp( currentcam->origin, currentcam->tangent, nextcam->origin, nextcam->tangent, lerpspline, cam_origin );
					if( !CG_DemoCam_LookAt( currentcam->trackEnt, cam_origin, cam_angles ) ) {
						VectorHermiteInterp( currentcam->angles, currentcam->angles_tangent, nextcam->angles, nextcam->angles_tangent, lerpspline, cam_angles );
					}
					cam_fov = (float)currentcam->fov + (float)( nextcam->fov - currentcam->fov ) * lerpfrac;
#undef VectorHermiteInterp
				}

				// set velocity
				VectorSubtract( cam_origin, v, cam_velocity );
				VectorScale( cam_velocity, 1.0f / (float)cg.frameTime, cam_velocity );
				break;

			case DEMOCAM_ORBITAL:
				viewType = VIEWDEF_DEMOCAM;
				cam_POVent = 0;
				cam_fov = currentcam->fov;
				VectorCopy( cam_origin, v );

				if( !currentcam->trackEnt || currentcam->trackEnt >= MAX_EDICTS ) {
					CG_Printf( "Warning: CG_DemoCam: orbital cam needs a track entity set\n" );
					VectorCopy( currentcam->origin, cam_origin );
					VectorClear( cam_angles );
					VectorClear( cam_velocity );
				} else {
					vec3_t center, forward;
					struct cmodel_s *cmodel;
					const float ft = (float)cg.frameTime * 0.001f;

					// find the trackEnt origin
					VectorLerp( cg_entities[currentcam->trackEnt].prev.origin, cg.lerpfrac, cg_entities[currentcam->trackEnt].current.origin, center );

					// if having a bounding box, look to its center
					if( ( cmodel = CG_CModelForEntity( currentcam->trackEnt ) ) != NULL ) {
						vec3_t mins, maxs;
						trap_CM_InlineModelBounds( cmodel, mins, maxs );
						for( i = 0; i < 3; i++ )
							center[i] += ( mins[i] + maxs[i] );
					}

					if( !cam_orbital_radius ) {
						// cam is just started, find distance from cam to trackEnt and keep it as radius
						VectorSubtract( currentcam->origin, center, forward );
						cam_orbital_radius = VectorNormalize( forward );
						VecToAngles( forward, cam_orbital_angles );
					}

					for( i = 0; i < 3; i++ ) {
						cam_orbital_angles[i] += currentcam->angles[i] * ft;
						cam_orbital_angles[i] = AngleNormalize360( cam_orbital_angles[i] );
					}

					AngleVectors( cam_orbital_angles, forward, NULL, NULL );
					VectorMA( center, cam_orbital_radius, forward, cam_origin );

					// lookat
					VectorInverse( forward );
					VecToAngles( forward, cam_angles );
				}

				// set velocity
				VectorSubtract( cam_origin, v, cam_velocity );
				VectorScale( cam_velocity, 1.0f / ( cg.frameTime * 1000.0f ), cam_velocity );
				break;

			default:
				break;
		}

		if( currentcam->type != DEMOCAM_ORBITAL ) {
			VectorClear( cam_orbital_angles );
			cam_orbital_radius = 0;
		}
	}

	return viewType;
}
コード例 #8
0
ファイル: cl_frame.c プロジェクト: UCyborg/xash3d
void CL_UpdateEntityFields( cl_entity_t *ent )
{
	// parametric rockets code
	if( ent->curstate.starttime != 0.0f && ent->curstate.impacttime != 0.0f )
	{
		float	lerp = ( cl.time - ent->curstate.starttime ) / ( ent->curstate.impacttime - ent->curstate.starttime );
		vec3_t	dir;

		lerp = bound( 0.0f, lerp, 1.0f );

		// first we need to calc actual origin
		VectorLerp( ent->curstate.startpos, lerp, ent->curstate.endpos, ent->curstate.origin );
		VectorSubtract( ent->curstate.endpos, ent->curstate.startpos, dir );
		VectorAngles( dir, ent->curstate.angles ); // re-aim projectile		
	}

	ent->model = Mod_Handle( ent->curstate.modelindex );
	ent->curstate.msg_time = cl.time;

	CL_InterpolateModel( ent );

	if( ent->player && RP_LOCALCLIENT( ent )) // stupid Half-Life bug
		ent->angles[PITCH] = -ent->angles[PITCH] / 3.0f;

	// make me lerp
	if( ent->model && ent->model->type == mod_brush && ent->curstate.animtime != 0.0f )
	{
		float		d, f = 0.0f;
		int		i;

		// don't do it if the goalstarttime hasn't updated in a while.
		// NOTE: Because we need to interpolate multiplayer characters, the interpolation time limit
		// was increased to 1.0 s., which is 2x the max lag we are accounting for.
		if(( cl.time < ent->curstate.animtime + 1.0f ) && ( ent->curstate.animtime != ent->latched.prevanimtime ))
			f = ( cl.time - ent->curstate.animtime ) / ( ent->curstate.animtime - ent->latched.prevanimtime );

		f = f - 1.0f;

		ent->origin[0] += ( ent->origin[0] - ent->latched.prevorigin[0] ) * f;
		ent->origin[1] += ( ent->origin[1] - ent->latched.prevorigin[1] ) * f;
		ent->origin[2] += ( ent->origin[2] - ent->latched.prevorigin[2] ) * f;

		for( i = 0; i < 3; i++ )
		{
			float	ang1, ang2;

			ang1 = ent->angles[i];
			ang2 = ent->latched.prevangles[i];
			d = ang1 - ang2;
			if( d > 180.0f ) d -= 360.0f;
			else if( d < -180.0f ) d += 360.0f;
			ent->angles[i] += d * f;
		}
	}
	else if( ent->curstate.eflags & EFLAG_SLERP )
	{
		float		d, f = 0.0f;
		cl_entity_t	*m_pGround = NULL;
		int		i;

		// don't do it if the goalstarttime hasn't updated in a while.
		// NOTE: Because we need to interpolate multiplayer characters, the interpolation time limit
		// was increased to 1.0 s., which is 2x the max lag we are accounting for.
		if(( cl.time < ent->curstate.animtime + 1.0f ) && ( ent->curstate.animtime != ent->latched.prevanimtime ))
			f = ( cl.time - ent->curstate.animtime ) / ( ent->curstate.animtime - ent->latched.prevanimtime );

		f = f - 1.0f;

		if( ent->curstate.movetype == MOVETYPE_FLY )
		{
			ent->origin[0] += ( ent->curstate.origin[0] - ent->latched.prevorigin[0] ) * f;
			ent->origin[1] += ( ent->curstate.origin[1] - ent->latched.prevorigin[1] ) * f;
			ent->origin[2] += ( ent->curstate.origin[2] - ent->latched.prevorigin[2] ) * f;

			for( i = 0; i < 3; i++ )
			{
				float	ang1, ang2;

				ang1 = ent->curstate.angles[i];
				ang2 = ent->latched.prevangles[i];
				d = ang1 - ang2;
				if( d > 180.0f ) d -= 360.0f;
				else if( d < -180.0f ) d += 360.0f;
				ent->angles[i] += d * f;
			}
		}
		else if( ent->curstate.movetype == MOVETYPE_STEP )
		{
			vec3_t	vecSrc, vecEnd;
			pmtrace_t	trace;

			if( ent->model )
			{
				CL_SetTraceHull( 0 ); // g-cont. player hull for better detect moving platforms
				VectorSet( vecSrc, ent->origin[0], ent->origin[1], ent->origin[2] + ent->model->maxs[2] );
				VectorSet( vecEnd, vecSrc[0], vecSrc[1], vecSrc[2] - ent->model->mins[2] - 8.0f );		
				CL_PlayerTraceExt( vecSrc, vecEnd, PM_STUDIO_IGNORE, CL_PushMoveFilter, &trace );
				m_pGround = CL_GetEntityByIndex( pfnIndexFromTrace( &trace ));
			}

			if( m_pGround && m_pGround->curstate.movetype == MOVETYPE_PUSH )
			{
				qboolean	applyVel, applyAvel;

				applyVel = !VectorCompare( m_pGround->curstate.origin, m_pGround->prevstate.origin );
				applyAvel = !VectorCompare( m_pGround->curstate.angles, m_pGround->prevstate.angles );

				if( applyVel || applyAvel )
				{
					ent->origin[0] += ( m_pGround->curstate.origin[0] - m_pGround->prevstate.origin[0] ) * -1.0f;
					ent->origin[1] += ( m_pGround->curstate.origin[1] - m_pGround->prevstate.origin[1] ) * -1.0f;
//					ent->origin[2] += ( m_pGround->curstate.origin[2] - m_pGround->prevstate.origin[2] ) * -1.0f;
					ent->latched.prevorigin[2] = ent->origin[2];
				}

				if( applyAvel )
				{
					for( i = 0; i < 3; i++ )
					{
						float	ang1, ang2;

						ang1 = m_pGround->curstate.angles[i];
						ang2 = m_pGround->prevstate.angles[i];
						d = ang1 - ang2;
						if( d > 180.0f ) d -= 360.0f;
						else if( d < -180.0f ) d += 360.0f;
						ent->angles[i] += d * -1.0f;
					}
				}
			}

			// moved code from StudioSetupTransform here
			if( host.features & ENGINE_COMPUTE_STUDIO_LERP )
			{
				ent->origin[0] += ( ent->curstate.origin[0] - ent->latched.prevorigin[0] ) * f;
				ent->origin[1] += ( ent->curstate.origin[1] - ent->latched.prevorigin[1] ) * f;
				ent->origin[2] += ( ent->curstate.origin[2] - ent->latched.prevorigin[2] ) * f;

				for( i = 0; i < 3; i++ )
				{
					float	ang1, ang2;

					ang1 = ent->angles[i];
					ang2 = ent->latched.prevangles[i];
					d = ang1 - ang2;
					if( d > 180.0f ) d -= 360.0f;
					else if( d < -180.0f ) d += 360.0f;
					ent->angles[i] += d * f;
				}
			}
		}
	}
}
コード例 #9
0
/*
==============
RE_BuildSkeleton
==============
*/
int RE_BuildSkeleton(refSkeleton_t * skel, qhandle_t hAnim, int startFrame, int endFrame, float frac, qboolean clearOrigin)
{
	skelAnimation_t *skelAnim;

	skelAnim = R_GetAnimationByHandle(hAnim);

	if(skelAnim->type == AT_MD5 && skelAnim->md5)
	{
		int             i;
		md5Animation_t *anim;
		md5Channel_t   *channel;
		md5Frame_t     *newFrame, *oldFrame;
		vec3_t          newOrigin, oldOrigin, lerpedOrigin;
		quat_t          newQuat, oldQuat, lerpedQuat;
		int             componentsApplied;

		anim = skelAnim->md5;

		// Validate the frames so there is no chance of a crash.
		// This will write directly into the entity structure, so
		// when the surfaces are rendered, they don't need to be
		// range checked again.
		/*
		   if((startFrame >= anim->numFrames) || (startFrame < 0) || (endFrame >= anim->numFrames) || (endFrame < 0))
		   {
		   ri.Printf(PRINT_DEVELOPER, "RE_BuildSkeleton: no such frame %d to %d for '%s'\n", startFrame, endFrame, anim->name);
		   //startFrame = 0;
		   //endFrame = 0;
		   }
		 */

		Q_clamp(startFrame, 0, anim->numFrames - 1);
		Q_clamp(endFrame, 0, anim->numFrames - 1);

		// compute frame pointers
		oldFrame = &anim->frames[startFrame];
		newFrame = &anim->frames[endFrame];

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

		for(i = 0, channel = anim->channels; i < anim->numChannels; i++, channel++)
		{
			// set baseframe values
			VectorCopy(channel->baseOrigin, newOrigin);
			VectorCopy(channel->baseOrigin, oldOrigin);

			QuatCopy(channel->baseQuat, newQuat);
			QuatCopy(channel->baseQuat, oldQuat);

			componentsApplied = 0;

			// update tranlation bits
			if(channel->componentsBits & COMPONENT_BIT_TX)
			{
				oldOrigin[0] = oldFrame->components[channel->componentsOffset + componentsApplied];
				newOrigin[0] = newFrame->components[channel->componentsOffset + componentsApplied];
				componentsApplied++;
			}

			if(channel->componentsBits & COMPONENT_BIT_TY)
			{
				oldOrigin[1] = oldFrame->components[channel->componentsOffset + componentsApplied];
				newOrigin[1] = newFrame->components[channel->componentsOffset + componentsApplied];
				componentsApplied++;
			}

			if(channel->componentsBits & COMPONENT_BIT_TZ)
			{
				oldOrigin[2] = oldFrame->components[channel->componentsOffset + componentsApplied];
				newOrigin[2] = newFrame->components[channel->componentsOffset + componentsApplied];
				componentsApplied++;
			}

			// update quaternion rotation bits
			if(channel->componentsBits & COMPONENT_BIT_QX)
			{
				((vec_t *) oldQuat)[0] = oldFrame->components[channel->componentsOffset + componentsApplied];
				((vec_t *) newQuat)[0] = newFrame->components[channel->componentsOffset + componentsApplied];
				componentsApplied++;
			}

			if(channel->componentsBits & COMPONENT_BIT_QY)
			{
				((vec_t *) oldQuat)[1] = oldFrame->components[channel->componentsOffset + componentsApplied];
				((vec_t *) newQuat)[1] = newFrame->components[channel->componentsOffset + componentsApplied];
				componentsApplied++;
			}

			if(channel->componentsBits & COMPONENT_BIT_QZ)
			{
				((vec_t *) oldQuat)[2] = oldFrame->components[channel->componentsOffset + componentsApplied];
				((vec_t *) newQuat)[2] = newFrame->components[channel->componentsOffset + componentsApplied];
			}

			QuatCalcW(oldQuat);
			QuatNormalize(oldQuat);

			QuatCalcW(newQuat);
			QuatNormalize(newQuat);

#if 1
			VectorLerp(oldOrigin, newOrigin, frac, lerpedOrigin);
			QuatSlerp(oldQuat, newQuat, frac, lerpedQuat);
#else
			VectorCopy(newOrigin, lerpedOrigin);
			QuatCopy(newQuat, lerpedQuat);
#endif

			// copy lerped information to the bone + extra data
			skel->bones[i].parentIndex = channel->parentIndex;

			if(channel->parentIndex < 0 && clearOrigin)
			{
				VectorClear(skel->bones[i].origin);
				QuatClear(skel->bones[i].rotation);

				// move bounding box back
				VectorSubtract(skel->bounds[0], lerpedOrigin, skel->bounds[0]);
				VectorSubtract(skel->bounds[1], lerpedOrigin, skel->bounds[1]);
			}
			else
			{
				VectorCopy(lerpedOrigin, skel->bones[i].origin);
			}

			QuatCopy(lerpedQuat, skel->bones[i].rotation);

#if defined(REFBONE_NAMES)
			Q_strncpyz(skel->bones[i].name, channel->name, sizeof(skel->bones[i].name));
#endif
		}

		skel->numBones = anim->numChannels;
		skel->type = SK_RELATIVE;
		return qtrue;
	}
	else if(skelAnim->type == AT_PSA && skelAnim->psa)
	{
		int             i;
		psaAnimation_t *anim;
		axAnimationKey_t *newKey, *oldKey;
		axReferenceBone_t *refBone;
		vec3_t          newOrigin, oldOrigin, lerpedOrigin;
		quat_t          newQuat, oldQuat, lerpedQuat;
		refSkeleton_t   skeleton;

		anim = skelAnim->psa;

		Q_clamp(startFrame, 0, anim->info.numRawFrames - 1);
		Q_clamp(endFrame, 0, anim->info.numRawFrames - 1);

		ClearBounds(skel->bounds[0], skel->bounds[1]);

		skel->numBones = anim->info.numBones;
		for(i = 0, refBone = anim->bones; i < anim->info.numBones; i++, refBone++)
		{
			oldKey = &anim->keys[startFrame * anim->info.numBones + i];
			newKey = &anim->keys[endFrame * anim->info.numBones + i];

			VectorCopy(newKey->position, newOrigin);
			VectorCopy(oldKey->position, oldOrigin);

			QuatCopy(newKey->quat, newQuat);
			QuatCopy(oldKey->quat, oldQuat);

			//QuatCalcW(oldQuat);
			//QuatNormalize(oldQuat);

			//QuatCalcW(newQuat);
			//QuatNormalize(newQuat);

			VectorLerp(oldOrigin, newOrigin, frac, lerpedOrigin);
			QuatSlerp(oldQuat, newQuat, frac, lerpedQuat);

			// copy lerped information to the bone + extra data
			skel->bones[i].parentIndex = refBone->parentIndex;

			if(refBone->parentIndex < 0 && clearOrigin)
			{
				VectorClear(skel->bones[i].origin);
				QuatClear(skel->bones[i].rotation);

				// move bounding box back
				VectorSubtract(skel->bounds[0], lerpedOrigin, skel->bounds[0]);
				VectorSubtract(skel->bounds[1], lerpedOrigin, skel->bounds[1]);
			}
			else
			{
				VectorCopy(lerpedOrigin, skel->bones[i].origin);
			}

			QuatCopy(lerpedQuat, skel->bones[i].rotation);

#if defined(REFBONE_NAMES)
			Q_strncpyz(skel->bones[i].name, refBone->name, sizeof(skel->bones[i].name));
#endif

			// calculate absolute values for the bounding box approximation
			VectorCopy(skel->bones[i].origin, skeleton.bones[i].origin);
			QuatCopy(skel->bones[i].rotation, skeleton.bones[i].rotation);

			if(refBone->parentIndex >= 0)
			{
				vec3_t          rotated;
				quat_t          quat;
				refBone_t      *parent;
				refBone_t      *bone;

				bone = &skeleton.bones[i];
				parent = &skeleton.bones[refBone->parentIndex];

				QuatTransformVector(parent->rotation, bone->origin, rotated);

				VectorAdd(parent->origin, rotated, bone->origin);

				QuatMultiply1(parent->rotation, bone->rotation, quat);
				QuatCopy(quat, bone->rotation);

				AddPointToBounds(bone->origin, skel->bounds[0], skel->bounds[1]);
			}
		}

		skel->numBones = anim->info.numBones;
		skel->type = SK_RELATIVE;
		return qtrue;
	}

	//ri.Printf(PRINT_WARNING, "RE_BuildSkeleton: bad animation '%s' with handle %i\n", anim->name, hAnim);

	// FIXME: clear existing bones and bounds?
	return qfalse;
}
コード例 #10
0
ファイル: cl_collision.c プロジェクト: VenFPS/Vengeance
float CL_SelectTraceLine(const vec3_t start, const vec3_t end, vec3_t impact, vec3_t normal, int *hitent, entity_render_t *ignoreent)
#endif
{
	float maxfrac, maxrealfrac;
	int n;
	entity_render_t *ent;
	float tracemins[3], tracemaxs[3];
	trace_t trace;
	float tempnormal[3], starttransformed[3], endtransformed[3];
#ifdef COLLISION_STUPID_TRACE_ENDPOS_IN_SOLID_WORKAROUND
	vec3_t end;
	vec_t len = 0;

	if(!VectorCompare(start, pEnd) && collision_endposnudge.value > 0)
	{
		// TRICK: make the trace 1 qu longer!
		VectorSubtract(pEnd, start, end);
		len = VectorNormalizeLength(end);
		VectorMA(pEnd, collision_endposnudge.value, end, end);
	}
	else
		VectorCopy(pEnd, end);
#endif

	memset (&trace, 0 , sizeof(trace_t));
	trace.fraction = 1;
	trace.realfraction = 1;
	VectorCopy (end, trace.endpos);

	if (hitent)
		*hitent = 0;
	if (cl.worldmodel && cl.worldmodel->TraceLine)
		cl.worldmodel->TraceLine(cl.worldmodel, NULL, NULL, &trace, start, end, SUPERCONTENTS_SOLID);

	if (normal)
		VectorCopy(trace.plane.normal, normal);
	maxfrac = trace.fraction;
	maxrealfrac = trace.realfraction;

	tracemins[0] = min(start[0], end[0]);
	tracemaxs[0] = max(start[0], end[0]);
	tracemins[1] = min(start[1], end[1]);
	tracemaxs[1] = max(start[1], end[1]);
	tracemins[2] = min(start[2], end[2]);
	tracemaxs[2] = max(start[2], end[2]);

	// look for embedded bmodels
	for (n = 0;n < cl.num_entities;n++)
	{
		if (!cl.entities_active[n])
			continue;
		ent = &cl.entities[n].render;
		if (!BoxesOverlap(ent->mins, ent->maxs, tracemins, tracemaxs))
			continue;
		if (!ent->model || !ent->model->TraceLine)
			continue;
		if ((ent->flags & RENDER_EXTERIORMODEL) && !chase_active.integer)
			continue;
		// if transparent and not selectable, skip entity
		if (!(cl.entities[n].state_current.effects & EF_SELECTABLE) && (ent->alpha < 1 || (ent->effects & (EF_ADDITIVE | EF_NODEPTHTEST))))
			continue;
		if (ent == ignoreent)
			continue;
		Matrix4x4_Transform(&ent->inversematrix, start, starttransformed);
		Matrix4x4_Transform(&ent->inversematrix, end, endtransformed);
		Collision_ClipTrace_Box(&trace, ent->model->normalmins, ent->model->normalmaxs, starttransformed, vec3_origin, vec3_origin, endtransformed, SUPERCONTENTS_SOLID, SUPERCONTENTS_SOLID, 0, NULL);
#ifdef COLLISION_STUPID_TRACE_ENDPOS_IN_SOLID_WORKAROUND
		if(!VectorCompare(start, pEnd) && collision_endposnudge.value > 0)
			Collision_ShortenTrace(&trace, len / (len + collision_endposnudge.value), pEnd);
#endif
		if (maxrealfrac < trace.realfraction)
			continue;

		ent->model->TraceLine(ent->model, ent->frameblend, ent->skeleton, &trace, starttransformed, endtransformed, SUPERCONTENTS_SOLID);

		if (maxrealfrac > trace.realfraction)
		{
			if (hitent)
				*hitent = n;
			maxfrac = trace.fraction;
			maxrealfrac = trace.realfraction;
			if (normal)
			{
				VectorCopy(trace.plane.normal, tempnormal);
				Matrix4x4_Transform3x3(&ent->matrix, tempnormal, normal);
			}
		}
	}
	maxfrac = bound(0, maxfrac, 1);
	maxrealfrac = bound(0, maxrealfrac, 1);
	//if (maxfrac < 0 || maxfrac > 1) Con_Printf("fraction out of bounds %f %s:%d\n", maxfrac, __FILE__, __LINE__);
	if (impact)
		VectorLerp(start, maxfrac, end, impact);
	return maxfrac;
}
コード例 #11
0
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void FX_GlassImpact( const Vector &pos, const Vector &normal )
{
	VPROF_BUDGET( "FX_GlassImpact", VPROF_BUDGETGROUP_PARTICLE_RENDERING );
	CSmartPtr<CSimple3DEmitter> pGlassEmitter = CSimple3DEmitter::Create( "FX_GlassImpact" );
	pGlassEmitter->SetSortOrigin( pos );

	Vector vecColor;
	engine->ComputeLighting( pos, NULL, true, vecColor );

	// HACK: Blend a little toward white to match the materials...
	VectorLerp( vecColor, Vector( 1, 1, 1 ), 0.3, vecColor );

	float flShardSize	= random->RandomFloat( 2.0f, 6.0f );

	unsigned char color[3] = { 200, 200, 210 };

	// ---------------------
	// Create glass shards
	// ----------------------

	int numShards = random->RandomInt( 2, 4 );

	for ( int i = 0; i < numShards; i++ )
	{
		Particle3D *pParticle;
		
		pParticle = (Particle3D *) pGlassEmitter->AddParticle( sizeof(Particle3D), g_Mat_Fleck_Glass[random->RandomInt(0,1)], pos );

		if ( pParticle )
		{
			pParticle->m_flLifeRemaining	= random->RandomFloat(GLASS_SHARD_MIN_LIFE,GLASS_SHARD_MAX_LIFE);

			pParticle->m_vecVelocity[0]		= ( normal[0] + random->RandomFloat( -0.8f, 0.8f ) ) * random->RandomFloat( GLASS_SHARD_MIN_SPEED, GLASS_SHARD_MAX_SPEED );
			pParticle->m_vecVelocity[1]		= ( normal[1] + random->RandomFloat( -0.8f, 0.8f ) ) * random->RandomFloat( GLASS_SHARD_MIN_SPEED, GLASS_SHARD_MAX_SPEED );
			pParticle->m_vecVelocity[2]		= ( normal[2] + random->RandomFloat( -0.8f, 0.8f ) ) * random->RandomFloat( GLASS_SHARD_MIN_SPEED, GLASS_SHARD_MAX_SPEED );

			pParticle->m_uchSize			= flShardSize + random->RandomFloat(-0.5*flShardSize,0.5*flShardSize);
			pParticle->m_vAngles			= RandomAngle( 0, 360 );
			pParticle->m_flAngSpeed			= random->RandomFloat(-800,800);

			pParticle->m_uchFrontColor[0]	= (byte)(color[0] * vecColor.x);
			pParticle->m_uchFrontColor[1]	= (byte)(color[1] * vecColor.y);
			pParticle->m_uchFrontColor[2]	= (byte)(color[2] * vecColor.z);
			pParticle->m_uchBackColor[0]	= (byte)(color[0] * vecColor.x);
			pParticle->m_uchBackColor[1]	= (byte)(color[1] * vecColor.y);
			pParticle->m_uchBackColor[2]	= (byte)(color[2] * vecColor.z);
		}
	}

	pGlassEmitter->m_ParticleCollision.Setup( pos, &normal, GLASS_SHARD_NOISE, GLASS_SHARD_MIN_SPEED, GLASS_SHARD_MAX_SPEED, GLASS_SHARD_GRAVITY, GLASS_SHARD_DAMPING );

	color[0] = 64;
	color[1] = 64;
	color[2] = 92;

	// ---------------------------
	// Dust
	// ---------------------------

	Vector	dir;
	Vector	offset = pos + ( normal * 2.0f );
	float	colorRamp;

	SimpleParticle newParticle;

	for ( int i = 0; i < 4; i++ )
	{
		newParticle.m_Pos = offset;

		newParticle.m_flLifetime= 0.0f;
		newParticle.m_flDieTime	= random->RandomFloat( 0.1f, 0.25f );
		
		dir[0] = normal[0] + random->RandomFloat( -0.8f, 0.8f );
		dir[1] = normal[1] + random->RandomFloat( -0.8f, 0.8f );
		dir[2] = normal[2] + random->RandomFloat( -0.8f, 0.8f );

		newParticle.m_uchStartSize	= random->RandomInt( 1, 4 );
		newParticle.m_uchEndSize	= newParticle.m_uchStartSize * 8;

		newParticle.m_vecVelocity	= dir * random->RandomFloat( 8.0f, 16.0f )*(i+1);
		newParticle.m_vecVelocity[2] -= random->RandomFloat( 16.0f, 32.0f )*(i+1);

		newParticle.m_uchStartAlpha	= random->RandomInt( 128, 255 );
		newParticle.m_uchEndAlpha	= 0;
		
		newParticle.m_flRoll		= random->RandomFloat( 0, 360 );
		newParticle.m_flRollDelta	= random->RandomFloat( -1, 1 );

		colorRamp = random->RandomFloat( 0.5f, 1.25f );

		newParticle.m_uchColor[0] = MIN( 1.0f, color[0]*colorRamp )*255.0f;
		newParticle.m_uchColor[1] = MIN( 1.0f, color[1]*colorRamp )*255.0f;
		newParticle.m_uchColor[2] = MIN( 1.0f, color[2]*colorRamp )*255.0f;

		AddSimpleParticle( &newParticle, g_Mat_BloodPuff[0] );
	}

	//
	// Bullet hole capper
	//
	newParticle.m_Pos = offset;

	newParticle.m_flLifetime		= 0.0f;
	newParticle.m_flDieTime		= random->RandomFloat( 1.0f, 1.5f );

	dir[0] = normal[0] + random->RandomFloat( -0.8f, 0.8f );
	dir[1] = normal[1] + random->RandomFloat( -0.8f, 0.8f );
	dir[2] = normal[2] + random->RandomFloat( -0.8f, 0.8f );

	newParticle.m_uchStartSize	= random->RandomInt( 4, 8 );
	newParticle.m_uchEndSize		= newParticle.m_uchStartSize * 4.0f;

	newParticle.m_vecVelocity = dir * random->RandomFloat( 2.0f, 8.0f );
	newParticle.m_vecVelocity[2] = random->RandomFloat( -2.0f, 2.0f );

	newParticle.m_uchStartAlpha	= random->RandomInt( 32, 64 );
	newParticle.m_uchEndAlpha	= 0;
	
	newParticle.m_flRoll			= random->RandomFloat( 0, 360 );
	newParticle.m_flRollDelta	= random->RandomFloat( -2, 2 );

	colorRamp = random->RandomFloat( 0.5f, 1.25f );

	newParticle.m_uchColor[0] = MIN( 1.0f, color[0]*colorRamp )*255.0f;
	newParticle.m_uchColor[1] = MIN( 1.0f, color[1]*colorRamp )*255.0f;
	newParticle.m_uchColor[2] = MIN( 1.0f, color[2]*colorRamp )*255.0f;

	AddSimpleParticle( &newParticle, g_Mat_DustPuff[0] );
}
コード例 #12
0
ファイル: disp_vrad.cpp プロジェクト: Bubbasacs/FinalProj
void BlendEdges( CCoreDispInfo **ppListBase, int listSize )
{
	for ( int iDisp=0; iDisp < listSize; iDisp++ )
	{
		CCoreDispInfo *pDisp = ppListBase[iDisp];

		for ( int iEdge=0; iEdge < 4; iEdge++ )
		{
			CDispNeighbor *pEdge = pDisp->GetEdgeNeighbor( iEdge );

			for ( int iSub=0; iSub < 2; iSub++ )
			{
				CDispSubNeighbor *pSub = &pEdge->m_SubNeighbors[iSub];
				if ( !pSub->IsValid() )
					continue;

				CCoreDispInfo *pNeighbor = ppListBase[ pSub->GetNeighborIndex() ];

				int iEdgeDim = g_EdgeDims[iEdge];

				CDispSubEdgeIterator it;
				it.Start( pDisp, iEdge, iSub, true );

				// Get setup on the first corner vert.
				it.Next();
				CVertIndex viPrevPos = it.GetVertIndex();

				while ( it.Next() )
				{
					// Blend the two.
					if ( !it.IsLastVert() )
					{
						Vector vAverage = pDisp->GetNormal( it.GetVertIndex() ) + pNeighbor->GetNormal( it.GetNBVertIndex() );
						VectorNormalize( vAverage );

						pDisp->SetNormal( it.GetVertIndex(), vAverage );
						pNeighbor->SetNormal( it.GetNBVertIndex(), vAverage );

#if defined( USE_SCRATCHPAD )
						ScratchPad_DrawArrowSimple( g_pPad, pDisp->GetVert( it.GetVertIndex() ), pDisp->GetNormal( it.GetVertIndex() ), Vector( 1, 0, 0 ), 25 );
#endif
					}

					// Now blend the in-between verts (if this edge is high-res).
					int iPrevPos = viPrevPos[ !iEdgeDim ];
					int iCurPos = it.GetVertIndex()[ !iEdgeDim ];
					
					for ( int iTween = iPrevPos+1; iTween < iCurPos; iTween++ )
					{
						float flPercent = RemapVal( iTween, iPrevPos, iCurPos, 0, 1 );
						Vector vNormal;
						VectorLerp( pDisp->GetNormal( viPrevPos ), pDisp->GetNormal( it.GetVertIndex() ), flPercent, vNormal );
						VectorNormalize( vNormal );

						CVertIndex viTween;
						viTween[iEdgeDim] = it.GetVertIndex()[ iEdgeDim ];
						viTween[!iEdgeDim] = iTween;
						pDisp->SetNormal( viTween, vNormal );

#if defined( USE_SCRATCHPAD )
						ScratchPad_DrawArrowSimple( g_pPad, pDisp->GetVert( viTween ), pDisp->GetNormal( viTween ), Vector( 1, 0.5, 0 ), 25 );
#endif
					}
			
					viPrevPos = it.GetVertIndex();
				}
			}
		}
	}
}
コード例 #13
0
ファイル: r_trace.c プロジェクト: adem4ik/qfusion
/*
* R_TraceAgainstTriangle
*
* Ray-triangle intersection as per
* http://geometryalgorithms.com/Archive/algorithm_0105/algorithm_0105.htm
* (original paper by Dan Sunday)
*/
static void R_TraceAgainstTriangle( const vec_t *a, const vec_t *b, const vec_t *c ) {
	const vec_t *p1 = trace_start, *p2 = trace_end, *p0 = a;
	vec3_t u, v, w, n, p;
	float d1, d2, d, frac;
	float uu, uv, vv, wu, wv, s, t;

	// calculate two mostly perpendicular edge directions
	VectorSubtract( b, p0, u );
	VectorSubtract( c, p0, v );

	// we have two edge directions, we can calculate the normal
	CrossProduct( v, u, n );
	if( VectorCompare( n, vec3_origin ) ) {
		return;     // degenerate triangle

	}
	VectorSubtract( p2, p1, p );
	d2 = DotProduct( n, p );
	if( fabs( d2 ) < 0.0001 ) {
		return;
	}

	VectorSubtract( p1, p0, w );
	d1 = -DotProduct( n, w );

	// get intersect point of ray with triangle plane
	frac = ( d1 ) / d2;
	if( frac <= 0 ) {
		return;
	}
	if( frac >= trace_fraction ) {
		return;     // we have hit something earlier

	}
	// calculate the impact point
	VectorLerp( p1, frac, p2, p );

	// does p lie inside triangle?
	uu = DotProduct( u, u );
	uv = DotProduct( u, v );
	vv = DotProduct( v, v );

	VectorSubtract( p, p0, w );
	wu = DotProduct( w, u );
	wv = DotProduct( w, v );
	d = 1.0 / ( uv * uv - uu * vv );

	// get and test parametric coords

	s = ( uv * wv - vv * wu ) * d;
	if( s < 0.0 || s > 1.0 ) {
		return;     // p is outside

	}
	t = ( uv * wu - uu * wv ) * d;
	if( t < 0.0 || ( s + t ) > 1.0 ) {
		return;     // p is outside

	}
	trace_fraction = frac;
	VectorCopy( p, trace_impact );
	VectorCopy( n, trace_plane.normal );
}
コード例 #14
0
ファイル: cm_trace.c プロジェクト: AstralSerpent/QtZ
// Traverse all the contacted leafs from the start to the end position.
//	If the trace is a point, they will be exactly in order, but for larger trace volumes it is possible to hit
//	something in a later leaf with a smaller intercept fraction.
void CM_TraceThroughTree( traceWork_t *tw, int num, float p1f, float p2f, vector3 *p1, vector3 *p2) {
	cNode_t		*node;
	cplane_t	*plane;
	float		t1, t2, offset;
	float		frac, frac2;
	float		idist;
	vector3		mid;
	int			side;
	float		midf;

	if (tw->trace.fraction <= p1f) {
		return;		// already hit something nearer
	}

	// if < 0, we are in a leaf node
	if (num < 0) {
		CM_TraceThroughLeaf( tw, &cm.leafs[-1-num] );
		return;
	}

	//
	// find the point distances to the seperating plane
	// and the offset for the size of the box
	//
	node = cm.nodes + num;
	plane = node->plane;

	// adjust the plane distance appropriately for mins/maxs
	if ( plane->type < 3 ) {
		t1 = p1->data[plane->type] - plane->dist;
		t2 = p2->data[plane->type] - plane->dist;
		offset = tw->extents.data[plane->type];
	} else {
		t1 = DotProduct (&plane->normal, p1) - plane->dist;
		t2 = DotProduct (&plane->normal, p2) - plane->dist;
		if ( tw->isPoint ) {
			offset = 0;
		} else {
			// this is silly
			offset = 2048;
		}
	}

	// see which sides we need to consider
	if ( t1 >= offset + 1 && t2 >= offset + 1 ) {
		CM_TraceThroughTree( tw, node->children[0], p1f, p2f, p1, p2 );
		return;
	}
	if ( t1 < -offset - 1 && t2 < -offset - 1 ) {
		CM_TraceThroughTree( tw, node->children[1], p1f, p2f, p1, p2 );
		return;
	}

	// put the crosspoint SURFACE_CLIP_EPSILON pixels on the near side
	if ( t1 < t2 ) {
		idist = 1.0f/(t1-t2);
		side = 1;
		frac2 = (t1 + offset + SURFACE_CLIP_EPSILON)*idist;
		frac = (t1 - offset + SURFACE_CLIP_EPSILON)*idist;
	} else if (t1 > t2) {
		idist = 1.0f/(t1-t2);
		side = 0;
		frac2 = (t1 - offset - SURFACE_CLIP_EPSILON)*idist;
		frac = (t1 + offset + SURFACE_CLIP_EPSILON)*idist;
	} else {
		side = 0;
		frac = 1;
		frac2 = 0;
	}

	// move up to the node
	if ( frac < 0 ) {
		frac = 0;
	}
	if ( frac > 1 ) {
		frac = 1;
	}
		
	midf = p1f + (p2f - p1f)*frac;
	VectorLerp( p1, frac, p2, &mid );
	CM_TraceThroughTree( tw, node->children[side], p1f, midf, p1, &mid );


	// go past the node
	if ( frac2 < 0 ) {
		frac2 = 0;
	}
	if ( frac2 > 1 ) {
		frac2 = 1;
	}
		
	midf = p1f + (p2f - p1f)*frac2;
	VectorLerp( p1, frac, p2, &mid );
	CM_TraceThroughTree( tw, node->children[side^1], midf, p2f, &mid, p2 );
}
コード例 #15
0
ファイル: cm_trace.c プロジェクト: AstralSerpent/QtZ
// Handles offseting and rotation of the end points for moving and rotating entities
void CM_TransformedBoxTrace( trace_t *results, const vector3 *start, const vector3 *end, const vector3 *mins, const vector3 *maxs, clipHandle_t model, int brushmask, const vector3 *origin, const vector3 *angles, int capsule ) {
	trace_t		trace;
	vector3		start_l, end_l;
	qboolean	rotated;
	vector3		offset;
	vector3		symetricSize[2];
	matrix3		matrix, transpose;
	int			i;
	float		halfwidth;
	float		halfheight;
	float		t;
	sphere_t	sphere;

	if ( !mins ) {
		mins = &vec3_origin;
	}
	if ( !maxs ) {
		maxs = &vec3_origin;
	}

	// adjust so that mins and maxs are always symetric, which
	// avoids some complications with plane expanding of rotated
	// bmodels
	for ( i = 0 ; i < 3 ; i++ ) {
		offset.data[i] = ( mins->data[i] + maxs->data[i] ) * 0.5f;
		symetricSize[0].data[i] = mins->data[i] - offset.data[i];
		symetricSize[1].data[i] = maxs->data[i] - offset.data[i];
		start_l.data[i] = start->data[i] + offset.data[i];
		end_l.data[i] = end->data[i] + offset.data[i];
	}

	// subtract origin offset
	VectorSubtract( &start_l, origin, &start_l );
	VectorSubtract( &end_l, origin, &end_l );

	// rotate start and end into the models frame of reference
	if ( model != BOX_MODEL_HANDLE && 
		(angles->x || angles->y || angles->z) ) {
		rotated = qtrue;
	} else {
		rotated = qfalse;
	}

	halfwidth = symetricSize[1].x;
	halfheight = symetricSize[1].z;

	sphere.use = capsule;
	sphere.radius = ( halfwidth > halfheight ) ? halfheight : halfwidth;
	sphere.halfheight = halfheight;
	t = halfheight - sphere.radius;

	if (rotated) {
		// rotation on trace line (start-end) instead of rotating the bmodel
		// NOTE: This is still incorrect for bounding boxes because the actual bounding
		//		 box that is swept through the model is not rotated. We cannot rotate
		//		 the bounding box or the bmodel because that would make all the brush
		//		 bevels invalid.
		//		 However this is correct for capsules since a capsule itself is rotated too.
		CreateRotationMatrix(angles, matrix);
		RotatePoint(&start_l, matrix);
		RotatePoint(&end_l, matrix);
		// rotated sphere offset for capsule
		sphere.offset.x =  matrix[0].z * t;
		sphere.offset.y = -matrix[1].z * t;
		sphere.offset.z =  matrix[2].z * t;
	}
	else {
		VectorSet( &sphere.offset, 0, 0, t );
	}

	// sweep the box through the model
	CM_Trace( &trace, &start_l, &end_l, &symetricSize[0], &symetricSize[1], model, origin, brushmask, capsule, &sphere );

	// if the bmodel was rotated and there was a collision
	if ( rotated && trace.fraction != 1.0 ) {
		// rotation of bmodel collision plane
		MatrixTranspose(matrix, transpose);
		RotatePoint(&trace.plane.normal, transpose);
	}

	// re-calculate the end position of the trace because the trace.endpos
	// calculated by CM_Trace could be rotated and have an offset
	VectorLerp( start, trace.fraction, end, &trace.endpos );
	*results = trace;
}
コード例 #16
0
ファイル: cg_events.c プロジェクト: hettoo/racesow
void CG_LaserBeamEffect( centity_t *cent )
{
	struct sfx_s *sound = NULL;
	float range;
	trace_t trace;
	orientation_t projectsource;
	vec4_t color;
	vec3_t laserOrigin, laserAngles, laserPoint;
	int i, j;

	if( cent->localEffects[LOCALEFFECT_LASERBEAM] <= cg.time )
		return;

	laserOwner = cent;

	if( cg_teamColoredBeams->integer && ( cent->current.team == TEAM_ALPHA || cent->current.team == TEAM_BETA ) )
		CG_TeamColor( cent->current.team, color );
	else
		Vector4Set( color, 1, 1, 1, 1 );

	// interpolate the positions

	if( ISVIEWERENTITY( cent->current.number ) && !cg.view.thirdperson )
	{
		VectorCopy( cg.predictedPlayerState.pmove.origin, laserOrigin );
		laserOrigin[2] += cg.predictedPlayerState.viewheight;
		VectorCopy( cg.predictedPlayerState.viewangles, laserAngles );

		VectorLerp( cent->laserPointOld, cg.lerpfrac, cent->laserPoint, laserPoint );
	}
	else
	{
		VectorLerp( cent->laserOriginOld, cg.lerpfrac, cent->laserOrigin, laserOrigin );
		VectorLerp( cent->laserPointOld, cg.lerpfrac, cent->laserPoint, laserPoint );
		if( !cent->laserCurved )
		{
			vec3_t dir;

			// make up the angles from the start and end points (s->angles is not so precise)
			VectorSubtract( laserPoint, laserOrigin, dir );
			VecToAngles( dir, laserAngles );
		}
		else // use player entity angles
		{
			for( i = 0; i < 3; i++ )
				laserAngles[i] = LerpAngle( cent->prev.angles[i], cent->current.angles[i], cg.lerpfrac );
		}
	}

	if( !cent->laserCurved )
	{
		range = GS_GetWeaponDef( WEAP_LASERGUN )->firedef.timeout;

		if( cent->current.effects & EF_QUAD )
			sound = CG_MediaSfx( cgs.media.sfxLasergunStrongQuadHum );
		else
			sound = CG_MediaSfx( cgs.media.sfxLasergunStrongHum );

		// trace the beam: for tracing we use the real beam origin
		GS_TraceLaserBeam( &trace, laserOrigin, laserAngles, range, cent->current.number, 0, _LaserImpact );
		
		// draw the beam: for drawing we use the weapon projection source (already handles the case of viewer entity)
		if( !CG_PModel_GetProjectionSource( cent->current.number, &projectsource ) )
			VectorCopy( laserOrigin, projectsource.origin );

		CG_KillPolyBeamsByTag( cent->current.number );
		CG_LaserGunPolyBeam( projectsource.origin, trace.endpos, color, cent->current.number );
	}
	else
	{
		float frac, subdivisions = cg_laserBeamSubdivisions->integer;
		vec3_t from, dir, end, blendPoint;
		int passthrough = cent->current.number;
		vec3_t tmpangles, blendAngles;

		range = GS_GetWeaponDef( WEAP_LASERGUN )->firedef_weak.timeout;

		if( cent->current.effects & EF_QUAD )
			sound = CG_MediaSfx( cgs.media.sfxLasergunWeakQuadHum );
		else
			sound = CG_MediaSfx( cgs.media.sfxLasergunWeakHum );

		// trace the beam: for tracing we use the real beam origin
		GS_TraceCurveLaserBeam( &trace, laserOrigin, laserAngles, laserPoint, cent->current.number, 0, _LaserImpact );

		// draw the beam: for drawing we use the weapon projection source (already handles the case of viewer entity)
		if( !CG_PModel_GetProjectionSource( cent->current.number, &projectsource ) )
			VectorCopy( laserOrigin, projectsource.origin );

		if( subdivisions < CURVELASERBEAM_SUBDIVISIONS )
			subdivisions = CURVELASERBEAM_SUBDIVISIONS;

		CG_KillPolyBeamsByTag( cent->current.number );

		// we redraw the full beam again, and trace each segment for stop dead impact
		VectorCopy( laserPoint, blendPoint );
		VectorCopy( projectsource.origin, from );
		VectorSubtract( blendPoint, projectsource.origin, dir );
		VecToAngles( dir, blendAngles );

		for( i = 1; i <= (int)subdivisions; i++ )
		{
			frac = ( ( range/subdivisions )*(float)i ) / (float)range;

			for( j = 0; j < 3; j++ )
				tmpangles[j] = LerpAngle( laserAngles[j], blendAngles[j], frac );

			AngleVectors( tmpangles, dir, NULL, NULL );
			VectorMA( projectsource.origin, range * frac, dir, end );

			GS_TraceLaserBeam( &trace, from, tmpangles, DistanceFast( from, end ), passthrough, 0, NULL );
			CG_LaserGunPolyBeam( from, trace.endpos, color, cent->current.number );
			if( trace.fraction != 1.0f )
				break;

			passthrough = trace.ent;
			VectorCopy( trace.endpos, from );
		}
	}

	// enable continuous flash on the weapon owner
	if( cg_weaponFlashes->integer )
		cg_entPModels[cent->current.number].flash_time = cg.time + CG_GetWeaponInfo( WEAP_LASERGUN )->flashTime;

	if( sound )
	{
		if( ISVIEWERENTITY( cent->current.number ) )
			trap_S_AddLoopSound( sound, cent->current.number, 1.0, ATTN_NONE );
		else
			trap_S_AddLoopSound( sound, cent->current.number, 1.0, ATTN_STATIC );
	}

	laserOwner = NULL;
}
コード例 #17
0
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : bool - 
//-----------------------------------------------------------------------------
void C_TEShatterSurface::PostDataUpdate( DataUpdateType_t updateType )
{
	CSmartPtr<CSimple3DEmitter> pGlassEmitter = CSimple3DEmitter::Create( "C_TEShatterSurface 1" );
	pGlassEmitter->SetSortOrigin( m_vecOrigin );

	Vector vecColor;
	engine->ComputeLighting( m_vecOrigin, NULL, false, vecColor );

	// HACK: Blend a little toward white to match the materials...
	VectorLerp( vecColor, Vector( 1, 1, 1 ), 0.3, vecColor );

	PMaterialHandle hMaterial1;
	PMaterialHandle hMaterial2;
	if (m_nSurfaceType == SHATTERSURFACE_GLASS)
	{
		hMaterial1 = pGlassEmitter->GetPMaterial( "effects/fleck_glass1" );
		hMaterial2 = pGlassEmitter->GetPMaterial( "effects/fleck_glass2" );
	}
	else
	{
		hMaterial1 = pGlassEmitter->GetPMaterial( "effects/fleck_tile1" );
		hMaterial2 = pGlassEmitter->GetPMaterial( "effects/fleck_tile2" );
	}

	// ---------------------------------------------------
	// Figure out number of particles required to fill space
	// ---------------------------------------------------
	int nNumWide = m_flWidth  / m_flShardSize;
	int nNumHigh = m_flHeight / m_flShardSize;

	Vector vWidthStep,vHeightStep;
	AngleVectors(m_vecAngles,NULL,&vWidthStep,&vHeightStep);
	vWidthStep	*= m_flShardSize;
	vHeightStep *= m_flShardSize;

	// ---------------------
	// Create glass shards
	// ----------------------
	Vector vCurPos = m_vecOrigin;
	vCurPos.x += 0.5*m_flShardSize;
	vCurPos.z += 0.5*m_flShardSize;

	float flMinSpeed = 9999999999;
	float flMaxSpeed = 0;

	for (int width=0;width<nNumWide;width++)
	{
		for (int height=0;height<nNumHigh;height++)
		{
			Particle3D *pParticle;
			if (random->RandomInt(0,1))
			{
				pParticle = (Particle3D *) pGlassEmitter->AddParticle( sizeof(Particle3D), hMaterial1, vCurPos );
			}
			else
			{
				pParticle = (Particle3D *) pGlassEmitter->AddParticle( sizeof(Particle3D), hMaterial2, vCurPos );
			}

			Vector vForceVel = Vector(0,0,0);
			if (random->RandomInt(0, 3) != 0)
			{
				float flForceDistSqr = (vCurPos - m_vecForcePos).LengthSqr();
				vForceVel = m_vecForce;
				if (flForceDistSqr > 0 )
				{
					vForceVel *= ( 40.0f / flForceDistSqr );
				}
			}

			if (pParticle)
			{
				pParticle->m_flLifetime			= 0.0f;
				pParticle->m_flDieTime			= random->RandomFloat(GLASS_SHARD_MIN_LIFE,GLASS_SHARD_MAX_LIFE);
				pParticle->m_vecVelocity		= vForceVel;
				pParticle->m_vecVelocity	   += RandomVector(-25,25);
				pParticle->m_uchSize			= m_flShardSize + random->RandomFloat(-0.5*m_flShardSize,0.5*m_flShardSize);
				pParticle->m_vAngles			= m_vecAngles;
				pParticle->m_flAngSpeed			= random->RandomFloat(-400,400);

				pParticle->m_uchFrontColor[0]	= (int)(m_uchFrontColor[0] * vecColor.x + 0.5f);
				pParticle->m_uchFrontColor[1]	= (int)(m_uchFrontColor[1] * vecColor.y + 0.5f);
				pParticle->m_uchFrontColor[2]	= (int)(m_uchFrontColor[2] * vecColor.z + 0.5f);
				pParticle->m_uchBackColor[0]	= (int)(m_uchBackColor[0] * vecColor.x + 0.5f);
				pParticle->m_uchBackColor[1]	= (int)(m_uchBackColor[1] * vecColor.y + 0.5f);
				pParticle->m_uchBackColor[2]	= (int)(m_uchBackColor[2] * vecColor.z + 0.5f);
			}

			// Keep track of min and max speed for collision detection
			float  flForceSpeed = vForceVel.Length();
			if (flForceSpeed > flMaxSpeed)
			{
				flMaxSpeed = flForceSpeed;
			}
			if (flForceSpeed < flMinSpeed)
			{
				flMinSpeed = flForceSpeed;
			}

			vCurPos += vHeightStep;
		}
		vCurPos	 -= nNumHigh*vHeightStep;
		vCurPos	 += vWidthStep;
	}

	// --------------------------------------------------
	// Set collision parameters
	// --------------------------------------------------
	Vector vMoveDir = m_vecForce;
	VectorNormalize(vMoveDir);

	pGlassEmitter->m_ParticleCollision.Setup( m_vecOrigin, &vMoveDir, GLASS_SHARD_NOISE, 
												flMinSpeed, flMaxSpeed, GLASS_SHARD_GRAVITY, GLASS_SHARD_DAMPING );
}
コード例 #18
0
ファイル: tr_surface.c プロジェクト: coltongit/ioq3
static void LerpMeshVertexes(mdvSurface_t *surf, float backlerp)
{
	float *outXyz;
	int16_t *outNormal, *outTangent;
	mdvVertex_t *newVerts;
	int		vertNum;

	newVerts = surf->verts + backEnd.currentEntity->e.frame * surf->numVerts;

	outXyz =     tess.xyz[tess.numVertexes];
	outNormal =  tess.normal[tess.numVertexes];
	outTangent = tess.tangent[tess.numVertexes];

	if (backlerp == 0)
	{
		//
		// just copy the vertexes
		//

		for (vertNum=0 ; vertNum < surf->numVerts ; vertNum++)
		{
			VectorCopy(newVerts->xyz,    outXyz);
			VectorCopy4(newVerts->normal, outNormal);
			VectorCopy4(newVerts->tangent, outTangent);

			newVerts++;
			outXyz += 4;
			outNormal += 4;
			outTangent += 4;
		}
	}
	else
	{
		//
		// interpolate and copy the vertex and normal
		//

		mdvVertex_t *oldVerts;

		oldVerts = surf->verts + backEnd.currentEntity->e.oldframe * surf->numVerts;

		for (vertNum=0 ; vertNum < surf->numVerts ; vertNum++)
		{
			VectorLerp(newVerts->xyz,    oldVerts->xyz,    backlerp, outXyz);

			outNormal[0] = (int16_t)(newVerts->normal[0] * (1.0f - backlerp) + oldVerts->normal[0] * backlerp);
			outNormal[1] = (int16_t)(newVerts->normal[1] * (1.0f - backlerp) + oldVerts->normal[1] * backlerp);
			outNormal[2] = (int16_t)(newVerts->normal[2] * (1.0f - backlerp) + oldVerts->normal[2] * backlerp);
			outNormal[3] = 0;

			outTangent[0] = (int16_t)(newVerts->tangent[0] * (1.0f - backlerp) + oldVerts->tangent[0] * backlerp);
			outTangent[1] = (int16_t)(newVerts->tangent[1] * (1.0f - backlerp) + oldVerts->tangent[1] * backlerp);
			outTangent[2] = (int16_t)(newVerts->tangent[2] * (1.0f - backlerp) + oldVerts->tangent[2] * backlerp);
			outTangent[3] = newVerts->tangent[3];

			newVerts++;
			oldVerts++;
			outXyz += 4;
			outNormal += 4;
			outTangent += 4;
		}
	}

}
コード例 #19
0
/*
==============
RE_BuildSkeleton
==============
*/
int RE_BuildSkeleton( refSkeleton_t *skel, qhandle_t hAnim, int startFrame, int endFrame, float frac, bool clearOrigin )
{
	skelAnimation_t *skelAnim;

	skelAnim = R_GetAnimationByHandle( hAnim );

	if ( skelAnim->type == animType_t::AT_IQM && skelAnim->iqm ) {
		return IQMBuildSkeleton( skel, skelAnim, startFrame, endFrame, frac );
	}
	else if ( skelAnim->type == animType_t::AT_MD5 && skelAnim->md5 )
	{
		int            i;
		md5Animation_t *anim;
		md5Channel_t   *channel;
		md5Frame_t     *newFrame, *oldFrame;
		vec3_t         newOrigin, oldOrigin, lerpedOrigin;
		quat_t         newQuat, oldQuat, lerpedQuat;
		int            componentsApplied;

		anim = skelAnim->md5;

		// Validate the frames so there is no chance of a crash.
		// This will write directly into the entity structure, so
		// when the surfaces are rendered, they don't need to be
		// range checked again.

		/*
		   if((startFrame >= anim->numFrames) || (startFrame < 0) || (endFrame >= anim->numFrames) || (endFrame < 0))
		   {
		   Log::Debug("RE_BuildSkeleton: no such frame %d to %d for '%s'\n", startFrame, endFrame, anim->name);
		   //startFrame = 0;
		   //endFrame = 0;
		   }
		 */

		startFrame = Math::Clamp( startFrame, 0, anim->numFrames - 1 );
		endFrame = Math::Clamp( endFrame, 0, anim->numFrames - 1 );

		// compute frame pointers
		oldFrame = &anim->frames[ startFrame ];
		newFrame = &anim->frames[ endFrame ];

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

		for ( i = 0, channel = anim->channels; i < anim->numChannels; i++, channel++ )
		{
			// set baseframe values
			VectorCopy( channel->baseOrigin, newOrigin );
			VectorCopy( channel->baseOrigin, oldOrigin );

			QuatCopy( channel->baseQuat, newQuat );
			QuatCopy( channel->baseQuat, oldQuat );

			componentsApplied = 0;

			// update tranlation bits
			if ( channel->componentsBits & COMPONENT_BIT_TX )
			{
				oldOrigin[ 0 ] = oldFrame->components[ channel->componentsOffset + componentsApplied ];
				newOrigin[ 0 ] = newFrame->components[ channel->componentsOffset + componentsApplied ];
				componentsApplied++;
			}

			if ( channel->componentsBits & COMPONENT_BIT_TY )
			{
				oldOrigin[ 1 ] = oldFrame->components[ channel->componentsOffset + componentsApplied ];
				newOrigin[ 1 ] = newFrame->components[ channel->componentsOffset + componentsApplied ];
				componentsApplied++;
			}

			if ( channel->componentsBits & COMPONENT_BIT_TZ )
			{
				oldOrigin[ 2 ] = oldFrame->components[ channel->componentsOffset + componentsApplied ];
				newOrigin[ 2 ] = newFrame->components[ channel->componentsOffset + componentsApplied ];
				componentsApplied++;
			}

			// update quaternion rotation bits
			if ( channel->componentsBits & COMPONENT_BIT_QX )
			{
				( ( vec_t * ) oldQuat ) [ 0 ] = oldFrame->components[ channel->componentsOffset + componentsApplied ];
				( ( vec_t * ) newQuat ) [ 0 ] = newFrame->components[ channel->componentsOffset + componentsApplied ];
				componentsApplied++;
			}

			if ( channel->componentsBits & COMPONENT_BIT_QY )
			{
				( ( vec_t * ) oldQuat ) [ 1 ] = oldFrame->components[ channel->componentsOffset + componentsApplied ];
				( ( vec_t * ) newQuat ) [ 1 ] = newFrame->components[ channel->componentsOffset + componentsApplied ];
				componentsApplied++;
			}

			if ( channel->componentsBits & COMPONENT_BIT_QZ )
			{
				( ( vec_t * ) oldQuat ) [ 2 ] = oldFrame->components[ channel->componentsOffset + componentsApplied ];
				( ( vec_t * ) newQuat ) [ 2 ] = newFrame->components[ channel->componentsOffset + componentsApplied ];
			}

			QuatCalcW( oldQuat );
			QuatNormalize( oldQuat );

			QuatCalcW( newQuat );
			QuatNormalize( newQuat );

#if 1
			VectorLerp( oldOrigin, newOrigin, frac, lerpedOrigin );
			QuatSlerp( oldQuat, newQuat, frac, lerpedQuat );
#else
			VectorCopy( newOrigin, lerpedOrigin );
			QuatCopy( newQuat, lerpedQuat );
#endif

			// copy lerped information to the bone + extra data
			skel->bones[ i ].parentIndex = channel->parentIndex;

			if ( channel->parentIndex < 0 && clearOrigin )
			{
				VectorClear( skel->bones[ i ].t.trans );
				QuatClear( skel->bones[ i ].t.rot );

				// move bounding box back
				VectorSubtract( skel->bounds[ 0 ], lerpedOrigin, skel->bounds[ 0 ] );
				VectorSubtract( skel->bounds[ 1 ], lerpedOrigin, skel->bounds[ 1 ] );
			}
			else
			{
				VectorCopy( lerpedOrigin, skel->bones[ i ].t.trans );
			}

			QuatCopy( lerpedQuat, skel->bones[ i ].t.rot );
			skel->bones[ i ].t.scale = 1.0f;

#if defined( REFBONE_NAMES )
			Q_strncpyz( skel->bones[ i ].name, channel->name, sizeof( skel->bones[ i ].name ) );
#endif
		}

		skel->numBones = anim->numChannels;
		skel->type = refSkeletonType_t::SK_RELATIVE;
		return true;
	}

	// FIXME: clear existing bones and bounds?
	return false;
}
コード例 #20
0
ファイル: pm_surface.c プロジェクト: DeadZoneLuna/xash3d
/*
==================
PM_RecursiveSurfCheck

==================
*/
msurface_t *PM_RecursiveSurfCheck( model_t *model, mnode_t *node, vec3_t p1, vec3_t p2 )
{
	float		t1, t2, frac;
	int		side, ds, dt;
	mplane_t		*plane;
	msurface_t	*surf;
	vec3_t		mid;
	int		i;

	if( node->contents < 0 )
		return NULL;

	plane = node->plane;

	if( plane->type < 3 )
	{
		t1 = p1[plane->type] - plane->dist;
		t2 = p2[plane->type] - plane->dist;
	}
	else
	{
		t1 = DotProduct( plane->normal, p1 ) - plane->dist;
		t2 = DotProduct( plane->normal, p2 ) - plane->dist;
	}

	if( t1 >= 0.0f && t2 >= 0.0f )
		return PM_RecursiveSurfCheck( model, node->children[0], p1, p2 );
	if( t1 < 0.0f && t2 < 0.0f )
		return PM_RecursiveSurfCheck( model, node->children[1], p1, p2 );

	frac = t1 / ( t1 - t2 );

	if( frac < 0.0f ) frac = 0.0f;
	if( frac > 1.0f ) frac = 1.0f;

	VectorLerp( p1, frac, p2, mid );

	side = (t1 < 0.0f);

	// now this is weird.
	surf = PM_RecursiveSurfCheck( model, node->children[side], p1, mid );

	if( surf != NULL || ( t1 >= 0.0f && t2 >= 0.0f ) || ( t1 < 0.0f && t2 < 0.0f ))
	{
		return surf;
	}

	surf = model->surfaces + node->firstsurface;

	for( i = 0; i < node->numsurfaces; i++, surf++ )
	{
		ds = (int)((float)DotProduct( mid, surf->texinfo->vecs[0] ) + surf->texinfo->vecs[0][3] );
		dt = (int)((float)DotProduct( mid, surf->texinfo->vecs[1] ) + surf->texinfo->vecs[1][3] );

		if( ds >= surf->texturemins[0] && dt >= surf->texturemins[1] )
		{
			int s = ds - surf->texturemins[0];
			int t = dt - surf->texturemins[1];

			if( s <= surf->extents[0] && t <= surf->extents[1] )
				return surf;
		}
	}

	return PM_RecursiveSurfCheck( model, node->children[side^1], mid, p2 );
}
コード例 #21
0
void FX_ThumperDust( const CEffectData &data )
{
	Vector vecDustColor;
	vecDustColor.x = 0.85f;
	vecDustColor.y = 0.75f;
	vecDustColor.z = 0.52f;

	CSmartPtr<ThumperDustEmitter> pSimple = ThumperDustEmitter::Create( "thumperdust" );

	C_BaseEntity *pEnt = C_BaseEntity::Instance( data.m_hEntity );
	if ( pEnt )
	{
		Vector vWorldMins, vWorldMaxs;
		float scale = pEnt->CollisionProp()->BoundingRadius();
		vWorldMins[0] = data.m_vOrigin[0] - scale;
		vWorldMins[1] = data.m_vOrigin[1] - scale;
		vWorldMins[2] = data.m_vOrigin[2] - scale;
		vWorldMaxs[0] = data.m_vOrigin[0] + scale;
		vWorldMaxs[1] = data.m_vOrigin[1] + scale;
		vWorldMaxs[2] = data.m_vOrigin[2] + scale;
		pSimple->GetBinding().SetBBox( vWorldMins, vWorldMaxs, true );
	}

	pSimple->SetSortOrigin( data.m_vOrigin );
	pSimple->SetNearClip( 32, 64 );

	SimpleParticle	*pParticle = NULL;

	Vector	offset;

	//int	numPuffs = IsXbox() ? THUMPER_MAX_PARTICLES/2 : THUMPER_MAX_PARTICLES;
	int	numPuffs = THUMPER_MAX_PARTICLES;

	float flYaw = 0;
	float flIncr = (2*M_PI) / (float) numPuffs; // Radians
	Vector forward;
	Vector vecColor;
	int i = 0;

	float flScale = min( data.m_flScale, 255 );

	// Setup the color for these particles
	engine->ComputeLighting( data.m_vOrigin, NULL, true, vecColor );
	VectorLerp( vecColor, vecDustColor, 0.5, vecColor );
	vecColor *= 255;

	for ( i = 0; i < numPuffs; i++ )
	{
		flYaw += flIncr;
		SinCos( flYaw, &forward.y, &forward.x );	
		forward.z = 0.0f;

		offset = ( RandomVector( -4.0f, 4.0f ) + data.m_vOrigin ) + ( forward * 128.0f );

		pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof(SimpleParticle), g_Mat_DustPuff[random->RandomInt(0,1)], offset );
		if ( pParticle != NULL )
		{	
			pParticle->m_flLifetime		= 0.0f;
			pParticle->m_flDieTime		= 1.5f;
	
			Vector dir = (offset - data.m_vOrigin);
			float length = dir.Length();
			VectorNormalize( dir );

			pParticle->m_vecVelocity	= dir * ( length * 2.0f );
			pParticle->m_vecVelocity[2]	= data.m_flScale / 3;

			pParticle->m_uchColor[0]	= vecColor[0];
			pParticle->m_uchColor[1]	= vecColor[1];
			pParticle->m_uchColor[2]	= vecColor[2];

			pParticle->m_uchStartAlpha	= random->RandomInt( 64, 96 );
			pParticle->m_uchEndAlpha	= 0;

			pParticle->m_uchStartSize	= flScale * 0.25f;
			pParticle->m_uchEndSize		= flScale * 0.5f;

			pParticle->m_flRoll			= random->RandomInt( 0, 360 );
			pParticle->m_flRollDelta	= random->RandomFloat( -6.0f, 6.0f );
		}
	}
}
コード例 #22
0
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
bool CNPC_VehicleDriver::OverridePathMove( float flInterval )
{
	// Setup our initial path data if we've just started running a path
	if ( !m_pCurrentWaypoint )
	{
		m_vecPrevPoint = GetAbsOrigin();
		m_vecPrevPrevPoint = GetAbsOrigin();
		m_vecDesiredPosition = GetNavigator()->GetCurWaypointPos();	
		CalculatePostPoints();
	
		// Init our two waypoints
		m_Waypoints[0] = new CVehicleWaypoint( m_vecPrevPrevPoint, m_vecPrevPoint, m_vecDesiredPosition, m_vecPostPoint );
		m_Waypoints[1] = new CVehicleWaypoint( m_vecPrevPoint, m_vecDesiredPosition, m_vecPostPoint, m_vecPostPostPoint );
		m_pCurrentWaypoint = m_Waypoints[0];
		m_pNextWaypoint = m_Waypoints[1];

		m_flDistanceAlongSpline = 0.2;
	}

	// Have we reached our target? See if we've passed the current waypoint's plane.
	Vector vecAbsMins, vecAbsMaxs;
	CollisionProp()->WorldSpaceAABB( &vecAbsMins, &vecAbsMaxs );
	if ( BoxOnPlaneSide( vecAbsMins, vecAbsMaxs, &m_pCurrentWaypoint->planeWaypoint ) == 3 )
	{
		if ( WaypointReached() )
			return true;
	}

	// Did we bypass it and reach the next one already?
	if ( m_pNextWaypoint && BoxOnPlaneSide( vecAbsMins, vecAbsMaxs, &m_pNextWaypoint->planeWaypoint ) == 3 )
	{
		if ( WaypointReached() )
			return true;
	}

	// We may have just teleported, so check to make sure we have a waypoint
	if ( !m_pCurrentWaypoint || !m_pNextWaypoint )
		return false;

	// Figure out which spline we're trucking along
	CVehicleWaypoint *pCurrentSplineBeingTraversed = m_pCurrentWaypoint;
	if ( m_flDistanceAlongSpline > 1 )
	{
		pCurrentSplineBeingTraversed = m_pNextWaypoint;
	}

	// Get our current speed, and check it against the length of the spline to know how far to advance our marker
	AngularImpulse angVel;
	Vector vecVelocity;
	IPhysicsObject *pVehiclePhysics = m_hVehicleEntity->VPhysicsGetObject();

	if( !pVehiclePhysics )
	{
		// I think my vehicle has been destroyed.
		return false;
	}

	pVehiclePhysics->GetVelocity( &vecVelocity, &angVel );
	float flSpeed = vecVelocity.Length();
	float flIncTime = gpGlobals->curtime - GetLastThink();
	float flIncrement = flIncTime * (flSpeed / pCurrentSplineBeingTraversed->GetLength());

	// Now advance our point along the spline
	m_flDistanceAlongSpline = clamp( m_flDistanceAlongSpline + flIncrement, 0, 2);
	if ( m_flDistanceAlongSpline > 1 )
	{
		// We crossed the spline boundary
		pCurrentSplineBeingTraversed = m_pNextWaypoint;
	}

	Vector vSplinePoint = pCurrentSplineBeingTraversed->GetPointAt( m_flDistanceAlongSpline > 1 ? m_flDistanceAlongSpline-1 : m_flDistanceAlongSpline );
	Vector vSplineTangent = pCurrentSplineBeingTraversed->GetTangentAt( m_flDistanceAlongSpline > 1 ? m_flDistanceAlongSpline-1 : m_flDistanceAlongSpline );

	// Now that we've got the target spline point & tangent, use it to decide what our desired velocity is.
	// If we're close to the tangent, just use the tangent. Otherwise, Lerp towards it.
	Vector vecToDesired = (vSplinePoint - GetAbsOrigin());
	float flDistToDesired = VectorNormalize( vecToDesired );
	float flTangentLength = VectorNormalize( vSplineTangent );

	if ( flDistToDesired > (flTangentLength * 0.75) )
	{
		m_vecDesiredVelocity = vecToDesired * flTangentLength;
	}
	else
	{
		VectorLerp( vSplineTangent, vecToDesired * flTangentLength, (flDistToDesired / (flTangentLength * 0.5)), m_vecDesiredVelocity );
	}

	// Decrease speed according to the turn we're trying to make
	Vector vecRight;
	m_hVehicleEntity->GetVectors( NULL, &vecRight, NULL );
	Vector vecNormVel = m_vecDesiredVelocity;
	VectorNormalize( vecNormVel );
	float flDotRight = DotProduct( vecRight, vecNormVel );
	flSpeed = (1.0 - fabs(flDotRight));
	// Don't go slower than we've been told to go
	if ( flSpeed < m_flDriversMinSpeed )
	{
		flSpeed = m_flDriversMinSpeed;
	}
	m_vecDesiredVelocity = vecNormVel * (flSpeed * m_flMaxSpeed);

	// Bunch o'debug
	if ( g_debug_vehicledriver.GetInt() & DRIVER_DEBUG_PATH )
	{
		NDebugOverlay::Box( m_vecPrevPrevPoint, -Vector(15,15,15), Vector(15,15,15), 192,0,0, true, 0.1);
		NDebugOverlay::Box( m_vecPrevPoint, -Vector(20,20,20), Vector(20,20,20), 255,0,0, true, 0.1);
		NDebugOverlay::Box( m_vecPostPoint, -Vector(20,20,20), Vector(20,20,20), 0,192,0, true, 0.1);
		NDebugOverlay::Box( m_vecPostPostPoint, -Vector(20,20,20), Vector(20,20,20), 0,128,0, true, 0.1);
		NDebugOverlay::Box( vSplinePoint, -Vector(10,10,10), Vector(10,10,10), 0,0,255, true, 0.1);
		NDebugOverlay::Line( vSplinePoint, vSplinePoint + (vSplineTangent * 40), 0,0,255, true, 0.1);

		//NDebugOverlay::HorzArrow( pCurrentSplineBeingTraversed->splinePoints[0], pCurrentSplineBeingTraversed->splinePoints[1], 30, 255,255,255,0, false, 0.1f );
		//NDebugOverlay::HorzArrow( pCurrentSplineBeingTraversed->splinePoints[1], pCurrentSplineBeingTraversed->splinePoints[2], 20, 255,255,255,0, false, 0.1f );
		//NDebugOverlay::HorzArrow( pCurrentSplineBeingTraversed->splinePoints[2], pCurrentSplineBeingTraversed->splinePoints[3], 10, 255,255,255,0, false, 0.1f );

		// Draw the plane we're checking against for waypoint passing
		Vector vecPlaneRight;
		CrossProduct( m_pCurrentWaypoint->planeWaypoint.normal, Vector(0,0,1), vecPlaneRight );
		Vector vecPlane = m_pCurrentWaypoint->splinePoints[2];
		NDebugOverlay::Line( vecPlane + (vecPlaneRight * -100), vecPlane + (vecPlaneRight * 100), 255,0,0, true, 0.1);

		// Draw the next plane too
		CrossProduct( m_pNextWaypoint->planeWaypoint.normal, Vector(0,0,1), vecPlaneRight );
		vecPlane = m_pNextWaypoint->splinePoints[2];
		NDebugOverlay::Line( vecPlane + (vecPlaneRight * -100), vecPlane + (vecPlaneRight * 100), 192,0,0, true, 0.1);
	}

	if ( g_debug_vehicledriver.GetInt() & DRIVER_DEBUG_PATH_SPLINE )
	{
		for ( int i = 0; i < 10; i++ )
		{
			Vector vecTarget = m_pCurrentWaypoint->GetPointAt( 0.1 * i );
			Vector vecTangent = m_pCurrentWaypoint->GetTangentAt( 0.1 * i );
			VectorNormalize(vecTangent);
			NDebugOverlay::Box( vecTarget, -Vector(10,10,10), Vector(10,10,10), 255,0,0, true, 0.1 );
			NDebugOverlay::Line( vecTarget, vecTarget + (vecTangent * 10), 255,255,0, true, 0.1);
		}
	}

	return true;
}
コード例 #23
0
/*
* CG_AddWeaponOnTag
*
* Add weapon model(s) positioned at the tag
*/
void CG_AddWeaponOnTag( entity_t *ent, orientation_t *tag, int weaponid, int effects, orientation_t *projectionSource, unsigned int flash_time, unsigned int barrel_time )
{
	entity_t weapon;
	weaponinfo_t *weaponInfo;
	float intensity;

	//don't try without base model
	if( !ent->model )
		return;

	//don't try without a tag
	if( !tag )
		return;

	weaponInfo = CG_GetWeaponInfo( weaponid );
	if( !weaponInfo )
		return;

	//if( ent->renderfx & RF_WEAPONMODEL )
	//	effects &= ~EF_RACEGHOST;

	//weapon
	memset( &weapon, 0, sizeof( weapon ) );
	Vector4Set( weapon.shaderRGBA, 255, 255, 255, 255 );
	weapon.scale = ent->scale;
	weapon.renderfx = ent->renderfx;
	weapon.frame = 0;
	weapon.oldframe = 0;
	weapon.model = weaponInfo->model[WEAPON];

	CG_PlaceModelOnTag( &weapon, ent, tag );

	CG_AddColoredOutLineEffect( &weapon, effects, 0, 0, 0, 255 );

	if( !( effects & EF_RACEGHOST ) )
		CG_AddEntityToScene( &weapon );

	if( !weapon.model )
		return;

	CG_AddShellEffects( &weapon, effects );

	// update projection source
	if( projectionSource != NULL )
	{
		VectorCopy( vec3_origin, projectionSource->origin );
		Matrix3_Copy( axis_identity, projectionSource->axis );
		CG_MoveToTag( projectionSource->origin, projectionSource->axis,
			weapon.origin, weapon.axis,
			weaponInfo->tag_projectionsource.origin,
			weaponInfo->tag_projectionsource.axis );
	}

	//expansion
	if( ( effects & EF_STRONG_WEAPON ) && weaponInfo->model[EXPANSION] )
	{
		if( CG_GrabTag( tag, &weapon, "tag_expansion" ) )
		{
			entity_t expansion;
			memset( &expansion, 0, sizeof( expansion ) );
			Vector4Set( expansion.shaderRGBA, 255, 255, 255, 255 );
			expansion.model = weaponInfo->model[EXPANSION];
			expansion.scale = ent->scale;
			expansion.renderfx = ent->renderfx;
			expansion.frame = 0;
			expansion.oldframe = 0;

			CG_PlaceModelOnTag( &expansion, &weapon, tag );

			CG_AddColoredOutLineEffect( &expansion, effects, 0, 0, 0, 255 );

			if( !( effects & EF_RACEGHOST ) )
				CG_AddEntityToScene( &expansion ); // skelmod

			CG_AddShellEffects( &expansion, effects );
		}
	}

	// barrel
	if( weaponInfo->model[BARREL] )
	{
		if( CG_GrabTag( tag, &weapon, "tag_barrel" ) )
		{
			orientation_t barrel_recoiled;
			vec3_t rotangles = { 0, 0, 0 };

			entity_t barrel;
			memset( &barrel, 0, sizeof( barrel ) );
			Vector4Set( barrel.shaderRGBA, 255, 255, 255, 255 );
			barrel.model = weaponInfo->model[BARREL];
			barrel.scale = ent->scale;
			barrel.renderfx = ent->renderfx;
			barrel.frame = 0;
			barrel.oldframe = 0;

			// rotation
			if( barrel_time > cg.time )
			{
				intensity =  (float)( barrel_time - cg.time ) / (float)weaponInfo->barrelTime;
				rotangles[2] = ( 360.0f * weaponInfo->barrelSpeed * intensity * intensity );
				while( rotangles[2] > 360 ) rotangles[2] -= 360;

				// Check for tag_recoil
				if( CG_GrabTag( &barrel_recoiled, &weapon, "tag_recoil" ) )
					VectorLerp( tag->origin, intensity, barrel_recoiled.origin, tag->origin );
			}

			AnglesToAxis( rotangles, barrel.axis );

			// barrel requires special tagging
			CG_PlaceRotatedModelOnTag( &barrel, &weapon, tag );

			CG_AddColoredOutLineEffect( &barrel, effects, 0, 0, 0, 255 );

			if( !( effects & EF_RACEGHOST ) )
				CG_AddEntityToScene( &barrel ); // skelmod

			CG_AddShellEffects( &barrel, effects );
		}
	}

	if( flash_time < cg.time )
		return;

	// flash
	if( !CG_GrabTag( tag, &weapon, "tag_flash" ) )
		return;

	if( weaponInfo->model[FLASH] )
	{
		entity_t flash;
		qbyte c;

		if( weaponInfo->flashFade )
		{
			intensity = (float)( flash_time - cg.time )/(float)weaponInfo->flashTime;
			c = ( qbyte )( 255 * intensity );
		}
		else
		{
			intensity = 1.0f;
			c = 255;
		}

		memset( &flash, 0, sizeof( flash ) );
		Vector4Set( flash.shaderRGBA, c, c, c, c );
		flash.model = weaponInfo->model[FLASH];
		flash.scale = ent->scale;
		flash.renderfx = ent->renderfx | RF_NOSHADOW;
		flash.frame = 0;
		flash.oldframe = 0;

		CG_PlaceModelOnTag( &flash, &weapon, tag );

		if( !( effects & EF_RACEGHOST ) )
			CG_AddEntityToScene( &flash );

		CG_AddLightToScene( flash.origin, weaponInfo->flashRadius * intensity,
			weaponInfo->flashColor[0], weaponInfo->flashColor[1], weaponInfo->flashColor[2] );
	}
}
コード例 #24
0
ファイル: view.c プロジェクト: DrBeef/QuakeGVR
void V_CalcViewBlend(void)
{
	float a2;
	int j;
	r_refdef.viewblend[0] = 0;
	r_refdef.viewblend[1] = 0;
	r_refdef.viewblend[2] = 0;
	r_refdef.viewblend[3] = 0;
	r_refdef.frustumscale_x = 1;
	r_refdef.frustumscale_y = 1;
	if (cls.state == ca_connected && cls.signon == SIGNONS)
	{
		// set contents color
		int supercontents;
		vec3_t vieworigin;
		Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, vieworigin);
		supercontents = CL_PointSuperContents(vieworigin);
		if (supercontents & SUPERCONTENTS_LIQUIDSMASK)
		{
			r_refdef.frustumscale_x *= 1 - (((sin(cl.time * 4.7) + 1) * 0.015) * r_waterwarp.value);
			r_refdef.frustumscale_y *= 1 - (((sin(cl.time * 3.0) + 1) * 0.015) * r_waterwarp.value);
			if (supercontents & SUPERCONTENTS_LAVA)
			{
				cl.cshifts[CSHIFT_CONTENTS].destcolor[0] = 255;
				cl.cshifts[CSHIFT_CONTENTS].destcolor[1] = 80;
				cl.cshifts[CSHIFT_CONTENTS].destcolor[2] = 0;
			}
			else if (supercontents & SUPERCONTENTS_SLIME)
			{
				cl.cshifts[CSHIFT_CONTENTS].destcolor[0] = 0;
				cl.cshifts[CSHIFT_CONTENTS].destcolor[1] = 25;
				cl.cshifts[CSHIFT_CONTENTS].destcolor[2] = 5;
			}
			else
			{
				cl.cshifts[CSHIFT_CONTENTS].destcolor[0] = 130;
				cl.cshifts[CSHIFT_CONTENTS].destcolor[1] = 80;
				cl.cshifts[CSHIFT_CONTENTS].destcolor[2] = 50;
			}
			cl.cshifts[CSHIFT_CONTENTS].percent = 150 * 0.5;
		}
		else
		{
			cl.cshifts[CSHIFT_CONTENTS].destcolor[0] = 0;
			cl.cshifts[CSHIFT_CONTENTS].destcolor[1] = 0;
			cl.cshifts[CSHIFT_CONTENTS].destcolor[2] = 0;
			cl.cshifts[CSHIFT_CONTENTS].percent = 0;
		}

		if (gamemode != GAME_TRANSFUSION)
		{
			if (cl.stats[STAT_ITEMS] & IT_QUAD)
			{
				cl.cshifts[CSHIFT_POWERUP].destcolor[0] = 0;
				cl.cshifts[CSHIFT_POWERUP].destcolor[1] = 0;
				cl.cshifts[CSHIFT_POWERUP].destcolor[2] = 255;
				cl.cshifts[CSHIFT_POWERUP].percent = 30;
			}
			else if (cl.stats[STAT_ITEMS] & IT_SUIT)
			{
				cl.cshifts[CSHIFT_POWERUP].destcolor[0] = 0;
				cl.cshifts[CSHIFT_POWERUP].destcolor[1] = 255;
				cl.cshifts[CSHIFT_POWERUP].destcolor[2] = 0;
				cl.cshifts[CSHIFT_POWERUP].percent = 20;
			}
			else if (cl.stats[STAT_ITEMS] & IT_INVISIBILITY)
			{
				cl.cshifts[CSHIFT_POWERUP].destcolor[0] = 100;
				cl.cshifts[CSHIFT_POWERUP].destcolor[1] = 100;
				cl.cshifts[CSHIFT_POWERUP].destcolor[2] = 100;
				cl.cshifts[CSHIFT_POWERUP].percent = 100;
			}
			else if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY)
			{
				cl.cshifts[CSHIFT_POWERUP].destcolor[0] = 255;
				cl.cshifts[CSHIFT_POWERUP].destcolor[1] = 255;
				cl.cshifts[CSHIFT_POWERUP].destcolor[2] = 0;
				cl.cshifts[CSHIFT_POWERUP].percent = 30;
			}
			else
				cl.cshifts[CSHIFT_POWERUP].percent = 0;
		}

		cl.cshifts[CSHIFT_VCSHIFT].destcolor[0] = v_cshift.destcolor[0];
		cl.cshifts[CSHIFT_VCSHIFT].destcolor[1] = v_cshift.destcolor[1];
		cl.cshifts[CSHIFT_VCSHIFT].destcolor[2] = v_cshift.destcolor[2];
		cl.cshifts[CSHIFT_VCSHIFT].percent = v_cshift.percent;

		// LordHavoc: fixed V_CalcBlend
		for (j = 0;j < NUM_CSHIFTS;j++)
		{
			a2 = bound(0.0f, cl.cshifts[j].percent * (1.0f / 255.0f), 1.0f);
			if (a2 > 0)
			{
				VectorLerp(r_refdef.viewblend, a2, cl.cshifts[j].destcolor, r_refdef.viewblend);
				r_refdef.viewblend[3] = (1 - (1 - r_refdef.viewblend[3]) * (1 - a2)); // correct alpha multiply...  took a while to find it on the web
			}
		}
		// saturate color (to avoid blending in black)
		if (r_refdef.viewblend[3])
		{
			a2 = 1 / r_refdef.viewblend[3];
			VectorScale(r_refdef.viewblend, a2, r_refdef.viewblend);
		}
		r_refdef.viewblend[0] = bound(0.0f, r_refdef.viewblend[0], 255.0f);
		r_refdef.viewblend[1] = bound(0.0f, r_refdef.viewblend[1], 255.0f);
		r_refdef.viewblend[2] = bound(0.0f, r_refdef.viewblend[2], 255.0f);
		r_refdef.viewblend[3] = bound(0.0f, r_refdef.viewblend[3] * gl_polyblend.value, 1.0f);
		if (vid.sRGB3D)
		{
			r_refdef.viewblend[0] = Image_LinearFloatFromsRGB(r_refdef.viewblend[0]);
			r_refdef.viewblend[1] = Image_LinearFloatFromsRGB(r_refdef.viewblend[1]);
			r_refdef.viewblend[2] = Image_LinearFloatFromsRGB(r_refdef.viewblend[2]);
		}
		else
		{
			r_refdef.viewblend[0] *= (1.0f/256.0f);
			r_refdef.viewblend[1] *= (1.0f/256.0f);
			r_refdef.viewblend[2] *= (1.0f/256.0f);
		}
		
		// Samual: Ugly hack, I know. But it's the best we can do since
		// there is no way to detect client states from the engine.
		if (cl.stats[STAT_HEALTH] <= 0 && cl.stats[STAT_HEALTH] != -666 && 
			cl.stats[STAT_HEALTH] != -2342 && cl_deathfade.value > 0)
		{
			cl.deathfade += cl_deathfade.value * max(0.00001, cl.time - cl.oldtime);
			cl.deathfade = bound(0.0f, cl.deathfade, 0.9f);
		}
		else
			cl.deathfade = 0.0f;

		if(cl.deathfade > 0)
		{
			float a;
			float deathfadevec[3] = {0.3f, 0.0f, 0.0f};
			a = r_refdef.viewblend[3] + cl.deathfade - r_refdef.viewblend[3]*cl.deathfade;
			if(a > 0)
				VectorMAM(r_refdef.viewblend[3] * (1 - cl.deathfade) / a, r_refdef.viewblend, cl.deathfade / a, deathfadevec, r_refdef.viewblend);
			r_refdef.viewblend[3] = a;
		}
	}
}
コード例 #25
0
ファイル: interpolatortypes.cpp プロジェクト: paralin/hl2sdk
void Interpolator_CurveInterpolate_NonNormalized( int interpolationType,
	const Vector &vPre,
	const Vector &vStart,
	const Vector &vEnd,
	const Vector &vNext,
	float f,
	Vector &vOut )
{
	vOut.Init();

	switch ( interpolationType )
	{
	default:
		Warning( "Unknown interpolation type %d\n",
			(int)interpolationType );
		// break; // Fall through and use catmull_rom as default
	case INTERPOLATE_CATMULL_ROM_NORMALIZEX:
	case INTERPOLATE_DEFAULT:
	case INTERPOLATE_CATMULL_ROM:
	case INTERPOLATE_CATMULL_ROM_NORMALIZE:
	case INTERPOLATE_CATMULL_ROM_TANGENT:
		Catmull_Rom_Spline( 
			vPre,
			vStart,
			vEnd,
			vNext,
			f, 
			vOut );
		break;
	case INTERPOLATE_EASE_IN:
		{
			f = sin( M_PI * f * 0.5f );
			// Fixme, since this ignores vPre and vNext we could omit computing them aove
			VectorLerp( vStart, vEnd, f, vOut );
		}
		break;
	case INTERPOLATE_EASE_OUT:
		{
			f = 1.0f - sin( M_PI * f * 0.5f + 0.5f * M_PI );
			// Fixme, since this ignores vPre and vNext we could omit computing them aove
			VectorLerp( vStart, vEnd, f, vOut );
		}
		break;
	case INTERPOLATE_EASE_INOUT:
		{
			f = SimpleSpline( f );
			// Fixme, since this ignores vPre and vNext we could omit computing them aove
			VectorLerp( vStart, vEnd, f, vOut );
		}
		break;
	case INTERPOLATE_LINEAR_INTERP:
		// Fixme, since this ignores vPre and vNext we could omit computing them aove
		VectorLerp( vStart, vEnd, f, vOut );
		break;
	case INTERPOLATE_KOCHANEK_BARTELS:
	case INTERPOLATE_KOCHANEK_BARTELS_EARLY:
	case INTERPOLATE_KOCHANEK_BARTELS_LATE:
		{
			float t, b, c;
			Interpolator_GetKochanekBartelsParams( interpolationType, t, b, c );
			Kochanek_Bartels_Spline
			( 
				t, b, c, 
				vPre,
				vStart,
				vEnd,
				vNext,
				f, 
				vOut 
			);
		}
		break;
	case INTERPOLATE_SIMPLE_CUBIC:
		Cubic_Spline( 
			vPre,
			vStart,
			vEnd,
			vNext,
			f, 
			vOut );
		break;
	case INTERPOLATE_BSPLINE:
		BSpline( 
			vPre,
			vStart,
			vEnd,
			vNext,
			f, 
			vOut );
		break;
	case INTERPOLATE_EXPONENTIAL_DECAY:
		{
			float dt = vEnd.x - vStart.x;
			if ( dt > 0.0f )
			{
				float val = 1.0f - ExponentialDecay( 0.001, dt, f * dt ); 
				vOut.y = vStart.y + val * ( vEnd.y - vStart.y );
			}
			else
			{
				vOut.y = vStart.y;
			}
		}
		break;
	case INTERPOLATE_HOLD:
		{
			vOut.y = vStart.y;
		}
		break;
	}
}
コード例 #26
0
void ScratchPad_DrawLitCylinder( 
	IScratchPad3D *pPad,
	const Vector &v1,
	const Vector &v2,
	const Vector &vBrightColor,
	const Vector &vDarkColor,
	const Vector &vLightDir,
	float width,
	int nSegments )
{
	// Make orthogonal vectors.
	Vector vDir = v2 - v1;
	VectorNormalize( vDir );

	Vector vRight, vUp;
	VectorVectors( vDir, vRight, vUp );
	vRight *= width;
	vUp *= width;

	// Setup the top and bottom caps.
	CSPVertList topCap, bottomCap, quad;
	
	topCap.m_Verts.SetSize( nSegments );
	bottomCap.m_Verts.SetSize( nSegments );
	quad.m_Verts.SetSize( 4 );

	float flDot = -vLightDir.Dot( vDir );
	Vector topColor, bottomColor;

	VectorLerp( vDarkColor, vBrightColor, RemapVal( flDot,  -1, 1, 0, 1 ), topColor );
	VectorLerp( vDarkColor, vBrightColor, RemapVal( -flDot, -1, 1, 0, 1 ), bottomColor );

	
	// Draw each quad.
	Vector vPrevTop = v1 + vRight;
	Vector vPrevBottom = v2 + vRight;
	
	for ( int i=0; i < nSegments; i++ )
	{
		float flAngle = (float)(i+1) * M_PI * 2.0 / nSegments;
		Vector vOffset = vRight * cos( flAngle ) + vUp * sin( flAngle );
		Vector vCurTop = v1 + vOffset;
		Vector vCurBottom = v2 + vOffset;

		// Now light it.
		VectorNormalize( vOffset );
		flDot = -vLightDir.Dot( vOffset );
		Vector vColor;
		VectorLerp( vDarkColor, vBrightColor, RemapVal( flDot,  -1, 1, 0, 1 ), vColor );

		// Draw the quad.
		quad.m_Verts[0] = CSPVert( vPrevTop, vColor );
		quad.m_Verts[1] = CSPVert( vPrevBottom, vColor );
		quad.m_Verts[2] = CSPVert( vCurBottom, vColor );
		quad.m_Verts[3] = CSPVert( vCurTop, vColor );
		pPad->DrawPolygon( quad );

		topCap.m_Verts[i] = CSPVert( vCurTop, topColor );
		bottomCap.m_Verts[i] = CSPVert( vCurBottom, bottomColor );
	}

	pPad->DrawPolygon( topCap );
	pPad->DrawPolygon( bottomCap );
}
コード例 #27
0
void CLagCompensationManager::BacktrackEntity( CAI_BaseNPC *pEntity, float flTargetTime )
{
	Vector org, mins, maxs;
	QAngle ang;

	VPROF_BUDGET( "BacktrackEntity", "CLagCompensationManager" );

	// get track history of this entity
	int index = pEntity->GetAIIndex();
	CUtlFixedLinkedList< LagRecord > *track = &m_EntityTrack[ index ];

	// check if we have at leat one entry
	if ( track->Count() <= 0 )
		return;

	int curr = track->Head();

	LagRecord *prevRecord = NULL;
	LagRecord *record = NULL;

	Vector prevOrg = pEntity->GetLocalOrigin();
	
	// Walk context looking for any invalidating event
	while( track->IsValidIndex(curr) )
	{
		// remember last record
		prevRecord = record;

		// get next record
		record = &track->Element( curr );

		if ( !(record->m_fFlags & LC_ALIVE) )
		{
			// entity must be alive, lost track
			return;
		}

		Vector delta = record->m_vecOrigin - prevOrg;
		if ( delta.LengthSqr() > LAG_COMPENSATION_TELEPORTED_DISTANCE_SQR )
		{
			// lost track, moved too far (may have teleported)
			return; 
		}

		// did we find a context smaller than target time ?
		if ( record->m_flSimulationTime <= flTargetTime )
			break; // hurra, stop

		prevOrg = record->m_vecOrigin;

		// go one step back in time
		curr = track->Next( curr );
	}

	Assert( record );

	if ( !record )
	{
		if ( sv_unlag_debug.GetBool() )
		{
			DevMsg( "No valid positions in history for BacktrackEntity ( %s )\n", pEntity->GetClassname() );
		}

		return; // that should never happen
	}

	float frac = 0.0f;
	if ( prevRecord && 
		 (record->m_flSimulationTime < flTargetTime) &&
		 (record->m_flSimulationTime < prevRecord->m_flSimulationTime) )
	{
		// we didn't find the exact time but have a valid previous record
		// so interpolate between these two records;

		Assert( prevRecord->m_flSimulationTime > record->m_flSimulationTime );
		Assert( flTargetTime < prevRecord->m_flSimulationTime );

		// calc fraction between both records
		frac = ( flTargetTime - record->m_flSimulationTime ) / 
			( prevRecord->m_flSimulationTime - record->m_flSimulationTime );

		Assert( frac > 0 && frac < 1 ); // should never extrapolate

		ang  = Lerp( frac, record->m_vecAngles, prevRecord->m_vecAngles );
		org  = Lerp( frac, record->m_vecOrigin, prevRecord->m_vecOrigin  );
		mins = Lerp( frac, record->m_vecMins, prevRecord->m_vecMins  );
		maxs = Lerp( frac, record->m_vecMaxs, prevRecord->m_vecMaxs );
	}
	else
	{
		// we found the exact record or no other record to interpolate with
		// just copy these values since they are the best we have
		ang  = record->m_vecAngles;
		org  = record->m_vecOrigin;
		mins = record->m_vecMins;
		maxs = record->m_vecMaxs;
	}

	// See if this is still a valid position for us to teleport to
	if ( sv_unlag_fixstuck.GetBool() )
	{
		// Try to move to the wanted position from our current position.
		trace_t tr;
		UTIL_TraceEntity( pEntity, org, org, MASK_NPCSOLID, &tr );
		if ( tr.startsolid || tr.allsolid )
		{
			if ( sv_unlag_debug.GetBool() )
				DevMsg( "WARNING: BackupEntity trying to back entity into a bad position - %s\n", pEntity->GetClassname() );

			CBasePlayer *pHitPlayer = dynamic_cast<CBasePlayer *>( tr.m_pEnt );

			// don't lag compensate the current player
			if ( pHitPlayer && ( pHitPlayer != m_pCurrentPlayer ) )	
			{
				// If we haven't backtracked this player, do it now
				// this deliberately ignores WantsLagCompensationOnEntity.
				if ( !m_RestorePlayer.Get( pHitPlayer->entindex() - 1 ) )
				{
					// prevent recursion - save a copy of m_RestorePlayer,
					// pretend that this player is off-limits
					int pl_index = pEntity->entindex() - 1;

					// Temp turn this flag on
					m_RestorePlayer.Set( pl_index );

					BacktrackPlayer( pHitPlayer, flTargetTime );

					// Remove the temp flag
					m_RestorePlayer.Clear( pl_index );
				}				
			}
			else
			{
				CAI_BaseNPC *pHitEntity = dynamic_cast<CAI_BaseNPC *>( tr.m_pEnt );
				if ( pHitEntity )
				{
					CAI_BaseNPC *pNPC = NULL;
					CAI_BaseNPC **ppAIs = g_AI_Manager.AccessAIs();
					int nAIs = g_AI_Manager.NumAIs();
					for ( int i = 0; i < nAIs; i++ ) // we'll have to find this entity's index though :(
					{
						pNPC = ppAIs[i];
						if ( pNPC == pHitEntity )
							break;
					}
					// If we haven't backtracked this player, do it now
					// this deliberately ignores WantsLagCompensationOnEntity.
					if ( pNPC && !m_RestoreEntity.Get( pNPC->GetAIIndex() ) )
					{
						// prevent recursion - save a copy of m_RestoreEntity,
						// pretend that this player is off-limits

						// Temp turn this flag on
						m_RestoreEntity.Set( pNPC->GetAIIndex() );

						BacktrackEntity( pHitEntity, flTargetTime );

						// Remove the temp flag
						m_RestoreEntity.Clear( pNPC->GetAIIndex() );
					}
				}
			}

			// now trace us back as far as we can go
			UTIL_TraceEntity( pEntity, pEntity->GetLocalOrigin(), org, MASK_NPCSOLID, &tr );

			if ( tr.startsolid || tr.allsolid )
			{
				// Our starting position is bogus

				if ( sv_unlag_debug.GetBool() )
					DevMsg( "Backtrack failed completely, bad starting position\n" );
			}
			else
			{
				// We can get to a valid place, but not all the way to the target
				Vector vPos;
				VectorLerp( pEntity->GetLocalOrigin(), org, tr.fraction * g_flFractionScale, vPos );
				
				// This is as close as we're going to get
				org = vPos;

				if ( sv_unlag_debug.GetBool() )
					DevMsg( "Backtrack got most of the way\n" );
			}
		}
	}
	
	// See if this represents a change for the entity
	int flags = 0;
	LagRecord *restore = &m_EntityRestoreData[ index ];
	LagRecord *change  = &m_EntityChangeData[ index ];

	QAngle angdiff = pEntity->GetLocalAngles() - ang;
	Vector orgdiff = pEntity->GetLocalOrigin() - org;

	// Always remember the pristine simulation time in case we need to restore it.
	restore->m_flSimulationTime = pEntity->GetSimulationTime();

	if ( angdiff.LengthSqr() > LAG_COMPENSATION_EPS_SQR )
	{
		flags |= LC_ANGLES_CHANGED;
		restore->m_vecAngles = pEntity->GetLocalAngles();
		pEntity->SetLocalAngles( ang );
		change->m_vecAngles = ang;
	}

	// Use absolute equality here
	if ( ( mins != pEntity->WorldAlignMins() ) ||
		 ( maxs != pEntity->WorldAlignMaxs() ) )
	{
		flags |= LC_SIZE_CHANGED;
		restore->m_vecMins = pEntity->WorldAlignMins() ;
		restore->m_vecMaxs = pEntity->WorldAlignMaxs();
		pEntity->SetSize( mins, maxs );
		change->m_vecMins = mins;
		change->m_vecMaxs = maxs;
	}

	// Note, do origin at end since it causes a relink into the k/d tree
	if ( orgdiff.LengthSqr() > LAG_COMPENSATION_EPS_SQR )
	{
		flags |= LC_ORIGIN_CHANGED;
		restore->m_vecOrigin = pEntity->GetLocalOrigin();
		pEntity->SetLocalOrigin( org );
		change->m_vecOrigin = org;
	}

	// Sorry for the loss of the optimization for the case of people
	// standing still, but you breathe even on the server.
	// This is quicker than actually comparing all bazillion floats.
	flags |= LC_ANIMATION_CHANGED;
	restore->m_masterSequence = pEntity->GetSequence();
	restore->m_masterCycle = pEntity->GetCycle();

	bool interpolationAllowed = false;
	if( prevRecord && (record->m_masterSequence == prevRecord->m_masterSequence) )
	{
		// If the master state changes, all layers will be invalid too, so don't interp (ya know, interp barely ever happens anyway)
		interpolationAllowed = true;
	}
	
	////////////////////////
	// First do the master settings
	bool interpolatedMasters = false;
	if( frac > 0.0f && interpolationAllowed )
	{
		interpolatedMasters = true;
		pEntity->SetSequence( Lerp( frac, record->m_masterSequence, prevRecord->m_masterSequence ) );
		pEntity->SetCycle( Lerp( frac, record->m_masterCycle, prevRecord->m_masterCycle ) );

		if( record->m_masterCycle > prevRecord->m_masterCycle )
		{
			// the older record is higher in frame than the newer, it must have wrapped around from 1 back to 0
			// add one to the newer so it is lerping from .9 to 1.1 instead of .9 to .1, for example.
			float newCycle = Lerp( frac, record->m_masterCycle, prevRecord->m_masterCycle + 1 );
			pEntity->SetCycle(newCycle < 1 ? newCycle : newCycle - 1 );// and make sure .9 to 1.2 does not end up 1.05
		}
		else
		{
			pEntity->SetCycle( Lerp( frac, record->m_masterCycle, prevRecord->m_masterCycle ) );
		}
	}
	if( !interpolatedMasters )
	{
		pEntity->SetSequence(record->m_masterSequence);
		pEntity->SetCycle(record->m_masterCycle);
	}

	////////////////////////
	// Now do all the layers
	int layerCount = pEntity->GetNumAnimOverlays();
	for( int layerIndex = 0; layerIndex < layerCount; ++layerIndex )
	{
		CAnimationLayer *currentLayer = pEntity->GetAnimOverlay(layerIndex);
		if( currentLayer )
		{
			restore->m_layerRecords[layerIndex].m_cycle = currentLayer->m_flCycle;
			restore->m_layerRecords[layerIndex].m_order = currentLayer->m_nOrder;
			restore->m_layerRecords[layerIndex].m_sequence = currentLayer->m_nSequence;
			restore->m_layerRecords[layerIndex].m_weight = currentLayer->m_flWeight;

			bool interpolated = false;
			if( (frac > 0.0f)  &&  interpolationAllowed )
			{
				LayerRecord &recordsLayerRecord = record->m_layerRecords[layerIndex];
				LayerRecord &prevRecordsLayerRecord = prevRecord->m_layerRecords[layerIndex];
				if( (recordsLayerRecord.m_order == prevRecordsLayerRecord.m_order)
					&& (recordsLayerRecord.m_sequence == prevRecordsLayerRecord.m_sequence)
					)
				{
					// We can't interpolate across a sequence or order change
					interpolated = true;
					if( recordsLayerRecord.m_cycle > prevRecordsLayerRecord.m_cycle )
					{
						// the older record is higher in frame than the newer, it must have wrapped around from 1 back to 0
						// add one to the newer so it is lerping from .9 to 1.1 instead of .9 to .1, for example.
						float newCycle = Lerp( frac, recordsLayerRecord.m_cycle, prevRecordsLayerRecord.m_cycle + 1 );
						currentLayer->m_flCycle = newCycle < 1 ? newCycle : newCycle - 1;// and make sure .9 to 1.2 does not end up 1.05
					}
					else
					{
						currentLayer->m_flCycle = Lerp( frac, recordsLayerRecord.m_cycle, prevRecordsLayerRecord.m_cycle  );
					}
					currentLayer->m_nOrder = recordsLayerRecord.m_order;
					currentLayer->m_nSequence = recordsLayerRecord.m_sequence;
					currentLayer->m_flWeight = Lerp( frac, recordsLayerRecord.m_weight, prevRecordsLayerRecord.m_weight  );
				}
			}
			if( !interpolated )
			{
				//Either no interp, or interp failed.  Just use record.
				currentLayer->m_flCycle = record->m_layerRecords[layerIndex].m_cycle;
				currentLayer->m_nOrder = record->m_layerRecords[layerIndex].m_order;
				currentLayer->m_nSequence = record->m_layerRecords[layerIndex].m_sequence;
				currentLayer->m_flWeight = record->m_layerRecords[layerIndex].m_weight;
			}
		}
	}
	
	if ( !flags )
		return; // we didn't change anything

	if ( sv_lagflushbonecache.GetBool() )
		pEntity->InvalidateBoneCache();

	/*char text[256]; Q_snprintf( text, sizeof(text), "time %.2f", flTargetTime );
	pEntity->DrawServerHitboxes( 10 );
	NDebugOverlay::Text( org, text, false, 10 );
	NDebugOverlay::EntityBounds( pEntity, 255, 0, 0, 32, 10 ); */

	m_RestoreEntity.Set( index ); //remember that we changed this entity
	m_bNeedToRestore = true;  // we changed at least one player / entity
	restore->m_fFlags = flags; // we need to restore these flags
	change->m_fFlags = flags; // we have changed these flags

	if( sv_showlagcompensation.GetInt() == 1 )
	{
		pEntity->DrawServerHitboxes(4, true);
	}
}
コード例 #28
0
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CPointCommentaryNode::UpdateViewThink( void )
{
	if ( !m_bActive )
		return;
	CBasePlayer *pPlayer = GetCommentaryPlayer();
	if ( !pPlayer )
		return;

	// Swing the view towards the target
	if ( m_hViewTarget )
	{
 		QAngle angGoal;
 		QAngle angCurrent;
		if ( m_hViewPositionMover )
		{
			angCurrent = m_hViewPositionMover->GetAbsAngles();
			VectorAngles( m_hViewTarget->WorldSpaceCenter() - m_hViewPositionMover->GetAbsOrigin(), angGoal );
		}
		else
		{
			angCurrent = pPlayer->EyeAngles();
      		VectorAngles( m_hViewTarget->WorldSpaceCenter() - pPlayer->EyePosition(), angGoal );
		}

		// Accelerate towards the target goal angles
  		float dx = AngleDiff( angGoal.x, angCurrent.x );
  		float dy = AngleDiff( angGoal.y, angCurrent.y );
		float mod = 1.0 - ExponentialDecay( 0.5, 0.3, gpGlobals->frametime );
   		float dxmod = dx * mod;
		float dymod = dy * mod;

 		angCurrent.x = AngleNormalize( angCurrent.x + dxmod );
 		angCurrent.y = AngleNormalize( angCurrent.y + dymod );

		if ( m_hViewPositionMover )
		{
			m_hViewPositionMover->SetAbsAngles( angCurrent );
		}
		else
		{
			pPlayer->SnapEyeAngles( angCurrent );
		}

		SetNextThink( gpGlobals->curtime, s_pCommentaryUpdateViewThink );
	}

 	if ( m_hViewPosition.Get() )
	{
		if ( pPlayer->GetActiveWeapon() )
		{
			pPlayer->GetActiveWeapon()->Holster();
		}

 		if ( !m_hViewPositionMover )
		{
			// Make an invisible info target entity for us to attach the view to, 
			// and move it to the desired view position.
			m_hViewPositionMover = CreateEntityByName( "env_laserdot" );
			m_hViewPositionMover->SetAbsAngles( pPlayer->EyeAngles() );
			pPlayer->SetViewEntity( m_hViewPositionMover );
		}

		// Blend to the target position over time. 
 		float flCurTime = (gpGlobals->curtime - m_flStartTime);
 		float flBlendPerc = clamp( flCurTime / 2.0, 0, 1 );

		// Figure out the current view position
		Vector vecCurEye;
		VectorLerp( pPlayer->EyePosition(), m_hViewPosition.Get()->GetAbsOrigin(), flBlendPerc, vecCurEye );
		m_hViewPositionMover->SetAbsOrigin( vecCurEye ); 

		SetNextThink( gpGlobals->curtime, s_pCommentaryUpdateViewThink );
	}
}
コード例 #29
0
ファイル: g_clip.c プロジェクト: Kaperstone/warsow
static c4clipedict_t *GClip_GetClipEdictForDeltaTime( int entNum, int deltaTime )
{
	static int index = 0;
	static c4clipedict_t clipEnts[8];
	static c4clipedict_t *clipent;
	static c4clipedict_t clipentNewer; // for interpolation
	c4frame_t *cframe = NULL;
	unsigned int backTime, cframenum, backframes, i;
	edict_t	*ent = game.edicts + entNum;

	// pick one of the 8 slots to prevent overwritings
	clipent = &clipEnts[index];
	index = ( index + 1 )&7;

	if( !entNum || deltaTime >= 0 || !g_antilag->integer )
	{                                                    // current time entity
		clipent->r = ent->r;
		clipent->s = ent->s;
		return clipent;
	}

	if( !ent->r.inuse || ent->r.solid == SOLID_NOT 
		|| ( ent->r.solid == SOLID_TRIGGER && !(entNum >= 1 && entNum <= gs.maxclients) ) )
	{
		clipent->r = ent->r;
		clipent->s = ent->s;
		return clipent;
	}

	// clamp delta time inside the backed up limits
	backTime = abs( deltaTime );
	if( g_antilag_maxtimedelta->integer )
	{
		if( g_antilag_maxtimedelta->integer < 0 )
			trap_Cvar_SetValue( "g_antilag_maxtimedelta", abs( g_antilag_maxtimedelta->integer ) );
		if( backTime > (unsigned int)g_antilag_maxtimedelta->integer )
			backTime = (unsigned int)g_antilag_maxtimedelta->integer;
	}

	// find the first snap with timestamp < than realtime - backtime
	cframenum = sv_collisionFrameNum;
	for( backframes = 1; backframes < CFRAME_UPDATE_BACKUP && backframes < sv_collisionFrameNum; backframes++ ) // never overpass limits
	{
		cframe = &sv_collisionframes[( cframenum-backframes ) & CFRAME_UPDATE_MASK];
		// if solid has changed, we can't keep moving backwards
		if( ent->r.solid != cframe->clipEdicts[entNum].r.solid || ent->r.inuse != cframe->clipEdicts[entNum].r.inuse )
		{
			backframes--;
			if( backframes == 0 )
			{           // we can't step back from first
				cframe = NULL;
			}
			else
			{
				cframe = &sv_collisionframes[( cframenum-backframes ) & CFRAME_UPDATE_MASK];
			}
			break;
		}

		if( game.serverTime >= cframe->timestamp + backTime )
			break;
	}

	if( !cframe )
	{           // current time entity
		clipent->r = ent->r;
		clipent->s = ent->s;
		return clipent;
	}

	// setup with older for the data that is not interpolated
	*clipent = cframe->clipEdicts[entNum];

	// if we found an older than desired backtime frame, interpolate to find a more precise position.
	if( game.serverTime > cframe->timestamp+backTime )
	{
		float lerpFrac;

		if( backframes == 1 )
		{               // interpolate from 1st backed up to current
			lerpFrac = (float)( ( game.serverTime - backTime ) - cframe->timestamp ) / (float)( game.serverTime - cframe->timestamp );
			clipentNewer.r = ent->r;
			clipentNewer.s = ent->s;
		}
		else
		{ // interpolate between 2 backed up
			c4frame_t *cframeNewer = &sv_collisionframes[( cframenum-( backframes-1 ) ) & CFRAME_UPDATE_MASK];
			lerpFrac = (float)( ( game.serverTime - backTime ) - cframe->timestamp ) / (float)( cframeNewer->timestamp - cframe->timestamp );
			clipentNewer = cframeNewer->clipEdicts[entNum];
		}

		//G_Printf( "backTime:%i cframeBackTime:%i backFrames:%i lerfrac:%f\n", backTime, game.serverTime - cframe->timestamp, backframes, lerpFrac );

		// interpolate
		VectorLerp( clipent->s.origin, lerpFrac, clipentNewer.s.origin, clipent->s.origin );
		VectorLerp( clipent->r.mins, lerpFrac, clipentNewer.r.mins, clipent->r.mins );
		VectorLerp( clipent->r.maxs, lerpFrac, clipentNewer.r.maxs, clipent->r.maxs );
		for( i = 0; i < 3; i++ )
			clipent->s.angles[i] = LerpAngle( clipent->s.angles[i], clipentNewer.s.angles[i], lerpFrac );
	}

	//G_Printf( "backTime:%i cframeBackTime:%i backFrames:%i\n", backTime, game.serverTime - cframe->timestamp, backframes );

	// back time entity
	return clipent;
}
コード例 #30
0
ファイル: Vector4D.cpp プロジェクト: ljuwon321/pChanger
	Vector4D VectorLerp(const Vector4D& src1, const Vector4D& src2, vec_t t) {
		Vector4D result;
		VectorLerp(src1, src2, t, result);
		return result;
	}