Exemplo n.º 1
0
    bool IntersectRayAABB(const Ray& r, const AABB& a, float* out_tmin, float3* out_pos, float3* out_nor)
    {
        const float3& p = r.pos;
        const float3& d = r.direction;
        float tmin = -FLT_MAX;
        float tmax = FLT_MAX;
        float3 minNorm, maxNorm;
        
        // check vs. all three 'slabs' of the aabb
        for(int i = 0; i < 3; ++i)
        {
            if(abs(d[i]) < Epsilon) 
            {   // ray is parallel to slab, no hit if origin not within slab
                if(p[i] < a.Min()[i] || p[i] > a.Max()[i] )
                {
                    return false;
                }
            }
            else
            {
                // compute intersection t values of ray with near and far plane of slab
                float ood = 1.0f / d[i];
                float t1 = (a.Min()[i] - p[i]) * ood;
                float t2 = (a.Max()[i] - p[i]) * ood;
                tmin = maximize(tmin, minimize(t1, t2));
                tmax = minimize(tmax, maximize(t1, t2));

                // exit with no collision as soon as slab intersection becomes empty
                if(tmin > tmax) 
                {
                    return false;
                }
            }
        }
        
        if(tmax < 0.f)
        {
            // entire bounding box is behind us
            return false;
        }
        else if(tmin < 0.f)
        {
            // we are inside the bounding box
            *out_tmin = 0.f;
            *out_pos = p;
            *out_nor = normalize(a.GetCenter() - (*out_pos)); // use 'sphere' type normal calculation to approximate.
            return true;
        }
        else
        {
            // ray intersects all 3 slabs. return point and normal of intersection
            *out_tmin = tmin;
            *out_pos = p + d * tmin;
            *out_nor = normalize(a.GetCenter() - (*out_pos)); // use 'sphere' type normal calculation to approximate.
            return true;
        }
    }
Exemplo n.º 2
0
//------------------------------------------------------------------------
void SKillEffect::Activate(EntityId targetId, EntityId ownerId, EntityId weaponId, const char *effect, const char *defaultEffect)
{
	CActor *pActor = (CActor *)gEnv->pGame->GetIGameFramework()->GetIActorSystem()->GetActor(targetId);

	if (pActor)
	{
		//Execute particle effect and kill the actor
		GameWarning("Explosion effect: %s (Actor)", effect);

		// TODO: make work in MP...
		IParticleEffect *pEffect = gEnv->p3DEngine->FindParticleEffect(effect);
		if (pEffect)
		{

			int effectId = 0;

			effectId = pActor->GetEntity()->LoadParticleEmitter(-1,pEffect);
			AABB box;
			pActor->GetEntity()->GetLocalBounds(box);
			Matrix34 tm = IParticleEffect::ParticleLoc(box.GetCenter());
			pActor->GetEntity()->SetSlotLocalTM(effectId, tm);
		}	

		HitInfo info(ownerId, targetId, weaponId, 1000.0f, 0.0f, 0, 0, 0);
	
		g_pGame->GetGameRules()->ServerHit(info);
	}
	else if(!pActor && targetId)
	{
		// TODO: make work in MP...

		//No actor, but we have an entity
		IEntity* pEntity = gEnv->pEntitySystem->GetEntity(targetId);
		if(pEntity)
		{
			//Execute particle effect and kill the actor
			GameWarning("Explosion effect: %s (Entity)", defaultEffect);

			IParticleEffect *pEffect = gEnv->p3DEngine->FindParticleEffect(defaultEffect);
			if (pEffect)
			{
				int effectId = 0;

				effectId = pEntity->LoadParticleEmitter(-1,pEffect);
				AABB box;
				pEntity->GetLocalBounds(box);
				Matrix34 tm = IParticleEffect::ParticleLoc(box.GetCenter());
				pEntity->SetSlotLocalTM(effectId, tm);
			}	
		}

	}
}
Exemplo n.º 3
0
bool AABBInHalfSpace(const AABB & box, const float * plane)
{
	/*
		Main Idea: 
            -> Separating-axis test with only normal of the plane.
	*/

	float radius = box.GetExtent(0) * abs(plane[0])
				+ box.GetExtent(1) * abs(plane[1])
				+ box.GetExtent(2) * abs(plane[2]);
	float signed_distance = box.GetCenter()[0] * plane[0]
							+ box.GetCenter()[1] * plane[1]
							+ box.GetCenter()[2] * plane[2] 
							+ plane[3];
	return signed_distance + radius >= 0; //Only test if box is in positive side of plane.
}
void CTacticalManager::Ping(const ETacticalEntityType type, const float fPingDistance)
{
	const Vec3& clientPos = CHUDUtils::GetClientPos();
	AABB entityBox;

	const float pingDistanceSq = fPingDistance*fPingDistance;

	TInterestPoints& points = GetTacticalPoints(type);

	TInterestPoints::iterator pointsIt = points.begin();
	TInterestPoints::iterator pointsItEnd = points.end();

	for(; pointsIt!=pointsItEnd; ++pointsIt)
	{
		STacticalInterestPoint &entry = (*pointsIt);

		IEntity* pEntity = gEnv->pEntitySystem->GetEntity(entry.m_entityId);
		if (!pEntity)
			continue;

		if(pEntity->IsHidden())
			continue;

		pEntity->GetWorldBounds(entityBox);

		if(clientPos.GetSquaredDistance(entityBox.GetCenter()) > pingDistanceSq) // Outside ping range
			continue;

		if (entry.m_pinged != true)
		{
			entry.m_pinged = true;
		}
	}
}
Exemplo n.º 5
0
    //-----------------------------------------------------------------------------
    // AABB vs Frustum test.     
    //
    // Return values: 0 = no intersection, 
    //                1 = intersection, 
    //                2 = box is completely inside frustum    
    //
    //-----------------------------------------------------------------------------
    int FrustumAABBIntersect(const Frustum& frustum, const AABB& box)
    {
        float3 c  = box.GetCenter();
        float3 r  = box.Max() - c;
        bool intersects = false;        
        for(int i = 0; i < 6; ++i)
        {
            const Plane& plane = frustum[i];
            // test plane and AABB intersection.
            float e =  r.x * abs(plane.normal.x) 
                + r.y * abs(plane.normal.y) 
                + r.z * abs(plane.normal.z);
            float s = plane.Eval(c);

           // assert(e > 0);
            // the box is in positive half-space.
            if((s - e) > 0) continue;
            
            // if box is completely in negative side of the plain 
            // then the box is outside frustum.
            if( (s + e) < 0) return 0; // no intersection, early exit.            
            intersects = true;             
        }    
        if(intersects) return 1;
        return 2; // either intersects or completely inside frustum      
    }
Exemplo n.º 6
0
	bool Enemy::SeekBehavior() {
		auto PlayerPtr = GetStage()->GetSharedGameObject<Player>(L"Player");
		auto PlayerPos = PlayerPtr->GetComponent<Transform>()->GetPosition();
		auto MyPos = GetComponent<Transform>()->GetPosition();

		auto MapPtr = m_CelMap.lock();
		if (MapPtr) {
			if (SearchPlayer()) {
				auto PtrSeek = GetBehavior<SeekSteering>();
				if (m_NextCellIndex == 0) {
					auto PtrRigid = GetComponent<Rigidbody>();
					auto Velo = PtrRigid->GetVelocity();
					Velo *= 0.95f;
					PtrRigid->SetVelocity(Velo);
					PlayerPos.y = m_StartPosition.y;
					PtrSeek->Execute(PlayerPos);
				}
				else {
					if (length(MyPos - PlayerPos) <= 3.0f){
						auto PtrRigid = GetComponent<Rigidbody>();
						auto Velo = PtrRigid->GetVelocity();
						Velo *= 0.95f;
						PtrRigid->SetVelocity(Velo);
					}
					AABB ret;
					MapPtr->FindAABB(m_CellPath[m_NextCellIndex], ret);
					auto Pos = ret.GetCenter();
					Pos.y = m_StartPosition.y;
					PtrSeek->Execute(Pos);
				}
				return true;
			}
			else {
				auto PtrSeek = GetBehavior<SeekSteering>();
				CellIndex PlayerCell;
				if (MapPtr->FindCell(PlayerPos, PlayerCell)) {
					AABB ret;
					MapPtr->FindAABB(PlayerCell, ret);
					auto Pos = ret.GetCenter();
					Pos.y = m_StartPosition.y;
					PtrSeek->Execute(Pos);
					return true;
				}
			}
		}
		return false;
	}
