mirror of
https://github.com/overte-org/overte.git
synced 2025-04-09 13:02:24 +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<StatTracker>();
|
||||
DependencyManager::set<ScriptEngines>(ScriptEngine::CLIENT_SCRIPT);
|
||||
DependencyManager::set<ScriptInitializerMixin, NativeScriptInitializers>();
|
||||
DependencyManager::set<Preferences>();
|
||||
DependencyManager::set<recording::Deck>();
|
||||
DependencyManager::set<recording::Recorder>();
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
#include "ModelEntityItem.h"
|
||||
#include "RenderableModelEntityItem.h"
|
||||
|
||||
#include <graphics-scripting/ScriptableModel.h>
|
||||
#include <graphics-scripting/Forward.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" ;
|
||||
if (!_skeletonModel || !_skeletonModel->isLoaded()) {
|
||||
return scriptable::ModelProvider::modelUnavailableError(ok);
|
||||
}
|
||||
scriptable::ScriptableModel result;
|
||||
result.metadata = {
|
||||
scriptable::ScriptableModelBase result = _skeletonModel->getScriptableModel(ok);
|
||||
result.objectID = getSessionUUID();
|
||||
result.mixin({
|
||||
{ "avatarID", getSessionUUID().toString() },
|
||||
{ "url", _skeletonModelURL.toString() },
|
||||
{ "origin", "Avatar/avatar::" + _displayName },
|
||||
{ "textures", _skeletonModel->getTextures() },
|
||||
};
|
||||
result.mixin(_skeletonModel->getScriptableModel(ok));
|
||||
|
||||
// FIXME: for now access to attachment models are merged with the main avatar model
|
||||
for (auto& attachmentModel : _attachmentModels) {
|
||||
if (attachmentModel->isLoaded()) {
|
||||
result.mixin(attachmentModel->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++) {
|
||||
auto& model = _attachmentModels.at(i);
|
||||
if (model->isLoaded()) {
|
||||
result.append(model->getScriptableModel(ok), _attachmentData.at(i).toVariant().toMap());
|
||||
}
|
||||
}
|
||||
if (ok) {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
|
||||
//
|
||||
// Avatar.h
|
||||
// interface/src/avatar
|
||||
|
@ -20,7 +21,7 @@
|
|||
#include <AvatarData.h>
|
||||
#include <ShapeInfo.h>
|
||||
#include <render/Scene.h>
|
||||
#include <graphics-scripting/ScriptableModel.h>
|
||||
#include <graphics-scripting/Forward.h>
|
||||
#include <GLMHelpers.h>
|
||||
|
||||
|
||||
|
@ -274,7 +275,7 @@ public:
|
|||
virtual void setAvatarEntityDataChanged(bool value) override;
|
||||
|
||||
|
||||
virtual scriptable::ScriptableModel getScriptableModel(bool* ok = nullptr) override;
|
||||
virtual scriptable::ScriptableModelBase getScriptableModel(bool* ok = nullptr) override;
|
||||
public slots:
|
||||
|
||||
// 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) {
|
||||
qCDebug(entitiesrenderer) << "REPLACING RenderableModelEntityItem" << newModel->objectName();
|
||||
ModelPointer model;
|
||||
withReadLock([&] { model = _model; });
|
||||
|
||||
|
@ -970,7 +969,7 @@ bool render::entities::ModelEntityRenderer::replaceScriptableModelMeshPart(scrip
|
|||
return false;
|
||||
}
|
||||
|
||||
return _model->replaceScriptableModelMeshPart(newModel, meshIndex, partIndex);
|
||||
return model->replaceScriptableModelMeshPart(newModel, meshIndex, partIndex);
|
||||
}
|
||||
|
||||
void RenderableModelEntityItem::simulateRelayedJoints() {
|
||||
|
|
|
@ -281,7 +281,7 @@ std::vector<PolyLineEntityRenderer::Vertex> PolyLineEntityRenderer::updateVertic
|
|||
return vertices;
|
||||
}
|
||||
|
||||
scriptable::ScriptableModel PolyLineEntityRenderer::getScriptableModel(bool *ok) {
|
||||
scriptable::ScriptableModelBase PolyLineEntityRenderer::getScriptableModel(bool *ok) {
|
||||
// TODO: adapt polyline into a triangles mesh...
|
||||
return EntityRenderer::getScriptableModel(ok);
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ class PolyLineEntityRenderer : public TypedEntityRenderer<PolyLineEntityItem> {
|
|||
public:
|
||||
PolyLineEntityRenderer(const EntityItemPointer& entity);
|
||||
|
||||
virtual scriptable::ScriptableModel getScriptableModel(bool* ok = nullptr) override;
|
||||
virtual scriptable::ScriptableModelBase getScriptableModel(bool* ok = nullptr) override;
|
||||
protected:
|
||||
virtual bool needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const override;
|
||||
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) {
|
||||
return scriptable::ModelProvider::modelUnavailableError(ok);
|
||||
}
|
||||
|
||||
bool success = false;
|
||||
glm::mat4 transform = voxelToLocalMatrix();
|
||||
scriptable::ScriptableModel result;
|
||||
scriptable::ScriptableModelBase result;
|
||||
withReadLock([&] {
|
||||
gpu::BufferView::Index numVertices = (gpu::BufferView::Index)_mesh->getNumVertices();
|
||||
if (!_meshReady) {
|
||||
|
@ -1433,11 +1433,12 @@ scriptable::ScriptableModel RenderablePolyVoxEntityItem::getScriptableModel(bool
|
|||
} else {
|
||||
success = true;
|
||||
// the mesh will be in voxel-space. transform it into object-space
|
||||
result.meshes <<
|
||||
_mesh->map([=](glm::vec3 position){ return glm::vec3(transform * glm::vec4(position, 1.0f)); },
|
||||
[=](glm::vec3 color){ return color; },
|
||||
[=](glm::vec3 normal){ return glm::normalize(glm::vec3(transform * glm::vec4(normal, 0.0f))); },
|
||||
[&](uint32_t index){ return index; });
|
||||
result.append(_mesh->map(
|
||||
[=](glm::vec3 position){ return glm::vec3(transform * glm::vec4(position, 1.0f)); },
|
||||
[=](glm::vec3 color){ return color; },
|
||||
[=](glm::vec3 normal){ return glm::normalize(glm::vec3(transform * glm::vec4(normal, 0.0f))); },
|
||||
[&](uint32_t index){ return index; }
|
||||
));
|
||||
}
|
||||
});
|
||||
if (ok) {
|
||||
|
|
|
@ -113,7 +113,7 @@ public:
|
|||
|
||||
void setVolDataDirty() { withWriteLock([&] { _volDataDirty = true; _meshReady = false; }); }
|
||||
|
||||
virtual scriptable::ScriptableModel getScriptableModel(bool* ok = nullptr) override;
|
||||
virtual scriptable::ScriptableModelBase getScriptableModel(bool* ok = nullptr) override;
|
||||
|
||||
private:
|
||||
bool updateOnCount(const ivec3& v, uint8_t toValue);
|
||||
|
@ -163,7 +163,7 @@ class PolyVoxEntityRenderer : public TypedEntityRenderer<RenderablePolyVoxEntity
|
|||
|
||||
public:
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -157,8 +157,8 @@ void ShapeEntityRenderer::doRender(RenderArgs* args) {
|
|||
args->_details._trianglesRendered += (int)triCount;
|
||||
}
|
||||
|
||||
scriptable::ScriptableModel ShapeEntityRenderer::getScriptableModel(bool* ok) {
|
||||
scriptable::ScriptableModel result;
|
||||
scriptable::ScriptableModelBase ShapeEntityRenderer::getScriptableModel(bool* ok) {
|
||||
scriptable::ScriptableModelBase result;
|
||||
result.metadata = {
|
||||
{ "entityID", getEntity()->getID().toString() },
|
||||
{ "shape", entity::stringFromShape(_shape) },
|
||||
|
@ -169,7 +169,10 @@ scriptable::ScriptableModel ShapeEntityRenderer::getScriptableModel(bool* ok) {
|
|||
auto vertexColor = glm::vec3(_color);
|
||||
auto success = false;
|
||||
if (auto mesh = geometryCache->meshFromShape(geometryShape, vertexColor)) {
|
||||
result.meshes << mesh;
|
||||
scriptable::ScriptableMeshBase base{ mesh, {
|
||||
{ "shape", entity::stringFromShape(_shape) },
|
||||
}};
|
||||
result.append(base);
|
||||
success = true;
|
||||
}
|
||||
if (ok) {
|
||||
|
|
|
@ -22,7 +22,7 @@ class ShapeEntityRenderer : public TypedEntityRenderer<ShapeEntityItem> {
|
|||
public:
|
||||
ShapeEntityRenderer(const EntityItemPointer& entity);
|
||||
|
||||
virtual scriptable::ScriptableModel getScriptableModel(bool* ok = nullptr) override;
|
||||
virtual scriptable::ScriptableModelBase getScriptableModel(bool* ok = nullptr) override;
|
||||
|
||||
private:
|
||||
virtual bool needsRenderUpdate() const override;
|
||||
|
|
|
@ -1897,7 +1897,8 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS
|
|||
geometry.meshes.append(extracted.mesh);
|
||||
int meshIndex = geometry.meshes.size() - 1;
|
||||
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);
|
||||
}
|
||||
|
@ -1983,7 +1984,7 @@ FBXGeometry* readFBX(QIODevice* device, const QVariantHash& mapping, const QStri
|
|||
reader._loadLightmaps = loadLightmaps;
|
||||
reader._lightmapLevel = lightmapLevel;
|
||||
|
||||
qDebug() << "Reading FBX: " << url;
|
||||
qCDebug(modelformat) << "Reading FBX: " << url;
|
||||
|
||||
return reader.extractFBXGeometry(mapping, url);
|
||||
}
|
||||
|
|
|
@ -71,7 +71,8 @@ bool writeOBJToTextStream(QTextStream& out, QList<MeshPointer> meshes) {
|
|||
out << formatFloat(v[1]) << " ";
|
||||
out << formatFloat(v[2]);
|
||||
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[1]);
|
||||
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);
|
||||
gpu::BufferView::Index numNormals = (gpu::BufferView::Index)normalsBufferView.getNumElements();
|
||||
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);
|
||||
out << "vn ";
|
||||
out << formatFloat(normal[0]) << " ";
|
||||
|
@ -117,7 +118,7 @@ bool writeOBJToTextStream(QTextStream& out, QList<MeshPointer> meshes) {
|
|||
const gpu::BufferView& indexBuffer = mesh->getIndexBuffer();
|
||||
|
||||
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]"), "_");
|
||||
for (int partIndex = 0; partIndex < partCount; partIndex++) {
|
||||
const graphics::Mesh::Part& part = partBuffer.get<graphics::Mesh::Part>(partIndex);
|
||||
|
|
|
@ -19,7 +19,9 @@ namespace scriptable {
|
|||
// JS => QPointer<QObject>
|
||||
template <typename T> QPointer<T> qpointer_qobject_cast(const QScriptValue& value) {
|
||||
auto obj = value.toQObject();
|
||||
#ifdef SCRIPTABLE_MESH_DEBUG
|
||||
qCInfo(graphics_scripting) << "qpointer_qobject_cast" << obj << value.toString();
|
||||
#endif
|
||||
if (auto tmp = qobject_cast<T*>(obj)) {
|
||||
return QPointer<T>(tmp);
|
||||
}
|
||||
|
@ -41,11 +43,15 @@ namespace scriptable {
|
|||
// C++ > QtOwned instance
|
||||
template <typename T, class... Rest> std::shared_ptr<T> make_qtowned(Rest... rest) {
|
||||
T* tmp = new T(rest...);
|
||||
#ifdef SCRIPTABLE_MESH_DEBUG
|
||||
qCInfo(graphics_scripting) << "scriptable::make_qtowned" << toDebugString(tmp);
|
||||
#endif
|
||||
QString debug = toDebugString(tmp);
|
||||
if (tmp) {
|
||||
tmp->metadata["__ownership__"] = QScriptEngine::QtOwnership;
|
||||
#ifdef SCRIPTABLE_MESH_DEBUG
|
||||
QObject::connect(tmp, &QObject::destroyed, [=]() { qCInfo(graphics_scripting) << "-------- ~scriptable::make_qtowned" << debug; });
|
||||
#endif
|
||||
auto ptr = std::shared_ptr<T>(tmp, [debug](T* tmp) {
|
||||
//qDebug() << "~std::shared_ptr<T>" << debug;
|
||||
delete tmp;
|
||||
|
@ -58,7 +64,9 @@ namespace scriptable {
|
|||
// C++ > ScriptOwned JS instance
|
||||
template <typename T, class... Rest> QPointer<T> make_scriptowned(Rest... rest) {
|
||||
T* tmp = new T(rest...);
|
||||
#ifdef SCRIPTABLE_MESH_DEBUG
|
||||
qCInfo(graphics_scripting) << "scriptable::make_scriptowned" << toDebugString(tmp);
|
||||
#endif
|
||||
if (tmp) {
|
||||
tmp->metadata["__ownership__"] = QScriptEngine::ScriptOwnership;
|
||||
//auto blah = (DeleterFunction)[](void* delme) { };
|
||||
|
@ -71,12 +79,14 @@ namespace scriptable {
|
|||
template <typename T> QPointer<T> add_scriptowned_destructor(T* tmp) {
|
||||
QString debug = toDebugString(tmp);
|
||||
if (tmp) {
|
||||
#ifdef SCRIPTABLE_MESH_DEBUG
|
||||
QObject::connect(tmp, &QObject::destroyed, [=]() {
|
||||
qCInfo(graphics_scripting) << "-------- ~scriptable::make_scriptowned" << debug;// << !!customDeleter;
|
||||
//if (customDeleter) {
|
||||
// customDeleter(tmp);
|
||||
//}
|
||||
});
|
||||
#endif
|
||||
} else {
|
||||
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) {
|
||||
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;
|
||||
QString providerType = provider ? provider->metadata.value("providerType").toString() : QString();
|
||||
if (providerType.isEmpty()) {
|
||||
|
@ -56,12 +56,12 @@ bool ModelScriptingInterface::updateMeshes(QUuid uuid, const scriptable::Scripta
|
|||
}
|
||||
bool success = false;
|
||||
if (provider) {
|
||||
qCDebug(graphics_scripting) << "fetching meshes from " << providerType << "...";
|
||||
//qCDebug(graphics_scripting) << "fetching meshes from " << providerType << "...";
|
||||
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) {
|
||||
const scriptable::ScriptableModelBasePointer base = model->operator scriptable::ScriptableModelBasePointer();
|
||||
qCDebug(graphics_scripting) << "as base" << base;
|
||||
//qCDebug(graphics_scripting) << "as base" << base;
|
||||
if (base) {
|
||||
//auto meshes = model->getConstMeshes();
|
||||
success = provider->replaceScriptableModelMeshPart(base, -1, -1);
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
|
||||
#include "OBJWriter.h"
|
||||
|
||||
// #define SCRIPTABLE_MESH_DEBUG
|
||||
|
||||
namespace scriptable {
|
||||
// QScriptValue jsBindCallback(QScriptValue callback);
|
||||
// template <typename T> QPointer<T> qpointer_qobject_cast(const QScriptValue& value);
|
||||
|
@ -287,7 +289,9 @@ quint32 scriptable::ScriptableMesh::mapAttributeValues(QScriptValue _callback) {
|
|||
return 0;
|
||||
}
|
||||
auto meshPart = js ? js->toScriptValue(getSelf()) : QScriptValue::NullValue;
|
||||
#ifdef SCRIPTABLE_MESH_DEBUG
|
||||
qCInfo(graphics_scripting) << "mapAttributeValues" << mesh.get() << js->currentContext()->thisObject().toQObject();
|
||||
#endif
|
||||
auto obj = js->newObject();
|
||||
auto attributeViews = buffer_helpers::gatherBufferViews(mesh, { "normal", "color" });
|
||||
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) {
|
||||
auto meshProxy = this;
|
||||
auto mesh = getMeshPointer();
|
||||
#ifdef SCRIPTABLE_MESH_DEBUG
|
||||
qCInfo(graphics_scripting) << "ScriptableMeshPart::unrollVertices" << !!mesh<< !!meshProxy;
|
||||
#endif
|
||||
if (!mesh) {
|
||||
return false;
|
||||
}
|
||||
|
@ -527,28 +532,32 @@ scriptable::ScriptableMeshPointer scriptable::ScriptableMesh::cloneMesh(bool rec
|
|||
qCInfo(graphics_scripting) << "ScriptableMesh::cloneMesh -- !meshPointer";
|
||||
return nullptr;
|
||||
}
|
||||
qCInfo(graphics_scripting) << "ScriptableMesh::cloneMesh...";
|
||||
// qCInfo(graphics_scripting) << "ScriptableMesh::cloneMesh...";
|
||||
auto clone = buffer_helpers::cloneMesh(mesh);
|
||||
|
||||
qCInfo(graphics_scripting) << "ScriptableMesh::cloneMesh...";
|
||||
// qCInfo(graphics_scripting) << "ScriptableMesh::cloneMesh...";
|
||||
if (recalcNormals) {
|
||||
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);
|
||||
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();
|
||||
//*ppMesh = clone;
|
||||
|
||||
if (meshPointer) {
|
||||
if (0 && meshPointer) {
|
||||
scriptable::WeakMeshPointer delme = meshPointer->mesh;
|
||||
QString debugString = scriptable::toDebugString(meshPointer);
|
||||
QObject::connect(meshPointer, &QObject::destroyed, meshPointer, [=]() {
|
||||
qCWarning(graphics_scripting) << "*************** cloneMesh/Destroy";
|
||||
qCWarning(graphics_scripting) << "*************** " << debugString << delme.lock().get();
|
||||
// qCWarning(graphics_scripting) << "*************** cloneMesh/Destroy";
|
||||
// qCWarning(graphics_scripting) << "*************** " << debugString << delme.lock().get();
|
||||
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() {
|
||||
ownedMesh.reset();
|
||||
#ifdef SCRIPTABLE_MESH_DEBUG
|
||||
qCInfo(graphics_scripting) << "//~ScriptableMeshBase" << this << "ownedMesh:" << ownedMesh.use_count() << "mesh:" << mesh.use_count();
|
||||
#endif
|
||||
}
|
||||
|
||||
scriptable::ScriptableMesh::~ScriptableMesh() {
|
||||
ownedMesh.reset();
|
||||
#ifdef SCRIPTABLE_MESH_DEBUG
|
||||
qCInfo(graphics_scripting) << "//~ScriptableMesh" << this << "ownedMesh:" << ownedMesh.use_count() << "mesh:" << mesh.use_count();
|
||||
#endif
|
||||
}
|
||||
|
||||
QString scriptable::ScriptableMeshPart::toOBJ() {
|
||||
|
|
|
@ -100,7 +100,7 @@ namespace scriptable {
|
|||
ScriptableMeshPart(scriptable::ScriptableMeshPointer parentMesh, int partIndex);
|
||||
ScriptableMeshPart& operator=(const ScriptableMeshPart& view) { parentMesh=view.parentMesh; return *this; };
|
||||
ScriptableMeshPart(const ScriptableMeshPart& other) : parentMesh(other.parentMesh), partIndex(other.partIndex) {}
|
||||
~ScriptableMeshPart() { qDebug() << "~ScriptableMeshPart" << this; }
|
||||
// ~ScriptableMeshPart() { qDebug() << "~ScriptableMeshPart" << this; }
|
||||
|
||||
public slots:
|
||||
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 ScriptableModelBase& other) : ScriptableModelBase(other) {}
|
||||
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());
|
||||
// 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);
|
||||
|
||||
QString displayName;
|
||||
std::string modelName;
|
||||
std::string displayName;
|
||||
|
||||
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);
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -9,6 +9,10 @@
|
|||
// 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 <QMetaType>
|
||||
|
@ -26,7 +30,7 @@
|
|||
#include <GLMHelpers.h>
|
||||
#include <TBBHelpers.h>
|
||||
|
||||
#include <graphics-scripting/ScriptableModel.h>
|
||||
#include <graphics-scripting/Forward.h>
|
||||
#include <DualQuaternion.h>
|
||||
|
||||
#include <glm/gtc/packing.hpp>
|
||||
|
@ -75,7 +79,7 @@ void initCollisionMaterials() {
|
|||
graphics::MaterialPointer material;
|
||||
material = std::make_shared<graphics::Material>();
|
||||
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 blue = component[(index + bluePhase) % NUM_COLLISION_HULL_COLORS];
|
||||
material->setAlbedo(glm::vec3(red, green, blue));
|
||||
|
@ -573,35 +577,109 @@ bool Model::convexHullContains(glm::vec3 point) {
|
|||
return false;
|
||||
}
|
||||
|
||||
scriptable::ScriptableModel Model::getScriptableModel(bool* ok) {
|
||||
scriptable::ScriptableModel result;
|
||||
// FIXME: temporary workaround that updates the whole FBXGeometry (to keep findRayIntersection in sync)
|
||||
#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();
|
||||
|
||||
if (!isLoaded()) {
|
||||
qDebug() << "Model::getScriptableModel -- !isLoaded";
|
||||
qCDebug(wtf) << "Model::getScriptableModel -- !isLoaded";
|
||||
return scriptable::ModelProvider::modelUnavailableError(ok);
|
||||
}
|
||||
|
||||
const FBXGeometry& geometry = getFBXGeometry();
|
||||
auto mat4toVariant = [](const glm::mat4& mat4) -> QVariant {
|
||||
QVector<float> floats;
|
||||
floats.resize(16);
|
||||
memcpy(floats.data(), &mat4, sizeof(glm::mat4));
|
||||
QVariant v;
|
||||
v.setValue<QVector<float>>(floats);
|
||||
return v;
|
||||
};
|
||||
Transform offset;
|
||||
offset.setScale(_scale);
|
||||
offset.postTranslate(_offset);
|
||||
glm::mat4 offsetMat = offset.getMatrix();
|
||||
glm::mat4 meshToModelMatrix = glm::scale(_scale) * glm::translate(_offset);
|
||||
glm::mat4 meshToWorldMatrix = createMatFromQuatAndPos(_rotation, _translation) * meshToModelMatrix;
|
||||
result.metadata = {
|
||||
{ "url", _url.toString() },
|
||||
{ "textures", renderGeometry->getTextures() },
|
||||
{ "offset", vec3toVariant(_offset) },
|
||||
{ "scale", vec3toVariant(_scale) },
|
||||
{ "rotation", quatToVariant(_rotation) },
|
||||
{ "translation", vec3toVariant(_translation) },
|
||||
{ "meshToModel", mat4toVariant(glm::scale(_scale) * glm::translate(_offset)) },
|
||||
{ "meshToWorld", mat4toVariant(createMatFromQuatAndPos(_rotation, _translation) * (glm::scale(_scale) * glm::translate(_offset))) },
|
||||
{ "geometryOffset", mat4toVariant(geometry.offset) },
|
||||
{ "scale", vec3toVariant(getScale()) },
|
||||
{ "rotation", quatToVariant(getRotation()) },
|
||||
{ "translation", vec3toVariant(getTranslation()) },
|
||||
{ "meshToModel", buffer_helpers::toVariant(meshToModelMatrix) },
|
||||
{ "meshToWorld", buffer_helpers::toVariant(meshToWorldMatrix) },
|
||||
{ "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;
|
||||
int numberOfMeshes = geometry.meshes.size();
|
||||
for (int i = 0; i < numberOfMeshes; i++) {
|
||||
|
@ -610,53 +688,43 @@ scriptable::ScriptableModel Model::getScriptableModel(bool* ok) {
|
|||
if (!mesh) {
|
||||
continue;
|
||||
}
|
||||
result.meshes << std::const_pointer_cast<graphics::Mesh>(mesh);
|
||||
auto extraInfo = geometry.getModelNameOfMesh(i);
|
||||
qDebug() << "Model::getScriptableModel #" << i << QString(mesh->displayName) << extraInfo;
|
||||
submeshes << QVariantMap{
|
||||
auto name = geometry.getModelNameOfMesh(i);
|
||||
qCDebug(wtf) << "Model::getScriptableModel #" << i << QString::fromStdString(mesh->displayName) << name;
|
||||
const AABox& box = _modelSpaceMeshTriangleSets.value(i).getBounds();
|
||||
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 },
|
||||
{ "name", name },
|
||||
{ "renderIDs", renderIDs },
|
||||
{ "meshIndex", fbxMesh.meshIndex },
|
||||
{ "modelName", extraInfo },
|
||||
{ "transform", mat4toVariant(fbxMesh.modelTransform) },
|
||||
{ "extents", QVariantMap({
|
||||
{ "minimum", vec3toVariant(fbxMesh.meshExtents.minimum) },
|
||||
{ "maximum", vec3toVariant(fbxMesh.meshExtents.maximum) },
|
||||
})},
|
||||
};
|
||||
{ "displayName", QString::fromStdString(mesh->displayName) },
|
||||
{ "modelName", QString::fromStdString(mesh->modelName) },
|
||||
{ "modelTransform", buffer_helpers::toVariant(fbxMesh.modelTransform) },
|
||||
{ "transform", buffer_helpers::toVariant(geometry.offset * fbxMesh.modelTransform) },
|
||||
{ "extents", buffer_helpers::toVariant(fbxMesh.meshExtents) },
|
||||
{ "bounds", buffer_helpers::toVariant(Extents(box)) },
|
||||
{ "hardbounds", buffer_helpers::toVariant(Extents(hardbounds)) },
|
||||
});
|
||||
}
|
||||
if (ok) {
|
||||
*ok = true;
|
||||
}
|
||||
qDebug() << "//Model::getScriptableModel -- #" << result.meshes.size();
|
||||
qCDebug(wtf) << "//Model::getScriptableModel -- #" << result.meshes.size();
|
||||
result.metadata["submeshes"] = submeshes;
|
||||
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() {
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
#include <gpu/Batch.h>
|
||||
#include <render/Forward.h>
|
||||
#include <render/Scene.h>
|
||||
#include <graphics-scripting/ScriptableModel.h>
|
||||
#include <graphics-scripting/Forward.h>
|
||||
#include <Transform.h>
|
||||
#include <SpatiallyNestable.h>
|
||||
#include <TriangleSet.h>
|
||||
|
@ -314,7 +314,8 @@ public:
|
|||
int getResourceDownloadAttempts() { return _renderWatcher.getResourceDownloadAttempts(); }
|
||||
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();
|
||||
|
||||
|
|
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(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);
|
||||
}
|
||||
|
|
|
@ -132,6 +132,20 @@ QUrl expandScriptUrl(const QUrl& rawScriptURL) {
|
|||
|
||||
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) {
|
||||
_scriptInitializers.push_back(initializer);
|
||||
}
|
||||
|
@ -520,6 +534,17 @@ void ScriptEngines::onScriptEngineLoaded(const QString& rawScriptURL) {
|
|||
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) {
|
||||
connect(scriptEngine.data(), &ScriptEngine::finished, this, &ScriptEngines::onScriptFinished, Qt::DirectConnection);
|
||||
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);
|
||||
});
|
||||
|
||||
// register our application services and set it off on its own thread
|
||||
for (auto initializer : _scriptInitializers) {
|
||||
initializer(scriptEngine);
|
||||
}
|
||||
runScriptInitializers(scriptEngine);
|
||||
|
||||
// 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
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include <SettingHandle.h>
|
||||
#include <DependencyManager.h>
|
||||
#include <shared/ScriptInitializerMixin.h>
|
||||
|
||||
#include "ScriptEngine.h"
|
||||
#include "ScriptsModel.h"
|
||||
|
@ -26,6 +27,12 @@
|
|||
|
||||
class ScriptEngine;
|
||||
|
||||
class NativeScriptInitializers : public ScriptInitializerMixin {
|
||||
public:
|
||||
bool registerNativeScriptInitializer(NativeScriptInitializer initializer) override;
|
||||
bool registerScriptInitializer(ScriptInitializer initializer) override;
|
||||
};
|
||||
|
||||
class ScriptEngines : public QObject, public Dependency {
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -34,11 +41,11 @@ class ScriptEngines : public QObject, public Dependency {
|
|||
Q_PROPERTY(QString debugScriptUrl READ getDebugScriptUrl WRITE setDebugScriptUrl)
|
||||
|
||||
public:
|
||||
using ScriptInitializer = std::function<void(ScriptEnginePointer)>;
|
||||
using ScriptInitializer = ScriptInitializerMixin::ScriptInitializer;
|
||||
|
||||
ScriptEngines(ScriptEngine::Context context);
|
||||
void registerScriptInitializer(ScriptInitializer initializer);
|
||||
|
||||
int runScriptInitializers(ScriptEnginePointer engine);
|
||||
void loadScripts();
|
||||
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