Changeset View
Changeset View
Standalone View
Standalone View
source/graphics/ObjectEntry.cpp
Show All 33 Lines | |||||
#include "ps/CLogger.h" | #include "ps/CLogger.h" | ||||
#include "ps/Game.h" | #include "ps/Game.h" | ||||
#include "ps/World.h" | #include "ps/World.h" | ||||
#include "renderer/Renderer.h" | #include "renderer/Renderer.h" | ||||
#include "simulation2/Simulation2.h" | #include "simulation2/Simulation2.h" | ||||
#include <sstream> | #include <sstream> | ||||
CObjectEntry::CObjectEntry(CObjectBase* base, CSimulation2& simulation) : | CObjectEntry::CObjectEntry(const CObjectBase& base, CSimulation2& simulation) : | ||||
m_Base(base), m_Color(1.0f, 1.0f, 1.0f, 1.0f), m_Model(NULL), m_Outdated(false), m_Simulation(simulation) | m_Base(base), m_Color(1.0f, 1.0f, 1.0f, 1.0f), m_Model(NULL), m_Outdated(false), m_Simulation(simulation) | ||||
{ | { | ||||
} | } | ||||
CObjectEntry::~CObjectEntry() | CObjectEntry::~CObjectEntry() | ||||
{ | { | ||||
for (const std::pair<const CStr, CSkeletonAnim*>& anim : m_Animations) | for (const std::pair<const CStr, CSkeletonAnim*>& anim : m_Animations) | ||||
delete anim.second; | delete anim.second; | ||||
delete m_Model; | delete m_Model; | ||||
} | } | ||||
bool CObjectEntry::BuildVariation(const std::vector<std::set<CStr> >& selections, | bool CObjectEntry::BuildVariation(const std::vector<std::set<CStr> >& selections, | ||||
const std::vector<u8>& variationKey, | const std::vector<u8>& variationKey, | ||||
CObjectManager& objectManager) | CObjectManager& objectManager) | ||||
{ | { | ||||
CObjectBase::Variation variation = m_Base->BuildVariation(variationKey); | CObjectBase::Variation variation = m_Base.BuildVariation(variationKey); | ||||
// Copy the chosen data onto this model: | // Copy the chosen data onto this model: | ||||
for (std::multimap<CStr, CObjectBase::Samp>::iterator it = variation.samplers.begin(); it != variation.samplers.end(); ++it) | for (std::multimap<CStr, CObjectBase::Samp>::iterator it = variation.samplers.begin(); it != variation.samplers.end(); ++it) | ||||
m_Samplers.push_back(it->second); | m_Samplers.push_back(it->second); | ||||
m_ModelName = variation.model; | m_ModelName = variation.model; | ||||
if (! variation.color.empty()) | if (! variation.color.empty()) | ||||
{ | { | ||||
std::stringstream str; | std::stringstream str; | ||||
str << variation.color; | str << variation.color; | ||||
int r, g, b; | int r, g, b; | ||||
if (! (str >> r >> g >> b)) // Any trailing data is ignored | if (! (str >> r >> g >> b)) // Any trailing data is ignored | ||||
LOGERROR("Actor '%s' has invalid RGB color '%s'", utf8_from_wstring(m_Base->m_ShortName), variation.color); | LOGERROR("Actor '%s' has invalid RGB color '%s'", utf8_from_wstring(m_Base.m_ShortName), variation.color); | ||||
else | else | ||||
m_Color = CColor(r/255.0f, g/255.0f, b/255.0f, 1.0f); | m_Color = CColor(r/255.0f, g/255.0f, b/255.0f, 1.0f); | ||||
} | } | ||||
if (variation.decal.m_SizeX && variation.decal.m_SizeZ) | if (variation.decal.m_SizeX && variation.decal.m_SizeZ) | ||||
{ | { | ||||
CMaterial material = g_Renderer.GetMaterialManager().LoadMaterial(m_Base->m_Material); | CMaterial material = g_Renderer.GetMaterialManager().LoadMaterial(m_Base.m_Material); | ||||
for (const CObjectBase::Samp& samp : m_Samplers) | for (const CObjectBase::Samp& samp : m_Samplers) | ||||
{ | { | ||||
CTextureProperties textureProps(samp.m_SamplerFile); | CTextureProperties textureProps(samp.m_SamplerFile); | ||||
textureProps.SetWrap(GL_CLAMP_TO_BORDER); | textureProps.SetWrap(GL_CLAMP_TO_BORDER); | ||||
CTexturePtr texture = g_Renderer.GetTextureManager().CreateTexture(textureProps); | CTexturePtr texture = g_Renderer.GetTextureManager().CreateTexture(textureProps); | ||||
// TODO: Should check which renderpath is selected and only preload the necessary textures. | // TODO: Should check which renderpath is selected and only preload the necessary textures. | ||||
texture->Prefetch(); | texture->Prefetch(); | ||||
material.AddSampler(CMaterial::TextureSampler(samp.m_SamplerName, texture)); | material.AddSampler(CMaterial::TextureSampler(samp.m_SamplerName, texture)); | ||||
} | } | ||||
SDecal decal(material, | SDecal decal(material, | ||||
variation.decal.m_SizeX, variation.decal.m_SizeZ, | variation.decal.m_SizeX, variation.decal.m_SizeZ, | ||||
variation.decal.m_Angle, variation.decal.m_OffsetX, variation.decal.m_OffsetZ, | variation.decal.m_Angle, variation.decal.m_OffsetX, variation.decal.m_OffsetZ, | ||||
m_Base->m_Properties.m_FloatOnWater); | m_Base.m_Properties.m_FloatOnWater); | ||||
m_Model = new CModelDecal(objectManager.GetTerrain(), decal); | m_Model = new CModelDecal(objectManager.GetTerrain(), decal); | ||||
return true; | return true; | ||||
} | } | ||||
if (!variation.particles.empty()) | if (!variation.particles.empty()) | ||||
{ | { | ||||
m_Model = new CModelParticleEmitter(g_Renderer.GetParticleManager().LoadEmitterType(variation.particles)); | m_Model = new CModelParticleEmitter(g_Renderer.GetParticleManager().LoadEmitterType(variation.particles)); | ||||
Show All 14 Lines | if (!modeldef) | ||||
LOGERROR("CObjectEntry::BuildVariation(): Model %s failed to load", m_ModelName.string8()); | LOGERROR("CObjectEntry::BuildVariation(): Model %s failed to load", m_ModelName.string8()); | ||||
return false; | return false; | ||||
} | } | ||||
// delete old model, create new | // delete old model, create new | ||||
CModel* model = new CModel(objectManager.GetSkeletonAnimManager(), m_Simulation); | CModel* model = new CModel(objectManager.GetSkeletonAnimManager(), m_Simulation); | ||||
delete m_Model; | delete m_Model; | ||||
m_Model = model; | m_Model = model; | ||||
model->SetMaterial(g_Renderer.GetMaterialManager().LoadMaterial(m_Base->m_Material)); | model->SetMaterial(g_Renderer.GetMaterialManager().LoadMaterial(m_Base.m_Material)); | ||||
model->GetMaterial().AddStaticUniform("objectColor", CVector4D(m_Color.r, m_Color.g, m_Color.b, m_Color.a)); | model->GetMaterial().AddStaticUniform("objectColor", CVector4D(m_Color.r, m_Color.g, m_Color.b, m_Color.a)); | ||||
model->InitModel(modeldef); | model->InitModel(modeldef); | ||||
if (m_Samplers.empty()) | if (m_Samplers.empty()) | ||||
LOGERROR("Actor '%s' has no textures.", utf8_from_wstring(m_Base->m_ShortName)); | LOGERROR("Actor '%s' has no textures.", utf8_from_wstring(m_Base.m_ShortName)); | ||||
for (const CObjectBase::Samp& samp : m_Samplers) | for (const CObjectBase::Samp& samp : m_Samplers) | ||||
{ | { | ||||
CTextureProperties textureProps(samp.m_SamplerFile); | CTextureProperties textureProps(samp.m_SamplerFile); | ||||
textureProps.SetWrap(GL_CLAMP_TO_EDGE); | textureProps.SetWrap(GL_CLAMP_TO_EDGE); | ||||
CTexturePtr texture = g_Renderer.GetTextureManager().CreateTexture(textureProps); | CTexturePtr texture = g_Renderer.GetTextureManager().CreateTexture(textureProps); | ||||
// if we've loaded this model we're probably going to render it soon, so prefetch its texture. | // if we've loaded this model we're probably going to render it soon, so prefetch its texture. | ||||
// All textures are prefetched even in the fixed pipeline, including the normal maps etc. | // All textures are prefetched even in the fixed pipeline, including the normal maps etc. | ||||
// TODO: Should check which renderpath is selected and only preload the necessary textures. | // TODO: Should check which renderpath is selected and only preload the necessary textures. | ||||
texture->Prefetch(); | texture->Prefetch(); | ||||
model->GetMaterial().AddSampler(CMaterial::TextureSampler(samp.m_SamplerName, texture)); | model->GetMaterial().AddSampler(CMaterial::TextureSampler(samp.m_SamplerName, texture)); | ||||
} | } | ||||
for (const CStrIntern& requSampName : model->GetMaterial().GetRequiredSampler()) | for (const CStrIntern& requSampName : model->GetMaterial().GetRequiredSampler()) | ||||
{ | { | ||||
if (std::find_if(m_Samplers.begin(), m_Samplers.end(), | if (std::find_if(m_Samplers.begin(), m_Samplers.end(), | ||||
[&](const CObjectBase::Samp& sampler) { return sampler.m_SamplerName == requSampName; }) == m_Samplers.end()) | [&](const CObjectBase::Samp& sampler) { return sampler.m_SamplerName == requSampName; }) == m_Samplers.end()) | ||||
LOGERROR("Actor %s: required texture sampler %s not found (material %s)", utf8_from_wstring(m_Base->m_ShortName), requSampName.string().c_str(), m_Base->m_Material.string8().c_str()); | LOGERROR("Actor %s: required texture sampler %s not found (material %s)", utf8_from_wstring(m_Base.m_ShortName), requSampName.string().c_str(), m_Base.m_Material.string8().c_str()); | ||||
} | } | ||||
// calculate initial object space bounds, based on vertex positions | // calculate initial object space bounds, based on vertex positions | ||||
model->CalcStaticObjectBounds(); | model->CalcStaticObjectBounds(); | ||||
// load the animations | // load the animations | ||||
for (std::multimap<CStr, CObjectBase::Anim>::iterator it = variation.anims.begin(); it != variation.anims.end(); ++it) | for (std::multimap<CStr, CObjectBase::Anim>::iterator it = variation.anims.begin(); it != variation.anims.end(); ++it) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 44 Lines • ▼ Show 20 Lines | bool CObjectEntry::BuildVariation(const std::vector<std::set<CStr> >& selections, | ||||
{ | { | ||||
// Pluck out the special attachpoint 'projectile' | // Pluck out the special attachpoint 'projectile' | ||||
if (prop.m_PropPointName == "projectile") | if (prop.m_PropPointName == "projectile") | ||||
{ | { | ||||
m_ProjectileModelName = prop.m_ModelName; | m_ProjectileModelName = prop.m_ModelName; | ||||
continue; | continue; | ||||
} | } | ||||
CObjectEntry* oe = objectManager.FindObjectVariation(prop.m_ModelName.c_str(), selections); | CObjectEntry* oe = objectManager.FindObjectVariation(prop.m_ModelName.c_str(), m_Base.m_LODLevel, selections); | ||||
if (!oe) | if (!oe) | ||||
{ | { | ||||
LOGERROR("Failed to build prop model \"%s\" on actor \"%s\"", utf8_from_wstring(prop.m_ModelName), utf8_from_wstring(m_Base->m_ShortName)); | LOGERROR("Failed to build prop model \"%s\" on actor \"%s\"", utf8_from_wstring(prop.m_ModelName), utf8_from_wstring(m_Base.m_ShortName)); | ||||
continue; | continue; | ||||
} | } | ||||
// If we don't have a projectile but this prop does (e.g. it's our rider), then | // If we don't have a projectile but this prop does (e.g. it's our rider), then | ||||
// use that as our projectile too | // use that as our projectile too | ||||
if (m_ProjectileModelName.empty() && !oe->m_ProjectileModelName.empty()) | if (m_ProjectileModelName.empty() && !oe->m_ProjectileModelName.empty()) | ||||
m_ProjectileModelName = oe->m_ProjectileModelName; | m_ProjectileModelName = oe->m_ProjectileModelName; | ||||
Show All 14 Lines | if (proppoint) | ||||
if (isAmmo) | if (isAmmo) | ||||
model->AddAmmoProp(proppoint, propmodel, oe); | model->AddAmmoProp(proppoint, propmodel, oe); | ||||
else | else | ||||
model->AddProp(proppoint, propmodel, oe, prop.m_minHeight, prop.m_maxHeight, prop.m_selectable); | model->AddProp(proppoint, propmodel, oe, prop.m_minHeight, prop.m_maxHeight, prop.m_selectable); | ||||
if (propmodel->ToCModel()) | if (propmodel->ToCModel()) | ||||
propmodel->ToCModel()->SetAnimation(oe->GetRandomAnimation("idle")); | propmodel->ToCModel()->SetAnimation(oe->GetRandomAnimation("idle")); | ||||
} | } | ||||
else | else | ||||
LOGERROR("Failed to find matching prop point called \"%s\" in model \"%s\" for actor \"%s\"", ppn, m_ModelName.string8(), utf8_from_wstring(m_Base->m_ShortName)); | LOGERROR("Failed to find matching prop point called \"%s\" in model \"%s\" for actor \"%s\"", ppn, m_ModelName.string8(), utf8_from_wstring(m_Base.m_ShortName)); | ||||
} | } | ||||
// Setup flags. | // Setup flags. | ||||
if (m_Base->m_Properties.m_CastShadows) | if (m_Base.m_Properties.m_CastShadows) | ||||
{ | { | ||||
model->SetFlags(model->GetFlags() | MODELFLAG_CASTSHADOWS); | model->SetFlags(model->GetFlags() | MODELFLAG_CASTSHADOWS); | ||||
} | } | ||||
if (m_Base->m_Properties.m_FloatOnWater) | if (m_Base.m_Properties.m_FloatOnWater) | ||||
{ | { | ||||
model->SetFlags(model->GetFlags() | MODELFLAG_FLOATONWATER); | model->SetFlags(model->GetFlags() | MODELFLAG_FLOATONWATER); | ||||
} | } | ||||
return true; | return true; | ||||
} | } | ||||
CSkeletonAnim* CObjectEntry::GetRandomAnimation(const CStr& animationName, const CStr& ID) const | CSkeletonAnim* CObjectEntry::GetRandomAnimation(const CStr& animationName, const CStr& ID) const | ||||
▲ Show 20 Lines • Show All 44 Lines • Show Last 20 Lines |
Wildfire Games · Phabricator