Merge branch 'master' into hazeOnTransparent

This commit is contained in:
Nissim Hadar 2017-11-08 14:11:41 -08:00
commit cc58f6ac2a
13 changed files with 99 additions and 128 deletions

View file

@ -728,19 +728,19 @@ void Avatar::simulateAttachments(float deltaTime) {
glm::quat jointRotation; glm::quat jointRotation;
if (attachment.isSoft) { if (attachment.isSoft) {
// soft attachments do not have transform offsets // soft attachments do not have transform offsets
model->setTranslation(getPosition()); model->setTransformNoUpdateRenderItems(Transform(getOrientation() * Quaternions::Y_180, glm::vec3(1.0), getPosition()));
model->setRotation(getOrientation() * Quaternions::Y_180);
model->simulate(deltaTime); model->simulate(deltaTime);
model->updateRenderItems();
} else { } else {
if (_skeletonModel->getJointPositionInWorldFrame(jointIndex, jointPosition) && if (_skeletonModel->getJointPositionInWorldFrame(jointIndex, jointPosition) &&
_skeletonModel->getJointRotationInWorldFrame(jointIndex, jointRotation)) { _skeletonModel->getJointRotationInWorldFrame(jointIndex, jointRotation)) {
model->setTranslation(jointPosition + jointRotation * attachment.translation * getModelScale()); model->setTransformNoUpdateRenderItems(Transform(jointRotation * attachment.rotation, glm::vec3(1.0), jointPosition + jointRotation * attachment.translation * getModelScale()));
model->setRotation(jointRotation * attachment.rotation);
float scale = getModelScale() * attachment.scale; float scale = getModelScale() * attachment.scale;
model->setScaleToFit(true, model->getNaturalDimensions() * scale, true); // hack to force rescale model->setScaleToFit(true, model->getNaturalDimensions() * scale, true); // hack to force rescale
model->setSnapModelToCenter(false); // hack to force resnap model->setSnapModelToCenter(false); // hack to force resnap
model->setSnapModelToCenter(true); model->setSnapModelToCenter(true);
model->simulate(deltaTime); model->simulate(deltaTime);
model->updateRenderItems();
} }
} }
} }

View file

