Merge pull request #13979 from AndrewMeadows/game-loop-optimizations-001

minor bug fix and optimization in ModelEntity animation
This commit is contained in:
Sam Gateau 2018-10-19 17:02:48 -07:00 committed by GitHub
commit 6005b934ad
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 49 additions and 58 deletions

View file

@ -22,7 +22,7 @@
class Animation; class Animation;
typedef QSharedPointer<Animation> AnimationPointer; using AnimationPointer = QSharedPointer<Animation>;
class AnimationCache : public ResourceCache, public Dependency { class AnimationCache : public ResourceCache, public Dependency {
Q_OBJECT Q_OBJECT

View file

@ -975,14 +975,21 @@ QStringList RenderableModelEntityItem::getJointNames() const {
return result; return result;
} }
// FIXME: deprecated; remove >= RC67 void RenderableModelEntityItem::setAnimationURL(const QString& url) {
bool RenderableModelEntityItem::getMeshes(MeshProxyList& result) { QString oldURL = getAnimationURL();
auto model = getModel(); ModelEntityItem::setAnimationURL(url);
if (!model || !model->isLoaded()) { if (oldURL != getAnimationURL()) {
return false; _needsAnimationReset = true;
} }
BLOCKING_INVOKE_METHOD(model.get(), "getMeshes", Q_RETURN_ARG(MeshProxyList, result)); }
return !result.isEmpty();
bool RenderableModelEntityItem::needsAnimationReset() const {
return _needsAnimationReset;
}
QString RenderableModelEntityItem::getAnimationURLAndReset() {
_needsAnimationReset = false;
return getAnimationURL();
} }
scriptable::ScriptableModelBase render::entities::ModelEntityRenderer::getScriptableModel() { scriptable::ScriptableModelBase render::entities::ModelEntityRenderer::getScriptableModel() {
@ -1068,6 +1075,13 @@ void RenderableModelEntityItem::copyAnimationJointDataToModel() {
} }
} }
bool RenderableModelEntityItem::readyToAnimate() const {
return resultWithReadLock<bool>([&] {
float firstFrame = _animationProperties.getFirstFrame();
return (firstFrame >= 0.0f) && (firstFrame <= _animationProperties.getLastFrame());
});
}
using namespace render; using namespace render;
using namespace render::entities; using namespace render::entities;
@ -1169,7 +1183,6 @@ void ModelEntityRenderer::animate(const TypedEntityPointer& entity) {
} }
} else if (index < animationJointNames.size()) { } else if (index < animationJointNames.size()) {
QString jointName = fbxJoints[index].name; // Pushing this here so its not done on every entity, with the exceptions of those allowing for translation QString jointName = fbxJoints[index].name; // Pushing this here so its not done on every entity, with the exceptions of those allowing for translation
if (originalFbxIndices.contains(jointName)) { if (originalFbxIndices.contains(jointName)) {
// Making sure the joint names exist in the original model the animation is trying to apply onto. If they do, then remap and get it's translation. // Making sure the joint names exist in the original model the animation is trying to apply onto. If they do, then remap and get it's translation.
int remappedIndex = originalFbxIndices[jointName] - 1; // JointIndeces seem to always start from 1 and the found index is always 1 higher than actual. int remappedIndex = originalFbxIndices[jointName] - 1; // JointIndeces seem to always start from 1 and the found index is always 1 higher than actual.
@ -1477,14 +1490,17 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
if (_animating) { if (_animating) {
DETAILED_PROFILE_RANGE(simulation_physics, "Animate"); DETAILED_PROFILE_RANGE(simulation_physics, "Animate");
if (!jointsMapped()) { if (_animation && entity->needsAnimationReset()) {
mapJoints(entity, model->getJointNames()); //(_animation->getURL().toString() != entity->getAnimationURL())) { // bad check
//else the joint have been mapped before but we have a new animation to load // the joints have been mapped before but we have a new animation to load
} else if (_animation && (_animation->getURL().toString() != entity->getAnimationURL())) { _animation.reset();
_jointMappingCompleted = false; _jointMappingCompleted = false;
mapJoints(entity, model->getJointNames());
} }
if (!(entity->getAnimationFirstFrame() < 0) && !(entity->getAnimationFirstFrame() > entity->getAnimationLastFrame())) {
if (!_jointMappingCompleted) {
mapJoints(entity, model);
}
if (entity->readyToAnimate()) {
animate(entity); animate(entity);
} }
emit requestRenderUpdate(); emit requestRenderUpdate();
@ -1518,19 +1534,20 @@ void ModelEntityRenderer::doRender(RenderArgs* args) {
#endif #endif
} }
void ModelEntityRenderer::mapJoints(const TypedEntityPointer& entity, const QStringList& modelJointNames) { void ModelEntityRenderer::mapJoints(const TypedEntityPointer& entity, const ModelPointer& model) {
// if we don't have animation, or we're already joint mapped then bail early // if we don't have animation, or we're already joint mapped then bail early
if (!entity->hasAnimation() || jointsMapped()) { if (!entity->hasAnimation()) {
return; return;
} }
if (!_animation || _animation->getURL().toString() != entity->getAnimationURL()) { if (!_animation) {
_animation = DependencyManager::get<AnimationCache>()->getAnimation(entity->getAnimationURL()); _animation = DependencyManager::get<AnimationCache>()->getAnimation(entity->getAnimationURLAndReset());
} }
if (_animation && _animation->isLoaded()) { if (_animation && _animation->isLoaded()) {
QStringList animationJointNames = _animation->getJointNames(); QStringList animationJointNames = _animation->getJointNames();
auto modelJointNames = model->getJointNames();
if (modelJointNames.size() > 0 && animationJointNames.size() > 0) { if (modelJointNames.size() > 0 && animationJointNames.size() > 0) {
_jointMapping.resize(modelJointNames.size()); _jointMapping.resize(modelJointNames.size());
for (int i = 0; i < modelJointNames.size(); i++) { for (int i = 0; i < modelJointNames.size(); i++) {

View file

@ -112,21 +112,25 @@ public:
virtual int getJointIndex(const QString& name) const override; virtual int getJointIndex(const QString& name) const override;
virtual QStringList getJointNames() const override; virtual QStringList getJointNames() const override;
bool getMeshes(MeshProxyList& result) override; // deprecated void setAnimationURL(const QString& url) override;
bool needsAnimationReset() const;
QString getAnimationURLAndReset();
private: private:
bool needsUpdateModelBounds() const; bool needsUpdateModelBounds() const;
void autoResizeJointArrays(); void autoResizeJointArrays();
void copyAnimationJointDataToModel(); void copyAnimationJointDataToModel();
bool readyToAnimate() const;
void getCollisionGeometryResource(); void getCollisionGeometryResource();
GeometryResource::Pointer _compoundShapeResource; GeometryResource::Pointer _compoundShapeResource;
bool _jointMapCompleted { false };
bool _originalTexturesRead { false };
std::vector<int> _jointMap; std::vector<int> _jointMap;
QVariantMap _originalTextures; QVariantMap _originalTextures;
bool _jointMapCompleted { false };
bool _originalTexturesRead { false };
bool _dimensionsInitialized { true }; bool _dimensionsInitialized { true };
bool _needsJointSimulation { false }; bool _needsJointSimulation { false };
bool _needsAnimationReset { false };
}; };
namespace render { namespace entities { namespace render { namespace entities {
@ -167,8 +171,7 @@ protected:
private: private:
void animate(const TypedEntityPointer& entity); void animate(const TypedEntityPointer& entity);
void mapJoints(const TypedEntityPointer& entity, const QStringList& modelJointNames); void mapJoints(const TypedEntityPointer& entity, const ModelPointer& model);
bool jointsMapped() const { return _jointMappingCompleted; }
// Transparency is handled in ModelMeshPartPayload // Transparency is handled in ModelMeshPartPayload
virtual bool isTransparent() const override { return false; } virtual bool isTransparent() const override { return false; }

View file

@ -629,30 +629,6 @@ bool ModelEntityItem::getAnimationHold() const {
}); });
} }
void ModelEntityItem::setAnimationFirstFrame(float firstFrame) {
withWriteLock([&] {
_animationProperties.setFirstFrame(firstFrame);
});
}
float ModelEntityItem::getAnimationFirstFrame() const {
return resultWithReadLock<float>([&] {
return _animationProperties.getFirstFrame();
});
}
void ModelEntityItem::setAnimationLastFrame(float lastFrame) {
withWriteLock([&] {
_animationProperties.setLastFrame(lastFrame);
});
}
float ModelEntityItem::getAnimationLastFrame() const {
return resultWithReadLock<float>([&] {
return _animationProperties.getLastFrame();
});
}
bool ModelEntityItem::getAnimationIsPlaying() const { bool ModelEntityItem::getAnimationIsPlaying() const {
return resultWithReadLock<bool>([&] { return resultWithReadLock<bool>([&] {
return _animationProperties.getRunning(); return _animationProperties.getRunning();

View file

@ -79,9 +79,10 @@ public:
// Animation related items... // Animation related items...
AnimationPropertyGroup getAnimationProperties() const; AnimationPropertyGroup getAnimationProperties() const;
// TODO: audit and remove unused Animation accessors
bool hasAnimation() const; bool hasAnimation() const;
QString getAnimationURL() const; QString getAnimationURL() const;
void setAnimationURL(const QString& url); virtual void setAnimationURL(const QString& url);
void setAnimationCurrentFrame(float value); void setAnimationCurrentFrame(float value);
void setAnimationIsPlaying(bool value); void setAnimationIsPlaying(bool value);
@ -99,12 +100,6 @@ public:
void setRelayParentJoints(bool relayJoints); void setRelayParentJoints(bool relayJoints);
bool getRelayParentJoints() const; bool getRelayParentJoints() const;
void setAnimationFirstFrame(float firstFrame);
float getAnimationFirstFrame() const;
void setAnimationLastFrame(float lastFrame);
float getAnimationLastFrame() const;
bool getAnimationIsPlaying() const; bool getAnimationIsPlaying() const;
float getAnimationCurrentFrame() const; float getAnimationCurrentFrame() const;
float getAnimationFPS() const; float getAnimationFPS() const;