Merge pull request #8205 from AndrewMeadows/model-cache-cleanup

decouple Geometry from its GeometryResource in ModelCache
This commit is contained in:
Brad Hefta-Gaub 2016-07-15 12:38:46 -07:00 committed by GitHub
commit 496f3b14c7
7 changed files with 152 additions and 147 deletions

View file

@ -709,9 +709,9 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& info) {
// compute meshPart local transforms
QVector<glm::mat4> localTransforms;
const FBXGeometry& fbxGeometry = _model->getFBXGeometry();
int32_t numMeshes = (int32_t)fbxGeometry.meshes.size();
int32_t totalNumVertices = 0;
for (int32_t i = 0; i < numMeshes; i++) {
int numFbxMeshes = fbxGeometry.meshes.size();
int totalNumVertices = 0;
for (int i = 0; i < numFbxMeshes; i++) {
const FBXMesh& mesh = fbxGeometry.meshes.at(i);
if (mesh.clusters.size() > 0) {
const FBXCluster& cluster = mesh.clusters.at(0);
@ -730,10 +730,8 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& info) {
return;
}
auto& meshes = _model->getGeometry()->getGeometry()->getMeshes();
// the render geometry's mesh count should match that of the FBXGeometry
assert(numMeshes == (int32_t)(meshes.size()));
auto& meshes = _model->getGeometry()->getMeshes();
int32_t numMeshes = (int32_t)(meshes.size());
ShapeInfo::PointCollection& pointCollection = info.getPointCollection();
pointCollection.clear();

View file

@ -70,7 +70,7 @@ void GeometryMappingResource::downloadFinished(const QByteArray& data) {
auto modelCache = DependencyManager::get<ModelCache>();
GeometryExtra extra{ mapping, _textureBaseUrl };
// Get the raw GeometryResource, not the wrapped NetworkGeometry
// Get the raw GeometryResource
_geometryResource = modelCache->getResource(url, QUrl(), &extra).staticCast<GeometryResource>();
// Avoid caching nested resources - their references will be held by the parent
_geometryResource->_isCacheable = false;
@ -90,8 +90,8 @@ void GeometryMappingResource::downloadFinished(const QByteArray& data) {
void GeometryMappingResource::onGeometryMappingLoaded(bool success) {
if (success && _geometryResource) {
_geometry = _geometryResource->_geometry;
_shapes = _geometryResource->_shapes;
_fbxGeometry = _geometryResource->_fbxGeometry;
_meshParts = _geometryResource->_meshParts;
_meshes = _geometryResource->_meshes;
_materials = _geometryResource->_materials;
@ -200,31 +200,31 @@ void GeometryDefinitionResource::downloadFinished(const QByteArray& data) {
void GeometryDefinitionResource::setGeometryDefinition(FBXGeometry::Pointer fbxGeometry) {
// Assume ownership of the geometry pointer
_geometry = fbxGeometry;
_fbxGeometry = fbxGeometry;
// Copy materials
QHash<QString, size_t> materialIDAtlas;
for (const FBXMaterial& material : _geometry->materials) {
for (const FBXMaterial& material : _fbxGeometry->materials) {
materialIDAtlas[material.materialID] = _materials.size();
_materials.push_back(std::make_shared<NetworkMaterial>(material, _textureBaseUrl));
}
std::shared_ptr<NetworkMeshes> meshes = std::make_shared<NetworkMeshes>();
std::shared_ptr<NetworkShapes> shapes = std::make_shared<NetworkShapes>();
std::shared_ptr<GeometryMeshes> meshes = std::make_shared<GeometryMeshes>();
std::shared_ptr<GeometryMeshParts> parts = std::make_shared<GeometryMeshParts>();
int meshID = 0;
for (const FBXMesh& mesh : _geometry->meshes) {
for (const FBXMesh& mesh : _fbxGeometry->meshes) {
// Copy mesh pointers
meshes->emplace_back(mesh._mesh);
int partID = 0;
for (const FBXMeshPart& part : mesh.parts) {
// Construct local shapes
shapes->push_back(std::make_shared<NetworkShape>(meshID, partID, (int)materialIDAtlas[part.materialID]));
// Construct local parts
parts->push_back(std::make_shared<MeshPart>(meshID, partID, (int)materialIDAtlas[part.materialID]));
partID++;
}
meshID++;
}
_meshes = meshes;
_shapes = shapes;
_meshParts = parts;
finishedLoading(true);
}
@ -250,17 +250,15 @@ QSharedPointer<Resource> ModelCache::createResource(const QUrl& url, const QShar
return QSharedPointer<Resource>(resource, &Resource::deleter);
}
std::shared_ptr<NetworkGeometry> ModelCache::getGeometry(const QUrl& url, const QVariantHash& mapping, const QUrl& textureBaseUrl) {
GeometryResource::Pointer ModelCache::getGeometryResource(const QUrl& url, const QVariantHash& mapping, const QUrl& textureBaseUrl) {
GeometryExtra geometryExtra = { mapping, textureBaseUrl };
GeometryResource::Pointer resource = getResource(url, QUrl(), &geometryExtra).staticCast<GeometryResource>();
if (resource) {
if (resource->isLoaded() && resource->shouldSetTextures()) {
resource->setTextures();
}
return std::make_shared<NetworkGeometry>(resource);
} else {
return NetworkGeometry::Pointer();
}
return resource;
}
const QVariantMap Geometry::getTextures() const {
@ -278,9 +276,9 @@ const QVariantMap Geometry::getTextures() const {
// FIXME: The materials should only be copied when modified, but the Model currently caches the original
Geometry::Geometry(const Geometry& geometry) {
_geometry = geometry._geometry;
_fbxGeometry = geometry._fbxGeometry;
_meshes = geometry._meshes;
_shapes = geometry._shapes;
_meshParts = geometry._meshParts;
_materials.reserve(geometry._materials.size());
for (const auto& material : geometry._materials) {
@ -336,9 +334,9 @@ bool Geometry::areTexturesLoaded() const {
return true;
}
const std::shared_ptr<const NetworkMaterial> Geometry::getShapeMaterial(int shapeID) const {
if ((shapeID >= 0) && (shapeID < (int)_shapes->size())) {
int materialID = _shapes->at(shapeID)->materialID;
const std::shared_ptr<const NetworkMaterial> Geometry::getShapeMaterial(int partID) const {
if ((partID >= 0) && (partID < (int)_meshParts->size())) {
int materialID = _meshParts->at(partID)->materialID;
if ((materialID >= 0) && (materialID < (int)_materials.size())) {
return _materials[materialID];
}
@ -352,7 +350,7 @@ void GeometryResource::deleter() {
}
void GeometryResource::setTextures() {
for (const FBXMaterial& material : _geometry->materials) {
for (const FBXMaterial& material : _fbxGeometry->materials) {
_materials.push_back(std::make_shared<NetworkMaterial>(material, _textureBaseUrl));
}
}
@ -361,26 +359,40 @@ void GeometryResource::resetTextures() {
_materials.clear();
}
NetworkGeometry::NetworkGeometry(const GeometryResource::Pointer& networkGeometry) : _resource(networkGeometry) {
connect(_resource.data(), &Resource::finished, this, &NetworkGeometry::resourceFinished);
connect(_resource.data(), &Resource::onRefresh, this, &NetworkGeometry::resourceRefreshed);
void GeometryResourceWatcher::startWatching() {
connect(_resource.data(), &Resource::finished, this, &GeometryResourceWatcher::resourceFinished);
connect(_resource.data(), &Resource::onRefresh, this, &GeometryResourceWatcher::resourceRefreshed);
if (_resource->isLoaded()) {
resourceFinished(!_resource->getURL().isEmpty());
}
}
void NetworkGeometry::resourceFinished(bool success) {
// FIXME: Model is not set up to handle a refresh
if (_instance) {
return;
}
if (success) {
_instance = std::make_shared<Geometry>(*_resource);
}
emit finished(success);
void GeometryResourceWatcher::stopWatching() {
disconnect(_resource.data(), &Resource::finished, this, &GeometryResourceWatcher::resourceFinished);
disconnect(_resource.data(), &Resource::onRefresh, this, &GeometryResourceWatcher::resourceRefreshed);
}
void NetworkGeometry::resourceRefreshed() {
void GeometryResourceWatcher::setResource(GeometryResource::Pointer resource) {
if (_resource) {
stopWatching();
}
_resource = resource;
if (_resource) {
if (_resource->isLoaded()) {
_geometryRef = std::make_shared<Geometry>(*_resource);
} else {
startWatching();
}
}
}
void GeometryResourceWatcher::resourceFinished(bool success) {
if (success) {
_geometryRef = std::make_shared<Geometry>(*_resource);
}
}
void GeometryResourceWatcher::resourceRefreshed() {
// FIXME: Model is not set up to handle a refresh
// _instance.reset();
}

View file

@ -22,52 +22,30 @@
#include "TextureCache.h"
// Alias instead of derive to avoid copying
using NetworkMesh = model::Mesh;
class NetworkTexture;
class NetworkMaterial;
class NetworkShape;
class NetworkGeometry;
class MeshPart;
class GeometryMappingResource;
/// Stores cached model geometries.
class ModelCache : public ResourceCache, public Dependency {
Q_OBJECT
SINGLETON_DEPENDENCY
public:
/// Loads a model geometry from the specified URL.
std::shared_ptr<NetworkGeometry> getGeometry(const QUrl& url,
const QVariantHash& mapping = QVariantHash(), const QUrl& textureBaseUrl = QUrl());
protected:
friend class GeometryMappingResource;
virtual QSharedPointer<Resource> createResource(const QUrl& url, const QSharedPointer<Resource>& fallback,
const void* extra);
private:
ModelCache();
virtual ~ModelCache() = default;
};
class Geometry {
public:
using Pointer = std::shared_ptr<Geometry>;
using WeakPointer = std::weak_ptr<Geometry>;
Geometry() = default;
Geometry(const Geometry& geometry);
// Immutable over lifetime
using NetworkMeshes = std::vector<std::shared_ptr<const NetworkMesh>>;
using NetworkShapes = std::vector<std::shared_ptr<const NetworkShape>>;
using GeometryMeshes = std::vector<std::shared_ptr<const model::Mesh>>;
using GeometryMeshParts = std::vector<std::shared_ptr<const MeshPart>>;
// Mutable, but must retain structure of vector
using NetworkMaterials = std::vector<std::shared_ptr<NetworkMaterial>>;
const FBXGeometry& getGeometry() const { return *_geometry; }
const NetworkMeshes& getMeshes() const { return *_meshes; }
const FBXGeometry& getFBXGeometry() const { return *_fbxGeometry; }
const GeometryMeshes& getMeshes() const { return *_meshes; }
const std::shared_ptr<const NetworkMaterial> getShapeMaterial(int shapeID) const;
const QVariantMap getTextures() const;
@ -79,9 +57,9 @@ protected:
friend class GeometryMappingResource;
// Shared across all geometries, constant throughout lifetime
std::shared_ptr<const FBXGeometry> _geometry;
std::shared_ptr<const NetworkMeshes> _meshes;
std::shared_ptr<const NetworkShapes> _shapes;
std::shared_ptr<const FBXGeometry> _fbxGeometry;
std::shared_ptr<const GeometryMeshes> _meshes;
std::shared_ptr<const GeometryMeshParts> _meshParts;
// Copied to each geometry, mutable throughout lifetime via setTextures
NetworkMaterials _materials;
@ -108,7 +86,7 @@ protected:
// Geometries may not hold onto textures while cached - that is for the texture cache
// Instead, these methods clear and reset textures from the geometry when caching/loading
bool shouldSetTextures() const { return _geometry && _materials.empty(); }
bool shouldSetTextures() const { return _fbxGeometry && _materials.empty(); }
void setTextures();
void resetTextures();
@ -118,22 +96,21 @@ protected:
bool _isCacheable { true };
};
class NetworkGeometry : public QObject {
class GeometryResourceWatcher : public QObject {
Q_OBJECT
public:
using Pointer = std::shared_ptr<NetworkGeometry>;
using Pointer = std::shared_ptr<GeometryResourceWatcher>;
NetworkGeometry() = delete;
NetworkGeometry(const GeometryResource::Pointer& networkGeometry);
GeometryResourceWatcher() = delete;
GeometryResourceWatcher(Geometry::Pointer& geometryPtr) : _geometryRef(geometryPtr) {}
const QUrl& getURL() { return _resource->getURL(); }
void setResource(GeometryResource::Pointer resource);
/// Returns the geometry, if it is loaded (must be checked!)
const Geometry::Pointer& getGeometry() { return _instance; }
QUrl getURL() const { return (bool)_resource ? _resource->getURL() : QUrl(); }
signals:
/// Emitted when the NetworkGeometry loads (or fails to)
void finished(bool success);
private:
void startWatching();
void stopWatching();
private slots:
void resourceFinished(bool success);
@ -141,7 +118,27 @@ private slots:
private:
GeometryResource::Pointer _resource;
Geometry::Pointer _instance { nullptr };
Geometry::Pointer& _geometryRef;
};
/// Stores cached model geometries.
class ModelCache : public ResourceCache, public Dependency {
Q_OBJECT
SINGLETON_DEPENDENCY
public:
GeometryResource::Pointer getGeometryResource(const QUrl& url,
const QVariantHash& mapping = QVariantHash(), const QUrl& textureBaseUrl = QUrl());
protected:
friend class GeometryMappingResource;
virtual QSharedPointer<Resource> createResource(const QUrl& url, const QSharedPointer<Resource>& fallback,
const void* extra);
private:
ModelCache();
virtual ~ModelCache() = default;
};
class NetworkMaterial : public model::Material {
@ -185,9 +182,9 @@ private:
bool _isOriginal { true };
};
class NetworkShape {
class MeshPart {
public:
NetworkShape(int mesh, int part, int material) : meshID { mesh }, partID { part }, materialID { material } {}
MeshPart(int mesh, int part, int material) : meshID { mesh }, partID { part }, materialID { material } {}
int meshID { -1 };
int partID { -1 };
int materialID { -1 };

View file

@ -402,8 +402,6 @@ private:
QHash<Vec2FloatPairPair, GridBuffer> _gridBuffers;
QHash<int, GridBuffer> _registeredGridBuffers;
QHash<QUrl, QWeakPointer<NetworkGeometry> > _networkGeometry;
gpu::ShaderPointer _simpleShader;
gpu::ShaderPointer _unlitShader;
static render::ShapePipelinePointer _simplePipeline;

View file

@ -310,7 +310,7 @@ ModelMeshPartPayload::ModelMeshPartPayload(Model* model, int _meshIndex, int par
_shapeID(shapeIndex) {
assert(_model && _model->isLoaded());
auto& modelMesh = _model->getGeometry()->getGeometry()->getMeshes().at(_meshIndex);
auto& modelMesh = _model->getGeometry()->getMeshes().at(_meshIndex);
updateMeshPart(modelMesh, partIndex);
updateTransform(transform, offsetTransform);
@ -331,7 +331,7 @@ void ModelMeshPartPayload::initCache() {
_isBlendShaped = !mesh.blendshapes.isEmpty();
}
auto networkMaterial = _model->getGeometry()->getGeometry()->getShapeMaterial(_shapeID);
auto networkMaterial = _model->getGeometry()->getShapeMaterial(_shapeID);
if (networkMaterial) {
_drawMaterial = networkMaterial;
};
@ -384,7 +384,7 @@ ItemKey ModelMeshPartPayload::getKey() const {
ShapeKey ModelMeshPartPayload::getShapeKey() const {
assert(_model->isLoaded());
const FBXGeometry& geometry = _model->getFBXGeometry();
const auto& networkMeshes = _model->getGeometry()->getGeometry()->getMeshes();
const auto& networkMeshes = _model->getGeometry()->getMeshes();
// guard against partially loaded meshes
if (_meshIndex >= (int)networkMeshes.size() || _meshIndex >= (int)geometry.meshes.size() || _meshIndex >= (int)_model->_meshStates.size()) {

View file

@ -31,7 +31,7 @@
using namespace std;
int nakedModelPointerTypeId = qRegisterMetaType<ModelPointer>();
int weakNetworkGeometryPointerTypeId = qRegisterMetaType<std::weak_ptr<NetworkGeometry> >();
int weakGeometryResourceBridgePointerTypeId = qRegisterMetaType<Geometry::WeakPointer >();
int vec3VectorTypeId = qRegisterMetaType<QVector<glm::vec3> >();
float Model::FAKE_DIMENSION_PLACEHOLDER = -1.0f;
#define HTTP_INVALID_COM "http://invalid.com"
@ -79,6 +79,10 @@ void initCollisionHullMaterials() {
Model::Model(RigPointer rig, QObject* parent) :
QObject(parent),
_renderGeometry(),
_collisionGeometry(),
_renderWatcher(_renderGeometry),
_collisionWatcher(_collisionGeometry),
_translation(0.0f),
_rotation(),
_scale(1.0f, 1.0f, 1.0f),
@ -98,7 +102,6 @@ Model::Model(RigPointer rig, QObject* parent) :
_calculatedMeshTrianglesValid(false),
_meshGroupsKnown(false),
_isWireframe(false),
_renderCollisionHull(false),
_rig(rig) {
// we may have been created in the network thread, but we live in the main thread
if (_viewState) {
@ -116,7 +119,7 @@ AbstractViewStateInterface* Model::_viewState = NULL;
bool Model::needsFixupInScene() const {
if (readyToAddToScene()) {
if (_needsUpdateTextures && _geometry->getGeometry()->areTexturesLoaded()) {
if (_needsUpdateTextures && _renderGeometry->areTexturesLoaded()) {
_needsUpdateTextures = false;
return true;
}
@ -793,13 +796,13 @@ int Model::getLastFreeJointIndex(int jointIndex) const {
void Model::setTextures(const QVariantMap& textures) {
if (isLoaded()) {
_needsUpdateTextures = true;
_geometry->getGeometry()->setTextures(textures);
_renderGeometry->setTextures(textures);
}
}
void Model::setURL(const QUrl& url) {
// don't recreate the geometry if it's the same URL
if (_url == url && _geometry && _geometry->getURL() == url) {
if (_url == url && _renderWatcher.getURL() == url) {
return;
}
@ -818,16 +821,16 @@ void Model::setURL(const QUrl& url) {
invalidCalculatedMeshBoxes();
deleteGeometry();
_geometry = DependencyManager::get<ModelCache>()->getGeometry(url);
_renderWatcher.setResource(DependencyManager::get<ModelCache>()->getGeometryResource(url));
onInvalidate();
}
void Model::setCollisionModelURL(const QUrl& url) {
if (_collisionUrl == url) {
if (_collisionUrl == url && _collisionWatcher.getURL() == url) {
return;
}
_collisionUrl = url;
_collisionGeometry = DependencyManager::get<ModelCache>()->getGeometry(url);
_collisionWatcher.setResource(DependencyManager::get<ModelCache>()->getGeometryResource(url));
}
bool Model::getJointPositionInWorldFrame(int jointIndex, glm::vec3& position) const {
@ -883,7 +886,7 @@ QStringList Model::getJointNames() const {
class Blender : public QRunnable {
public:
Blender(ModelPointer model, int blendNumber, const std::weak_ptr<NetworkGeometry>& geometry,
Blender(ModelPointer model, int blendNumber, const Geometry::WeakPointer& geometry,
const QVector<FBXMesh>& meshes, const QVector<float>& blendshapeCoefficients);
virtual void run();
@ -892,12 +895,12 @@ private:
ModelPointer _model;
int _blendNumber;
std::weak_ptr<NetworkGeometry> _geometry;
Geometry::WeakPointer _geometry;
QVector<FBXMesh> _meshes;
QVector<float> _blendshapeCoefficients;
};
Blender::Blender(ModelPointer model, int blendNumber, const std::weak_ptr<NetworkGeometry>& geometry,
Blender::Blender(ModelPointer model, int blendNumber, const Geometry::WeakPointer& geometry,
const QVector<FBXMesh>& meshes, const QVector<float>& blendshapeCoefficients) :
_model(model),
_blendNumber(blendNumber),
@ -940,7 +943,7 @@ void Blender::run() {
// post the result to the geometry cache, which will dispatch to the model if still alive
QMetaObject::invokeMethod(DependencyManager::get<ModelBlender>().data(), "setBlendedVertices",
Q_ARG(ModelPointer, _model), Q_ARG(int, _blendNumber),
Q_ARG(const std::weak_ptr<NetworkGeometry>&, _geometry), Q_ARG(const QVector<glm::vec3>&, vertices),
Q_ARG(const Geometry::WeakPointer&, _geometry), Q_ARG(const QVector<glm::vec3>&, vertices),
Q_ARG(const QVector<glm::vec3>&, normals));
}
@ -1151,7 +1154,7 @@ bool Model::maybeStartBlender() {
if (isLoaded()) {
const FBXGeometry& fbxGeometry = getFBXGeometry();
if (fbxGeometry.hasBlendedMeshes()) {
QThreadPool::globalInstance()->start(new Blender(getThisPointer(), ++_blendNumber, _geometry,
QThreadPool::globalInstance()->start(new Blender(getThisPointer(), ++_blendNumber, _renderGeometry,
fbxGeometry.meshes, _blendshapeCoefficients));
return true;
}
@ -1159,10 +1162,10 @@ bool Model::maybeStartBlender() {
return false;
}
void Model::setBlendedVertices(int blendNumber, const std::weak_ptr<NetworkGeometry>& geometry,
void Model::setBlendedVertices(int blendNumber, const Geometry::WeakPointer& geometry,
const QVector<glm::vec3>& vertices, const QVector<glm::vec3>& normals) {
auto geometryRef = geometry.lock();
if (!geometryRef || _geometry != geometryRef || _blendedVertexBuffers.empty() || blendNumber < _appliedBlendNumber) {
if (!geometryRef || _renderGeometry != geometryRef || _blendedVertexBuffers.empty() || blendNumber < _appliedBlendNumber) {
return;
}
_appliedBlendNumber = blendNumber;
@ -1205,27 +1208,23 @@ AABox Model::getRenderableMeshBound() const {
}
void Model::segregateMeshGroups() {
NetworkGeometry::Pointer networkGeometry;
Geometry::Pointer geometry;
bool showingCollisionHull = false;
if (_showCollisionHull && _collisionGeometry) {
if (isCollisionLoaded()) {
networkGeometry = _collisionGeometry;
geometry = _collisionGeometry;
showingCollisionHull = true;
} else {
return;
}
} else {
assert(isLoaded());
networkGeometry = _geometry;
geometry = _renderGeometry;
}
const FBXGeometry& geometry = networkGeometry->getGeometry()->getGeometry();
const auto& networkMeshes = networkGeometry->getGeometry()->getMeshes();
const auto& meshes = geometry->getMeshes();
// all of our mesh vectors must match in size
auto geoMeshesSize = geometry.meshes.size();
if ((int)networkMeshes.size() != geoMeshesSize ||
// geometry.meshes.size() != _meshStates.size()) {
geoMeshesSize > _meshStates.size()) {
if ((int)meshes.size() != _meshStates.size()) {
qDebug() << "WARNING!!!! Mesh Sizes don't match! We will not segregate mesh groups yet.";
return;
}
@ -1249,23 +1248,25 @@ void Model::segregateMeshGroups() {
// Run through all of the meshes, and place them into their segregated, but unsorted buckets
int shapeID = 0;
for (int i = 0; i < (int)networkMeshes.size(); i++) {
const FBXMesh& mesh = geometry.meshes.at(i);
const auto& networkMesh = networkMeshes.at(i);
uint32_t numMeshes = (uint32_t)meshes.size();
for (uint32_t i = 0; i < numMeshes; i++) {
const auto& mesh = meshes.at(i);
if (mesh) {
// Create the render payloads
int totalParts = mesh.parts.size();
for (int partIndex = 0; partIndex < totalParts; partIndex++) {
if (showingCollisionHull) {
if (_collisionHullMaterials.empty()) {
initCollisionHullMaterials();
// Create the render payloads
int numParts = (int)mesh->getNumParts();
for (int partIndex = 0; partIndex < numParts; partIndex++) {
if (showingCollisionHull) {
if (_collisionHullMaterials.empty()) {
initCollisionHullMaterials();
}
_collisionRenderItemsSet << std::make_shared<MeshPartPayload>(mesh, partIndex, _collisionHullMaterials[partIndex % NUM_COLLISION_HULL_COLORS], transform, offset);
} else {
_modelMeshRenderItemsSet << std::make_shared<ModelMeshPartPayload>(this, i, partIndex, shapeID, transform, offset);
}
_collisionRenderItemsSet << std::make_shared<MeshPartPayload>(networkMesh, partIndex, _collisionHullMaterials[partIndex % NUM_COLLISION_HULL_COLORS], transform, offset);
} else {
_modelMeshRenderItemsSet << std::make_shared<ModelMeshPartPayload>(this, i, partIndex, shapeID, transform, offset);
}
shapeID++;
shapeID++;
}
}
}
_meshGroupsKnown = true;
@ -1328,7 +1329,7 @@ void ModelBlender::noteRequiresBlend(ModelPointer model) {
}
void ModelBlender::setBlendedVertices(ModelPointer model, int blendNumber,
const std::weak_ptr<NetworkGeometry>& geometry, const QVector<glm::vec3>& vertices, const QVector<glm::vec3>& normals) {
const Geometry::WeakPointer& geometry, const QVector<glm::vec3>& vertices, const QVector<glm::vec3>& normals) {
if (model) {
model->setBlendedVertices(blendNumber, geometry, vertices, normals);
}

View file

@ -97,7 +97,7 @@ public:
bool showCollisionHull = false);
void removeFromScene(std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges);
void renderSetup(RenderArgs* args);
bool isRenderable() const { return !_meshStates.isEmpty() || (isActive() && getGeometry()->getGeometry()->getMeshes().empty()); }
bool isRenderable() const { return !_meshStates.isEmpty() || (isActive() && _renderGeometry->getMeshes().empty()); }
bool isVisible() const { return _isVisible; }
@ -107,11 +107,11 @@ public:
bool maybeStartBlender();
/// Sets blended vertices computed in a separate thread.
void setBlendedVertices(int blendNumber, const std::weak_ptr<NetworkGeometry>& geometry,
void setBlendedVertices(int blendNumber, const Geometry::WeakPointer& geometry,
const QVector<glm::vec3>& vertices, const QVector<glm::vec3>& normals);
bool isLoaded() const { return _geometry && _geometry->getGeometry(); }
bool isCollisionLoaded() const { return _collisionGeometry && _collisionGeometry->getGeometry(); }
bool isLoaded() const { return (bool)_renderGeometry; }
bool isCollisionLoaded() const { return (bool)_collisionGeometry; }
void setIsWireframe(bool isWireframe) { _isWireframe = isWireframe; }
bool isWireframe() const { return _isWireframe; }
@ -128,18 +128,18 @@ public:
virtual void updateClusterMatrices(glm::vec3 modelPosition, glm::quat modelOrientation);
/// Returns a reference to the shared geometry.
const NetworkGeometry::Pointer& getGeometry() const { return _geometry; }
const Geometry::Pointer& getGeometry() const { return _renderGeometry; }
/// Returns a reference to the shared collision geometry.
const NetworkGeometry::Pointer& getCollisionGeometry() const { return _collisionGeometry; }
const Geometry::Pointer& getCollisionGeometry() const { return _collisionGeometry; }
const QVariantMap getTextures() const { assert(isLoaded()); return _geometry->getGeometry()->getTextures(); }
const QVariantMap getTextures() const { assert(isLoaded()); return _renderGeometry->getTextures(); }
void setTextures(const QVariantMap& textures);
/// Provided as a convenience, will crash if !isLoaded()
// And so that getGeometry() isn't chained everywhere
const FBXGeometry& getFBXGeometry() const { assert(isLoaded()); return getGeometry()->getGeometry()->getGeometry(); }
const FBXGeometry& getFBXGeometry() const { assert(isLoaded()); return _renderGeometry->getFBXGeometry(); }
/// Provided as a convenience, will crash if !isCollisionLoaded()
const FBXGeometry& getCollisionFBXGeometry() const { assert(isCollisionLoaded()); return getCollisionGeometry()->getGeometry()->getGeometry(); }
const FBXGeometry& getCollisionFBXGeometry() const { assert(isCollisionLoaded()); return _collisionGeometry->getFBXGeometry(); }
// Set the model to use for collisions.
// Should only be called from the model's rendering thread to avoid access violations of changed geometry.
@ -263,7 +263,11 @@ protected:
/// \return true if joint exists
bool getJointPosition(int jointIndex, glm::vec3& position) const;
NetworkGeometry::Pointer _geometry;
Geometry::Pointer _renderGeometry; // only ever set by its watcher
Geometry::Pointer _collisionGeometry; // only ever set by its watcher
GeometryResourceWatcher _renderWatcher;
GeometryResourceWatcher _collisionWatcher;
glm::vec3 _translation;
glm::quat _rotation;
@ -330,8 +334,6 @@ protected:
void deleteGeometry();
void initJointTransforms();
NetworkGeometry::Pointer _collisionGeometry;
float _pupilDilation;
QVector<float> _blendshapeCoefficients;
@ -373,9 +375,6 @@ protected:
static AbstractViewStateInterface* _viewState;
bool _renderCollisionHull;
QSet<std::shared_ptr<MeshPartPayload>> _collisionRenderItemsSet;
QMap<render::ItemID, render::PayloadPointer> _collisionRenderItems;
@ -395,7 +394,7 @@ protected:
};
Q_DECLARE_METATYPE(ModelPointer)
Q_DECLARE_METATYPE(std::weak_ptr<NetworkGeometry>)
Q_DECLARE_METATYPE(Geometry::WeakPointer)
/// Handle management of pending models that need blending
class ModelBlender : public QObject, public Dependency {
@ -408,7 +407,7 @@ public:
void noteRequiresBlend(ModelPointer model);
public slots:
void setBlendedVertices(ModelPointer model, int blendNumber, const std::weak_ptr<NetworkGeometry>& geometry,
void setBlendedVertices(ModelPointer model, int blendNumber, const Geometry::WeakPointer& geometry,
const QVector<glm::vec3>& vertices, const QVector<glm::vec3>& normals);
private: