From 541692c5cafc389c96d1f0b25a4d4b39d6e1011f Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Sat, 28 Jan 2017 15:38:18 -0800 Subject: [PATCH 01/12] start on scripting interface to allow saving polyvox meshes to obj files --- interface/src/Application.cpp | 1 + interface/src/Application.h | 2 + .../entities/src/EntityScriptingInterface.cpp | 4 ++ .../entities/src/EntityScriptingInterface.h | 2 + libraries/fbx/src/OBJWriter.cpp | 71 +++++++++++++++++++ libraries/fbx/src/OBJWriter.h | 6 ++ .../src/ModelScriptingInterface.cpp | 31 ++++++++ .../src/ModelScriptingInterface.h | 52 ++++++++++++++ libraries/script-engine/src/ScriptEngine.cpp | 7 +- 9 files changed, 175 insertions(+), 1 deletion(-) create mode 100644 libraries/fbx/src/OBJWriter.cpp create mode 100644 libraries/fbx/src/OBJWriter.h create mode 100644 libraries/script-engine/src/ModelScriptingInterface.cpp create mode 100644 libraries/script-engine/src/ModelScriptingInterface.h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c96a63ce1c..93a67fe639 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -175,6 +175,7 @@ #include #include #include +#include // On Windows PC, NVidia Optimus laptop, we want to enable NVIDIA GPU // FIXME seems to be broken. diff --git a/interface/src/Application.h b/interface/src/Application.h index 3b89aa52f3..cac11e3ed9 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -71,6 +71,8 @@ #include #include +#include + class OffscreenGLCanvas; class GLCanvas; diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 46bc46adab..c6a17a56bd 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -911,6 +911,10 @@ bool EntityScriptingInterface::setVoxelsInCuboid(QUuid entityID, const glm::vec3 }); } +MeshProxy* EntityScriptingInterface::voxelsToMesh(QUuid entityID) { + return nullptr; +} + bool EntityScriptingInterface::setAllPoints(QUuid entityID, const QVector& points) { EntityItemPointer entity = static_cast(_entityTree->findEntityByEntityItemID(entityID)); if (!entity) { diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index 0353fa08a8..c0260bd199 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -35,6 +35,7 @@ #include "EntityItemProperties.h" class EntityTree; +class MeshProxy; class RayToEntityIntersectionResult { public: @@ -227,6 +228,7 @@ public slots: Q_INVOKABLE bool setAllVoxels(QUuid entityID, int value); Q_INVOKABLE bool setVoxelsInCuboid(QUuid entityID, const glm::vec3& lowPosition, const glm::vec3& cuboidSize, int value); + Q_INVOKABLE MeshProxy* voxelsToMesh(QUuid entityID); Q_INVOKABLE bool setAllPoints(QUuid entityID, const QVector& points); Q_INVOKABLE bool appendPoint(QUuid entityID, const glm::vec3& point); diff --git a/libraries/fbx/src/OBJWriter.cpp b/libraries/fbx/src/OBJWriter.cpp new file mode 100644 index 0000000000..ab84e7b0fd --- /dev/null +++ b/libraries/fbx/src/OBJWriter.cpp @@ -0,0 +1,71 @@ +// +// FBXReader.h +// libraries/fbx/src/ +// +// Created by Seth Alves on 2017-1-27. +// Copyright 2017 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 "OBJWriter.h" + + +bool writeOBJ(QString outFileName, QVector) { +//bool writeOBJ(QString outFileName, FBXGeometry& geometry, bool outputCentimeters, int whichMeshPart) { + // QFile file(outFileName); + // if (!file.open(QIODevice::WriteOnly)) { + // qWarning() << "unable to write to" << outFileName; + // return false; + // } + + // QTextStream out(&file); + // if (outputCentimeters) { + // out << "# This file uses centimeters as units\n\n"; + // } + + // unsigned int nth = 0; + + // // vertex indexes in obj files span the entire file + // // vertex indexes in a mesh span just that mesh + + // int vertexIndexOffset = 0; + + // foreach (const FBXMesh& mesh, geometry.meshes) { + // bool verticesHaveBeenOutput = false; + // foreach (const FBXMeshPart &meshPart, mesh.parts) { + // if (whichMeshPart >= 0 && nth != (unsigned int) whichMeshPart) { + // nth++; + // continue; + // } + + // if (!verticesHaveBeenOutput) { + // for (int i = 0; i < mesh.vertices.size(); i++) { + // glm::vec4 v = mesh.modelTransform * glm::vec4(mesh.vertices[i], 1.0f); + // out << "v "; + // out << formatFloat(v[0]) << " "; + // out << formatFloat(v[1]) << " "; + // out << formatFloat(v[2]) << "\n"; + // } + // verticesHaveBeenOutput = true; + // } + + // out << "g hull-" << nth++ << "\n"; + // int triangleCount = meshPart.triangleIndices.size() / 3; + // for (int i = 0; i < triangleCount; i++) { + // out << "f "; + // out << vertexIndexOffset + meshPart.triangleIndices[i*3] + 1 << " "; + // out << vertexIndexOffset + meshPart.triangleIndices[i*3+1] + 1 << " "; + // out << vertexIndexOffset + meshPart.triangleIndices[i*3+2] + 1 << "\n"; + // } + // out << "\n"; + // } + + // if (verticesHaveBeenOutput) { + // vertexIndexOffset += mesh.vertices.size(); + // } + // } + + return true; +} diff --git a/libraries/fbx/src/OBJWriter.h b/libraries/fbx/src/OBJWriter.h new file mode 100644 index 0000000000..c0400b3d8e --- /dev/null +++ b/libraries/fbx/src/OBJWriter.h @@ -0,0 +1,6 @@ + +#include +#include +#include + +bool writeOBJ(QString outFileName, QVector); diff --git a/libraries/script-engine/src/ModelScriptingInterface.cpp b/libraries/script-engine/src/ModelScriptingInterface.cpp new file mode 100644 index 0000000000..fd550749f7 --- /dev/null +++ b/libraries/script-engine/src/ModelScriptingInterface.cpp @@ -0,0 +1,31 @@ +// +// ModelScriptingInterface.cpp +// libraries/script-engine/src +// +// Created by Seth Alves on 2017-1-27. +// Copyright 2017 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 "ModelScriptingInterface.h" + +ModelScriptingInterface::ModelScriptingInterface(QObject* parent) : QObject(parent) { +} + + +MeshProxy::MeshProxy(MeshPointer mesh) : _mesh(mesh) { +} + +MeshProxy::~MeshProxy() { +} + + +QScriptValue meshToScriptValue(QScriptEngine* engine, MeshProxy* const &in) { + QScriptValue obj("something"); + return obj; +} + +void meshFromScriptValue(const QScriptValue& value, MeshProxy* &out) { +} diff --git a/libraries/script-engine/src/ModelScriptingInterface.h b/libraries/script-engine/src/ModelScriptingInterface.h new file mode 100644 index 0000000000..3d3e6b94a2 --- /dev/null +++ b/libraries/script-engine/src/ModelScriptingInterface.h @@ -0,0 +1,52 @@ +// +// ModelScriptingInterface.h +// libraries/script-engine/src +// +// Created by Seth Alves on 2017-1-27. +// Copyright 2017 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 +// + + +#ifndef hifi_ModelScriptingInterface_h +#define hifi_ModelScriptingInterface_h + +#include +#include +#include +#include + +using MeshPointer = std::shared_ptr; + +class ModelScriptingInterface : public QObject { + Q_OBJECT + +public: + ModelScriptingInterface(QObject* parent); +}; + +class MeshProxy : public QObject { + Q_OBJECT + +public: + MeshProxy(MeshPointer mesh); + // MeshProxy(const MeshProxy& meshProxy) { _mesh = meshProxy.getMeshPointer(); } + ~MeshProxy(); + + MeshPointer getMeshPointer() const { return _mesh; } + +protected: + MeshPointer _mesh; +}; + + +Q_DECLARE_METATYPE(MeshProxy*); + + +QScriptValue meshToScriptValue(QScriptEngine* engine, MeshProxy* const &in); +// QScriptValue meshToScriptValue(QScriptEngine* engine, const MeshPointer& in); +void meshFromScriptValue(const QScriptValue& value, MeshProxy* &out); + +#endif // hifi_ModelScriptingInterface_h diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 2191d45d45..b687da7e23 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -63,6 +63,8 @@ #include "RecordingScriptingInterface.h" #include "ScriptEngines.h" #include "TabletScriptingInterface.h" +#include "ModelScriptingInterface.h" + #include "MIDIEvent.h" @@ -570,7 +572,7 @@ void ScriptEngine::init() { registerGlobalObject("Messages", DependencyManager::get().data()); registerGlobalObject("File", new FileScriptingInterface(this)); - + qScriptRegisterMetaType(this, animVarMapToScriptValue, animVarMapFromScriptValue); qScriptRegisterMetaType(this, resultHandlerToScriptValue, resultHandlerFromScriptValue); @@ -586,6 +588,9 @@ void ScriptEngine::init() { registerGlobalObject("Tablet", DependencyManager::get().data()); registerGlobalObject("Assets", &_assetScriptingInterface); registerGlobalObject("Resources", DependencyManager::get().data()); + + registerGlobalObject("Model", new ModelScriptingInterface(this)); + qScriptRegisterMetaType(this, meshToScriptValue, meshFromScriptValue); } void ScriptEngine::registerValue(const QString& valueName, QScriptValue value) { From d158f6afd16cf8641f577a14294e98498bd05cd0 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Sat, 28 Jan 2017 20:42:14 -0800 Subject: [PATCH 02/12] hook up a way to get mesh out of polyvox --- .../src/RenderablePolyVoxEntityItem.cpp | 27 ++++++++++---- .../src/RenderablePolyVoxEntityItem.h | 5 ++- .../entities/src/EntityScriptingInterface.cpp | 37 +++++++++++-------- .../entities/src/EntityScriptingInterface.h | 4 +- libraries/entities/src/PolyVoxEntityItem.cpp | 4 ++ libraries/entities/src/PolyVoxEntityItem.h | 4 +- .../src/ModelScriptingInterface.cpp | 7 +++- .../src/ModelScriptingInterface.h | 2 + 8 files changed, 60 insertions(+), 30 deletions(-) diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index 7646f0a454..0179814641 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -14,6 +14,7 @@ #include #include #include +#include "ModelScriptingInterface.h" #if defined(__GNUC__) && !defined(__clang__) #pragma GCC diagnostic push @@ -73,7 +74,7 @@ const float MARCHING_CUBE_COLLISION_HULL_OFFSET = 0.5; _meshDirty In RenderablePolyVoxEntityItem::render, these flags are checked and changes are propagated along the chain. - decompressVolumeData() is called to decompress _voxelData into _volData. getMesh() is called to invoke the + decompressVolumeData() is called to decompress _voxelData into _volData. recomputeMesh() is called to invoke the polyVox surface extractor to create _mesh (as well as set Simulation _dirtyFlags). Because Simulation::DIRTY_SHAPE is set, isReadyToComputeShape() gets called and _shape is created either from _volData or _shape, depending on the surface style. @@ -81,7 +82,7 @@ const float MARCHING_CUBE_COLLISION_HULL_OFFSET = 0.5; When a script changes _volData, compressVolumeDataAndSendEditPacket is called to update _voxelData and to send a packet to the entity-server. - decompressVolumeData, getMesh, computeShapeInfoWorker, and compressVolumeDataAndSendEditPacket are too expensive + decompressVolumeData, recomputeMesh, computeShapeInfoWorker, and compressVolumeDataAndSendEditPacket are too expensive to run on a thread that has other things to do. These use QtConcurrent::run to spawn a thread. As each thread finishes, it adjusts the dirty flags so that the next call to render() will kick off the next step. @@ -570,7 +571,7 @@ void RenderablePolyVoxEntityItem::render(RenderArgs* args) { if (voxelDataDirty) { decompressVolumeData(); } else if (volDataDirty) { - getMesh(); + recomputeMesh(); } model::MeshPointer mesh; @@ -1096,7 +1097,7 @@ void RenderablePolyVoxEntityItem::copyUpperEdgesFromNeighbors() { } } -void RenderablePolyVoxEntityItem::getMesh() { +void RenderablePolyVoxEntityItem::recomputeMesh() { // use _volData to make a renderable mesh PolyVoxSurfaceStyle voxelSurfaceStyle; withReadLock([&] { @@ -1171,7 +1172,7 @@ void RenderablePolyVoxEntityItem::getMesh() { } void RenderablePolyVoxEntityItem::setMesh(model::MeshPointer mesh) { - // this catches the payload from getMesh + // this catches the payload from recomputeMesh bool neighborsNeedUpdate; withWriteLock([&] { _dirtyFlags |= Simulation::DIRTY_SHAPE | Simulation::DIRTY_MASS; @@ -1426,7 +1427,6 @@ std::shared_ptr RenderablePolyVoxEntityItem::getZPN return std::dynamic_pointer_cast(_zPNeighbor.lock()); } - void RenderablePolyVoxEntityItem::bonkNeighbors() { // flag neighbors to the negative of this entity as needing to rebake their meshes. cacheNeighbors(); @@ -1446,7 +1446,6 @@ void RenderablePolyVoxEntityItem::bonkNeighbors() { } } - void RenderablePolyVoxEntityItem::locationChanged(bool tellPhysics) { EntityItem::locationChanged(tellPhysics); if (!_pipeline || !render::Item::isValidID(_myItem)) { @@ -1458,3 +1457,17 @@ void RenderablePolyVoxEntityItem::locationChanged(bool tellPhysics) { scene->enqueuePendingChanges(pendingChanges); } + +bool RenderablePolyVoxEntityItem::getMeshAsScriptValue(QScriptEngine *engine, QScriptValue& result) const { + bool success = false; + MeshProxy* meshProxy = nullptr; + model::MeshPointer mesh = nullptr; + withReadLock([&] { + if (_meshInitialized) { + success = true; + meshProxy = new MeshProxy(_mesh); + } + }); + result = meshToScriptValue(engine, meshProxy); + return success; +} diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h index ee4c3b318f..e86356deb3 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h @@ -130,6 +130,7 @@ public: std::function thunk); void setMesh(model::MeshPointer mesh); + bool getMeshAsScriptValue(QScriptEngine *engine, QScriptValue& result) const override; void setCollisionPoints(ShapeInfo::PointCollection points, AABox box); PolyVox::SimpleVolume* getVolData() { return _volData; } @@ -164,7 +165,7 @@ private: ShapeInfo _shapeInfo; PolyVox::SimpleVolume* _volData = nullptr; - bool _volDataDirty = false; // does getMesh need to be called? + bool _volDataDirty = false; // does recomputeMesh need to be called? int _onCount; // how many non-zero voxels are in _volData bool _neighborsNeedUpdate { false }; @@ -175,7 +176,7 @@ private: // these are run off the main thread void decompressVolumeData(); void compressVolumeDataAndSendEditPacket(); - virtual void getMesh() override; // recompute mesh + virtual void recomputeMesh() override; // recompute mesh void computeShapeInfoWorker(); // these are cached lookups of _xNNeighborID, _yNNeighborID, _zNNeighborID, _xPNeighborID, _yPNeighborID, _zPNeighborID diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index c6a17a56bd..b83816cc19 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -822,8 +822,7 @@ void RayToEntityIntersectionResultFromScriptValue(const QScriptValue& object, Ra } } -bool EntityScriptingInterface::setVoxels(QUuid entityID, - std::function actor) { +bool EntityScriptingInterface::polyVoxWorker(QUuid entityID, std::function actor) { if (!_entityTree) { return false; } @@ -887,32 +886,38 @@ bool EntityScriptingInterface::setPoints(QUuid entityID, std::function& points) { diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index c0260bd199..5822d93df2 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -228,7 +228,7 @@ public slots: Q_INVOKABLE bool setAllVoxels(QUuid entityID, int value); Q_INVOKABLE bool setVoxelsInCuboid(QUuid entityID, const glm::vec3& lowPosition, const glm::vec3& cuboidSize, int value); - Q_INVOKABLE MeshProxy* voxelsToMesh(QUuid entityID); + Q_INVOKABLE void voxelsToMesh(QUuid entityID, QScriptValue callback); Q_INVOKABLE bool setAllPoints(QUuid entityID, const QVector& points); Q_INVOKABLE bool appendPoint(QUuid entityID, const glm::vec3& point); @@ -321,7 +321,7 @@ signals: private: bool actionWorker(const QUuid& entityID, std::function actor); - bool setVoxels(QUuid entityID, std::function actor); + bool polyVoxWorker(QUuid entityID, std::function actor); bool setPoints(QUuid entityID, std::function actor); void queueEntityMessage(PacketType packetType, EntityItemID entityID, const EntityItemProperties& properties); diff --git a/libraries/entities/src/PolyVoxEntityItem.cpp b/libraries/entities/src/PolyVoxEntityItem.cpp index 2a374c1d17..a827a9903d 100644 --- a/libraries/entities/src/PolyVoxEntityItem.cpp +++ b/libraries/entities/src/PolyVoxEntityItem.cpp @@ -242,3 +242,7 @@ const QByteArray PolyVoxEntityItem::getVoxelData() const { }); return voxelDataCopy; } + +bool PolyVoxEntityItem::getMeshAsScriptValue(QScriptEngine *engine, QScriptValue& result) const { + return false; +} diff --git a/libraries/entities/src/PolyVoxEntityItem.h b/libraries/entities/src/PolyVoxEntityItem.h index 4f478c8bf7..bc8ace2827 100644 --- a/libraries/entities/src/PolyVoxEntityItem.h +++ b/libraries/entities/src/PolyVoxEntityItem.h @@ -129,7 +129,9 @@ class PolyVoxEntityItem : public EntityItem { virtual void rebakeMesh() {}; void setVoxelDataDirty(bool value) { withWriteLock([&] { _voxelDataDirty = value; }); } - virtual void getMesh() {}; // recompute mesh + virtual void recomputeMesh() {}; + + virtual bool getMeshAsScriptValue(QScriptEngine *engine, QScriptValue& result) const; protected: glm::vec3 _voxelVolumeSize; // this is always 3 bytes diff --git a/libraries/script-engine/src/ModelScriptingInterface.cpp b/libraries/script-engine/src/ModelScriptingInterface.cpp index fd550749f7..30ef9a713e 100644 --- a/libraries/script-engine/src/ModelScriptingInterface.cpp +++ b/libraries/script-engine/src/ModelScriptingInterface.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include +#include #include "ModelScriptingInterface.h" ModelScriptingInterface::ModelScriptingInterface(QObject* parent) : QObject(parent) { @@ -23,9 +25,10 @@ MeshProxy::~MeshProxy() { QScriptValue meshToScriptValue(QScriptEngine* engine, MeshProxy* const &in) { - QScriptValue obj("something"); - return obj; + return engine->newQObject(in, QScriptEngine::QtOwnership, + QScriptEngine::ExcludeDeleteLater | QScriptEngine::ExcludeChildObjects); } void meshFromScriptValue(const QScriptValue& value, MeshProxy* &out) { + out = qobject_cast(value.toQObject()); } diff --git a/libraries/script-engine/src/ModelScriptingInterface.h b/libraries/script-engine/src/ModelScriptingInterface.h index 3d3e6b94a2..4cc493b257 100644 --- a/libraries/script-engine/src/ModelScriptingInterface.h +++ b/libraries/script-engine/src/ModelScriptingInterface.h @@ -37,6 +37,8 @@ public: MeshPointer getMeshPointer() const { return _mesh; } + Q_INVOKABLE int getNumVertices() const { return _mesh->getNumVertices(); } + protected: MeshPointer _mesh; }; From bb3155ee6100fd9ba73c60667737fd8286e620f2 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 31 Jan 2017 14:29:42 -0800 Subject: [PATCH 03/12] obj file is now produced in /tmp --- .../src/RenderablePolyVoxEntityItem.cpp | 8 + libraries/fbx/src/OBJWriter.cpp | 157 ++++++++++++------ libraries/fbx/src/OBJWriter.h | 22 ++- libraries/script-engine/src/MeshProxy.h | 39 +++++ .../src/ModelScriptingInterface.cpp | 20 ++- .../src/ModelScriptingInterface.h | 25 +-- 6 files changed, 194 insertions(+), 77 deletions(-) create mode 100644 libraries/script-engine/src/MeshProxy.h diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index 0179814641..78a9e6a84a 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -1167,6 +1167,14 @@ void RenderablePolyVoxEntityItem::recomputeMesh() { vertexBufferPtr->getSize() , sizeof(PolyVox::PositionMaterialNormal), gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::RAW))); + + std::vector parts; + parts.emplace_back(model::Mesh::Part(0, // startIndex + vecIndices.size(), // numIndices + 0, // baseVertex + model::Mesh::TRIANGLES)); // topology + mesh->setPartBuffer(gpu::BufferView(new gpu::Buffer(parts.size() * sizeof(model::Mesh::Part), + (gpu::Byte*) parts.data()), gpu::Element::PART_DRAWCALL)); entity->setMesh(mesh); }); } diff --git a/libraries/fbx/src/OBJWriter.cpp b/libraries/fbx/src/OBJWriter.cpp index ab84e7b0fd..d33d767e5d 100644 --- a/libraries/fbx/src/OBJWriter.cpp +++ b/libraries/fbx/src/OBJWriter.cpp @@ -1,5 +1,5 @@ // -// FBXReader.h +// OBJWriter.cpp // libraries/fbx/src/ // // Created by Seth Alves on 2017-1-27. @@ -9,63 +9,126 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include +#include +#include "model/Geometry.h" #include "OBJWriter.h" -bool writeOBJ(QString outFileName, QVector) { -//bool writeOBJ(QString outFileName, FBXGeometry& geometry, bool outputCentimeters, int whichMeshPart) { - // QFile file(outFileName); - // if (!file.open(QIODevice::WriteOnly)) { - // qWarning() << "unable to write to" << outFileName; - // return false; - // } - // QTextStream out(&file); - // if (outputCentimeters) { - // out << "# This file uses centimeters as units\n\n"; - // } +static QString formatFloat(double n) { + // limit precision to 6, but don't output trailing zeros. + QString s = QString::number(n, 'f', 6); + while (s.endsWith("0")) { + s.remove(s.size() - 1, 1); + } + if (s.endsWith(".")) { + s.remove(s.size() - 1, 1); + } + return s; +} - // unsigned int nth = 0; - // // vertex indexes in obj files span the entire file - // // vertex indexes in a mesh span just that mesh - // int vertexIndexOffset = 0; +bool writeOBJToTextStream(QTextStream& out, std::vector meshes) { + qDebug() << "writeOBJToTextStream mesh count is" << meshes.size(); - // foreach (const FBXMesh& mesh, geometry.meshes) { - // bool verticesHaveBeenOutput = false; - // foreach (const FBXMeshPart &meshPart, mesh.parts) { - // if (whichMeshPart >= 0 && nth != (unsigned int) whichMeshPart) { - // nth++; - // continue; - // } + // each mesh's vertices are numbered from zero. We're combining all their vertices into one list here, + // so keep track of the start index for each mesh. + QList meshVertexStartOffset; + int currentVertexStartOffset = 0; - // if (!verticesHaveBeenOutput) { - // for (int i = 0; i < mesh.vertices.size(); i++) { - // glm::vec4 v = mesh.modelTransform * glm::vec4(mesh.vertices[i], 1.0f); - // out << "v "; - // out << formatFloat(v[0]) << " "; - // out << formatFloat(v[1]) << " "; - // out << formatFloat(v[2]) << "\n"; - // } - // verticesHaveBeenOutput = true; - // } + // write out all vertices + foreach (const MeshPointer& mesh, meshes) { + meshVertexStartOffset.append(currentVertexStartOffset); + const gpu::BufferView& vertexBuffer = mesh->getVertexBuffer(); + int vertexCount = 0; + gpu::BufferView::Iterator vertexItr = vertexBuffer.cbegin(); + while (vertexItr != vertexBuffer.cend()) { + glm::vec3 v = *vertexItr; + out << "v "; + out << formatFloat(v[0]) << " "; + out << formatFloat(v[1]) << " "; + out << formatFloat(v[2]) << "\n"; + vertexItr++; + vertexCount++; + } + currentVertexStartOffset += vertexCount; + } + out << "\n"; - // out << "g hull-" << nth++ << "\n"; - // int triangleCount = meshPart.triangleIndices.size() / 3; - // for (int i = 0; i < triangleCount; i++) { - // out << "f "; - // out << vertexIndexOffset + meshPart.triangleIndices[i*3] + 1 << " "; - // out << vertexIndexOffset + meshPart.triangleIndices[i*3+1] + 1 << " "; - // out << vertexIndexOffset + meshPart.triangleIndices[i*3+2] + 1 << "\n"; - // } - // out << "\n"; - // } + // write out faces + int nth = 0; + foreach (const MeshPointer& mesh, meshes) { + currentVertexStartOffset = meshVertexStartOffset.takeFirst(); - // if (verticesHaveBeenOutput) { - // vertexIndexOffset += mesh.vertices.size(); - // } - // } + const gpu::BufferView& partBuffer = mesh->getPartBuffer(); + const gpu::BufferView& indexBuffer = mesh->getIndexBuffer(); + // const gpu::BufferView& vertexBuffer = mesh->getVertexBuffer(); + + int partCount = mesh->getNumParts(); + qDebug() << "writeOBJToTextStream part count is" << partCount; + for (int partIndex = 0; partIndex < partCount; partIndex++) { + const model::Mesh::Part& part = partBuffer.get(partIndex); + + out << "g part-" << nth++ << "\n"; + + // model::Mesh::TRIANGLES + // XXX handle other formats + gpu::BufferView::Iterator indexItr = indexBuffer.cbegin(); + indexItr += part._startIndex; + + int indexCount = 0; + while (indexItr != indexBuffer.cend() && indexItr != part._numIndices) { + uint32_t index0 = *indexItr; + indexItr++; + indexCount++; + if (indexItr == indexBuffer.cend() || indexItr == part._numIndices) { + qDebug() << "OBJWriter -- index buffer length isn't multiple of 3"; + break; + } + uint32_t index1 = *indexItr; + indexItr++; + indexCount++; + if (indexItr == indexBuffer.cend() || indexItr == part._numIndices) { + qDebug() << "OBJWriter -- index buffer length isn't multiple of 3"; + break; + } + uint32_t index2 = *indexItr; + indexItr++; + indexCount++; + + out << "f "; + out << currentVertexStartOffset + index0 + 1 << " "; + out << currentVertexStartOffset + index1 + 1 << " "; + out << currentVertexStartOffset + index2 + 1 << "\n"; + } + out << "\n"; + } + } return true; } + + +bool writeOBJToFile(QString path, MeshPointer mesh) { + if (QFileInfo(path).exists() && !QFile::remove(path)) { + qDebug() << "OBJ writer failed, file exists:" << path; // XXX qCDebug + return false; + } + + QFile file(path); + if (!file.open(QIODevice::WriteOnly)) { + qDebug() << "OBJ writer failed to open output file:" << path; // XXX qCDebug + return false; + } + + QTextStream outStream(&file); + + bool success; + std::vector meshes { mesh }; + success = writeOBJToTextStream(outStream, meshes); + + file.close(); + return success; +} diff --git a/libraries/fbx/src/OBJWriter.h b/libraries/fbx/src/OBJWriter.h index c0400b3d8e..58dc93b84a 100644 --- a/libraries/fbx/src/OBJWriter.h +++ b/libraries/fbx/src/OBJWriter.h @@ -1,6 +1,26 @@ +// +// OBJWriter.h +// libraries/fbx/src/ +// +// Created by Seth Alves on 2017-1-27. +// Copyright 2017 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 +// + +#ifndef hifi_objwriter_h +#define hifi_objwriter_h + #include #include #include -bool writeOBJ(QString outFileName, QVector); +using MeshPointer = std::shared_ptr; + +bool writeOBJToTextStream(QTextStream& out, std::vector meshes); +bool writeOBJToFile(QString path, MeshPointer mesh); + + +#endif // hifi_objwriter_h diff --git a/libraries/script-engine/src/MeshProxy.h b/libraries/script-engine/src/MeshProxy.h new file mode 100644 index 0000000000..3226e0f467 --- /dev/null +++ b/libraries/script-engine/src/MeshProxy.h @@ -0,0 +1,39 @@ +// +// MeshProxy.h +// libraries/script-engine/src +// +// Created by Seth Alves on 2017-1-27. +// Copyright 2017 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 +// + +#ifndef hifi_MeshProxy_h +#define hifi_MeshProxy_h + +#include + +using MeshPointer = std::shared_ptr; + +class MeshProxy : public QObject { + Q_OBJECT + +public: + MeshProxy(MeshPointer mesh) : _mesh(mesh) {} + ~MeshProxy() {} + + MeshPointer getMeshPointer() const { return _mesh; } + + Q_INVOKABLE int getNumVertices() const { return _mesh->getNumVertices(); } + Q_INVOKABLE glm::vec3 getPos3(int index) const { return _mesh->getPos3(index); } + + +protected: + MeshPointer _mesh; +}; + + +Q_DECLARE_METATYPE(MeshProxy*); + +#endif // hifi_MeshProxy_h diff --git a/libraries/script-engine/src/ModelScriptingInterface.cpp b/libraries/script-engine/src/ModelScriptingInterface.cpp index 30ef9a713e..1fb8e8f193 100644 --- a/libraries/script-engine/src/ModelScriptingInterface.cpp +++ b/libraries/script-engine/src/ModelScriptingInterface.cpp @@ -12,18 +12,12 @@ #include #include #include "ModelScriptingInterface.h" +#include "OBJWriter.h" + ModelScriptingInterface::ModelScriptingInterface(QObject* parent) : QObject(parent) { } - -MeshProxy::MeshProxy(MeshPointer mesh) : _mesh(mesh) { -} - -MeshProxy::~MeshProxy() { -} - - QScriptValue meshToScriptValue(QScriptEngine* engine, MeshProxy* const &in) { return engine->newQObject(in, QScriptEngine::QtOwnership, QScriptEngine::ExcludeDeleteLater | QScriptEngine::ExcludeChildObjects); @@ -32,3 +26,13 @@ QScriptValue meshToScriptValue(QScriptEngine* engine, MeshProxy* const &in) { void meshFromScriptValue(const QScriptValue& value, MeshProxy* &out) { out = qobject_cast(value.toQObject()); } + +QString ModelScriptingInterface::meshToOBJ(MeshProxy* const &in) { + bool success; + QString filename = "/tmp/okokok.obj"; + success = writeOBJToFile(filename, in->getMeshPointer()); + if (!success) { + return ""; + } + return filename; +} diff --git a/libraries/script-engine/src/ModelScriptingInterface.h b/libraries/script-engine/src/ModelScriptingInterface.h index 4cc493b257..4d8f7ad999 100644 --- a/libraries/script-engine/src/ModelScriptingInterface.h +++ b/libraries/script-engine/src/ModelScriptingInterface.h @@ -17,6 +17,7 @@ #include #include #include +#include "MeshProxy.h" using MeshPointer = std::shared_ptr; @@ -25,30 +26,12 @@ class ModelScriptingInterface : public QObject { public: ModelScriptingInterface(QObject* parent); + + Q_INVOKABLE QString meshToOBJ(MeshProxy* const &in); }; -class MeshProxy : public QObject { - Q_OBJECT - -public: - MeshProxy(MeshPointer mesh); - // MeshProxy(const MeshProxy& meshProxy) { _mesh = meshProxy.getMeshPointer(); } - ~MeshProxy(); - - MeshPointer getMeshPointer() const { return _mesh; } - - Q_INVOKABLE int getNumVertices() const { return _mesh->getNumVertices(); } - -protected: - MeshPointer _mesh; -}; - - -Q_DECLARE_METATYPE(MeshProxy*); - - QScriptValue meshToScriptValue(QScriptEngine* engine, MeshProxy* const &in); -// QScriptValue meshToScriptValue(QScriptEngine* engine, const MeshPointer& in); void meshFromScriptValue(const QScriptValue& value, MeshProxy* &out); + #endif // hifi_ModelScriptingInterface_h From 91e542a7a7128b71e5300b0b331574774f7d66f0 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 31 Jan 2017 21:26:49 -0800 Subject: [PATCH 04/12] ModelScriptingInterface::meshToOBJ takes a list of MeshProxys instead of just one --- libraries/fbx/src/OBJWriter.cpp | 10 ++----- libraries/fbx/src/OBJWriter.h | 6 ++--- libraries/script-engine/src/MeshProxy.h | 4 ++- .../src/ModelScriptingInterface.cpp | 26 +++++++++++++++++-- .../src/ModelScriptingInterface.h | 4 ++- libraries/script-engine/src/ScriptEngine.cpp | 1 + 6 files changed, 36 insertions(+), 15 deletions(-) diff --git a/libraries/fbx/src/OBJWriter.cpp b/libraries/fbx/src/OBJWriter.cpp index d33d767e5d..b2d391fea3 100644 --- a/libraries/fbx/src/OBJWriter.cpp +++ b/libraries/fbx/src/OBJWriter.cpp @@ -14,8 +14,6 @@ #include "model/Geometry.h" #include "OBJWriter.h" - - static QString formatFloat(double n) { // limit precision to 6, but don't output trailing zeros. QString s = QString::number(n, 'f', 6); @@ -28,9 +26,7 @@ static QString formatFloat(double n) { return s; } - - -bool writeOBJToTextStream(QTextStream& out, std::vector meshes) { +bool writeOBJToTextStream(QTextStream& out, QList meshes) { qDebug() << "writeOBJToTextStream mesh count is" << meshes.size(); // each mesh's vertices are numbered from zero. We're combining all their vertices into one list here, @@ -110,8 +106,7 @@ bool writeOBJToTextStream(QTextStream& out, std::vector meshes) { return true; } - -bool writeOBJToFile(QString path, MeshPointer mesh) { +bool writeOBJToFile(QString path, QList meshes) { if (QFileInfo(path).exists() && !QFile::remove(path)) { qDebug() << "OBJ writer failed, file exists:" << path; // XXX qCDebug return false; @@ -126,7 +121,6 @@ bool writeOBJToFile(QString path, MeshPointer mesh) { QTextStream outStream(&file); bool success; - std::vector meshes { mesh }; success = writeOBJToTextStream(outStream, meshes); file.close(); diff --git a/libraries/fbx/src/OBJWriter.h b/libraries/fbx/src/OBJWriter.h index 58dc93b84a..dcf5a3ee39 100644 --- a/libraries/fbx/src/OBJWriter.h +++ b/libraries/fbx/src/OBJWriter.h @@ -14,13 +14,13 @@ #include -#include +#include #include using MeshPointer = std::shared_ptr; -bool writeOBJToTextStream(QTextStream& out, std::vector meshes); -bool writeOBJToFile(QString path, MeshPointer mesh); +bool writeOBJToTextStream(QTextStream& out, QList meshes); +bool writeOBJToFile(QString path, QList meshes); #endif // hifi_objwriter_h diff --git a/libraries/script-engine/src/MeshProxy.h b/libraries/script-engine/src/MeshProxy.h index 3226e0f467..93c5ce5918 100644 --- a/libraries/script-engine/src/MeshProxy.h +++ b/libraries/script-engine/src/MeshProxy.h @@ -33,7 +33,9 @@ protected: MeshPointer _mesh; }; - Q_DECLARE_METATYPE(MeshProxy*); +class MeshProxyList : public QList {}; // typedef and using fight with the Qt macros/templates, do this instead +Q_DECLARE_METATYPE(MeshProxyList); + #endif // hifi_MeshProxy_h diff --git a/libraries/script-engine/src/ModelScriptingInterface.cpp b/libraries/script-engine/src/ModelScriptingInterface.cpp index 1fb8e8f193..922dee2e8f 100644 --- a/libraries/script-engine/src/ModelScriptingInterface.cpp +++ b/libraries/script-engine/src/ModelScriptingInterface.cpp @@ -10,6 +10,7 @@ // #include +#include #include #include "ModelScriptingInterface.h" #include "OBJWriter.h" @@ -27,10 +28,31 @@ void meshFromScriptValue(const QScriptValue& value, MeshProxy* &out) { out = qobject_cast(value.toQObject()); } -QString ModelScriptingInterface::meshToOBJ(MeshProxy* const &in) { +QScriptValue meshesToScriptValue(QScriptEngine* engine, const MeshProxyList &in) { + return engine->toScriptValue(in); +} + +void meshesFromScriptValue(const QScriptValue& value, MeshProxyList &out) { + QScriptValueIterator itr(value); + while(itr.hasNext()) { + itr.next(); + MeshProxy* meshProxy = qscriptvalue_cast(itr.value()); + if (meshProxy) { + out.append(meshProxy); + } + } +} + +QString ModelScriptingInterface::meshToOBJ(MeshProxyList in) { bool success; QString filename = "/tmp/okokok.obj"; - success = writeOBJToFile(filename, in->getMeshPointer()); + + QList meshes; + foreach (const MeshProxy* meshProxy, in) { + meshes.append(meshProxy->getMeshPointer()); + } + + success = writeOBJToFile(filename, meshes); if (!success) { return ""; } diff --git a/libraries/script-engine/src/ModelScriptingInterface.h b/libraries/script-engine/src/ModelScriptingInterface.h index 4d8f7ad999..94b7338ae2 100644 --- a/libraries/script-engine/src/ModelScriptingInterface.h +++ b/libraries/script-engine/src/ModelScriptingInterface.h @@ -27,11 +27,13 @@ class ModelScriptingInterface : public QObject { public: ModelScriptingInterface(QObject* parent); - Q_INVOKABLE QString meshToOBJ(MeshProxy* const &in); + Q_INVOKABLE QString meshToOBJ(MeshProxyList in); }; QScriptValue meshToScriptValue(QScriptEngine* engine, MeshProxy* const &in); void meshFromScriptValue(const QScriptValue& value, MeshProxy* &out); +QScriptValue meshesToScriptValue(QScriptEngine* engine, const MeshProxyList &in); +void meshesFromScriptValue(const QScriptValue& value, MeshProxyList &out); #endif // hifi_ModelScriptingInterface_h diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index b687da7e23..31dc30d2c5 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -591,6 +591,7 @@ void ScriptEngine::init() { registerGlobalObject("Model", new ModelScriptingInterface(this)); qScriptRegisterMetaType(this, meshToScriptValue, meshFromScriptValue); + qScriptRegisterMetaType(this, meshesToScriptValue, meshesFromScriptValue); } void ScriptEngine::registerValue(const QString& valueName, QScriptValue value) { From 1eedce98251f726e87afe8130c18ebdc7227b3d8 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 13 Mar 2017 18:18:26 -0700 Subject: [PATCH 05/12] unmangle merge --- libraries/entities/src/EntityScriptingInterface.cpp | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 087518a393..ae34024bbc 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -881,7 +881,6 @@ bool EntityScriptingInterface::setPoints(QUuid entityID, std::function Date: Tue, 14 Mar 2017 07:11:38 -0700 Subject: [PATCH 06/12] writeOBJToString --- libraries/fbx/src/OBJWriter.cpp | 11 +++++++++++ libraries/fbx/src/OBJWriter.h | 2 +- .../script-engine/src/ModelScriptingInterface.cpp | 9 +-------- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/libraries/fbx/src/OBJWriter.cpp b/libraries/fbx/src/OBJWriter.cpp index b2d391fea3..c424290b9b 100644 --- a/libraries/fbx/src/OBJWriter.cpp +++ b/libraries/fbx/src/OBJWriter.cpp @@ -126,3 +126,14 @@ bool writeOBJToFile(QString path, QList meshes) { file.close(); return success; } + +QString writeOBJToString(QList meshes) { + QString result; + QTextStream outStream(&result, QIODevice::ReadWrite); + bool success; + success = writeOBJToTextStream(outStream, meshes); + if (success) { + return result; + } + return QString(""); +} diff --git a/libraries/fbx/src/OBJWriter.h b/libraries/fbx/src/OBJWriter.h index dcf5a3ee39..b6e20e1ae6 100644 --- a/libraries/fbx/src/OBJWriter.h +++ b/libraries/fbx/src/OBJWriter.h @@ -21,6 +21,6 @@ using MeshPointer = std::shared_ptr; bool writeOBJToTextStream(QTextStream& out, QList meshes); bool writeOBJToFile(QString path, QList meshes); - +QString writeOBJToString(QList meshes); #endif // hifi_objwriter_h diff --git a/libraries/script-engine/src/ModelScriptingInterface.cpp b/libraries/script-engine/src/ModelScriptingInterface.cpp index 922dee2e8f..4ba82edf7d 100644 --- a/libraries/script-engine/src/ModelScriptingInterface.cpp +++ b/libraries/script-engine/src/ModelScriptingInterface.cpp @@ -44,17 +44,10 @@ void meshesFromScriptValue(const QScriptValue& value, MeshProxyList &out) { } QString ModelScriptingInterface::meshToOBJ(MeshProxyList in) { - bool success; - QString filename = "/tmp/okokok.obj"; - QList meshes; foreach (const MeshProxy* meshProxy, in) { meshes.append(meshProxy->getMeshPointer()); } - success = writeOBJToFile(filename, meshes); - if (!success) { - return ""; - } - return filename; + return writeOBJToString(meshes); } From 5b28f3a3c427659c694146d870c5fe0406eabf11 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 14 Mar 2017 10:08:34 -0700 Subject: [PATCH 07/12] cleanups --- libraries/fbx/src/OBJWriter.cpp | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/libraries/fbx/src/OBJWriter.cpp b/libraries/fbx/src/OBJWriter.cpp index c424290b9b..4983dfef60 100644 --- a/libraries/fbx/src/OBJWriter.cpp +++ b/libraries/fbx/src/OBJWriter.cpp @@ -13,6 +13,7 @@ #include #include "model/Geometry.h" #include "OBJWriter.h" +#include "ModelFormatLogging.h" static QString formatFloat(double n) { // limit precision to 6, but don't output trailing zeros. @@ -23,6 +24,18 @@ static QString formatFloat(double n) { if (s.endsWith(".")) { s.remove(s.size() - 1, 1); } + + // check for non-numbers. if we get NaN or inf or scientific notation, just return 0 + for (int i = 0; i < s.length(); i++) { + auto c = s.at(i).toLatin1(); + if (c != '-' && + c != '.' && + (c < '0' || c > '9')) { + qCDebug(modelformat) << "OBJWriter zeroing bad vertex coordinate:" << s << "because of" << c; + return QString("0"); + } + } + return s; } @@ -70,7 +83,7 @@ bool writeOBJToTextStream(QTextStream& out, QList meshes) { out << "g part-" << nth++ << "\n"; // model::Mesh::TRIANGLES - // XXX handle other formats + // TODO -- handle other formats gpu::BufferView::Iterator indexItr = indexBuffer.cbegin(); indexItr += part._startIndex; @@ -108,13 +121,13 @@ bool writeOBJToTextStream(QTextStream& out, QList meshes) { bool writeOBJToFile(QString path, QList meshes) { if (QFileInfo(path).exists() && !QFile::remove(path)) { - qDebug() << "OBJ writer failed, file exists:" << path; // XXX qCDebug + qCDebug(modelformat) << "OBJ writer failed, file exists:" << path; return false; } QFile file(path); if (!file.open(QIODevice::WriteOnly)) { - qDebug() << "OBJ writer failed to open output file:" << path; // XXX qCDebug + qCDebug(modelformat) << "OBJ writer failed to open output file:" << path; return false; } From 40b87171a9c73675244e9d6e7ebc985d10ad0a7d Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 14 Mar 2017 17:49:39 -0700 Subject: [PATCH 08/12] quiet warnings --- .../entities-renderer/src/RenderablePolyVoxEntityItem.cpp | 6 +++--- libraries/fbx/src/FBXReader_Node.cpp | 3 ++- libraries/fbx/src/OBJWriter.cpp | 6 +++--- libraries/script-engine/src/MeshProxy.h | 2 +- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index d60c2081e2..88a0d25b7f 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -1272,9 +1272,9 @@ void RenderablePolyVoxEntityItem::recomputeMesh() { gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::RAW))); std::vector parts; - parts.emplace_back(model::Mesh::Part(0, // startIndex - vecIndices.size(), // numIndices - 0, // baseVertex + parts.emplace_back(model::Mesh::Part((model::Index)0, // startIndex + (model::Index)vecIndices.size(), // numIndices + (model::Index)0, // baseVertex model::Mesh::TRIANGLES)); // topology mesh->setPartBuffer(gpu::BufferView(new gpu::Buffer(parts.size() * sizeof(model::Mesh::Part), (gpu::Byte*) parts.data()), gpu::Element::PART_DRAWCALL)); diff --git a/libraries/fbx/src/FBXReader_Node.cpp b/libraries/fbx/src/FBXReader_Node.cpp index d814f58dab..d987f885eb 100644 --- a/libraries/fbx/src/FBXReader_Node.cpp +++ b/libraries/fbx/src/FBXReader_Node.cpp @@ -54,7 +54,8 @@ template QVariant readBinaryArray(QDataStream& in, int& position) { in.readRawData(compressed.data() + sizeof(quint32), compressedLength); position += compressedLength; arrayData = qUncompress(compressed); - if (arrayData.isEmpty() || arrayData.size() != (sizeof(T) * arrayLength)) { // answers empty byte array if corrupt + if (arrayData.isEmpty() || + (unsigned int)arrayData.size() != (sizeof(T) * arrayLength)) { // answers empty byte array if corrupt throw QString("corrupt fbx file"); } } else { diff --git a/libraries/fbx/src/OBJWriter.cpp b/libraries/fbx/src/OBJWriter.cpp index 4983dfef60..11f87d900a 100644 --- a/libraries/fbx/src/OBJWriter.cpp +++ b/libraries/fbx/src/OBJWriter.cpp @@ -75,7 +75,7 @@ bool writeOBJToTextStream(QTextStream& out, QList meshes) { const gpu::BufferView& indexBuffer = mesh->getIndexBuffer(); // const gpu::BufferView& vertexBuffer = mesh->getVertexBuffer(); - int partCount = mesh->getNumParts(); + size_t partCount = mesh->getNumParts(); qDebug() << "writeOBJToTextStream part count is" << partCount; for (int partIndex = 0; partIndex < partCount; partIndex++) { const model::Mesh::Part& part = partBuffer.get(partIndex); @@ -88,11 +88,11 @@ bool writeOBJToTextStream(QTextStream& out, QList meshes) { indexItr += part._startIndex; int indexCount = 0; - while (indexItr != indexBuffer.cend() && indexItr != part._numIndices) { + while (indexItr != indexBuffer.cend() && (indexItr != part._numIndices)) { uint32_t index0 = *indexItr; indexItr++; indexCount++; - if (indexItr == indexBuffer.cend() || indexItr == part._numIndices) { + if (indexItr == indexBuffer.cend() || (indexItr == part._numIndices)) { qDebug() << "OBJWriter -- index buffer length isn't multiple of 3"; break; } diff --git a/libraries/script-engine/src/MeshProxy.h b/libraries/script-engine/src/MeshProxy.h index 93c5ce5918..3504d11e8b 100644 --- a/libraries/script-engine/src/MeshProxy.h +++ b/libraries/script-engine/src/MeshProxy.h @@ -25,7 +25,7 @@ public: MeshPointer getMeshPointer() const { return _mesh; } - Q_INVOKABLE int getNumVertices() const { return _mesh->getNumVertices(); } + Q_INVOKABLE int getNumVertices() const { (int)return _mesh->getNumVertices(); } Q_INVOKABLE glm::vec3 getPos3(int index) const { return _mesh->getPos3(index); } From 08ad56d25427759a84b1fb235522da2ec1290599 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 14 Mar 2017 18:05:53 -0700 Subject: [PATCH 09/12] quiet warnings --- libraries/fbx/src/OBJWriter.cpp | 2 +- libraries/script-engine/src/MeshProxy.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/fbx/src/OBJWriter.cpp b/libraries/fbx/src/OBJWriter.cpp index 11f87d900a..dc6ad2e58b 100644 --- a/libraries/fbx/src/OBJWriter.cpp +++ b/libraries/fbx/src/OBJWriter.cpp @@ -75,7 +75,7 @@ bool writeOBJToTextStream(QTextStream& out, QList meshes) { const gpu::BufferView& indexBuffer = mesh->getIndexBuffer(); // const gpu::BufferView& vertexBuffer = mesh->getVertexBuffer(); - size_t partCount = mesh->getNumParts(); + model::Index partCount = mesh->getNumParts(); qDebug() << "writeOBJToTextStream part count is" << partCount; for (int partIndex = 0; partIndex < partCount; partIndex++) { const model::Mesh::Part& part = partBuffer.get(partIndex); diff --git a/libraries/script-engine/src/MeshProxy.h b/libraries/script-engine/src/MeshProxy.h index 3504d11e8b..82f5038348 100644 --- a/libraries/script-engine/src/MeshProxy.h +++ b/libraries/script-engine/src/MeshProxy.h @@ -25,7 +25,7 @@ public: MeshPointer getMeshPointer() const { return _mesh; } - Q_INVOKABLE int getNumVertices() const { (int)return _mesh->getNumVertices(); } + Q_INVOKABLE int getNumVertices() const { return (int)_mesh->getNumVertices(); } Q_INVOKABLE glm::vec3 getPos3(int index) const { return _mesh->getPos3(index); } From 0785172398baef65342fe0bca25247cdf27f8c25 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 14 Mar 2017 19:01:13 -0700 Subject: [PATCH 10/12] quiet warnings --- libraries/fbx/src/OBJWriter.cpp | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/libraries/fbx/src/OBJWriter.cpp b/libraries/fbx/src/OBJWriter.cpp index dc6ad2e58b..e0269be080 100644 --- a/libraries/fbx/src/OBJWriter.cpp +++ b/libraries/fbx/src/OBJWriter.cpp @@ -40,8 +40,6 @@ static QString formatFloat(double n) { } bool writeOBJToTextStream(QTextStream& out, QList meshes) { - qDebug() << "writeOBJToTextStream mesh count is" << meshes.size(); - // each mesh's vertices are numbered from zero. We're combining all their vertices into one list here, // so keep track of the start index for each mesh. QList meshVertexStartOffset; @@ -75,8 +73,7 @@ bool writeOBJToTextStream(QTextStream& out, QList meshes) { const gpu::BufferView& indexBuffer = mesh->getIndexBuffer(); // const gpu::BufferView& vertexBuffer = mesh->getVertexBuffer(); - model::Index partCount = mesh->getNumParts(); - qDebug() << "writeOBJToTextStream part count is" << partCount; + model::Index partCount = (model::Index)mesh->getNumParts(); for (int partIndex = 0; partIndex < partCount; partIndex++) { const model::Mesh::Part& part = partBuffer.get(partIndex); @@ -88,19 +85,30 @@ bool writeOBJToTextStream(QTextStream& out, QList meshes) { indexItr += part._startIndex; int indexCount = 0; - while (indexItr != indexBuffer.cend() && (indexItr != part._numIndices)) { + while (indexItr != indexBuffer.cend()) { + if (indexItr == part._numIndices) { + break; + } uint32_t index0 = *indexItr; indexItr++; indexCount++; - if (indexItr == indexBuffer.cend() || (indexItr == part._numIndices)) { - qDebug() << "OBJWriter -- index buffer length isn't multiple of 3"; + if (indexItr == indexBuffer.cend()) { + qCDebug(modelformat) << "OBJWriter -- index buffer length isn't multiple of 3"; + break; + } + if (indexItr == part._numIndices) { + qCDebug(modelformat) << "OBJWriter -- index buffer length isn't multiple of 3"; break; } uint32_t index1 = *indexItr; indexItr++; indexCount++; - if (indexItr == indexBuffer.cend() || indexItr == part._numIndices) { - qDebug() << "OBJWriter -- index buffer length isn't multiple of 3"; + if (indexItr == indexBuffer.cend()) { + qCDebug(modelformat) << "OBJWriter -- index buffer length isn't multiple of 3"; + break; + } + if (indexItr == part._numIndices) { + qCDebug(modelformat) << "OBJWriter -- index buffer length isn't multiple of 3"; break; } uint32_t index2 = *indexItr; From 7afe091c52c5ec02572347e159a25225a3f19553 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 14 Mar 2017 19:47:30 -0700 Subject: [PATCH 11/12] quiet warnings --- libraries/fbx/src/OBJWriter.cpp | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/libraries/fbx/src/OBJWriter.cpp b/libraries/fbx/src/OBJWriter.cpp index e0269be080..42b5774245 100644 --- a/libraries/fbx/src/OBJWriter.cpp +++ b/libraries/fbx/src/OBJWriter.cpp @@ -85,29 +85,18 @@ bool writeOBJToTextStream(QTextStream& out, QList meshes) { indexItr += part._startIndex; int indexCount = 0; - while (indexItr != indexBuffer.cend()) { - if (indexItr == part._numIndices) { - break; - } + while (indexItr != indexBuffer.cend() && indexCount < part._numIndices) { uint32_t index0 = *indexItr; indexItr++; indexCount++; - if (indexItr == indexBuffer.cend()) { - qCDebug(modelformat) << "OBJWriter -- index buffer length isn't multiple of 3"; - break; - } - if (indexItr == part._numIndices) { + if (indexItr == indexBuffer.cend() || indexCount >= part._numIndices) { qCDebug(modelformat) << "OBJWriter -- index buffer length isn't multiple of 3"; break; } uint32_t index1 = *indexItr; indexItr++; indexCount++; - if (indexItr == indexBuffer.cend()) { - qCDebug(modelformat) << "OBJWriter -- index buffer length isn't multiple of 3"; - break; - } - if (indexItr == part._numIndices) { + if (indexItr == indexBuffer.cend() || indexCount >= part._numIndices) { qCDebug(modelformat) << "OBJWriter -- index buffer length isn't multiple of 3"; break; } From 0e8d62c11e5cfa1421d8f28dd6137c6730ed4d31 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 16 Mar 2017 15:24:39 -0700 Subject: [PATCH 12/12] delete dead code --- libraries/fbx/src/OBJWriter.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/fbx/src/OBJWriter.cpp b/libraries/fbx/src/OBJWriter.cpp index 42b5774245..5ee04c5718 100644 --- a/libraries/fbx/src/OBJWriter.cpp +++ b/libraries/fbx/src/OBJWriter.cpp @@ -71,7 +71,6 @@ bool writeOBJToTextStream(QTextStream& out, QList meshes) { const gpu::BufferView& partBuffer = mesh->getPartBuffer(); const gpu::BufferView& indexBuffer = mesh->getIndexBuffer(); - // const gpu::BufferView& vertexBuffer = mesh->getVertexBuffer(); model::Index partCount = (model::Index)mesh->getNumParts(); for (int partIndex = 0; partIndex < partCount; partIndex++) {