/* * 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 "StdAfx.h" #include "EnvironmentProbeObject.h" #include "../EnvironmentProbePanel.h" #include "Util/CubemapUtils.h" #include "Util/Variable.h" #include "GameEngine.h" #include "../Cry3DEngine/StatObj.h" #include "../Cry3DEngine/Material.h" #include "../Cry3DEngine/MatMan.h" #include <IShader.h> // <> required for Interfuscator #include <ITimeOfDay.h> ////////////////////////////////////////////////////////////////////////// // CBase implementation. ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// // statics ////////////////////////////////////////////////////////////////////////// int CEnvironementProbeObject::s_panelProbeID = 0; CEnvironmentProbePanel* CEnvironementProbeObject::s_pProbePanel = NULL; ////////////////////////////////////////////////////////////////////////// CEnvironementProbeObject::CEnvironementProbeObject() { m_entityClass = "EnvironmentLight"; } ////////////////////////////////////////////////////////////////////////// CEnvironementProbeTODObject::CEnvironementProbeTODObject() { m_entityClass = "EnvironmentLightTOD"; m_timeSlots = 4; } ////////////////////////////////////////////////////////////////////////// bool CEnvironementProbeObject::Init(IEditor* ie, CBaseObject* prev, const QString& file) { bool res = CEntityObject::Init(ie, prev, file); return res; } ////////////////////////////////////////////////////////////////////////// void CEnvironementProbeObject::InitVariables() { CVarEnumList<int>* enumList = new CVarEnumList<int>(); enumList->AddItem("skip update", 0); //enumList->AddItem( "32",32 ); //enumList->AddItem( "64",64 ); //enumList->AddItem( "128",128 ); enumList->AddItem("256", 256); enumList->AddItem("512", 512); enumList->AddItem("1024", 1024); m_cubemap_resolution->SetEnumList(enumList); m_cubemap_resolution->SetDisplayValue("256"); m_cubemap_resolution->SetFlags(m_cubemap_resolution->GetFlags() | IVariable::UI_UNSORTED); AddVariable(m_cubemap_resolution, QString("cubemap_resolution")); AddVariable(m_preview_cubemap, QString("preview_cubemap"), functor(*this, &CEnvironementProbeObject::OnPreviewCubemap), IVariable::DT_SIMPLE); m_preview_cubemap->Set(false); CEntityObject::InitVariables(); } ////////////////////////////////////////////////////////////////////////// void CEnvironementProbeObject::Serialize(CObjectArchive& ar) { CEntityObject::Serialize(ar); } ////////////////////////////////////////////////////////////////////////// void CEnvironementProbeObject::BeginEditParams(IEditor* ie, int flags) { CEntityObject::BeginEditParams(ie, flags); if (!s_panelProbeID) { s_pProbePanel = new CEnvironmentProbePanel(); s_panelProbeID = ie->AddRollUpPage(ROLLUP_OBJECTS, "Probe Functions", s_pProbePanel, 3); } if (s_panelProbeID) { s_pProbePanel->SetEntity(this); } } ////////////////////////////////////////////////////////////////////////// void CEnvironementProbeObject::EndEditParams(IEditor* ie) { if (s_pProbePanel) { ie->RemoveRollUpPage(ROLLUP_OBJECTS, s_panelProbeID); s_panelProbeID = 0; s_pProbePanel = 0; } CEntityObject::EndEditParams(ie); } ////////////////////////////////////////////////////////////////////////// void CEnvironementProbeObject::Display(DisplayContext& dc) { // Check to see if m_preview_cubemap is enabled but the m_visualObject does not exist. // This scenario is hit when serializing the level because m_visualObject will be destroyed // in the entity base class during serialization, so we have to recreate it here. bool doPreview = false; m_preview_cubemap->Get(doPreview); if ( doPreview && !m_visualObject ) { ToggleCubemapPreview( true ); } Matrix34 wtm = GetWorldTM(); Vec3 wp = wtm.GetTranslation(); float fScale = GetHelperScale(); if (IsHighlighted() && !IsFrozen()) { dc.SetLineWidth(3); } if (IsSelected()) { dc.SetSelectedColor(); } else if (IsFrozen()) { dc.SetFreezeColor(); } else { dc.SetColor(GetColor()); } if (!m_visualObject) { dc.PushMatrix(wtm); Vec3 sz(fScale * 0.5f, fScale * 0.5f, fScale * 0.5f); dc.DrawWireBox(-sz, sz); // Draw radiuses if present and object selected. if (gSettings.viewports.bAlwaysShowRadiuses || IsSelected()) { if (m_bBoxProjectedCM) { // Draw helper for box projection. float fBoxWidth = m_fBoxWidth * 0.5f; float fBoxHeight = m_fBoxHeight * 0.5f; float fBoxLength = m_fBoxLength * 0.5f; dc.SetColor(0, 1, 0, 0.8f); dc.DrawWireBox(Vec3(-fBoxLength, -fBoxWidth, -fBoxHeight), Vec3(fBoxLength, fBoxWidth, fBoxHeight)); } const Vec3& scale = GetScale(); if (scale.x != 0.0f && scale.y != 0.0f && scale.z != 0.0f) { Vec3 size(m_boxSizeX * 0.5f / scale.x, m_boxSizeY * 0.5f / scale.y, m_boxSizeZ * 0.5f / scale.z); dc.SetColor(1, 1, 0, 0.8f); dc.DrawWireBox(Vec3(-size.x, -size.y, -size.z), Vec3(size.x, size.y, size.z)); } } dc.PopMatrix(); } if (IsHighlighted() && !IsFrozen()) { dc.SetLineWidth(0); } if (!m_visualObject) { DrawDefault(dc); } if (m_visualObject) { Matrix34 tm(wtm); float sz = m_helperScale * gSettings.gizmo.helpersScale; tm.ScaleColumn(Vec3(sz, sz, sz)); SRendParams rp; rp.AmbientColor = ColorF(1.0f, 1.0f, 1.0f, 1); rp.fAlpha = 1; rp.pMatrix = &tm; rp.pMaterial = m_visualObject->GetMaterial(); SRenderingPassInfo passInfo = SRenderingPassInfo::CreateGeneralPassRenderingInfo(gEnv->p3DEngine->GetRenderingCamera()); m_visualObject->Render(rp, passInfo); } } ////////////////////////////////////////////////////////////////////////// //! Get bounding box of object in world coordinate space. void CEnvironementProbeObject::GetBoundBox(AABB& box) { const float fScale = GetHelperScale(); const Vec3& position = GetPos(); const Vec3 sz(fScale * 0.5f, fScale * 0.5f, fScale * 0.5f); box.max = position + sz; box.min = position - sz; } void CEnvironementProbeObject::GetLocalBounds(AABB& aabb) { const float fScale = GetHelperScale(); const Vec3 sz(fScale * 0.5f, fScale * 0.5f, fScale * 0.5f); aabb.max = sz; aabb.min = -sz; } ////////////////////////////////////////////////////////////////////////// void CEnvironementProbeObject::GenerateCubemap() { QString levelfolder = GetIEditor()->GetGameEngine()->GetLevelPath(); QString levelname = Path::GetFile(levelfolder).toLower(); QString fullGameFolder = QString(Path::GetEditingGameDataFolder().c_str()); QString texturename = (GetName() + QString("_cm.tif")).toLower(); QString fullFolder = Path::SubDirectoryCaseInsensitive(fullGameFolder, {"textures", "cubemaps", levelname}); QString fullFilename = QDir(fullFolder).absoluteFilePath(texturename); QString relFilename = QDir(fullGameFolder).relativeFilePath(fullFilename); CFileUtil::CreateDirectory(fullFolder.toUtf8().data()); int cubemapres = 256; m_cubemap_resolution->Get(cubemapres); if (cubemapres > 0 && CubemapUtils::GenCubemapWithObjectPathAndSize(fullFilename, this, (int)cubemapres, true)) { IVariable* pVar = GetProperties()->FindVariable("texture_deferred_cubemap", true); if (!pVar) { return; } Path::ConvertBackSlashToSlash(relFilename); if (GetIEditor()->GetConsoleVar("ed_lowercasepaths")) { relFilename = relFilename.toLower(); } // the actual asset name should be a dds. pVar->Set(Path::ReplaceExtension(relFilename, "dds")); if (m_visualObject) { m_visualObject->SetMaterial(CreateMaterial()); } UpdatePropertyPanels(); UpdateLinks(); } } ////////////////////////////////////////////////////////////////////////// void CEnvironementProbeTODObject::GenerateCubemap() { QString levelfolder = QString(GetIEditor()->GetGameEngine()->GetLevelPath()); QString levelname = Path::GetFile(levelfolder).toLower(); QString fullGameFolder = Path::GetEditingGameDataFolder().c_str(); QString fullFolder = Path::SubDirectoryCaseInsensitive(fullGameFolder, {"textures", "cubemaps", levelname}); QString relFolder = QDir(fullGameFolder).relativeFilePath(fullFolder); CFileUtil::CreateDirectory(fullFolder.toUtf8().data()); int cubemapres = 256; m_cubemap_resolution->Get(cubemapres); float fCurTime = gEnv->p3DEngine->GetTimeOfDay()->GetTime(); for (int i = 1; i <= m_timeSlots; i++) { QString texturename = (GetName() + QString(string().Format("_tod%d_cm.tif", i))).toLower(); QString fullFilenameTOD = QDir(fullFolder).absoluteFilePath(texturename); QString relFilenameTOD = QDir(fullGameFolder).relativeFilePath(fullFilenameTOD); IVariable* pTODVar = GetProperties()->FindVariable(string().Format("TimeOfDay%d", i), true)->FindVariable("fHour", true); if (pTODVar) { float hour; pTODVar->Get(hour); gEnv->p3DEngine->GetTimeOfDay()->SetTime(hour, true); if (cubemapres > 0 && CubemapUtils::GenCubemapWithObjectPathAndSize(fullFilenameTOD, this, (int)cubemapres, true)) { IVariable* pTexVar = GetProperties()->FindVariable(string().Format("TimeOfDay%d", i), true)->FindVariable(string().Format("texture_deferred_cubemap_tod%d", i), true); if (!pTexVar) { return; } Path::ConvertBackSlashToSlash(relFilenameTOD); if (GetIEditor()->GetConsoleVar("ed_lowercasepaths")) { relFilenameTOD = relFilenameTOD.toLower(); } pTexVar->Set(relFilenameTOD); if (m_visualObject) { m_visualObject->SetMaterial(CreateMaterial()); } } } } gEnv->p3DEngine->GetTimeOfDay()->SetTime(fCurTime, true); UpdatePropertyPanels(); UpdateLinks(); } ////////////////////////////////////////////////////////////////////////// _smart_ptr<IMaterial> CEnvironementProbeObject::CreateMaterial() { QString deferredCubemapPath; QString matName; if (!GetProperties()) { return NULL; } IVariable* pVar = GetProperties()->FindVariable("texture_deferred_cubemap", true); if (!pVar) { return NULL; } pVar->Get(deferredCubemapPath); matName = Path::GetFileName(deferredCubemapPath); IMaterialManager* pMatMan = GetIEditor()->Get3DEngine()->GetMaterialManager(); _smart_ptr<IMaterial> pMatSrc = pMatMan->LoadMaterial("Editor/Objects/envcube", false, true); if (pMatSrc) { _smart_ptr<IMaterial> pMatDst = pMatMan->CreateMaterial(matName.toUtf8().data(), pMatSrc->GetFlags() | MTL_FLAG_NON_REMOVABLE); if (pMatDst) { SShaderItem& si = pMatSrc->GetShaderItem(); SInputShaderResources isr = si.m_pShaderResources; // The following will create the environment map slot if did not exist isr.m_TexturesResourcesMap[ EFTT_ENV ].m_Name = deferredCubemapPath.toUtf8().data(); SShaderItem siDst = GetIEditor()->GetRenderer()->EF_LoadShaderItem(si.m_pShader->GetName(), true, 0, &isr, si.m_pShader->GetGenerationMask()); pMatDst->AssignShaderItem(siDst); return pMatDst; } } return nullptr; } ////////////////////////////////////////////////////////////////////////// void CEnvironementProbeObject::OnPreviewCubemap(IVariable* piVariable) { bool preview = false; piVariable->Get(preview); ToggleCubemapPreview(preview); } void CEnvironementProbeObject::ToggleCubemapPreview( bool enable ) { if (enable) { m_visualObject = GetIEditor()->Get3DEngine()->LoadStatObjUnsafeManualRef("Editor/Objects/envcube.cgf", nullptr, nullptr, false); if (m_visualObject) { m_visualObject = m_visualObject->Clone(false, false, false); m_visualObject->SetMaterial(CreateMaterial()); m_visualObject->AddRef(); } } else { if (m_visualObject) { m_visualObject->Release(); } m_visualObject = NULL; } } int CEnvironementProbeObject::AddEntityLink(const QString& name, GUID targetEntityId) { int ret = CEntityObject::AddEntityLink(name, targetEntityId); UpdateLinks(); return ret; } void CEnvironementProbeObject::UpdateLinks() { int count = GetEntityLinkCount(); for (int idx = 0; idx < count; idx++) { CEntityLink link = GetEntityLink(idx); CBaseObject* pObject = GetIEditor()->GetObjectManager()->FindObject(link.targetId); if (!pObject) { continue; } CEntityObject* pTarget = NULL; if (qobject_cast<CEntityObject*>(pObject)) { pTarget = (CEntityObject*)pObject; } if (!pTarget) { continue; } CVarBlock* pVarBlock = NULL; QString type = pObject->GetTypeDescription(); if (QString::compare(type, "Light", Qt::CaseInsensitive) == 0) { pVarBlock = pTarget->GetProperties(); if (!pVarBlock) { continue; } } else if (QString::compare(type, "DestroyableLight", Qt::CaseInsensitive) == 0 || QString::compare(type, "RigidBodyLight", Qt::CaseInsensitive) == 0) { pVarBlock = pTarget->GetProperties2(); if (!pVarBlock) { continue; } } else { continue; } CVarBlock* pProperties = GetProperties(); if (!pProperties || !pVarBlock) { continue; } IVariable* pDstDeferredCubemap = pVarBlock->FindVariable("texture_deferred_cubemap", true); IVariable* pDeferredCubemap = pProperties->FindVariable("texture_deferred_cubemap", true); if (!pDstDeferredCubemap || !pDeferredCubemap) { continue; } bool bDeferred = false; QString strCubemap; pDeferredCubemap->Get(strCubemap); pDstDeferredCubemap->Set(strCubemap); } } void CEnvironementProbeTODObject::UpdateLinks() { int count = GetEntityLinkCount(); for (int idx = 0; idx < count; idx++) { CEntityLink link = GetEntityLink(idx); CBaseObject* pObject = GetIEditor()->GetObjectManager()->FindObject(link.targetId); if (!pObject) { continue; } CEntityObject* pTarget = NULL; if (qobject_cast<CEntityObject*>(pObject)) { pTarget = (CEntityObject*)pObject; } if (!pTarget) { continue; } CVarBlock* pVarBlock = NULL; QString type = pObject->GetTypeDescription(); if (QString::compare(type, "Light", Qt::CaseInsensitive) == 0) { pVarBlock = pTarget->GetProperties(); if (!pVarBlock) { continue; } } else if (QString::compare(type, "DestroyableLight", Qt::CaseInsensitive) == 0 || QString::compare(type, "RigidBodyLight", Qt::CaseInsensitive) == 0) { pVarBlock = pTarget->GetProperties2(); if (!pVarBlock) { continue; } } else { continue; } } } void CEnvironementProbeObject::OnPropertyChanged(IVariable* pVar) { UpdateLinks(); if (QString::compare(pVar->GetName(), "fHour", Qt::CaseInsensitive) == 0) { float hour; pVar->Get(hour); if (hour < float(0.0)) { pVar->Set(float(0.0)); } else if (hour > float(24.0)) { pVar->Set(float(24.0)); } } CBaseObject::OnPropertyChanged(pVar); } void CEnvironementProbeObject::OnMultiSelPropertyChanged(IVariable* pVar) { UpdateLinks(); CBaseObject::OnMultiSelPropertyChanged(pVar); } #include <Objects/EnvironmentProbeObject.moc>