/// Update light-related shader variables
void SetLightsToShader( CCopyEntity& entity, ShaderManager& rShaderMgr )
{
	shared_ptr<ShaderLightManager> pShaderLightMgr = rShaderMgr.GetShaderLightManager();

	int i, num_current_lights = entity.GetNumLights();
	LightEntity *pLightEntity = NULL;

	// clear any lights currenly stored in the shader light manager
	pShaderLightMgr->ClearLights();

	ShaderLightParamsWriter light_params_writer( pShaderLightMgr.get() );

	for( i=0; i<num_current_lights; i++ )
	{
		EntityHandle<LightEntity>& light_entity = entity.GetLight( i );
		LightEntity *pLightEntity = light_entity.GetRawPtr();
		if( !pLightEntity )
			continue;

//		pLightEntity->SetLightToShader( pShaderLightMgr );

		// copy light properties to the shader registers
		pLightEntity->GetLightObject()->Accept( light_params_writer );
	}

	pShaderLightMgr->CommitChanges();
}
/// Update shader params loaders for the entity.
/// Shader params loaders are shared by entities, and need to be updated every time an entity is rendered.
void UpdateEntityForRendering( CCopyEntity& entity )
{
	BaseEntity& base_entity = *(entity.pBaseEntity);

	// light params writer
	if( entity.GetEntityFlags() & BETYPE_LIGHTING )
	{
		UpdateLightInfo( entity );

		if( base_entity.MeshProperty().m_pShaderLightParamsLoader )
		{
			// Set the entity to the light params loader, because a single light params loader
			// is shared by all the entities of this base entity.
			base_entity.MeshProperty().m_pShaderLightParamsLoader->SetEntity( entity.Self().lock() );
		}
	}

	const float offset_world_transform_threshold = 150000.0f;
	if( square(offset_world_transform_threshold) < Vec3LengthSq(entity.GetWorldPose().vPosition) )
	{
		Camera* pCam = entity.GetStage()->GetCurrentCamera();
		if( pCam )
		{
			sg_pWorldTransLoader->SetActive( true );
			sg_pWorldTransLoader->SetCameraPosition( pCam->GetPosition() );
		}
		else
			sg_pWorldTransLoader->SetActive( false );

	}
	else
		sg_pWorldTransLoader->SetActive( false );
}
Exemple #3
0
void CStage::UpdateListener()
{
	Matrix34 cam_pose;
	Camera *pCamera;

	// get the pose of the current camera
	pCamera = this->GetCurrentCamera();
	if( pCamera )
	{
		pCamera->GetPose( cam_pose );
	}
	else
	{
		CCopyEntity* pEntity = this->GetEntitySet()->GetCameraEntity();
		if( pEntity )
			cam_pose = pEntity->GetWorldPose();
		else
			cam_pose.Identity();
	}

	// update listener for sound manager
	GetSoundManager().SetListenerPose( cam_pose ); 

	CCopyEntity *pCameraEntity = this->GetEntitySet()->GetCameraEntity();
	if( pCameraEntity )
		GetSoundManager().SetListenerVelocity( pCameraEntity->Velocity() ); 

	GetSoundManager().CommitDeferredSettings();
}
Result::Name RegisterAsPlanarMirror( CCopyEntity& entity, BasicMesh& mesh, int subset_index )
{
	const AABB3& aabb = mesh.GetAABB(subset_index);

	EntityRenderManager& entity_render_mgr
		= *(entity.GetStage()->GetEntitySet()->GetRenderManager());

	// >>> TODO: support planes that are not axis-aligned or facing along the negative half-space
	SPlane plane;
	int plane_axis = 1;
	if(      aabb.vMax.x - aabb.vMin.x < 0.001f ) plane_axis = 0;
	else if( aabb.vMax.y - aabb.vMin.y < 0.001f ) plane_axis = 1;
	else if( aabb.vMax.z - aabb.vMin.z < 0.001f ) plane_axis = 2;
	else plane_axis = 1;

	plane.normal = Vector3(0,0,0);
	plane.normal[plane_axis] = 1;
	plane.dist = aabb.vMax[plane_axis];

	Result::Name res = entity_render_mgr.AddPlanarReflector( EntityHandle<>( entity.Self() ), plane );

	if( res != Result::SUCCESS )
		return Result::UNKNOWN_ERROR;

	entity.RaiseEntityFlags( BETYPE_PLANAR_REFLECTOR );

	// Create shader variable loader for mirror 

	if( !entity.m_pMeshRenderMethod )
	{
		if( entity.pBaseEntity->MeshProperty().m_pMeshRenderMethod )
		{
			entity.m_pMeshRenderMethod
				= entity.pBaseEntity->MeshProperty().m_pMeshRenderMethod->CreateCopy();

			if( !entity.m_pMeshRenderMethod )
				return Result::UNKNOWN_ERROR;
		}
		else
			return Result::UNKNOWN_ERROR;
	}

	// create a planar reflection entity
//	shared_ptr<MeshContainerRenderMethod> pMeshRenderMethodCopy
//		= entity.m_pMeshRenderMethod->CreateCopy();

	shared_ptr<MirroredSceneTextureParam> pTexParam;
	pTexParam.reset( new MirroredSceneTextureParam( EntityHandle<>( entity.Self() ) ) );
	pTexParam->m_fReflection = mesh.GetMaterial(subset_index).m_Mat.fReflection;
//	pMeshRenderMethodCopy->SetShaderParamsLoaderToAllMeshRenderMethods( pTexParam );

	// test - we assume that the entity's mesh is composed of polygons that belong to a single plane.
	entity.m_pMeshRenderMethod->SetShaderParamsLoaderToAllMeshRenderMethods( pTexParam );

	// Move the indices of the planar reflection subset(s)
	// to the render method of the planar reflection entity

	return Result::SUCCESS;
}
Exemple #5
0
void AlphaEntity::Update( float dt )
{
	CCopyEntity *pParent = m_pParent;
	if( !pParent )
		return;

	SetWorldPose( pParent->GetWorldPose() );
}
static Vector3 GetPlayerPosition()
{
	CCopyEntity *pPlayer = GetPlayerEntity();
	if( pPlayer )
		return pPlayer->GetWorldPosition();
	else
		return Vector3(0,0,0);
}
Exemple #7
0
void EntityManager::UpdateGraphics()
{
	if( m_pEntityInUse )
	{
		for( CCopyEntity* pEntity = m_pEntityInUse.get();
			 pEntity != NULL;
			 pEntity = pEntity->m_pNextRawPtr )
		{
			pEntity->UpdateGraphics();
		}
	}
}
void UpdateLightInfo( CCopyEntity& entity )
{
	if( entity.Lighting() )
	{
		if( entity.sState & CESTATE_LIGHT_INFORMATION_INVALID )
		{
			// need to update light information - find lights that reaches to this entity
			entity.ClearLights();
			entity.GetStage()->GetEntitySet()->UpdateLights( &entity );
			entity.sState &= ~CESTATE_LIGHT_INFORMATION_INVALID;
		}
	}
}
void CBE_GeneralEntity::Act(CCopyEntity* pCopyEnt)
{
	float frametime = m_pStage->GetFrameTime();
	if( m_sGEAttribute & GETYPE_LIFETIMER )
	{
		float& rfLifeTimer = LifeTimer(pCopyEnt);
		rfLifeTimer -= frametime;

		if( rfLifeTimer <= 0.0f )
		{
			// lifetime has expired - terminate the entity

			if( 0 < strlen(m_Explosion.GetBaseEntityName()) )
			{
				// create explosion animation
				m_pStage->CreateEntity( m_Explosion, pCopyEnt->GetWorldPosition(), Vector3(0,0,0), pCopyEnt->GetDirection() );
			}

			m_pStage->TerminateEntity( pCopyEnt );
			return;
		}
	}

	if( pCopyEnt->bNoClip
	 && !(pCopyEnt->GetEntityFlags() & BETYPE_RIGIDBODY) )
	{
		// TODO: pose update for collidable enitity
		pCopyEnt->SetWorldPosition( pCopyEnt->GetWorldPosition() + pCopyEnt->Velocity() * frametime );
	}

//	if( 0 < strlen(m_SmokeTrace.GetBaseEntityName()) )
	if( 0 < m_vecSmokeTrail.size() )
	{
		int i, num = (int)m_vecSmokeTrail.size();
		for( i=0; i<num; i++ )
		{
			CCopyEntity* pSmokeTrace = pCopyEnt->GetChild(i);
			if( IsValidEntity( pSmokeTrace ) )
				pSmokeTrace->Act();	// update smoke trace
		}
	}

	if( pCopyEnt->GetEntityFlags() & BETYPE_ENVMAPTARGET )
	{
	}

/**	if( pCopyEnt->GetChild(0) )
		pCopyEnt->GetChild(0)->Act();**/

}
Exemple #10
0
void CBE_Enemy::SearchPlayer(CCopyEntity* pCopyEnt, short& rsMode,
							  Vector3& rvDesiredDirection, float* pfSqDistToPlayer)
{

	// ========= enable the following 2 lines to use enemy observation mode ==========
//	rsMode = CEnemyState::STATE_SEARCH;
//	return;


	Vector3 vStart, vMyselfToPlayer;
	CCopyEntity* pPlayer = SinglePlayerInfo().GetCurrentPlayerBaseEntity()->GetPlayerCopyEntity();

	vStart = pCopyEnt->GetWorldPosition() + pCopyEnt->GetDirection() * 1.42f;
	vMyselfToPlayer = pPlayer->GetWorldPosition() - vStart;

	// chehck the distance to the player
	float fSqDist = Vec3LengthSq( vMyselfToPlayer );
	if( pfSqDistToPlayer )
		*pfSqDistToPlayer = fSqDist;
	if( 40000 < fSqDist )
	{	// too far from the player
		rsMode = CEnemyState::STATE_SEARCH;
		return;
	}

	if( !CheckRayToPlayer(pCopyEnt) )
	{
		rsMode = CEnemyState::STATE_SEARCH;	// there is an obstacle between the player
		return;
	}

	// set 'rvDesiredDirection' - unit vector pointing at the target(player)
	Vec3Normalize( vMyselfToPlayer, vMyselfToPlayer );
	rvDesiredDirection = vMyselfToPlayer;

	float fDotProduct = Vec3Dot( pCopyEnt->GetDirection(), vMyselfToPlayer );

	// 'fDotProduct' ranges from -1 through 1
	if( 0 < fDotProduct )
	{	//the player is visible from this entity
		rsMode = CEnemyState::STATE_ATTACK;	// move to attack mode
	}
	else
	{
		if( fSqDist < 400.0f )
			rsMode = CEnemyState::STATE_ATTACK;	// close enough to hear the player
		else
			rsMode = CEnemyState::STATE_SEARCH;
	}
}
void BaseEntity::RenderEntity( CCopyEntity& entity )
{
	UpdateEntityForRendering( entity );

	// default render states for fixed function pipeline

	// default alpha-blending settings (premultiplied alpha)
	GraphicsDevice().Enable( RenderStateType::ALPHA_BLEND );
	GraphicsDevice().SetSourceBlendMode( AlphaBlend::One );
	GraphicsDevice().SetDestBlendMode( AlphaBlend::InvSrcAlpha );

	if( entity.m_pMeshRenderMethod )
	{
		entity.m_pMeshRenderMethod->RenderMesh( entity.m_MeshHandle, entity.GetWorldPose() );
	}
	else if( m_MeshProperty.m_pMeshRenderMethod )
	{
		m_MeshProperty.m_pMeshRenderMethod->RenderMesh( entity.m_MeshHandle, entity.GetWorldPose() );
	}

//	entity.m_pMeshRenderMethod->RenderMeshContainerNode( *(entity.m_pMeshNode.get()), m_vecpShaderParamsWriterBuffer );
}
Exemple #12
0
EntityHandle<> CStage::LoadStaticGeometryFromFile( const std::string filename )
{
	SafeDelete( m_pStaticGeometry );
	m_pStaticGeometry = CreateStaticGeometry( this, filename );

	if( !m_pStaticGeometry )
		return EntityHandle<>();

	// register the static geometry as an entity
	// - the entity is used to render the static geometry

	BaseEntityHandle baseentity_handle;
	baseentity_handle.SetBaseEntityName( "StaticGeometry" );
	CCopyEntityDesc desc;
	desc.strName = filename;
	desc.pBaseEntityHandle = &baseentity_handle;
	desc.pUserData = m_pStaticGeometry;

	CCopyEntity *pStaticGeometryEntity = CreateEntity( desc );

	if( !pStaticGeometryEntity )
		return EntityHandle<>();

//	shared_ptr<CStaticGeometryEntity> pEntity( new CStaticGeometryEntity );
//	pEntity->SetStaticGeometry( m_pStaticGeometry );
//	EntityHandle<CStaticGeometryEntity> entity
//		= CreateEntity( pEntity, baseentity_handle );

	m_pEntitySet->WriteEntityTreeToFile( "debug/entity_tree - loaded static geometry.txt" );

	// load the static geometry from file
	this->PauseTimer();
	bool loaded = m_pStaticGeometry->LoadFromFile( filename );
	this->ResumeTimer();

	return EntityHandle<>( pStaticGeometryEntity->Self() );
//	return entity;
}
// sets the following shader params loaders to the render method of an entity
// - CEntityShaderLightParamsLoader
//   - Set if the BETYPE_LIGHTING flag is on
// - BlendTransformsLoader
//   - Set if pEntity->m_MeshHandle is a skeletal mesh
void InitMeshRenderMethod( CCopyEntity &entity, shared_ptr<BlendTransformsLoader> pBlendTransformsLoader )
{
	if( !entity.m_pMeshRenderMethod )
	{
		entity.m_pMeshRenderMethod.reset( new MeshContainerRenderMethod );
//		entity.m_pMeshRenderMethod->MeshRenderMethod().resize( 1 );
	}

	if( entity.GetEntityFlags() & BETYPE_LIGHTING )
	{
		shared_ptr<CEntityShaderLightParamsLoader> pLightParamsLoader( new CEntityShaderLightParamsLoader() );
		pLightParamsLoader->SetEntity( entity.Self() );
		entity.m_pMeshRenderMethod->SetShaderParamsLoaderToAllMeshRenderMethods( pLightParamsLoader );
	}

	// Not used now.
	// Item entities set this in its own member function ItemEntity::InitMesh().
	// Does any entity other than item entty need this?
	if( pBlendTransformsLoader )
		entity.m_pMeshRenderMethod->SetShaderParamsLoaderToAllMeshRenderMethods( pBlendTransformsLoader );
/*
	shared_ptr<BasicMesh> pMesh = entity.m_MeshHandle.GetMesh();
	if( pMesh && pMesh->GetMeshType() == MeshType::SKELETAL )
	{
//		shared_ptr<SkeletalMesh> pSkeletalMesh
//			= boost::dynamic_pointer_cast<SkeletalMesh,BasicMesh>(pMesh);

		if( !pBlendTransformsLoader )
			pBlendTransformsLoader.reset( new BlendTransformsLoader() );

		entity.m_pMeshRenderMethod->SetShaderParamsLoaderToAllMeshRenderMethods( pBlendTransformsLoader );
	}*/

	if( true /* world position of entity has large values */ )
	{
		entity.m_pMeshRenderMethod->SetShaderParamsLoaderToAllMeshRenderMethods( sg_pWorldTransLoader );
	}
}
Exemple #14
0
void CES_Search::Act( CCopyEntity& rEntity, CBE_Enemy& rBaseEntity, float dt )
{
	// first, get the extra data of 'pCopyEnt'
	SBE_EnemyExtraData* pExtraData = rBaseEntity.GetExtraData( rEntity.iExtraDataIndex );

	short& rsCurrentState = rEntity.s1;
	float& rfSensoringInterval	= rEntity.f1;
	Vector3& rvDesiredDirection  = rEntity.v1;
	float fSqDistToPlayer;

	rfSensoringInterval += dt;

	if( 0.32f <= rfSensoringInterval )
	{
		rfSensoringInterval = 0;

		// check if the player is in a visible position and update 'rvDesiredDirection' and 'rsMode'
		short sSearchResult = 0;
		rBaseEntity.SearchPlayer( &rEntity, sSearchResult, rvDesiredDirection, &fSqDistToPlayer );

		if( sSearchResult == STATE_ATTACK )
		{	// the player is in sight - engage
			rsCurrentState = STATE_ATTACK;
			rBaseEntity.UpdateDesiredYawAndPitch( &rEntity, rvDesiredDirection );
			pExtraData->vLastCheckedDirectionToPlayer = rvDesiredDirection;
			pExtraData->fLastCheckedSqDistToPlayer    = fSqDistToPlayer;
			pExtraData->vLastCheckedPlayerPosition = rvDesiredDirection * (float)sqrt(fSqDistToPlayer);
			return;
		}
		else
		{	// lost sight of the player
			if( pExtraData->vLastCheckedPlayerPosition != Vector3(0,0,0) )
			{
				Vector3 vDir = pExtraData->vLastCheckedPlayerPosition - rEntity.GetWorldPosition();
				Vec3Normalize( rvDesiredDirection, vDir );
			}
		}
	}

	rBaseEntity.SearchManeuver(&rEntity,pExtraData);
}
/// Perhaps this should be a member of CCopyEntity, not BaseEntity
/// - m_pStage is the only member of the base entity
/// - CCopyEnttiy has m_pStage
void BaseEntity::SetAsEnvMapTarget( CCopyEntity& entity )
{
	if( entity.GetEntityFlags() & BETYPE_ENVMAPTARGET )
	{
//		shared_ptr<CubeTextureParamsLoader> pCubeTexLoader( new CCubeTextureParamsLoader() );
//		pCubeTexLoader->SetCubeTexture( 0, m_pStage->GetEntitySet()->GetRenderManager()->GetEnvMapTexture(entity.GetID()) );

//		entity.m_pMeshRenderMethod->AddShaderParamsLoaderToAllRenderMethods( pCubeTexLoader );

/*
		if( 0 < entity.m_pMeshRenderMethod->MeshRenderMethod().size() )
		{
			// shader LOD: fixed to 0
			entity.m_pMeshRenderMethod->MeshRenderMethod(0).m_vecpShaderParamsLoader.push_back( pCubeTexLoader );
		}
		else
		{
			// alpha entity?
		}*/
	}

}
Exemple #16
0
void EntityManager::UpdatePhysics( float frametime )
{
	PROFILE_FUNCTION();

//	frametime *= 0.5f;

	Scalar total_time = frametime + m_PhysOverlapTime;

	if (total_time > 0.1f)
		total_time = 0.1f;

	// split the timestep into fixed size chunks

	int num_loops = (int) (total_time / m_PhysTimestep);
	Scalar timestep = m_PhysTimestep;

	if ( false /*m_allow_smaller_timesteps*/ )
	{
		if (num_loops == 0)
			num_loops = 1;
		timestep = total_time / num_loops;
	}

	m_PhysOverlapTime = total_time - num_loops * timestep;

//	TCPreAllocDynamicLinkList<CJL_PhysicsActor>& rActorList = m_pStage->m_pPhysicsManager->GetActorList();

//	TCPreAllocDynamicLinkList<CJL_PhysicsActor>::LinkListIterator itrActor;

	int i;
	for (i=0 ; i<num_loops ; ++i)
	{
//		m_physics_time += timestep;

		// apply gravity
/*		for( itrActor = rActorList.Begin();
			itrActor != rActorList.End();
			itrActor++ )
		{
			if( !(itrActor->GetActorFlag() & JL_ACTOR_STATIC) )
                itrActor->AddWorldForce( itrActor->GetMass() * Vector3(0,-9.8f,0) );
		}
*/

		ProfileBegin( "Entity Update (Physics)" );

		// update physics properties that are specific to each entity
		// DO NOT CONFUSE THIS WITH CCopyEntity::UpdatePhysics()
		CCopyEntity *pEntity;
		for( pEntity = m_pEntityInUse.get();
			 pEntity != NULL;
			 pEntity = pEntity->m_pNextRawPtr )
		{
			if( pEntity->GetEntityFlags() & BETYPE_COPY_PARENT_POSE )
				pEntity->CopyParentPose();

//			if( pEntity->inuse && pEntity->pPhysicsActor )
			if( pEntity->inuse && 0 < pEntity->m_vecpPhysicsActor.size() )
                pEntity->pBaseEntity->UpdatePhysics( pEntity, timestep );

			UpdateEntityAfterMoving( pEntity );

		}

		ProfileEnd( "Entity Update (Physics)" );


		{
			PROFILE_SCOPE( "Physics Simulation" );

			// handle the motions and collisions of rigid body entities
//			m_pStage->m_pPhysicsManager->Integrate( timestep );
			m_pStage->GetPhysicsScene()->Simulate( timestep );

			while( !m_pStage->GetPhysicsScene()->FetchResults( physics::SimulationStatus::RigidBodyFinished ) )
			{}
		}

		// clear forces on actors
/*		for( itrActor = rActorList.Begin();
			itrActor != rActorList.End();
			itrActor++ )
		{
			itrActor->ClearForces();
		}
*/
	}
}
Exemple #17
0
void EntityManager::InitEntity( boost::shared_ptr<CCopyEntity> pNewCopyEntPtr,
							 CCopyEntity *pParent,
							 BaseEntity *pBaseEntity,
							 CActorDesc* pPhysActorDesc )
{
	CCopyEntity* pNewCopyEnt = pNewCopyEntPtr.get();

	// Mark the entity as in use
	pNewCopyEnt->inuse = true;

	pNewCopyEnt->m_pSelf = pNewCopyEntPtr;

	pNewCopyEnt->pBaseEntity = pBaseEntity;
	BaseEntity& rBaseEntity = (*pBaseEntity);

	pNewCopyEnt->m_pStage = m_pStage;

	// set id and increment the counter
	pNewCopyEnt->m_ID = m_EntityIDConter++;

	// z-sort is disabled by default initialization
	// Entities that have translucent polygons have to turn on their copy entities'
	// 'BETYPE_USE_ZSORT' in InitCopyEntity()
	if( pNewCopyEnt->m_TypeID == CCopyEntityTypeID::ALPHA_ENTITY )
	{
		// For alpha entity, always use the  z-sorting
		pNewCopyEnt->RaiseEntityFlags( BETYPE_USE_ZSORT );
	}
	else
	{
		// Otherwise, disable z-sorting by default
		pNewCopyEnt->ClearEntityFlags( BETYPE_USE_ZSORT );
	}

	// set the glare type
	if( rBaseEntity.m_EntityFlag & BETYPE_GLARESOURCE )
	{
		pNewCopyEnt->RaiseEntityFlags( BETYPE_GLARESOURCE );
	}
	else if( rBaseEntity.m_EntityFlag & BETYPE_GLAREHINDER )
	{
		pNewCopyEnt->RaiseEntityFlags( BETYPE_GLAREHINDER );
	}

	// update world aabb
	pNewCopyEnt->world_aabb.TransformCoord( pNewCopyEnt->local_aabb, pNewCopyEnt->GetWorldPosition() );


	// link the new copy-entity to the top of 'm_pEntityInUse'
	if( m_pEntityInUse )
		pNewCopyEnt->SetNext( m_pEntityInUse );
	else
		pNewCopyEnt->SetNextToNull(); // first entity in the link list

	m_pEntityInUse = pNewCopyEntPtr;


	// set the created time of the entity
	pNewCopyEnt->m_CreatedTime = m_pStage->GetElapsedTime();

	// set parent entity
	pNewCopyEnt->m_pParent = pParent;
	if( pNewCopyEnt->m_pParent )
	{
		// 'pNewCopyEnt' is being created as a child of another copy entity
		pNewCopyEnt->m_pParent->AddChild( pNewCopyEnt->m_pSelf );	// establish link from the parent to this entity
	}

//	LOG_PRINT( "linking a copy entity of " + rBaseEntity.GetNameString() + " to the tree" );

	// link the new copy-entity to the entity-tree
	Link( pNewCopyEnt );

	// update light information
	if( pNewCopyEnt->Lighting() )
	{
		pNewCopyEnt->ClearLights();
//		UpdateLightInfo( pNewCopyEnt );

		pNewCopyEnt->sState |= CESTATE_LIGHT_INFORMATION_INVALID;
	}

	// create object for physics simulation
	if( pNewCopyEnt->GetEntityFlags() & BETYPE_RIGIDBODY )
	{
		CActor *pPhysActor = NULL;
		if( pPhysActorDesc )
		{
			pPhysActorDesc->WorldPose = pNewCopyEnt->GetWorldPose();// * pNewCopyEnt->GetActorLocalPose();
			pPhysActorDesc->BodyDesc.LinearVelocity = pNewCopyEnt->Velocity();

			// each entity has its own actor desc
			pPhysActor = m_pStage->GetPhysicsScene()->CreateActor( *pPhysActorDesc );
		}
		else if( pBaseEntity->GetPhysicsActorDesc().IsValid() )
		{
			// actor desc is defined by entity attributes
			CActorDesc actor_desc = pBaseEntity->GetPhysicsActorDesc();
			actor_desc.WorldPose = pNewCopyEnt->GetWorldPose();
			actor_desc.BodyDesc.LinearVelocity = pNewCopyEnt->Velocity();
//			pNewCopyEnt->pPhysicsActor = m_pStage->GetPhysicsScene()->CreateActor( actor_desc );
			pPhysActor = m_pStage->GetPhysicsScene()->CreateActor( actor_desc );
		}

		if( pPhysActor )
		{
			pNewCopyEnt->m_vecpPhysicsActor.resize( 1 );
			pNewCopyEnt->m_vecpPhysicsActor[0] = pPhysActor;
			pPhysActor->m_pFrameworkData = pNewCopyEnt;
		}
	}

	// When all the basic properties are copied, InitCopyEntity() is called to 
	// do additional initialization specific to each base entity.
	rBaseEntity.InitCopyEntity( pNewCopyEnt );
}
Exemple #18
0
CCopyEntity *EntityManager::CreateEntity( CCopyEntityDesc& rCopyEntityDesc )
{
	if( !rCopyEntityDesc.pBaseEntityHandle )
		return NULL;

	BaseEntityHandle& rBaseEntityHandle = *(rCopyEntityDesc.pBaseEntityHandle);

//	LOG_PRINT( "creating a copy entity of " + string(rBaseEntityHandle.GetBaseEntityName()) );

	BaseEntity *pBaseEntity = GetBaseEntity( rBaseEntityHandle );
	if( !pBaseEntity )
		return NULL;

	BaseEntity& rBaseEntity = *(pBaseEntity);

//	LOG_PRINT( "checking the initial position of " + rBaseEntity.GetNameString() );

	// determine the entity group id
	// priority (higher to lower):
	// (id set to copy entity desc) -> (id set to base entity)
	int entity_group_id = ENTITY_GROUP_INVALID_ID;
	if( rCopyEntityDesc.sGroupID != ENTITY_GROUP_INVALID_ID )
	{
		entity_group_id = rCopyEntityDesc.sGroupID;
	}
	else
	{
		// try the group of base entity
		entity_group_id = rBaseEntity.GetEntityGroupID();
	}

	if( false )
//	if( !rBaseEntity.m_bNoClip )
//	 && rCopyEntityDesc.DontCreateIfOverlapIsDetected )
	{	// check for overlaps with other entities
		// to see if the new entity is in a valid position
//		if( rCopyEnt.bvType == BVTYPE_AABB || rCopyEnt.bvType == BVTYPE_DOT )
//		{
			STrace tr;
			tr.sTraceType = TRACETYPE_IGNORE_NOCLIP_ENTITIES;
			tr.vEnd       = rCopyEntityDesc.WorldPose.vPosition;
			tr.bvType     = rBaseEntity.m_BoundingVolumeType;
			tr.aabb       = rBaseEntity.m_aabb;
			tr.GroupIndex = entity_group_id;
			if( rBaseEntity.m_bNoClipAgainstMap )
				tr.sTraceType |= TRACETYPE_IGNORE_MAP;
			m_pStage->CheckPosition( tr );
			if(tr.in_solid)
			{
				LOG_PRINT( " - cannot create a copy entity due to overlaps: " + string(rBaseEntityHandle.GetBaseEntityName()) );
				return NULL;	// specified position is invalid - cannot create entity
			}
//		}
	}

//	LOG_PRINT( "the copy entity of " + rBaseEntity.GetNameString() + " is in a valid position" );

	// create an entity
	shared_ptr<CCopyEntity> pNewEntitySharedPtr = m_pEntityFactory->CreateEntity( rCopyEntityDesc.TypeID );
	if( !pNewEntitySharedPtr )
	{
		/// too many entities or no entity is defined for rCopyEntityDesc.TypeID
		LOG_PRINT_ERROR( " - cannot create a copy entity of '" + string(rBaseEntityHandle.GetBaseEntityName()) + "'" );
		return NULL;
	}

	CCopyEntity *pNewCopyEnt = pNewEntitySharedPtr.get();

	pNewCopyEnt->m_TypeID    = rCopyEntityDesc.TypeID;

	// copy parameter values from base entity (entity attributes set)
	SetBasicEntityAttributes( pNewCopyEnt, rBaseEntity );

	// copy parameter values from entity desc

	pNewCopyEnt->SetName( rCopyEntityDesc.strName );

	pNewCopyEnt->SetWorldPose( rCopyEntityDesc.WorldPose );

	pNewCopyEnt->Velocity()  = rCopyEntityDesc.vVelocity;
	pNewCopyEnt->fSpeed      = rCopyEntityDesc.fSpeed;

	pNewCopyEnt->m_MeshHandle = rCopyEntityDesc.MeshObjectHandle;

	pNewCopyEnt->f1 = rCopyEntityDesc.f1;
	pNewCopyEnt->f2 = rCopyEntityDesc.f2;
	pNewCopyEnt->f3 = rCopyEntityDesc.f3;
	pNewCopyEnt->f4 = rCopyEntityDesc.f4;
	pNewCopyEnt->f5 = 0.0f;
	pNewCopyEnt->s1 = rCopyEntityDesc.s1;
	pNewCopyEnt->v1 = rCopyEntityDesc.v1;
	pNewCopyEnt->v2 = rCopyEntityDesc.v2;
	pNewCopyEnt->iExtraDataIndex = rCopyEntityDesc.iExtraDataIndex;
	pNewCopyEnt->pUserData = rCopyEntityDesc.pUserData;

	pNewCopyEnt->sState   = 0;
	pNewCopyEnt->bInSolid = false;

	pNewCopyEnt->GroupIndex = entity_group_id;

//	pNewCopyEnt->GroupIndex = rCopyEntityDesc.sGroupID;

	pNewCopyEnt->touch_plane.dist   = 0;
	pNewCopyEnt->touch_plane.normal = Vector3(0,0,0);

	InitEntity( pNewEntitySharedPtr, rCopyEntityDesc.pParent, pBaseEntity, rCopyEntityDesc.pPhysActorDesc );

	pNewCopyEnt->Init( rCopyEntityDesc );

	LOG_PRINT_VERBOSE( " - created a copy entity of " + rBaseEntity.GetNameString() );

	return pNewCopyEnt;
}
// Initializes CCopyEntity::m_pMeshRenderMethod
// - Initialize the mesh render method
// - Initialize shader parameter loaders
// - Create alpha entities
// - Creates a shader
void BaseEntity::InitEntityGraphics( CCopyEntity &entity,
                                      ShaderHandle& shader,
                                      ShaderTechniqueHandle& tech )
{
	if( shader.IsLoaded()
	 && tech.GetTechniqueName()
	 && 0 < strlen(tech.GetTechniqueName()) )
	{
		CreateMeshRenderMethod( EntityHandle<>( entity.Self() ), shader, tech );
	}
	else
	{
		InitMeshRenderMethod( entity );
	}

	// create transparent parts of the model as separate entities
	if( m_EntityFlag & BETYPE_SUPPORT_TRANSPARENT_PARTS )
	{
		// Remove any previous alpha entities
		int next_child_index = 0;
		while( next_child_index < entity.GetNumChildren() )
//		for( int i=0; i<entity.GetNumChildren(); i++ )
		{
			shared_ptr<CCopyEntity> pChild = entity.m_aChild[next_child_index].Get();
			if( IsValidEntity(pChild.get())
			 && pChild->GetEntityTypeID() == CCopyEntityTypeID::ALPHA_ENTITY )
			{
				CCopyEntity *pChildRawPtr = pChild.get();
				m_pStage->TerminateEntity( pChildRawPtr );
			}
			else
				next_child_index += 1;
		}

		CreateAlphaEntities( &entity );
	}

	shared_ptr<BasicMesh> pMesh = entity.m_MeshHandle.GetMesh();
	if( !pMesh )
		return;

	BasicMesh& mesh = *pMesh;
	const int num_mesh_materials = mesh.GetNumMaterials();

	std::vector<GenericShaderDesc> shader_descs;
	shader_descs.resize( num_mesh_materials );

	std::vector<int> mirror_subsets_indices;
//	std::vector<int> non_mirror_subsets_indices;

	if( m_MeshProperty.m_MeshDesc.IsValid() )
//	if( true )
	{
		// The mesh is specified in the base entity
	}
	else
	{
		// base entity has no mesh
		// - entity's mesh is individual
		shader_descs.resize( num_mesh_materials );
		for( int i=0; i<num_mesh_materials; i++ )
		{
			// Fill out the shader desc based on the parameter values of the material

			// reflection
			bool registered_as_mirror = RegisterAsMirrorIfReflective( entity, mesh, i, shader_descs[i] );
			if( registered_as_mirror )
				mirror_subsets_indices.push_back( i );

			// specularity
			if( 0.001f < mesh.GetMaterial(i).m_Mat.fSpecularity )
				shader_descs[i].Specular = SpecularSource::UNIFORM;
			else
				shader_descs[i].Specular = SpecularSource::NONE;
		}

		vector< pair< GenericShaderDesc, vector<unsigned int> > > grouped_descs;
		group_elements( shader_descs, grouped_descs );

		// Do a NULL check just in case
		// The mesh render method is initialized by InitMeshRenderMethod() above.
		if( !entity.m_pMeshRenderMethod )
			entity.m_pMeshRenderMethod.reset( new MeshContainerRenderMethod );

		bool shader_loaded = false;
		if( grouped_descs.size() == 1 )
		{
			SubsetRenderMethod& render_method = entity.m_pMeshRenderMethod->PrimaryMeshRenderMethod();

			render_method.m_Technique.SetTechniqueName( "Default" );
			render_method.m_ShaderDesc.pShaderGenerator.reset( new GenericShaderGenerator( grouped_descs[0].first ) );

//			shader_loaded = render_method.Load();
			shader_loaded = render_method.m_Shader.Load( render_method.m_ShaderDesc );
		}
		else
		{
			LOG_PRINT_WARNING( "Mesh materials need different shaders. This situation is not supported yet (the total number of materials: " + to_string(num_mesh_materials) + ")." );
		}
	}
}
Exemple #20
0
bool EntityManager::MakeEntityTree(BSPTree* pSrcBSPTree)
{
//	Reset();

	vector<EntityNode> entity_tree;

	// allocate some memory in advance
	// not doing this may cause error in Release build
	entity_tree.reserve( 10000 );

	// create the new entity tree on the temporary node buffer entity_tree
	// - Do not copy the tree to m_paEntityTree until all the entities are unlinked
	MakeEntityNode_r(0, pSrcBSPTree, &entity_tree);

	if(entity_tree.size() == 0)
		return false;	// entity tree costruction failed

	entity_tree[0].sParent = -1;	// the root node has no parent

	// unlink all the entities from the current entity tree
	if( m_pEntityInUse )
	{
		for( CCopyEntity* pEntity = m_pEntityInUse.get();
			 pEntity != NULL;
			 pEntity = pEntity->m_pNextRawPtr )
		{
			pEntity->Unlink();
		}
	}

	// Do this AFTER all the entities are unlinked from the entity nodes
	SafeDeleteArray( m_paEntityTree );

	// copy the new tree
	m_NumEntityNodes = (int)entity_tree.size();
	m_paEntityTree = new EntityNode [ m_NumEntityNodes ];
	for(int i=0; i<m_NumEntityNodes; i++)
		m_paEntityTree[i] = entity_tree[i];

	entity_tree.clear();

	// set stage and entity set
	for(int i=0; i<m_NumEntityNodes; i++)
	{
		m_paEntityTree[i].m_pStage     = m_pStage;
		m_paEntityTree[i].m_pEntitySet = this;
	}


	// update entity tree of the render manager
	m_pRenderManager->UpdateEntityTree( m_paEntityTree, m_NumEntityNodes );

	WriteEntityTreeToFile( "debug/entity_tree - recreated the tree.txt" );

	// re-link all the entities to the new tree nodes
	if( m_pEntityInUse )
	{
		for( CCopyEntity* pEntity = m_pEntityInUse.get();
			 pEntity != NULL;
			 pEntity = pEntity->m_pNextRawPtr )
		{
			// added: 11:34 PM 5/25/2008
			// Do not re-link an entity if it has already been marked as 'not in use'
			// - Failure to do this leads to an invalid link in the entity tree node
			//   - Caused infinite loops in EntityNode::CheckPosition_r()
			if( !IsValidEntity( pEntity ) )
				continue;

			Link( pEntity );
		}
	}

	WriteEntityTreeToFile( "debug/entity_tree - re-linked entities to the tree.txt" );

	// re-link all the light entities to the new tree nodes
//	m_pLightEntityManager->RelinkLightEntities();

	return true;
}
Exemple #21
0
/**
 Update all the entities cerrently existing in the stage.
 This function must be called once per frame.
 - Basic steps
   - 1. Call BaseEntity::UpdateBaseEntity( dt ) for each base entity
   - 2. Save positions of copy entities
   - 3. Run physics simulator
   - 4. Remove terminated entities from the active list
   - 5. Call CCopyEntity::Act() for each copy entity except for child entities
   - 6. Update link to the entity tree node if an entity has changed its position in Act()
   TODO: Do 5 & 6 in a single loop to update link for each entity right after is Act().
         Current code does this in separate loops.
 */
