1
0
forked from 0ad/0ad

Move BuildAnimation to CSkeletalAnimMgr / CObjectEntry

There is no need to have BuildAnimation in CModel when everything is
done in CObjectEntry anyways.
This removes a pointer in every CModel object, which is nice.

Accepted By: vladislavbelov
Differential Revision: https://code.wildfiregames.com/D4454
This was SVN commit r26254.
This commit is contained in:
wraitii 2022-01-26 14:55:19 +00:00
parent fe816ecb1a
commit 83d251406c
6 changed files with 75 additions and 78 deletions

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2021 Wildfire Games.
/* Copyright (C) 2022 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -25,7 +25,6 @@
#include "graphics/ObjectEntry.h"
#include "graphics/SkeletonAnim.h"
#include "graphics/SkeletonAnimDef.h"
#include "graphics/SkeletonAnimManager.h"
#include "maths/BoundingBoxAligned.h"
#include "maths/Quaternion.h"
#include "lib/sysdep/rtl.h"
@ -40,10 +39,9 @@
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Constructor
CModel::CModel(CSkeletonAnimManager& skeletonAnimManager, CSimulation2& simulation)
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),
m_SkeletonAnimManager(skeletonAnimManager)
m_BoneMatrices(NULL), m_AmmoPropPoint(NULL), m_AmmoLoadedProp(0)
{
}
@ -198,43 +196,6 @@ const CBoundingBoxAligned CModel::GetObjectSelectionBoundsRec()
return objBounds;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
// BuildAnimation: load raw animation frame animation from given file, and build a
// animation specific to this model
CSkeletonAnim* CModel::BuildAnimation(const VfsPath& pathname, const CStr& name, const CStr& ID, int frequency, float speed, float actionpos, float actionpos2, float soundpos)
{
CSkeletonAnimDef* def = m_SkeletonAnimManager.GetAnimation(pathname);
if (!def)
return NULL;
CSkeletonAnim* anim = new CSkeletonAnim();
anim->m_Name = name;
anim->m_ID = ID;
anim->m_Frequency = frequency;
anim->m_AnimDef = def;
anim->m_Speed = speed;
if (actionpos == -1.f)
anim->m_ActionPos = -1.f;
else
anim->m_ActionPos = actionpos * anim->m_AnimDef->GetDuration();
if (actionpos2 == -1.f)
anim->m_ActionPos2 = -1.f;
else
anim->m_ActionPos2 = actionpos2 * anim->m_AnimDef->GetDuration();
if (soundpos == -1.f)
anim->m_SoundPos = -1.f;
else
anim->m_SoundPos = soundpos * anim->m_AnimDef->GetDuration();
anim->m_ObjectBounds.SetEmpty();
InvalidateBounds();
return anim;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Update: update this model to the given time, in msec
void CModel::UpdateTo(float time)
@ -533,7 +494,7 @@ CModelAbstract* CModel::FindFirstAmmoProp()
// Clone: return a clone of this model
CModelAbstract* CModel::Clone() const
{
CModel* clone = new CModel(m_SkeletonAnimManager, m_Simulation);
CModel* clone = new CModel(m_Simulation);
clone->m_ObjectBounds = m_ObjectBounds;
clone->InitModel(m_pModelDef);
clone->SetMaterial(m_Material);

View File

@ -32,7 +32,6 @@ struct SPropPoint;
class CObjectEntry;
class CSkeletonAnim;
class CSkeletonAnimDef;
class CSkeletonAnimManager;
class CSimulation2;
#define MODELFLAG_CASTSHADOWS (1<<0)
@ -77,7 +76,7 @@ public:
public:
// constructor
CModel(CSkeletonAnimManager& skeletonAnimManager, CSimulation2& simulation);
CModel(CSimulation2& simulation);
// destructor
~CModel();
@ -187,21 +186,6 @@ public:
return m_BoneMatrices;
}
/**
* Load raw animation frame animation from given file, and build an
* animation specific to this model.
* @param pathname animation file to load
* @param name animation name (e.g. "idle")
* @param ID specific ID of the animation, to sync with props
* @param frequency influences the random choices
* @param speed animation speed as a factor of the default animation speed
* @param actionpos offset of 'action' event, in range [0, 1]
* @param actionpos2 offset of 'action2' event, in range [0, 1]
* @param sound offset of 'sound' event, in range [0, 1]
* @return new animation, or NULL on error
*/
CSkeletonAnim* BuildAnimation(const VfsPath& pathname, const CStr& name, const CStr& ID, int frequency, float speed, float actionpos, float actionpos2, float soundpos);
/**
* Add a prop to the model on the given point.
*/
@ -290,9 +274,6 @@ private:
* If m_AmmoPropPoint is not NULL, then the index in m_Props of the ammo prop
*/
size_t m_AmmoLoadedProp;
// manager object which can load animations for us
CSkeletonAnimManager& m_SkeletonAnimManager;
};
#endif

