You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
177 lines
5.7 KiB
C++
177 lines
5.7 KiB
C++
/*
|
|
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
|
* its licensors.
|
|
*
|
|
* For complete copyright and license terms please see the LICENSE at the root of this
|
|
* distribution (the "License"). All use of this software is governed by the License,
|
|
* or, if provided, by the license below or the license accompanying this file. Do not
|
|
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
*
|
|
*/
|
|
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
|
|
|
#include "Cry3DEngine_precompiled.h"
|
|
|
|
#include "ClipVolume.h"
|
|
#include "ClipVolumeManager.h"
|
|
#include "LightEntity.h"
|
|
#include "FogVolumeRenderNode.h"
|
|
#include "ObjMan.h"
|
|
|
|
CClipVolumeManager::~CClipVolumeManager()
|
|
{
|
|
assert(m_ClipVolumes.empty());
|
|
}
|
|
|
|
IClipVolume* CClipVolumeManager::CreateClipVolume()
|
|
{
|
|
SClipVolumeInfo volumeInfo(new CClipVolume());
|
|
m_ClipVolumes.push_back(volumeInfo);
|
|
|
|
return m_ClipVolumes.back().m_pVolume;
|
|
}
|
|
|
|
bool CClipVolumeManager::DeleteClipVolume(IClipVolume* pClipVolume)
|
|
{
|
|
if (m_ClipVolumes.Delete(static_cast<CClipVolume*>(pClipVolume)))
|
|
{
|
|
delete pClipVolume;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool CClipVolumeManager::UpdateClipVolume(IClipVolume* pClipVolume, _smart_ptr<IRenderMesh> pRenderMesh, IBSPTree3D* pBspTree, const Matrix34& worldTM, bool bActive, uint32 flags, const char* szName)
|
|
{
|
|
int nVolumeIndex = m_ClipVolumes.Find((CClipVolume*)pClipVolume);
|
|
if (nVolumeIndex >= 0)
|
|
{
|
|
SClipVolumeInfo& volumeInfo = m_ClipVolumes[nVolumeIndex];
|
|
volumeInfo.m_pVolume->Update(pRenderMesh, pBspTree, worldTM, flags);
|
|
volumeInfo.m_pVolume->SetName(szName);
|
|
volumeInfo.m_bActive = bActive;
|
|
|
|
AABB volumeBBox = pClipVolume->GetClipVolumeBBox();
|
|
Get3DEngine()->GetObjManager()->ReregisterEntitiesInArea(volumeBBox.min, volumeBBox.max);
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void CClipVolumeManager::PrepareVolumesForRendering(const SRenderingPassInfo& passInfo)
|
|
{
|
|
for (size_t i = 0; i < m_ClipVolumes.size(); ++i)
|
|
{
|
|
SClipVolumeInfo& volInfo = m_ClipVolumes[i];
|
|
volInfo.m_pVolume->SetStencilRef(InactiveVolumeStencilRef);
|
|
|
|
if (volInfo.m_bActive && passInfo.GetCamera().IsAABBVisible_F(volInfo.m_pVolume->GetClipVolumeBBox()))
|
|
{
|
|
uint8 nStencilRef = GetRenderer()->EF_AddDeferredClipVolume(volInfo.m_pVolume);
|
|
volInfo.m_pVolume->SetStencilRef(nStencilRef);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CClipVolumeManager::UpdateEntityClipVolume(const Vec3& pos, IRenderNode* pRenderNode)
|
|
{
|
|
FRAME_PROFILER("CClipVolumeManager::UpdateEntityClipVolume", GetSystem(), PROFILE_3DENGINE);
|
|
|
|
if (!pRenderNode || !pRenderNode->m_pRNTmpData)
|
|
{
|
|
return;
|
|
}
|
|
|
|
IClipVolume* pPreviousVolume = pRenderNode->m_pRNTmpData->userData.m_pClipVolume;
|
|
UnregisterRenderNode(pRenderNode);
|
|
|
|
// user assigned clip volume
|
|
CLightEntity* pLight = static_cast<CLightEntity*>(pRenderNode);
|
|
if (pRenderNode->GetRenderNodeType() == eERType_Light && (pLight->m_light.m_Flags & DLF_HAS_CLIP_VOLUME) != 0)
|
|
{
|
|
for (int i = 1; i >= 0; --i)
|
|
{
|
|
if (CClipVolume* pVolume = static_cast<CClipVolume*>(pLight->m_light.m_pClipVolumes[i]))
|
|
{
|
|
pVolume->RegisterRenderNode(pRenderNode);
|
|
}
|
|
}
|
|
}
|
|
else // assign by position
|
|
{
|
|
// Check if entity is in same clip volume as before
|
|
if (pPreviousVolume && (pPreviousVolume->GetClipVolumeFlags() & IClipVolume::eClipVolumeIsVisArea) == 0)
|
|
{
|
|
CClipVolume* pVolume = static_cast<CClipVolume*>(pPreviousVolume);
|
|
if (pVolume->IsPointInsideClipVolume(pos))
|
|
{
|
|
pVolume->RegisterRenderNode(pRenderNode);
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (CClipVolume* pVolume = GetClipVolumeByPos(pos, pPreviousVolume))
|
|
{
|
|
pVolume->RegisterRenderNode(pRenderNode);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CClipVolumeManager::UnregisterRenderNode(IRenderNode* pRenderNode)
|
|
{
|
|
if (!pRenderNode)
|
|
{
|
|
return;
|
|
}
|
|
|
|
for (size_t i = 0; i < m_ClipVolumes.size(); ++i)
|
|
{
|
|
m_ClipVolumes[i].m_pVolume->UnregisterRenderNode(pRenderNode);
|
|
}
|
|
|
|
if (pRenderNode->m_pRNTmpData)
|
|
{
|
|
pRenderNode->m_pRNTmpData->userData.m_pClipVolume = NULL;
|
|
}
|
|
}
|
|
|
|
bool CClipVolumeManager::IsClipVolumeRequired(IRenderNode* pRenderNode) const
|
|
{
|
|
const uint32 NoClipVolumeLights = DLF_SUN | DLF_ATTACH_TO_SUN;
|
|
|
|
const bool bForwardObject = (pRenderNode->m_nInternalFlags & IRenderNode::REQUIRES_FORWARD_RENDERING) != 0;
|
|
const EERType ertype = pRenderNode->GetRenderNodeType();
|
|
const bool bIsValidLight = ertype == eERType_Light &&
|
|
(static_cast<CLightEntity*>(pRenderNode)->m_light.m_Flags & NoClipVolumeLights) == 0;
|
|
const bool bIsValidFogVolume = (ertype == eERType_FogVolume) &&
|
|
static_cast<CFogVolumeRenderNode*>(pRenderNode)->IsAffectsThisAreaOnly();
|
|
|
|
return bIsValidLight || bForwardObject || bIsValidFogVolume;
|
|
}
|
|
|
|
CClipVolume* CClipVolumeManager::GetClipVolumeByPos(const Vec3& pos, const IClipVolume* pIgnoreVolume) const
|
|
{
|
|
for (size_t i = 0; i < m_ClipVolumes.size(); ++i)
|
|
{
|
|
const SClipVolumeInfo& volInfo = m_ClipVolumes[i];
|
|
|
|
if (volInfo.m_bActive && volInfo.m_pVolume != pIgnoreVolume && volInfo.m_pVolume->IsPointInsideClipVolume(pos))
|
|
{
|
|
return m_ClipVolumes[i].m_pVolume;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
void CClipVolumeManager::GetMemoryUsage(class ICrySizer* pSizer) const
|
|
{
|
|
pSizer->AddObject(this, sizeof(this));
|
|
for (size_t i = 0; i < m_ClipVolumes.size(); ++i)
|
|
{
|
|
pSizer->AddObject(m_ClipVolumes[i].m_pVolume);
|
|
}
|
|
}
|