Merge pull request #9358 from AndrewMeadows/model-cleanup

minor cleanup for Model rendering code
This commit is contained in:
samcake 2017-01-12 14:30:16 -08:00 committed by GitHub
commit ca53235d54
6 changed files with 49 additions and 56 deletions

View file

@ -37,7 +37,7 @@ int SoftAttachmentModel::getJointIndexOverride(int i) const {
// virtual // virtual
// use the _rigOverride matrices instead of the Model::_rig // use the _rigOverride matrices instead of the Model::_rig
void SoftAttachmentModel::updateClusterMatrices(glm::vec3 modelPosition, glm::quat modelOrientation) { void SoftAttachmentModel::updateClusterMatrices() {
if (!_needsUpdateClusterMatrices) { if (!_needsUpdateClusterMatrices) {
return; return;
} }
@ -45,7 +45,6 @@ void SoftAttachmentModel::updateClusterMatrices(glm::vec3 modelPosition, glm::qu
const FBXGeometry& geometry = getFBXGeometry(); const FBXGeometry& geometry = getFBXGeometry();
glm::mat4 modelToWorld = glm::mat4_cast(modelOrientation);
for (int i = 0; i < _meshStates.size(); i++) { for (int i = 0; i < _meshStates.size(); i++) {
MeshState& state = _meshStates[i]; MeshState& state = _meshStates[i];
const FBXMesh& mesh = geometry.meshes.at(i); const FBXMesh& mesh = geometry.meshes.at(i);
@ -53,7 +52,7 @@ void SoftAttachmentModel::updateClusterMatrices(glm::vec3 modelPosition, glm::qu
for (int j = 0; j < mesh.clusters.size(); j++) { for (int j = 0; j < mesh.clusters.size(); j++) {
const FBXCluster& cluster = mesh.clusters.at(j); const FBXCluster& cluster = mesh.clusters.at(j);
// TODO: cache these look ups as an optimization // TODO: cache these look-ups as an optimization
int jointIndexOverride = getJointIndexOverride(cluster.jointIndex); int jointIndexOverride = getJointIndexOverride(cluster.jointIndex);
glm::mat4 jointMatrix; glm::mat4 jointMatrix;
if (jointIndexOverride >= 0 && jointIndexOverride < _rigOverride->getJointStateCount()) { if (jointIndexOverride >= 0 && jointIndexOverride < _rigOverride->getJointStateCount()) {
@ -61,7 +60,13 @@ void SoftAttachmentModel::updateClusterMatrices(glm::vec3 modelPosition, glm::qu
} else { } else {
jointMatrix = _rig->getJointTransform(cluster.jointIndex); jointMatrix = _rig->getJointTransform(cluster.jointIndex);
} }
state.clusterMatrices[j] = modelToWorld * jointMatrix * cluster.inverseBindMatrix; #if GLM_ARCH & GLM_ARCH_SSE2
glm::mat4 out, inverseBindMatrix = cluster.inverseBindMatrix;
glm_mat4_mul((glm_vec4*)&jointMatrix, (glm_vec4*)&inverseBindMatrix, (glm_vec4*)&out);
state.clusterMatrices[j] = out;
#else
state.clusterMatrices[j] = jointMatrix * cluster.inverseBindMatrix;
#endif
} }
// Once computed the cluster matrices, update the buffer(s) // Once computed the cluster matrices, update the buffer(s)

View file

@ -31,7 +31,7 @@ public:
~SoftAttachmentModel(); ~SoftAttachmentModel();
virtual void updateRig(float deltaTime, glm::mat4 parentTransform) override; virtual void updateRig(float deltaTime, glm::mat4 parentTransform) override;
virtual void updateClusterMatrices(glm::vec3 modelPosition, glm::quat modelOrientation) override; virtual void updateClusterMatrices() override;
protected: protected:
int getJointIndexOverride(int i) const; int getJointIndexOverride(int i) const;

View file

@ -63,8 +63,7 @@ void MeshPartPayload::updateMeshPart(const std::shared_ptr<const model::Mesh>& d
void MeshPartPayload::updateTransform(const Transform& transform, const Transform& offsetTransform) { void MeshPartPayload::updateTransform(const Transform& transform, const Transform& offsetTransform) {
_transform = transform; _transform = transform;
_offsetTransform = offsetTransform; Transform::mult(_drawTransform, _transform, offsetTransform);
Transform::mult(_drawTransform, _transform, _offsetTransform);
_worldBound = _localBound; _worldBound = _localBound;
_worldBound.transform(_drawTransform); _worldBound.transform(_drawTransform);
} }
@ -360,8 +359,8 @@ void ModelMeshPartPayload::notifyLocationChanged() {
} }
void ModelMeshPartPayload::updateTransformForSkinnedMesh(const Transform& transform, const Transform& offsetTransform, const QVector<glm::mat4>& clusterMatrices) { void ModelMeshPartPayload::updateTransformForSkinnedMesh(const Transform& transform, const QVector<glm::mat4>& clusterMatrices) {
ModelMeshPartPayload::updateTransform(transform, offsetTransform); _transform = transform;
if (clusterMatrices.size() > 0) { if (clusterMatrices.size() > 0) {
_worldBound = AABox(); _worldBound = AABox();
@ -371,8 +370,10 @@ void ModelMeshPartPayload::updateTransformForSkinnedMesh(const Transform& transf
_worldBound += clusterBound; _worldBound += clusterBound;
} }
// clusterMatrix has world rotation but not world translation. _worldBound.transform(transform);
_worldBound.translate(transform.getTranslation()); if (clusterMatrices.size() == 1) {
_transform = _transform.worldTransform(Transform(clusterMatrices[0]));
}
} }
} }
@ -520,23 +521,15 @@ void ModelMeshPartPayload::bindTransform(gpu::Batch& batch, const ShapePipeline:
// Still relying on the raw data from the model // Still relying on the raw data from the model
const Model::MeshState& state = _model->_meshStates.at(_meshIndex); const Model::MeshState& state = _model->_meshStates.at(_meshIndex);
Transform transform;
if (state.clusterBuffer) { if (state.clusterBuffer) {
if (canCauterize && _model->getCauterizeBones()) { if (canCauterize && _model->getCauterizeBones()) {
batch.setUniformBuffer(ShapePipeline::Slot::BUFFER::SKINNING, state.cauterizedClusterBuffer); batch.setUniformBuffer(ShapePipeline::Slot::BUFFER::SKINNING, state.cauterizedClusterBuffer);
} else { } else {
batch.setUniformBuffer(ShapePipeline::Slot::BUFFER::SKINNING, state.clusterBuffer); batch.setUniformBuffer(ShapePipeline::Slot::BUFFER::SKINNING, state.clusterBuffer);
} }
} else {
if (canCauterize && _model->getCauterizeBones()) {
transform = Transform(state.cauterizedClusterMatrices[0]);
} else {
transform = Transform(state.clusterMatrices[0]);
}
} }
transform.preTranslate(_transform.getTranslation()); batch.setModelTransform(_transform);
batch.setModelTransform(transform);
} }
void ModelMeshPartPayload::startFade() { void ModelMeshPartPayload::startFade() {
@ -569,8 +562,7 @@ void ModelMeshPartPayload::render(RenderArgs* args) const {
return; return;
} }
// When an individual mesh parts like this finishes its fade, we will mark the Model as
// When an individual mesh parts like this finishes its fade, we will mark the Model as
// having render items that need updating // having render items that need updating
bool nextIsFading = _isFading ? isStillFading() : false; bool nextIsFading = _isFading ? isStillFading() : false;
bool startFading = !_isFading && !_hasFinishedFade && _hasStartedFade; bool startFading = !_isFading && !_hasFinishedFade && _hasStartedFade;
@ -592,7 +584,7 @@ void ModelMeshPartPayload::render(RenderArgs* args) const {
// Bind the model transform and the skinCLusterMatrices if needed // Bind the model transform and the skinCLusterMatrices if needed
bool canCauterize = args->_renderMode != RenderArgs::SHADOW_RENDER_MODE; bool canCauterize = args->_renderMode != RenderArgs::SHADOW_RENDER_MODE;
_model->updateClusterMatrices(_transform.getTranslation(), _transform.getRotation()); _model->updateClusterMatrices();
bindTransform(batch, locations, canCauterize); bindTransform(batch, locations, canCauterize);
//Bind the index buffer and vertex buffer and Blend shapes if needed //Bind the index buffer and vertex buffer and Blend shapes if needed

View file

@ -34,7 +34,7 @@ public:
virtual void updateMeshPart(const std::shared_ptr<const model::Mesh>& drawMesh, int partIndex); virtual void updateMeshPart(const std::shared_ptr<const model::Mesh>& drawMesh, int partIndex);
virtual void notifyLocationChanged() {} virtual void notifyLocationChanged() {}
virtual void updateTransform(const Transform& transform, const Transform& offsetTransform); void updateTransform(const Transform& transform, const Transform& offsetTransform);
virtual void updateMaterial(model::MaterialPointer drawMaterial); virtual void updateMaterial(model::MaterialPointer drawMaterial);
@ -56,13 +56,12 @@ public:
model::Mesh::Part _drawPart; model::Mesh::Part _drawPart;
std::shared_ptr<const model::Material> _drawMaterial; std::shared_ptr<const model::Material> _drawMaterial;
model::Box _localBound; model::Box _localBound;
Transform _drawTransform; Transform _drawTransform;
Transform _transform; Transform _transform;
Transform _offsetTransform;
mutable model::Box _worldBound; mutable model::Box _worldBound;
bool _hasColorAttrib = false; bool _hasColorAttrib = false;
size_t getVerticesCount() const { return _drawMesh ? _drawMesh->getNumVertices() : 0; } size_t getVerticesCount() const { return _drawMesh ? _drawMesh->getNumVertices() : 0; }
@ -86,7 +85,7 @@ public:
typedef Payload::DataPointer Pointer; typedef Payload::DataPointer Pointer;
void notifyLocationChanged() override; void notifyLocationChanged() override;
void updateTransformForSkinnedMesh(const Transform& transform, const Transform& offsetTransform, const QVector<glm::mat4>& clusterMatrices); void updateTransformForSkinnedMesh(const Transform& transform, const QVector<glm::mat4>& clusterMatrices);
// Entity fade in // Entity fade in
void startFade(); void startFade();
@ -101,7 +100,7 @@ public:
// ModelMeshPartPayload functions to perform render // ModelMeshPartPayload functions to perform render
void bindMesh(gpu::Batch& batch) const override; void bindMesh(gpu::Batch& batch) const override;
void bindTransform(gpu::Batch& batch, const render::ShapePipeline::LocationsPointer locations, bool canCauterize) const override; void bindTransform(gpu::Batch& batch, const render::ShapePipeline::LocationsPointer locations, bool canCauterize = true) const override;
void initCache(); void initCache();

View file

@ -92,7 +92,6 @@ Model::Model(RigPointer rig, QObject* parent) :
_snapModelToRegistrationPoint(false), _snapModelToRegistrationPoint(false),
_snappedToRegistrationPoint(false), _snappedToRegistrationPoint(false),
_cauterizeBones(false), _cauterizeBones(false),
_pupilDilation(0.0f),
_url(HTTP_INVALID_COM), _url(HTTP_INVALID_COM),
_isVisible(true), _isVisible(true),
_blendNumber(0), _blendNumber(0),
@ -217,23 +216,17 @@ void Model::updateRenderItems() {
render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene(); render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene();
Transform modelTransform; Transform modelTransform;
modelTransform.setScale(scale);
modelTransform.setTranslation(self->_translation); modelTransform.setTranslation(self->_translation);
modelTransform.setRotation(self->_rotation); modelTransform.setRotation(self->_rotation);
Transform modelMeshOffset; Transform scaledModelTransform(modelTransform);
if (self->isLoaded()) { scaledModelTransform.setScale(scale);
// includes model offset and unitScale.
modelMeshOffset = Transform(self->_rig->getGeometryToRigTransform());
} else {
modelMeshOffset.postTranslate(self->_offset);
}
uint32_t deleteGeometryCounter = self->_deleteGeometryCounter; uint32_t deleteGeometryCounter = self->_deleteGeometryCounter;
render::PendingChanges pendingChanges; render::PendingChanges pendingChanges;
foreach (auto itemID, self->_modelMeshRenderItems.keys()) { foreach (auto itemID, self->_modelMeshRenderItems.keys()) {
pendingChanges.updateItem<ModelMeshPartPayload>(itemID, [modelTransform, modelMeshOffset, deleteGeometryCounter](ModelMeshPartPayload& data) { pendingChanges.updateItem<ModelMeshPartPayload>(itemID, [modelTransform, deleteGeometryCounter](ModelMeshPartPayload& data) {
if (data._model && data._model->isLoaded()) { if (data._model && data._model->isLoaded()) {
if (!data.hasStartedFade() && data._model->getGeometry()->areTexturesLoaded()) { if (!data.hasStartedFade() && data._model->getGeometry()->areTexturesLoaded()) {
data.startFade(); data.startFade();
@ -241,11 +234,11 @@ void Model::updateRenderItems() {
// Ensure the model geometry was not reset between frames // Ensure the model geometry was not reset between frames
if (deleteGeometryCounter == data._model->_deleteGeometryCounter) { if (deleteGeometryCounter == data._model->_deleteGeometryCounter) {
// lazy update of cluster matrices used for rendering. We need to update them here, so we can correctly update the bounding box. // lazy update of cluster matrices used for rendering. We need to update them here, so we can correctly update the bounding box.
data._model->updateClusterMatrices(modelTransform.getTranslation(), modelTransform.getRotation()); data._model->updateClusterMatrices();
// update the model transform and bounding box for this render item. // update the model transform and bounding box for this render item.
const Model::MeshState& state = data._model->_meshStates.at(data._meshIndex); const Model::MeshState& state = data._model->_meshStates.at(data._meshIndex);
data.updateTransformForSkinnedMesh(modelTransform, modelMeshOffset, state.clusterMatrices); data.updateTransformForSkinnedMesh(modelTransform, state.clusterMatrices);
} }
} }
}); });
@ -255,9 +248,9 @@ void Model::updateRenderItems() {
Transform collisionMeshOffset; Transform collisionMeshOffset;
collisionMeshOffset.setIdentity(); collisionMeshOffset.setIdentity();
foreach (auto itemID, self->_collisionRenderItems.keys()) { foreach (auto itemID, self->_collisionRenderItems.keys()) {
pendingChanges.updateItem<MeshPartPayload>(itemID, [modelTransform, collisionMeshOffset](MeshPartPayload& data) { pendingChanges.updateItem<MeshPartPayload>(itemID, [scaledModelTransform, collisionMeshOffset](MeshPartPayload& data) {
// update the model transform for this render item. // update the model transform for this render item.
data.updateTransform(modelTransform, collisionMeshOffset); data.updateTransform(scaledModelTransform, collisionMeshOffset);
}); });
} }
@ -295,6 +288,7 @@ bool Model::updateGeometry() {
if (_rig->jointStatesEmpty() && getFBXGeometry().joints.size() > 0) { if (_rig->jointStatesEmpty() && getFBXGeometry().joints.size() > 0) {
initJointStates(); initJointStates();
assert(_meshStates.empty());
const FBXGeometry& fbxGeometry = getFBXGeometry(); const FBXGeometry& fbxGeometry = getFBXGeometry();
foreach (const FBXMesh& mesh, fbxGeometry.meshes) { foreach (const FBXMesh& mesh, fbxGeometry.meshes) {
@ -304,6 +298,9 @@ bool Model::updateGeometry() {
_meshStates.append(state); _meshStates.append(state);
// Note: we add empty buffers for meshes that lack blendshapes so we can access the buffers by index
// later in ModelMeshPayload, however the vast majority of meshes will not have them.
// TODO? make _blendedVertexBuffers a map instead of vector and only add for meshes with blendshapes?
auto buffer = std::make_shared<gpu::Buffer>(); auto buffer = std::make_shared<gpu::Buffer>();
if (!mesh.blendshapes.isEmpty()) { if (!mesh.blendshapes.isEmpty()) {
buffer->resize((mesh.vertices.size() + mesh.normals.size()) * sizeof(glm::vec3)); buffer->resize((mesh.vertices.size() + mesh.normals.size()) * sizeof(glm::vec3));
@ -1152,7 +1149,7 @@ void Model::simulateInternal(float deltaTime) {
} }
// virtual // virtual
void Model::updateClusterMatrices(glm::vec3 modelPosition, glm::quat modelOrientation) { void Model::updateClusterMatrices() {
PerformanceTimer perfTimer("Model::updateClusterMatrices"); PerformanceTimer perfTimer("Model::updateClusterMatrices");
if (!_needsUpdateClusterMatrices || !isLoaded()) { if (!_needsUpdateClusterMatrices || !isLoaded()) {
@ -1167,7 +1164,6 @@ void Model::updateClusterMatrices(glm::vec3 modelPosition, glm::quat modelOrient
glm::vec4(0.0f, 0.0f, 0.0f, 1.0f)); glm::vec4(0.0f, 0.0f, 0.0f, 1.0f));
auto cauterizeMatrix = _rig->getJointTransform(geometry.neckJointIndex) * zeroScale; auto cauterizeMatrix = _rig->getJointTransform(geometry.neckJointIndex) * zeroScale;
glm::mat4 modelToWorld = glm::mat4_cast(modelOrientation);
for (int i = 0; i < _meshStates.size(); i++) { for (int i = 0; i < _meshStates.size(); i++) {
MeshState& state = _meshStates[i]; MeshState& state = _meshStates[i];
const FBXMesh& mesh = geometry.meshes.at(i); const FBXMesh& mesh = geometry.meshes.at(i);
@ -1175,12 +1171,11 @@ void Model::updateClusterMatrices(glm::vec3 modelPosition, glm::quat modelOrient
const FBXCluster& cluster = mesh.clusters.at(j); const FBXCluster& cluster = mesh.clusters.at(j);
auto jointMatrix = _rig->getJointTransform(cluster.jointIndex); auto jointMatrix = _rig->getJointTransform(cluster.jointIndex);
#if GLM_ARCH & GLM_ARCH_SSE2 #if GLM_ARCH & GLM_ARCH_SSE2
glm::mat4 temp, out, inverseBindMatrix = cluster.inverseBindMatrix; glm::mat4 out, inverseBindMatrix = cluster.inverseBindMatrix;
glm_mat4_mul((glm_vec4*)&modelToWorld, (glm_vec4*)&jointMatrix, (glm_vec4*)&temp); glm_mat4_mul((glm_vec4*)&jointMatrix, (glm_vec4*)&inverseBindMatrix, (glm_vec4*)&out);
glm_mat4_mul((glm_vec4*)&temp, (glm_vec4*)&inverseBindMatrix, (glm_vec4*)&out);
state.clusterMatrices[j] = out; state.clusterMatrices[j] = out;
#else #else
state.clusterMatrices[j] = modelToWorld * jointMatrix * cluster.inverseBindMatrix; state.clusterMatrices[j] = jointMatrix * cluster.inverseBindMatrix;
#endif #endif
// as an optimization, don't build cautrizedClusterMatrices if the boneSet is empty. // as an optimization, don't build cautrizedClusterMatrices if the boneSet is empty.
@ -1188,7 +1183,13 @@ void Model::updateClusterMatrices(glm::vec3 modelPosition, glm::quat modelOrient
if (_cauterizeBoneSet.find(cluster.jointIndex) != _cauterizeBoneSet.end()) { if (_cauterizeBoneSet.find(cluster.jointIndex) != _cauterizeBoneSet.end()) {
jointMatrix = cauterizeMatrix; jointMatrix = cauterizeMatrix;
} }
state.cauterizedClusterMatrices[j] = modelToWorld * jointMatrix * cluster.inverseBindMatrix; #if GLM_ARCH & GLM_ARCH_SSE2
glm::mat4 out, inverseBindMatrix = cluster.inverseBindMatrix;
glm_mat4_mul((glm_vec4*)&jointMatrix, (glm_vec4*)&inverseBindMatrix, (glm_vec4*)&out);
state.cauterizedClusterMatrices[j] = out;
#else
state.cauterizedClusterMatrices[j] = jointMatrix * cluster.inverseBindMatrix;
#endif
} }
} }

View file

@ -126,7 +126,7 @@ public:
bool getSnapModelToRegistrationPoint() { return _snapModelToRegistrationPoint; } bool getSnapModelToRegistrationPoint() { return _snapModelToRegistrationPoint; }
virtual void simulate(float deltaTime, bool fullUpdate = true); virtual void simulate(float deltaTime, bool fullUpdate = true);
virtual void updateClusterMatrices(glm::vec3 modelPosition, glm::quat modelOrientation); virtual void updateClusterMatrices();
/// Returns a reference to the shared geometry. /// Returns a reference to the shared geometry.
const Geometry::Pointer& getGeometry() const { return _renderGeometry; } const Geometry::Pointer& getGeometry() const { return _renderGeometry; }
@ -251,9 +251,6 @@ signals:
protected: protected:
bool addedToScene() const { return _addedToScene; } bool addedToScene() const { return _addedToScene; }
void setPupilDilation(float dilation) { _pupilDilation = dilation; }
float getPupilDilation() const { return _pupilDilation; }
void setBlendshapeCoefficients(const QVector<float>& coefficients) { _blendshapeCoefficients = coefficients; } void setBlendshapeCoefficients(const QVector<float>& coefficients) { _blendshapeCoefficients = coefficients; }
const QVector<float>& getBlendshapeCoefficients() const { return _blendshapeCoefficients; } const QVector<float>& getBlendshapeCoefficients() const { return _blendshapeCoefficients; }
@ -347,7 +344,6 @@ protected:
void deleteGeometry(); void deleteGeometry();
void initJointTransforms(); void initJointTransforms();
float _pupilDilation;
QVector<float> _blendshapeCoefficients; QVector<float> _blendshapeCoefficients;
QUrl _url; QUrl _url;