mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-09 01:17:19 +02:00
NetworkGeometry --> GeometryResourceWatcher
Model class gets render and collision geometries with watchers also changed names for readability
This commit is contained in:
parent
f6681d4b3d
commit
9f7d2cf263
5 changed files with 144 additions and 135 deletions
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 };
|
||||||
|
|
|
@ -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()) {
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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:
|
||||||
|
|
Loading…
Reference in a new issue