bool BasicPrimitiveTests::IntersectingRayAgainstAABB(const Ray & ray, const AABB & aabb)
{
	
	const Eigen::Vector3f & ray_d_aabb = ray.GetDirection();
	Eigen::Vector3f ray_o_aabb = ray.GetOrigin() - aabb.GetCenter();
	
	return 0;
}
bool BasicPrimitiveTests::IntersectingRayAgainstAABB(const Ray & ray, const AABB & aabb, float & rtn_t)
{
	/*
		Main Idea:
            -> Uses slab representation for box.
            -> Finds intersection of ray/segment with each slab. Then compares intersection times for overlap in all slabs.
                -> Keep track of:
                    -> A: The farthest of all entries into a slab
                    -> B: The closest of all exits out of a slab.
                -> If A > B at anytime, exit with no intersection. 

        Intersecting slabs:
            -> Intersect slabs by inserting ray equation into plane equations for slab.
            -> Solve for t

        -> Must handle case when ray parallel to slab separately.
            -> To avoid division by zero.

        Can test for intersection without calculating intersection point:
            -> Choose coordinate system where box is axis aligned and centered at origin:
                AABB:
                    -> Translate segment and AABB to origin.
                OBB:
                    -> Transform Segment to OBB space, then translate both segment and OBB to origin.

            -> Do separating axis test with 6 axes:
                -> Three principle axes.
                -> Three cross products of box face normals and segment direction vector.
	*/
	
	rtn_t = 0.0f;
	float tmax = FLT_MAX;
	Eigen::Vector3f aabb_min = aabb.GetCenter() - aabb.GetExtents();
	Eigen::Vector3f aabb_max = aabb.GetCenter() + aabb.GetExtents();
	for (int i = 0; i < 3; ++i)
	{
		if (abs(ray.GetDirection()[i]) < EPSILON)
		{
			//Ray is parallel to slab. Not hit if origin not within slab.
			if (ray.GetOrigin()[i] < aabb_min[i] || ray.GetOrigin()[i] > aabb_max[i])
			{
				return false;
			}
		}
		else
		{
			float one_over_direction = 1.0f / ray.GetDirection()[i];
			float t1 = (aabb_min[i] - ray.GetOrigin()[i]) * one_over_direction;
			float t2 = (aabb_max[i] - ray.GetOrigin()[i]) * one_over_direction;
			if (t1 > t2) Swap(t1, t2);
			if (t1 > rtn_t) rtn_t = t1;
			if (t2 > tmax) tmax = t2;
			if (rtn_t > tmax) return false;
		}
	}
	
	return true;
}
int BasicPrimitiveTests::IntersectingSegmentAgainstAABB(const LineSegment & segment, const AABB & aabb)
{
	
	Eigen::Vector3f segment_a_aabb = segment.GetPointA() - aabb.GetCenter();
	Eigen::Vector3f segment_b_aabb = segment.GetPointB() - aabb.GetCenter();
	Eigen::Vector3f segment_m_aabb = (segment_a_aabb + segment_b_aabb) * 0.5f;
	
	return 0;
}
const Vec3&	CTacticalManager::GetTacticalIconCenterBBoxWorldPos(IEntity* pTacticalEntity)
{
	CRY_ASSERT(pTacticalEntity != NULL);

	AABB box;
	pTacticalEntity->GetWorldBounds(box);
	m_tempVec3 = box.GetCenter();

	return m_tempVec3;
}
int BasicPrimitiveTests::IntersectingSegmentAgainstAABB(const LineSegment & segment, const AABB & aabb, float & rtn_t1, float & rtn_t2)
{
	
	rtn_t1 = 0.0f;
	rtn_t2 = FLT_MAX;
	Eigen::Vector3f aabb_min = aabb.GetCenter() - aabb.GetExtents();
	Eigen::Vector3f aabb_max = aabb.GetCenter() + aabb.GetExtents();
	Eigen::Vector3f segment_direction = segment.GetPointB() - segment.GetPointA();
	for (int i = 0; i < 3; ++i)
	{
		if (abs(segment_direction[i]) < EPSILON)
		{
			//Ray is parallel to slab. Not hit if origin not within slab.
			if (segment.GetPointA()[i] < aabb_min[i] || segment.GetPointA()[i] > aabb_max[i])
			{
				return 0;
			}
		}
		else
		{
			float one_over_direction = 1.0f / segment_direction[i];
			float t1 = (aabb_min[i] - segment.GetPointA()[i]) * one_over_direction;
			float t2 = (aabb_max[i] - segment.GetPointA()[i]) * one_over_direction;
			if (t1 > 1.0f && t2 > 1.0f)
			{
				return 0;
			}
			if (t1 > t2) Swap(t1, t2);
			if (t1 > rtn_t1) rtn_t1 = t1;
			if (t2 > rtn_t2) rtn_t2 = t2;
			if (rtn_t1 > rtn_t2) return 0;
		}
	}
	if (rtn_t1 >= 0.0f && rtn_t1 <= 1.0f)
	{
		if (rtn_t2 >= 0.0f && rtn_t2 <= 1.0f)
		{
			return 2;
		}
		else
		{
			return 1;
		}
	}
	else
	{
		Swap(rtn_t1, rtn_t2);
		if (rtn_t1 >= 0.0f && rtn_t1 <= 1.0f)
		{
			return 1;
		}
		return 0;
	}
	
}
Exemplo n.º 12
0
 //-----------------------------------------------------------------------------
 // Plane vs AABB test.
 //
 // Return values: 
 //              0 = (Front) There is no intersection, and the box is in 
 //                   the positive half-space of the Plane. 
 //                  
 //              1 = (Back) There is no intersection, and the box is in 
 //                  the negative half-space of the Plane.
 //              2 = (Intersecting) the box intersects the plane.
 //-----------------------------------------------------------------------------
 int PlaneAABBIntersection(const Plane& plane, const AABB& box)
 {
     float3 c  = box.GetCenter();
     float3 r  = box.Max() - c;
     float e = r.x * abs(plane.normal.x) 
             + r.y * abs(plane.normal.y) 
             + r.z * abs(plane.normal.z);
     float s = plane.Eval(c);
     if((s - e) > 0)  return 0; // front side
     if((s + e) < 0)  return 1; // back side
     return 2; // Intersecting
 }
Exemplo n.º 13
0
void CAICorpseManager::RemoveSomeCorpses()
{
	const uint32 corspeCount = (uint32)m_corpsesArray.size();
	assert(corspeCount > AI_CORPSES_MINIMUM);

	const uint32 maxCorpsesToRemove = MIN((corspeCount / AI_CORPSES_MINIMUM), 8);
	assert(maxCorpsesToRemove > 0);

	std::vector<SCorpseRemovalScore> corpseScoresInfo;
	corpseScoresInfo.reserve( corspeCount );

	const CCamera& viewCamera = gEnv->pSystem->GetViewCamera();
	const Vec3 cameraPosition = viewCamera.GetPosition();

	const float farAway = (g_pGameCVars->g_aiCorpses_ForceDeleteDistance * 0.85f);
	const float kUpCloseThreshold = (15.0f * 15.0f);   //Gives non-removal priority to corpses near the player
	const float kFarAwayThreshold = max((farAway * farAway), kUpCloseThreshold * 2.0f); //Gives removal priority to corpses far away from the player

	for(uint32 i = 0; i < corspeCount; ++i)
	{
		CorpseInfo& corpseInfo = m_corpsesArray[i];
		SCorpseRemovalScore removalScore(corpseInfo.corpseId);
		
		CAICorpse* pCorpse = corpseInfo.GetCorpse();
		if(pCorpse != NULL)
		{
			AABB corpseBounds;
			pCorpse->GetEntity()->GetWorldBounds(corpseBounds);
			corpseBounds.Expand( Vec3(0.1f, 0.1f, 0.1f) );
			
			const float distanceSqr = (cameraPosition - corpseBounds.GetCenter()).len2();
			removalScore.distance = distanceSqr;
			removalScore.upClose = (distanceSqr < kUpCloseThreshold);
			removalScore.farAway = (distanceSqr > kFarAwayThreshold);
			removalScore.visible = viewCamera.IsAABBVisible_F(corpseBounds);
			removalScore.priority = pCorpse->GetPriority();
		}

		corpseScoresInfo.push_back(removalScore);
	}

	std::sort(corpseScoresInfo.begin(), corpseScoresInfo.end());

	assert(maxCorpsesToRemove < corpseScoresInfo.size());

	const uint32 corpseScoresCount = corpseScoresInfo.size();
	for(uint32 i = 0; i < maxCorpsesToRemove; ++i)
	{
		RemoveCorpse(corpseScoresInfo[i].corpseId);
	}
}
Exemplo n.º 14
0
void OBB::Create(const AABB& aabb, const Matrix4x4& mat)
{
	// Note: must be coherent with Rotate()

	aabb.GetCenter(mCenter);
	aabb.GetExtents(mExtents);
	// Here we have the same as OBB::Rotate(mat) where the obb is (mCenter, mExtents, Identity).

	// So following what's done in Rotate:
	// - x-form the center
	mCenter *= mat;
	// - combine rotation with identity, i.e. just use given matrix
	mRot = mat;
}
Exemplo n.º 15
0
bool CPersistantDebug::GetEntityParams(EntityId entityId, Vec3& baseCenterPos, float& height)
{
    IEntity *ent = gEnv->pEntitySystem->GetEntity(entityId);
    if (ent)
    {
        AABB bounds;
        ent->GetWorldBounds(bounds);
        baseCenterPos = bounds.GetCenter();
        baseCenterPos.z = bounds.min.z;
        height = bounds.GetSize().z;
        return true;
    }

    return false;
}
Exemplo n.º 16
0
	bool CPhysBody::Create(AABB boundingbox, Vec3 position, bool dynamic)
	{
		NxActorDesc actorDesc;
		NxBodyDesc bodyDesc;

		NxBoxShapeDesc boxDesc;
		//set size
		//boxDesc.dimensions.set(boundingbox.GetExtent(0), boundingbox.GetExtent(1), boundingbox.GetExtent(2));
		boxDesc.dimensions.set((boundingbox.max.x - boundingbox.min.x)/2, (boundingbox.max.y - boundingbox.min.y)/2, (boundingbox.max.z - boundingbox.min.z)/2);
		//set local position within the body
		boxDesc.localPose.t = NxVec3(boundingbox.GetCenter(0), boundingbox.GetCenter(1), boundingbox.GetCenter(2));
		//boxDesc.localPose.t = NxVec3(0.0f, 0.0f, 0.0f);
		actorDesc.shapes.pushBack(&boxDesc);

		if(dynamic) actorDesc.body = &bodyDesc;
		else actorDesc.body = 0;

		//set actor's global position
		actorDesc.globalPose.t = NxVec3(position.x, position.y, position.z);
		actorDesc.density = 10;
		m_pActor = g_pPhysScene->createActor(actorDesc);
		m_pActor->userData = new sNxActorUserData;
		return true;
	}
Exemplo n.º 17
0
    //-----------------------------------------------------------------------------
    // AABB vs frustum test.
    //
    // Return values: false = no intersection, 
    //                true  = either the box intersections or it is fully containt.
    // note: this test is fast but not 100% accurate (it is good for viewfrustum culling)          
    //-----------------------------------------------------------------------------
    bool TestFrustumAABB(const Frustum& frustum, const AABB& box)
	{              
        float3 c  = box.GetCenter();
        float3 r  = box.Max() - c;        
        for(int i = 0; i < 6; ++i)
        {
            const Plane& plane = frustum[i];
            // test plane and AABB intersection.
            float e =  r.x * abs(plane.normal.x) 
                + r.y * abs(plane.normal.y) 
                + r.z * abs(plane.normal.z);
            float s = plane.Eval(c);
            
            // if box is completely in negative side of the plain 
            // then the box is outside frustum.
            if( (s + e) < 0)  return false; // no intersection, early exit.               
        }            
        return true; // either intersects or completely inside frustum         
    }