@ -20,11 +20,22 @@ using namespace render;
CauterizedMeshPartPayload::CauterizedMeshPartPayload(ModelPointer 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::updateClusterBuffer(const std::vector<glm::mat4>& clusterMatrices, const std::vector<glm::mat4>& cauterizedClusterMatrices) {
const Transform& renderTransform, ModelMeshPartPayload::updateClusterBuffer(clusterMatrices);
const gpu::BufferPointer& buffer) {
if (cauterizedClusterMatrices.size() > 1) {
if (!_cauterizedClusterBuffer) {
_cauterizedClusterBuffer = std::make_shared<gpu::Buffer>(cauterizedClusterMatrices.size() * sizeof(glm::mat4),
(const gpu::Byte*) cauterizedClusterMatrices.data());
} else {
_cauterizedClusterBuffer->setSubData(0, cauterizedClusterMatrices.size() * sizeof(glm::mat4),
(const gpu::Byte*) cauterizedClusterMatrices.data());
}
}
}
void CauterizedMeshPartPayload::updateTransformForCauterizedMesh(const Transform& renderTransform) {
_cauterizedTransform = renderTransform; _cauterizedTransform = renderTransform;
_cauterizedClusterBuffer = buffer;
} }
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 {

View file

@ -15,7 +15,9 @@ class CauterizedMeshPartPayload : public ModelMeshPartPayload {
public: public:
CauterizedMeshPartPayload(ModelPointer 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 updateClusterBuffer(const std::vector<glm::mat4>& clusterMatrices, const std::vector<glm::mat4>& cauterizedClusterMatrices);
void updateTransformForCauterizedMesh(const Transform& renderTransform);
void bindTransform(gpu::Batch& batch, const render::ShapePipeline::LocationsPointer locations, RenderArgs::RenderMode renderMode) const override; void bindTransform(gpu::Batch& batch, const render::ShapePipeline::LocationsPointer locations, RenderArgs::RenderMode renderMode) const override;

View file

@ -48,7 +48,7 @@ void CauterizedModel::createVisibleRenderItemSet() {
const auto& meshes = _renderGeometry->getMeshes(); const auto& meshes = _renderGeometry->getMeshes();
// all of our mesh vectors must match in size // all of our mesh vectors must match in size
if ((int)meshes.size() != _meshStates.size()) { if (meshes.size() != _meshStates.size()) {
qCDebug(renderutils) << "WARNING!!!! Mesh Sizes don't match! We will not segregate mesh groups yet."; qCDebug(renderutils) << "WARNING!!!! Mesh Sizes don't match! We will not segregate mesh groups yet.";
return; return;
} }
@ -57,6 +57,7 @@ void CauterizedModel::createVisibleRenderItemSet() {
Q_ASSERT(_modelMeshRenderItems.isEmpty()); Q_ASSERT(_modelMeshRenderItems.isEmpty());
_modelMeshRenderItems.clear(); _modelMeshRenderItems.clear();
_modelMeshRenderItemShapes.clear();
Transform transform; Transform transform;
transform.setTranslation(_translation); transform.setTranslation(_translation);
@ -80,6 +81,7 @@ void CauterizedModel::createVisibleRenderItemSet() {
for (int partIndex = 0; partIndex < numParts; partIndex++) { for (int partIndex = 0; partIndex < numParts; partIndex++) {
auto ptr = std::make_shared<CauterizedMeshPartPayload>(shared_from_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);
_modelMeshRenderItemShapes.emplace_back(ShapeInfo{ (int)i });
shapeID++; shapeID++;
} }
} }
@ -102,7 +104,7 @@ void CauterizedModel::updateClusterMatrices() {
_needsUpdateClusterMatrices = false; _needsUpdateClusterMatrices = false;
const FBXGeometry& geometry = getFBXGeometry(); const FBXGeometry& geometry = getFBXGeometry();
for (int i = 0; i < _meshStates.size(); i++) { for (int i = 0; i < (int)_meshStates.size(); i++) {
Model::MeshState& state = _meshStates[i]; Model::MeshState& state = _meshStates[i];
const FBXMesh& mesh = geometry.meshes.at(i); const FBXMesh& mesh = geometry.meshes.at(i);
for (int j = 0; j < mesh.clusters.size(); j++) { for (int j = 0; j < mesh.clusters.size(); j++) {
@ -110,17 +112,6 @@ void CauterizedModel::updateClusterMatrices() {
auto jointMatrix = _rig.getJointTransform(cluster.jointIndex); auto jointMatrix = _rig.getJointTransform(cluster.jointIndex);
glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, state.clusterMatrices[j]); glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, state.clusterMatrices[j]);
} }
// Once computed the cluster matrices, update the buffer(s)
if (mesh.clusters.size() > 1) {
if (!state.clusterBuffer) {
state.clusterBuffer = std::make_shared<gpu::Buffer>(state.clusterMatrices.size() * sizeof(glm::mat4),
(const gpu::Byte*) state.clusterMatrices.constData());
} else {
state.clusterBuffer->setSubData(0, state.clusterMatrices.size() * sizeof(glm::mat4),
(const gpu::Byte*) state.clusterMatrices.constData());
}
}
} }
// as an optimization, don't build cautrizedClusterMatrices if the boneSet is empty. // as an optimization, don't build cautrizedClusterMatrices if the boneSet is empty.
@ -143,17 +134,6 @@ void CauterizedModel::updateClusterMatrices() {
} }
glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, state.clusterMatrices[j]); glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, state.clusterMatrices[j]);
} }
if (!_cauterizeBoneSet.empty() && (state.clusterMatrices.size() > 1)) {
if (!state.clusterBuffer) {
state.clusterBuffer =
std::make_shared<gpu::Buffer>(state.clusterMatrices.size() * sizeof(glm::mat4),
(const gpu::Byte*) state.clusterMatrices.constData());
} else {
state.clusterBuffer->setSubData(0, state.clusterMatrices.size() * sizeof(glm::mat4),
(const gpu::Byte*) state.clusterMatrices.constData());
}
}
} }
} }
@ -181,11 +161,11 @@ void CauterizedModel::updateRenderItems() {
// queue up this work for later processing, at the end of update and just before rendering. // queue up this work for later processing, at the end of update and just before rendering.
// the application will ensure only the last lambda is actually invoked. // the application will ensure only the last lambda is actually invoked.
void* key = (void*)this; void* key = (void*)this;
std::weak_ptr<Model> weakSelf = shared_from_this(); std::weak_ptr<CauterizedModel> weakSelf = std::dynamic_pointer_cast<CauterizedModel>(shared_from_this());
AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [weakSelf, scale]() { AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [weakSelf]() {
// do nothing, if the model has already been destroyed. // do nothing, if the model has already been destroyed.
auto self = weakSelf.lock(); auto self = weakSelf.lock();
if (!self) { if (!self || !self->isLoaded()) {
return; return;
} }
@ -198,37 +178,28 @@ void CauterizedModel::updateRenderItems() {
modelTransform.setTranslation(self->getTranslation()); modelTransform.setTranslation(self->getTranslation());
modelTransform.setRotation(self->getRotation()); modelTransform.setRotation(self->getRotation());
Transform scaledModelTransform(modelTransform);
scaledModelTransform.setScale(scale);
uint32_t deleteGeometryCounter = self->getGeometryCounter();
render::Transaction transaction; render::Transaction transaction;
QList<render::ItemID> keys = self->getRenderItems().keys(); for (int i = 0; i < (int)self->_modelMeshRenderItemIDs.size(); i++) {
foreach (auto itemID, keys) {
transaction.updateItem<CauterizedMeshPartPayload>(itemID, [modelTransform, deleteGeometryCounter](CauterizedMeshPartPayload& data) { auto itemID = self->_modelMeshRenderItemIDs[i];
ModelPointer model = data._model.lock(); auto meshIndex = self->_modelMeshRenderItemShapes[i].meshIndex;
if (model && model->isLoaded()) { auto clusterMatrices(self->getMeshState(meshIndex).clusterMatrices);
// Ensure the model geometry was not reset between frames auto clusterMatricesCauterized(self->getCauterizeMeshState(meshIndex).clusterMatrices);
if (deleteGeometryCounter == model->getGeometryCounter()) {
// this stuff identical to what happens in regular Model transaction.updateItem<CauterizedMeshPartPayload>(itemID, [modelTransform, clusterMatrices, clusterMatricesCauterized](CauterizedMeshPartPayload& data) {
const Model::MeshState& state = model->getMeshState(data._meshIndex); data.updateClusterBuffer(clusterMatrices, clusterMatricesCauterized);
Transform renderTransform = modelTransform;
if (state.clusterMatrices.size() == 1) { Transform renderTransform = modelTransform;
renderTransform = modelTransform.worldTransform(Transform(state.clusterMatrices[0])); if (clusterMatrices.size() == 1) {
} renderTransform = modelTransform.worldTransform(Transform(clusterMatrices[0]));
data.updateTransformForSkinnedMesh(renderTransform, modelTransform, state.clusterBuffer); }
data.updateTransformForSkinnedMesh(renderTransform, modelTransform);
// this stuff for cauterized mesh
CauterizedModel* cModel = static_cast<CauterizedModel*>(model.get());
const Model::MeshState& cState = cModel->getCauterizeMeshState(data._meshIndex);
renderTransform = modelTransform; renderTransform = modelTransform;
if (cState.clusterMatrices.size() == 1) { if (clusterMatricesCauterized.size() == 1) {
renderTransform = modelTransform.worldTransform(Transform(cState.clusterMatrices[0])); renderTransform = modelTransform.worldTransform(Transform(clusterMatricesCauterized[0]));
}
data.updateTransformForCauterizedMesh(renderTransform, cState.clusterBuffer);
}
} }
data.updateTransformForCauterizedMesh(renderTransform);
}); });
} }

View file

@ -140,7 +140,7 @@ void DrawHaze::run(const render::RenderContextPointer& renderContext, const Inpu
gpu::StatePointer state = gpu::StatePointer(new gpu::State()); gpu::StatePointer state = gpu::StatePointer(new gpu::State());
// Mask out haze on the tablet // Mask out haze on the tablet
PrepareStencil::testNoAA(*state); PrepareStencil::testMask(*state);
gpu::Shader::BindingSet slotBindings; gpu::Shader::BindingSet slotBindings;
slotBindings.insert(gpu::Shader::Binding(std::string("hazeBuffer"), HazeEffect_ParamsSlot)); slotBindings.insert(gpu::Shader::Binding(std::string("hazeBuffer"), HazeEffect_ParamsSlot));

View file

@ -337,7 +337,7 @@ ModelMeshPartPayload::ModelMeshPartPayload(ModelPointer model, int meshIndex, in
if (state.clusterMatrices.size() == 1) { if (state.clusterMatrices.size() == 1) {
renderTransform = transform.worldTransform(Transform(state.clusterMatrices[0])); renderTransform = transform.worldTransform(Transform(state.clusterMatrices[0]));
} }
updateTransformForSkinnedMesh(renderTransform, transform, state.clusterBuffer); updateTransformForSkinnedMesh(renderTransform, transform);
initCache(); initCache();
} }
@ -367,12 +367,25 @@ void ModelMeshPartPayload::notifyLocationChanged() {
} }
void ModelMeshPartPayload::updateTransformForSkinnedMesh(const Transform& renderTransform, const Transform& boundTransform,
const gpu::BufferPointer& buffer) { void ModelMeshPartPayload::updateClusterBuffer(const std::vector<glm::mat4>& clusterMatrices) {
// Once computed the cluster matrices, update the buffer(s)
if (clusterMatrices.size() > 1) {
if (!_clusterBuffer) {
_clusterBuffer = std::make_shared<gpu::Buffer>(clusterMatrices.size() * sizeof(glm::mat4),
(const gpu::Byte*) clusterMatrices.data());
}
else {
_clusterBuffer->setSubData(0, clusterMatrices.size() * sizeof(glm::mat4),
(const gpu::Byte*) clusterMatrices.data());
}
}
}
void ModelMeshPartPayload::updateTransformForSkinnedMesh(const Transform& renderTransform, const Transform& boundTransform) {
_transform = renderTransform; _transform = renderTransform;
_worldBound = _adjustedLocalBound; _worldBound = _adjustedLocalBound;
_worldBound.transform(boundTransform); _worldBound.transform(boundTransform);
_clusterBuffer = buffer;
} }
ItemKey ModelMeshPartPayload::getKey() const { ItemKey ModelMeshPartPayload::getKey() const {
@ -416,7 +429,6 @@ int ModelMeshPartPayload::getLayer() const {
} }
ShapeKey ModelMeshPartPayload::getShapeKey() const { ShapeKey ModelMeshPartPayload::getShapeKey() const {
// guard against partially loaded meshes // guard against partially loaded meshes
ModelPointer model = _model.lock(); ModelPointer model = _model.lock();
if (!model || !model->isLoaded() || !model->getGeometry()) { if (!model || !model->isLoaded() || !model->getGeometry()) {
@ -582,11 +594,11 @@ void ModelMeshPartPayload::render(RenderArgs* args) {
args->_details._trianglesRendered += _drawPart._numIndices / INDICES_PER_TRIANGLE; args->_details._trianglesRendered += _drawPart._numIndices / INDICES_PER_TRIANGLE;
} }
void ModelMeshPartPayload::computeAdjustedLocalBound(const QVector<glm::mat4>& clusterMatrices) { void ModelMeshPartPayload::computeAdjustedLocalBound(const std::vector<glm::mat4>& clusterMatrices) {
_adjustedLocalBound = _localBound; _adjustedLocalBound = _localBound;
if (clusterMatrices.size() > 0) { if (clusterMatrices.size() > 0) {
_adjustedLocalBound.transform(clusterMatrices[0]); _adjustedLocalBound.transform(clusterMatrices[0]);
for (int i = 1; i < clusterMatrices.size(); ++i) { for (int i = 1; i < (int)clusterMatrices.size(); ++i) {
AABox clusterBound = _localBound; AABox clusterBound = _localBound;
clusterBound.transform(clusterMatrices[i]); clusterBound.transform(clusterMatrices[i]);
_adjustedLocalBound += clusterBound; _adjustedLocalBound += clusterBound;

View file

@ -87,9 +87,8 @@ public:
typedef Payload::DataPointer Pointer; typedef Payload::DataPointer Pointer;
void notifyLocationChanged() override; void notifyLocationChanged() override;
void updateTransformForSkinnedMesh(const Transform& renderTransform, void updateClusterBuffer(const std::vector<glm::mat4>& clusterMatrices);
const Transform& boundTransform, void updateTransformForSkinnedMesh(const Transform& renderTransform, const Transform& boundTransform);
const gpu::BufferPointer& buffer);
// Render Item interface // Render Item interface
render::ItemKey getKey() const override; render::ItemKey getKey() const override;
@ -103,7 +102,7 @@ public:
void initCache(); void initCache();
void computeAdjustedLocalBound(const QVector<glm::mat4>& clusterMatrices); void computeAdjustedLocalBound(const std::vector<glm::mat4>& clusterMatrices);
gpu::BufferPointer _clusterBuffer; gpu::BufferPointer _clusterBuffer;
ModelWeakPointer _model; ModelWeakPointer _model;

View file

@ -226,7 +226,7 @@ void Model::updateRenderItems() {
// do nothing, if the model has already been destroyed. // do nothing, if the model has already been destroyed.
auto self = weakSelf.lock(); auto self = weakSelf.lock();
if (!self) { if (!self || !self->isLoaded()) {
return; return;
} }
@ -237,24 +237,20 @@ void Model::updateRenderItems() {
Transform modelTransform = self->getTransform(); Transform modelTransform = self->getTransform();
modelTransform.setScale(glm::vec3(1.0f)); modelTransform.setScale(glm::vec3(1.0f));
uint32_t deleteGeometryCounter = self->_deleteGeometryCounter;
render::Transaction transaction; render::Transaction transaction;
foreach (auto itemID, self->_modelMeshRenderItemsMap.keys()) { for (int i = 0; i < (int) self->_modelMeshRenderItemIDs.size(); i++) {
transaction.updateItem<ModelMeshPartPayload>(itemID, [deleteGeometryCounter, modelTransform](ModelMeshPartPayload& data) {
ModelPointer model = data._model.lock();
if (model && model->isLoaded()) {
// Ensure the model geometry was not reset between frames
if (deleteGeometryCounter == model->_deleteGeometryCounter) {
const Model::MeshState& state = model->getMeshState(data._meshIndex); auto itemID = self->_modelMeshRenderItemIDs[i];
auto meshIndex = self->_modelMeshRenderItemShapes[i].meshIndex;
auto clusterMatrices(self->getMeshState(meshIndex).clusterMatrices);
transaction.updateItem<ModelMeshPartPayload>(itemID, [modelTransform, clusterMatrices](ModelMeshPartPayload& data) {
data.updateClusterBuffer(clusterMatrices);
Transform renderTransform = modelTransform; Transform renderTransform = modelTransform;
if (state.clusterMatrices.size() == 1) { if (clusterMatrices.size() == 1) {
renderTransform = modelTransform.worldTransform(Transform(state.clusterMatrices[0])); renderTransform = modelTransform.worldTransform(Transform(clusterMatrices[0]));
}
data.updateTransformForSkinnedMesh(renderTransform, modelTransform, state.clusterBuffer);
}
} }
data.updateTransformForSkinnedMesh(renderTransform, modelTransform);
}); });
} }
@ -311,7 +307,7 @@ bool Model::updateGeometry() {
foreach (const FBXMesh& mesh, fbxGeometry.meshes) { foreach (const FBXMesh& mesh, fbxGeometry.meshes) {
MeshState state; MeshState state;
state.clusterMatrices.resize(mesh.clusters.size()); state.clusterMatrices.resize(mesh.clusters.size());
_meshStates.append(state); _meshStates.push_back(state);
// Note: we add empty buffers for meshes that lack blendshapes so we can access the buffers by index // 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. // later in ModelMeshPayload, however the vast majority of meshes will not have them.
@ -686,6 +682,7 @@ void Model::removeFromScene(const render::ScenePointer& scene, render::Transacti
_modelMeshRenderItemIDs.clear(); _modelMeshRenderItemIDs.clear();
_modelMeshRenderItemsMap.clear(); _modelMeshRenderItemsMap.clear();
_modelMeshRenderItems.clear(); _modelMeshRenderItems.clear();
_modelMeshRenderItemShapes.clear();
foreach(auto item, _collisionRenderItemsMap.keys()) { foreach(auto item, _collisionRenderItemsMap.keys()) {
transaction.removeItem(item); transaction.removeItem(item);
@ -1127,7 +1124,7 @@ void Model::updateClusterMatrices() {
} }
_needsUpdateClusterMatrices = false; _needsUpdateClusterMatrices = false;
const FBXGeometry& geometry = getFBXGeometry(); const FBXGeometry& geometry = getFBXGeometry();
for (int i = 0; i < _meshStates.size(); i++) { for (int i = 0; i < (int) _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);
for (int j = 0; j < mesh.clusters.size(); j++) { for (int j = 0; j < mesh.clusters.size(); j++) {
@ -1135,17 +1132,6 @@ void Model::updateClusterMatrices() {
auto jointMatrix = _rig.getJointTransform(cluster.jointIndex); auto jointMatrix = _rig.getJointTransform(cluster.jointIndex);
glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, state.clusterMatrices[j]); glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, state.clusterMatrices[j]);
} }
// Once computed the cluster matrices, update the buffer(s)
if (mesh.clusters.size() > 1) {
if (!state.clusterBuffer) {
state.clusterBuffer = std::make_shared<gpu::Buffer>(state.clusterMatrices.size() * sizeof(glm::mat4),
(const gpu::Byte*) state.clusterMatrices.constData());
} else {
state.clusterBuffer->setSubData(0, state.clusterMatrices.size() * sizeof(glm::mat4),
(const gpu::Byte*) state.clusterMatrices.constData());
}
}
} }
// post the blender if we're not currently waiting for one to finish // post the blender if we're not currently waiting for one to finish
@ -1255,7 +1241,7 @@ void Model::createVisibleRenderItemSet() {
const auto& meshes = _renderGeometry->getMeshes(); const auto& meshes = _renderGeometry->getMeshes();
// all of our mesh vectors must match in size // all of our mesh vectors must match in size
if ((int)meshes.size() != _meshStates.size()) { if (meshes.size() != _meshStates.size()) {
qCDebug(renderutils) << "WARNING!!!! Mesh Sizes don't match! We will not segregate mesh groups yet."; qCDebug(renderutils) << "WARNING!!!! Mesh Sizes don't match! We will not segregate mesh groups yet.";
return; return;
} }
@ -1264,6 +1250,7 @@ void Model::createVisibleRenderItemSet() {
Q_ASSERT(_modelMeshRenderItems.isEmpty()); Q_ASSERT(_modelMeshRenderItems.isEmpty());
_modelMeshRenderItems.clear(); _modelMeshRenderItems.clear();
_modelMeshRenderItemShapes.clear();
Transform transform; Transform transform;
transform.setTranslation(_translation); transform.setTranslation(_translation);
@ -1286,6 +1273,7 @@ void Model::createVisibleRenderItemSet() {
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>(shared_from_this(), i, partIndex, shapeID, transform, offset); _modelMeshRenderItems << std::make_shared<ModelMeshPartPayload>(shared_from_this(), i, partIndex, shapeID, transform, offset);
_modelMeshRenderItemShapes.emplace_back(ShapeInfo{ (int)i });
shapeID++; shapeID++;
} }
} }
@ -1327,7 +1315,7 @@ void Model::createCollisionRenderItemSet() {
} }
bool Model::isRenderable() const { bool Model::isRenderable() const {
return !_meshStates.isEmpty() || (isLoaded() && _renderGeometry->getMeshes().empty()); return !_meshStates.empty() || (isLoaded() && _renderGeometry->getMeshes().empty());
} }
class CollisionRenderGeometry : public Geometry { class CollisionRenderGeometry : public Geometry {

View file

@ -246,8 +246,7 @@ public:
class MeshState { class MeshState {
public: public:
QVector<glm::mat4> clusterMatrices; std::vector<glm::mat4> clusterMatrices;
gpu::BufferPointer clusterBuffer;
}; };
const MeshState& getMeshState(int index) { return _meshStates.at(index); } const MeshState& getMeshState(int index) { return _meshStates.at(index); }
@ -317,7 +316,7 @@ protected:
bool _snappedToRegistrationPoint; /// are we currently snapped to a registration point bool _snappedToRegistrationPoint; /// are we currently snapped to a registration point
glm::vec3 _registrationPoint = glm::vec3(0.5f); /// the point in model space our center is snapped to glm::vec3 _registrationPoint = glm::vec3(0.5f); /// the point in model space our center is snapped to
QVector<MeshState> _meshStates; std::vector<MeshState> _meshStates;
virtual void initJointStates(); virtual void initJointStates();
@ -388,8 +387,9 @@ protected:
QVector<std::shared_ptr<ModelMeshPartPayload>> _modelMeshRenderItems; QVector<std::shared_ptr<ModelMeshPartPayload>> _modelMeshRenderItems;
QMap<render::ItemID, render::PayloadPointer> _modelMeshRenderItemsMap; QMap<render::ItemID, render::PayloadPointer> _modelMeshRenderItemsMap;
render::ItemIDs _modelMeshRenderItemIDs; render::ItemIDs _modelMeshRenderItemIDs;
using ShapeInfo = struct { int meshIndex; };
std::vector<ShapeInfo> _modelMeshRenderItemShapes;
bool _addedToScene { false }; // has been added to scene bool _addedToScene { false }; // has been added to scene
bool _needsFixupInScene { true }; // needs to be removed/re-added to scene bool _needsFixupInScene { true }; // needs to be removed/re-added to scene

View file

@ -43,7 +43,7 @@ void SoftAttachmentModel::updateClusterMatrices() {
const FBXGeometry& geometry = getFBXGeometry(); const FBXGeometry& geometry = getFBXGeometry();
for (int i = 0; i < _meshStates.size(); i++) { for (int i = 0; i < (int) _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);
@ -60,17 +60,6 @@ void SoftAttachmentModel::updateClusterMatrices() {
} }
glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, state.clusterMatrices[j]); glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, state.clusterMatrices[j]);
} }
// Once computed the cluster matrices, update the buffer(s)
if (mesh.clusters.size() > 1) {
if (!state.clusterBuffer) {
state.clusterBuffer = std::make_shared<gpu::Buffer>(state.clusterMatrices.size() * sizeof(glm::mat4),
(const gpu::Byte*) state.clusterMatrices.constData());
} else {
state.clusterBuffer->setSubData(0, state.clusterMatrices.size() * sizeof(glm::mat4),
(const gpu::Byte*) state.clusterMatrices.constData());
}
}
} }
// post the blender if we're not currently waiting for one to finish // post the blender if we're not currently waiting for one to finish

View file

@ -116,9 +116,9 @@ void PrepareStencil::drawBackground(gpu::State& state) {
gpu::State::STENCIL_OP_REPLACE, gpu::State::STENCIL_OP_REPLACE, gpu::State::STENCIL_OP_KEEP)); gpu::State::STENCIL_OP_REPLACE, gpu::State::STENCIL_OP_REPLACE, gpu::State::STENCIL_OP_KEEP));
} }
// Pass if this area has NOT been marked as MASK // Pass if this area has NOT been marked as MASK or anything containing MASK
void PrepareStencil::testMask(gpu::State& state) { void PrepareStencil::testMask(gpu::State& state) {
state.setStencilTest(true, 0x00, gpu::State::StencilTest(STENCIL_MASK, 0xFF, gpu::NOT_EQUAL, state.setStencilTest(true, 0x00, gpu::State::StencilTest(STENCIL_MASK, STENCIL_MASK, gpu::NOT_EQUAL,
gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP)); gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP));
} }

View file

@ -49,8 +49,8 @@ public:
static void drawMask(gpu::State& state); static void drawMask(gpu::State& state);
static void drawBackground(gpu::State& state); static void drawBackground(gpu::State& state);
static void testNoAA(gpu::State& state);
static void testMask(gpu::State& state); static void testMask(gpu::State& state);
static void testNoAA(gpu::State& state);
static void testBackground(gpu::State& state); static void testBackground(gpu::State& state);
static void testShape(gpu::State& state); static void testShape(gpu::State& state);
static void testMaskDrawShape(gpu::State& state); static void testMaskDrawShape(gpu::State& state);

View file

@ -8,8 +8,7 @@
/* global entityIsCloneable:true, getGrabbableData:true, cloneEntity:true, propsAreCloneDynamic:true, Script, /* global entityIsCloneable:true, getGrabbableData:true, cloneEntity:true, propsAreCloneDynamic:true, Script,
propsAreCloneDynamic:true, Entities*/ propsAreCloneDynamic:true, Entities*/
Script.include("/~/system/controllers/controllerDispatcherUtils.js"); Script.include("/~/system/libraries/controllerDispatcherUtils.js");
// Object assign polyfill // Object assign polyfill
if (typeof Object.assign !== 'function') { if (typeof Object.assign !== 'function') {