mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-05 23:27:42 +02:00
interim checkin
This commit is contained in:
parent
145a0df082
commit
5791ca4c51
27 changed files with 557 additions and 119 deletions
|
@ -771,6 +771,7 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) {
|
||||||
DependencyManager::set<AccountManager>(std::bind(&Application::getUserAgent, qApp));
|
DependencyManager::set<AccountManager>(std::bind(&Application::getUserAgent, qApp));
|
||||||
DependencyManager::set<StatTracker>();
|
DependencyManager::set<StatTracker>();
|
||||||
DependencyManager::set<ScriptEngines>(ScriptEngine::CLIENT_SCRIPT);
|
DependencyManager::set<ScriptEngines>(ScriptEngine::CLIENT_SCRIPT);
|
||||||
|
DependencyManager::set<ScriptInitializerMixin, NativeScriptInitializers>();
|
||||||
DependencyManager::set<Preferences>();
|
DependencyManager::set<Preferences>();
|
||||||
DependencyManager::set<recording::Deck>();
|
DependencyManager::set<recording::Deck>();
|
||||||
DependencyManager::set<recording::Recorder>();
|
DependencyManager::set<recording::Recorder>();
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
#include "ModelEntityItem.h"
|
#include "ModelEntityItem.h"
|
||||||
#include "RenderableModelEntityItem.h"
|
#include "RenderableModelEntityItem.h"
|
||||||
|
|
||||||
#include <graphics-scripting/ScriptableModel.h>
|
#include <graphics-scripting/Forward.h>
|
||||||
|
|
||||||
#include "Logging.h"
|
#include "Logging.h"
|
||||||
|
|
||||||
|
@ -1763,24 +1763,24 @@ float Avatar::getUnscaledEyeHeightFromSkeleton() const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
scriptable::ScriptableModel Avatar::getScriptableModel(bool* ok) {
|
scriptable::ScriptableModelBase Avatar::getScriptableModel(bool* ok) {
|
||||||
qDebug() << "Avatar::getScriptableModel" ;
|
qDebug() << "Avatar::getScriptableModel" ;
|
||||||
if (!_skeletonModel || !_skeletonModel->isLoaded()) {
|
if (!_skeletonModel || !_skeletonModel->isLoaded()) {
|
||||||
return scriptable::ModelProvider::modelUnavailableError(ok);
|
return scriptable::ModelProvider::modelUnavailableError(ok);
|
||||||
}
|
}
|
||||||
scriptable::ScriptableModel result;
|
scriptable::ScriptableModelBase result = _skeletonModel->getScriptableModel(ok);
|
||||||
result.metadata = {
|
result.objectID = getSessionUUID();
|
||||||
|
result.mixin({
|
||||||
{ "avatarID", getSessionUUID().toString() },
|
{ "avatarID", getSessionUUID().toString() },
|
||||||
{ "url", _skeletonModelURL.toString() },
|
{ "url", _skeletonModelURL.toString() },
|
||||||
{ "origin", "Avatar/avatar::" + _displayName },
|
{ "origin", "Avatar/avatar::" + _displayName },
|
||||||
{ "textures", _skeletonModel->getTextures() },
|
{ "textures", _skeletonModel->getTextures() },
|
||||||
};
|
});
|
||||||
result.mixin(_skeletonModel->getScriptableModel(ok));
|
// FIXME: for now access to attachment models are merged into the main avatar ScriptableModel set
|
||||||
|
for (int i = 0; i < (int)_attachmentModels.size(); i++) {
|
||||||
// FIXME: for now access to attachment models are merged with the main avatar model
|
auto& model = _attachmentModels.at(i);
|
||||||
for (auto& attachmentModel : _attachmentModels) {
|
if (model->isLoaded()) {
|
||||||
if (attachmentModel->isLoaded()) {
|
result.append(model->getScriptableModel(ok), _attachmentData.at(i).toVariant().toMap());
|
||||||
result.mixin(attachmentModel->getScriptableModel(ok));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ok) {
|
if (ok) {
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
|
||||||
//
|
//
|
||||||
// Avatar.h
|
// Avatar.h
|
||||||
// interface/src/avatar
|
// interface/src/avatar
|
||||||
|
@ -20,7 +21,7 @@
|
||||||
#include <AvatarData.h>
|
#include <AvatarData.h>
|
||||||
#include <ShapeInfo.h>
|
#include <ShapeInfo.h>
|
||||||
#include <render/Scene.h>
|
#include <render/Scene.h>
|
||||||
#include <graphics-scripting/ScriptableModel.h>
|
#include <graphics-scripting/Forward.h>
|
||||||
#include <GLMHelpers.h>
|
#include <GLMHelpers.h>
|
||||||
|
|
||||||
|
|
||||||
|
@ -274,7 +275,7 @@ public:
|
||||||
virtual void setAvatarEntityDataChanged(bool value) override;
|
virtual void setAvatarEntityDataChanged(bool value) override;
|
||||||
|
|
||||||
|
|
||||||
virtual scriptable::ScriptableModel getScriptableModel(bool* ok = nullptr) override;
|
virtual scriptable::ScriptableModelBase getScriptableModel(bool* ok = nullptr) override;
|
||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
// FIXME - these should be migrated to use Pose data instead
|
// FIXME - these should be migrated to use Pose data instead
|
||||||
|
|
|
@ -962,7 +962,6 @@ scriptable::ScriptableModelBase render::entities::ModelEntityRenderer::getScript
|
||||||
}
|
}
|
||||||
|
|
||||||
bool render::entities::ModelEntityRenderer::replaceScriptableModelMeshPart(scriptable::ScriptableModelBasePointer newModel, int meshIndex, int partIndex) {
|
bool render::entities::ModelEntityRenderer::replaceScriptableModelMeshPart(scriptable::ScriptableModelBasePointer newModel, int meshIndex, int partIndex) {
|
||||||
qCDebug(entitiesrenderer) << "REPLACING RenderableModelEntityItem" << newModel->objectName();
|
|
||||||
ModelPointer model;
|
ModelPointer model;
|
||||||
withReadLock([&] { model = _model; });
|
withReadLock([&] { model = _model; });
|
||||||
|
|
||||||
|
@ -970,7 +969,7 @@ bool render::entities::ModelEntityRenderer::replaceScriptableModelMeshPart(scrip
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return _model->replaceScriptableModelMeshPart(newModel, meshIndex, partIndex);
|
return model->replaceScriptableModelMeshPart(newModel, meshIndex, partIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderableModelEntityItem::simulateRelayedJoints() {
|
void RenderableModelEntityItem::simulateRelayedJoints() {
|
||||||
|
|
|
@ -281,7 +281,7 @@ std::vector<PolyLineEntityRenderer::Vertex> PolyLineEntityRenderer::updateVertic
|
||||||
return vertices;
|
return vertices;
|
||||||
}
|
}
|
||||||
|
|
||||||
scriptable::ScriptableModel PolyLineEntityRenderer::getScriptableModel(bool *ok) {
|
scriptable::ScriptableModelBase PolyLineEntityRenderer::getScriptableModel(bool *ok) {
|
||||||
// TODO: adapt polyline into a triangles mesh...
|
// TODO: adapt polyline into a triangles mesh...
|
||||||
return EntityRenderer::getScriptableModel(ok);
|
return EntityRenderer::getScriptableModel(ok);
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ class PolyLineEntityRenderer : public TypedEntityRenderer<PolyLineEntityItem> {
|
||||||
public:
|
public:
|
||||||
PolyLineEntityRenderer(const EntityItemPointer& entity);
|
PolyLineEntityRenderer(const EntityItemPointer& entity);
|
||||||
|
|
||||||
virtual scriptable::ScriptableModel getScriptableModel(bool* ok = nullptr) override;
|
virtual scriptable::ScriptableModelBase getScriptableModel(bool* ok = nullptr) override;
|
||||||
protected:
|
protected:
|
||||||
virtual bool needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const override;
|
virtual bool needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const override;
|
||||||
virtual void doRenderUpdateSynchronousTyped(const ScenePointer& scene,
|
virtual void doRenderUpdateSynchronousTyped(const ScenePointer& scene,
|
||||||
|
|
|
@ -1414,14 +1414,14 @@ void RenderablePolyVoxEntityItem::bonkNeighbors() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
scriptable::ScriptableModel RenderablePolyVoxEntityItem::getScriptableModel(bool * ok) {
|
scriptable::ScriptableModelBase RenderablePolyVoxEntityItem::getScriptableModel(bool * ok) {
|
||||||
if (!updateDependents() || !_mesh) {
|
if (!updateDependents() || !_mesh) {
|
||||||
return scriptable::ModelProvider::modelUnavailableError(ok);
|
return scriptable::ModelProvider::modelUnavailableError(ok);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool success = false;
|
bool success = false;
|
||||||
glm::mat4 transform = voxelToLocalMatrix();
|
glm::mat4 transform = voxelToLocalMatrix();
|
||||||
scriptable::ScriptableModel result;
|
scriptable::ScriptableModelBase result;
|
||||||
withReadLock([&] {
|
withReadLock([&] {
|
||||||
gpu::BufferView::Index numVertices = (gpu::BufferView::Index)_mesh->getNumVertices();
|
gpu::BufferView::Index numVertices = (gpu::BufferView::Index)_mesh->getNumVertices();
|
||||||
if (!_meshReady) {
|
if (!_meshReady) {
|
||||||
|
@ -1433,11 +1433,12 @@ scriptable::ScriptableModel RenderablePolyVoxEntityItem::getScriptableModel(bool
|
||||||
} else {
|
} else {
|
||||||
success = true;
|
success = true;
|
||||||
// the mesh will be in voxel-space. transform it into object-space
|
// the mesh will be in voxel-space. transform it into object-space
|
||||||
result.meshes <<
|
result.append(_mesh->map(
|
||||||
_mesh->map([=](glm::vec3 position){ return glm::vec3(transform * glm::vec4(position, 1.0f)); },
|
[=](glm::vec3 position){ return glm::vec3(transform * glm::vec4(position, 1.0f)); },
|
||||||
[=](glm::vec3 color){ return color; },
|
[=](glm::vec3 color){ return color; },
|
||||||
[=](glm::vec3 normal){ return glm::normalize(glm::vec3(transform * glm::vec4(normal, 0.0f))); },
|
[=](glm::vec3 normal){ return glm::normalize(glm::vec3(transform * glm::vec4(normal, 0.0f))); },
|
||||||
[&](uint32_t index){ return index; });
|
[&](uint32_t index){ return index; }
|
||||||
|
));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (ok) {
|
if (ok) {
|
||||||
|
|
|
@ -113,7 +113,7 @@ public:
|
||||||
|
|
||||||
void setVolDataDirty() { withWriteLock([&] { _volDataDirty = true; _meshReady = false; }); }
|
void setVolDataDirty() { withWriteLock([&] { _volDataDirty = true; _meshReady = false; }); }
|
||||||
|
|
||||||
virtual scriptable::ScriptableModel getScriptableModel(bool* ok = nullptr) override;
|
virtual scriptable::ScriptableModelBase getScriptableModel(bool* ok = nullptr) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool updateOnCount(const ivec3& v, uint8_t toValue);
|
bool updateOnCount(const ivec3& v, uint8_t toValue);
|
||||||
|
@ -163,7 +163,7 @@ class PolyVoxEntityRenderer : public TypedEntityRenderer<RenderablePolyVoxEntity
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PolyVoxEntityRenderer(const EntityItemPointer& entity);
|
PolyVoxEntityRenderer(const EntityItemPointer& entity);
|
||||||
virtual scriptable::ScriptableModel getScriptableModel(bool* ok = nullptr) override {
|
virtual scriptable::ScriptableModelBase getScriptableModel(bool* ok = nullptr) override {
|
||||||
return asTypedEntity<RenderablePolyVoxEntityItem>()->getScriptableModel(ok);
|
return asTypedEntity<RenderablePolyVoxEntityItem>()->getScriptableModel(ok);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -157,8 +157,8 @@ void ShapeEntityRenderer::doRender(RenderArgs* args) {
|
||||||
args->_details._trianglesRendered += (int)triCount;
|
args->_details._trianglesRendered += (int)triCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
scriptable::ScriptableModel ShapeEntityRenderer::getScriptableModel(bool* ok) {
|
scriptable::ScriptableModelBase ShapeEntityRenderer::getScriptableModel(bool* ok) {
|
||||||
scriptable::ScriptableModel result;
|
scriptable::ScriptableModelBase result;
|
||||||
result.metadata = {
|
result.metadata = {
|
||||||
{ "entityID", getEntity()->getID().toString() },
|
{ "entityID", getEntity()->getID().toString() },
|
||||||
{ "shape", entity::stringFromShape(_shape) },
|
{ "shape", entity::stringFromShape(_shape) },
|
||||||
|
@ -169,7 +169,10 @@ scriptable::ScriptableModel ShapeEntityRenderer::getScriptableModel(bool* ok) {
|
||||||
auto vertexColor = glm::vec3(_color);
|
auto vertexColor = glm::vec3(_color);
|
||||||
auto success = false;
|
auto success = false;
|
||||||
if (auto mesh = geometryCache->meshFromShape(geometryShape, vertexColor)) {
|
if (auto mesh = geometryCache->meshFromShape(geometryShape, vertexColor)) {
|
||||||
result.meshes << mesh;
|
scriptable::ScriptableMeshBase base{ mesh, {
|
||||||
|
{ "shape", entity::stringFromShape(_shape) },
|
||||||
|
}};
|
||||||
|
result.append(base);
|
||||||
success = true;
|
success = true;
|
||||||
}
|
}
|
||||||
if (ok) {
|
if (ok) {
|
||||||
|
|
|
@ -22,7 +22,7 @@ class ShapeEntityRenderer : public TypedEntityRenderer<ShapeEntityItem> {
|
||||||
public:
|
public:
|
||||||
ShapeEntityRenderer(const EntityItemPointer& entity);
|
ShapeEntityRenderer(const EntityItemPointer& entity);
|
||||||
|
|
||||||
virtual scriptable::ScriptableModel getScriptableModel(bool* ok = nullptr) override;
|
virtual scriptable::ScriptableModelBase getScriptableModel(bool* ok = nullptr) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual bool needsRenderUpdate() const override;
|
virtual bool needsRenderUpdate() const override;
|
||||||
|
|
|
@ -1897,7 +1897,8 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS
|
||||||
geometry.meshes.append(extracted.mesh);
|
geometry.meshes.append(extracted.mesh);
|
||||||
int meshIndex = geometry.meshes.size() - 1;
|
int meshIndex = geometry.meshes.size() - 1;
|
||||||
if (extracted.mesh._mesh) {
|
if (extracted.mesh._mesh) {
|
||||||
extracted.mesh._mesh->displayName = QString("%1#/mesh/%2").arg(url).arg(meshIndex);
|
extracted.mesh._mesh->displayName = QString("%1#/mesh/%2").arg(url).arg(meshIndex).toStdString();
|
||||||
|
extracted.mesh._mesh->modelName = modelIDsToNames.value(modelID).toStdString();
|
||||||
}
|
}
|
||||||
meshIDsToMeshIndices.insert(it.key(), meshIndex);
|
meshIDsToMeshIndices.insert(it.key(), meshIndex);
|
||||||
}
|
}
|
||||||
|
@ -1983,7 +1984,7 @@ FBXGeometry* readFBX(QIODevice* device, const QVariantHash& mapping, const QStri
|
||||||
reader._loadLightmaps = loadLightmaps;
|
reader._loadLightmaps = loadLightmaps;
|
||||||
reader._lightmapLevel = lightmapLevel;
|
reader._lightmapLevel = lightmapLevel;
|
||||||
|
|
||||||
qDebug() << "Reading FBX: " << url;
|
qCDebug(modelformat) << "Reading FBX: " << url;
|
||||||
|
|
||||||
return reader.extractFBXGeometry(mapping, url);
|
return reader.extractFBXGeometry(mapping, url);
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,7 +71,8 @@ bool writeOBJToTextStream(QTextStream& out, QList<MeshPointer> meshes) {
|
||||||
out << formatFloat(v[1]) << " ";
|
out << formatFloat(v[1]) << " ";
|
||||||
out << formatFloat(v[2]);
|
out << formatFloat(v[2]);
|
||||||
if (colorIndex < numColors) {
|
if (colorIndex < numColors) {
|
||||||
glm::vec3 color = colorsBufferView.get<glm::vec3>(colorIndex);
|
glm::vec3 color = glmVecFromVariant<glm::vec3>(buffer_helpers::toVariant(colorsBufferView, colorIndex));
|
||||||
|
//glm::vec3 color = colorsBufferView.get<glm::vec3>(colorIndex);
|
||||||
out << " " << formatFloat(color[0]);
|
out << " " << formatFloat(color[0]);
|
||||||
out << " " << formatFloat(color[1]);
|
out << " " << formatFloat(color[1]);
|
||||||
out << " " << formatFloat(color[2]);
|
out << " " << formatFloat(color[2]);
|
||||||
|
@ -94,7 +95,7 @@ bool writeOBJToTextStream(QTextStream& out, QList<MeshPointer> meshes) {
|
||||||
const gpu::BufferView& normalsBufferView = mesh->getAttributeBuffer(gpu::Stream::InputSlot::NORMAL);
|
const gpu::BufferView& normalsBufferView = mesh->getAttributeBuffer(gpu::Stream::InputSlot::NORMAL);
|
||||||
gpu::BufferView::Index numNormals = (gpu::BufferView::Index)normalsBufferView.getNumElements();
|
gpu::BufferView::Index numNormals = (gpu::BufferView::Index)normalsBufferView.getNumElements();
|
||||||
for (gpu::BufferView::Index i = 0; i < numNormals; i++) {
|
for (gpu::BufferView::Index i = 0; i < numNormals; i++) {
|
||||||
glm::vec3 normal = glmVecFromVariant<glm::vec3>(bufferViewElementToVariant(normalsBufferView, i));
|
glm::vec3 normal = glmVecFromVariant<glm::vec3>(buffer_helpers::toVariant(normalsBufferView, i));
|
||||||
//glm::vec3 normal = normalsBufferView.get<glm::vec3>(i);
|
//glm::vec3 normal = normalsBufferView.get<glm::vec3>(i);
|
||||||
out << "vn ";
|
out << "vn ";
|
||||||
out << formatFloat(normal[0]) << " ";
|
out << formatFloat(normal[0]) << " ";
|
||||||
|
@ -117,7 +118,7 @@ bool writeOBJToTextStream(QTextStream& out, QList<MeshPointer> meshes) {
|
||||||
const gpu::BufferView& indexBuffer = mesh->getIndexBuffer();
|
const gpu::BufferView& indexBuffer = mesh->getIndexBuffer();
|
||||||
|
|
||||||
graphics::Index partCount = (graphics::Index)mesh->getNumParts();
|
graphics::Index partCount = (graphics::Index)mesh->getNumParts();
|
||||||
QString name = (!mesh->displayName.size() ? QString("mesh-%1-part").arg(nth) : QString(mesh->displayName))
|
QString name = (!mesh->displayName.size() ? QString("mesh-%1-part").arg(nth) : QString::fromStdString(mesh->displayName))
|
||||||
.replace(QRegExp("[^-_a-zA-Z0-9]"), "_");
|
.replace(QRegExp("[^-_a-zA-Z0-9]"), "_");
|
||||||
for (int partIndex = 0; partIndex < partCount; partIndex++) {
|
for (int partIndex = 0; partIndex < partCount; partIndex++) {
|
||||||
const graphics::Mesh::Part& part = partBuffer.get<graphics::Mesh::Part>(partIndex);
|
const graphics::Mesh::Part& part = partBuffer.get<graphics::Mesh::Part>(partIndex);
|
||||||
|
|
|
@ -19,7 +19,9 @@ namespace scriptable {
|
||||||
// JS => QPointer<QObject>
|
// JS => QPointer<QObject>
|
||||||
template <typename T> QPointer<T> qpointer_qobject_cast(const QScriptValue& value) {
|
template <typename T> QPointer<T> qpointer_qobject_cast(const QScriptValue& value) {
|
||||||
auto obj = value.toQObject();
|
auto obj = value.toQObject();
|
||||||
|
#ifdef SCRIPTABLE_MESH_DEBUG
|
||||||
qCInfo(graphics_scripting) << "qpointer_qobject_cast" << obj << value.toString();
|
qCInfo(graphics_scripting) << "qpointer_qobject_cast" << obj << value.toString();
|
||||||
|
#endif
|
||||||
if (auto tmp = qobject_cast<T*>(obj)) {
|
if (auto tmp = qobject_cast<T*>(obj)) {
|
||||||
return QPointer<T>(tmp);
|
return QPointer<T>(tmp);
|
||||||
}
|
}
|
||||||
|
@ -41,11 +43,15 @@ namespace scriptable {
|
||||||
// C++ > QtOwned instance
|
// C++ > QtOwned instance
|
||||||
template <typename T, class... Rest> std::shared_ptr<T> make_qtowned(Rest... rest) {
|
template <typename T, class... Rest> std::shared_ptr<T> make_qtowned(Rest... rest) {
|
||||||
T* tmp = new T(rest...);
|
T* tmp = new T(rest...);
|
||||||
|
#ifdef SCRIPTABLE_MESH_DEBUG
|
||||||
qCInfo(graphics_scripting) << "scriptable::make_qtowned" << toDebugString(tmp);
|
qCInfo(graphics_scripting) << "scriptable::make_qtowned" << toDebugString(tmp);
|
||||||
|
#endif
|
||||||
QString debug = toDebugString(tmp);
|
QString debug = toDebugString(tmp);
|
||||||
if (tmp) {
|
if (tmp) {
|
||||||
tmp->metadata["__ownership__"] = QScriptEngine::QtOwnership;
|
tmp->metadata["__ownership__"] = QScriptEngine::QtOwnership;
|
||||||
|
#ifdef SCRIPTABLE_MESH_DEBUG
|
||||||
QObject::connect(tmp, &QObject::destroyed, [=]() { qCInfo(graphics_scripting) << "-------- ~scriptable::make_qtowned" << debug; });
|
QObject::connect(tmp, &QObject::destroyed, [=]() { qCInfo(graphics_scripting) << "-------- ~scriptable::make_qtowned" << debug; });
|
||||||
|
#endif
|
||||||
auto ptr = std::shared_ptr<T>(tmp, [debug](T* tmp) {
|
auto ptr = std::shared_ptr<T>(tmp, [debug](T* tmp) {
|
||||||
//qDebug() << "~std::shared_ptr<T>" << debug;
|
//qDebug() << "~std::shared_ptr<T>" << debug;
|
||||||
delete tmp;
|
delete tmp;
|
||||||
|
@ -58,7 +64,9 @@ namespace scriptable {
|
||||||
// C++ > ScriptOwned JS instance
|
// C++ > ScriptOwned JS instance
|
||||||
template <typename T, class... Rest> QPointer<T> make_scriptowned(Rest... rest) {
|
template <typename T, class... Rest> QPointer<T> make_scriptowned(Rest... rest) {
|
||||||
T* tmp = new T(rest...);
|
T* tmp = new T(rest...);
|
||||||
|
#ifdef SCRIPTABLE_MESH_DEBUG
|
||||||
qCInfo(graphics_scripting) << "scriptable::make_scriptowned" << toDebugString(tmp);
|
qCInfo(graphics_scripting) << "scriptable::make_scriptowned" << toDebugString(tmp);
|
||||||
|
#endif
|
||||||
if (tmp) {
|
if (tmp) {
|
||||||
tmp->metadata["__ownership__"] = QScriptEngine::ScriptOwnership;
|
tmp->metadata["__ownership__"] = QScriptEngine::ScriptOwnership;
|
||||||
//auto blah = (DeleterFunction)[](void* delme) { };
|
//auto blah = (DeleterFunction)[](void* delme) { };
|
||||||
|
@ -71,12 +79,14 @@ namespace scriptable {
|
||||||
template <typename T> QPointer<T> add_scriptowned_destructor(T* tmp) {
|
template <typename T> QPointer<T> add_scriptowned_destructor(T* tmp) {
|
||||||
QString debug = toDebugString(tmp);
|
QString debug = toDebugString(tmp);
|
||||||
if (tmp) {
|
if (tmp) {
|
||||||
|
#ifdef SCRIPTABLE_MESH_DEBUG
|
||||||
QObject::connect(tmp, &QObject::destroyed, [=]() {
|
QObject::connect(tmp, &QObject::destroyed, [=]() {
|
||||||
qCInfo(graphics_scripting) << "-------- ~scriptable::make_scriptowned" << debug;// << !!customDeleter;
|
qCInfo(graphics_scripting) << "-------- ~scriptable::make_scriptowned" << debug;// << !!customDeleter;
|
||||||
//if (customDeleter) {
|
//if (customDeleter) {
|
||||||
// customDeleter(tmp);
|
// customDeleter(tmp);
|
||||||
//}
|
//}
|
||||||
});
|
});
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
qCInfo(graphics_scripting) << "add_scriptowned_destructor -- not connecting to null value" << debug;
|
qCInfo(graphics_scripting) << "add_scriptowned_destructor -- not connecting to null value" << debug;
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,7 @@ bool ModelScriptingInterface::updateMeshes(QUuid uuid, const scriptable::Scripta
|
||||||
|
|
||||||
bool ModelScriptingInterface::updateMeshes(QUuid uuid, const scriptable::ScriptableModelPointer model) {
|
bool ModelScriptingInterface::updateMeshes(QUuid uuid, const scriptable::ScriptableModelPointer model) {
|
||||||
auto appProvider = DependencyManager::get<scriptable::ModelProviderFactory>();
|
auto appProvider = DependencyManager::get<scriptable::ModelProviderFactory>();
|
||||||
qCDebug(graphics_scripting) << "appProvider" << appProvider.data();
|
//qCDebug(graphics_scripting) << "appProvider" << appProvider.data();
|
||||||
scriptable::ModelProviderPointer provider = appProvider ? appProvider->lookupModelProvider(uuid) : nullptr;
|
scriptable::ModelProviderPointer provider = appProvider ? appProvider->lookupModelProvider(uuid) : nullptr;
|
||||||
QString providerType = provider ? provider->metadata.value("providerType").toString() : QString();
|
QString providerType = provider ? provider->metadata.value("providerType").toString() : QString();
|
||||||
if (providerType.isEmpty()) {
|
if (providerType.isEmpty()) {
|
||||||
|
@ -56,12 +56,12 @@ bool ModelScriptingInterface::updateMeshes(QUuid uuid, const scriptable::Scripta
|
||||||
}
|
}
|
||||||
bool success = false;
|
bool success = false;
|
||||||
if (provider) {
|
if (provider) {
|
||||||
qCDebug(graphics_scripting) << "fetching meshes from " << providerType << "...";
|
//qCDebug(graphics_scripting) << "fetching meshes from " << providerType << "...";
|
||||||
auto scriptableMeshes = provider->getScriptableModel(&success);
|
auto scriptableMeshes = provider->getScriptableModel(&success);
|
||||||
qCDebug(graphics_scripting) << "//fetched meshes from " << providerType << "success:" <<success << "#" << scriptableMeshes.meshes.size();
|
//qCDebug(graphics_scripting) << "//fetched meshes from " << providerType << "success:" <<success << "#" << scriptableMeshes.meshes.size();
|
||||||
if (success) {
|
if (success) {
|
||||||
const scriptable::ScriptableModelBasePointer base = model->operator scriptable::ScriptableModelBasePointer();
|
const scriptable::ScriptableModelBasePointer base = model->operator scriptable::ScriptableModelBasePointer();
|
||||||
qCDebug(graphics_scripting) << "as base" << base;
|
//qCDebug(graphics_scripting) << "as base" << base;
|
||||||
if (base) {
|
if (base) {
|
||||||
//auto meshes = model->getConstMeshes();
|
//auto meshes = model->getConstMeshes();
|
||||||
success = provider->replaceScriptableModelMeshPart(base, -1, -1);
|
success = provider->replaceScriptableModelMeshPart(base, -1, -1);
|
||||||
|
|
|
@ -28,6 +28,8 @@
|
||||||
|
|
||||||
#include "OBJWriter.h"
|
#include "OBJWriter.h"
|
||||||
|
|
||||||
|
// #define SCRIPTABLE_MESH_DEBUG
|
||||||
|
|
||||||
namespace scriptable {
|
namespace scriptable {
|
||||||
// QScriptValue jsBindCallback(QScriptValue callback);
|
// QScriptValue jsBindCallback(QScriptValue callback);
|
||||||
// template <typename T> QPointer<T> qpointer_qobject_cast(const QScriptValue& value);
|
// template <typename T> QPointer<T> qpointer_qobject_cast(const QScriptValue& value);
|
||||||
|
@ -287,7 +289,9 @@ quint32 scriptable::ScriptableMesh::mapAttributeValues(QScriptValue _callback) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
auto meshPart = js ? js->toScriptValue(getSelf()) : QScriptValue::NullValue;
|
auto meshPart = js ? js->toScriptValue(getSelf()) : QScriptValue::NullValue;
|
||||||
|
#ifdef SCRIPTABLE_MESH_DEBUG
|
||||||
qCInfo(graphics_scripting) << "mapAttributeValues" << mesh.get() << js->currentContext()->thisObject().toQObject();
|
qCInfo(graphics_scripting) << "mapAttributeValues" << mesh.get() << js->currentContext()->thisObject().toQObject();
|
||||||
|
#endif
|
||||||
auto obj = js->newObject();
|
auto obj = js->newObject();
|
||||||
auto attributeViews = buffer_helpers::gatherBufferViews(mesh, { "normal", "color" });
|
auto attributeViews = buffer_helpers::gatherBufferViews(mesh, { "normal", "color" });
|
||||||
metadata["last-modified"] = QDateTime::currentDateTime().toTimeSpec(Qt::OffsetFromUTC).toString(Qt::ISODate);
|
metadata["last-modified"] = QDateTime::currentDateTime().toTimeSpec(Qt::OffsetFromUTC).toString(Qt::ISODate);
|
||||||
|
@ -328,9 +332,10 @@ quint32 scriptable::ScriptableMeshPart::mapAttributeValues(QScriptValue callback
|
||||||
}
|
}
|
||||||
|
|
||||||
bool scriptable::ScriptableMeshPart::unrollVertices(bool recalcNormals) {
|
bool scriptable::ScriptableMeshPart::unrollVertices(bool recalcNormals) {
|
||||||
auto meshProxy = this;
|
|
||||||
auto mesh = getMeshPointer();
|
auto mesh = getMeshPointer();
|
||||||
|
#ifdef SCRIPTABLE_MESH_DEBUG
|
||||||
qCInfo(graphics_scripting) << "ScriptableMeshPart::unrollVertices" << !!mesh<< !!meshProxy;
|
qCInfo(graphics_scripting) << "ScriptableMeshPart::unrollVertices" << !!mesh<< !!meshProxy;
|
||||||
|
#endif
|
||||||
if (!mesh) {
|
if (!mesh) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -527,28 +532,32 @@ scriptable::ScriptableMeshPointer scriptable::ScriptableMesh::cloneMesh(bool rec
|
||||||
qCInfo(graphics_scripting) << "ScriptableMesh::cloneMesh -- !meshPointer";
|
qCInfo(graphics_scripting) << "ScriptableMesh::cloneMesh -- !meshPointer";
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
qCInfo(graphics_scripting) << "ScriptableMesh::cloneMesh...";
|
// qCInfo(graphics_scripting) << "ScriptableMesh::cloneMesh...";
|
||||||
auto clone = buffer_helpers::cloneMesh(mesh);
|
auto clone = buffer_helpers::cloneMesh(mesh);
|
||||||
|
|
||||||
qCInfo(graphics_scripting) << "ScriptableMesh::cloneMesh...";
|
// qCInfo(graphics_scripting) << "ScriptableMesh::cloneMesh...";
|
||||||
if (recalcNormals) {
|
if (recalcNormals) {
|
||||||
buffer_helpers::recalculateNormals(clone);
|
buffer_helpers::recalculateNormals(clone);
|
||||||
}
|
}
|
||||||
qCDebug(graphics_scripting) << clone.get();// << metadata;
|
//qCDebug(graphics_scripting) << clone.get();// << metadata;
|
||||||
auto meshPointer = scriptable::make_scriptowned<scriptable::ScriptableMesh>(provider, model, clone, metadata);
|
auto meshPointer = scriptable::make_scriptowned<scriptable::ScriptableMesh>(provider, model, clone, metadata);
|
||||||
clone.reset(); // free local reference
|
clone.reset(); // free local reference
|
||||||
qCInfo(graphics_scripting) << "========= ScriptableMesh::cloneMesh..." << meshPointer << meshPointer->ownedMesh.use_count();
|
// qCInfo(graphics_scripting) << "========= ScriptableMesh::cloneMesh..." << meshPointer << meshPointer->ownedMesh.use_count();
|
||||||
//scriptable::MeshPointer* ppMesh = new scriptable::MeshPointer();
|
//scriptable::MeshPointer* ppMesh = new scriptable::MeshPointer();
|
||||||
//*ppMesh = clone;
|
//*ppMesh = clone;
|
||||||
|
|
||||||
if (meshPointer) {
|
if (0 && meshPointer) {
|
||||||
scriptable::WeakMeshPointer delme = meshPointer->mesh;
|
scriptable::WeakMeshPointer delme = meshPointer->mesh;
|
||||||
QString debugString = scriptable::toDebugString(meshPointer);
|
QString debugString = scriptable::toDebugString(meshPointer);
|
||||||
QObject::connect(meshPointer, &QObject::destroyed, meshPointer, [=]() {
|
QObject::connect(meshPointer, &QObject::destroyed, meshPointer, [=]() {
|
||||||
qCWarning(graphics_scripting) << "*************** cloneMesh/Destroy";
|
// qCWarning(graphics_scripting) << "*************** cloneMesh/Destroy";
|
||||||
qCWarning(graphics_scripting) << "*************** " << debugString << delme.lock().get();
|
// qCWarning(graphics_scripting) << "*************** " << debugString << delme.lock().get();
|
||||||
if (!delme.expired()) {
|
if (!delme.expired()) {
|
||||||
qCWarning(graphics_scripting) << "cloneMesh -- potential memory leak..." << debugString << delme.lock().get();
|
QTimer::singleShot(250, this, [=]{
|
||||||
|
if (!delme.expired()) {
|
||||||
|
qCWarning(graphics_scripting) << "cloneMesh -- potential memory leak..." << debugString << delme.use_count();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -575,12 +584,16 @@ scriptable::ScriptableMeshBase& scriptable::ScriptableMeshBase::operator=(const
|
||||||
}
|
}
|
||||||
scriptable::ScriptableMeshBase::~ScriptableMeshBase() {
|
scriptable::ScriptableMeshBase::~ScriptableMeshBase() {
|
||||||
ownedMesh.reset();
|
ownedMesh.reset();
|
||||||
|
#ifdef SCRIPTABLE_MESH_DEBUG
|
||||||
qCInfo(graphics_scripting) << "//~ScriptableMeshBase" << this << "ownedMesh:" << ownedMesh.use_count() << "mesh:" << mesh.use_count();
|
qCInfo(graphics_scripting) << "//~ScriptableMeshBase" << this << "ownedMesh:" << ownedMesh.use_count() << "mesh:" << mesh.use_count();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
scriptable::ScriptableMesh::~ScriptableMesh() {
|
scriptable::ScriptableMesh::~ScriptableMesh() {
|
||||||
ownedMesh.reset();
|
ownedMesh.reset();
|
||||||
|
#ifdef SCRIPTABLE_MESH_DEBUG
|
||||||
qCInfo(graphics_scripting) << "//~ScriptableMesh" << this << "ownedMesh:" << ownedMesh.use_count() << "mesh:" << mesh.use_count();
|
qCInfo(graphics_scripting) << "//~ScriptableMesh" << this << "ownedMesh:" << ownedMesh.use_count() << "mesh:" << mesh.use_count();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
QString scriptable::ScriptableMeshPart::toOBJ() {
|
QString scriptable::ScriptableMeshPart::toOBJ() {
|
||||||
|
|
|
@ -100,7 +100,7 @@ namespace scriptable {
|
||||||
ScriptableMeshPart(scriptable::ScriptableMeshPointer parentMesh, int partIndex);
|
ScriptableMeshPart(scriptable::ScriptableMeshPointer parentMesh, int partIndex);
|
||||||
ScriptableMeshPart& operator=(const ScriptableMeshPart& view) { parentMesh=view.parentMesh; return *this; };
|
ScriptableMeshPart& operator=(const ScriptableMeshPart& view) { parentMesh=view.parentMesh; return *this; };
|
||||||
ScriptableMeshPart(const ScriptableMeshPart& other) : parentMesh(other.parentMesh), partIndex(other.partIndex) {}
|
ScriptableMeshPart(const ScriptableMeshPart& other) : parentMesh(other.parentMesh), partIndex(other.partIndex) {}
|
||||||
~ScriptableMeshPart() { qDebug() << "~ScriptableMeshPart" << this; }
|
// ~ScriptableMeshPart() { qDebug() << "~ScriptableMeshPart" << this; }
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
scriptable::ScriptableMeshPointer getParentMesh() const { return parentMesh; }
|
scriptable::ScriptableMeshPointer getParentMesh() const { return parentMesh; }
|
||||||
|
|
|
@ -0,0 +1,149 @@
|
||||||
|
//
|
||||||
|
// ScriptableModel.cpp
|
||||||
|
// libraries/graphics-scripting
|
||||||
|
//
|
||||||
|
// Copyright 2018 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "GraphicsScriptingUtil.h"
|
||||||
|
#include "ScriptableModel.h"
|
||||||
|
#include "ScriptableMesh.h"
|
||||||
|
|
||||||
|
#include <QtScript/QScriptEngine>
|
||||||
|
//#include "ScriptableModel.moc"
|
||||||
|
|
||||||
|
void scriptable::ScriptableModelBase::mixin(const QVariantMap& modelMetaData) {
|
||||||
|
for (const auto& key : modelMetaData.keys()) {
|
||||||
|
const auto& value = modelMetaData[key];
|
||||||
|
if (metadata.contains(key) && metadata[key].type() == (QVariant::Type)QMetaType::QVariantList) {
|
||||||
|
qCDebug(graphics_scripting) << "CONCATENATING" << key << metadata[key].toList().size() << "+" << value.toList().size();
|
||||||
|
metadata[key] = metadata[key].toList() + value.toList();
|
||||||
|
} else {
|
||||||
|
metadata[key] = modelMetaData[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
scriptable::ScriptableModelBase::~ScriptableModelBase() {
|
||||||
|
#ifdef SCRIPTABLE_MESH_DEBUG
|
||||||
|
qCDebug(graphics_scripting) << "~ScriptableModelBase" << this;
|
||||||
|
#endif
|
||||||
|
for (auto& m : meshes) {
|
||||||
|
m.ownedMesh.reset();
|
||||||
|
//qCDebug(graphics_scripting) << "~~~~ScriptableModelBase" << &m << m.mesh.use_count();
|
||||||
|
}
|
||||||
|
meshes.clear();
|
||||||
|
//qCDebug(graphics_scripting) << "//~ScriptableModelBase" << this;
|
||||||
|
}
|
||||||
|
void scriptable::ScriptableModelBase::append(scriptable::WeakMeshPointer mesh, const QVariantMap& metadata) {
|
||||||
|
//qCDebug(graphics_scripting) << "+ APPEND WeakMeshPointer" << mesh.lock().get();
|
||||||
|
meshes << ScriptableMeshBase{ provider, this, mesh, metadata };
|
||||||
|
}
|
||||||
|
|
||||||
|
void scriptable::ScriptableModelBase::append(const ScriptableMeshBase& mesh, const QVariantMap& modelMetaData) {
|
||||||
|
//qCDebug(graphics_scripting) << "+ APPEND ScriptableMeshBase" << &mesh;
|
||||||
|
if (mesh.provider.lock().get() != provider.lock().get()) {
|
||||||
|
qCDebug(graphics_scripting) << "warning: appending mesh from different provider..." << mesh.provider.lock().get() << " != " << provider.lock().get();
|
||||||
|
}
|
||||||
|
//if (mesh.model && mesh.model != this) {
|
||||||
|
// qCDebug(graphics_scripting) << "warning: appending mesh from different model..." << mesh.model << " != " << this;
|
||||||
|
//}
|
||||||
|
meshes << mesh;
|
||||||
|
mixin(modelMetaData);
|
||||||
|
}
|
||||||
|
|
||||||
|
void scriptable::ScriptableModelBase::append(const ScriptableModelBase& other, const QVariantMap& modelMetaData) {
|
||||||
|
//qCDebug(graphics_scripting) << "+ APPEND ScriptableModelBase" << &other;
|
||||||
|
for (const auto& mesh : other.meshes) { append(mesh); }
|
||||||
|
mixin(other.metadata);
|
||||||
|
mixin(modelMetaData);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QString scriptable::ScriptableModel::toString() const {
|
||||||
|
return QString("[ScriptableModel%1%2]")
|
||||||
|
.arg(objectID.isNull() ? "" : " objectID="+objectID.toString())
|
||||||
|
.arg(objectName().isEmpty() ? "" : " name=" +objectName());
|
||||||
|
}
|
||||||
|
|
||||||
|
scriptable::ScriptableModelPointer scriptable::ScriptableModel::cloneModel(const QVariantMap& options) {
|
||||||
|
scriptable::ScriptableModelPointer clone = scriptable::ScriptableModelPointer(new scriptable::ScriptableModel(*this));
|
||||||
|
qCDebug(graphics_scripting) << "clone->getNumMeshes" << clone->getNumMeshes();
|
||||||
|
clone->meshes.clear();
|
||||||
|
qCDebug(graphics_scripting) << "..clone->getNumMeshes" << clone->getNumMeshes();
|
||||||
|
for (const auto &mesh : getConstMeshes()) {
|
||||||
|
auto cloned = mesh->cloneMesh(options.value("recalculateNormals").toBool());
|
||||||
|
if (auto tmp = qobject_cast<scriptable::ScriptableMeshBase*>(cloned)) {
|
||||||
|
qCDebug(graphics_scripting) << "++ APPEND" << tmp << tmp->ownedMesh.use_count() << tmp->metadata.value("__ownership__") << tmp->metadata.value("__native__");
|
||||||
|
clone->meshes << *tmp;
|
||||||
|
tmp->deleteLater();
|
||||||
|
qCDebug(graphics_scripting) << "//++ APPEND" << clone->meshes.constLast().ownedMesh.use_count();;
|
||||||
|
} else {
|
||||||
|
qCDebug(graphics_scripting) << "error cloning mesh" << cloned;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
qCDebug(graphics_scripting) << "//clone->getNumMeshes" << clone->getNumMeshes();
|
||||||
|
return clone;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const QVector<scriptable::ScriptableMeshPointer> scriptable::ScriptableModel::getConstMeshes() const {
|
||||||
|
QVector<scriptable::ScriptableMeshPointer> out;
|
||||||
|
for(const auto& mesh : meshes) {
|
||||||
|
const scriptable::ScriptableMesh* m = qobject_cast<const scriptable::ScriptableMesh*>(&mesh);
|
||||||
|
if (!m) {
|
||||||
|
m = scriptable::make_scriptowned<scriptable::ScriptableMesh>(mesh);
|
||||||
|
} else {
|
||||||
|
qCDebug(graphics_scripting) << "reusing scriptable mesh" << m;
|
||||||
|
}
|
||||||
|
const scriptable::ScriptableMeshPointer mp = scriptable::ScriptableMeshPointer(const_cast<scriptable::ScriptableMesh*>(m));
|
||||||
|
out << mp;
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVector<scriptable::ScriptableMeshPointer> scriptable::ScriptableModel::getMeshes() {
|
||||||
|
QVector<scriptable::ScriptableMeshPointer> out;
|
||||||
|
for(auto& mesh : meshes) {
|
||||||
|
scriptable::ScriptableMesh* m = qobject_cast<scriptable::ScriptableMesh*>(&mesh);
|
||||||
|
if (!m) {
|
||||||
|
m = scriptable::make_scriptowned<scriptable::ScriptableMesh>(mesh);
|
||||||
|
} else {
|
||||||
|
qCDebug(graphics_scripting) << "reusing scriptable mesh" << m;
|
||||||
|
}
|
||||||
|
scriptable::ScriptableMeshPointer mp = scriptable::ScriptableMeshPointer(m);
|
||||||
|
out << mp;
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
quint32 scriptable::ScriptableModel::mapAttributeValues(QScriptValue callback) {
|
||||||
|
quint32 result = 0;
|
||||||
|
QVector<scriptable::ScriptableMeshPointer> in = getMeshes();
|
||||||
|
if (in.size()) {
|
||||||
|
foreach (scriptable::ScriptableMeshPointer meshProxy, in) {
|
||||||
|
result += meshProxy->mapAttributeValues(callback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*namespace {
|
||||||
|
QScriptValue modelPointerToScriptValue(QScriptEngine* engine, scriptable::ScriptableModelPointer const &in) {
|
||||||
|
return qObjectToScriptValue(engine, in);
|
||||||
|
}
|
||||||
|
void modelPointerFromScriptValue(const QScriptValue& value, scriptable::ScriptableModelPointer &out) {
|
||||||
|
out = scriptable::qpointer_qobject_cast<scriptable::ScriptableModel>(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace scriptable {
|
||||||
|
bool registerMetaTypes(QScriptEngine* engine) {
|
||||||
|
qScriptRegisterMetaType(engine, modelPointerToScriptValue, modelPointerFromScriptValue);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
|
@ -16,7 +16,7 @@ namespace scriptable {
|
||||||
ScriptableModel(const ScriptableModel& other) : ScriptableModelBase(other) {}
|
ScriptableModel(const ScriptableModel& other) : ScriptableModelBase(other) {}
|
||||||
ScriptableModel(const ScriptableModelBase& other) : ScriptableModelBase(other) {}
|
ScriptableModel(const ScriptableModelBase& other) : ScriptableModelBase(other) {}
|
||||||
ScriptableModel& operator=(const ScriptableModelBase& view) { ScriptableModelBase::operator=(view); return *this; }
|
ScriptableModel& operator=(const ScriptableModelBase& view) { ScriptableModelBase::operator=(view); return *this; }
|
||||||
virtual ~ScriptableModel() { qDebug() << "~ScriptableModel" << this; }
|
//virtual ~ScriptableModel() { qDebug() << "~ScriptableModel" << this; }
|
||||||
|
|
||||||
Q_INVOKABLE scriptable::ScriptableModelPointer cloneModel(const QVariantMap& options = QVariantMap());
|
Q_INVOKABLE scriptable::ScriptableModelPointer cloneModel(const QVariantMap& options = QVariantMap());
|
||||||
// TODO: in future accessors for these could go here
|
// TODO: in future accessors for these could go here
|
||||||
|
|
|
@ -136,7 +136,8 @@ public:
|
||||||
|
|
||||||
static MeshPointer createIndexedTriangles_P3F(uint32_t numVertices, uint32_t numTriangles, const glm::vec3* vertices = nullptr, const uint32_t* indices = nullptr);
|
static MeshPointer createIndexedTriangles_P3F(uint32_t numVertices, uint32_t numTriangles, const glm::vec3* vertices = nullptr, const uint32_t* indices = nullptr);
|
||||||
|
|
||||||
QString displayName;
|
std::string modelName;
|
||||||
|
std::string displayName;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
|
|
@ -2448,7 +2448,8 @@ graphics::MeshPointer GeometryCache::meshFromShape(Shape geometryShape, glm::vec
|
||||||
auto partBuffer = new gpu::Buffer(sizeof(graphics::Mesh::Part), (gpu::Byte*)&part);
|
auto partBuffer = new gpu::Buffer(sizeof(graphics::Mesh::Part), (gpu::Byte*)&part);
|
||||||
mesh->setPartBuffer(gpu::BufferView(partBuffer, gpu::Element::PART_DRAWCALL));
|
mesh->setPartBuffer(gpu::BufferView(partBuffer, gpu::Element::PART_DRAWCALL));
|
||||||
|
|
||||||
mesh->displayName = QString("GeometryCache/shape::%1").arg(GeometryCache::stringFromShape(geometryShape));
|
mesh->modelName = GeometryCache::stringFromShape(geometryShape).toStdString();
|
||||||
|
mesh->displayName = QString("GeometryCache/shape::%1").arg(GeometryCache::stringFromShape(geometryShape)).toStdString();
|
||||||
|
|
||||||
return mesh;
|
return mesh;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,10 @@
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#include <QtCore/QLoggingCategory>
|
||||||
|
namespace { QLoggingCategory wtf{ "tim.Model.cpp" }; }
|
||||||
|
|
||||||
|
|
||||||
#include "Model.h"
|
#include "Model.h"
|
||||||
|
|
||||||
#include <QMetaType>
|
#include <QMetaType>
|
||||||
|
@ -26,7 +30,7 @@
|
||||||
#include <GLMHelpers.h>
|
#include <GLMHelpers.h>
|
||||||
#include <TBBHelpers.h>
|
#include <TBBHelpers.h>
|
||||||
|
|
||||||
#include <graphics-scripting/ScriptableModel.h>
|
#include <graphics-scripting/Forward.h>
|
||||||
#include <DualQuaternion.h>
|
#include <DualQuaternion.h>
|
||||||
|
|
||||||
#include <glm/gtc/packing.hpp>
|
#include <glm/gtc/packing.hpp>
|
||||||
|
@ -75,7 +79,7 @@ void initCollisionMaterials() {
|
||||||
graphics::MaterialPointer material;
|
graphics::MaterialPointer material;
|
||||||
material = std::make_shared<graphics::Material>();
|
material = std::make_shared<graphics::Material>();
|
||||||
int index = j * sectionWidth + i;
|
int index = j * sectionWidth + i;
|
||||||
float red = component[index];
|
float red = component[index % NUM_COLLISION_HULL_COLORS];
|
||||||
float green = component[(index + greenPhase) % NUM_COLLISION_HULL_COLORS];
|
float green = component[(index + greenPhase) % NUM_COLLISION_HULL_COLORS];
|
||||||
float blue = component[(index + bluePhase) % NUM_COLLISION_HULL_COLORS];
|
float blue = component[(index + bluePhase) % NUM_COLLISION_HULL_COLORS];
|
||||||
material->setAlbedo(glm::vec3(red, green, blue));
|
material->setAlbedo(glm::vec3(red, green, blue));
|
||||||
|
@ -573,35 +577,109 @@ bool Model::convexHullContains(glm::vec3 point) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
scriptable::ScriptableModel Model::getScriptableModel(bool* ok) {
|
// FIXME: temporary workaround that updates the whole FBXGeometry (to keep findRayIntersection in sync)
|
||||||
scriptable::ScriptableModel result;
|
#include "Model_temporary_hack.cpp.h"
|
||||||
|
|
||||||
|
bool Model::replaceScriptableModelMeshPart(scriptable::ScriptableModelBasePointer _newModel, int meshIndex, int partIndex) {
|
||||||
|
QMutexLocker lock(&_mutex);
|
||||||
|
|
||||||
|
if (!isLoaded()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// FIXME: temporary workaround for updating the whole FBXGeometry (to keep findRayIntersection in sync)
|
||||||
|
auto newRenderGeometry = new MyGeometryMappingResource(
|
||||||
|
_url, _renderGeometry, _newModel ? scriptable::make_qtowned<scriptable::ScriptableModelBase>(*_newModel) : nullptr
|
||||||
|
);
|
||||||
|
_needsUpdateTextures = true;
|
||||||
|
_visualGeometryRequestFailed = false;
|
||||||
|
invalidCalculatedMeshBoxes();
|
||||||
|
deleteGeometry();
|
||||||
|
_renderGeometry.reset(newRenderGeometry);
|
||||||
|
onInvalidate();
|
||||||
|
reset();
|
||||||
|
_rig.destroyAnimGraph();
|
||||||
|
assert(_rig.jointStatesEmpty());
|
||||||
|
updateGeometry();
|
||||||
|
calculateTriangleSets();
|
||||||
|
computeMeshPartLocalBounds();
|
||||||
|
_needsReload = false;
|
||||||
|
_needsFixupInScene = true;
|
||||||
|
invalidCalculatedMeshBoxes();
|
||||||
|
setRenderItemsNeedUpdate();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
scriptable::ScriptableModelBase Model::getScriptableModel(bool* ok) {
|
||||||
|
QMutexLocker lock(&_mutex);
|
||||||
|
scriptable::ScriptableModelBase result;
|
||||||
const Geometry::Pointer& renderGeometry = getGeometry();
|
const Geometry::Pointer& renderGeometry = getGeometry();
|
||||||
|
|
||||||
if (!isLoaded()) {
|
if (!isLoaded()) {
|
||||||
qDebug() << "Model::getScriptableModel -- !isLoaded";
|
qCDebug(wtf) << "Model::getScriptableModel -- !isLoaded";
|
||||||
return scriptable::ModelProvider::modelUnavailableError(ok);
|
return scriptable::ModelProvider::modelUnavailableError(ok);
|
||||||
}
|
}
|
||||||
|
|
||||||
const FBXGeometry& geometry = getFBXGeometry();
|
const FBXGeometry& geometry = getFBXGeometry();
|
||||||
auto mat4toVariant = [](const glm::mat4& mat4) -> QVariant {
|
Transform offset;
|
||||||
QVector<float> floats;
|
offset.setScale(_scale);
|
||||||
floats.resize(16);
|
offset.postTranslate(_offset);
|
||||||
memcpy(floats.data(), &mat4, sizeof(glm::mat4));
|
glm::mat4 offsetMat = offset.getMatrix();
|
||||||
QVariant v;
|
glm::mat4 meshToModelMatrix = glm::scale(_scale) * glm::translate(_offset);
|
||||||
v.setValue<QVector<float>>(floats);
|
glm::mat4 meshToWorldMatrix = createMatFromQuatAndPos(_rotation, _translation) * meshToModelMatrix;
|
||||||
return v;
|
|
||||||
};
|
|
||||||
result.metadata = {
|
result.metadata = {
|
||||||
{ "url", _url.toString() },
|
{ "url", _url.toString() },
|
||||||
{ "textures", renderGeometry->getTextures() },
|
{ "textures", renderGeometry->getTextures() },
|
||||||
{ "offset", vec3toVariant(_offset) },
|
{ "offset", vec3toVariant(_offset) },
|
||||||
{ "scale", vec3toVariant(_scale) },
|
{ "scale", vec3toVariant(getScale()) },
|
||||||
{ "rotation", quatToVariant(_rotation) },
|
{ "rotation", quatToVariant(getRotation()) },
|
||||||
{ "translation", vec3toVariant(_translation) },
|
{ "translation", vec3toVariant(getTranslation()) },
|
||||||
{ "meshToModel", mat4toVariant(glm::scale(_scale) * glm::translate(_offset)) },
|
{ "meshToModel", buffer_helpers::toVariant(meshToModelMatrix) },
|
||||||
{ "meshToWorld", mat4toVariant(createMatFromQuatAndPos(_rotation, _translation) * (glm::scale(_scale) * glm::translate(_offset))) },
|
{ "meshToWorld", buffer_helpers::toVariant(meshToWorldMatrix) },
|
||||||
{ "geometryOffset", mat4toVariant(geometry.offset) },
|
{ "geometryOffset", buffer_helpers::toVariant(geometry.offset) },
|
||||||
|
{ "naturalDimensions", vec3toVariant(getNaturalDimensions()) },
|
||||||
|
{ "meshExtents", buffer_helpers::toVariant(getMeshExtents()) },
|
||||||
|
{ "unscaledMeshExtents", buffer_helpers::toVariant(getUnscaledMeshExtents()) },
|
||||||
|
{ "meshBound", buffer_helpers::toVariant(Extents(getRenderableMeshBound())) },
|
||||||
|
{ "bindExtents", buffer_helpers::toVariant(getBindExtents()) },
|
||||||
|
{ "offsetMat", buffer_helpers::toVariant(offsetMat) },
|
||||||
|
{ "transform", buffer_helpers::toVariant(getTransform().getMatrix()) },
|
||||||
};
|
};
|
||||||
|
{
|
||||||
|
Transform transform;
|
||||||
|
transform.setScale(getScale());
|
||||||
|
transform.setTranslation(getTranslation());
|
||||||
|
transform.setRotation(getRotation());
|
||||||
|
result.metadata["_transform"] = buffer_helpers::toVariant(transform.getMatrix());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
glm::vec3 position = _translation;
|
||||||
|
glm::mat4 rotation = glm::mat4_cast(_rotation);
|
||||||
|
glm::mat4 translation = glm::translate(position);
|
||||||
|
glm::mat4 modelToWorldMatrix = translation * rotation;
|
||||||
|
//glm::mat4 worldToModelMatrix = glm::inverse(modelToWorldMatrix);
|
||||||
|
result.metadata["_modelToWorld"] = buffer_helpers::toVariant(modelToWorldMatrix);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
glm::mat4 meshToModelMatrix = glm::scale(_scale) * glm::translate(_offset);
|
||||||
|
glm::mat4 meshToWorldMatrix = createMatFromQuatAndPos(_rotation, _translation) * meshToModelMatrix;
|
||||||
|
//glm::mat4 worldToMeshMatrix = glm::inverse(meshToWorldMatrix);
|
||||||
|
result.metadata["_meshToWorld"] = buffer_helpers::toVariant(meshToWorldMatrix);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Transform transform;
|
||||||
|
transform.setTranslation(_translation);
|
||||||
|
transform.setRotation(_rotation);
|
||||||
|
Transform offset;
|
||||||
|
offset.setScale(_scale);
|
||||||
|
offset.postTranslate(_offset);
|
||||||
|
Transform output;
|
||||||
|
Transform::mult( output, transform, offset);
|
||||||
|
result.metadata["_renderTransform"] = buffer_helpers::toVariant(output.getMatrix());
|
||||||
|
}
|
||||||
|
|
||||||
QVariantList submeshes;
|
QVariantList submeshes;
|
||||||
int numberOfMeshes = geometry.meshes.size();
|
int numberOfMeshes = geometry.meshes.size();
|
||||||
for (int i = 0; i < numberOfMeshes; i++) {
|
for (int i = 0; i < numberOfMeshes; i++) {
|
||||||
|
@ -610,53 +688,43 @@ scriptable::ScriptableModel Model::getScriptableModel(bool* ok) {
|
||||||
if (!mesh) {
|
if (!mesh) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
result.meshes << std::const_pointer_cast<graphics::Mesh>(mesh);
|
auto name = geometry.getModelNameOfMesh(i);
|
||||||
auto extraInfo = geometry.getModelNameOfMesh(i);
|
qCDebug(wtf) << "Model::getScriptableModel #" << i << QString::fromStdString(mesh->displayName) << name;
|
||||||
qDebug() << "Model::getScriptableModel #" << i << QString(mesh->displayName) << extraInfo;
|
const AABox& box = _modelSpaceMeshTriangleSets.value(i).getBounds();
|
||||||
submeshes << QVariantMap{
|
AABox hardbounds;
|
||||||
|
auto meshTransform = geometry.offset * fbxMesh.modelTransform;
|
||||||
|
for (const auto& v : fbxMesh.vertices) {
|
||||||
|
hardbounds += glm::vec3(meshTransform * glm::vec4(v,1));
|
||||||
|
}
|
||||||
|
QVariantList renderIDs;
|
||||||
|
for (uint32_t m = 0; m < _modelMeshRenderItemIDs.size(); m++) {
|
||||||
|
auto meshIndex = _modelMeshRenderItemShapes.size() > m ? _modelMeshRenderItemShapes.at(m).meshIndex : -1;
|
||||||
|
if (meshIndex == i) {
|
||||||
|
renderIDs << _modelMeshRenderItemIDs[m];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result.append(std::const_pointer_cast<graphics::Mesh>(mesh), {
|
||||||
{ "index", i },
|
{ "index", i },
|
||||||
|
{ "name", name },
|
||||||
|
{ "renderIDs", renderIDs },
|
||||||
{ "meshIndex", fbxMesh.meshIndex },
|
{ "meshIndex", fbxMesh.meshIndex },
|
||||||
{ "modelName", extraInfo },
|
{ "displayName", QString::fromStdString(mesh->displayName) },
|
||||||
{ "transform", mat4toVariant(fbxMesh.modelTransform) },
|
{ "modelName", QString::fromStdString(mesh->modelName) },
|
||||||
{ "extents", QVariantMap({
|
{ "modelTransform", buffer_helpers::toVariant(fbxMesh.modelTransform) },
|
||||||
{ "minimum", vec3toVariant(fbxMesh.meshExtents.minimum) },
|
{ "transform", buffer_helpers::toVariant(geometry.offset * fbxMesh.modelTransform) },
|
||||||
{ "maximum", vec3toVariant(fbxMesh.meshExtents.maximum) },
|
{ "extents", buffer_helpers::toVariant(fbxMesh.meshExtents) },
|
||||||
})},
|
{ "bounds", buffer_helpers::toVariant(Extents(box)) },
|
||||||
};
|
{ "hardbounds", buffer_helpers::toVariant(Extents(hardbounds)) },
|
||||||
|
});
|
||||||
}
|
}
|
||||||
if (ok) {
|
if (ok) {
|
||||||
*ok = true;
|
*ok = true;
|
||||||
}
|
}
|
||||||
qDebug() << "//Model::getScriptableModel -- #" << result.meshes.size();
|
qCDebug(wtf) << "//Model::getScriptableModel -- #" << result.meshes.size();
|
||||||
result.metadata["submeshes"] = submeshes;
|
result.metadata["submeshes"] = submeshes;
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
// TODO: remove -- this was an earlier approach using renderGeometry instead of FBXGeometry
|
|
||||||
#if 0 // renderGeometry approach
|
|
||||||
const Geometry::GeometryMeshes& meshes = renderGeometry->getMeshes();
|
|
||||||
Transform offset;
|
|
||||||
offset.setScale(_scale);
|
|
||||||
offset.postTranslate(_offset);
|
|
||||||
glm::mat4 offsetMat = offset.getMatrix();
|
|
||||||
|
|
||||||
for (std::shared_ptr<const graphics::Mesh> mesh : meshes) {
|
|
||||||
if (!mesh) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
qDebug() << "Model::getScriptableModel #" << i++ << mesh->displayName;
|
|
||||||
auto newmesh = mesh->map(
|
|
||||||
[=](glm::vec3 position) {
|
|
||||||
return glm::vec3(offsetMat * glm::vec4(position, 1.0f));
|
|
||||||
},
|
|
||||||
[=](glm::vec3 color) { return color; },
|
|
||||||
[=](glm::vec3 normal) {
|
|
||||||
return glm::normalize(glm::vec3(offsetMat * glm::vec4(normal, 0.0f)));
|
|
||||||
},
|
|
||||||
[&](uint32_t index) { return index; });
|
|
||||||
newmesh->displayName = mesh->displayName;
|
|
||||||
result << newmesh;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Model::calculateTriangleSets() {
|
void Model::calculateTriangleSets() {
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
#include <gpu/Batch.h>
|
#include <gpu/Batch.h>
|
||||||
#include <render/Forward.h>
|
#include <render/Forward.h>
|
||||||
#include <render/Scene.h>
|
#include <render/Scene.h>
|
||||||
#include <graphics-scripting/ScriptableModel.h>
|
#include <graphics-scripting/Forward.h>
|
||||||
#include <Transform.h>
|
#include <Transform.h>
|
||||||
#include <SpatiallyNestable.h>
|
#include <SpatiallyNestable.h>
|
||||||
#include <TriangleSet.h>
|
#include <TriangleSet.h>
|
||||||
|
@ -314,7 +314,8 @@ public:
|
||||||
int getResourceDownloadAttempts() { return _renderWatcher.getResourceDownloadAttempts(); }
|
int getResourceDownloadAttempts() { return _renderWatcher.getResourceDownloadAttempts(); }
|
||||||
int getResourceDownloadAttemptsRemaining() { return _renderWatcher.getResourceDownloadAttemptsRemaining(); }
|
int getResourceDownloadAttemptsRemaining() { return _renderWatcher.getResourceDownloadAttemptsRemaining(); }
|
||||||
|
|
||||||
Q_INVOKABLE virtual scriptable::ScriptableModel getScriptableModel(bool* ok = nullptr) override;
|
Q_INVOKABLE virtual scriptable::ScriptableModelBase getScriptableModel(bool* ok = nullptr) override;
|
||||||
|
virtual bool replaceScriptableModelMeshPart(scriptable::ScriptableModelBasePointer model, int meshIndex, int partIndex) override;
|
||||||
|
|
||||||
void scaleToFit();
|
void scaleToFit();
|
||||||
|
|
||||||
|
|
121
libraries/render-utils/src/Model_temporary_hack.cpp.h
Normal file
121
libraries/render-utils/src/Model_temporary_hack.cpp.h
Normal file
|
@ -0,0 +1,121 @@
|
||||||
|
#include <graphics-scripting/BufferViewHelpers.h>
|
||||||
|
#include <graphics-scripting/GraphicsScriptingUtil.h>
|
||||||
|
class MyGeometryMappingResource : public GeometryResource {
|
||||||
|
// Q_OBJECT
|
||||||
|
public:
|
||||||
|
virtual void init(bool resetLoaded = true) override {
|
||||||
|
qCDebug(wtf) << "############################# Snarfing init()...";
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void deleter() override {
|
||||||
|
qCDebug(wtf) << "############################# Snarfing deleter()...";
|
||||||
|
}
|
||||||
|
shared_ptr<FBXGeometry> fbxGeometry;
|
||||||
|
MyGeometryMappingResource(const QUrl& url, Geometry::Pointer originalGeometry, std::shared_ptr<scriptable::ScriptableModelBase> newModel) : GeometryResource(url) {
|
||||||
|
fbxGeometry = std::make_shared<FBXGeometry>();
|
||||||
|
FBXGeometry& geometry = *fbxGeometry.get();
|
||||||
|
const FBXGeometry* original;
|
||||||
|
shared_ptr<FBXGeometry> tmpGeometry;
|
||||||
|
if (originalGeometry) {
|
||||||
|
original = &originalGeometry->getFBXGeometry();
|
||||||
|
} else {
|
||||||
|
tmpGeometry = std::make_shared<FBXGeometry>();
|
||||||
|
original = tmpGeometry.get();
|
||||||
|
}
|
||||||
|
geometry.originalURL = original->originalURL;
|
||||||
|
|
||||||
|
geometry.author = original->author;
|
||||||
|
geometry.applicationName = original->applicationName;
|
||||||
|
for (const auto &j : original->joints) {
|
||||||
|
geometry.joints << j;
|
||||||
|
}
|
||||||
|
geometry.jointIndices = QHash<QString,int>{ original->jointIndices };
|
||||||
|
|
||||||
|
geometry.animationFrames = QVector<FBXAnimationFrame>{ original->animationFrames };
|
||||||
|
geometry.meshIndicesToModelNames = QHash<int, QString>{ original->meshIndicesToModelNames };
|
||||||
|
geometry.blendshapeChannelNames = QList<QString>{ original->blendshapeChannelNames };
|
||||||
|
|
||||||
|
geometry.hasSkeletonJoints = original->hasSkeletonJoints;
|
||||||
|
geometry.offset = original->offset;
|
||||||
|
geometry.leftEyeJointIndex = original->leftEyeJointIndex;
|
||||||
|
geometry.rightEyeJointIndex = original->rightEyeJointIndex;
|
||||||
|
geometry.neckJointIndex = original->neckJointIndex;
|
||||||
|
geometry.rootJointIndex = original->rootJointIndex;
|
||||||
|
geometry.leanJointIndex = original->leanJointIndex;
|
||||||
|
geometry.headJointIndex = original->headJointIndex;
|
||||||
|
geometry.leftHandJointIndex = original->leftHandJointIndex;
|
||||||
|
geometry.rightHandJointIndex = original->rightHandJointIndex;
|
||||||
|
geometry.leftToeJointIndex = original->leftToeJointIndex;
|
||||||
|
geometry.rightToeJointIndex = original->rightToeJointIndex;
|
||||||
|
geometry.leftEyeSize = original->leftEyeSize;
|
||||||
|
geometry.rightEyeSize = original->rightEyeSize;
|
||||||
|
geometry.humanIKJointIndices = original->humanIKJointIndices;
|
||||||
|
geometry.palmDirection = original->palmDirection;
|
||||||
|
geometry.neckPivot = original->neckPivot;
|
||||||
|
geometry.bindExtents = original->bindExtents;
|
||||||
|
|
||||||
|
// Copy materials
|
||||||
|
QHash<QString, size_t> materialIDAtlas;
|
||||||
|
for (const FBXMaterial& material : original->materials) {
|
||||||
|
materialIDAtlas[material.materialID] = _materials.size();
|
||||||
|
_materials.push_back(std::make_shared<NetworkMaterial>(material, _textureBaseUrl));
|
||||||
|
}
|
||||||
|
std::shared_ptr<GeometryMeshes> meshes = std::make_shared<GeometryMeshes>();
|
||||||
|
std::shared_ptr<GeometryMeshParts> parts = std::make_shared<GeometryMeshParts>();
|
||||||
|
int meshID = 0;
|
||||||
|
if (newModel) {
|
||||||
|
geometry.meshExtents.reset();
|
||||||
|
for (const auto& newMesh : newModel->meshes) {
|
||||||
|
FBXMesh mesh;
|
||||||
|
if (meshID < original->meshes.size()) {
|
||||||
|
mesh = original->meshes.at(meshID); // copy
|
||||||
|
}
|
||||||
|
mesh._mesh = newMesh.getMeshPointer();
|
||||||
|
// duplicate the buffers
|
||||||
|
mesh.vertices = buffer_helpers::toVector<glm::vec3>(mesh._mesh->getVertexBuffer(), "mesh.vertices");
|
||||||
|
mesh.normals = buffer_helpers::toVector<glm::vec3>(buffer_helpers::getBufferView(mesh._mesh, gpu::Stream::NORMAL), "mesh.normals");
|
||||||
|
mesh.colors = buffer_helpers::toVector<glm::vec3>(buffer_helpers::getBufferView(mesh._mesh, gpu::Stream::COLOR), "mesh.colors");
|
||||||
|
mesh.texCoords = buffer_helpers::toVector<glm::vec2>(buffer_helpers::getBufferView(mesh._mesh, gpu::Stream::TEXCOORD0), "mesh.texCoords");
|
||||||
|
mesh.texCoords1 = buffer_helpers::toVector<glm::vec2>(buffer_helpers::getBufferView(mesh._mesh, gpu::Stream::TEXCOORD1), "mesh.texCoords1");
|
||||||
|
geometry.meshes << mesh;
|
||||||
|
// Copy mesh pointers
|
||||||
|
meshes->emplace_back(newMesh.getMeshPointer());//buffer_helpers::cloneMesh(ptr));
|
||||||
|
int partID = 0;
|
||||||
|
const auto oldParts = mesh.parts;
|
||||||
|
mesh.parts.clear();
|
||||||
|
for (const FBXMeshPart& fbxPart : oldParts) {
|
||||||
|
FBXMeshPart part; // copy;
|
||||||
|
part.materialID = fbxPart.materialID;
|
||||||
|
// Construct local parts
|
||||||
|
///qCDebug(wtf) << "GeometryMappingResource -- meshes part" << meshID << partID << part.materialID;
|
||||||
|
part.triangleIndices = buffer_helpers::toVector<int>(mesh._mesh->getIndexBuffer(), "part.triangleIndices");
|
||||||
|
mesh.parts << part;
|
||||||
|
auto p = std::make_shared<MeshPart>(meshID, partID, (int)materialIDAtlas[part.materialID]);
|
||||||
|
parts->push_back(p);
|
||||||
|
partID++;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// accumulate local transforms
|
||||||
|
// compute the mesh extents from the transformed vertices
|
||||||
|
foreach (const glm::vec3& vertex, mesh.vertices) {
|
||||||
|
glm::vec3 transformedVertex = glm::vec3(mesh.modelTransform * glm::vec4(vertex, 1.0f));
|
||||||
|
geometry.meshExtents.minimum = glm::min(geometry.meshExtents.minimum, transformedVertex);
|
||||||
|
geometry.meshExtents.maximum = glm::max(geometry.meshExtents.maximum, transformedVertex);
|
||||||
|
|
||||||
|
mesh.meshExtents.minimum = glm::min(mesh.meshExtents.minimum, transformedVertex);
|
||||||
|
mesh.meshExtents.maximum = glm::max(mesh.meshExtents.maximum, transformedVertex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
meshID++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_meshes = meshes;
|
||||||
|
_meshParts = parts;
|
||||||
|
_animGraphOverrideUrl = originalGeometry ? originalGeometry->getAnimGraphOverrideUrl() : QUrl();
|
||||||
|
_loaded = true;
|
||||||
|
_fbxGeometry = fbxGeometry;
|
||||||
|
finishedLoading(true);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
|
@ -440,7 +440,7 @@ void AssetScriptingInterface::saveToCache(const QUrl& rawURL, const QByteArray&
|
||||||
JS_VERIFY(url.scheme() == "atp" || url.scheme() == "cache", "only 'atp' and 'cache' URL schemes supported");
|
JS_VERIFY(url.scheme() == "atp" || url.scheme() == "cache", "only 'atp' and 'cache' URL schemes supported");
|
||||||
JS_VERIFY(hash.isEmpty() || hash == hashDataHex(data), QString("invalid checksum hash for atp:HASH style URL (%1 != %2)").arg(hash, hashDataHex(data)));
|
JS_VERIFY(hash.isEmpty() || hash == hashDataHex(data), QString("invalid checksum hash for atp:HASH style URL (%1 != %2)").arg(hash, hashDataHex(data)));
|
||||||
|
|
||||||
qCDebug(scriptengine) << "saveToCache" << url.toDisplayString() << data << hash << metadata;
|
//qCDebug(scriptengine) << "saveToCache" << url.toDisplayString() << data << hash << metadata;
|
||||||
|
|
||||||
jsPromiseReady(Parent::saveToCache(url, data, metadata), scope, callback);
|
jsPromiseReady(Parent::saveToCache(url, data, metadata), scope, callback);
|
||||||
}
|
}
|
||||||
|
|
|
@ -132,6 +132,20 @@ QUrl expandScriptUrl(const QUrl& rawScriptURL) {
|
||||||
|
|
||||||
QObject* scriptsModel();
|
QObject* scriptsModel();
|
||||||
|
|
||||||
|
bool NativeScriptInitializers::registerNativeScriptInitializer(NativeScriptInitializer initializer) {
|
||||||
|
return registerScriptInitializer([=](ScriptEnginePointer engine) {
|
||||||
|
initializer(qobject_cast<QScriptEngine*>(engine.data()));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NativeScriptInitializers::registerScriptInitializer(ScriptInitializer initializer) {
|
||||||
|
if (auto scriptEngines = DependencyManager::get<ScriptEngines>().data()) {
|
||||||
|
scriptEngines->registerScriptInitializer(initializer);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void ScriptEngines::registerScriptInitializer(ScriptInitializer initializer) {
|
void ScriptEngines::registerScriptInitializer(ScriptInitializer initializer) {
|
||||||
_scriptInitializers.push_back(initializer);
|
_scriptInitializers.push_back(initializer);
|
||||||
}
|
}
|
||||||
|
@ -520,6 +534,17 @@ void ScriptEngines::onScriptEngineLoaded(const QString& rawScriptURL) {
|
||||||
emit scriptCountChanged();
|
emit scriptCountChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ScriptEngines::runScriptInitializers(ScriptEnginePointer scriptEngine) {
|
||||||
|
// register our application services and set it off on its own thread
|
||||||
|
int ii=0;
|
||||||
|
for (auto initializer : _scriptInitializers) {
|
||||||
|
ii++;
|
||||||
|
qDebug() << "initializer" << ii;
|
||||||
|
initializer(scriptEngine);
|
||||||
|
}
|
||||||
|
return ii;
|
||||||
|
}
|
||||||
|
|
||||||
void ScriptEngines::launchScriptEngine(ScriptEnginePointer scriptEngine) {
|
void ScriptEngines::launchScriptEngine(ScriptEnginePointer scriptEngine) {
|
||||||
connect(scriptEngine.data(), &ScriptEngine::finished, this, &ScriptEngines::onScriptFinished, Qt::DirectConnection);
|
connect(scriptEngine.data(), &ScriptEngine::finished, this, &ScriptEngines::onScriptFinished, Qt::DirectConnection);
|
||||||
connect(scriptEngine.data(), &ScriptEngine::loadScript, [&](const QString& scriptName, bool userLoaded) {
|
connect(scriptEngine.data(), &ScriptEngine::loadScript, [&](const QString& scriptName, bool userLoaded) {
|
||||||
|
@ -529,10 +554,7 @@ void ScriptEngines::launchScriptEngine(ScriptEnginePointer scriptEngine) {
|
||||||
loadScript(scriptName, userLoaded, false, false, true);
|
loadScript(scriptName, userLoaded, false, false, true);
|
||||||
});
|
});
|
||||||
|
|
||||||
// register our application services and set it off on its own thread
|
runScriptInitializers(scriptEngine);
|
||||||
for (auto initializer : _scriptInitializers) {
|
|
||||||
initializer(scriptEngine);
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME disabling 'shift key' debugging for now. If you start up the application with
|
// FIXME disabling 'shift key' debugging for now. If you start up the application with
|
||||||
// the shift key held down, it triggers a deadlock because of script interfaces running
|
// the shift key held down, it triggers a deadlock because of script interfaces running
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
#include <SettingHandle.h>
|
#include <SettingHandle.h>
|
||||||
#include <DependencyManager.h>
|
#include <DependencyManager.h>
|
||||||
|
#include <shared/ScriptInitializerMixin.h>
|
||||||
|
|
||||||
#include "ScriptEngine.h"
|
#include "ScriptEngine.h"
|
||||||
#include "ScriptsModel.h"
|
#include "ScriptsModel.h"
|
||||||
|
@ -26,6 +27,12 @@
|
||||||
|
|
||||||
class ScriptEngine;
|
class ScriptEngine;
|
||||||
|
|
||||||
|
class NativeScriptInitializers : public ScriptInitializerMixin {
|
||||||
|
public:
|
||||||
|
bool registerNativeScriptInitializer(NativeScriptInitializer initializer) override;
|
||||||
|
bool registerScriptInitializer(ScriptInitializer initializer) override;
|
||||||
|
};
|
||||||
|
|
||||||
class ScriptEngines : public QObject, public Dependency {
|
class ScriptEngines : public QObject, public Dependency {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
@ -34,11 +41,11 @@ class ScriptEngines : public QObject, public Dependency {
|
||||||
Q_PROPERTY(QString debugScriptUrl READ getDebugScriptUrl WRITE setDebugScriptUrl)
|
Q_PROPERTY(QString debugScriptUrl READ getDebugScriptUrl WRITE setDebugScriptUrl)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using ScriptInitializer = std::function<void(ScriptEnginePointer)>;
|
using ScriptInitializer = ScriptInitializerMixin::ScriptInitializer;
|
||||||
|
|
||||||
ScriptEngines(ScriptEngine::Context context);
|
ScriptEngines(ScriptEngine::Context context);
|
||||||
void registerScriptInitializer(ScriptInitializer initializer);
|
void registerScriptInitializer(ScriptInitializer initializer);
|
||||||
|
int runScriptInitializers(ScriptEnginePointer engine);
|
||||||
void loadScripts();
|
void loadScripts();
|
||||||
void saveScripts();
|
void saveScripts();
|
||||||
|
|
||||||
|
|
38
libraries/shared/src/shared/ScriptInitializerMixin.h
Normal file
38
libraries/shared/src/shared/ScriptInitializerMixin.h
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
//
|
||||||
|
// ScriptInitializerMixin.h
|
||||||
|
// libraries/shared/src/shared
|
||||||
|
//
|
||||||
|
// Copyright 2018 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <QSharedPointer>
|
||||||
|
#include "../DependencyManager.h"
|
||||||
|
|
||||||
|
class QScriptEngine;
|
||||||
|
class ScriptEngine;
|
||||||
|
|
||||||
|
class ScriptInitializerMixin : public QObject, public Dependency {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
// Lightweight `QScriptEngine*` initializer (only depends on built-in Qt components)
|
||||||
|
// example registration:
|
||||||
|
// eg: [&](QScriptEngine* engine) -> bool {
|
||||||
|
// engine->globalObject().setProperties("API", engine->newQObject(...instance...))
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
using NativeScriptInitializer = std::function<void(QScriptEngine*)>;
|
||||||
|
virtual bool registerNativeScriptInitializer(NativeScriptInitializer initializer) = 0;
|
||||||
|
|
||||||
|
// Heavyweight `ScriptEngine*` initializer (tightly coupled to Interface and script-engine library internals)
|
||||||
|
// eg: [&](ScriptEnginePointer scriptEngine) -> bool {
|
||||||
|
// engine->registerGlobalObject("API", ...instance..);
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
using ScriptEnginePointer = QSharedPointer<ScriptEngine>;
|
||||||
|
using ScriptInitializer = std::function<void(ScriptEnginePointer)>;
|
||||||
|
virtual bool registerScriptInitializer(ScriptInitializer initializer) { return false; };
|
||||||
|
};
|
Loading…
Reference in a new issue