Refactors models and materials, part 1, reduces amount of mutable properties.

Comments By: phosit
Differential Revision: https://code.wildfiregames.com/D5108
This was SVN commit r27841.
This commit is contained in:
Vladislav Belov 2023-09-14 08:37:06 +00:00
parent af13be489e
commit b8cd3a0268
4 changed files with 57 additions and 110 deletions

View File

@ -37,62 +37,33 @@
#include "simulation2/Simulation2.h"
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Constructor
CModel::CModel(CSimulation2& simulation)
: m_Flags(0), m_Anim(NULL), m_AnimTime(0), m_Simulation(simulation),
m_BoneMatrices(NULL), m_AmmoPropPoint(NULL), m_AmmoLoadedProp(0)
CModel::CModel(const CSimulation2& simulation, const CMaterial& material, const CModelDefPtr& modeldef)
: m_Simulation{simulation}, m_Material{material}, m_pModelDef{modeldef}
{
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Destructor
CModel::~CModel()
{
ReleaseData();
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ReleaseData: delete anything allocated by the model
void CModel::ReleaseData()
{
rtl_FreeAligned(m_BoneMatrices);
for (size_t i = 0; i < m_Props.size(); ++i)
delete m_Props[i].m_Model;
m_Props.clear();
m_pModelDef = CModelDefPtr();
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
// InitModel: setup model from given geometry
bool CModel::InitModel(const CModelDefPtr& modeldef)
{
// clean up any existing data first
ReleaseData();
m_pModelDef = modeldef;
size_t numBones = modeldef->GetNumBones();
if (numBones != 0)
const size_t numberOfBones = modeldef->GetNumBones();
if (numberOfBones != 0)
{
size_t numBlends = modeldef->GetNumBlends();
const size_t numberOfBlends = modeldef->GetNumBlends();
// allocate matrices for bone transformations
// (one extra matrix is used for the special case of bind-shape relative weighting)
m_BoneMatrices = (CMatrix3D*)rtl_AllocateAligned(sizeof(CMatrix3D) * (numBones + 1 + numBlends), 16);
for (size_t i = 0; i < numBones + 1 + numBlends; ++i)
m_BoneMatrices = (CMatrix3D*)rtl_AllocateAligned(sizeof(CMatrix3D) * (numberOfBones + 1 + numberOfBlends), 16);
for (size_t i = 0; i < numberOfBones + 1 + numberOfBlends; ++i)
{
m_BoneMatrices[i].SetIdentity();
}
}
m_PositionValid = true;
return true;
}
CModel::~CModel()
{
rtl_FreeAligned(m_BoneMatrices);
for (Prop& prop : m_Props)
delete prop.m_Model;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
// CalcBound: calculate the world space bounds of this model
@ -497,10 +468,8 @@ CModelAbstract* CModel::FindFirstAmmoProp()
// Clone: return a clone of this model
CModelAbstract* CModel::Clone() const
{
CModel* clone = new CModel(m_Simulation);
CModel* clone = new CModel(m_Simulation, m_Material, m_pModelDef);
clone->m_ObjectBounds = m_ObjectBounds;
clone->InitModel(m_pModelDef);
clone->SetMaterial(m_Material);
clone->SetAnimation(m_Anim);
clone->SetFlags(m_Flags);
@ -555,11 +524,6 @@ void CModel::RemoveShadowsRec()
}
}
void CModel::SetMaterial(const CMaterial &material)
{
m_Material = material;
}
void CModel::SetPlayerID(player_id_t id)
{
CModelAbstract::SetPlayerID(id);

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2022 Wildfire Games.
/* Copyright (C) 2023 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -40,9 +40,8 @@ class CSimulation2;
#define MODELFLAG_SILHOUETTE_OCCLUDER (1<<3)
#define MODELFLAG_IGNORE_LOS (1<<4)
#define MODELFLAG_FLOATONWATER (1<<5)
///////////////////////////////////////////////////////////////////////////////
// CModel: basically, a mesh object - holds the texturing and skinning
// information for a model in game
// Holds world information for a particular instance of a model in the game.
class CModel : public CModelAbstract
{
NONCOPYABLE(CModel);
@ -75,34 +74,27 @@ public:
};
public:
// constructor
CModel(CSimulation2& simulation);
// destructor
CModel(const CSimulation2& simulation, const CMaterial& material, const CModelDefPtr& modeldef);
~CModel();
/// Dynamic cast
virtual CModel* ToCModel()
{
return this;
}
// setup model from given geometry
bool InitModel(const CModelDefPtr& modeldef);
// update this model's state; 'time' is the absolute time since the start of the animation, in MS
void UpdateTo(float time);
// get the model's geometry data
const CModelDefPtr& GetModelDef() { return m_pModelDef; }
// set the model's material
void SetMaterial(const CMaterial &material);
// set the model's player ID, recursively through props
void SetPlayerID(player_id_t id);
// set the models mod color
virtual void SetShadingColor(const CColor& color);
// get the model's material
CMaterial& GetMaterial() { return m_Material; }
const CMaterial& GetMaterial() { return m_Material; }
// set the given animation as the current animation on this model
bool SetAnimation(CSkeletonAnim* anim, bool once = false);
@ -118,6 +110,7 @@ public:
void SetFlags(int flags) { m_Flags=flags; }
// get object flags
int GetFlags() const { return m_Flags; }
// add object flags, recursively through props
void AddFlagsRec(int flags);
// remove shadow casting and receiving, recursively through props
@ -232,26 +225,23 @@ public:
virtual void InvalidatePosition();
private:
// delete anything allocated by the model
void ReleaseData();
// Needed for terrain aligned props
CSimulation2& m_Simulation;
const CSimulation2& m_Simulation;
// object flags
int m_Flags;
int m_Flags{0};
// model's material
CMaterial m_Material;
// pointer to the model's raw 3d data
CModelDefPtr m_pModelDef;
const CModelDefPtr m_pModelDef;
// object space bounds of model - accounts for bounds of all possible animations
// that can play on a model. Not always up-to-date - currently CalcBounds()
// updates it when necessary.
CBoundingBoxAligned m_ObjectBounds;
// animation currently playing on this model, if any
CSkeletonAnim* m_Anim;
CSkeletonAnim* m_Anim = nullptr;
// time (in MS) into the current animation
float m_AnimTime;
float m_AnimTime{0.0f};
/**
* Current state of all bones on this model; null if associated modeldef isn't skeletal.
@ -261,19 +251,19 @@ private:
*
* @see SPropPoint
*/
CMatrix3D* m_BoneMatrices;
CMatrix3D* m_BoneMatrices{nullptr};
// list of current props on model
std::vector<Prop> m_Props;
/**
* The prop point to which the ammo prop is attached, or NULL if none
*/
const SPropPoint* m_AmmoPropPoint;
const SPropPoint* m_AmmoPropPoint{nullptr};
/**
* If m_AmmoPropPoint is not NULL, then the index in m_Props of the ammo prop
*/
size_t m_AmmoLoadedProp;
size_t m_AmmoLoadedProp{0};
};
#endif
#endif // INCLUDED_MODEL

View File

@ -43,16 +43,12 @@
#include <sstream>
CObjectEntry::CObjectEntry(const std::shared_ptr<CObjectBase>& base, CSimulation2& simulation) :
m_Base(base), m_Color(1.0f, 1.0f, 1.0f, 1.0f), m_Model(NULL), m_Simulation(simulation)
CObjectEntry::CObjectEntry(const std::shared_ptr<CObjectBase>& base, const CSimulation2& simulation) :
m_Base(base), m_Color(1.0f, 1.0f, 1.0f, 1.0f), m_Simulation(simulation)
{
}
CObjectEntry::~CObjectEntry()
{
delete m_Model;
}
CObjectEntry::~CObjectEntry() = default;
bool CObjectEntry::BuildVariation(const std::vector<const std::set<CStr>*>& completeSelections,
const std::vector<u8>& variationKey,
@ -101,20 +97,20 @@ bool CObjectEntry::BuildVariation(const std::vector<const std::set<CStr>*>& comp
variation.decal.m_SizeX, variation.decal.m_SizeZ,
variation.decal.m_Angle, variation.decal.m_OffsetX, variation.decal.m_OffsetZ,
m_Base->m_Properties.m_FloatOnWater);
m_Model = new CModelDecal(objectManager.GetTerrain(), decal);
m_Model = std::make_unique<CModelDecal>(objectManager.GetTerrain(), decal);
return true;
}
if (!variation.particles.empty())
{
m_Model = new CModelParticleEmitter(g_Renderer.GetSceneRenderer().GetParticleManager().LoadEmitterType(variation.particles));
m_Model = std::make_unique<CModelParticleEmitter>(g_Renderer.GetSceneRenderer().GetParticleManager().LoadEmitterType(variation.particles));
return true;
}
if (variation.model.empty())
{
m_Model = new CModelDummy();
m_Model = std::make_unique<CModelDummy>();
return true;
}
@ -134,12 +130,8 @@ bool CObjectEntry::BuildVariation(const std::vector<const std::set<CStr>*>& comp
}
// delete old model, create new
CModel* model = new CModel(m_Simulation);
delete m_Model;
m_Model = model;
model->SetMaterial(g_Renderer.GetSceneRenderer().GetMaterialManager().LoadMaterial(m_Base->m_Material));
model->GetMaterial().AddStaticUniform("objectColor", CVector4D(m_Color.r, m_Color.g, m_Color.b, m_Color.a));
model->InitModel(modeldef);
CMaterial material = g_Renderer.GetSceneRenderer().GetMaterialManager().LoadMaterial(m_Base->m_Material);
material.AddStaticUniform("objectColor", CVector4D(m_Color.r, m_Color.g, m_Color.b, m_Color.a));
if (m_Samplers.empty())
LOGERROR("Actor '%s' has no textures.", m_Base->GetIdentifier());
@ -153,9 +145,13 @@ bool CObjectEntry::BuildVariation(const std::vector<const std::set<CStr>*>& comp
// 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.
texture->Prefetch();
model->GetMaterial().AddSampler(CMaterial::TextureSampler(samp.m_SamplerName, texture));
material.AddSampler(CMaterial::TextureSampler(samp.m_SamplerName, texture));
}
std::unique_ptr<CModel> newModel = std::make_unique<CModel>(m_Simulation, material, modeldef);
CModel* model = newModel.get();
m_Model = std::move(newModel);
for (const CStrIntern& requSampName : model->GetMaterial().GetRequiredSampler())
{
if (std::find_if(m_Samplers.begin(), m_Samplers.end(),

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2022 Wildfire Games.
/* Copyright (C) 2023 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -18,29 +18,28 @@
#ifndef INCLUDED_OBJECTENTRY
#define INCLUDED_OBJECTENTRY
class CModelAbstract;
class CSkeletonAnim;
class CObjectBase;
class CObjectManager;
class CSimulation2;
#include "graphics/Color.h"
#include "graphics/ObjectBase.h"
#include "lib/file/vfs/vfs_path.h"
#include "ps/CStr.h"
#include <map>
#include <memory>
#include <set>
#include <vector>
#include "graphics/Color.h"
#include "lib/file/vfs/vfs_path.h"
#include "ps/CStr.h"
#include "graphics/ObjectBase.h"
class CModelAbstract;
class CSkeletonAnim;
class CObjectBase;
class CObjectManager;
class CSimulation2;
class CObjectEntry
{
NONCOPYABLE(CObjectEntry);
public:
CObjectEntry(const std::shared_ptr<CObjectBase>& base, CSimulation2& simulation);
CObjectEntry(const std::shared_ptr<CObjectBase>& base, const CSimulation2& simulation);
~CObjectEntry();
// Construct this actor, using the specified variation selections
@ -78,16 +77,14 @@ public:
std::vector<CSkeletonAnim*> GetAnimations(const CStr& animationName, const CStr& ID = "") const;
// corresponding model
CModelAbstract* m_Model;
std::unique_ptr<CModelAbstract> m_Model;
private:
CSimulation2& m_Simulation;
const CSimulation2& m_Simulation;
using SkeletonAnimMap = std::multimap<CStr, std::unique_ptr<CSkeletonAnim>>;
SkeletonAnimMap m_Animations;
// TODO: something more memory-efficient than storing loads of similar strings for each unit?
};
#endif
#endif // INCLUDED_OBJECTENTRY