Add profiling, refactor Model animation ticking

Only tick animations that are marked active.
More work needs to be done in Ship.cpp to support this,
but it should enable us to have far more ships in one system.
master
Webster Sheets 2020-12-22 03:21:37 -05:00 committed by Webster Sheets
parent 993ed15d11
commit f5a9a64436
9 changed files with 85 additions and 16 deletions

View File

@ -479,6 +479,7 @@ void Frame::ClearMovement()
void Frame::UpdateOrbitRails(double time, double timestep)
{
PROFILE_SCOPED()
std::for_each(begin(s_frames), end(s_frames), [&time, &timestep](Frame &frame) {
frame.m_oldPos = frame.m_pos;
frame.m_oldAngDisplacement = frame.m_angSpeed * timestep;

View File

@ -183,6 +183,10 @@ void ModelBody::SetModel(const char *modelName)
//create model instance (some modelbodies, like missiles could avoid this)
m_model = Pi::FindModel(m_modelName)->MakeInstance();
m_idleAnimation = m_model->FindAnimation("idle");
// TODO: this isn't great, as animations will be ticked regardless of whether the modelbody
// is next to the player or on the other side of the solar system.
if (m_idleAnimation)
m_model->SetAnimationActive(m_model->FindAnimationIndex(m_idleAnimation), true);
SetClipRadius(m_model->GetDrawClipRadius());

View File

@ -843,6 +843,8 @@ void ModelViewer::OnModelChanged()
m_animations = m_model->GetAnimations();
m_currentAnimation = m_animations.size() ? m_animations.front() : nullptr;
if (m_currentAnimation)
m_model->SetAnimationActive(0, true);
m_patterns.clear();
m_currentPattern = 0;
@ -1056,6 +1058,8 @@ void ModelViewer::DrawModelOptions()
const bool selected = m_currentAnimation == anim;
if (ImGui::Selectable(anim->GetName().c_str(), selected) && !selected) {
// selected a new animation entry
m_model->SetAnimationActive(m_model->FindAnimationIndex(m_currentAnimation), false);
m_model->SetAnimationActive(m_model->FindAnimationIndex(anim), true);
m_currentAnimation = anim;
}
}

View File

@ -229,6 +229,10 @@ void Ship::Init()
m_hyperspaceCloud = 0;
m_landingGearAnimation = GetModel()->FindAnimation("gear_down");
// TODO: this causes the landing gear animation to be ticked for all ships regardless of whether it actually needs to be.
// Need smarter control regarding landing gear transitions.
if (m_landingGearAnimation)
GetModel()->SetAnimationActive(GetModel()->FindAnimationIndex(m_landingGearAnimation), true);
GetFixedGuns()->InitGuns(GetModel());
@ -979,6 +983,7 @@ void Ship::SetFrame(FrameId fId)
void Ship::TimeStepUpdate(const float timeStep)
{
PROFILE_SCOPED()
// If docked, station is responsible for updating position/orient of ship
// but we call this crap anyway and hope it doesn't do anything bad
@ -1210,6 +1215,7 @@ void Ship::UpdateFuel(const float timeStep)
void Ship::StaticUpdate(const float timeStep)
{
PROFILE_SCOPED()
// do player sounds before dead check, so they also turn off
if (IsType(ObjectType::PLAYER)) DoThrusterSounds();

View File

@ -953,6 +953,7 @@ static void hitCallback(CollisionContact *c)
// temporary one-point version
static void CollideWithTerrain(Body *body, float timeStep)
{
PROFILE_SCOPED()
if (!body->IsType(ObjectType::DYNAMICBODY))
return;
DynamicBody *dynBody = static_cast<DynamicBody *>(body);
@ -1016,6 +1017,7 @@ void Space::TimeStep(float step)
void Space::UpdateBodies()
{
PROFILE_SCOPED()
#ifndef NDEBUG
m_processingFinalizationQueue = true;
#endif

View File

@ -261,7 +261,7 @@ Model *BinaryConverter::CreateModel(const std::string &filename, Serializer::Rea
LoadAnimations(rd);
m_model->UpdateAnimations();
m_model->InitAnimations();
//m_model->CreateCollisionMesh();
if (m_patternsUsed) SetUpPatterns();

View File

@ -8,11 +8,11 @@
#include "LOD.h"
#include "Parser.h"
#include "SceneGraph.h"
#include "scenegraph/Animation.h"
#include "StringF.h"
#include "graphics/Renderer.h"
#include "graphics/RenderState.h"
#include "graphics/Renderer.h"
#include "graphics/TextureBuilder.h"
#include "scenegraph/Animation.h"
#include "utils.h"
#include <assimp/material.h>
#include <assimp/postprocess.h>
@ -303,7 +303,7 @@ namespace SceneGraph {
m_model->CreateCollisionMesh();
// Do an initial animation update to get all the animation transforms correct
m_model->UpdateAnimations();
m_model->InitAnimations();
//find usable pattern textures from the model directory
if (patternsUsed)

View File

@ -457,14 +457,45 @@ namespace SceneGraph {
for (AnimationContainer::const_iterator anim = m_animations.begin(); anim != m_animations.end(); ++anim) {
if ((*anim)->GetName() == name) return (*anim);
}
return 0;
return nullptr;
}
void Model::InitAnimations()
{
for (AnimationContainer::iterator anim = m_animations.begin(); anim != m_animations.end(); ++anim)
(*anim)->Interpolate();
}
void Model::UpdateAnimations()
{
// XXX WIP. Assuming animations are controlled manually by SetProgress.
for (AnimationContainer::iterator anim = m_animations.begin(); anim != m_animations.end(); ++anim)
(*anim)->Interpolate();
for (size_t i = 0; i < m_animations.size(); i++) {
if (m_activeAnimations & (1 << i))
m_animations[i]->Interpolate();
}
}
uint32_t Model::FindAnimationIndex(Animation *anim) const
{
for (size_t i = 0; i < m_animations.size(); i++) {
if (anim == m_animations[i]) return uint32_t(i);
}
return UINT32_MAX;
}
void Model::SetAnimationActive(uint32_t index, bool active)
{
if (index >= m_animations.size()) return;
if (active)
m_activeAnimations |= (1 << index);
else
m_activeAnimations &= ~(1 << index);
}
bool Model::GetAnimationActive(uint32_t index) const
{
if (index >= m_animations.size()) return false;
return m_activeAnimations & (1 << index);
}
void Model::SetThrust(const vector3f &lin, const vector3f &ang)
@ -531,9 +562,13 @@ namespace SceneGraph {
Json modelObj({}); // Create JSON object to contain model data.
Json animationArray = Json::array(); // Create JSON array to contain animation data.
for (auto i : m_animations)
animationArray.push_back(i->GetProgress());
Json activeArray = Json::array(); // Create JSON array to contain animation data.
for (size_t i = 0; i < m_animations.size(); i++) {
animationArray.push_back(m_animations[i]->GetProgress());
activeArray.push_back(GetAnimationActive(i));
}
modelObj["animations"] = animationArray; // Add animation array to model object.
modelObj["activeAnimations"] = animationArray;
modelObj["cur_pattern_index"] = m_curPatternIndex;
@ -546,14 +581,20 @@ namespace SceneGraph {
Json modelObj = jsonObj["model"];
Json animationArray = modelObj["animations"].get<Json::array_t>();
Json activeArray = modelObj["activeAnimations"];
if (m_animations.size() == animationArray.size()) {
unsigned int arrayIndex = 0;
for (auto i : m_animations)
i->SetProgress(animationArray[arrayIndex++]);
bool hasActive = activeArray.is_array();
for (auto i : m_animations) {
i->SetProgress(animationArray[arrayIndex]);
SetAnimationActive(arrayIndex, hasActive ? activeArray[arrayIndex].get<bool>() : true);
++arrayIndex;
}
} else {
Log::Info("Saved model '{}' has invalid animation data. The model file may have changed on disk.\n", m_name);
}
UpdateAnimations();
InitAnimations();
SetPattern(modelObj["cur_pattern_index"]);
} catch (Json::type_error &) {

View File

@ -107,7 +107,7 @@ namespace SceneGraph {
float GetDrawClipRadius() const { return m_boundingRadius; }
void SetDrawClipRadius(float clipRadius) { m_boundingRadius = clipRadius; }
void Render(const matrix4x4f &trans, const RenderData *rd = 0); //ModelNode can override RD
void Render(const matrix4x4f &trans, const RenderData *rd = 0); //ModelNode can override RD
void Render(const std::vector<matrix4x4f> &trans, const RenderData *rd = 0); //ModelNode can override RD
RefCountedPtr<CollMesh> CreateCollisionMesh();
@ -142,8 +142,18 @@ namespace SceneGraph {
bool SupportsDecals();
bool SupportsPatterns();
Animation *FindAnimation(const std::string &) const; //0 if not found
// update all animations once to ensure all transforms are correctly positioned
void InitAnimations();
// Get an animation matching the given name or return nullptr.
Animation *FindAnimation(const std::string &) const;
// Get the index of an animation in this container. If there is no such animation, returns UINT32_MAX.
uint32_t FindAnimationIndex(Animation *) const;
// Return a reference to all animations defined on this model.
const std::vector<Animation *> GetAnimations() const { return m_animations; }
// Mark an animation as actively updating. A maximum of 64 active animations are supported.
void SetAnimationActive(uint32_t index, bool active);
bool GetAnimationActive(uint32_t index) const;
// Update all active animations.
void UpdateAnimations();
Graphics::Renderer *GetRenderer() const { return m_renderer; }
@ -185,7 +195,8 @@ namespace SceneGraph {
Graphics::Renderer *m_renderer;
std::string m_name;
std::vector<Animation *> m_animations;
TagContainer m_tags; //named attachment points
uint64_t m_activeAnimations; // bitmask of actively ticking animations
TagContainer m_tags; //named attachment points
RenderData m_renderData;
//per-instance flavour data