Exemplo n.º 18
0
	Vec3 GetTargetPos( SActivationInfo* pActInfo )
	{
		EntityId targetId = GetPortEntityId(pActInfo, IN_TARGETID);

		Vec3 targetPos(0,0,0);

		if (targetId)
		{
			IEntity* pTarget = gEnv->pEntitySystem->GetEntity(targetId);
			if (pTarget)
			{
				AABB box;
				pTarget->GetWorldBounds(box);
				targetPos = box.GetCenter();
			}        
		}
		else
		{
			targetPos = GetPortVec3(pActInfo, IN_TARGETPOS);		
		}
		return targetPos;
	}
Exemplo n.º 19
0
	void Update(float elapsed)
	{
		float maxTime = GetPortFloat(&m_actInfo, EIP_Duration);
		float percent = maxTime > FLT_EPSILON ? elapsed / maxTime : 1.0f;
		if(percent >= 1.0f)
		{
			m_actInfo.pGraph->SetRegularlyUpdated(m_actInfo.myID, false);
			m_triggered = false;
			return;
		}

		Vec3 N = GetPortVec3(&m_actInfo, EIP_Normal);

		float rangeMin = GetPortFloat(&m_actInfo, EIP_RangeMin);
		float rangeMax = GetPortFloat(&m_actInfo, EIP_RangeMax);
		const float range = rangeMax - rangeMin;
		Vec3 boxDim(rangeMax, rangeMax, rangeMax);
		Vec3 ptmin = m_effectCenter - boxDim;
		Vec3 ptmax = m_effectCenter + boxDim;

		float speed = GetPortFloat(&m_actInfo, EIP_Speed);
		float waveFront = elapsed * speed;

		float decay = GetPortFloat(&m_actInfo, EIP_Decay);
		if(decay > FLT_EPSILON) decay = 1.0f / decay;

		float force = GetPortFloat(&m_actInfo, EIP_Force);
		force = pow_tpl(force * (1-percent), decay);

		float amplitude = GetPortFloat(&m_actInfo, EIP_Amplitude);
		amplitude = pow_tpl(amplitude * (1-percent), decay);

		if (gEnv->bMultiplayer) // Turned off for performance and network issues
		{
			return;
		}

		IPhysicalEntity** pEntityList = NULL;
		static const int iObjTypes = ent_rigid | ent_sleeping_rigid | ent_living;// | ent_allocate_list;
		int numEntities = gEnv->pPhysicalWorld->GetEntitiesInBox(ptmin, ptmax, pEntityList, iObjTypes);
		AABB bounds;
		for(int i=0; i<numEntities; ++i)
		{
			IPhysicalEntity* pPhysicalEntity = pEntityList[i];
			IEntity* pEntity = static_cast<IEntity*>(pPhysicalEntity->GetForeignData(PHYS_FOREIGN_ID_ENTITY));

			// Has the entity already been affected?
			if(pEntity)
			{
				bool affected = stl::find(m_entitiesAffected, pEntity->GetId());
				if(!affected)
				{
					IEntityPhysicalProxy* pPhysicalProxy = static_cast<IEntityPhysicalProxy*>(pEntity->GetProxy(ENTITY_PROXY_PHYSICS));
					if(pPhysicalProxy)
					{
						pPhysicalProxy->GetWorldBounds(bounds);
						Vec3 p = bounds.GetCenter();
						Vec3 v = p - m_effectCenter;
						float distFromCenter = v.GetLength() + FLT_EPSILON;
						if(distFromCenter < rangeMax)
						{
							if(waveFront > distFromCenter) // has the wavefront passed the entity?
							{
								//pPhysicalEntity->GetStatus(&dyn);

								// normalize v, cheaper than another sqrt
								v /= distFromCenter;

								Vec3 dir = N + v * force;
								static bool usePos = false;
								float impulse = 1.0f - (max(0.0f, distFromCenter - rangeMin) / range);
								impulse = impulse * amplitude;// / dyn.mass;
								if(impulse > FLT_EPSILON)
								{
									pPhysicalProxy->AddImpulse(-1, p, dir * impulse, usePos, 1.0f);
									m_entitiesAffected.push_back(pEntity->GetId());
								}
							}
						}
					}
				}
			}
		}
	}
