mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 14:47:41 +02:00
move cauterization out of Model class
This commit is contained in:
parent
601223aa98
commit
3dd8fd838b
12 changed files with 430 additions and 115 deletions
72
interface/src/avatar/CauterizedMeshPartPayload.cpp
Normal file
72
interface/src/avatar/CauterizedMeshPartPayload.cpp
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
//
|
||||||
|
// MeshPartPayload.cpp
|
||||||
|
// interface/src/renderer
|
||||||
|
//
|
||||||
|
// Created by Sam Gateau on 10/3/15.
|
||||||
|
// Copyright 2015 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "CauterizedMeshPartPayload.h"
|
||||||
|
|
||||||
|
#include <PerfStat.h>
|
||||||
|
|
||||||
|
#include "SkeletonModel.h"
|
||||||
|
//#include "EntityItem.h"
|
||||||
|
|
||||||
|
using namespace render;
|
||||||
|
|
||||||
|
CauterizedMeshPartPayload::CauterizedMeshPartPayload(Model* model, int meshIndex, int partIndex, int shapeIndex, const Transform& transform, const Transform& offsetTransform)
|
||||||
|
: ModelMeshPartPayload(model, meshIndex, partIndex, shapeIndex, transform, offsetTransform) {}
|
||||||
|
|
||||||
|
void CauterizedMeshPartPayload::updateTransformForSkinnedCauterizedMesh(const Transform& transform,
|
||||||
|
const QVector<glm::mat4>& clusterMatrices,
|
||||||
|
const QVector<glm::mat4>& cauterizedClusterMatrices) {
|
||||||
|
_transform = transform;
|
||||||
|
_cauterizedTransform = transform;
|
||||||
|
|
||||||
|
if (clusterMatrices.size() > 0) {
|
||||||
|
_worldBound = AABox();
|
||||||
|
for (auto& clusterMatrix : clusterMatrices) {
|
||||||
|
AABox clusterBound = _localBound;
|
||||||
|
clusterBound.transform(clusterMatrix);
|
||||||
|
_worldBound += clusterBound;
|
||||||
|
}
|
||||||
|
|
||||||
|
_worldBound.transform(transform);
|
||||||
|
if (clusterMatrices.size() == 1) {
|
||||||
|
_transform = _transform.worldTransform(Transform(clusterMatrices[0]));
|
||||||
|
if (cauterizedClusterMatrices.size() != 0) {
|
||||||
|
_cauterizedTransform = _cauterizedTransform.worldTransform(Transform(cauterizedClusterMatrices[0]));
|
||||||
|
} else {
|
||||||
|
_cauterizedTransform = _transform;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CauterizedMeshPartPayload::bindTransform(gpu::Batch& batch, const render::ShapePipeline::LocationsPointer locations, RenderArgs::RenderMode renderMode) const {
|
||||||
|
// Still relying on the raw data from the model
|
||||||
|
const Model::MeshState& state = _model->getMeshState(_meshIndex);
|
||||||
|
SkeletonModel* skeleton = static_cast<SkeletonModel*>(_model);
|
||||||
|
bool canCauterize = (renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE);
|
||||||
|
|
||||||
|
if (state.clusterBuffer) {
|
||||||
|
if (canCauterize && skeleton->getCauterizeBones()) {
|
||||||
|
const Model::MeshState& cState = skeleton->getCauterizeMeshState(_meshIndex);
|
||||||
|
batch.setUniformBuffer(ShapePipeline::Slot::BUFFER::SKINNING, cState.clusterBuffer);
|
||||||
|
} else {
|
||||||
|
batch.setUniformBuffer(ShapePipeline::Slot::BUFFER::SKINNING, state.clusterBuffer);
|
||||||
|
}
|
||||||
|
batch.setModelTransform(_transform);
|
||||||
|
} else {
|
||||||
|
if (canCauterize && skeleton->getCauterizeBones()) {
|
||||||
|
batch.setModelTransform(_cauterizedTransform);
|
||||||
|
} else {
|
||||||
|
batch.setModelTransform(_transform);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
29
interface/src/avatar/CauterizedMeshPartPayload.h
Normal file
29
interface/src/avatar/CauterizedMeshPartPayload.h
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
//
|
||||||
|
// CauterizedModelMeshPartPayload.h
|
||||||
|
// interface/src/avatar
|
||||||
|
//
|
||||||
|
// Created by AndrewMeadows 2017.01.17
|
||||||
|
// Copyright 2017 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef hifi_CauterizedMeshPartPayload_h
|
||||||
|
#define hifi_CauterizedMeshPartPayload_h
|
||||||
|
|
||||||
|
#include <MeshPartPayload.h>
|
||||||
|
|
||||||
|
class CauterizedMeshPartPayload : public ModelMeshPartPayload {
|
||||||
|
public:
|
||||||
|
CauterizedMeshPartPayload(Model* model, int meshIndex, int partIndex, int shapeIndex, const Transform& transform, const Transform& offsetTransform);
|
||||||
|
void updateTransformForSkinnedCauterizedMesh(const Transform& transform,
|
||||||
|
const QVector<glm::mat4>& clusterMatrices,
|
||||||
|
const QVector<glm::mat4>& cauterizedClusterMatrices);
|
||||||
|
|
||||||
|
void bindTransform(gpu::Batch& batch, const render::ShapePipeline::LocationsPointer locations, RenderArgs::RenderMode renderMode) const override;
|
||||||
|
private:
|
||||||
|
Transform _cauterizedTransform;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // hifi_CauterizedMeshPartPayload_h
|
236
interface/src/avatar/CauterizedModel.cpp
Normal file
236
interface/src/avatar/CauterizedModel.cpp
Normal file
|
@ -0,0 +1,236 @@
|
||||||
|
//
|
||||||
|
// CauterizedModel.cpp
|
||||||
|
// interface/src/avatar
|
||||||
|
//
|
||||||
|
// Created by Andrew Meadows 2017.01.17
|
||||||
|
// Copyright 2017 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
//#include <glm/gtx/transform.hpp>
|
||||||
|
//#include <QMultiMap>
|
||||||
|
|
||||||
|
#include "CauterizedModel.h"
|
||||||
|
|
||||||
|
#include <AbstractViewStateInterface.h>
|
||||||
|
#include <MeshPartPayload.h>
|
||||||
|
#include <PerfStat.h>
|
||||||
|
|
||||||
|
#include "CauterizedMeshPartPayload.h"
|
||||||
|
|
||||||
|
|
||||||
|
CauterizedModel::CauterizedModel(RigPointer rig, QObject* parent) : Model(rig, parent) {
|
||||||
|
}
|
||||||
|
|
||||||
|
CauterizedModel::~CauterizedModel() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void CauterizedModel::deleteGeometry() {
|
||||||
|
Model::deleteGeometry();
|
||||||
|
_cauterizeMeshStates.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called within Model::simulate call, below.
|
||||||
|
void CauterizedModel::updateRig(float deltaTime, glm::mat4 parentTransform) {
|
||||||
|
Model::updateRig(deltaTime, parentTransform);
|
||||||
|
_needsUpdateClusterMatrices = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CauterizedModel::createVisibleRenderItemSet() {
|
||||||
|
// Temporary HACK: use base class method for now
|
||||||
|
Model::createVisibleRenderItemSet();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CauterizedModel::createCollisionRenderItemSet() {
|
||||||
|
// Temporary HACK: use base class method for now
|
||||||
|
Model::createCollisionRenderItemSet();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CauterizedModel::updateGeometry() {
|
||||||
|
bool returnValue = Model::updateGeometry();
|
||||||
|
if (_rig->jointStatesEmpty() && getFBXGeometry().joints.size() > 0) {
|
||||||
|
const FBXGeometry& fbxGeometry = getFBXGeometry();
|
||||||
|
foreach (const FBXMesh& mesh, fbxGeometry.meshes) {
|
||||||
|
Model::MeshState state;
|
||||||
|
state.clusterMatrices.resize(mesh.clusters.size());
|
||||||
|
_cauterizeMeshStates.append(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return returnValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CauterizedModel::updateClusterMatrices() {
|
||||||
|
PerformanceTimer perfTimer("CauterizedModel::updateClusterMatrices");
|
||||||
|
|
||||||
|
if (!_needsUpdateClusterMatrices || !isLoaded()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_needsUpdateClusterMatrices = false;
|
||||||
|
const FBXGeometry& geometry = getFBXGeometry();
|
||||||
|
|
||||||
|
for (int i = 0; i < _meshStates.size(); i++) {
|
||||||
|
Model::MeshState& state = _meshStates[i];
|
||||||
|
const FBXMesh& mesh = geometry.meshes.at(i);
|
||||||
|
for (int j = 0; j < mesh.clusters.size(); j++) {
|
||||||
|
const FBXCluster& cluster = mesh.clusters.at(j);
|
||||||
|
auto jointMatrix = _rig->getJointTransform(cluster.jointIndex);
|
||||||
|
#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)
|
||||||
|
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.
|
||||||
|
if (!_cauterizeBoneSet.empty()) {
|
||||||
|
static const glm::mat4 zeroScale(
|
||||||
|
glm::vec4(0.0f, 0.0f, 0.0f, 0.0f),
|
||||||
|
glm::vec4(0.0f, 0.0f, 0.0f, 0.0f),
|
||||||
|
glm::vec4(0.0f, 0.0f, 0.0f, 0.0f),
|
||||||
|
glm::vec4(0.0f, 0.0f, 0.0f, 1.0f));
|
||||||
|
auto cauterizeMatrix = _rig->getJointTransform(geometry.neckJointIndex) * zeroScale;
|
||||||
|
|
||||||
|
for (int i = 0; i < _cauterizeMeshStates.size(); i++) {
|
||||||
|
Model::MeshState& state = _cauterizeMeshStates[i];
|
||||||
|
const FBXMesh& mesh = geometry.meshes.at(i);
|
||||||
|
for (int j = 0; j < mesh.clusters.size(); j++) {
|
||||||
|
const FBXCluster& cluster = mesh.clusters.at(j);
|
||||||
|
auto jointMatrix = _rig->getJointTransform(cluster.jointIndex);
|
||||||
|
if (_cauterizeBoneSet.find(cluster.jointIndex) != _cauterizeBoneSet.end()) {
|
||||||
|
jointMatrix = cauterizeMatrix;
|
||||||
|
}
|
||||||
|
#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
|
||||||
|
}
|
||||||
|
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// post the blender if we're not currently waiting for one to finish
|
||||||
|
if (geometry.hasBlendedMeshes() && _blendshapeCoefficients != _blendedBlendshapeCoefficients) {
|
||||||
|
_blendedBlendshapeCoefficients = _blendshapeCoefficients;
|
||||||
|
DependencyManager::get<ModelBlender>()->noteRequiresBlend(getThisPointer());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CauterizedModel::updateRenderItems() {
|
||||||
|
// Temporary HACK: use base class method for now
|
||||||
|
Model::updateRenderItems();
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef FOO
|
||||||
|
// TODO: finish implementing this
|
||||||
|
void CauterizedModel::updateRenderItems() {
|
||||||
|
if (!_addedToScene) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::vec3 scale = getScale();
|
||||||
|
if (_collisionGeometry) {
|
||||||
|
// _collisionGeometry is already scaled
|
||||||
|
scale = glm::vec3(1.0f);
|
||||||
|
}
|
||||||
|
_needsUpdateClusterMatrices = true;
|
||||||
|
_renderItemsNeedUpdate = false;
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
void* key = (void*)this;
|
||||||
|
std::weak_ptr<Model> weakSelf = shared_from_this();
|
||||||
|
AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [weakSelf, scale]() {
|
||||||
|
|
||||||
|
// do nothing, if the model has already been destroyed.
|
||||||
|
auto self = weakSelf.lock();
|
||||||
|
if (!self) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene();
|
||||||
|
|
||||||
|
Transform modelTransform;
|
||||||
|
modelTransform.setTranslation(self->getTranslation());
|
||||||
|
modelTransform.setRotation(self->getRotation());
|
||||||
|
|
||||||
|
Transform scaledModelTransform(modelTransform);
|
||||||
|
scaledModelTransform.setScale(scale);
|
||||||
|
|
||||||
|
uint32_t deleteGeometryCounter = self->getGeometryCounter();
|
||||||
|
|
||||||
|
// TODO: handle two cases:
|
||||||
|
// (a) our payloads are of type ModelMeshPartPayload
|
||||||
|
// (b) our payloads are of type ModelMeshPartPayload
|
||||||
|
render::PendingChanges pendingChanges;
|
||||||
|
QList<render::ItemID> keys = self->getRenderItems().keys();
|
||||||
|
foreach (auto itemID, keys) {
|
||||||
|
pendingChanges.updateItem<CauterizedMeshPartPayload>(itemID, [modelTransform, deleteGeometryCounter](CauterizedMeshPartPayload& data) {
|
||||||
|
if (data._model && data._model->isLoaded()) {
|
||||||
|
if (!data.hasStartedFade() && data._model->getGeometry()->areTexturesLoaded()) {
|
||||||
|
data.startFade();
|
||||||
|
}
|
||||||
|
// Ensure the model geometry was not reset between frames
|
||||||
|
if (deleteGeometryCounter == data._model->getGeometryCounter()) {
|
||||||
|
// 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();
|
||||||
|
|
||||||
|
// update the model transform and bounding box for this render item.
|
||||||
|
const Model::MeshState& state = data._model->getMeshState(data._meshIndex);
|
||||||
|
CauterizedModel* cModel = static_cast<CauterizedModel*>(data._model);
|
||||||
|
const Model::MeshState& cState = cModel->_cauterizeMeshStates.at(data._meshIndex);
|
||||||
|
data.updateTransformForSkinnedCauterizedMesh(modelTransform, state.clusterMatrices, cState.clusterMatrices);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
// collision mesh does not share the same unit scale as the FBX file's mesh: only apply offset
|
||||||
|
Transform collisionMeshOffset;
|
||||||
|
collisionMeshOffset.setIdentity();
|
||||||
|
foreach (auto itemID, self->_collisionRenderItems.keys()) {
|
||||||
|
pendingChanges.updateItem<MeshPartPayload>(itemID, [scaledModelTransform, collisionMeshOffset](MeshPartPayload& data) {
|
||||||
|
// update the model transform for this render item.
|
||||||
|
data.updateTransform(scaledModelTransform, collisionMeshOffset);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
scene->enqueuePendingChanges(pendingChanges);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
#endif // FOO
|
||||||
|
|
||||||
|
const Model::MeshState& CauterizedModel::getCauterizeMeshState(int index) const {
|
||||||
|
assert(index < _meshStates.size());
|
||||||
|
return _cauterizeMeshStates.at(index);
|
||||||
|
}
|
49
interface/src/avatar/CauterizedModel.h
Normal file
49
interface/src/avatar/CauterizedModel.h
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
//
|
||||||
|
// CauterizeableModel.h
|
||||||
|
// interface/src/avatar
|
||||||
|
//
|
||||||
|
// Created by Andrew Meadows 2016.01.17
|
||||||
|
// Copyright 2017 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef hifi_CauterizedModel_h
|
||||||
|
#define hifi_CauterizedModel_h
|
||||||
|
|
||||||
|
|
||||||
|
#include <Model.h>
|
||||||
|
|
||||||
|
class CauterizedModel : public Model {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
CauterizedModel(RigPointer rig, QObject* parent);
|
||||||
|
virtual ~CauterizedModel();
|
||||||
|
|
||||||
|
void deleteGeometry() override;
|
||||||
|
virtual void updateRig(float deltaTime, glm::mat4 parentTransform) override;
|
||||||
|
|
||||||
|
void setCauterizeBones(bool flag) { _cauterizeBones = flag; }
|
||||||
|
bool getCauterizeBones() const { return _cauterizeBones; }
|
||||||
|
|
||||||
|
const std::unordered_set<int>& getCauterizeBoneSet() const { return _cauterizeBoneSet; }
|
||||||
|
void setCauterizeBoneSet(const std::unordered_set<int>& boneSet) { _cauterizeBoneSet = boneSet; }
|
||||||
|
|
||||||
|
void createVisibleRenderItemSet() override;
|
||||||
|
void createCollisionRenderItemSet() override;
|
||||||
|
|
||||||
|
bool updateGeometry() override;
|
||||||
|
virtual void updateClusterMatrices() override;
|
||||||
|
void updateRenderItems() override;
|
||||||
|
|
||||||
|
const Model::MeshState& getCauterizeMeshState(int index) const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::unordered_set<int> _cauterizeBoneSet;
|
||||||
|
QVector<Model::MeshState> _cauterizeMeshStates;
|
||||||
|
bool _cauterizeBones { false };
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // hifi_CauterizedModel_h
|
|
@ -24,7 +24,7 @@
|
||||||
#include "AnimDebugDraw.h"
|
#include "AnimDebugDraw.h"
|
||||||
|
|
||||||
SkeletonModel::SkeletonModel(Avatar* owningAvatar, QObject* parent, RigPointer rig) :
|
SkeletonModel::SkeletonModel(Avatar* owningAvatar, QObject* parent, RigPointer rig) :
|
||||||
Model(rig, parent),
|
CauterizedModel(rig, parent),
|
||||||
_owningAvatar(owningAvatar),
|
_owningAvatar(owningAvatar),
|
||||||
_boundingCapsuleLocalOffset(0.0f),
|
_boundingCapsuleLocalOffset(0.0f),
|
||||||
_boundingCapsuleRadius(0.0f),
|
_boundingCapsuleRadius(0.0f),
|
||||||
|
@ -166,7 +166,7 @@ void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) {
|
||||||
_rig->computeMotionAnimationState(deltaTime, position, velocity, orientation, ccState);
|
_rig->computeMotionAnimationState(deltaTime, position, velocity, orientation, ccState);
|
||||||
|
|
||||||
// evaluate AnimGraph animation and update jointStates.
|
// evaluate AnimGraph animation and update jointStates.
|
||||||
Model::updateRig(deltaTime, parentTransform);
|
CauterizedModel::updateRig(deltaTime, parentTransform);
|
||||||
|
|
||||||
Rig::EyeParameters eyeParams;
|
Rig::EyeParameters eyeParams;
|
||||||
eyeParams.worldHeadOrientation = headParams.worldHeadOrientation;
|
eyeParams.worldHeadOrientation = headParams.worldHeadOrientation;
|
||||||
|
@ -178,10 +178,8 @@ void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) {
|
||||||
eyeParams.rightEyeJointIndex = geometry.rightEyeJointIndex;
|
eyeParams.rightEyeJointIndex = geometry.rightEyeJointIndex;
|
||||||
|
|
||||||
_rig->updateFromEyeParameters(eyeParams);
|
_rig->updateFromEyeParameters(eyeParams);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
CauterizedModel::updateRig(deltaTime, parentTransform);
|
||||||
Model::updateRig(deltaTime, parentTransform);
|
|
||||||
|
|
||||||
// This is a little more work than we really want.
|
// This is a little more work than we really want.
|
||||||
//
|
//
|
||||||
|
|
|
@ -12,8 +12,7 @@
|
||||||
#ifndef hifi_SkeletonModel_h
|
#ifndef hifi_SkeletonModel_h
|
||||||
#define hifi_SkeletonModel_h
|
#define hifi_SkeletonModel_h
|
||||||
|
|
||||||
|
#include "CauterizedModel.h"
|
||||||
#include <Model.h>
|
|
||||||
|
|
||||||
class Avatar;
|
class Avatar;
|
||||||
class MuscleConstraint;
|
class MuscleConstraint;
|
||||||
|
@ -23,7 +22,7 @@ using SkeletonModelPointer = std::shared_ptr<SkeletonModel>;
|
||||||
using SkeletonModelWeakPointer = std::weak_ptr<SkeletonModel>;
|
using SkeletonModelWeakPointer = std::weak_ptr<SkeletonModel>;
|
||||||
|
|
||||||
/// A skeleton loaded from a model.
|
/// A skeleton loaded from a model.
|
||||||
class SkeletonModel : public Model {
|
class SkeletonModel : public CauterizedModel {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -31,10 +30,10 @@ public:
|
||||||
SkeletonModel(Avatar* owningAvatar, QObject* parent = nullptr, RigPointer rig = nullptr);
|
SkeletonModel(Avatar* owningAvatar, QObject* parent = nullptr, RigPointer rig = nullptr);
|
||||||
~SkeletonModel();
|
~SkeletonModel();
|
||||||
|
|
||||||
virtual void initJointStates() override;
|
void initJointStates() override;
|
||||||
|
|
||||||
virtual void simulate(float deltaTime, bool fullUpdate = true) override;
|
void simulate(float deltaTime, bool fullUpdate = true) override;
|
||||||
virtual void updateRig(float deltaTime, glm::mat4 parentTransform) override;
|
void updateRig(float deltaTime, glm::mat4 parentTransform) override;
|
||||||
void updateAttitude();
|
void updateAttitude();
|
||||||
|
|
||||||
/// Returns the index of the left hand joint, or -1 if not found.
|
/// Returns the index of the left hand joint, or -1 if not found.
|
||||||
|
@ -105,7 +104,7 @@ public:
|
||||||
|
|
||||||
float getHeadClipDistance() const { return _headClipDistance; }
|
float getHeadClipDistance() const { return _headClipDistance; }
|
||||||
|
|
||||||
virtual void onInvalidate() override;
|
void onInvalidate() override;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
#include "InterfaceLogging.h"
|
#include "InterfaceLogging.h"
|
||||||
|
|
||||||
SoftAttachmentModel::SoftAttachmentModel(RigPointer rig, QObject* parent, RigPointer rigOverride) :
|
SoftAttachmentModel::SoftAttachmentModel(RigPointer rig, QObject* parent, RigPointer rigOverride) :
|
||||||
Model(rig, parent),
|
CauterizedModel(rig, parent),
|
||||||
_rigOverride(rigOverride) {
|
_rigOverride(rigOverride) {
|
||||||
assert(_rig);
|
assert(_rig);
|
||||||
assert(_rigOverride);
|
assert(_rigOverride);
|
||||||
|
@ -38,6 +38,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() {
|
void SoftAttachmentModel::updateClusterMatrices() {
|
||||||
|
// adebug TODO: this needs work?
|
||||||
if (!_needsUpdateClusterMatrices) {
|
if (!_needsUpdateClusterMatrices) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
#ifndef hifi_SoftAttachmentModel_h
|
#ifndef hifi_SoftAttachmentModel_h
|
||||||
#define hifi_SoftAttachmentModel_h
|
#define hifi_SoftAttachmentModel_h
|
||||||
|
|
||||||
#include <Model.h>
|
#include "CauterizedModel.h"
|
||||||
|
|
||||||
// A model that allows the creator to specify a secondary rig instance.
|
// A model that allows the creator to specify a secondary rig instance.
|
||||||
// When the cluster matrices are created for rendering, the
|
// When the cluster matrices are created for rendering, the
|
||||||
|
@ -22,16 +22,15 @@
|
||||||
// This is used by Avatar instances to wear clothing that follows the same
|
// This is used by Avatar instances to wear clothing that follows the same
|
||||||
// animated pose as the SkeletonModel.
|
// animated pose as the SkeletonModel.
|
||||||
|
|
||||||
class SoftAttachmentModel : public Model {
|
class SoftAttachmentModel : public CauterizedModel {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
SoftAttachmentModel(RigPointer rig, QObject* parent, RigPointer rigOverride);
|
SoftAttachmentModel(RigPointer rig, QObject* parent, RigPointer rigOverride);
|
||||||
~SoftAttachmentModel();
|
~SoftAttachmentModel();
|
||||||
|
|
||||||
virtual void updateRig(float deltaTime, glm::mat4 parentTransform) override;
|
void updateRig(float deltaTime, glm::mat4 parentTransform) override;
|
||||||
virtual void updateClusterMatrices() override;
|
void updateClusterMatrices() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
int getJointIndexOverride(int i) const;
|
int getJointIndexOverride(int i) const;
|
||||||
|
|
|
@ -251,7 +251,7 @@ void MeshPartPayload::bindMaterial(gpu::Batch& batch, const ShapePipeline::Locat
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MeshPartPayload::bindTransform(gpu::Batch& batch, const ShapePipeline::LocationsPointer locations, bool canCauterize) const {
|
void MeshPartPayload::bindTransform(gpu::Batch& batch, const ShapePipeline::LocationsPointer locations, RenderArgs::RenderMode renderMode) const {
|
||||||
batch.setModelTransform(_drawTransform);
|
batch.setModelTransform(_drawTransform);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -265,7 +265,7 @@ void MeshPartPayload::render(RenderArgs* args) const {
|
||||||
assert(locations);
|
assert(locations);
|
||||||
|
|
||||||
// Bind the model transform and the skinCLusterMatrices if needed
|
// Bind the model transform and the skinCLusterMatrices if needed
|
||||||
bindTransform(batch, locations);
|
bindTransform(batch, locations, args->_renderMode);
|
||||||
|
|
||||||
//Bind the index buffer and vertex buffer and Blend shapes if needed
|
//Bind the index buffer and vertex buffer and Blend shapes if needed
|
||||||
bindMesh(batch);
|
bindMesh(batch);
|
||||||
|
@ -359,11 +359,8 @@ void ModelMeshPartPayload::notifyLocationChanged() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModelMeshPartPayload::updateTransformForSkinnedMesh(const Transform& transform,
|
void ModelMeshPartPayload::updateTransformForSkinnedMesh(const Transform& transform, const QVector<glm::mat4>& clusterMatrices) {
|
||||||
const QVector<glm::mat4>& clusterMatrices,
|
|
||||||
const QVector<glm::mat4>& cauterizedClusterMatrices) {
|
|
||||||
_transform = transform;
|
_transform = transform;
|
||||||
_cauterizedTransform = transform;
|
|
||||||
|
|
||||||
if (clusterMatrices.size() > 0) {
|
if (clusterMatrices.size() > 0) {
|
||||||
_worldBound = AABox();
|
_worldBound = AABox();
|
||||||
|
@ -372,16 +369,7 @@ void ModelMeshPartPayload::updateTransformForSkinnedMesh(const Transform& transf
|
||||||
clusterBound.transform(clusterMatrix);
|
clusterBound.transform(clusterMatrix);
|
||||||
_worldBound += clusterBound;
|
_worldBound += clusterBound;
|
||||||
}
|
}
|
||||||
|
|
||||||
_worldBound.transform(transform);
|
_worldBound.transform(transform);
|
||||||
if (clusterMatrices.size() == 1) {
|
|
||||||
_transform = _transform.worldTransform(Transform(clusterMatrices[0]));
|
|
||||||
if (cauterizedClusterMatrices.size() != 0) {
|
|
||||||
_cauterizedTransform = _cauterizedTransform.worldTransform(Transform(cauterizedClusterMatrices[0]));
|
|
||||||
} else {
|
|
||||||
_cauterizedTransform = _transform;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -525,24 +513,13 @@ void ModelMeshPartPayload::bindMesh(gpu::Batch& batch) const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModelMeshPartPayload::bindTransform(gpu::Batch& batch, const ShapePipeline::LocationsPointer locations, bool canCauterize) const {
|
void ModelMeshPartPayload::bindTransform(gpu::Batch& batch, const 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
|
||||||
const Model::MeshState& state = _model->_meshStates.at(_meshIndex);
|
const Model::MeshState& state = _model->getMeshState(_meshIndex);
|
||||||
|
|
||||||
if (state.clusterBuffer) {
|
if (state.clusterBuffer) {
|
||||||
if (canCauterize && _model->getCauterizeBones()) {
|
batch.setUniformBuffer(ShapePipeline::Slot::BUFFER::SKINNING, state.clusterBuffer);
|
||||||
batch.setUniformBuffer(ShapePipeline::Slot::BUFFER::SKINNING, state.cauterizedClusterBuffer);
|
|
||||||
} else {
|
|
||||||
batch.setUniformBuffer(ShapePipeline::Slot::BUFFER::SKINNING, state.clusterBuffer);
|
|
||||||
}
|
|
||||||
batch.setModelTransform(_transform);
|
|
||||||
} else {
|
|
||||||
if (canCauterize && _model->getCauterizeBones()) {
|
|
||||||
batch.setModelTransform(_cauterizedTransform);
|
|
||||||
} else {
|
|
||||||
batch.setModelTransform(_transform);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
batch.setModelTransform(_transform);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModelMeshPartPayload::startFade() {
|
void ModelMeshPartPayload::startFade() {
|
||||||
|
@ -596,9 +573,8 @@ void ModelMeshPartPayload::render(RenderArgs* args) const {
|
||||||
assert(locations);
|
assert(locations);
|
||||||
|
|
||||||
// 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;
|
|
||||||
_model->updateClusterMatrices();
|
_model->updateClusterMatrices();
|
||||||
bindTransform(batch, locations, canCauterize);
|
bindTransform(batch, locations, args->_renderMode);
|
||||||
|
|
||||||
//Bind the index buffer and vertex buffer and Blend shapes if needed
|
//Bind the index buffer and vertex buffer and Blend shapes if needed
|
||||||
bindMesh(batch);
|
bindMesh(batch);
|
||||||
|
@ -621,4 +597,3 @@ void ModelMeshPartPayload::render(RenderArgs* args) const {
|
||||||
args->_details._trianglesRendered += _drawPart._numIndices / INDICES_PER_TRIANGLE;
|
args->_details._trianglesRendered += _drawPart._numIndices / INDICES_PER_TRIANGLE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,7 @@ public:
|
||||||
void drawCall(gpu::Batch& batch) const;
|
void drawCall(gpu::Batch& batch) const;
|
||||||
virtual void bindMesh(gpu::Batch& batch) const;
|
virtual void bindMesh(gpu::Batch& batch) const;
|
||||||
virtual void bindMaterial(gpu::Batch& batch, const render::ShapePipeline::LocationsPointer locations) const;
|
virtual void bindMaterial(gpu::Batch& batch, const render::ShapePipeline::LocationsPointer locations) const;
|
||||||
virtual void bindTransform(gpu::Batch& batch, const render::ShapePipeline::LocationsPointer locations, bool canCauterize = true) const;
|
virtual void bindTransform(gpu::Batch& batch, const render::ShapePipeline::LocationsPointer locations, RenderArgs::RenderMode renderMode) const;
|
||||||
|
|
||||||
// Payload resource cached values
|
// Payload resource cached values
|
||||||
std::shared_ptr<const model::Mesh> _drawMesh;
|
std::shared_ptr<const model::Mesh> _drawMesh;
|
||||||
|
@ -86,8 +86,7 @@ public:
|
||||||
|
|
||||||
void notifyLocationChanged() override;
|
void notifyLocationChanged() override;
|
||||||
void updateTransformForSkinnedMesh(const Transform& transform,
|
void updateTransformForSkinnedMesh(const Transform& transform,
|
||||||
const QVector<glm::mat4>& clusterMatrices,
|
const QVector<glm::mat4>& clusterMatrices);
|
||||||
const QVector<glm::mat4>& cauterizedClusterMatrices);
|
|
||||||
|
|
||||||
// Entity fade in
|
// Entity fade in
|
||||||
void startFade();
|
void startFade();
|
||||||
|
@ -102,13 +101,12 @@ 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 = true) const override;
|
void bindTransform(gpu::Batch& batch, const render::ShapePipeline::LocationsPointer locations, RenderArgs::RenderMode renderMode) const override;
|
||||||
|
|
||||||
void initCache();
|
void initCache();
|
||||||
|
|
||||||
Model* _model;
|
Model* _model;
|
||||||
|
|
||||||
Transform _cauterizedTransform;
|
|
||||||
int _meshIndex;
|
int _meshIndex;
|
||||||
int _shapeID;
|
int _shapeID;
|
||||||
|
|
||||||
|
|
|
@ -91,7 +91,6 @@ Model::Model(RigPointer rig, QObject* parent) :
|
||||||
_scaledToFit(false),
|
_scaledToFit(false),
|
||||||
_snapModelToRegistrationPoint(false),
|
_snapModelToRegistrationPoint(false),
|
||||||
_snappedToRegistrationPoint(false),
|
_snappedToRegistrationPoint(false),
|
||||||
_cauterizeBones(false),
|
|
||||||
_url(HTTP_INVALID_COM),
|
_url(HTTP_INVALID_COM),
|
||||||
_isVisible(true),
|
_isVisible(true),
|
||||||
_blendNumber(0),
|
_blendNumber(0),
|
||||||
|
@ -238,7 +237,7 @@ void Model::updateRenderItems() {
|
||||||
|
|
||||||
// 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, state.clusterMatrices, state.cauterizedClusterMatrices);
|
data.updateTransformForSkinnedMesh(modelTransform, state.clusterMatrices);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -294,8 +293,6 @@ 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());
|
||||||
state.cauterizedClusterMatrices.resize(mesh.clusters.size());
|
|
||||||
|
|
||||||
_meshStates.append(state);
|
_meshStates.append(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
|
||||||
|
@ -1159,13 +1156,6 @@ void Model::updateClusterMatrices() {
|
||||||
}
|
}
|
||||||
_needsUpdateClusterMatrices = false;
|
_needsUpdateClusterMatrices = false;
|
||||||
const FBXGeometry& geometry = getFBXGeometry();
|
const FBXGeometry& geometry = getFBXGeometry();
|
||||||
static const glm::mat4 zeroScale(
|
|
||||||
glm::vec4(0.0f, 0.0f, 0.0f, 0.0f),
|
|
||||||
glm::vec4(0.0f, 0.0f, 0.0f, 0.0f),
|
|
||||||
glm::vec4(0.0f, 0.0f, 0.0f, 0.0f),
|
|
||||||
glm::vec4(0.0f, 0.0f, 0.0f, 1.0f));
|
|
||||||
auto cauterizeMatrix = _rig->getJointTransform(geometry.neckJointIndex) * zeroScale;
|
|
||||||
|
|
||||||
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);
|
||||||
|
@ -1179,20 +1169,6 @@ void Model::updateClusterMatrices() {
|
||||||
#else
|
#else
|
||||||
state.clusterMatrices[j] = jointMatrix * cluster.inverseBindMatrix;
|
state.clusterMatrices[j] = jointMatrix * cluster.inverseBindMatrix;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// as an optimization, don't build cautrizedClusterMatrices if the boneSet is empty.
|
|
||||||
if (!_cauterizeBoneSet.empty()) {
|
|
||||||
if (_cauterizeBoneSet.find(cluster.jointIndex) != _cauterizeBoneSet.end()) {
|
|
||||||
jointMatrix = cauterizeMatrix;
|
|
||||||
}
|
|
||||||
#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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Once computed the cluster matrices, update the buffer(s)
|
// Once computed the cluster matrices, update the buffer(s)
|
||||||
|
@ -1204,17 +1180,6 @@ void Model::updateClusterMatrices() {
|
||||||
state.clusterBuffer->setSubData(0, state.clusterMatrices.size() * sizeof(glm::mat4),
|
state.clusterBuffer->setSubData(0, state.clusterMatrices.size() * sizeof(glm::mat4),
|
||||||
(const gpu::Byte*) state.clusterMatrices.constData());
|
(const gpu::Byte*) state.clusterMatrices.constData());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_cauterizeBoneSet.empty() && (state.cauterizedClusterMatrices.size() > 1)) {
|
|
||||||
if (!state.cauterizedClusterBuffer) {
|
|
||||||
state.cauterizedClusterBuffer =
|
|
||||||
std::make_shared<gpu::Buffer>(state.cauterizedClusterMatrices.size() * sizeof(glm::mat4),
|
|
||||||
(const gpu::Byte*) state.cauterizedClusterMatrices.constData());
|
|
||||||
} else {
|
|
||||||
state.cauterizedClusterBuffer->setSubData(0, state.cauterizedClusterMatrices.size() * sizeof(glm::mat4),
|
|
||||||
(const gpu::Byte*) state.cauterizedClusterMatrices.constData());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -101,7 +101,7 @@ public:
|
||||||
|
|
||||||
bool isLayeredInFront() const { return _isLayeredInFront; }
|
bool isLayeredInFront() const { return _isLayeredInFront; }
|
||||||
|
|
||||||
void updateRenderItems();
|
virtual void updateRenderItems();
|
||||||
void setRenderItemsNeedUpdate() { _renderItemsNeedUpdate = true; }
|
void setRenderItemsNeedUpdate() { _renderItemsNeedUpdate = true; }
|
||||||
bool getRenderItemsNeedUpdate() { return _renderItemsNeedUpdate; }
|
bool getRenderItemsNeedUpdate() { return _renderItemsNeedUpdate; }
|
||||||
AABox getRenderableMeshBound() const;
|
AABox getRenderableMeshBound() const;
|
||||||
|
@ -215,12 +215,6 @@ public:
|
||||||
bool getIsScaledToFit() const { return _scaledToFit; } /// is model scaled to fit
|
bool getIsScaledToFit() const { return _scaledToFit; } /// is model scaled to fit
|
||||||
glm::vec3 getScaleToFitDimensions() const; /// the dimensions model is scaled to, including inferred y/z
|
glm::vec3 getScaleToFitDimensions() const; /// the dimensions model is scaled to, including inferred y/z
|
||||||
|
|
||||||
void setCauterizeBones(bool flag) { _cauterizeBones = flag; }
|
|
||||||
bool getCauterizeBones() const { return _cauterizeBones; }
|
|
||||||
|
|
||||||
const std::unordered_set<int>& getCauterizeBoneSet() const { return _cauterizeBoneSet; }
|
|
||||||
void setCauterizeBoneSet(const std::unordered_set<int>& boneSet) { _cauterizeBoneSet = boneSet; }
|
|
||||||
|
|
||||||
int getBlendshapeCoefficientsNum() const { return _blendshapeCoefficients.size(); }
|
int getBlendshapeCoefficientsNum() const { return _blendshapeCoefficients.size(); }
|
||||||
float getBlendshapeCoefficient(int index) const {
|
float getBlendshapeCoefficient(int index) const {
|
||||||
return ((index < 0) && (index >= _blendshapeCoefficients.size())) ? 0.0f : _blendshapeCoefficients.at(index);
|
return ((index < 0) && (index >= _blendshapeCoefficients.size())) ? 0.0f : _blendshapeCoefficients.at(index);
|
||||||
|
@ -231,7 +225,7 @@ public:
|
||||||
const glm::vec3& getRegistrationPoint() const { return _registrationPoint; }
|
const glm::vec3& getRegistrationPoint() const { return _registrationPoint; }
|
||||||
|
|
||||||
// returns 'true' if needs fullUpdate after geometry change
|
// returns 'true' if needs fullUpdate after geometry change
|
||||||
bool updateGeometry();
|
virtual bool updateGeometry();
|
||||||
void setCollisionMesh(model::MeshPointer mesh);
|
void setCollisionMesh(model::MeshPointer mesh);
|
||||||
|
|
||||||
void setLoadingPriority(float priority) { _loadingPriority = priority; }
|
void setLoadingPriority(float priority) { _loadingPriority = priority; }
|
||||||
|
@ -242,6 +236,18 @@ public:
|
||||||
int getRenderInfoDrawCalls() const { return _renderInfoDrawCalls; }
|
int getRenderInfoDrawCalls() const { return _renderInfoDrawCalls; }
|
||||||
bool getRenderInfoHasTransparent() const { return _renderInfoHasTransparent; }
|
bool getRenderInfoHasTransparent() const { return _renderInfoHasTransparent; }
|
||||||
|
|
||||||
|
class MeshState {
|
||||||
|
public:
|
||||||
|
QVector<glm::mat4> clusterMatrices;
|
||||||
|
gpu::BufferPointer clusterBuffer;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
const MeshState& getMeshState(int index) { return _meshStates.at(index); }
|
||||||
|
|
||||||
|
uint32_t getGeometryCounter() const { return _deleteGeometryCounter; }
|
||||||
|
const QMap<render::ItemID, render::PayloadPointer>& getRenderItems() const { return _modelMeshRenderItems; }
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void loadURLFinished(bool success);
|
void loadURLFinished(bool success);
|
||||||
|
|
||||||
|
@ -298,18 +304,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
|
||||||
|
|
||||||
class MeshState {
|
|
||||||
public:
|
|
||||||
QVector<glm::mat4> clusterMatrices;
|
|
||||||
QVector<glm::mat4> cauterizedClusterMatrices;
|
|
||||||
gpu::BufferPointer clusterBuffer;
|
|
||||||
gpu::BufferPointer cauterizedClusterBuffer;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
QVector<MeshState> _meshStates;
|
QVector<MeshState> _meshStates;
|
||||||
std::unordered_set<int> _cauterizeBoneSet;
|
|
||||||
bool _cauterizeBones;
|
|
||||||
|
|
||||||
virtual void initJointStates();
|
virtual void initJointStates();
|
||||||
|
|
||||||
|
@ -342,7 +337,7 @@ protected:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
void deleteGeometry();
|
virtual void deleteGeometry();
|
||||||
void initJointTransforms();
|
void initJointTransforms();
|
||||||
|
|
||||||
QVector<float> _blendshapeCoefficients;
|
QVector<float> _blendshapeCoefficients;
|
||||||
|
@ -371,12 +366,11 @@ protected:
|
||||||
void recalculateMeshBoxes(bool pickAgainstTriangles = false);
|
void recalculateMeshBoxes(bool pickAgainstTriangles = false);
|
||||||
|
|
||||||
void createRenderItemSet();
|
void createRenderItemSet();
|
||||||
void createVisibleRenderItemSet();
|
virtual void createVisibleRenderItemSet();
|
||||||
void createCollisionRenderItemSet();
|
virtual void createCollisionRenderItemSet();
|
||||||
|
|
||||||
bool _isWireframe;
|
bool _isWireframe;
|
||||||
|
|
||||||
|
|
||||||
// debug rendering support
|
// debug rendering support
|
||||||
void renderDebugMeshBoxes(gpu::Batch& batch);
|
void renderDebugMeshBoxes(gpu::Batch& batch);
|
||||||
int _debugMeshBoxesID = GeometryCache::UNKNOWN_ID;
|
int _debugMeshBoxesID = GeometryCache::UNKNOWN_ID;
|
||||||
|
|
Loading…
Reference in a new issue