View File

@ -30,6 +30,7 @@
#include "graphics/ObjectManager.h"
#include "graphics/ParticleManager.h"
#include "graphics/SkeletonAnim.h"
#include "graphics/SkeletonAnimManager.h"
#include "graphics/TextureManager.h"
#include "lib/rand.h"
#include "ps/CLogger.h"
@ -48,9 +49,6 @@ CObjectEntry::CObjectEntry(const std::shared_ptr<CObjectBase>& base, CSimulation
CObjectEntry::~CObjectEntry()
{
for (const std::pair<const CStr, CSkeletonAnim*>& anim : m_Animations)
delete anim.second;
delete m_Model;
}
@ -130,7 +128,7 @@ bool CObjectEntry::BuildVariation(const std::vector<const std::set<CStr>*>& comp
}
// delete old model, create new
CModel* model = new CModel(objectManager.GetSkeletonAnimManager(), m_Simulation);
CModel* model = new CModel(m_Simulation);
delete m_Model;
m_Model = model;
model->SetMaterial(g_Renderer.GetSceneRenderer().GetMaterialManager().LoadMaterial(m_Base->m_Material));
@ -169,7 +167,7 @@ bool CObjectEntry::BuildVariation(const std::vector<const std::set<CStr>*>& comp
if (it->second.m_FileName.empty())
continue;
CSkeletonAnim* anim = model->BuildAnimation(
std::unique_ptr<CSkeletonAnim> anim = objectManager.GetSkeletonAnimManager().BuildAnimation(
it->second.m_FileName,
name,
it->second.m_ID,
@ -179,13 +177,13 @@ bool CObjectEntry::BuildVariation(const std::vector<const std::set<CStr>*>& comp
it->second.m_ActionPos2,
it->second.m_SoundPos);
if (anim)
m_Animations.insert(std::make_pair(name, anim));
m_Animations.emplace(name, std::move(anim));
}
// ensure there's always an idle animation
if (m_Animations.find("idle") == m_Animations.end())
{
CSkeletonAnim* anim = new CSkeletonAnim();
std::unique_ptr<CSkeletonAnim> anim = std::make_unique<CSkeletonAnim>();
anim->m_Name = "idle";
anim->m_ID = "";
anim->m_AnimDef = NULL;
@ -194,10 +192,10 @@ bool CObjectEntry::BuildVariation(const std::vector<const std::set<CStr>*>& comp
anim->m_ActionPos = 0.f;
anim->m_ActionPos2 = 0.f;
anim->m_SoundPos = 0.f;
m_Animations.insert(std::make_pair("idle", anim));
SkeletonAnimMap::const_iterator it = m_Animations.emplace("idle", std::move(anim));
// Ignore errors, since they're probably saying this is a non-animated model
model->SetAnimation(anim);
model->SetAnimation(it->second.get());
}
else
{
@ -302,7 +300,7 @@ std::vector<CSkeletonAnim*> CObjectEntry::GetAnimations(const CStr& animationNam
for (SkeletonAnimMap::const_iterator it = lower; it != upper; ++it)
{
if (ID.empty() || it->second->m_ID == ID)
anims.push_back(it->second);
anims.push_back(it->second.get());
}
if (anims.empty())
@ -310,7 +308,7 @@ std::vector<CSkeletonAnim*> CObjectEntry::GetAnimations(const CStr& animationNam
lower = m_Animations.lower_bound("idle");
upper = m_Animations.upper_bound("idle");
for (SkeletonAnimMap::const_iterator it = lower; it != upper; ++it)
anims.push_back(it->second);
anims.push_back(it->second.get());
}
ENSURE(!anims.empty());

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2021 Wildfire Games.
/* Copyright (C) 2022 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -25,6 +25,7 @@ class CObjectManager;
class CSimulation2;
#include <map>
#include <memory>
#include <set>
#include <vector>
@ -83,7 +84,7 @@ private:
CSimulation2& m_Simulation;
typedef std::multimap<CStr, CSkeletonAnim*> SkeletonAnimMap;
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?
};

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2021 Wildfire Games.
/* Copyright (C) 2022 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -25,8 +25,10 @@
#include "graphics/ColladaManager.h"
#include "graphics/Model.h"
#include "graphics/SkeletonAnim.h"
#include "graphics/SkeletonAnimDef.h"
#include "ps/CLogger.h"
#include "ps/CStr.h"
#include "ps/FileIo.h"
///////////////////////////////////////////////////////////////////////////////
@ -79,3 +81,40 @@ CSkeletonAnimDef* CSkeletonAnimManager::GetAnimation(const VfsPath& pathname)
// Add to map, NULL if failed to load - we won't try loading it again
return m_Animations.insert_or_assign(name, std::move(def)).first->second.get();
}
/**
* BuildAnimation: load raw animation frame animation from given file, and build a
* animation specific to this model
*/
std::unique_ptr<CSkeletonAnim> CSkeletonAnimManager::BuildAnimation(const VfsPath& pathname, const CStr8& name, const CStr8& ID, int frequency, float speed, float actionpos, float actionpos2, float soundpos)
{
CSkeletonAnimDef* def = GetAnimation(pathname);
if (!def)
return nullptr;
std::unique_ptr<CSkeletonAnim> anim = std::make_unique<CSkeletonAnim>();
anim->m_Name = name;
anim->m_ID = ID;
anim->m_Frequency = frequency;
anim->m_AnimDef = def;
anim->m_Speed = speed;
if (actionpos == -1.f)
anim->m_ActionPos = -1.f;
else
anim->m_ActionPos = actionpos * anim->m_AnimDef->GetDuration();
if (actionpos2 == -1.f)
anim->m_ActionPos2 = -1.f;
else
anim->m_ActionPos2 = actionpos2 * anim->m_AnimDef->GetDuration();
if (soundpos == -1.f)
anim->m_SoundPos = -1.f;
else
anim->m_SoundPos = soundpos * anim->m_AnimDef->GetDuration();
anim->m_ObjectBounds.SetEmpty();
return anim;
}

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2021 Wildfire Games.
/* Copyright (C) 2022 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -29,6 +29,8 @@
class CColladaManager;
class CSkeletonAnimDef;
class CSkeletonAnim;
class CStr8;
///////////////////////////////////////////////////////////////////////////////
// CSkeletonAnimManager : owner class of all skeleton anims - manages creation,
@ -45,6 +47,21 @@ public:
// refer to valid animation file
CSkeletonAnimDef* GetAnimation(const VfsPath& pathname);
/**
* Load raw animation frame animation from given file, and build an
* animation specific to this model.
* @param pathname animation file to load
* @param name animation name (e.g. "idle")
* @param ID specific ID of the animation, to sync with props
* @param frequency influences the random choices
* @param speed animation speed as a factor of the default animation speed
* @param actionpos offset of 'action' event, in range [0, 1]
* @param actionpos2 offset of 'action2' event, in range [0, 1]
* @param sound offset of 'sound' event, in range [0, 1]
* @return new animation, or NULL on error
*/
std::unique_ptr<CSkeletonAnim> BuildAnimation(const VfsPath& pathname, const CStr8& name, const CStr8& ID, int frequency, float speed, float actionpos, float actionpos2, float soundpos);
private:
// map of all known animations. Value is NULL if it failed to load.
std::unordered_map<VfsPath, std::unique_ptr<CSkeletonAnimDef>> m_Animations;