Merge pull request #10528 from AndrewMeadows/payload-gets-weak-pointer

MeshPartPayload keeps weak pointer to Model
This commit is contained in:
Chris Collins 2017-05-22 21:54:40 -07:00 committed by GitHub
commit 207c13c3c3
6 changed files with 85 additions and 61 deletions

View file

@ -17,7 +17,7 @@
using namespace render; using namespace render;
CauterizedMeshPartPayload::CauterizedMeshPartPayload(Model* model, int meshIndex, int partIndex, int shapeIndex, const Transform& transform, const Transform& offsetTransform) CauterizedMeshPartPayload::CauterizedMeshPartPayload(ModelPointer model, int meshIndex, int partIndex, int shapeIndex, const Transform& transform, const Transform& offsetTransform)
: ModelMeshPartPayload(model, meshIndex, partIndex, shapeIndex, transform, offsetTransform) {} : ModelMeshPartPayload(model, meshIndex, partIndex, shapeIndex, transform, offsetTransform) {}
void CauterizedMeshPartPayload::updateTransformForCauterizedMesh( void CauterizedMeshPartPayload::updateTransformForCauterizedMesh(
@ -29,8 +29,16 @@ void CauterizedMeshPartPayload::updateTransformForCauterizedMesh(
void CauterizedMeshPartPayload::bindTransform(gpu::Batch& batch, const render::ShapePipeline::LocationsPointer locations, RenderArgs::RenderMode renderMode) const { void CauterizedMeshPartPayload::bindTransform(gpu::Batch& batch, const render::ShapePipeline::LocationsPointer locations, RenderArgs::RenderMode renderMode) const {
// Still relying on the raw data from the model // Still relying on the raw data from the model
CauterizedModel* skeleton = static_cast<CauterizedModel*>(_model); bool useCauterizedMesh = (renderMode != RenderArgs::RenderMode::SHADOW_RENDER_MODE);
bool useCauterizedMesh = (renderMode != RenderArgs::RenderMode::SHADOW_RENDER_MODE) && skeleton->getEnableCauterization(); if (useCauterizedMesh) {
ModelPointer model = _model.lock();
if (model) {
CauterizedModel* skeleton = static_cast<CauterizedModel*>(model.get());
useCauterizedMesh = useCauterizedMesh && skeleton->getEnableCauterization();
} else {
useCauterizedMesh = false;
}
}
if (useCauterizedMesh) { if (useCauterizedMesh) {
if (_cauterizedClusterBuffer) { if (_cauterizedClusterBuffer) {

View file

@ -13,7 +13,7 @@
class CauterizedMeshPartPayload : public ModelMeshPartPayload { class CauterizedMeshPartPayload : public ModelMeshPartPayload {
public: public:
CauterizedMeshPartPayload(Model* model, int meshIndex, int partIndex, int shapeIndex, const Transform& transform, const Transform& offsetTransform); CauterizedMeshPartPayload(ModelPointer model, int meshIndex, int partIndex, int shapeIndex, const Transform& transform, const Transform& offsetTransform);
void updateTransformForCauterizedMesh(const Transform& renderTransform, const gpu::BufferPointer& buffer); void updateTransformForCauterizedMesh(const Transform& renderTransform, const gpu::BufferPointer& buffer);

View file

@ -78,7 +78,7 @@ void CauterizedModel::createVisibleRenderItemSet() {
// Create the render payloads // Create the render payloads
int numParts = (int)mesh->getNumParts(); int numParts = (int)mesh->getNumParts();
for (int partIndex = 0; partIndex < numParts; partIndex++) { for (int partIndex = 0; partIndex < numParts; partIndex++) {
auto ptr = std::make_shared<CauterizedMeshPartPayload>(this, i, partIndex, shapeID, transform, offset); auto ptr = std::make_shared<CauterizedMeshPartPayload>(shared_from_this(), i, partIndex, shapeID, transform, offset);
_modelMeshRenderItems << std::static_pointer_cast<ModelMeshPartPayload>(ptr); _modelMeshRenderItems << std::static_pointer_cast<ModelMeshPartPayload>(ptr);
shapeID++; shapeID++;
} }
@ -207,11 +207,12 @@ void CauterizedModel::updateRenderItems() {
QList<render::ItemID> keys = self->getRenderItems().keys(); QList<render::ItemID> keys = self->getRenderItems().keys();
foreach (auto itemID, keys) { foreach (auto itemID, keys) {
transaction.updateItem<CauterizedMeshPartPayload>(itemID, [modelTransform, deleteGeometryCounter](CauterizedMeshPartPayload& data) { transaction.updateItem<CauterizedMeshPartPayload>(itemID, [modelTransform, deleteGeometryCounter](CauterizedMeshPartPayload& data) {
if (data._model && data._model->isLoaded()) { ModelPointer model = data._model.lock();
if (model && model->isLoaded()) {
// Ensure the model geometry was not reset between frames // Ensure the model geometry was not reset between frames
if (deleteGeometryCounter == data._model->getGeometryCounter()) { if (deleteGeometryCounter == model->getGeometryCounter()) {
// this stuff identical to what happens in regular Model // this stuff identical to what happens in regular Model
const Model::MeshState& state = data._model->getMeshState(data._meshIndex); const Model::MeshState& state = model->getMeshState(data._meshIndex);
Transform renderTransform = modelTransform; Transform renderTransform = modelTransform;
if (state.clusterMatrices.size() == 1) { if (state.clusterMatrices.size() == 1) {
renderTransform = modelTransform.worldTransform(Transform(state.clusterMatrices[0])); renderTransform = modelTransform.worldTransform(Transform(state.clusterMatrices[0]));
@ -219,7 +220,7 @@ void CauterizedModel::updateRenderItems() {
data.updateTransformForSkinnedMesh(renderTransform, modelTransform, state.clusterBuffer); data.updateTransformForSkinnedMesh(renderTransform, modelTransform, state.clusterBuffer);
// this stuff for cauterized mesh // this stuff for cauterized mesh
CauterizedModel* cModel = static_cast<CauterizedModel*>(data._model); CauterizedModel* cModel = static_cast<CauterizedModel*>(model.get());
const Model::MeshState& cState = cModel->getCauterizeMeshState(data._meshIndex); const Model::MeshState& cState = cModel->getCauterizeMeshState(data._meshIndex);
renderTransform = modelTransform; renderTransform = modelTransform;
if (cState.clusterMatrices.size() == 1) { if (cState.clusterMatrices.size() == 1) {

View file

@ -14,7 +14,6 @@
#include <PerfStat.h> #include <PerfStat.h>
#include "DeferredLightingEffect.h" #include "DeferredLightingEffect.h"
#include "Model.h"
#include "EntityItem.h" #include "EntityItem.h"
using namespace render; using namespace render;
@ -321,13 +320,13 @@ template <> void payloadRender(const ModelMeshPartPayload::Pointer& payload, Ren
} }
} }
ModelMeshPartPayload::ModelMeshPartPayload(Model* model, int _meshIndex, int partIndex, int shapeIndex, const Transform& transform, const Transform& offsetTransform) : ModelMeshPartPayload::ModelMeshPartPayload(ModelPointer model, int _meshIndex, int partIndex, int shapeIndex, const Transform& transform, const Transform& offsetTransform) :
_model(model),
_meshIndex(_meshIndex), _meshIndex(_meshIndex),
_shapeID(shapeIndex) { _shapeID(shapeIndex) {
assert(_model && _model->isLoaded()); assert(model && model->isLoaded());
auto& modelMesh = _model->getGeometry()->getMeshes().at(_meshIndex); _model = model;
auto& modelMesh = model->getGeometry()->getMeshes().at(_meshIndex);
updateMeshPart(modelMesh, partIndex); updateMeshPart(modelMesh, partIndex);
updateTransform(transform, offsetTransform); updateTransform(transform, offsetTransform);
@ -335,20 +334,21 @@ ModelMeshPartPayload::ModelMeshPartPayload(Model* model, int _meshIndex, int par
} }
void ModelMeshPartPayload::initCache() { void ModelMeshPartPayload::initCache() {
assert(_model->isLoaded()); ModelPointer model = _model.lock();
assert(model && model->isLoaded());
if (_drawMesh) { if (_drawMesh) {
auto vertexFormat = _drawMesh->getVertexFormat(); auto vertexFormat = _drawMesh->getVertexFormat();
_hasColorAttrib = vertexFormat->hasAttribute(gpu::Stream::COLOR); _hasColorAttrib = vertexFormat->hasAttribute(gpu::Stream::COLOR);
_isSkinned = vertexFormat->hasAttribute(gpu::Stream::SKIN_CLUSTER_WEIGHT) && vertexFormat->hasAttribute(gpu::Stream::SKIN_CLUSTER_INDEX); _isSkinned = vertexFormat->hasAttribute(gpu::Stream::SKIN_CLUSTER_WEIGHT) && vertexFormat->hasAttribute(gpu::Stream::SKIN_CLUSTER_INDEX);
const FBXGeometry& geometry = _model->getFBXGeometry(); const FBXGeometry& geometry = model->getFBXGeometry();
const FBXMesh& mesh = geometry.meshes.at(_meshIndex); const FBXMesh& mesh = geometry.meshes.at(_meshIndex);
_isBlendShaped = !mesh.blendshapes.isEmpty(); _isBlendShaped = !mesh.blendshapes.isEmpty();
} }
auto networkMaterial = _model->getGeometry()->getShapeMaterial(_shapeID); auto networkMaterial = model->getGeometry()->getShapeMaterial(_shapeID);
if (networkMaterial) { if (networkMaterial) {
_drawMaterial = networkMaterial; _drawMaterial = networkMaterial;
} }
@ -370,29 +370,31 @@ ItemKey ModelMeshPartPayload::getKey() const {
ItemKey::Builder builder; ItemKey::Builder builder;
builder.withTypeShape(); builder.withTypeShape();
if (!_model->isVisible()) { ModelPointer model = _model.lock();
builder.withInvisible(); if (model) {
} if (!model->isVisible()) {
builder.withInvisible();
}
if (_model->isLayeredInFront()) { if (model->isLayeredInFront()) {
builder.withLayered(); builder.withLayered();
} }
if (_isBlendShaped || _isSkinned) { if (_isBlendShaped || _isSkinned) {
builder.withDeformed(); builder.withDeformed();
} }
if (_drawMaterial) { if (_drawMaterial) {
auto matKey = _drawMaterial->getKey(); auto matKey = _drawMaterial->getKey();
if (matKey.isTranslucent()) { if (matKey.isTranslucent()) {
builder.withTransparent();
}
}
if (_fadeState != FADE_COMPLETE) {
builder.withTransparent(); builder.withTransparent();
} }
} }
if (_fadeState != FADE_COMPLETE) {
builder.withTransparent();
}
return builder.build(); return builder.build();
} }
@ -400,7 +402,8 @@ int ModelMeshPartPayload::getLayer() const {
// MAgic number while we are defining the layering mechanism: // MAgic number while we are defining the layering mechanism:
const int LAYER_3D_FRONT = 1; const int LAYER_3D_FRONT = 1;
const int LAYER_3D = 0; const int LAYER_3D = 0;
if (_model->isLayeredInFront()) { ModelPointer model = _model.lock();
if (model && model->isLayeredInFront()) {
return LAYER_3D_FRONT; return LAYER_3D_FRONT;
} else { } else {
return LAYER_3D; return LAYER_3D;
@ -410,15 +413,16 @@ int ModelMeshPartPayload::getLayer() const {
ShapeKey ModelMeshPartPayload::getShapeKey() const { ShapeKey ModelMeshPartPayload::getShapeKey() const {
// guard against partially loaded meshes // guard against partially loaded meshes
if (!_model || !_model->isLoaded() || !_model->getGeometry()) { ModelPointer model = _model.lock();
if (!model || !model->isLoaded() || !model->getGeometry()) {
return ShapeKey::Builder::invalid(); return ShapeKey::Builder::invalid();
} }
const FBXGeometry& geometry = _model->getFBXGeometry(); const FBXGeometry& geometry = model->getFBXGeometry();
const auto& networkMeshes = _model->getGeometry()->getMeshes(); const auto& networkMeshes = model->getGeometry()->getMeshes();
// guard against partially loaded meshes // guard against partially loaded meshes
if (_meshIndex >= (int)networkMeshes.size() || _meshIndex >= (int)geometry.meshes.size() || _meshIndex >= (int)_model->_meshStates.size()) { if (_meshIndex >= (int)networkMeshes.size() || _meshIndex >= (int)geometry.meshes.size() || _meshIndex >= (int)model->_meshStates.size()) {
return ShapeKey::Builder::invalid(); return ShapeKey::Builder::invalid();
} }
@ -427,8 +431,8 @@ ShapeKey ModelMeshPartPayload::getShapeKey() const {
// if our index is ever out of range for either meshes or networkMeshes, then skip it, and set our _meshGroupsKnown // if our index is ever out of range for either meshes or networkMeshes, then skip it, and set our _meshGroupsKnown
// to false to rebuild out mesh groups. // to false to rebuild out mesh groups.
if (_meshIndex < 0 || _meshIndex >= (int)networkMeshes.size() || _meshIndex > geometry.meshes.size()) { if (_meshIndex < 0 || _meshIndex >= (int)networkMeshes.size() || _meshIndex > geometry.meshes.size()) {
_model->_needsFixupInScene = true; // trigger remove/add cycle model->_needsFixupInScene = true; // trigger remove/add cycle
_model->invalidCalculatedMeshBoxes(); // if we have to reload, we need to assume our mesh boxes are all invalid model->invalidCalculatedMeshBoxes(); // if we have to reload, we need to assume our mesh boxes are all invalid
return ShapeKey::Builder::invalid(); return ShapeKey::Builder::invalid();
} }
@ -452,7 +456,7 @@ ShapeKey ModelMeshPartPayload::getShapeKey() const {
bool isUnlit = drawMaterialKey.isUnlit(); bool isUnlit = drawMaterialKey.isUnlit();
bool isSkinned = _isSkinned; bool isSkinned = _isSkinned;
bool wireframe = _model->isWireframe(); bool wireframe = model->isWireframe();
if (wireframe) { if (wireframe) {
isTranslucent = hasTangents = hasSpecular = hasLightmap = isSkinned = false; isTranslucent = hasTangents = hasSpecular = hasLightmap = isSkinned = false;
@ -488,18 +492,22 @@ ShapeKey ModelMeshPartPayload::getShapeKey() const {
void ModelMeshPartPayload::bindMesh(gpu::Batch& batch) { void ModelMeshPartPayload::bindMesh(gpu::Batch& batch) {
if (!_isBlendShaped) { if (!_isBlendShaped) {
batch.setIndexBuffer(gpu::UINT32, (_drawMesh->getIndexBuffer()._buffer), 0); batch.setIndexBuffer(gpu::UINT32, (_drawMesh->getIndexBuffer()._buffer), 0);
batch.setInputFormat((_drawMesh->getVertexFormat())); batch.setInputFormat((_drawMesh->getVertexFormat()));
batch.setInputStream(0, _drawMesh->getVertexStream()); batch.setInputStream(0, _drawMesh->getVertexStream());
} else { } else {
batch.setIndexBuffer(gpu::UINT32, (_drawMesh->getIndexBuffer()._buffer), 0); batch.setIndexBuffer(gpu::UINT32, (_drawMesh->getIndexBuffer()._buffer), 0);
batch.setInputFormat((_drawMesh->getVertexFormat())); batch.setInputFormat((_drawMesh->getVertexFormat()));
batch.setInputBuffer(0, _model->_blendedVertexBuffers[_meshIndex], 0, sizeof(glm::vec3)); ModelPointer model = _model.lock();
batch.setInputBuffer(1, _model->_blendedVertexBuffers[_meshIndex], _drawMesh->getNumVertices() * sizeof(glm::vec3), sizeof(glm::vec3)); if (model) {
batch.setInputStream(2, _drawMesh->getVertexStream().makeRangedStream(2)); batch.setInputBuffer(0, model->_blendedVertexBuffers[_meshIndex], 0, sizeof(glm::vec3));
batch.setInputBuffer(1, model->_blendedVertexBuffers[_meshIndex], _drawMesh->getNumVertices() * sizeof(glm::vec3), sizeof(glm::vec3));
batch.setInputStream(2, _drawMesh->getVertexStream().makeRangedStream(2));
} else {
batch.setIndexBuffer(gpu::UINT32, (_drawMesh->getIndexBuffer()._buffer), 0);
batch.setInputFormat((_drawMesh->getVertexFormat()));
batch.setInputStream(0, _drawMesh->getVertexStream());
}
} }
if (_fadeState != FADE_COMPLETE) { if (_fadeState != FADE_COMPLETE) {
@ -530,7 +538,10 @@ float ModelMeshPartPayload::computeFadeAlpha() {
if (fadeAlpha >= 1.0f) { if (fadeAlpha >= 1.0f) {
_fadeState = FADE_COMPLETE; _fadeState = FADE_COMPLETE;
// when fade-in completes we flag model for one last "render item update" // when fade-in completes we flag model for one last "render item update"
_model->setRenderItemsNeedUpdate(); ModelPointer model = _model.lock();
if (model) {
model->setRenderItemsNeedUpdate();
}
return 1.0f; return 1.0f;
} }
return Interpolate::simpleNonLinearBlend(fadeAlpha); return Interpolate::simpleNonLinearBlend(fadeAlpha);
@ -539,26 +550,27 @@ float ModelMeshPartPayload::computeFadeAlpha() {
void ModelMeshPartPayload::render(RenderArgs* args) { void ModelMeshPartPayload::render(RenderArgs* args) {
PerformanceTimer perfTimer("ModelMeshPartPayload::render"); PerformanceTimer perfTimer("ModelMeshPartPayload::render");
if (!_model->addedToScene() || !_model->isVisible()) { ModelPointer model = _model.lock();
if (!model || !model->addedToScene() || !model->isVisible()) {
return; // bail asap return; // bail asap
} }
if (_fadeState == FADE_WAITING_TO_START) { if (_fadeState == FADE_WAITING_TO_START) {
if (_model->isLoaded()) { if (model->isLoaded()) {
if (EntityItem::getEntitiesShouldFadeFunction()()) { if (EntityItem::getEntitiesShouldFadeFunction()()) {
_fadeStartTime = usecTimestampNow(); _fadeStartTime = usecTimestampNow();
_fadeState = FADE_IN_PROGRESS; _fadeState = FADE_IN_PROGRESS;
} else { } else {
_fadeState = FADE_COMPLETE; _fadeState = FADE_COMPLETE;
} }
_model->setRenderItemsNeedUpdate(); model->setRenderItemsNeedUpdate();
} else { } else {
return; return;
} }
} }
if (_materialNeedsUpdate && _model->getGeometry()->areTexturesLoaded()) { if (_materialNeedsUpdate && model->getGeometry()->areTexturesLoaded()) {
_model->setRenderItemsNeedUpdate(); model->setRenderItemsNeedUpdate();
_materialNeedsUpdate = false; _materialNeedsUpdate = false;
} }

View file

@ -21,6 +21,8 @@
#include <model/Geometry.h> #include <model/Geometry.h>
#include "Model.h"
const uint8_t FADE_WAITING_TO_START = 0; const uint8_t FADE_WAITING_TO_START = 0;
const uint8_t FADE_IN_PROGRESS = 1; const uint8_t FADE_IN_PROGRESS = 1;
const uint8_t FADE_COMPLETE = 2; const uint8_t FADE_COMPLETE = 2;
@ -83,7 +85,7 @@ namespace render {
class ModelMeshPartPayload : public MeshPartPayload { class ModelMeshPartPayload : public MeshPartPayload {
public: public:
ModelMeshPartPayload(Model* model, int meshIndex, int partIndex, int shapeIndex, const Transform& transform, const Transform& offsetTransform); ModelMeshPartPayload(ModelPointer model, int meshIndex, int partIndex, int shapeIndex, const Transform& transform, const Transform& offsetTransform);
typedef render::Payload<ModelMeshPartPayload> Payload; typedef render::Payload<ModelMeshPartPayload> Payload;
typedef Payload::DataPointer Pointer; typedef Payload::DataPointer Pointer;
@ -110,7 +112,7 @@ public:
void computeAdjustedLocalBound(const QVector<glm::mat4>& clusterMatrices); void computeAdjustedLocalBound(const QVector<glm::mat4>& clusterMatrices);
gpu::BufferPointer _clusterBuffer; gpu::BufferPointer _clusterBuffer;
Model* _model; ModelWeakPointer _model;
int _meshIndex; int _meshIndex;
int _shapeID; int _shapeID;

View file

@ -235,13 +235,14 @@ void Model::updateRenderItems() {
render::Transaction transaction; render::Transaction transaction;
foreach (auto itemID, self->_modelMeshRenderItemsMap.keys()) { foreach (auto itemID, self->_modelMeshRenderItemsMap.keys()) {
transaction.updateItem<ModelMeshPartPayload>(itemID, [deleteGeometryCounter](ModelMeshPartPayload& data) { transaction.updateItem<ModelMeshPartPayload>(itemID, [deleteGeometryCounter](ModelMeshPartPayload& data) {
if (data._model && data._model->isLoaded()) { ModelPointer model = data._model.lock();
if (model && model->isLoaded()) {
// 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 == model->_deleteGeometryCounter) {
Transform modelTransform = data._model->getTransform(); Transform modelTransform = model->getTransform();
modelTransform.setScale(glm::vec3(1.0f)); modelTransform.setScale(glm::vec3(1.0f));
const Model::MeshState& state = data._model->getMeshState(data._meshIndex); const Model::MeshState& state = model->getMeshState(data._meshIndex);
Transform renderTransform = modelTransform; Transform renderTransform = modelTransform;
if (state.clusterMatrices.size() == 1) { if (state.clusterMatrices.size() == 1) {
renderTransform = modelTransform.worldTransform(Transform(state.clusterMatrices[0])); renderTransform = modelTransform.worldTransform(Transform(state.clusterMatrices[0]));
@ -1225,7 +1226,7 @@ void Model::createVisibleRenderItemSet() {
// Create the render payloads // Create the render payloads
int numParts = (int)mesh->getNumParts(); int numParts = (int)mesh->getNumParts();
for (int partIndex = 0; partIndex < numParts; partIndex++) { for (int partIndex = 0; partIndex < numParts; partIndex++) {
_modelMeshRenderItems << std::make_shared<ModelMeshPartPayload>(this, i, partIndex, shapeID, transform, offset); _modelMeshRenderItems << std::make_shared<ModelMeshPartPayload>(shared_from_this(), i, partIndex, shapeID, transform, offset);
shapeID++; shapeID++;
} }
} }