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
// use the _rigOverride matrices instead of the Model::_rig
void SoftAttachmentModel::updateClusterMatrices(glm::vec3 modelPosition, glm::quat modelOrientation) {
void SoftAttachmentModel::updateClusterMatrices() {
if (!_needsUpdateClusterMatrices) {
return;
}
@ -45,7 +45,6 @@ void SoftAttachmentModel::updateClusterMatrices(glm::vec3 modelPosition, glm::qu
const FBXGeometry& geometry = getFBXGeometry();
glm::mat4 modelToWorld = glm::mat4_cast(modelOrientation);
for (int i = 0; i < _meshStates.size(); i++) {
MeshState& state = _meshStates[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++) {
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);
glm::mat4 jointMatrix;
if (jointIndexOverride >= 0 && jointIndexOverride < _rigOverride->getJointStateCount()) {
@ -61,7 +60,13 @@ void SoftAttachmentModel::updateClusterMatrices(glm::vec3 modelPosition, glm::qu
} else {
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)

View file

@ -31,7 +31,7 @@ public:
~SoftAttachmentModel();
virtual void updateRig(float deltaTime, glm::mat4 parentTransform) override;
virtual void updateClusterMatrices(glm::vec3 modelPosition, glm::quat modelOrientation) override;
virtual void updateClusterMatrices() override;
protected:
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) {
_transform = transform;
_offsetTransform = offsetTransform;
Transform::mult(_drawTransform, _transform, _offsetTransform);
Transform::mult(_drawTransform, _transform, offsetTransform);
_worldBound = _localBound;
_worldBound.transform(_drawTransform);
}
@ -360,8 +359,8 @@ void ModelMeshPartPayload::notifyLocationChanged() {
}
void ModelMeshPartPayload::updateTransformForSkinnedMesh(const Transform& transform, const Transform& offsetTransform, const QVector<glm::mat4>& clusterMatrices) {
ModelMeshPartPayload::updateTransform(transform, offsetTransform);
void ModelMeshPartPayload::updateTransformForSkinnedMesh(const Transform& transform, const QVector<glm::mat4>& clusterMatrices) {
_transform = transform;
if (clusterMatrices.size() > 0) {
_worldBound = AABox();
@ -371,8 +370,10 @@ void ModelMeshPartPayload::updateTransformForSkinnedMesh(const Transform& transf
_worldBound += clusterBound;
}
// clusterMatrix has world rotation but not world translation.
_worldBound.translate(transform.getTranslation());
_worldBound.transform(transform);
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
const Model::MeshState& state = _model->_meshStates.at(_meshIndex);
Transform transform;
if (state.clusterBuffer) {
if (canCauterize && _model->getCauterizeBones()) {
batch.setUniformBuffer(ShapePipeline::Slot::BUFFER::SKINNING, state.cauterizedClusterBuffer);
} else {
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() {
@ -569,8 +562,7 @@ void ModelMeshPartPayload::render(RenderArgs* args) const {
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
bool nextIsFading = _isFading ? isStillFading() : false;
bool startFading = !_isFading && !_hasFinishedFade && _hasStartedFade;
@ -592,7 +584,7 @@ void ModelMeshPartPayload::render(RenderArgs* args) const {
// Bind the model transform and the skinCLusterMatrices if needed
bool canCauterize = args->_renderMode != RenderArgs::SHADOW_RENDER_MODE;
_model->updateClusterMatrices(_transform.getTranslation(), _transform.getRotation());
_model->updateClusterMatrices();
bindTransform(batch, locations, canCauterize);
//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 notifyLocationChanged() {}
virtual void updateTransform(const Transform& transform, const Transform& offsetTransform);
void updateTransform(const Transform& transform, const Transform& offsetTransform);
virtual void updateMaterial(model::MaterialPointer drawMaterial);
@ -56,13 +56,12 @@ public:
model::Mesh::Part _drawPart;
std::shared_ptr<const model::Material> _drawMaterial;
model::Box _localBound;
Transform _drawTransform;
Transform _transform;
Transform _offsetTransform;
mutable model::Box _worldBound;
bool _hasColorAttrib = false;
size_t getVerticesCount() const { return _drawMesh ? _drawMesh->getNumVertices() : 0; }
@ -86,7 +85,7 @@ public:
typedef Payload::DataPointer Pointer;
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
void startFade();
@ -101,7 +100,7 @@ public:
// ModelMeshPartPayload functions to perform render
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();

View file

@ -92,7 +92,6 @@ Model::Model(RigPointer rig, QObject* parent) :
_snapModelToRegistrationPoint(false),
_snappedToRegistrationPoint(false),
_cauterizeBones(false),
_pupilDilation(0.0f),
_url(HTTP_INVALID_COM),
_isVisible(true),
_blendNumber(0),
@ -217,23 +216,17 @@ void Model::updateRenderItems() {
render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene();
Transform modelTransform;
modelTransform.setScale(scale);
modelTransform.setTranslation(self->_translation);
modelTransform.setRotation(self->_rotation);
Transform modelMeshOffset;
if (self->isLoaded()) {
// includes model offset and unitScale.
modelMeshOffset = Transform(self->_rig->getGeometryToRigTransform());
} else {
modelMeshOffset.postTranslate(self->_offset);
}
Transform scaledModelTransform(modelTransform);
scaledModelTransform.setScale(scale);
uint32_t deleteGeometryCounter = self->_deleteGeometryCounter;
render::PendingChanges pendingChanges;
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.hasStartedFade() && data._model->getGeometry()->areTexturesLoaded()) {
data.startFade();
@ -241,11 +234,11 @@ void Model::updateRenderItems() {
// Ensure the model geometry was not reset between frames
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.
data._model->updateClusterMatrices(modelTransform.getTranslation(), modelTransform.getRotation());
data._model->updateClusterMatrices();
// update the model transform and bounding box for this render item.
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;
collisionMeshOffset.setIdentity();
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.
data.updateTransform(modelTransform, collisionMeshOffset);
data.updateTransform(scaledModelTransform, collisionMeshOffset);
});
}
@ -295,6 +288,7 @@ bool Model::updateGeometry() {
if (_rig->jointStatesEmpty() && getFBXGeometry().joints.size() > 0) {
initJointStates();
assert(_meshStates.empty());
const FBXGeometry& fbxGeometry = getFBXGeometry();
foreach (const FBXMesh& mesh, fbxGeometry.meshes) {
@ -304,6 +298,9 @@ bool Model::updateGeometry() {
_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>();
if (!mesh.blendshapes.isEmpty()) {
buffer->resize((mesh.vertices.size() + mesh.normals.size()) * sizeof(glm::vec3));
@ -1152,7 +1149,7 @@ void Model::simulateInternal(float deltaTime) {
}
// virtual
void Model::updateClusterMatrices(glm::vec3 modelPosition, glm::quat modelOrientation) {
void Model::updateClusterMatrices() {
PerformanceTimer perfTimer("Model::updateClusterMatrices");
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));
auto cauterizeMatrix = _rig->getJointTransform(geometry.neckJointIndex) * zeroScale;
glm::mat4 modelToWorld = glm::mat4_cast(modelOrientation);
for (int i = 0; i < _meshStates.size(); i++) {
MeshState& state = _meshStates[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);
auto jointMatrix = _rig->getJointTransform(cluster.jointIndex);
#if GLM_ARCH & GLM_ARCH_SSE2
glm::mat4 temp, out, inverseBindMatrix = cluster.inverseBindMatrix;
glm_mat4_mul((glm_vec4*)&modelToWorld, (glm_vec4*)&jointMatrix, (glm_vec4*)&temp);
glm_mat4_mul((glm_vec4*)&temp, (glm_vec4*)&inverseBindMatrix, (glm_vec4*)&out);
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] = modelToWorld * jointMatrix * cluster.inverseBindMatrix;
#else
state.clusterMatrices[j] = jointMatrix * cluster.inverseBindMatrix;
#endif
// 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()) {
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; }
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.
const Geometry::Pointer& getGeometry() const { return _renderGeometry; }
@ -251,9 +251,6 @@ signals:
protected:
bool addedToScene() const { return _addedToScene; }
void setPupilDilation(float dilation) { _pupilDilation = dilation; }
float getPupilDilation() const { return _pupilDilation; }
void setBlendshapeCoefficients(const QVector<float>& coefficients) { _blendshapeCoefficients = coefficients; }
const QVector<float>& getBlendshapeCoefficients() const { return _blendshapeCoefficients; }
@ -347,7 +344,6 @@ protected:
void deleteGeometry();
void initJointTransforms();
float _pupilDilation;
QVector<float> _blendshapeCoefficients;
QUrl _url;