Exemplo n.º 20
0
void KDTree::BuildTreeHelper(KDNode& CurrentNode, uint32_t Depth, uint32_t MinObjectsPerNode)
{
	if (Depth == 0 || CurrentNode.ObjectList.size() <= MinObjectsPerNode)
		return;

	const uint32_t& DividingAxis = CurrentNode.Axis;
	auto& CurrentObjects = CurrentNode.ObjectList;
	
	const size_t PrimitiveListSize = CurrentNode.ObjectList.size();
	const size_t DividingObjectIndex = PrimitiveListSize / 2;

	// sort all objects by splitting axis
	std::partial_sort(CurrentObjects.begin(), CurrentObjects.begin() + DividingObjectIndex, CurrentObjects.end(), [DividingAxis](const std::unique_ptr<IDrawable>& lhs, const std::unique_ptr<IDrawable>& rhs) -> bool
	{
		return lhs->GetWorldAABB().GetCenter()[DividingAxis] < rhs->GetWorldAABB().GetCenter()[DividingAxis];
	});

	auto& DividingObject = CurrentObjects[DividingObjectIndex];

	AABB DividingAABB = DividingObject->GetWorldAABB();
	
	// offset the dividing axis value to just after the median objects AABB
	const float DividingAxisValue = DividingAABB.GetCenter()[DividingAxis] + DividingAABB.GetDeminsions()[DividingAxis] + 0.1f;
	CurrentNode.SplitValue = DividingAxisValue;

	std::vector<std::unique_ptr<IDrawable>> StraddlingPrimitives;
	CurrentNode.Child[0] = std::unique_ptr<KDNode>(new KDNode());
	CurrentNode.Child[1] = std::unique_ptr<KDNode>(new KDNode());

	// check for objects straddling the dividing axis, if so, add them to array
	for (int i = DividingObjectIndex; i >= 0; i--)
	{
		const AABB& CurrentBBox = CurrentObjects[i]->GetWorldAABB();
		const float AxisRange = CurrentBBox.GetDeminsions()[DividingAxis];
		const float DividedRange = std::abs(CurrentBBox.Min[DividingAxis] - DividingAxisValue);
		if (AxisRange > DividedRange)
			StraddlingPrimitives.push_back(std::move(CurrentObjects[i]));
		else
		{
			// add non straddling to near child
			CurrentNode.Child[0]->ObjectList.push_back(std::move(CurrentObjects[i]));
		}
	}

	for (size_t i = DividingObjectIndex + 1; i < PrimitiveListSize; i++)
	{
		const AABB& CurrentBBox = CurrentObjects[i]->GetWorldAABB();
		float AxisRange = CurrentBBox.GetDeminsions()[DividingAxis];
		float DividedRange = CurrentBBox.Max[DividingAxis] - DividingAxisValue;
		if (AxisRange > DividedRange)
			StraddlingPrimitives.push_back(std::move(CurrentObjects[i]));
		else
		{
			// add non straddling to far child
			CurrentNode.Child[1]->ObjectList.push_back(std::move(CurrentObjects[i]));
		}
	}

	CurrentNode.Child[0]->ObjectList.shrink_to_fit();
	CurrentNode.Child[1]->ObjectList.shrink_to_fit();

	// increment axis for children
	CurrentNode.Child[0]->Axis = CurrentNode.Child[1]->Axis = (DividingAxis + 1) % 3;

	// add all straddling objects to this node
	CurrentNode.ObjectList.clear();
	CurrentNode.ObjectList = std::move(StraddlingPrimitives);

	BuildTreeHelper(*CurrentNode.Child[0], Depth - 1, MinObjectsPerNode);
	BuildTreeHelper(*CurrentNode.Child[1], Depth - 1, MinObjectsPerNode);
}
Exemplo n.º 21
0
void CClaymore::Update(SEntityUpdateContext &ctx, int updateSlot)
{
	CProjectile::Update(ctx, updateSlot);

	bool debug = (g_pGameCVars->g_debugMines != 0);

	if(gEnv->bServer)
	{
		if(m_armed)
		{
			CGameRules* pGR = g_pGame->GetGameRules();
			if(pGR)
			{
				for(std::list<EntityId>::iterator it = m_targetList.begin(); it != m_targetList.end(); ++it)
				{
					IEntity* pEntity = gEnv->pEntitySystem->GetEntity(*it);
					if(!pEntity) continue;
						
					// if this is a team game, claymores aren't set off by their own team...
					if(pGR->GetTeamCount() > 0 && (m_teamId != 0 && pGR->GetTeam(pEntity->GetId()) == m_teamId))
						continue;

					// otherwise, not set off by the player who dropped them.
					if(pGR->GetTeamCount() == 0 && m_ownerId == pEntity->GetId())
						continue;
					
					IPhysicalEntity *pPhysics = pEntity->GetPhysics();
					if(pPhysics)
					{
						pe_status_dynamics physStatus;
						if(0 != pPhysics->GetStatus(&physStatus) && physStatus.v.GetLengthSquared() > 0.01f)
						{
							// now check angle between this claymore and approaching object
							//	to see if it is within the angular range m_triggerAngle.
							//	If it is, then check distance is less than m_triggerRange,
							//	and also check line-of-sight between the two entities.
							IRenderAuxGeom * pRAG = gEnv->pRenderer->GetIRenderAuxGeom();
							pRAG->SetRenderFlags( e_Mode3D | e_AlphaBlended | e_DrawInFrontOff | e_FillModeSolid | e_CullModeNone );

							AABB entityBBox;	
							pEntity->GetWorldBounds(entityBBox);

							if(debug)
							{
								pRAG->DrawAABB( entityBBox, true, ColorF(1,0,0,0.4f), eBBD_Faceted );
							}

							Vec3 enemyDir = entityBBox.GetCenter() - GetEntity()->GetPos();
							Vec3 checkDir = enemyDir; 
							checkDir.z = 0;
							float distanceSq = enemyDir.GetLengthSquared();

							// for players a simple distance check is fine, but for vehicles use a better intersection check
							//	so any corner of the vehicle going inside the zone sets off the claymore.
							static float playerRadius = 2.5f;
							bool inside = false;
							if(entityBBox.GetRadius() < playerRadius)
							{
								inside = (distanceSq < (m_triggerRadius * m_triggerRadius));
							}
							else
							{							
								static ray_hit hit;
								if(gEnv->pPhysicalWorld->CollideEntityWithBeam(pEntity->GetPhysics(), GetEntity()->GetWorldPos(), enemyDir, m_triggerRadius, &hit))
								{
									inside = true;
									enemyDir = hit.pt - GetEntity()->GetWorldPos();
								}
							}

							if(inside)
							{
								enemyDir.NormalizeSafe();
								checkDir.NormalizeSafe();
								float dotProd = checkDir.Dot(m_triggerDirection);

								if(debug)
								{
									pRAG->DrawLine(GetEntity()->GetPos(), ColorF(1,0,0,1), GetEntity()->GetPos() + Matrix33::CreateRotationZ(m_triggerAngle/2.0f)*m_triggerDirection*m_triggerRadius, ColorF(1,0,0,1), 5.0f);
									pRAG->DrawLine(GetEntity()->GetPos(), ColorF(1,0,0,1), GetEntity()->GetPos() + Matrix33::CreateRotationZ(-m_triggerAngle/2.0f)*m_triggerDirection*m_triggerRadius, ColorF(1,0,0,1), 5.0f);

									ColorF clr;
									clr.a = 0.3f;
									clr.b = 0.4f;
									clr.g = 0.1f;
									clr.r = 1.0f;
									pRAG->DrawLine(GetEntity()->GetPos(), clr, GetEntity()->GetPos() + (enemyDir * m_triggerRadius), clr, 5.0f);
								}

								if(dotProd > cry_cosf(m_triggerAngle/2.0f))
								{
									static const int objTypes = ent_all&(~ent_terrain);   
									static const unsigned int flags = rwi_stop_at_pierceable|rwi_colltype_any;
									ray_hit hit;
									int col = gEnv->pPhysicalWorld->RayWorldIntersection(GetEntity()->GetPos(), (enemyDir * m_triggerRadius * 1.5f), objTypes, flags, &hit, 1, GetEntity()->GetPhysics());

									bool bang = false;
									if (!col)
										bang = true;
									else if (entityBBox.IsContainPoint(hit.pt))
										bang = true;
									else if (hit.pt.GetSquaredDistance(GetEntity()->GetWorldPos()) >= distanceSq)
										bang = true;
									if (bang)
									{
										// pass in the explosion normal, which is -m_triggerDirection
										Explode(true, false, Vec3(0,0,0), -m_triggerDirection);

										if(debug)
										{
											ColorF clr;
											clr.a = 0.3f;
											clr.g = 0.1f;
											clr.r = 1.0f;
											clr.b = 1.0f;
											pRAG->DrawLine(GetEntity()->GetPos(), clr, GetEntity()->GetPos() + (enemyDir * m_triggerRadius), clr, 5.0f);
										}
									}
								}
							}
						}
					}
				}
			}
		}
		else
		{
			m_timeToArm -= gEnv->pTimer->GetFrameTime();
			if(m_timeToArm <= 0.0f)
			{
				m_armed = true;

				IEntityTriggerProxy *pTriggerProxy = (IEntityTriggerProxy*)(GetEntity()->GetProxy(ENTITY_PROXY_TRIGGER));

				if (!pTriggerProxy)
				{
					GetEntity()->CreateProxy(ENTITY_PROXY_TRIGGER);
					pTriggerProxy = (IEntityTriggerProxy*)GetEntity()->GetProxy(ENTITY_PROXY_TRIGGER);
				}

				if(pTriggerProxy)
				{
					// create a trigger volume a couple of metres bigger than we need, to ensure we catch vehicles.
					//	Checks above will still make sure the entity is within the radius before detonating though.
					float radius = m_triggerRadius + 2.0f;
					AABB boundingBox = AABB(Vec3(-radius,-radius,-radius), Vec3(radius,radius,radius));
					pTriggerProxy->SetTriggerBounds(boundingBox);
				}
			}
		}
	}

	if(debug && m_armed)
	{
		IRenderAuxGeom * pRAG = gEnv->pRenderer->GetIRenderAuxGeom();
		ColorF clr;
		clr.a = 0.3f;
		clr.b = 0.4f;
		clr.g = 0.1f;
		clr.r = 1.0f;
		pRAG->SetRenderFlags( e_Mode3D | e_AlphaBlended | e_DrawInFrontOff | e_FillModeSolid | e_CullModeNone );
		pRAG->DrawCylinder(GetEntity()->GetPos(), Vec3(0, 0, 1), m_triggerRadius, m_triggerRadius * 2.0f, clr);
		Vec3 size(m_triggerRadius + 2.0f, m_triggerRadius + 2.0f, m_triggerRadius + 2.0f);
		AABB box(GetEntity()->GetPos() - size, GetEntity()->GetPos() + size);
		pRAG->DrawAABB(box, false, ColorF(0.1f, 0.1f, 0.1f, 0.1f), eBBD_Faceted);
		pRAG->DrawLine(GetEntity()->GetPos(), clr, GetEntity()->GetPos() + m_triggerDirection, clr, 5.0f);
	}
}
Exemplo n.º 22
0
void CSpammer::UpdatePotentialTargets()
{
	const float minLockOnDistance = m_fireParams->spammerParams.minLockOnDistance;
	const float maxLockOnDistance = m_fireParams->spammerParams.maxLockOnDistance;
	const float maxAngleCos = cry_cosf(DEG2RAD(m_fireParams->spammerParams.targetingTolerance));

	const CAutoAimManager& autoAimManager = g_pGame->GetAutoAimManager();
	const TAutoaimTargets& aaTargets = autoAimManager.GetAutoAimTargets();
	const int targetCount = aaTargets.size();

	const Vec3 probableHit = Vec3Constants<float>::fVec3_Zero;
	const Vec3 weaponPos = GetWeaponPosition(probableHit);
	const Vec3 weaponFwd = GetWeaponDirection(weaponPos, probableHit);

	m_potentialTargets.Clear();

	CPlayerVisTable::SVisibilityParams queryTargetParams(0);
	const bool flat2DMode = m_fireParams->spammerParams.targetingFlatMode;

	for (int i = 0; i < targetCount; ++i)
	{
		const SAutoaimTarget& target = aaTargets[i];
		CRY_ASSERT(target.entityId != m_pWeapon->GetOwnerId());

		if (!target.HasFlagSet(eAATF_AIHostile))
			continue;

		IEntity* pTargetEntity = gEnv->pEntitySystem->GetEntity(target.entityId);
		if (!pTargetEntity)
			continue;
		CActor* pActor = target.pActorWeak.lock().get();

		AABB bounds;
		pTargetEntity->GetWorldBounds(bounds);
		Vec3 targetPos = bounds.GetCenter();
		Vec3 targetDistVec = (targetPos - weaponPos).normalized();
		float distance = targetPos.GetDistance(weaponPos);

		if (distance <= minLockOnDistance || distance >= maxLockOnDistance)
			continue;

		float alignment;
		if (!flat2DMode)
		{
			alignment = weaponFwd * targetDistVec;
		}
		else
		{
			const CCamera& viewCamera = gEnv->pSystem->GetViewCamera();
			if (!viewCamera.IsPointVisible(targetPos))
				continue;

			alignment = Vec3(weaponFwd.x, weaponFwd.y, 0.0f).GetNormalizedSafe() * Vec3(targetDistVec.x, targetDistVec.y, 0.0f).GetNormalizedSafe();
		}

		if (alignment <= maxAngleCos)
			continue;

		const SpammerTarget finalTargetInfo = GetVisibilityTestTarget(pTargetEntity, target.entityId, pActor, bounds);

		const int kAutoaimVisibilityLatency = 0;
		queryTargetParams.targetEntityId = finalTargetInfo.targetId;
		if (!g_pGame->GetPlayerVisTable()->CanLocalPlayerSee(queryTargetParams, kAutoaimVisibilityLatency))
			continue;

		float priority = 1.0f;
		priority *= finalTargetInfo.radius;
		priority /= m_targetsAssigned.GetNumLockOns(target.entityId)+1;
		const float m = 1.0f / (1.0f - maxAngleCos);
		priority *= m * alignment + (1.0f - m);
		priority *= 0.1f;
		priority = min(priority, 1.0f);

		m_potentialTargets.AddTarget(target.entityId, priority);
	}

	float n = 0.0f;
	size_t num = m_potentialTargets.m_potentialTargets.size();
	for (size_t i = 0; i < num; ++i)
	{
		n = max(n, m_potentialTargets.m_potentialTargets[i].m_probability);
	}
	m_potentialTargets.m_totalProbability = 0.0f;
	for (size_t i = 0; num && i < m_potentialTargets.m_potentialTargets.size(); ++i)
	{
		m_potentialTargets.m_potentialTargets[i].m_probability /= n + FLT_EPSILON;
		m_potentialTargets.m_totalProbability += m_potentialTargets.m_potentialTargets[i].m_probability;
	}
}
Exemplo n.º 23
0
//----------------------------------------------------------------------------------------------------------------------------------
///  Init  dynamics
//----------------------------------------------------------------------------------------------------------------------------------
void CARDYNAMICS::Init(
	class SETTINGS* pSet1, class Scene* pScene1, class FluidsXml* pFluids1,
	COLLISION_WORLD & world,
	const MODEL & chassisModel, const MODEL & wheelModelFront, const MODEL & wheelModelRear,
	const MATHVECTOR<Dbl,3> & position, const QUATERNION<Dbl> & orientation)
{
	pSet = pSet1;  pScene = pScene1;  pFluids = pFluids1;
	this->world = &world;

	MATHVECTOR<Dbl,3> zero(0, 0, 0);
	body.SetPosition(position);
	body.SetOrientation(orientation);
	body.SetInitialForce(zero);
	body.SetInitialTorque(zero);

	// init engine
	engine.SetInitialConditions();


	// init chassis
	btTransform tr;
	tr.setIdentity();

	AABB <float> box = chassisModel.GetAABB();
	for (int i = 0; i < 4; i++)
	{
		MATHVECTOR<float,3> wheelpos = GetLocalWheelPosition(WHEEL_POSITION(i), 0);

		const MODEL * wheelmodel = &wheelModelFront;
		if (i > 1) wheelmodel = &wheelModelRear;

		AABB <float> wheelaabb;
		float sidefactor = 1.0;
		if (i == 1 || i == 3) sidefactor = -1.0;

		wheelaabb.SetFromCorners(
			wheelpos - wheelmodel->GetAABB().GetSize() * 0.5 * sidefactor,
			wheelpos + wheelmodel->GetAABB().GetSize() * 0.5 * sidefactor);
		box.CombineWith(wheelaabb);
	}


	///  chassis shape  ---------------------------------------------------------
	const MATHVECTOR<Dbl,3> verticalMargin(0, 0, 0.3);
	btVector3 origin = ToBulletVector(box.GetCenter() + verticalMargin - center_of_mass);
	btVector3 size = ToBulletVector(box.GetSize() - verticalMargin);

	//btCompoundShape * chassisShape = new btCompoundShape(false);
	#if 0
		//btBoxShape * hull = new btBoxShape( btVector3(1.8,0.8,0.5) );
		btBoxShape * hull = new btBoxShape( btVector3(1.7,0.7,0.3) );
		tr.setOrigin(origin + btVector3(0,0,0.2));
		chassisShape->addChildShape(tr, hull);
	#else
		/// todo: all params in .car
		// y| length  x- width  z^ height
		btScalar w = size.getX()*0.2, r = size.getZ()*0.3, h = 0.45;

		///  spheres
		btScalar l0 = 0.f, w0 = 0.f, h0 = 0.f;
		if (coll_R > 0.f)  r = coll_R;  l0 = coll_Lofs;
		if (coll_W > 0.f)  w = coll_W;  w0 = coll_Wofs;
		if (coll_H > 0.f)  h = coll_H;	h0 = coll_Hofs;
		origin = btVector3(l0, w0, h0);

		btScalar r2 = r*0.6;
		btScalar l1 = coll_posLfront, l2 = coll_posLback, l1m = l1*0.5, l2m = l2*0.5;

		//LogO("Car shape dims:  r="+toStr(r)+"  w="+toStr(w)+"  h="+toStr(h)+"  h0="+toStr(h0));
		//LogO("Car offset:  x="+toStr(origin.x())+"  y="+toStr(origin.y())+"  z="+toStr(origin.z()));

		const int numSph = 14;  int i = 0;
		btScalar rad[numSph];  btVector3 pos[numSph];
		pos[i] = btVector3( l1 , -w,    -h);    	rad[i] = r2;  ++i;  // front
		pos[i] = btVector3( l1 ,  w,    -h);    	rad[i] = r2;  ++i;
		pos[i] = btVector3( l1m, -w,    -h);    	rad[i] = r;   ++i;  // front near
		pos[i] = btVector3( l1m,  w,    -h);    	rad[i] = r;   ++i;

		pos[i] = btVector3( l2m, -w,    -h);    	rad[i] = r;   ++i;  // rear near
		pos[i] = btVector3( l2m,  w,    -h);    	rad[i] = r;   ++i;
		pos[i] = btVector3( l2 , -w,    -h);    	rad[i] = r2;  ++i;  // rear
		pos[i] = btVector3( l2 ,  w,    -h);    	rad[i] = r2;  ++i;

		pos[i] = btVector3( 0.4, -w*0.8, h*0.2);	rad[i] = r2;  ++i;  // top
		pos[i] = btVector3( 0.4,  w*0.8, h*0.2);	rad[i] = r2;  ++i;
		pos[i] = btVector3(-0.3, -w*0.8, h*0.4);	rad[i] = r2;  ++i;
		pos[i] = btVector3(-0.3,  w*0.8, h*0.4);	rad[i] = r2;  ++i;
		pos[i] = btVector3(-1.1, -w*0.8, h*0.2);	rad[i] = r2;  ++i;  // top rear
		pos[i] = btVector3(-1.1,  w*0.8, h*0.2);	rad[i] = r2;  ++i;

		for (i=0; i < numSph; ++i)
			pos[i] += origin;
		btMultiSphereShape* chassisShape = new btMultiSphereShape(pos, rad, numSph);
		//chassisShape->setMargin(0.2f);
	#endif


	Dbl chassisMass = body.GetMass();// * 0.4;  // Magic multiplier makes collisions better - problem: mud is very different
	MATRIX3 <Dbl> inertia = body.GetInertia();
	btVector3 chassisInertia(inertia[0], inertia[4], inertia[8]);

	btTransform transform;
	transform.setOrigin(ToBulletVector(position));
	transform.setRotation(ToBulletQuaternion(orientation));
	btDefaultMotionState * chassisState = new btDefaultMotionState();
	chassisState->setWorldTransform(transform);

	btRigidBody::btRigidBodyConstructionInfo info(chassisMass, chassisState, chassisShape, chassisInertia);
	info.m_angularDamping = ang_damp;
	info.m_restitution = 0.0;  //...
	info.m_friction = coll_friction;  /// 0.4~ 0.7
	///  chasis^
	chassis = world.AddRigidBody(info, true, pSet->game.collis_cars);
	chassis->setActivationState(DISABLE_DEACTIVATION);
	chassis->setUserPointer(new ShapeData(ST_Car, this, 0));  ///~~
	
	world.AddAction(this);
	

	///  join chassis and wheel triggers
	//________________________________________________________
	{
		for (int w=0; w < 4; ++w)
		{
			WHEEL_POSITION wp = WHEEL_POSITION(w);
			Dbl whR = GetWheel(wp).GetRadius() * 1.2;  //bigger par..
			MATHVECTOR<float,3> wheelpos = GetWheelPosition(wp, 0);  //par
			wheelpos[0] += coll_Lofs;
			wheelpos[2] += coll_flTrig_H;

			btSphereShape* whSph = new btSphereShape(whR);
			//btCylinderShapeX* whSph = new btCylinderShapeX(btVector3(whR,whR,whR));//todo..
			whTrigs = new btRigidBody(0.001f, 0, whSph);
			
			whTrigs->setUserPointer(new ShapeData(ST_Wheel, this, 0, w));  ///~~
			whTrigs->setActivationState(DISABLE_DEACTIVATION);
			whTrigs->setCollisionFlags(whTrigs->getCollisionFlags() | btCollisionObject::CF_NO_CONTACT_RESPONSE);
			world.world->addRigidBody(whTrigs);
			world.shapes.push_back(whSph);
				
			//todo: collision mask only to fluid triggers
			//todo: optimize- 1 constr only or none?
			//todo: cylinders? fixed constr\_
			/*btTransform f1,f2;  f1.setIdentity();  f2.setIdentity();
			f1.setOrigin(ToBulletVector(wheelpos));
			btGeneric6DofConstraint* constr = new btGeneric6DofConstraint(*chassis, *whTrigs, f1, f2, true);
			constr->setLimit(0,0,0);  constr->setLimit(1,0,1);  constr->setLimit(2,0,0);
			//constr->setLimit(3,0,0);
			//constr->setLimit(4,0,0);
			constr->setLimit(5,0,0);/*??*/
			btTypedConstraint* constr = new btPoint2PointConstraint(*chassis, *whTrigs,
				ToBulletVector(wheelpos), btVector3(0,0,0));
			world.world->addConstraint(constr, true);
			world.constraints.push_back(constr);
		}

		///  init poly for buoyancy computations
		//________________________________________________________
		if (poly == NULL)
		{
			poly = new Polyhedron();
			poly->numVerts = 8;  poly->numFaces = 12;
			poly->verts = new Vec3[8];
			poly->faces = new Face[12];

			float hx = 1.2f, hy = 0.7f, hz = 0.4f;  // box dim
			poly->verts[0] = Vec3(-hx,-hy,-hz);	poly->verts[1] = Vec3(-hx,-hy, hz);
			poly->verts[2] = Vec3(-hx, hy,-hz);	poly->verts[3] = Vec3(-hx, hy, hz);
			poly->verts[4] = Vec3( hx,-hy,-hz);	poly->verts[5] = Vec3( hx,-hy, hz);
			poly->verts[6] = Vec3( hx, hy,-hz);	poly->verts[7] = Vec3( hx, hy, hz);

			poly->faces[0] = Face(0,1,3);	poly->faces[1] = Face(0,3,2);	poly->faces[2] = Face(6,3,7);	poly->faces[3] = Face(6,2,3);
			poly->faces[4] = Face(4,6,5);	poly->faces[5] = Face(6,7,5);	poly->faces[6] = Face(4,5,0);	poly->faces[7] = Face(0,5,1);
			poly->faces[8] = Face(5,7,1);	poly->faces[9] = Face(7,3,1);	poly->faces[10]= Face(0,6,4);	poly->faces[11]= Face(0,2,6);

			poly->length = 1.0f;  //  approx. length-?
			poly->volume = ComputeVolume(*poly);

			body_mass = 1900.0f * 2.688;  //poly->volume;  // car density
			body_inertia = (4.0f * body_mass / 12.0f) * btVector3(hy*hz, hx*hz, hx*hy);
		}
	}
	//-------------------------------------------------------------	


	// init wheels, suspension
	for (int i = 0; i < WHEEL_POSITION_SIZE; i++)
	{
		wheel[WHEEL_POSITION(i)].SetInitialConditions();
		wheel_velocity[i].Set(0.0);
		wheel_position[i] = GetWheelPositionAtDisplacement(WHEEL_POSITION(i), 0);
		wheel_orientation[i] = orientation * GetWheelSteeringAndSuspensionOrientation(WHEEL_POSITION(i));
	}

	AlignWithGround();//--
}
Exemplo n.º 24
0
void CVehicleDamageBehaviorBlowTire::DamagePlayers()
{
	// check for the nasty case when the player is shooting at the vehicle tires while prone 
	// under or behind the car, In that case the player should get killed by the vehicle, 
	// otherwise he gets stuck forever. Note that he should only get killed when the tier
	// is actually destroyed and not by collision resulting by the impulse added by just 
	// shooting at the tiers. Unfortunately using physics for doing this check is not reliable
	// enough so we have to check it explicitly
	
	IEntityPhysicalProxy *pPhysicsProxy = (IEntityPhysicalProxy*)m_pVehicle->GetEntity()->GetProxy(ENTITY_PROXY_PHYSICS);
	if (!pPhysicsProxy)
		return;

	AABB bbox;
	pPhysicsProxy->GetWorldBounds( bbox );

	IPhysicalWorld *pWorld = gEnv->pSystem->GetIPhysicalWorld();
	IPhysicalEntity **ppColliders;
	// check entities in collision with the car
	int cnt = pWorld->GetEntitiesInBox( bbox.min,bbox.max, ppColliders,ent_living);
	for (int i = 0; i < cnt; i++)
	{

		IEntity *pEntity = gEnv->pEntitySystem->GetEntityFromPhysics( ppColliders[i] );
		if (!pEntity)
			continue;
		
		// skip the vehicle itself
		if (pEntity==m_pVehicle->GetEntity())
			continue;

		IPhysicalEntity *pPhysEnt = pEntity->GetPhysics();
		if (!pPhysEnt) 
			continue;

		IActor* pActor = gEnv->pGame->GetIGameFramework()->GetIActorSystem()->GetActor(pEntity->GetId());            
		if(!pActor)
			continue;

		//Jan M.: the player is killed when he entered the vehicle while prone although he is still passenger!
		if(m_pVehicle == pActor->GetLinkedVehicle())
			continue;

		//the player must be prone under the vehicle
		IAnimatedCharacter * animatedCharacter=pActor->GetAnimatedCharacter();
		if (!animatedCharacter)
			continue;

		int stance = animatedCharacter->GetCurrentStance();
		if (stance!=STANCE_PRONE)
			continue;

		pe_player_dimensions dim;
		if (!pPhysEnt->GetParams(&dim))
			continue;
		// position returned is at entity's feet, add head position from physics
		Vec3 vPos1=pEntity->GetPos();
		vPos1.z = vPos1.z + dim.heightHead;

		float fZ=bbox.GetCenter().z;
		if (vPos1.z>fZ)
			continue; // not under the vehicle

		// at this point we have a collision with the car moving down and the guy prone under the car, it is safe
		// to assume he has been squished so let's kill him.
		if (gEnv->bServer && pActor->GetHealth()>0)
		{
			// adding a server hit to make it working in MP
			IGameRules *pGameRules = gEnv->pGame->GetIGameFramework()->GetIGameRulesSystem()->GetCurrentGameRules();
			if (pGameRules)
			{
				HitInfo hit;

				EntityId shooterId=m_pVehicle->GetEntityId();
				if (m_pVehicle->GetDriver())
					shooterId=m_pVehicle->GetDriver()->GetEntityId();					

				hit.targetId = pEntity->GetId();      
				hit.shooterId = shooterId;
				hit.weaponId = m_pVehicle->GetEntityId();
				hit.damage = 1000.f;
				hit.type = 0;
				hit.pos = pActor->GetEntity()->GetWorldPos();

				pGameRules->ServerHit(hit); 
			}  
		} 
	} //i
}
Exemplo n.º 25
0
//-----------------------------------------------------------------------
void gkAuxRenderer::AuxRenderAABB( const AABB& aabb, ColorF& color /*= ColorF(1.0,1.0,1.0,1.0)*/, bool ignoreZ )
{

	//Vec3 vecAABB = aabb.GetCenter();
	AuxRender3DBoxFrame( aabb.GetCenter(), aabb.GetSize(), color, ignoreZ );
}
Exemplo n.º 26
0
/// Used to update any time dependent state (such as timeouts)
void CFlowNode_FeatureTest::Update(float deltaTime)
{
	if(m_running)
	{
		m_timeRunning += deltaTime;
		CryWatch("$7[FG FeatureTest]$o Running test '%s'", Name());

		const string &description = GetPortString(&m_actInfo, eInputPorts_Description);

		if(!description.empty())
			CryWatch("$7[FG FeatureTest]$o %s", description.c_str());

		const float maxTime = GetPortFloat(&m_actInfo, eInputPorts_MaxTime);

		IEntity *pFollowEntity = NULL;

		// Firstly, attempt to get the camera entity (index: -1)
		bool bHasEntry = GetEntityAtIndex(-1, pFollowEntity);

		if(!bHasEntry && !pFollowEntity)
		{
			// If there's an entity being tested, force the view camera to follow it (if no camera entity defined)
			// This needs to be implemented in a cleaner way and allow other options for non-entity based tests.
			bHasEntry = GetEntityAtIndex(m_entitySeqIndex, pFollowEntity);

			// If no sequence entity defined
			if(!bHasEntry && !pFollowEntity)
			{
				// Look for another suitable (active) entity to follow
				for(int i = 0; i < SEQ_ENTITY_COUNT; ++i)
				{
					GetEntityAtIndex(i, pFollowEntity);

					if(pFollowEntity && pFollowEntity->IsActive())
					{
						break;
					}
				}
			}
		}

		if(pFollowEntity)
		{
			CCamera &viewCamera = gEnv->pSystem->GetViewCamera();

			Vec3 vPos(0,0,0);
			Vec3 vDir(0,0,0);

			AABB bounds;
			pFollowEntity->GetWorldBounds(bounds);

			Vec3 vTarget;
			vTarget = bounds.GetCenter();

			vPos = vTarget + (pFollowEntity->GetForwardDir().GetNormalizedSafe() * -2.5f) + Vec3(0.0f, 0.0f, 1.0f);
			vDir = (vTarget - vPos).GetNormalizedSafe();

			float	fRoll(0.0f);

			viewCamera.SetMatrix(CCamera::CreateOrientationYPR(CCamera::CreateAnglesYPR(vDir, fRoll)));
			viewCamera.SetPosition(vPos);
		}

		// If a valid max time has been set
		if(maxTime > 0.0f)
		{
			// If test has exceeded max time
			if(m_timeRunning >= maxTime)
			{
				OnTestResult(false, string().Format("Test failed: Test exceeded maximum time (%f).", maxTime).c_str());
			}
		}
	}
}
Exemplo n.º 27
0
void CGame::Draw()
{
	Vector vecForward = m_hPlayer->GetGlobalView();
	Vector vecUp(0, 1, 0);

	// Cross-product http://www.youtube.com/watch?v=FT7MShdqK6w
	Vector vecRight = vecUp.Cross(vecForward).Normalized();

	CRenderer* pRenderer = GetRenderer();

	// Tell the renderer how to set up the camera.
	pRenderer->SetCameraPosition(m_hPlayer->GetGlobalOrigin() - vecForward * 6 + vecUp * 3 - vecRight * 0.5f);
	pRenderer->SetCameraDirection(vecForward);
	pRenderer->SetCameraUp(Vector(0, 1, 0));
	pRenderer->SetCameraFOV(90);
	pRenderer->SetCameraNear(0.1f);
	pRenderer->SetCameraFar(1000);

	// This rendering context is a tool for rendering things to the screen.
	// All of our drawing commands are part of it.
	CRenderingContext r(pRenderer);

	// Clear the depth buffer and set a background color.
	r.ClearDepth();
	r.ClearColor(Color(210, 230, 255));

	// CRenderer::StartRendering() - This function sets up OpenGL with the
	// camera information that we passed it before.
	pRenderer->StartRendering(&r);

	m_oFrameFrustum = CFrustum(r.GetProjection() * r.GetView());

	// First tell OpenGL what "shader" or "program" to use.
	r.UseProgram("model");

	// Set the sunlight direction. The y component is -1 so the light is pointing down.
	Vector vecSunlight = Vector(1, -1, 1).Normalized();

	// Uncomment this code to make the sunlight rotate:
	//Vector vecSunlight = Vector(cos(Game()->GetTime()), -1, sin(Game()->GetTime())).Normalized();

	r.SetUniform("vecSunlight", vecSunlight);

	r.SetUniform("bLighted", false);
	r.SetUniform("bDiffuse", false);

	// Render the ground.
	r.SetUniform("vecColor", Vector4D(0.6f, 0.7f, 0.9f, 1));
	r.SetUniform("vecCameraPosition", GetRenderer()->GetCameraPosition());
	r.BeginRenderTriFan();
		r.Normal(Vector(0, 1, 0));
		r.Tangent(Vector(1, 0, 0));
		r.Bitangent(Vector(0, 0, 1));
		r.TexCoord(Vector2D(0, 1));
		r.Vertex(Vector(-30, 0, -30));
		r.TexCoord(Vector2D(0, 0));
		r.Vertex(Vector(-30, 0, 30));
		r.TexCoord(Vector2D(1, 0));
		r.Vertex(Vector(30, 0, 30));
		r.TexCoord(Vector2D(1, 1));
		r.Vertex(Vector(30, 0, -30));
	r.EndRender();

	r.SetUniform("bLighted", true);

	// Prepare a list of entities to render.
	m_apRenderOpaqueList.clear();
	m_apRenderTransparentList.clear();

	for (size_t i = 0; i < MAX_CHARACTERS; i++)
	{
		CCharacter* pCharacter = GetCharacterIndex(i);
		if (!pCharacter)
			continue;

		// We need to scale the AABB using the character's scale values before we can use it to calculate our center/radius.
		AABB aabbSizeWithScaling = pCharacter->m_aabbSize * pCharacter->m_vecScaling;
		Vector vecCharacterCenter = pCharacter->GetGlobalOrigin() + aabbSizeWithScaling.GetCenter();
		float flCharacterRadius = aabbSizeWithScaling.GetRadius();

		// If the entity is outside the viewing frustum then the player can't see it - don't draw it.
		// http://youtu.be/4p-E_31XOPM
		if (!m_oFrameFrustum.SphereIntersection(vecCharacterCenter, flCharacterRadius))
			continue;

		if (pCharacter->m_bDrawTransparent)
			m_apRenderTransparentList.push_back(pCharacter);
		else
			m_apRenderOpaqueList.push_back(pCharacter);
	}

	// Draw all opaque characters first.
	DrawCharacters(m_apRenderOpaqueList, false);

	for (size_t i = 0; i < MAX_CHARACTERS; i++)
	{
		CCharacter* pCharacter = GetCharacterIndex(i);
		if (!pCharacter)
			continue;

		if (!pCharacter->m_bEnemyAI)
			continue;

		float flRadius = 3.5f;

		Vector vecIndicatorOrigin = NearestPointOnSphere(m_hPlayer->GetGlobalOrigin(), flRadius, pCharacter->GetGlobalOrigin());

		float flBoxSize = 0.1f;

		r.SetUniform("vecColor", Color(255, 0, 0, 255));
		r.RenderBox(vecIndicatorOrigin - Vector(1, 1, 1)*flBoxSize, vecIndicatorOrigin + Vector(1, 1, 1)*flBoxSize);
	}

	// Sort the transparent render list so that we paint the items farther from the camera first. http://youtu.be/fEjZrwDKdi8
	MergeSortTransparentRenderList();

	// Now draw all transparent characters, sorted by distance from the camera.
	DrawCharacters(m_apRenderTransparentList, true);

	r.SetUniform("bDiffuse", false);

	// Render any bullet tracers that may have been created.
	float flBulletTracerTime = 0.1f;
	for (size_t i = 0; i < Game()->GetTracers().size(); i++)
	{
		if (Game()->GetTime() < Game()->GetTracers()[i].flTimeCreated + flBulletTracerTime)
		{
			Vector vecStart = Game()->GetTracers()[i].vecStart;
			Vector vecEnd = Game()->GetTracers()[i].vecEnd;

			r.SetUniform("vecColor", Vector4D(1, 0.9f, 0, 1));
			r.BeginRenderLines();
				r.Normal(Vector(0, 1, 0));
				r.Vertex(vecStart);
				r.Vertex(vecEnd);
			r.EndRender();
		}
	}

	// Render any puffs that may have been created.
	float flPuffTime = 0.3f;
	for (size_t i = 0; i < Game()->GetPuffs().size(); i++)
	{
		if (Game()->GetTime() < Game()->GetPuffs()[i].flTimeCreated + flPuffTime)
		{
			float flTimeCreated = Game()->GetPuffs()[i].flTimeCreated;
			float flTimeOver = Game()->GetPuffs()[i].flTimeCreated + flPuffTime;
			float flStartSize = 0.2f;
			float flEndSize = 2.0f;

			float flSize = Remap(Game()->GetTime(), flTimeCreated, flTimeOver, flStartSize, flEndSize);

			Vector vecOrigin = Game()->GetPuffs()[i].vecOrigin;

			int iOrange = (int)Remap(Game()->GetTime(), flTimeCreated, flTimeOver, 0, 255);
			r.SetUniform("vecColor", Color(255, iOrange, 0, 255));
			r.RenderBox(vecOrigin - Vector(1, 1, 1)*flSize, vecOrigin + Vector(1, 1, 1)*flSize);
		}
	}

	GraphDraw();

	pRenderer->FinishRendering(&r);

	// Call this last. Your rendered stuff won't appear on the screen until you call this.
	Application()->SwapBuffers();
}
Exemplo n.º 28
0
void CAutoAimManager::UpdateTargetInfo(SAutoaimTarget& aaTarget, float fFrameTime)
{
	IEntity * pTargetEntity = gEnv->pEntitySystem->GetEntity(aaTarget.entityId);
	if(pTargetEntity)
	{
		CActorPtr pTargetActor = aaTarget.pActorWeak.lock();
		if (pTargetActor)
		{
			Vec3 characterPos;
			Quat characterRot;

			//Need this because of decouple catch-up movement 
			if (IAnimatedCharacter* pAnimatedCharacter = pTargetActor->GetAnimatedCharacter())
			{
				const QuatT& animationLocation = pAnimatedCharacter->GetAnimLocation();
				characterPos = animationLocation.t;
				characterRot = animationLocation.q;
			}
			else
			{
				const Matrix34& targetWorldTM = pTargetEntity->GetWorldTM();

				//Fallback to entity position
				characterPos = targetWorldTM.GetTranslation();
				characterRot = Quat(targetWorldTM);
			}

			Vec3 primaryOffset(0.0f, 0.0f, aaTarget.fallbackOffset);
			Vec3 secondaryOffset(0.0f, 0.0f, aaTarget.fallbackOffset);

			if (aaTarget.primaryBoneId >= 0)
			{
				if (pTargetActor->HasBoneID(aaTarget.primaryBoneId))
				{
					primaryOffset = pTargetActor->GetBoneTransform(aaTarget.primaryBoneId).t;
				}
				else
				{		
					GameWarning("CAutoAimManager: Character %s missing primary boneID: %s", pTargetEntity->GetName(), s_BONE_ID_NAME[aaTarget.primaryBoneId]);
					aaTarget.primaryBoneId = -1;
				}
			}
			if (aaTarget.secondaryBoneId >= 0)
			{
				if (pTargetActor->HasBoneID(aaTarget.secondaryBoneId))
				{
					secondaryOffset = pTargetActor->GetBoneTransform(aaTarget.secondaryBoneId).t;
				}
				else
				{		
					GameWarning("CAutoAimManager: Character %s missing secondary boneID: %s", pTargetEntity->GetName(), s_BONE_ID_NAME[aaTarget.secondaryBoneId]);
					aaTarget.secondaryBoneId = -1;
				}
			}

			aaTarget.primaryAimPosition = characterPos + (characterRot * primaryOffset);
			aaTarget.secondaryAimPosition = characterPos + (characterRot * secondaryOffset);

			//Update hostility (changes during gameplay)
			if (!gEnv->bMultiplayer)
			{
				uint8 targetFaction = (aaTarget.aiFaction != IFactionMap::InvalidFactionID) ? aaTarget.aiFaction : GetTargetFaction(*pTargetEntity);

				if (gEnv->pAISystem->GetFactionMap().GetReaction(GetLocalPlayerFaction(), aaTarget.aiFaction) == IFactionMap::Hostile)
				{
					aaTarget.SetFlag(eAATF_AIHostile);
				}
				else
				{
					aaTarget.RemoveFlag(eAATF_AIHostile);
				}

				aaTarget.aiFaction = targetFaction;
			}
		}
		else if(aaTarget.hasSkeleton)
		{
			//Not an actor but has a skeleton (and so can use bone offsets)
			ISkeletonPose* pSkeletonPose = pTargetEntity->GetCharacter(0)->GetISkeletonPose();

			const Matrix34& characterMat = pTargetEntity->GetWorldTM();
			const Vec3 characterPos = characterMat.GetTranslation();
			const Quat characterRot(characterMat);

			Vec3 primaryOffset(0.0f, 0.0f, aaTarget.fallbackOffset);
			Vec3 secondaryOffset(0.0f, 0.0f, aaTarget.fallbackOffset);

			if (aaTarget.primaryBoneId >= 0)
			{
				primaryOffset = pSkeletonPose->GetAbsJointByID(aaTarget.primaryBoneId).t;
			}
			if (aaTarget.secondaryBoneId >= 0)
			{
				secondaryOffset = pSkeletonPose->GetAbsJointByID(aaTarget.secondaryBoneId).t;
			}

			aaTarget.primaryAimPosition = characterPos + (characterRot * primaryOffset);
			aaTarget.secondaryAimPosition = characterPos + (characterRot * secondaryOffset);
		}
		else
		{
			//Must be an object
			const Matrix34& entityWorldTM = pTargetEntity->GetWorldTM(); 
			Vec3 primaryPosition = entityWorldTM.GetTranslation();
			Vec3 secondaryPosition = entityWorldTM.TransformPoint(Vec3(0.0f, 0.0f, 0.5f));

			AABB entityLocalBBox;
			pTargetEntity->GetLocalBounds(entityLocalBBox);
			if (!entityLocalBBox.IsEmpty())
			{
				const Vec3 offset (0.0f, 0.0f, entityLocalBBox.GetRadius() * 0.2f);
				const Vec3 objectCenter = entityLocalBBox.GetCenter();
				primaryPosition = entityWorldTM.TransformPoint((objectCenter - offset));
				secondaryPosition = entityWorldTM.TransformPoint((objectCenter + offset));
			}

			aaTarget.primaryAimPosition = primaryPosition;
			aaTarget.secondaryAimPosition = secondaryPosition;
		}

		//The physics drags the render proxy and entity behind it. If we auto aim at the render position,
		//	we will handicap the console players by failing to let them aim ahead of the target.
		if(IPhysicalEntity * pPhysicalEntity = pTargetEntity->GetPhysics())
		{
			pe_status_dynamics dyn;
			if(pPhysicalEntity->GetStatus(&dyn))
			{
				Vec3 lookAhead = (dyn.v * fFrameTime);
				aaTarget.primaryAimPosition = aaTarget.primaryAimPosition + lookAhead;
				aaTarget.secondaryAimPosition = aaTarget.secondaryAimPosition + lookAhead;
			}
		}
	}
}
Exemplo n.º 29
0
bool CDialogActorContext::DoLocalPlayerChecks(const float dt)
{
	// don't check this every frame, but only every .2 secs
	m_checkPlayerTimeOut-=dt;
	if (m_checkPlayerTimeOut <= 0.0f)
	{
		do // a dummy loop to use break
		{
			float awareDistance;
			float awareDistanceSq;
			float awareAngle;
			m_pSession->GetPlayerAwarenessValues(awareDistance, awareAngle);
			awareDistanceSq=awareDistance*awareDistance;

			m_checkPlayerTimeOut = PLAYER_CHECKTIME;
			const float spotAngleCos = cos_tpl(DEG2RAD(awareAngle));
	
			const CDialogSession::TActorContextMap& contextMap = m_pSession->GetAllContexts();
			if (contextMap.size() == 1 && contextMap.begin()->first == m_actorID)
			{
				m_bIsAware = true;
				break;
			}
	
			// early out, when we don't have to do any checks
			if (awareDistance <= 0.0f && awareAngle <= 0.0f)
			{
				m_bIsAware = true;
				break;
			}

			IEntity* pThisEntity = m_pSession->GetActorEntity(m_actorID);
			if (!pThisEntity)
			{
				assert (false);
				m_bIsAware = true;
				break;
			}
			IMovementController* pMC = (m_pIActor != NULL) ? m_pIActor->GetMovementController() : NULL;
			if (!pMC)
			{
				assert (false);
				m_bIsAware = true;
				break;
			}
			SMovementState moveState;
			pMC->GetMovementState(moveState);
			Vec3 viewPos = moveState.eyePosition;
			Vec3 viewDir = moveState.eyeDirection;
			viewDir.z = 0.0f;
			viewDir.NormalizeSafe();
	
			// check the player's position
			// check the player's view direction
			AABB groupBounds;
			groupBounds.Reset();

			CDialogSession::TActorContextMap::const_iterator iter = contextMap.begin();
			CDialogScript::SActorSet lookingAt = 0;
			while (iter != contextMap.end())
			{
				if (iter->first != m_actorID)
				{
					IEntity* pActorEntity = m_pSession->GetActorEntity(iter->first);
					if (pActorEntity)
					{
						Vec3 vEntityPos = pActorEntity->GetWorldPos();
						AABB worldBounds;
						pActorEntity->GetWorldBounds(worldBounds);
						groupBounds.Add(worldBounds);
						// calc if we look at it somehow
						Vec3 vEntityDir = vEntityPos - viewPos;
						vEntityDir.z = 0.0f;
						vEntityDir.NormalizeSafe();
						if (viewDir.IsUnit() && vEntityDir.IsUnit())
						{
							const float dot = clamp_tpl(viewDir.Dot(vEntityDir),-1.0f,+1.0f); // clamping should not be needed
							if (spotAngleCos <= dot)
								lookingAt.SetActor(iter->first);
							DiaLOG::Log(DiaLOG::eDebugC, "Angle to actor %d is %f deg", iter->first, RAD2DEG(acos_tpl(dot)));
						}
					}
				}
				++iter;
			}

			const float distanceSq = pThisEntity->GetWorldPos().GetSquaredDistance(groupBounds.GetCenter());
			CCamera& camera=gEnv->pSystem->GetViewCamera();
			const bool bIsInAABB  = camera.IsAABBVisible_F(groupBounds);
			const bool bIsInRange = distanceSq <= awareDistanceSq;
			const bool bIsLooking = contextMap.empty() || lookingAt.NumActors() > 0;
			m_bIsAwareLooking = awareAngle <= 0.0f || (bIsInAABB || bIsLooking);
			m_bIsAwareInRange = awareDistance <= 0.0f || bIsInRange;
			m_bIsAware = m_bIsAwareLooking && m_bIsAwareInRange;

			DiaLOG::Log(DiaLOG::eDebugB, "[DIALOG] LPC: %s awDist=%f awAng=%f AABBVis=%d IsLooking=%d InRange=%d [Distance=%f LookingActors=%d] Final=%saware", 
				m_pSession->GetDebugName(), awareDistance, awareAngle, bIsInAABB, bIsLooking, bIsInRange, sqrt_tpl(distanceSq), lookingAt.NumActors(), m_bIsAware ? "" : "not ");
		
		} while (false);
	}

	if (m_bIsAware)
	{
		m_playerAwareTimeOut = m_pSession->GetPlayerAwarenessGraceTime();
	}
	else
	{
		m_playerAwareTimeOut-= dt;
		if (m_playerAwareTimeOut <= 0)
		{
			return false;
		}
	}

	return true;
}
Exemplo n.º 30
0
	void ShadowSystem::ProcessEntity(ECS::Entity* p_entity)
	{
		Transform* transform = m_transforms.Get(p_entity);
		Shadowcaster* shadowcaster = m_shadowcasters.Get(p_entity);

		Render::Shadowcaster sc;
		
		Orientation tOr = transform->m_orientation;
		tOr.Yaw(180.0f);
		glm::mat4 tempWorldMatrix;
		tempWorldMatrix = glm::translate(glm::mat4(1.0f), transform->m_position);
		tempWorldMatrix = glm::rotate(tempWorldMatrix, tOr.GetAngle(), tOr.GetAxis());
		tempWorldMatrix = glm::scale(tempWorldMatrix, transform->m_scale);

		glm::mat4 lightSpace = glm::inverse(tempWorldMatrix);

		m_maxWorldX = -99999;
		m_minWorldX = 99999;
		m_maxWorldY = -99999;
		m_minWorldY = 99999;
		m_maxWorldZ = -99999;
		m_minWorldZ = 99999;
		for(int i = 0; i < 8; i++)
		{
			glm::vec4 cornerInLightSpace = lightSpace * glm::vec4(worldCorners[i], 1.0f);
			if(cornerInLightSpace.x < m_minWorldX)
			{
				m_minWorldX = cornerInLightSpace.x;
			}
			if(cornerInLightSpace.x > m_maxWorldX)
			{
				m_maxWorldX = cornerInLightSpace.x;
			}
			if(cornerInLightSpace.y < m_minWorldY)
			{
				m_minWorldY = cornerInLightSpace.y;
			}
			if(cornerInLightSpace.y > m_maxWorldY)
			{
				m_maxWorldY = cornerInLightSpace.y;
			}
			if(cornerInLightSpace.z < m_minWorldZ)
			{
				m_minWorldZ = cornerInLightSpace.z;
			}
			if(cornerInLightSpace.z > m_maxWorldZ)
			{
				m_maxWorldZ = cornerInLightSpace.z;
			}
		}

		glm::mat4 lazyOrthoAroundMap = glm::ortho(m_minWorldX, m_maxWorldX, m_minWorldY, m_maxWorldY, -m_maxWorldZ, -m_minWorldZ);

		// Get the eye camera.
		ECS::Entity* cameraEntity = m_world->GetTagManager()->GetEntityByTag("Camera");
		RootForce::Camera* camera = m_world->GetEntityManager()->GetComponent<RootForce::Camera>(cameraEntity);

		Frustum frustum = camera->m_frustum;

		glm::vec4 frustumCorners[8];
		frustumCorners[0] = glm::vec4(frustum.ntl, 1.0f);
		frustumCorners[1] = glm::vec4(frustum.ntr, 1.0f);
		frustumCorners[2] = glm::vec4(frustum.nbl, 1.0f);
		frustumCorners[3] = glm::vec4(frustum.nbr, 1.0f);
		frustumCorners[4] = glm::vec4(frustum.ftl, 1.0f);
		frustumCorners[5] = glm::vec4(frustum.ftr, 1.0f);
		frustumCorners[6] = glm::vec4(frustum.fbl, 1.0f);
		frustumCorners[7] = glm::vec4(frustum.fbr, 1.0f);
		
		// Convert camera frustrum to view space.
		for(int i = 0; i < 8; i++)
		{
			frustumCorners[i] = camera->m_viewMatrix * frustumCorners[i];
		}

		// Calculate directions.
		glm::vec3 directions[4];
		for(int i = 0; i < 4; i++)
		{
			directions[i].x = glm::normalize(frustumCorners[i+4].x - frustumCorners[i].x);
			directions[i].y = glm::normalize(frustumCorners[i+4].y - frustumCorners[i].y);
			directions[i].z = glm::normalize(frustumCorners[i+4].z - frustumCorners[i].z);
		}

		static glm::vec4 localOBB[8] = 
		{
			glm::vec4(-1.0f, -1.0f, -1.0f, 1.0f),
			glm::vec4(1.0f, -1.0f, -1.0f, 1.0f),
			glm::vec4(1.0f, 1.0f, -1.0f, 1.0f),
			glm::vec4(1.0f, 1.0f, 1.0f, 1.0f),
			glm::vec4(-1.0f, 1.0f, -1.0f, 1.0f),
			glm::vec4(-1.0f, 1.0f, 1.0f, 1.0f),
			glm::vec4(-1.0f, -1.0f, 1.0f, 1.0f),
			glm::vec4(1.0f, -1.0f, 1.0f, 1.0f)
		};

		if(RENDER_SHADOW_CASCADES >= 4)
		{
			// Define near/far planes for the sub frustrums.
			float _near[4];
			_near[0] = camera->m_frustum.m_near;
			_near[1] = 8.0f; //Daniel's 2k-values: 15, 60, 200
			_near[2] = 40.0f;
			_near[3] = 150.0f;

			float _far[4];
			_far[0] = _near[1];
			_far[1] = _near[2];
			_far[2] = _near[3];
			_far[3] = camera->m_frustum.m_far;

			// Create cascades.
			for(int i = 0; i < RENDER_SHADOW_CASCADES; i++)
			{
				AABB boundingbox;
				for(int p = 0; p < 4; p++)
				{
					glm::vec3 nearCorner;
					nearCorner = glm::swizzle<glm::X, glm::Y, glm::Z>(frustumCorners[p]);
					boundingbox.Expand(nearCorner + directions[p] * _near[i]);
					boundingbox.Expand(nearCorner + directions[p] * _far[i]);
				}

				glm::vec3 center = boundingbox.GetCenter();
				glm::vec3 centerInWorldSpace = glm::swizzle<glm::X, glm::Y, glm::Z>(glm::inverse(camera->m_viewMatrix) * glm::vec4(center, 1.0f)); 
				glm::vec4 centerInViewSpace = lightSpace * glm::vec4(centerInWorldSpace, 1.0f);

				float nearPlane = 1.0f;
				float lookAtDistance = glm::length(centerInViewSpace - 2000.0f) + nearPlane;
				float radius = glm::length(center - glm::vec3(boundingbox.m_maxX, boundingbox.m_maxY, boundingbox.m_maxZ)); 
				float farPlane = lookAtDistance + radius;

				sc.m_projectionMatrices[i] = glm::ortho(-radius, radius, -radius, radius, nearPlane, farPlane);
				sc.m_viewMatrices[i] = glm::lookAt(centerInWorldSpace + tOr.GetFront() * lookAtDistance, centerInWorldSpace - tOr.GetFront() * lookAtDistance, tOr.GetUp());
				sc.m_viewProjections[i] = sc.m_projectionMatrices[i] * sc.m_viewMatrices[i];
			}

			sc.m_projectionMatrices[RENDER_SHADOW_CASCADES-1] = OrthoProjectionFromFrustum(&camera->m_frustum, lightSpace);
			sc.m_viewMatrices[RENDER_SHADOW_CASCADES-1] = lightSpace;
			sc.m_viewProjections[RENDER_SHADOW_CASCADES-1] = sc.m_projectionMatrices[RENDER_SHADOW_CASCADES-1] * sc.m_viewMatrices[RENDER_SHADOW_CASCADES-1];
		}
		else
		{
			sc.m_projectionMatrices[RENDER_SHADOW_CASCADES-1] = lazyOrthoAroundMap;
			sc.m_viewMatrices[RENDER_SHADOW_CASCADES-1] = lightSpace;
			sc.m_viewProjections[RENDER_SHADOW_CASCADES-1] = sc.m_projectionMatrices[RENDER_SHADOW_CASCADES-1] * sc.m_viewMatrices[RENDER_SHADOW_CASCADES-1];
		}
		g_engineContext.m_renderer->AddShadowcaster(sc, (int)shadowcaster->m_directionalLightSlot);
	}