void EntityManager::UpdateAllEntities( float dt )
{
	CCopyEntity *pEntity = NULL;
	CCopyEntity *pPrevEntity = NULL;
	CCopyEntity *pTouchedEnt = NULL;

	ONCE( LOG_PRINT( " - updating base entities" ) );

	size_t i, num_base_entities = m_vecpBaseEntity.size();
	for( i=0; i<num_base_entities; i++ )
	{
		m_vecpBaseEntity[i]->UpdateBaseEntity( dt );
	}

	// save the current entity positions
	for( pEntity = m_pEntityInUse.get();
	     pEntity != NULL;
	     pEntity = pEntity->m_pNextRawPtr )
	{
		pEntity->PrevPosition() = pEntity->GetWorldPosition();
	}

	// run physics simulator
	// entity position may be modified in this call
	UpdatePhysics( dt );

	ONCE( LOG_PRINT( " - updated physics" ) );

	// remove terminated entities from the active entity list
	ReleaseTerminatedEntities();

	ONCE( LOG_PRINT( " - removed terminated entities from the active entity list" ) );

	// update active entities
	for( pEntity = this->m_pEntityInUse.get(), pPrevEntity = NULL;
		 pEntity != NULL;
		 pPrevEntity = pEntity, pEntity = pEntity->m_pNextRawPtr )
	{
		// before updating pEntity, check if it has been terminated.
		if( !pEntity->inuse )
			continue;

		// set the results of physics simulation to
		// pose, velocity and angular velocity of the entity
//		if( pEntity->pPhysicsActor && pEntity->GetEntityFlags() & BETYPE_USE_PHYSSIM_RESULTS )
		if( 0 < pEntity->m_vecpPhysicsActor.size() && pEntity->GetEntityFlags() & BETYPE_USE_PHYSSIM_RESULTS )
			pEntity->UpdatePhysics();

		if( pEntity->sState & CESTATE_ATREST )
			continue;

		if( !pEntity->m_pParent || !pEntity->m_pParent->inuse )
		{
			// 'pEntity' has no parent or its parent is already terminated
			pEntity->pBaseEntity->Act( pEntity );
		}

		if( !pEntity->inuse )
			continue; // terminated in its own update routine

		UpdateEntityAfterMoving( pEntity );

		// deal with entities touched during this frame
		for(int i=0; i<pEntity->vecpTouchedEntity.size(); i++)
		{
			pTouchedEnt = pEntity->vecpTouchedEntity[i];
			pEntity->pBaseEntity->Touch( pEntity, pTouchedEnt );

			if( pTouchedEnt )
				pTouchedEnt->pBaseEntity->Touch( pTouchedEnt, pEntity );
		}

		// clear touched entities for the next frame
		pEntity->vecpTouchedEntity.clear();
	}

	ONCE( LOG_PRINT( " - updated active entities" ) );

	// unlink and link the entity in the entity tree if it changed its position
/*
	for( pEntity = m_pEntityInUse.get();
		 pEntity != NULL;
		 pPrevEntity = pEntity, pEntity = pEntity->m_pNextRawPtr )
	{
		if( !pEntity->inuse )
			continue;

		UpdateEntityAfterMoving();
	}
*/
}
Exemple #22
0
void CBE_Enemy::OnDestroyed( CCopyEntity* pCopyEnt )
{
	// explosion - usu. done by texture animation
	CCopyEntityDesc explosion;
	explosion.pBaseEntityHandle = &m_Explosion;
	explosion.SetWorldPose( pCopyEnt->GetWorldPose() );
	explosion.vVelocity  = Vector3(0,0,0);

	this->m_pStage->CreateEntity( explosion );

	// avoid overlaps with fragment entities
	pCopyEnt->bNoClip = true;

	LOG_PRINT( " An enemy entity destroyed - velocity: " + to_string(pCopyEnt->Velocity()) );

	CCopyEntity* pFragEntity;
//	MsgBoxFmt( "%s destroyed - creating %d fragments", pCopyEnt->GetName().c_str(), m_iNumFragments );
	const int num_fragments = m_iNumFragments;
	for(int i=0; i<num_fragments; i++)
	{
		const Fragment& frag = m_aFragment[i];

		CCopyEntityDesc& rFrag = explosion;	// reuse desc object
		rFrag.pBaseEntityHandle = &m_aFragment[i].BaseEntity;

		rFrag.SetWorldPosition( pCopyEnt->GetWorldPose() * frag.vOffset );
//		D3DXVec3TransformCoord( &vWorldFragmentOffset, &m_avFragmentOffset[i], &pCopyEnt->GetOrientation() );
//		rFrag.vPosition  = pCopyEnt->GetWorldPosition() + vWorldFragmentOffset;

		rFrag.SetWorldOrient( pCopyEnt->GetWorldPose().matOrient );

//BSPStageBase	rFrag.vVelocity  = pCopyEnt->Velocity() * 0.3f + vWorldFragmentOffset * 20.0f
//BSPStageBase			         + Vector3( RangedRand(-10.0f,10.0f), RangedRand(-8.0f,8.0f), RangedRand(-10.0f,10.0f) );

		rFrag.vVelocity = Vec3RandDir() * RangedRand( frag.InitVelocity.min, frag.InitVelocity.max )
//		rFrag.vVelocity = Vec3RandDir() * RangedRand( 15.5f, 35.0f )
				        + pCopyEnt->Velocity();

		pFragEntity = this->m_pStage->CreateEntity( rFrag );
		if( pFragEntity )
		{
			physics::CActor *pPhysicsActor = pFragEntity->GetPrimaryPhysicsActor();
			if( pPhysicsActor )
			{
				pPhysicsActor->SetAngularVelocity( Vec3RandDir() * RangedRand( 0.5f, 8.0f ) );
			}
		}
	}

/*
	int num_items = m_vecRewardItem.size();
	float f = 0, rand_val;
	for(i=0; i<m_iNumFragments; i++)
	{
		rand_val = GetRangedRand( 0.0f, 1.0f );
		f += m_vecRewardItem[i].m_fProbability;

		if( rand_val < f )
		{
		}
	}
	*/

	// leave a life item
//			m_pStage->CreateEntity( "s_Life", pCopyEnt->GetWorldPosition(),
//				Vector3(0,0,0), Vector3(0,0,1) );
}
Exemple #23
0
bool CBE_Enemy::CheckRayToPlayer( CCopyEntity* pCopyEnt )
{
	CCopyEntity* pPlayer = SinglePlayerInfo().GetCurrentPlayerBaseEntity()->GetPlayerCopyEntity();
///	CCopyEntity* pPlayer = PlayerShip.GetPlayerCopyEntity();
	STrace tr;
	Vector3 vCurrentPos = pCopyEnt->GetWorldPosition();
	Vector3 vGoal       = pPlayer->GetWorldPosition();
	tr.vStart        = vCurrentPos;
	tr.vGoal         = vGoal;
	tr.bvType        = BVTYPE_DOT;
	tr.fRadius       = 0;
	tr.pSourceEntity = pCopyEnt;
	tr.sTraceType    = TRACETYPE_IGNORE_NOCLIP_ENTITIES;
	Vector3 vDirToPlayer = vGoal - vCurrentPos;
	Vec3Normalize( vDirToPlayer, vDirToPlayer );	// normalization
	short sRadarPenetrationCount = 2;
	short sRadarState = ERS_NOT_IN_SOLID;

	while( 0 <= sRadarPenetrationCount )
	{
		if( sRadarState == ERS_NOT_IN_SOLID )
		{	// check trace to the player
//			tr.vStart = vCurrentPos;
//			vGoal  =  &pPlayer->GetWorldPosition();
			tr.in_solid = false;
			tr.fFraction = 1.0f;
			this->m_pStage->ClipTrace( tr );

			vCurrentPos = tr.vEnd;

			if( tr.fFraction < 1.0f )	// hit something
			{
				if( tr.pTouchedEntity == pPlayer )
					return true;	// player is in a visible position
				else
				{	// hit static geometry or another entity
					sRadarState = ERS_IN_SOLID;
					vCurrentPos += vDirToPlayer * 0.01f;	// put 'vCurrentPos' in solid region
					sRadarPenetrationCount--;
					continue;
				}
			}
			else // i.e. tr.fFraction == 1.0f
			{	// no hit - an exception. trace should at least hit the player
				return false;
			}
		}
		else // i.e. sRadarState == ERS_IN_SOLID
		{
			vCurrentPos += vDirToPlayer * CBE_ENEMY_RADAR_PENETRATION_CALC_STEP;
			tr.vEnd = vCurrentPos;
			tr.fFraction = 1.0f;
			tr.in_solid = false;
			m_pStage->CheckPosition( tr );

			if( tr.in_solid )
			{	// proceeding inside the material
				sRadarPenetrationCount--;
				continue;
			}
			else
			{	// penetrated through the material

				// move a little forward so that 'vCurrentPos' can safely get out of the wall
				vCurrentPos += vDirToPlayer * 0.05f;
				sRadarState = ERS_NOT_IN_SOLID;
				continue;
			}
		}
	}

	// player is not visible to this enemy entity
	return false;
}
Exemple #24
0
bool GravityGun::HandleInput( int input_code, int input_type, float fParam )
{
    Vector3 vOwnerMuzzlePos = m_MuzzleEndWorldPose.vPosition;

    switch( input_code )
    {
    case ACTION_ATK_FIRE:
        if( input_type == ITYPE_KEY_PRESSED )
        {
            m_aTriggerState[0] = 1;

            CCopyEntity *pTarget = m_Target.GetRawPtr();
            if( pTarget )
            {
                physics::CActor *pPhysicsActor = pTarget->GetPrimaryPhysicsActor();
                Vector3 vDist = vOwnerMuzzlePos - pTarget->GetWorldPosition();

                float fDistSq = Vec3LengthSq(vDist);
                if( fDistSq < m_fGraspRange * m_fGraspRange )
                {
                    Vector3 vImpulse = m_MuzzleEndLocalPose.matOrient.GetColumn(2) * m_fPower;

                    // shoot object
//					pTarget->ApplyWorldImpulse( vImpulse, m_pTarget->GetWorldPosition() );
                    pPhysicsActor->SetLinearVelocity( vImpulse );

                    // release object
//					m_pTarget->pPhysicsActor->SetAllowFreezing( true );
                    m_Target.Reset();
                    m_iHoldingTargetToggle = 0;
                    return true;
                }
            }
        }
        else if( input_type == ITYPE_KEY_RELEASED )
        {
            m_aTriggerState[0] = 0;
            return true;
        }
        break;

    case ACTION_ATK_RAISEWEAPON:
    case ACTION_ATK_UNLOCK_TRIGGER_SAFETY:
        if( input_type == ITYPE_KEY_PRESSED )
        {
            m_aTriggerState[1] = 1;

            // the owner pulled the second trigger
            m_iHoldingTargetToggle = ~m_iHoldingTargetToggle;

            CCopyEntity *pTarget = m_Target.GetRawPtr();
            if( !pTarget )
            {
                // trigger is pulled and the gravity gun is not holding any object right now
                // - check if there is an object in the aim direction
                return GraspObjectInAimDirection();
            }
            else
            {
                // trigger is pulled when the gun is holding an object
                // - release the object
                ReleaseObject();
                return true;
            }
        }
        else if( input_type == ITYPE_KEY_RELEASED )
        {
            m_aTriggerState[1] = 0;
            return true;
        }
        break;
    default:
        break;
    }

    return false;
}
Exemple #25
0
void GravityGun::Update( float dt )
{
    if( !IsWeaponSelected() )
        return;

//	Vector3 vOwnerMuzzlePos = rWeaponSystem.m_vMuzzlePosition + rWeaponSystem.m_vMuzzleDirection * 0.25f
//		                                                      + rWeaponSystem.m_vMuzzleDir_Up * 0.90f;

    Vector3 vOwnerMuzzlePos = m_MuzzleEndWorldPose.vPosition;

    CCopyEntity *pTarget = m_Target.GetRawPtr();
    if( pTarget )
    {
        // calc the translation from the center of the target to the muzzle position
        Vector3 vDist = vOwnerMuzzlePos - pTarget->GetWorldPosition();

        float fDistSq = Vec3LengthSq(vDist);
        if( m_fMaxRange * m_fMaxRange < fDistSq )
        {
            m_iHoldingTargetToggle = 0;
//			m_pTarget->pPhysicsActor->SetAllowFreezing( true );
            m_Target.Reset();
            return;
        }

        STrace tr;
        tr.bvType = BVTYPE_DOT;
        tr.vStart = vOwnerMuzzlePos;
        Vector3 vGoal = pTarget->GetWorldPosition();
        tr.vGoal = vGoal;
        tr.sTraceType = TRACETYPE_IGNORE_NOCLIP_ENTITIES;
        /*
        		CTrace tr;
        		tr.BVType    = BVTYPE_DOT;
        		tr.vStart    = &vOwnerMuzzlePos;
        		tr.vGoal     = &pTarget->GetWorldPosition();
        		tr.TypeFlags = CTrace::FLAG_IGNORE_NOCLIP_ENTITIES;//TRACETYPE_IGNORE_NOCLIP_ENTITIES;
        */
        // check trace
        CStageSharedPtr pStage = m_pStage.lock();
        if( pStage )
            pStage->ClipTrace( tr );

        if( tr.pTouchedEntity != pTarget )
        {
            // found an obstacle between the player and the target object
            // - unable to hold the target any more
            m_iHoldingTargetToggle = 0;
//			m_pTarget->pPhysicsActor->SetAllowFreezing( true );
            m_Target.Reset();
            return;
        }

        if( fDistSq < m_fGraspRange * m_fGraspRange || m_aTriggerState[1] == 1 )
        {
            // the gravity gun is holding the target object

            // account for the target object's size so that it does not bump into the shooter
            float fDist = sqrtf(fDistSq);
            Vector3 vDir = vDist / fDist;		// normalization
            fDist -= ( pTarget->fRadius + 0.2f );
            vDist = vDir * fDist;

            // calc relative velocity
            Vector3 vRVel = pTarget->Velocity() - m_vMuzzleEndVelocity;

            Vector3 vForce;
//			vForce = m_fPosGain * vDist - m_fSpeedGain * vRVel;
//			m_pTarget->ApplyWorldImpulse( vForce, m_pTarget->GetWorldPosition());


            if( 6.0f < fDist )
                vForce = vDir * 6.0f * 2.5f;
            else if( fDist < 0.6f )
                vForce = vDir * fDist * 8.0f;
            else
//				vForce = vDir * fDist * 2.5f;
                vForce = vDir * ( fDist * 2.0f + 3.0f );

            vForce += m_vMuzzleEndVelocity;

            physics::CActor *pPhysicsActor = pTarget->GetPrimaryPhysicsActor();
            if( pPhysicsActor )
                pPhysicsActor->SetLinearVelocity( vForce );

            /*			Vector3 vPos = m_pTarget->pPhysicsActor->GetPosition();
            			Vector3 vVel = m_pTarget->pPhysicsActor->GetVelocity();
            			SmoothCD( vPos, vPos + vDist, vVel, 0.25f, dt );

            			if( 12.0f * 12.0f < Vec3LengthSq(vVel) )
            			{
            				Vec3Normalize( vVel, vVel );
            				vVel *= 12.0f;
            			}
            			m_pTarget->pPhysicsActor->SetVelocity( vVel );
            */
            return;
        }
        else
        {
            // lost control of the target
            m_iHoldingTargetToggle = 0;

            ReleaseObject();

            return;
        }
    }
}