NetworkGeometry --> GeometryResourceWatcher

Model class gets render and collision geometries with watchers
also changed names for readability
This commit is contained in:
Andrew Meadows 2016-07-07 13:08:18 -07:00
parent f6681d4b3d
commit 9f7d2cf263
5 changed files with 144 additions and 135 deletions

View file

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

View file

@ -22,52 +22,30 @@
#include "TextureCache.h" #include "TextureCache.h"
// Alias instead of derive to avoid copying // Alias instead of derive to avoid copying
using NetworkMesh = model::Mesh;
class NetworkTexture; class NetworkTexture;
class NetworkMaterial; class NetworkMaterial;
class NetworkShape; class MeshPart;
class NetworkGeometry;
class GeometryMappingResource; 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 { class Geometry {
public: public:
using Pointer = std::shared_ptr<Geometry>; using Pointer = std::shared_ptr<Geometry>;
using WeakPointer = std::weak_ptr<Geometry>;
Geometry() = default; Geometry() = default;
Geometry(const Geometry& geometry); Geometry(const Geometry& geometry);
// Immutable over lifetime // Immutable over lifetime
using NetworkMeshes = std::vector<std::shared_ptr<const NetworkMesh>>; using GeometryMeshes = std::vector<std::shared_ptr<const model::Mesh>>;
using NetworkShapes = std::vector<std::shared_ptr<const NetworkShape>>; using GeometryMeshParts = std::vector<std::shared_ptr<const MeshPart>>;
// Mutable, but must retain structure of vector // Mutable, but must retain structure of vector
using NetworkMaterials = std::vector<std::shared_ptr<NetworkMaterial>>; using NetworkMaterials = std::vector<std::shared_ptr<NetworkMaterial>>;
const FBXGeometry& getGeometry() const { return *_geometry; } const FBXGeometry& getFBXGeometry() const { return *_fbxGeometry; }
const NetworkMeshes& getMeshes() const { return *_meshes; } const GeometryMeshes& getMeshes() const { return *_meshes; }
const std::shared_ptr<const NetworkMaterial> getShapeMaterial(int shapeID) const; const std::shared_ptr<const NetworkMaterial> getShapeMaterial(int shapeID) const;
const QVariantMap getTextures() const; const QVariantMap getTextures() const;
@ -79,9 +57,9 @@ protected:
friend class GeometryMappingResource; friend class GeometryMappingResource;
// Shared across all geometries, constant throughout lifetime // Shared across all geometries, constant throughout lifetime
std::shared_ptr<const FBXGeometry> _geometry; std::shared_ptr<const FBXGeometry> _fbxGeometry;
std::shared_ptr<const NetworkMeshes> _meshes; std::shared_ptr<const GeometryMeshes> _meshes;
std::shared_ptr<const NetworkShapes> _shapes; std::shared_ptr<const GeometryMeshParts> _meshParts;
// Copied to each geometry, mutable throughout lifetime via setTextures // Copied to each geometry, mutable throughout lifetime via setTextures
NetworkMaterials _materials; NetworkMaterials _materials;
@ -108,7 +86,7 @@ protected:
// Geometries may not hold onto textures while cached - that is for the texture cache // 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 // 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 setTextures();
void resetTextures(); void resetTextures();
@ -118,22 +96,21 @@ protected:
bool _isCacheable { true }; bool _isCacheable { true };
}; };
class NetworkGeometry : public QObject { class GeometryResourceWatcher : public QObject {
Q_OBJECT Q_OBJECT
public: public:
using Pointer = std::shared_ptr<NetworkGeometry>; using Pointer = std::shared_ptr<GeometryResourceWatcher>;
NetworkGeometry() = delete; GeometryResourceWatcher() = delete;
NetworkGeometry(const GeometryResource::Pointer& networkGeometry); 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 QUrl& getURL() const { return _resource->getURL(); }
const Geometry::Pointer& getGeometry() { return _instance; }
signals: private:
/// Emitted when the NetworkGeometry loads (or fails to) void startWatching();
void finished(bool success); void stopWatching();
private slots: private slots:
void resourceFinished(bool success); void resourceFinished(bool success);
@ -141,7 +118,27 @@ private slots:
private: private:
GeometryResource::Pointer _resource; 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 fetchResource(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 { class NetworkMaterial : public model::Material {
@ -185,9 +182,9 @@ private:
bool _isOriginal { true }; bool _isOriginal { true };
}; };
class NetworkShape { class MeshPart {
public: 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 meshID { -1 };
int partID { -1 }; int partID { -1 };
int materialID { -1 }; int materialID { -1 };

View file

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

View file

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

View file

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