Beispiel #1
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);
	}
}
Beispiel #2
0
  virtual void GetDimension(BaseObject* op, Vector* mp, Vector* rad) override
  {
    // Find the Minimum/Maximum of the object's bounding
    // box by all hidden child-objects in its hierarchy.
    AABB bbox;
    for (NodeIterator<BaseObject> it(op->GetDown(), op); it; ++it)
    {
      // We skip objects that are being controlled by
      // a generator object.
      if (it->GetInfo() & OBJECT_GENERATOR && !IsControlledByGenerator(*it))
        bbox.Expand(*it, it->GetMg(), false);
    }

    *mp = bbox.GetMidpoint();
    *rad = bbox.GetSize();
  }
	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);
	}
Beispiel #4
0
// This function inserts the given child node into the bounding volume
// hierarchy and adjusts all the associated costs that are stored in
// the tree.
void node::AddChild( node *new_child )
    {
    double old_AIC;
    double increment;
    AABB new_volume( new_child->bbox );

    if( child == NULL ) 
        {
        // The current node is a leaf, so we must convert it into
        // an internal node.  To do this, copy its current contents into
        // a new node, which will become a child of this one.
        child         = new node;
        child->bbox   = bbox;
        child->object = object;
        child->parent = this;
 
        // Fill in all the fields of the current node, which has just changed
        // into an internal node with a single child.
        EC   = 1;
        SA   = child->SA;
        SEC_ = child->EC;  // There is only one child.
        SAIC = child->AIC; // There is only one child.
        AIC  = SA * SEC_ + SAIC;
        }

    // Splice the new child into the linked list of children.
    new_child->sibling = child;
    new_child->parent  = this;
    child = new_child;
    
    // Update the summed external cost and the summed AIC as a result
    // of adding the new child node.  These do not depend on surface
    // area, so we needn't consider any expansion of the bounding volume.
    SEC_ += new_child->EC;
    SAIC += new_child->AIC;

    // Now take bounding volume expansion into account due to the new child.
    bool expanded = false;
    if( bbox.Expand( new_volume ) )
        {
        expanded = true;
        SA = SurfaceArea( bbox );
        }

    // Compute new area cost & how much it increased due to new child.
    old_AIC = AIC;
    AIC = SA * SEC_ + SAIC;
    increment = AIC - old_AIC;

    // Propagate the information upward, in two phases.  The first phase
    // deals with volumes that get expanded.  Once a volume is reached that does
    // not expand, there will be no more expansion all the way to the root.
    node *n = this;
    while( expanded )
        {
        expanded = false;
        node *prev = n;
        n = n->parent;
        if( n != NULL && n->bbox.Expand( new_volume ) )
            {
            expanded  = true;
            old_AIC   = n->AIC;
            n->SA     = SurfaceArea( n->bbox );
            n->SAIC  += increment;
            n->AIC    = n->SA * n->SEC_ + n->SAIC;
            increment = n->AIC - old_AIC;
            }
        }

    // From this point up to the root there will be no more expansion.
    // However, we must still propagate information upward.
    while( n != NULL )
        {
        n->SAIC += increment;
        n->AIC  += increment;
        n = n->parent;
        }
    }
Beispiel #5
0
void CAICorpseManager::Update( const float frameTime )
{
	const uint32 maxCorpsesToUpdateThisFrame = 4;

	const float cullPhysicsDistanceSqr = g_pGameCVars->g_aiCorpses_CullPhysicsDistance * g_pGameCVars->g_aiCorpses_CullPhysicsDistance;
	const float forceDeleteDistanceSqr = g_pGameCVars->g_aiCorpses_ForceDeleteDistance * g_pGameCVars->g_aiCorpses_ForceDeleteDistance;

	if (m_lastUpdatedCorpseIdx >= (uint32)m_corpsesArray.size())
		m_lastUpdatedCorpseIdx = 0;

	const CCamera& viewCamera = gEnv->pSystem->GetViewCamera();

	CryFixedArray<EntityId, maxCorpsesToUpdateThisFrame> corpsesToDelete;
	const uint32 corpsesEndIdx = min(m_lastUpdatedCorpseIdx + maxCorpsesToUpdateThisFrame, (uint32)m_corpsesArray.size());

	for(uint32 i = m_lastUpdatedCorpseIdx; i < corpsesEndIdx; ++i)
	{
		CorpseInfo& corpseInfo = m_corpsesArray[i];

		IEntity* pCorpseEntity = corpseInfo.GetCorpseEntity();
		if(pCorpseEntity != NULL)
		{
			AABB corpseBbox;
			pCorpseEntity->GetWorldBounds(corpseBbox);
			corpseBbox.Expand(Vec3(0.1f, 0.1f, 0.1f));

			const Vec3 corpsePosition = corpseBbox.GetCenter();
			const float distanceSqr = (corpsePosition - viewCamera.GetPosition()).len2();

			const bool attemptDeleteFarAway = (distanceSqr > forceDeleteDistanceSqr);
			const bool cullPhysics = (distanceSqr > cullPhysicsDistanceSqr);
			const bool isVisible = viewCamera.IsAABBVisible_F(corpseBbox);
			
			corpseInfo.flags.SetFlags( CorpseInfo::eFlag_FarAway, attemptDeleteFarAway );
			
			if(attemptDeleteFarAway && !isVisible)
			{
				corpsesToDelete.push_back(corpseInfo.corpseId);
			}
			else if(cullPhysics != corpseInfo.flags.AreAllFlagsActive( CorpseInfo::eFlag_PhysicsDisabled ))
			{
				IEntityPhysicalProxy* pCorpsePhysicsProxy = static_cast<IEntityPhysicalProxy*>(pCorpseEntity->GetProxy( ENTITY_PROXY_PHYSICS ));
				if (pCorpsePhysicsProxy != NULL)
				{
					//Simulate entity event to enable/disable physics
					SEntityEvent visibilityEvent;
					visibilityEvent.event = cullPhysics ? ENTITY_EVENT_HIDE : ENTITY_EVENT_UNHIDE;
					pCorpsePhysicsProxy->ProcessEvent( visibilityEvent );
					
					if(cullPhysics == false)
					{
						IPhysicalEntity* pCorpsePhysics = pCorpseEntity->GetPhysics();
						if(pCorpsePhysics != NULL)
						{
							pe_action_awake awakeAction;
							awakeAction.bAwake = 0;
							pCorpsePhysics->Action( &awakeAction );
						}
					}
				}

				corpseInfo.flags.SetFlags( CorpseInfo::eFlag_PhysicsDisabled, cullPhysics );
			}
		}
		else
		{
			//This should not happen, but in case remove the entity from the list
			GameWarning("AICorpseManager - Detected corpse with no entity, removing from list");
			corpsesToDelete.push_back(corpseInfo.corpseId);
		}
	}

	m_lastUpdatedCorpseIdx = corpsesEndIdx;

	for(uint32 i = 0; i < (uint32)corpsesToDelete.size(); ++i)
	{
		RemoveCorpse(corpsesToDelete[i]);
	}

	DebugDraw();
}