Merge pull request #5530 from ZappoMan/RenderableModelEntityItemOptimization

optimizations to RenderableModelEntityItem::render()
This commit is contained in:
Brad Davis 2015-08-07 15:32:07 -07:00
commit 64fcd2da96
7 changed files with 50 additions and 27 deletions

View file

@ -91,6 +91,10 @@ QVector<FBXAnimationFrame> Animation::getFrames() const {
return _geometry.animationFrames; return _geometry.animationFrames;
} }
const QVector<FBXAnimationFrame>& Animation::getFramesReference() const {
return _geometry.animationFrames;
}
void Animation::setGeometry(const FBXGeometry& geometry) { void Animation::setGeometry(const FBXGeometry& geometry) {
_geometry = geometry; _geometry = geometry;
finishedLoading(true); finishedLoading(true);

View file

@ -57,6 +57,8 @@ public:
Q_INVOKABLE QStringList getJointNames() const; Q_INVOKABLE QStringList getJointNames() const;
Q_INVOKABLE QVector<FBXAnimationFrame> getFrames() const; Q_INVOKABLE QVector<FBXAnimationFrame> getFrames() const;
const QVector<FBXAnimationFrame>& getFramesReference() const;
protected: protected:

View file

@ -227,24 +227,30 @@ void RenderableModelEntityItem::render(RenderArgs* args) {
if (hasModel()) { if (hasModel()) {
if (_model) { if (_model) {
if (QUrl(getModelURL()) != _model->getURL()) { if (getModelURL() != _model->getURLAsString()) {
qDebug() << "Updating model URL: " << getModelURL(); qDebug() << "Updating model URL: " << getModelURL();
_model->setURL(getModelURL()); _model->setURL(getModelURL());
} }
render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene();
// check to see if when we added our models to the scene they were ready, if they were not ready, then // check to see if when we added our models to the scene they were ready, if they were not ready, then
// fix them up in the scene // fix them up in the scene
render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene();
render::PendingChanges pendingChanges;
if (_model->needsFixupInScene()) { if (_model->needsFixupInScene()) {
render::PendingChanges pendingChanges;
_model->removeFromScene(scene, pendingChanges); _model->removeFromScene(scene, pendingChanges);
render::Item::Status::Getters statusGetters; render::Item::Status::Getters statusGetters;
makeEntityItemStatusGetters(this, statusGetters); makeEntityItemStatusGetters(this, statusGetters);
_model->addToScene(scene, pendingChanges, statusGetters); _model->addToScene(scene, pendingChanges, statusGetters);
}
scene->enqueuePendingChanges(pendingChanges);
scene->enqueuePendingChanges(pendingChanges);
}
// FIXME: this seems like it could be optimized if we tracked our last known visible state in
// the renderable item. As it stands now the model checks it's visible/invisible state
// so most of the time we don't do anything in this function.
_model->setVisibleInScene(getVisible(), scene); _model->setVisibleInScene(getVisible(), scene);
} }
@ -269,7 +275,7 @@ void RenderableModelEntityItem::render(RenderArgs* args) {
} }
if (jointsMapped()) { if (jointsMapped()) {
QVector<glm::quat> frameData = getAnimationFrame(); auto frameData = getAnimationFrame();
for (int i = 0; i < frameData.size(); i++) { for (int i = 0; i < frameData.size(); i++) {
_model->setJointState(i, true, frameData[i]); _model->setJointState(i, true, frameData[i]);
} }

View file

@ -39,6 +39,7 @@ ModelEntityItem::ModelEntityItem(const EntityItemID& entityItemID, const EntityI
setProperties(properties); setProperties(properties);
_lastAnimated = usecTimestampNow(); _lastAnimated = usecTimestampNow();
_jointMappingCompleted = false; _jointMappingCompleted = false;
_lastKnownFrameIndex = -1;
_color[0] = _color[1] = _color[2] = 0; _color[0] = _color[1] = _color[2] = 0;
} }
@ -217,15 +218,17 @@ void ModelEntityItem::mapJoints(const QStringList& modelJointNames) {
} }
} }
QVector<glm::quat> ModelEntityItem::getAnimationFrame() { const QVector<glm::quat>& ModelEntityItem::getAnimationFrame() {
QVector<glm::quat> frameData;
if (!hasAnimation() || !_jointMappingCompleted) { if (!hasAnimation() || !_jointMappingCompleted) {
return frameData; return _lastKnownFrameData;
} }
AnimationPointer myAnimation = getAnimation(_animationURL); AnimationPointer myAnimation = getAnimation(_animationURL); // FIXME: this could be optimized
if (myAnimation && myAnimation->isLoaded()) { if (myAnimation && myAnimation->isLoaded()) {
QVector<FBXAnimationFrame> frames = myAnimation->getFrames();
const QVector<FBXAnimationFrame>& frames = myAnimation->getFramesReference(); // NOTE: getFrames() is too heavy
int frameCount = frames.size(); int frameCount = frames.size();
if (frameCount > 0) { if (frameCount > 0) {
int animationFrameIndex = (int)(glm::floor(getAnimationFrameIndex())) % frameCount; int animationFrameIndex = (int)(glm::floor(getAnimationFrameIndex())) % frameCount;
@ -233,18 +236,22 @@ QVector<glm::quat> ModelEntityItem::getAnimationFrame() {
animationFrameIndex = 0; animationFrameIndex = 0;
} }
QVector<glm::quat> rotations = frames[animationFrameIndex].rotations; if (animationFrameIndex != _lastKnownFrameIndex) {
_lastKnownFrameIndex = animationFrameIndex;
const QVector<glm::quat>& rotations = frames[animationFrameIndex].rotations;
frameData.resize(_jointMapping.size()); _lastKnownFrameData.resize(_jointMapping.size());
for (int j = 0; j < _jointMapping.size(); j++) { for (int j = 0; j < _jointMapping.size(); j++) {
int rotationIndex = _jointMapping[j]; int rotationIndex = _jointMapping[j];
if (rotationIndex != -1 && rotationIndex < rotations.size()) { if (rotationIndex != -1 && rotationIndex < rotations.size()) {
frameData[j] = rotations[rotationIndex]; _lastKnownFrameData[j] = rotations[rotationIndex];
}
} }
} }
} }
} }
return frameData; return _lastKnownFrameData;
} }
bool ModelEntityItem::isAnimatingSomething() const { bool ModelEntityItem::isAnimatingSomething() const {

View file

@ -106,7 +106,7 @@ public:
float getAnimationLastFrame() const { return _animationLoop.getLastFrame(); } float getAnimationLastFrame() const { return _animationLoop.getLastFrame(); }
void mapJoints(const QStringList& modelJointNames); void mapJoints(const QStringList& modelJointNames);
QVector<glm::quat> getAnimationFrame(); const QVector<glm::quat>& getAnimationFrame();
bool jointsMapped() const { return _jointMappingCompleted; } bool jointsMapped() const { return _jointMappingCompleted; }
bool getAnimationIsPlaying() const { return _animationLoop.isRunning(); } bool getAnimationIsPlaying() const { return _animationLoop.isRunning(); }
@ -123,6 +123,9 @@ public:
static void cleanupLoadedAnimations(); static void cleanupLoadedAnimations();
protected: protected:
QVector<glm::quat> _lastKnownFrameData;
int _lastKnownFrameIndex;
bool isAnimatingSomething() const; bool isAnimatingSomething() const;

View file

@ -54,6 +54,7 @@ static int modelPointerTypeId = qRegisterMetaType<QPointer<Model> >();
static int weakNetworkGeometryPointerTypeId = qRegisterMetaType<QWeakPointer<NetworkGeometry> >(); static int weakNetworkGeometryPointerTypeId = qRegisterMetaType<QWeakPointer<NetworkGeometry> >();
static int vec3VectorTypeId = qRegisterMetaType<QVector<glm::vec3> >(); static int vec3VectorTypeId = qRegisterMetaType<QVector<glm::vec3> >();
float Model::FAKE_DIMENSION_PLACEHOLDER = -1.0f; float Model::FAKE_DIMENSION_PLACEHOLDER = -1.0f;
#define HTTP_INVALID_COM "http://invalid.com"
Model::Model(RigPointer rig, QObject* parent) : Model::Model(RigPointer rig, QObject* parent) :
QObject(parent), QObject(parent),
@ -67,7 +68,8 @@ Model::Model(RigPointer rig, QObject* parent) :
_cauterizeBones(false), _cauterizeBones(false),
_lodDistance(0.0f), _lodDistance(0.0f),
_pupilDilation(0.0f), _pupilDilation(0.0f),
_url("http://invalid.com"), _url(HTTP_INVALID_COM),
_urlAsString(HTTP_INVALID_COM),
_isVisible(true), _isVisible(true),
_blendNumber(0), _blendNumber(0),
_appliedBlendNumber(0), _appliedBlendNumber(0),
@ -181,17 +183,12 @@ void Model::RenderPipelineLib::initLocations(gpu::ShaderPointer& program, Model:
locations.texcoordMatrices = program->getUniforms().findLocation("texcoordMatrices"); locations.texcoordMatrices = program->getUniforms().findLocation("texcoordMatrices");
locations.emissiveParams = program->getUniforms().findLocation("emissiveParams"); locations.emissiveParams = program->getUniforms().findLocation("emissiveParams");
locations.glowIntensity = program->getUniforms().findLocation("glowIntensity"); locations.glowIntensity = program->getUniforms().findLocation("glowIntensity");
locations.normalFittingMapUnit = program->getTextures().findLocation("normalFittingMap"); locations.normalFittingMapUnit = program->getTextures().findLocation("normalFittingMap");
locations.specularTextureUnit = program->getTextures().findLocation("specularMap"); locations.specularTextureUnit = program->getTextures().findLocation("specularMap");
locations.emissiveTextureUnit = program->getTextures().findLocation("emissiveMap"); locations.emissiveTextureUnit = program->getTextures().findLocation("emissiveMap");
locations.materialBufferUnit = program->getBuffers().findLocation("materialBuffer"); locations.materialBufferUnit = program->getBuffers().findLocation("materialBuffer");
locations.lightBufferUnit = program->getBuffers().findLocation("lightBuffer"); locations.lightBufferUnit = program->getBuffers().findLocation("lightBuffer");
locations.clusterMatrices = program->getUniforms().findLocation("clusterMatrices"); locations.clusterMatrices = program->getUniforms().findLocation("clusterMatrices");
locations.clusterIndices = program->getInputs().findLocation("inSkinClusterIndex"); locations.clusterIndices = program->getInputs().findLocation("inSkinClusterIndex");
locations.clusterWeights = program->getInputs().findLocation("inSkinClusterWeight"); locations.clusterWeights = program->getInputs().findLocation("inSkinClusterWeight");
} }
@ -1083,6 +1080,7 @@ void Model::setURL(const QUrl& url, const QUrl& fallback, bool retainCurrent, bo
invalidCalculatedMeshBoxes(); invalidCalculatedMeshBoxes();
_url = url; _url = url;
_urlAsString = _url.toString();
onInvalidate(); onInvalidate();
@ -1866,8 +1864,9 @@ void Model::pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, f
batch._glUniform1f(locations->glowIntensity, DEFAULT_GLOW_INTENSITY); batch._glUniform1f(locations->glowIntensity, DEFAULT_GLOW_INTENSITY);
} }
if ((locations->normalFittingMapUnit > -1)) { if ((locations->normalFittingMapUnit > -1)) {
batch.setResourceTexture(locations->normalFittingMapUnit, DependencyManager::get<TextureCache>()->getNormalFittingTexture()); batch.setResourceTexture(locations->normalFittingMapUnit,
DependencyManager::get<TextureCache>()->getNormalFittingTexture());
} }
} }

View file

@ -74,6 +74,7 @@ public:
Q_INVOKABLE void setURL(const QUrl& url, const QUrl& fallback = QUrl(), Q_INVOKABLE void setURL(const QUrl& url, const QUrl& fallback = QUrl(),
bool retainCurrent = false, bool delayLoad = false); bool retainCurrent = false, bool delayLoad = false);
const QUrl& getURL() const { return _url; } const QUrl& getURL() const { return _url; }
const QString& getURLAsString() const { return _urlAsString; }
// new Scene/Engine rendering support // new Scene/Engine rendering support
void setVisibleInScene(bool newValue, std::shared_ptr<render::Scene> scene); void setVisibleInScene(bool newValue, std::shared_ptr<render::Scene> scene);
@ -328,6 +329,7 @@ private:
QVector<float> _blendshapeCoefficients; QVector<float> _blendshapeCoefficients;
QUrl _url; QUrl _url;
QString _urlAsString;
QUrl _collisionUrl; QUrl _collisionUrl;
bool _isVisible; bool _isVisible;