From 200550aba98205629014d268c24fb4d749b243ce Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 16 Mar 2017 15:22:34 -0700 Subject: [PATCH 1/5] ModelScriptingInterface::appendMeshes --- .../src/RenderablePolyVoxEntityItem.cpp | 1 - libraries/gpu/src/gpu/Buffer.h | 2 +- .../src/ModelScriptingInterface.cpp | 89 ++++++++++++++++++- .../src/ModelScriptingInterface.h | 5 ++ 4 files changed, 94 insertions(+), 3 deletions(-) diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index 88a0d25b7f..dd62122633 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -1574,7 +1574,6 @@ void RenderablePolyVoxEntityItem::locationChanged(bool tellPhysics) { bool RenderablePolyVoxEntityItem::getMeshAsScriptValue(QScriptEngine *engine, QScriptValue& result) const { bool success = false; MeshProxy* meshProxy = nullptr; - model::MeshPointer mesh = nullptr; withReadLock([&] { if (_meshInitialized) { success = true; diff --git a/libraries/gpu/src/gpu/Buffer.h b/libraries/gpu/src/gpu/Buffer.h index 2507e8e0a6..290b84bef0 100644 --- a/libraries/gpu/src/gpu/Buffer.h +++ b/libraries/gpu/src/gpu/Buffer.h @@ -198,7 +198,7 @@ public: BufferView(const BufferPointer& buffer, Size offset, Size size, const Element& element = DEFAULT_ELEMENT); BufferView(const BufferPointer& buffer, Size offset, Size size, uint16 stride, const Element& element = DEFAULT_ELEMENT); - Size getNumElements() const { return _size / _element.getSize(); } + Size getNumElements() const { return (_size - _offset) / _stride; } //Template iterator with random access on the buffer sysmem template diff --git a/libraries/script-engine/src/ModelScriptingInterface.cpp b/libraries/script-engine/src/ModelScriptingInterface.cpp index 4ba82edf7d..b725548c96 100644 --- a/libraries/script-engine/src/ModelScriptingInterface.cpp +++ b/libraries/script-engine/src/ModelScriptingInterface.cpp @@ -12,11 +12,12 @@ #include #include #include +#include "ScriptEngine.h" #include "ModelScriptingInterface.h" #include "OBJWriter.h" - ModelScriptingInterface::ModelScriptingInterface(QObject* parent) : QObject(parent) { + _modelScriptEngine = qobject_cast(parent); } QScriptValue meshToScriptValue(QScriptEngine* engine, MeshProxy* const &in) { @@ -51,3 +52,89 @@ QString ModelScriptingInterface::meshToOBJ(MeshProxyList in) { return writeOBJToString(meshes); } + + +QScriptValue ModelScriptingInterface::appendMeshes(MeshProxyList in) { + model::MeshPointer result(new model::Mesh()); + int attributeTypeNormal = gpu::Stream::InputSlot::NORMAL; // libraries/gpu/src/gpu/Stream.h + + size_t totalVertexCount { 0 }; + size_t totalAttributeCount { 0 }; + size_t totalIndexCount { 0 }; + foreach (const MeshProxy* meshProxy, in) { + MeshPointer mesh = meshProxy->getMeshPointer(); + totalVertexCount += mesh->getNumVertices(); + totalAttributeCount += mesh->getNumAttributes(); + totalIndexCount += mesh->getNumIndices(); + } + + gpu::Resource::Size combinedVertexSize = totalVertexCount * sizeof(glm::vec3); + unsigned char* combinedVertexData = new unsigned char[combinedVertexSize]; + unsigned char* combinedVertexDataCursor = combinedVertexData; + + gpu::Resource::Size combinedNormalSize = totalVertexCount * sizeof(glm::vec3); + unsigned char* combinedNormalData = new unsigned char[combinedNormalSize]; + unsigned char* combinedNormalDataCursor = combinedNormalData; + + gpu::Resource::Size combinedIndexSize = totalVertexCount * sizeof(uint32_t); + unsigned char* combinedIndexData = new unsigned char[combinedIndexSize]; + unsigned char* combinedIndexDataCursor = combinedIndexData; + + uint32_t indexStartOffset { 0 }; + + foreach (const MeshProxy* meshProxy, in) { + MeshPointer mesh = meshProxy->getMeshPointer(); + + // vertex data + const gpu::BufferView& vertexBufferView = mesh->getVertexBuffer(); + gpu::BufferView::Index numVertices = (gpu::BufferView::Index)mesh->getNumVertices(); + for (gpu::BufferView::Index i = 0; i < numVertices; i ++) { + glm::vec3 pos = vertexBufferView.get(i); + memcpy(combinedVertexDataCursor, &pos, sizeof(pos)); + combinedVertexDataCursor += sizeof(pos); + } + + // normal data + const gpu::BufferView& normalsBufferView = mesh->getAttributeBuffer(attributeTypeNormal); + gpu::BufferView::Index numNormals = (gpu::BufferView::Index)mesh->getNumAttributes(); + for (gpu::BufferView::Index i = 0; i < numNormals; i ++) { + glm::vec3 normal = normalsBufferView.get(i); + memcpy(combinedNormalDataCursor, &normal, sizeof(normal)); + combinedNormalDataCursor += sizeof(normal); + } + // TODO -- other attributes + + // face data + const gpu::BufferView& indexBufferView = mesh->getIndexBuffer(); + gpu::BufferView::Index numIndexes = (gpu::BufferView::Index)mesh->getNumAttributes(); + for (gpu::BufferView::Index i = 0; i < numIndexes; i ++) { + uint32_t index = indexBufferView.get(i); + index += indexStartOffset; + memcpy(combinedIndexDataCursor, &index, sizeof(index)); + combinedIndexDataCursor += sizeof(index); + } + + indexStartOffset += numVertices; + } + + gpu::Element vertexElement = gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ); + gpu::Buffer* combinedVertexBuffer = new gpu::Buffer(combinedVertexSize, combinedVertexData); + gpu::BufferPointer combinedVertexBufferPointer(combinedVertexBuffer); + gpu::BufferView combinedVertexBufferView(combinedVertexBufferPointer, vertexElement); + result->setVertexBuffer(combinedVertexBufferView); + + gpu::Element normalElement = gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ); + gpu::Buffer* combinedNormalsBuffer = new gpu::Buffer(combinedNormalSize, combinedNormalData); + gpu::BufferPointer combinedNormalsBufferPointer(combinedNormalsBuffer); + gpu::BufferView combinedNormalsBufferView(combinedNormalsBufferPointer, normalElement); + result->addAttribute(attributeTypeNormal, combinedNormalsBufferView); + + gpu::Element indexElement = gpu::Element(gpu::SCALAR, gpu::UINT32, gpu::RAW); + gpu::Buffer* combinedIndexesBuffer = new gpu::Buffer(combinedIndexSize, combinedIndexData); + gpu::BufferPointer combinedIndexesBufferPointer(combinedIndexesBuffer); + gpu::BufferView combinedIndexesBufferView(combinedIndexesBufferPointer, indexElement); + result->setIndexBuffer(combinedIndexesBufferView); + + MeshProxy* resultProxy = new MeshProxy(result); + return meshToScriptValue(_modelScriptEngine, resultProxy); +} diff --git a/libraries/script-engine/src/ModelScriptingInterface.h b/libraries/script-engine/src/ModelScriptingInterface.h index 94b7338ae2..7ec8ab46ef 100644 --- a/libraries/script-engine/src/ModelScriptingInterface.h +++ b/libraries/script-engine/src/ModelScriptingInterface.h @@ -20,6 +20,7 @@ #include "MeshProxy.h" using MeshPointer = std::shared_ptr; +class ScriptEngine; class ModelScriptingInterface : public QObject { Q_OBJECT @@ -28,6 +29,10 @@ public: ModelScriptingInterface(QObject* parent); Q_INVOKABLE QString meshToOBJ(MeshProxyList in); + Q_INVOKABLE QScriptValue appendMeshes(MeshProxyList in); + +private: + ScriptEngine* _modelScriptEngine { nullptr }; }; QScriptValue meshToScriptValue(QScriptEngine* engine, MeshProxy* const &in); From bbad6a0eb7cb1c6ee32f2ea77dbed6dc7564bc71 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 16 Mar 2017 17:26:07 -0700 Subject: [PATCH 2/5] mesh-append works, mesh-transform doesn't? --- .../entities/src/EntityScriptingInterface.cpp | 13 +++ .../entities/src/EntityScriptingInterface.h | 1 + .../src/ModelScriptingInterface.cpp | 104 +++++++++++++++++- .../src/ModelScriptingInterface.h | 1 + 4 files changed, 114 insertions(+), 5 deletions(-) diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index ae34024bbc..7eae5b2dc4 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -1550,3 +1550,16 @@ bool EntityScriptingInterface::AABoxIntersectsCapsule(const glm::vec3& low, cons AABox aaBox(low, dimensions); return aaBox.findCapsulePenetration(start, end, radius, penetration); } + +glm::mat4 EntityScriptingInterface::getEntityTransform(const QUuid& entityID) { + glm::mat4 result; + if (_entityTree) { + _entityTree->withReadLock([&] { + EntityItemPointer entity = _entityTree->findEntityByEntityItemID(EntityItemID(entityID)); + if (entity) { + result = entity->getEntityToWorldMatrix(); + } + }); + } + return result; +} diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index b0c137ef77..be34317cd5 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -294,6 +294,7 @@ public slots: Q_INVOKABLE bool AABoxIntersectsCapsule(const glm::vec3& low, const glm::vec3& dimensions, const glm::vec3& start, const glm::vec3& end, float radius); + Q_INVOKABLE glm::mat4 getEntityTransform(const QUuid& entityID); signals: void collisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const Collision& collision); diff --git a/libraries/script-engine/src/ModelScriptingInterface.cpp b/libraries/script-engine/src/ModelScriptingInterface.cpp index b725548c96..86a651b6b2 100644 --- a/libraries/script-engine/src/ModelScriptingInterface.cpp +++ b/libraries/script-engine/src/ModelScriptingInterface.cpp @@ -55,7 +55,6 @@ QString ModelScriptingInterface::meshToOBJ(MeshProxyList in) { QScriptValue ModelScriptingInterface::appendMeshes(MeshProxyList in) { - model::MeshPointer result(new model::Mesh()); int attributeTypeNormal = gpu::Stream::InputSlot::NORMAL; // libraries/gpu/src/gpu/Stream.h size_t totalVertexCount { 0 }; @@ -72,11 +71,11 @@ QScriptValue ModelScriptingInterface::appendMeshes(MeshProxyList in) { unsigned char* combinedVertexData = new unsigned char[combinedVertexSize]; unsigned char* combinedVertexDataCursor = combinedVertexData; - gpu::Resource::Size combinedNormalSize = totalVertexCount * sizeof(glm::vec3); + gpu::Resource::Size combinedNormalSize = totalAttributeCount * sizeof(glm::vec3); unsigned char* combinedNormalData = new unsigned char[combinedNormalSize]; unsigned char* combinedNormalDataCursor = combinedNormalData; - gpu::Resource::Size combinedIndexSize = totalVertexCount * sizeof(uint32_t); + gpu::Resource::Size combinedIndexSize = totalIndexCount * sizeof(uint32_t); unsigned char* combinedIndexData = new unsigned char[combinedIndexSize]; unsigned char* combinedIndexDataCursor = combinedIndexData; @@ -96,7 +95,7 @@ QScriptValue ModelScriptingInterface::appendMeshes(MeshProxyList in) { // normal data const gpu::BufferView& normalsBufferView = mesh->getAttributeBuffer(attributeTypeNormal); - gpu::BufferView::Index numNormals = (gpu::BufferView::Index)mesh->getNumAttributes(); + gpu::BufferView::Index numNormals = (gpu::BufferView::Index)mesh->getNumAttributes(); for (gpu::BufferView::Index i = 0; i < numNormals; i ++) { glm::vec3 normal = normalsBufferView.get(i); memcpy(combinedNormalDataCursor, &normal, sizeof(normal)); @@ -106,7 +105,7 @@ QScriptValue ModelScriptingInterface::appendMeshes(MeshProxyList in) { // face data const gpu::BufferView& indexBufferView = mesh->getIndexBuffer(); - gpu::BufferView::Index numIndexes = (gpu::BufferView::Index)mesh->getNumAttributes(); + gpu::BufferView::Index numIndexes = (gpu::BufferView::Index)mesh->getNumIndices(); for (gpu::BufferView::Index i = 0; i < numIndexes; i ++) { uint32_t index = indexBufferView.get(i); index += indexStartOffset; @@ -117,6 +116,8 @@ QScriptValue ModelScriptingInterface::appendMeshes(MeshProxyList in) { indexStartOffset += numVertices; } + model::MeshPointer result(new model::Mesh()); + gpu::Element vertexElement = gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ); gpu::Buffer* combinedVertexBuffer = new gpu::Buffer(combinedVertexSize, combinedVertexData); gpu::BufferPointer combinedVertexBufferPointer(combinedVertexBuffer); @@ -135,6 +136,99 @@ QScriptValue ModelScriptingInterface::appendMeshes(MeshProxyList in) { gpu::BufferView combinedIndexesBufferView(combinedIndexesBufferPointer, indexElement); result->setIndexBuffer(combinedIndexesBufferView); + + std::vector parts; + parts.emplace_back(model::Mesh::Part((model::Index)0, // startIndex + (model::Index)result->getNumIndices(), // numIndices + (model::Index)0, // baseVertex + model::Mesh::TRIANGLES)); // topology + result->setPartBuffer(gpu::BufferView(new gpu::Buffer(parts.size() * sizeof(model::Mesh::Part), + (gpu::Byte*) parts.data()), gpu::Element::PART_DRAWCALL)); + + + MeshProxy* resultProxy = new MeshProxy(result); + return meshToScriptValue(_modelScriptEngine, resultProxy); +} + + +QScriptValue ModelScriptingInterface::transformMesh(glm::mat4 transform, MeshProxy* meshProxy) { + int attributeTypeNormal = gpu::Stream::InputSlot::NORMAL; // libraries/gpu/src/gpu/Stream.h + + MeshPointer mesh = meshProxy->getMeshPointer(); + + gpu::Resource::Size vertexSize = mesh->getNumVertices() * sizeof(glm::vec3); + unsigned char* resultVertexData = new unsigned char[vertexSize]; + unsigned char* vertexDataCursor = resultVertexData; + + gpu::Resource::Size normalSize = mesh->getNumAttributes() * sizeof(glm::vec3); + unsigned char* resultNormalData = new unsigned char[normalSize]; + unsigned char* normalDataCursor = resultNormalData; + + gpu::Resource::Size indexSize = mesh->getNumIndices() * sizeof(uint32_t); + unsigned char* resultIndexData = new unsigned char[indexSize]; + unsigned char* indexDataCursor = resultIndexData; + + // vertex data + const gpu::BufferView& vertexBufferView = mesh->getVertexBuffer(); + gpu::BufferView::Index numVertices = (gpu::BufferView::Index)mesh->getNumVertices(); + for (gpu::BufferView::Index i = 0; i < numVertices; i ++) { + glm::vec3 pos = vertexBufferView.get(i); + pos = glm::vec3(transform * glm::vec4(pos, 0.0f)); + memcpy(vertexDataCursor, &pos, sizeof(pos)); + vertexDataCursor += sizeof(pos); + } + + // normal data + const gpu::BufferView& normalsBufferView = mesh->getAttributeBuffer(attributeTypeNormal); + gpu::BufferView::Index numNormals = (gpu::BufferView::Index)mesh->getNumAttributes(); + for (gpu::BufferView::Index i = 0; i < numNormals; i ++) { + glm::vec3 normal = normalsBufferView.get(i); + normal = glm::vec3(transform * glm::vec4(normal, 0.0f)); + memcpy(normalDataCursor, &normal, sizeof(normal)); + normalDataCursor += sizeof(normal); + } + // TODO -- other attributes + + // face data + const gpu::BufferView& indexBufferView = mesh->getIndexBuffer(); + gpu::BufferView::Index numIndexes = (gpu::BufferView::Index)mesh->getNumIndices(); + for (gpu::BufferView::Index i = 0; i < numIndexes; i ++) { + uint32_t index = indexBufferView.get(i); + memcpy(indexDataCursor, &index, sizeof(index)); + indexDataCursor += sizeof(index); + } + + model::MeshPointer result(new model::Mesh()); + + gpu::Element vertexElement = gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ); + gpu::Buffer* resultVertexBuffer = new gpu::Buffer(vertexSize, resultVertexData); + gpu::BufferPointer resultVertexBufferPointer(resultVertexBuffer); + gpu::BufferView resultVertexBufferView(resultVertexBufferPointer, vertexElement); + result->setVertexBuffer(resultVertexBufferView); + + gpu::Element normalElement = gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ); + gpu::Buffer* resultNormalsBuffer = new gpu::Buffer(normalSize, resultNormalData); + gpu::BufferPointer resultNormalsBufferPointer(resultNormalsBuffer); + gpu::BufferView resultNormalsBufferView(resultNormalsBufferPointer, normalElement); + result->addAttribute(attributeTypeNormal, resultNormalsBufferView); + + gpu::Element indexElement = gpu::Element(gpu::SCALAR, gpu::UINT32, gpu::RAW); + gpu::Buffer* resultIndexesBuffer = new gpu::Buffer(indexSize, resultIndexData); + gpu::BufferPointer resultIndexesBufferPointer(resultIndexesBuffer); + gpu::BufferView resultIndexesBufferView(resultIndexesBufferPointer, indexElement); + result->setIndexBuffer(resultIndexesBufferView); + + + std::vector parts; + parts.emplace_back(model::Mesh::Part((model::Index)0, // startIndex + (model::Index)result->getNumIndices(), // numIndices + (model::Index)0, // baseVertex + model::Mesh::TRIANGLES)); // topology + result->setPartBuffer(gpu::BufferView(new gpu::Buffer(parts.size() * sizeof(model::Mesh::Part), + (gpu::Byte*) parts.data()), gpu::Element::PART_DRAWCALL)); + + + MeshProxy* resultProxy = new MeshProxy(result); return meshToScriptValue(_modelScriptEngine, resultProxy); } diff --git a/libraries/script-engine/src/ModelScriptingInterface.h b/libraries/script-engine/src/ModelScriptingInterface.h index 7ec8ab46ef..14789943e3 100644 --- a/libraries/script-engine/src/ModelScriptingInterface.h +++ b/libraries/script-engine/src/ModelScriptingInterface.h @@ -30,6 +30,7 @@ public: Q_INVOKABLE QString meshToOBJ(MeshProxyList in); Q_INVOKABLE QScriptValue appendMeshes(MeshProxyList in); + Q_INVOKABLE QScriptValue transformMesh(glm::mat4 transform, MeshProxy* meshProxy); private: ScriptEngine* _modelScriptEngine { nullptr }; From b3603ce8b3331b1e3ad3c37270c74c61ca833713 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 17 Mar 2017 16:52:56 -0700 Subject: [PATCH 3/5] Entities.voxelsToMesh, Model.transformMesh, Model.appendMeshes, Model.meshToOBJ appear to work now --- .../src/RenderablePolyVoxEntityItem.cpp | 29 ++- .../src/RenderablePolyVoxEntityItem.h | 3 +- .../entities/src/EntityScriptingInterface.cpp | 23 ++- .../entities/src/EntityScriptingInterface.h | 8 + libraries/entities/src/PolyVoxEntityItem.cpp | 2 +- libraries/entities/src/PolyVoxEntityItem.h | 2 +- libraries/model/src/model/Geometry.cpp | 84 ++++++++- libraries/model/src/model/Geometry.h | 10 +- .../src/ModelScriptingInterface.cpp | 169 ++++++++++-------- 9 files changed, 238 insertions(+), 92 deletions(-) diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index dd62122633..6f9310a36e 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -664,11 +664,8 @@ void RenderablePolyVoxEntityItem::setZTextureURL(QString zTextureURL) { } } -void RenderablePolyVoxEntityItem::render(RenderArgs* args) { - PerformanceTimer perfTimer("RenderablePolyVoxEntityItem::render"); - assert(getType() == EntityTypes::PolyVox); - Q_ASSERT(args->_batch); +bool RenderablePolyVoxEntityItem::updateDependents() { bool voxelDataDirty; bool volDataDirty; withWriteLock([&] { @@ -686,6 +683,17 @@ void RenderablePolyVoxEntityItem::render(RenderArgs* args) { recomputeMesh(); } + return !volDataDirty; +} + + +void RenderablePolyVoxEntityItem::render(RenderArgs* args) { + PerformanceTimer perfTimer("RenderablePolyVoxEntityItem::render"); + assert(getType() == EntityTypes::PolyVox); + Q_ASSERT(args->_batch); + + updateDependents(); + model::MeshPointer mesh; glm::vec3 voxelVolumeSize; withReadLock([&] { @@ -1571,13 +1579,22 @@ void RenderablePolyVoxEntityItem::locationChanged(bool tellPhysics) { scene->enqueuePendingChanges(pendingChanges); } -bool RenderablePolyVoxEntityItem::getMeshAsScriptValue(QScriptEngine *engine, QScriptValue& result) const { +bool RenderablePolyVoxEntityItem::getMeshAsScriptValue(QScriptEngine *engine, QScriptValue& result) { + if (!updateDependents()) { + return false; + } + bool success = false; MeshProxy* meshProxy = nullptr; + glm::mat4 transform = voxelToLocalMatrix(); withReadLock([&] { if (_meshInitialized) { success = true; - meshProxy = new MeshProxy(_mesh); + // the mesh will be in voxel-space. transform it into object-space + meshProxy = new MeshProxy( + _mesh->map([=](glm::vec3 position){ return glm::vec3(transform * glm::vec4(position, 1.0f)); }, + [=](glm::vec3 normal){ return glm::vec3(transform * glm::vec4(normal, 0.0f)); }, + [](uint32_t index){ return index; })); } }); result = meshToScriptValue(engine, meshProxy); diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h index 7fe45f8d99..5eaf93e3ae 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h @@ -133,7 +133,7 @@ public: QByteArray volDataToArray(quint16 voxelXSize, quint16 voxelYSize, quint16 voxelZSize) const; void setMesh(model::MeshPointer mesh); - bool getMeshAsScriptValue(QScriptEngine *engine, QScriptValue& result) const override; + bool getMeshAsScriptValue(QScriptEngine *engine, QScriptValue& result) override; void setCollisionPoints(ShapeInfo::PointCollection points, AABox box); PolyVox::SimpleVolume* getVolData() { return _volData; } @@ -192,6 +192,7 @@ private: void cacheNeighbors(); void copyUpperEdgesFromNeighbors(); void bonkNeighbors(); + bool updateDependents(); }; bool inUserBounds(const PolyVox::SimpleVolume* vol, PolyVoxEntityItem::PolyVoxSurfaceStyle surfaceStyle, diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 7eae5b2dc4..37e9e940b1 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -8,6 +8,10 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // + +#include +#include + #include "EntityScriptingInterface.h" #include "EntityItemID.h" @@ -926,13 +930,16 @@ bool EntityScriptingInterface::setVoxelsInCuboid(QUuid entityID, const glm::vec3 void EntityScriptingInterface::voxelsToMesh(QUuid entityID, QScriptValue callback) { PROFILE_RANGE(script_entities, __FUNCTION__); - polyVoxWorker(entityID, [callback](PolyVoxEntityItem& polyVoxEntity) mutable { - QScriptValue mesh; - polyVoxEntity.getMeshAsScriptValue(callback.engine(), mesh); - QScriptValueList args { mesh }; - callback.call(QScriptValue(), args); + bool success; + QScriptValue mesh; + + polyVoxWorker(entityID, [&](PolyVoxEntityItem& polyVoxEntity) mutable { + success = polyVoxEntity.getMeshAsScriptValue(callback.engine(), mesh); return true; }); + + QScriptValueList args { mesh, success }; + callback.call(QScriptValue(), args); } bool EntityScriptingInterface::setAllPoints(QUuid entityID, const QVector& points) { @@ -1557,7 +1564,11 @@ glm::mat4 EntityScriptingInterface::getEntityTransform(const QUuid& entityID) { _entityTree->withReadLock([&] { EntityItemPointer entity = _entityTree->findEntityByEntityItemID(EntityItemID(entityID)); if (entity) { - result = entity->getEntityToWorldMatrix(); + glm::mat4 translation = glm::translate(entity->getPosition()); + glm::mat4 rotation = glm::mat4_cast(entity->getRotation()); + glm::mat4 registration = glm::translate(ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - + entity->getRegistrationPoint()); + result = translation * rotation * registration; } }); } diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index be34317cd5..fa727aaa7a 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -294,6 +294,14 @@ public slots: Q_INVOKABLE bool AABoxIntersectsCapsule(const glm::vec3& low, const glm::vec3& dimensions, const glm::vec3& start, const glm::vec3& end, float radius); + + /**jsdoc + * Returns object to world transform, excluding scale + * + * @function Entities.getEntityTransform + * @param {EntityID} entityID The ID of the entity whose transform is to be returned + * @return {Mat4} Entity's object to world transform, excluding scale + */ Q_INVOKABLE glm::mat4 getEntityTransform(const QUuid& entityID); signals: diff --git a/libraries/entities/src/PolyVoxEntityItem.cpp b/libraries/entities/src/PolyVoxEntityItem.cpp index a827a9903d..90344d6c4b 100644 --- a/libraries/entities/src/PolyVoxEntityItem.cpp +++ b/libraries/entities/src/PolyVoxEntityItem.cpp @@ -243,6 +243,6 @@ const QByteArray PolyVoxEntityItem::getVoxelData() const { return voxelDataCopy; } -bool PolyVoxEntityItem::getMeshAsScriptValue(QScriptEngine *engine, QScriptValue& result) const { +bool PolyVoxEntityItem::getMeshAsScriptValue(QScriptEngine *engine, QScriptValue& result) { return false; } diff --git a/libraries/entities/src/PolyVoxEntityItem.h b/libraries/entities/src/PolyVoxEntityItem.h index ae722b2add..943d273452 100644 --- a/libraries/entities/src/PolyVoxEntityItem.h +++ b/libraries/entities/src/PolyVoxEntityItem.h @@ -133,7 +133,7 @@ class PolyVoxEntityItem : public EntityItem { void setVoxelDataDirty(bool value) { withWriteLock([&] { _voxelDataDirty = value; }); } virtual void recomputeMesh() {}; - virtual bool getMeshAsScriptValue(QScriptEngine *engine, QScriptValue& result) const; + virtual bool getMeshAsScriptValue(QScriptEngine *engine, QScriptValue& result); protected: glm::vec3 _voxelVolumeSize; // this is always 3 bytes diff --git a/libraries/model/src/model/Geometry.cpp b/libraries/model/src/model/Geometry.cpp index 2bb6cfa436..4e5134a7d7 100755 --- a/libraries/model/src/model/Geometry.cpp +++ b/libraries/model/src/model/Geometry.cpp @@ -117,7 +117,7 @@ Box Mesh::evalPartsBound(int partStart, int partEnd) const { auto partItEnd = _partBuffer.cbegin() + partEnd; for (;part != partItEnd; part++) { - + Box partBound; auto index = _indexBuffer.cbegin() + (*part)._startIndex; auto endIndex = index + (*part)._numIndices; @@ -134,6 +134,87 @@ Box Mesh::evalPartsBound(int partStart, int partEnd) const { return totalBound; } + +model::MeshPointer Mesh::map(std::function vertexFunc, + std::function normalFunc, + std::function indexFunc) { + int attributeTypeNormal = gpu::Stream::InputSlot::NORMAL; // libraries/gpu/src/gpu/Stream.h + + gpu::Resource::Size vertexSize = getNumVertices() * sizeof(glm::vec3); + unsigned char* resultVertexData = new unsigned char[vertexSize]; + unsigned char* vertexDataCursor = resultVertexData; + + gpu::Resource::Size normalSize = getNumAttributes() * sizeof(glm::vec3); + unsigned char* resultNormalData = new unsigned char[normalSize]; + unsigned char* normalDataCursor = resultNormalData; + + gpu::Resource::Size indexSize = getNumIndices() * sizeof(uint32_t); + unsigned char* resultIndexData = new unsigned char[indexSize]; + unsigned char* indexDataCursor = resultIndexData; + + // vertex data + const gpu::BufferView& vertexBufferView = getVertexBuffer(); + gpu::BufferView::Index numVertices = (gpu::BufferView::Index)getNumVertices(); + for (gpu::BufferView::Index i = 0; i < numVertices; i ++) { + glm::vec3 pos = vertexFunc(vertexBufferView.get(i)); + memcpy(vertexDataCursor, &pos, sizeof(pos)); + vertexDataCursor += sizeof(pos); + } + + // normal data + const gpu::BufferView& normalsBufferView = getAttributeBuffer(attributeTypeNormal); + gpu::BufferView::Index numNormals = (gpu::BufferView::Index)getNumAttributes(); + for (gpu::BufferView::Index i = 0; i < numNormals; i ++) { + glm::vec3 normal = normalFunc(normalsBufferView.get(i)); + memcpy(normalDataCursor, &normal, sizeof(normal)); + normalDataCursor += sizeof(normal); + } + // TODO -- other attributes + + // face data + const gpu::BufferView& indexBufferView = getIndexBuffer(); + gpu::BufferView::Index numIndexes = (gpu::BufferView::Index)getNumIndices(); + for (gpu::BufferView::Index i = 0; i < numIndexes; i ++) { + uint32_t index = indexFunc(indexBufferView.get(i)); + memcpy(indexDataCursor, &index, sizeof(index)); + indexDataCursor += sizeof(index); + } + + model::MeshPointer result(new model::Mesh()); + + gpu::Element vertexElement = gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ); + gpu::Buffer* resultVertexBuffer = new gpu::Buffer(vertexSize, resultVertexData); + gpu::BufferPointer resultVertexBufferPointer(resultVertexBuffer); + gpu::BufferView resultVertexBufferView(resultVertexBufferPointer, vertexElement); + result->setVertexBuffer(resultVertexBufferView); + + gpu::Element normalElement = gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ); + gpu::Buffer* resultNormalsBuffer = new gpu::Buffer(normalSize, resultNormalData); + gpu::BufferPointer resultNormalsBufferPointer(resultNormalsBuffer); + gpu::BufferView resultNormalsBufferView(resultNormalsBufferPointer, normalElement); + result->addAttribute(attributeTypeNormal, resultNormalsBufferView); + + gpu::Element indexElement = gpu::Element(gpu::SCALAR, gpu::UINT32, gpu::RAW); + gpu::Buffer* resultIndexesBuffer = new gpu::Buffer(indexSize, resultIndexData); + gpu::BufferPointer resultIndexesBufferPointer(resultIndexesBuffer); + gpu::BufferView resultIndexesBufferView(resultIndexesBufferPointer, indexElement); + result->setIndexBuffer(resultIndexesBufferView); + + + // TODO -- shouldn't assume just one part + + std::vector parts; + parts.emplace_back(model::Mesh::Part((model::Index)0, // startIndex + (model::Index)result->getNumIndices(), // numIndices + (model::Index)0, // baseVertex + model::Mesh::TRIANGLES)); // topology + result->setPartBuffer(gpu::BufferView(new gpu::Buffer(parts.size() * sizeof(model::Mesh::Part), + (gpu::Byte*) parts.data()), gpu::Element::PART_DRAWCALL)); + + return result; +} + + Geometry::Geometry() { } @@ -148,4 +229,3 @@ Geometry::~Geometry() { void Geometry::setMesh(const MeshPointer& mesh) { _mesh = mesh; } - diff --git a/libraries/model/src/model/Geometry.h b/libraries/model/src/model/Geometry.h index 4256f0be03..9a20861ea7 100755 --- a/libraries/model/src/model/Geometry.h +++ b/libraries/model/src/model/Geometry.h @@ -25,6 +25,10 @@ typedef AABox Box; typedef std::vector< Box > Boxes; typedef glm::vec3 Vec3; +class Mesh; +using MeshPointer = std::shared_ptr< Mesh >; + + class Mesh { public: const static Index PRIMITIVE_RESTART_INDEX = -1; @@ -114,6 +118,11 @@ public: static gpu::Primitive topologyToPrimitive(Topology topo) { return static_cast(topo); } + // create a copy of this mesh after passing its vertices, normals, and indexes though the provided functions + MeshPointer map(std::function vertexFunc, + std::function normalFunc, + std::function indexFunc); + protected: gpu::Stream::FormatPointer _vertexFormat; @@ -130,7 +139,6 @@ protected: void evalVertexStream(); }; -using MeshPointer = std::shared_ptr< Mesh >; class Geometry { diff --git a/libraries/script-engine/src/ModelScriptingInterface.cpp b/libraries/script-engine/src/ModelScriptingInterface.cpp index 86a651b6b2..71b82a2d60 100644 --- a/libraries/script-engine/src/ModelScriptingInterface.cpp +++ b/libraries/script-engine/src/ModelScriptingInterface.cpp @@ -151,84 +151,105 @@ QScriptValue ModelScriptingInterface::appendMeshes(MeshProxyList in) { } +// QScriptValue ModelScriptingInterface::transformMesh(glm::mat4 transform, MeshProxy* meshProxy) { +// int attributeTypeNormal = gpu::Stream::InputSlot::NORMAL; // libraries/gpu/src/gpu/Stream.h + +// if (!meshProxy) { +// return QScriptValue(false); +// } + +// MeshPointer mesh = meshProxy->getMeshPointer(); + +// gpu::Resource::Size vertexSize = mesh->getNumVertices() * sizeof(glm::vec3); +// unsigned char* resultVertexData = new unsigned char[vertexSize]; +// unsigned char* vertexDataCursor = resultVertexData; + +// gpu::Resource::Size normalSize = mesh->getNumAttributes() * sizeof(glm::vec3); +// unsigned char* resultNormalData = new unsigned char[normalSize]; +// unsigned char* normalDataCursor = resultNormalData; + +// gpu::Resource::Size indexSize = mesh->getNumIndices() * sizeof(uint32_t); +// unsigned char* resultIndexData = new unsigned char[indexSize]; +// unsigned char* indexDataCursor = resultIndexData; + +// // vertex data +// const gpu::BufferView& vertexBufferView = mesh->getVertexBuffer(); +// gpu::BufferView::Index numVertices = (gpu::BufferView::Index)mesh->getNumVertices(); +// for (gpu::BufferView::Index i = 0; i < numVertices; i ++) { +// glm::vec3 pos = vertexBufferView.get(i); +// pos = glm::vec3(transform * glm::vec4(pos, 1.0f)); +// memcpy(vertexDataCursor, &pos, sizeof(pos)); +// vertexDataCursor += sizeof(pos); +// } + +// // normal data +// const gpu::BufferView& normalsBufferView = mesh->getAttributeBuffer(attributeTypeNormal); +// gpu::BufferView::Index numNormals = (gpu::BufferView::Index)mesh->getNumAttributes(); +// for (gpu::BufferView::Index i = 0; i < numNormals; i ++) { +// glm::vec3 normal = normalsBufferView.get(i); +// normal = glm::vec3(transform * glm::vec4(normal, 0.0f)); +// memcpy(normalDataCursor, &normal, sizeof(normal)); +// normalDataCursor += sizeof(normal); +// } +// // TODO -- other attributes + +// // face data +// const gpu::BufferView& indexBufferView = mesh->getIndexBuffer(); +// gpu::BufferView::Index numIndexes = (gpu::BufferView::Index)mesh->getNumIndices(); +// for (gpu::BufferView::Index i = 0; i < numIndexes; i ++) { +// uint32_t index = indexBufferView.get(i); +// memcpy(indexDataCursor, &index, sizeof(index)); +// indexDataCursor += sizeof(index); +// } + +// model::MeshPointer result(new model::Mesh()); + +// gpu::Element vertexElement = gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ); +// gpu::Buffer* resultVertexBuffer = new gpu::Buffer(vertexSize, resultVertexData); +// gpu::BufferPointer resultVertexBufferPointer(resultVertexBuffer); +// gpu::BufferView resultVertexBufferView(resultVertexBufferPointer, vertexElement); +// result->setVertexBuffer(resultVertexBufferView); + +// gpu::Element normalElement = gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ); +// gpu::Buffer* resultNormalsBuffer = new gpu::Buffer(normalSize, resultNormalData); +// gpu::BufferPointer resultNormalsBufferPointer(resultNormalsBuffer); +// gpu::BufferView resultNormalsBufferView(resultNormalsBufferPointer, normalElement); +// result->addAttribute(attributeTypeNormal, resultNormalsBufferView); + +// gpu::Element indexElement = gpu::Element(gpu::SCALAR, gpu::UINT32, gpu::RAW); +// gpu::Buffer* resultIndexesBuffer = new gpu::Buffer(indexSize, resultIndexData); +// gpu::BufferPointer resultIndexesBufferPointer(resultIndexesBuffer); +// gpu::BufferView resultIndexesBufferView(resultIndexesBufferPointer, indexElement); +// result->setIndexBuffer(resultIndexesBufferView); + + +// std::vector parts; +// parts.emplace_back(model::Mesh::Part((model::Index)0, // startIndex +// (model::Index)result->getNumIndices(), // numIndices +// (model::Index)0, // baseVertex +// model::Mesh::TRIANGLES)); // topology +// result->setPartBuffer(gpu::BufferView(new gpu::Buffer(parts.size() * sizeof(model::Mesh::Part), +// (gpu::Byte*) parts.data()), gpu::Element::PART_DRAWCALL)); + + + +// MeshProxy* resultProxy = new MeshProxy(result); +// return meshToScriptValue(_modelScriptEngine, resultProxy); +// } + + QScriptValue ModelScriptingInterface::transformMesh(glm::mat4 transform, MeshProxy* meshProxy) { - int attributeTypeNormal = gpu::Stream::InputSlot::NORMAL; // libraries/gpu/src/gpu/Stream.h - + if (!meshProxy) { + return QScriptValue(false); + } MeshPointer mesh = meshProxy->getMeshPointer(); - - gpu::Resource::Size vertexSize = mesh->getNumVertices() * sizeof(glm::vec3); - unsigned char* resultVertexData = new unsigned char[vertexSize]; - unsigned char* vertexDataCursor = resultVertexData; - - gpu::Resource::Size normalSize = mesh->getNumAttributes() * sizeof(glm::vec3); - unsigned char* resultNormalData = new unsigned char[normalSize]; - unsigned char* normalDataCursor = resultNormalData; - - gpu::Resource::Size indexSize = mesh->getNumIndices() * sizeof(uint32_t); - unsigned char* resultIndexData = new unsigned char[indexSize]; - unsigned char* indexDataCursor = resultIndexData; - - // vertex data - const gpu::BufferView& vertexBufferView = mesh->getVertexBuffer(); - gpu::BufferView::Index numVertices = (gpu::BufferView::Index)mesh->getNumVertices(); - for (gpu::BufferView::Index i = 0; i < numVertices; i ++) { - glm::vec3 pos = vertexBufferView.get(i); - pos = glm::vec3(transform * glm::vec4(pos, 0.0f)); - memcpy(vertexDataCursor, &pos, sizeof(pos)); - vertexDataCursor += sizeof(pos); + if (!mesh) { + return QScriptValue(false); } - // normal data - const gpu::BufferView& normalsBufferView = mesh->getAttributeBuffer(attributeTypeNormal); - gpu::BufferView::Index numNormals = (gpu::BufferView::Index)mesh->getNumAttributes(); - for (gpu::BufferView::Index i = 0; i < numNormals; i ++) { - glm::vec3 normal = normalsBufferView.get(i); - normal = glm::vec3(transform * glm::vec4(normal, 0.0f)); - memcpy(normalDataCursor, &normal, sizeof(normal)); - normalDataCursor += sizeof(normal); - } - // TODO -- other attributes - - // face data - const gpu::BufferView& indexBufferView = mesh->getIndexBuffer(); - gpu::BufferView::Index numIndexes = (gpu::BufferView::Index)mesh->getNumIndices(); - for (gpu::BufferView::Index i = 0; i < numIndexes; i ++) { - uint32_t index = indexBufferView.get(i); - memcpy(indexDataCursor, &index, sizeof(index)); - indexDataCursor += sizeof(index); - } - - model::MeshPointer result(new model::Mesh()); - - gpu::Element vertexElement = gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ); - gpu::Buffer* resultVertexBuffer = new gpu::Buffer(vertexSize, resultVertexData); - gpu::BufferPointer resultVertexBufferPointer(resultVertexBuffer); - gpu::BufferView resultVertexBufferView(resultVertexBufferPointer, vertexElement); - result->setVertexBuffer(resultVertexBufferView); - - gpu::Element normalElement = gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ); - gpu::Buffer* resultNormalsBuffer = new gpu::Buffer(normalSize, resultNormalData); - gpu::BufferPointer resultNormalsBufferPointer(resultNormalsBuffer); - gpu::BufferView resultNormalsBufferView(resultNormalsBufferPointer, normalElement); - result->addAttribute(attributeTypeNormal, resultNormalsBufferView); - - gpu::Element indexElement = gpu::Element(gpu::SCALAR, gpu::UINT32, gpu::RAW); - gpu::Buffer* resultIndexesBuffer = new gpu::Buffer(indexSize, resultIndexData); - gpu::BufferPointer resultIndexesBufferPointer(resultIndexesBuffer); - gpu::BufferView resultIndexesBufferView(resultIndexesBufferPointer, indexElement); - result->setIndexBuffer(resultIndexesBufferView); - - - std::vector parts; - parts.emplace_back(model::Mesh::Part((model::Index)0, // startIndex - (model::Index)result->getNumIndices(), // numIndices - (model::Index)0, // baseVertex - model::Mesh::TRIANGLES)); // topology - result->setPartBuffer(gpu::BufferView(new gpu::Buffer(parts.size() * sizeof(model::Mesh::Part), - (gpu::Byte*) parts.data()), gpu::Element::PART_DRAWCALL)); - - - + model::MeshPointer result = mesh->map([&](glm::vec3 position){ return glm::vec3(transform * glm::vec4(position, 1.0f)); }, + [&](glm::vec3 normal){ return glm::vec3(transform * glm::vec4(normal, 0.0f)); }, + [&](uint32_t index){ return index; }); MeshProxy* resultProxy = new MeshProxy(result); return meshToScriptValue(_modelScriptEngine, resultProxy); } From 488ed081ddcd9b14e7e5b75470df3aaeba65e4cc Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Sat, 18 Mar 2017 10:18:04 -0700 Subject: [PATCH 4/5] Mesh::forEach and Mesh::map --- libraries/model/src/model/Geometry.cpp | 47 ++++-- libraries/model/src/model/Geometry.h | 4 + .../src/ModelScriptingInterface.cpp | 135 +++--------------- 3 files changed, 59 insertions(+), 127 deletions(-) diff --git a/libraries/model/src/model/Geometry.cpp b/libraries/model/src/model/Geometry.cpp index 4e5134a7d7..d511ae6cb9 100755 --- a/libraries/model/src/model/Geometry.cpp +++ b/libraries/model/src/model/Geometry.cpp @@ -140,19 +140,11 @@ model::MeshPointer Mesh::map(std::function vertexFunc, std::function indexFunc) { int attributeTypeNormal = gpu::Stream::InputSlot::NORMAL; // libraries/gpu/src/gpu/Stream.h + // vertex data gpu::Resource::Size vertexSize = getNumVertices() * sizeof(glm::vec3); unsigned char* resultVertexData = new unsigned char[vertexSize]; unsigned char* vertexDataCursor = resultVertexData; - gpu::Resource::Size normalSize = getNumAttributes() * sizeof(glm::vec3); - unsigned char* resultNormalData = new unsigned char[normalSize]; - unsigned char* normalDataCursor = resultNormalData; - - gpu::Resource::Size indexSize = getNumIndices() * sizeof(uint32_t); - unsigned char* resultIndexData = new unsigned char[indexSize]; - unsigned char* indexDataCursor = resultIndexData; - - // vertex data const gpu::BufferView& vertexBufferView = getVertexBuffer(); gpu::BufferView::Index numVertices = (gpu::BufferView::Index)getNumVertices(); for (gpu::BufferView::Index i = 0; i < numVertices; i ++) { @@ -162,6 +154,10 @@ model::MeshPointer Mesh::map(std::function vertexFunc, } // normal data + gpu::Resource::Size normalSize = getNumAttributes() * sizeof(glm::vec3); + unsigned char* resultNormalData = new unsigned char[normalSize]; + unsigned char* normalDataCursor = resultNormalData; + const gpu::BufferView& normalsBufferView = getAttributeBuffer(attributeTypeNormal); gpu::BufferView::Index numNormals = (gpu::BufferView::Index)getNumAttributes(); for (gpu::BufferView::Index i = 0; i < numNormals; i ++) { @@ -172,6 +168,10 @@ model::MeshPointer Mesh::map(std::function vertexFunc, // TODO -- other attributes // face data + gpu::Resource::Size indexSize = getNumIndices() * sizeof(uint32_t); + unsigned char* resultIndexData = new unsigned char[indexSize]; + unsigned char* indexDataCursor = resultIndexData; + const gpu::BufferView& indexBufferView = getIndexBuffer(); gpu::BufferView::Index numIndexes = (gpu::BufferView::Index)getNumIndices(); for (gpu::BufferView::Index i = 0; i < numIndexes; i ++) { @@ -215,6 +215,35 @@ model::MeshPointer Mesh::map(std::function vertexFunc, } +void Mesh::forEach(std::function vertexFunc, + std::function normalFunc, + std::function indexFunc) { + int attributeTypeNormal = gpu::Stream::InputSlot::NORMAL; // libraries/gpu/src/gpu/Stream.h + + // vertex data + const gpu::BufferView& vertexBufferView = getVertexBuffer(); + gpu::BufferView::Index numVertices = (gpu::BufferView::Index)getNumVertices(); + for (gpu::BufferView::Index i = 0; i < numVertices; i ++) { + vertexFunc(vertexBufferView.get(i)); + } + + // normal data + const gpu::BufferView& normalsBufferView = getAttributeBuffer(attributeTypeNormal); + gpu::BufferView::Index numNormals = (gpu::BufferView::Index)getNumAttributes(); + for (gpu::BufferView::Index i = 0; i < numNormals; i ++) { + normalFunc(normalsBufferView.get(i)); + } + // TODO -- other attributes + + // face data + const gpu::BufferView& indexBufferView = getIndexBuffer(); + gpu::BufferView::Index numIndexes = (gpu::BufferView::Index)getNumIndices(); + for (gpu::BufferView::Index i = 0; i < numIndexes; i ++) { + indexFunc(indexBufferView.get(i)); + } +} + + Geometry::Geometry() { } diff --git a/libraries/model/src/model/Geometry.h b/libraries/model/src/model/Geometry.h index 9a20861ea7..7ba3e83407 100755 --- a/libraries/model/src/model/Geometry.h +++ b/libraries/model/src/model/Geometry.h @@ -123,6 +123,10 @@ public: std::function normalFunc, std::function indexFunc); + void forEach(std::function vertexFunc, + std::function normalFunc, + std::function indexFunc); + protected: gpu::Stream::FormatPointer _vertexFormat; diff --git a/libraries/script-engine/src/ModelScriptingInterface.cpp b/libraries/script-engine/src/ModelScriptingInterface.cpp index 71b82a2d60..cfcb6da0dc 100644 --- a/libraries/script-engine/src/ModelScriptingInterface.cpp +++ b/libraries/script-engine/src/ModelScriptingInterface.cpp @@ -53,10 +53,8 @@ QString ModelScriptingInterface::meshToOBJ(MeshProxyList in) { return writeOBJToString(meshes); } - QScriptValue ModelScriptingInterface::appendMeshes(MeshProxyList in) { - int attributeTypeNormal = gpu::Stream::InputSlot::NORMAL; // libraries/gpu/src/gpu/Stream.h - + // figure out the size of the resulting mesh size_t totalVertexCount { 0 }; size_t totalAttributeCount { 0 }; size_t totalIndexCount { 0 }; @@ -67,6 +65,7 @@ QScriptValue ModelScriptingInterface::appendMeshes(MeshProxyList in) { totalIndexCount += mesh->getNumIndices(); } + // alloc the resulting mesh gpu::Resource::Size combinedVertexSize = totalVertexCount * sizeof(glm::vec3); unsigned char* combinedVertexData = new unsigned char[combinedVertexSize]; unsigned char* combinedVertexDataCursor = combinedVertexData; @@ -83,36 +82,22 @@ QScriptValue ModelScriptingInterface::appendMeshes(MeshProxyList in) { foreach (const MeshProxy* meshProxy, in) { MeshPointer mesh = meshProxy->getMeshPointer(); + mesh->forEach( + [&](glm::vec3 position){ + memcpy(combinedVertexDataCursor, &position, sizeof(position)); + combinedVertexDataCursor += sizeof(position); + }, + [&](glm::vec3 normal){ + memcpy(combinedNormalDataCursor, &normal, sizeof(normal)); + combinedNormalDataCursor += sizeof(normal); + }, + [&](uint32_t index){ + index += indexStartOffset; + memcpy(combinedIndexDataCursor, &index, sizeof(index)); + combinedIndexDataCursor += sizeof(index); + }); - // vertex data - const gpu::BufferView& vertexBufferView = mesh->getVertexBuffer(); gpu::BufferView::Index numVertices = (gpu::BufferView::Index)mesh->getNumVertices(); - for (gpu::BufferView::Index i = 0; i < numVertices; i ++) { - glm::vec3 pos = vertexBufferView.get(i); - memcpy(combinedVertexDataCursor, &pos, sizeof(pos)); - combinedVertexDataCursor += sizeof(pos); - } - - // normal data - const gpu::BufferView& normalsBufferView = mesh->getAttributeBuffer(attributeTypeNormal); - gpu::BufferView::Index numNormals = (gpu::BufferView::Index)mesh->getNumAttributes(); - for (gpu::BufferView::Index i = 0; i < numNormals; i ++) { - glm::vec3 normal = normalsBufferView.get(i); - memcpy(combinedNormalDataCursor, &normal, sizeof(normal)); - combinedNormalDataCursor += sizeof(normal); - } - // TODO -- other attributes - - // face data - const gpu::BufferView& indexBufferView = mesh->getIndexBuffer(); - gpu::BufferView::Index numIndexes = (gpu::BufferView::Index)mesh->getNumIndices(); - for (gpu::BufferView::Index i = 0; i < numIndexes; i ++) { - uint32_t index = indexBufferView.get(i); - index += indexStartOffset; - memcpy(combinedIndexDataCursor, &index, sizeof(index)); - combinedIndexDataCursor += sizeof(index); - } - indexStartOffset += numVertices; } @@ -124,6 +109,7 @@ QScriptValue ModelScriptingInterface::appendMeshes(MeshProxyList in) { gpu::BufferView combinedVertexBufferView(combinedVertexBufferPointer, vertexElement); result->setVertexBuffer(combinedVertexBufferView); + int attributeTypeNormal = gpu::Stream::InputSlot::NORMAL; // libraries/gpu/src/gpu/Stream.h gpu::Element normalElement = gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ); gpu::Buffer* combinedNormalsBuffer = new gpu::Buffer(combinedNormalSize, combinedNormalData); gpu::BufferPointer combinedNormalsBufferPointer(combinedNormalsBuffer); @@ -136,7 +122,6 @@ QScriptValue ModelScriptingInterface::appendMeshes(MeshProxyList in) { gpu::BufferView combinedIndexesBufferView(combinedIndexesBufferPointer, indexElement); result->setIndexBuffer(combinedIndexesBufferView); - std::vector parts; parts.emplace_back(model::Mesh::Part((model::Index)0, // startIndex (model::Index)result->getNumIndices(), // numIndices @@ -151,92 +136,6 @@ QScriptValue ModelScriptingInterface::appendMeshes(MeshProxyList in) { } -// QScriptValue ModelScriptingInterface::transformMesh(glm::mat4 transform, MeshProxy* meshProxy) { -// int attributeTypeNormal = gpu::Stream::InputSlot::NORMAL; // libraries/gpu/src/gpu/Stream.h - -// if (!meshProxy) { -// return QScriptValue(false); -// } - -// MeshPointer mesh = meshProxy->getMeshPointer(); - -// gpu::Resource::Size vertexSize = mesh->getNumVertices() * sizeof(glm::vec3); -// unsigned char* resultVertexData = new unsigned char[vertexSize]; -// unsigned char* vertexDataCursor = resultVertexData; - -// gpu::Resource::Size normalSize = mesh->getNumAttributes() * sizeof(glm::vec3); -// unsigned char* resultNormalData = new unsigned char[normalSize]; -// unsigned char* normalDataCursor = resultNormalData; - -// gpu::Resource::Size indexSize = mesh->getNumIndices() * sizeof(uint32_t); -// unsigned char* resultIndexData = new unsigned char[indexSize]; -// unsigned char* indexDataCursor = resultIndexData; - -// // vertex data -// const gpu::BufferView& vertexBufferView = mesh->getVertexBuffer(); -// gpu::BufferView::Index numVertices = (gpu::BufferView::Index)mesh->getNumVertices(); -// for (gpu::BufferView::Index i = 0; i < numVertices; i ++) { -// glm::vec3 pos = vertexBufferView.get(i); -// pos = glm::vec3(transform * glm::vec4(pos, 1.0f)); -// memcpy(vertexDataCursor, &pos, sizeof(pos)); -// vertexDataCursor += sizeof(pos); -// } - -// // normal data -// const gpu::BufferView& normalsBufferView = mesh->getAttributeBuffer(attributeTypeNormal); -// gpu::BufferView::Index numNormals = (gpu::BufferView::Index)mesh->getNumAttributes(); -// for (gpu::BufferView::Index i = 0; i < numNormals; i ++) { -// glm::vec3 normal = normalsBufferView.get(i); -// normal = glm::vec3(transform * glm::vec4(normal, 0.0f)); -// memcpy(normalDataCursor, &normal, sizeof(normal)); -// normalDataCursor += sizeof(normal); -// } -// // TODO -- other attributes - -// // face data -// const gpu::BufferView& indexBufferView = mesh->getIndexBuffer(); -// gpu::BufferView::Index numIndexes = (gpu::BufferView::Index)mesh->getNumIndices(); -// for (gpu::BufferView::Index i = 0; i < numIndexes; i ++) { -// uint32_t index = indexBufferView.get(i); -// memcpy(indexDataCursor, &index, sizeof(index)); -// indexDataCursor += sizeof(index); -// } - -// model::MeshPointer result(new model::Mesh()); - -// gpu::Element vertexElement = gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ); -// gpu::Buffer* resultVertexBuffer = new gpu::Buffer(vertexSize, resultVertexData); -// gpu::BufferPointer resultVertexBufferPointer(resultVertexBuffer); -// gpu::BufferView resultVertexBufferView(resultVertexBufferPointer, vertexElement); -// result->setVertexBuffer(resultVertexBufferView); - -// gpu::Element normalElement = gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ); -// gpu::Buffer* resultNormalsBuffer = new gpu::Buffer(normalSize, resultNormalData); -// gpu::BufferPointer resultNormalsBufferPointer(resultNormalsBuffer); -// gpu::BufferView resultNormalsBufferView(resultNormalsBufferPointer, normalElement); -// result->addAttribute(attributeTypeNormal, resultNormalsBufferView); - -// gpu::Element indexElement = gpu::Element(gpu::SCALAR, gpu::UINT32, gpu::RAW); -// gpu::Buffer* resultIndexesBuffer = new gpu::Buffer(indexSize, resultIndexData); -// gpu::BufferPointer resultIndexesBufferPointer(resultIndexesBuffer); -// gpu::BufferView resultIndexesBufferView(resultIndexesBufferPointer, indexElement); -// result->setIndexBuffer(resultIndexesBufferView); - - -// std::vector parts; -// parts.emplace_back(model::Mesh::Part((model::Index)0, // startIndex -// (model::Index)result->getNumIndices(), // numIndices -// (model::Index)0, // baseVertex -// model::Mesh::TRIANGLES)); // topology -// result->setPartBuffer(gpu::BufferView(new gpu::Buffer(parts.size() * sizeof(model::Mesh::Part), -// (gpu::Byte*) parts.data()), gpu::Element::PART_DRAWCALL)); - - - -// MeshProxy* resultProxy = new MeshProxy(result); -// return meshToScriptValue(_modelScriptEngine, resultProxy); -// } - QScriptValue ModelScriptingInterface::transformMesh(glm::mat4 transform, MeshProxy* meshProxy) { if (!meshProxy) { From b876d22e46f21bd4c6e87eec2b8c6675255975cc Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Sat, 18 Mar 2017 22:36:24 -0700 Subject: [PATCH 5/5] fix handling of normals. don't crash when extracting a mesh from a polyvox with no 'on' voxels --- .../src/RenderablePolyVoxEntityItem.h | 2 ++ .../entities/src/EntityScriptingInterface.cpp | 10 ++++-- libraries/entities/src/PolyVoxEntityItem.h | 2 ++ libraries/model/src/model/Geometry.cpp | 31 +++++++++---------- .../src/ModelScriptingInterface.cpp | 7 ++++- 5 files changed, 32 insertions(+), 20 deletions(-) diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h index fa2cdb952f..cf4672f068 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h @@ -61,6 +61,8 @@ public: virtual uint8_t getVoxel(int x, int y, int z) override; virtual bool setVoxel(int x, int y, int z, uint8_t toValue) override; + int getOnCount() const override { return _onCount; } + void render(RenderArgs* args) override; virtual bool supportsDetailedRayIntersection() const override { return true; } virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 37e9e940b1..7ab0c3f7d9 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -930,11 +930,15 @@ bool EntityScriptingInterface::setVoxelsInCuboid(QUuid entityID, const glm::vec3 void EntityScriptingInterface::voxelsToMesh(QUuid entityID, QScriptValue callback) { PROFILE_RANGE(script_entities, __FUNCTION__); - bool success; - QScriptValue mesh; + bool success { false }; + QScriptValue mesh { false }; polyVoxWorker(entityID, [&](PolyVoxEntityItem& polyVoxEntity) mutable { - success = polyVoxEntity.getMeshAsScriptValue(callback.engine(), mesh); + if (polyVoxEntity.getOnCount() == 0) { + success = true; + } else { + success = polyVoxEntity.getMeshAsScriptValue(callback.engine(), mesh); + } return true; }); diff --git a/libraries/entities/src/PolyVoxEntityItem.h b/libraries/entities/src/PolyVoxEntityItem.h index 943d273452..311a002a4a 100644 --- a/libraries/entities/src/PolyVoxEntityItem.h +++ b/libraries/entities/src/PolyVoxEntityItem.h @@ -57,6 +57,8 @@ class PolyVoxEntityItem : public EntityItem { virtual void setVoxelData(QByteArray voxelData); virtual const QByteArray getVoxelData() const; + virtual int getOnCount() const { return 0; } + enum PolyVoxSurfaceStyle { SURFACE_MARCHING_CUBES, SURFACE_CUBIC, diff --git a/libraries/model/src/model/Geometry.cpp b/libraries/model/src/model/Geometry.cpp index d511ae6cb9..04b0db92d3 100755 --- a/libraries/model/src/model/Geometry.cpp +++ b/libraries/model/src/model/Geometry.cpp @@ -138,15 +138,13 @@ Box Mesh::evalPartsBound(int partStart, int partEnd) const { model::MeshPointer Mesh::map(std::function vertexFunc, std::function normalFunc, std::function indexFunc) { - int attributeTypeNormal = gpu::Stream::InputSlot::NORMAL; // libraries/gpu/src/gpu/Stream.h - // vertex data - gpu::Resource::Size vertexSize = getNumVertices() * sizeof(glm::vec3); - unsigned char* resultVertexData = new unsigned char[vertexSize]; - unsigned char* vertexDataCursor = resultVertexData; - const gpu::BufferView& vertexBufferView = getVertexBuffer(); gpu::BufferView::Index numVertices = (gpu::BufferView::Index)getNumVertices(); + gpu::Resource::Size vertexSize = numVertices * sizeof(glm::vec3); + unsigned char* resultVertexData = new unsigned char[vertexSize]; + unsigned char* vertexDataCursor = resultVertexData; + for (gpu::BufferView::Index i = 0; i < numVertices; i ++) { glm::vec3 pos = vertexFunc(vertexBufferView.get(i)); memcpy(vertexDataCursor, &pos, sizeof(pos)); @@ -154,12 +152,13 @@ model::MeshPointer Mesh::map(std::function vertexFunc, } // normal data - gpu::Resource::Size normalSize = getNumAttributes() * sizeof(glm::vec3); - unsigned char* resultNormalData = new unsigned char[normalSize]; + int attributeTypeNormal = gpu::Stream::InputSlot::NORMAL; // libraries/gpu/src/gpu/Stream.h + const gpu::BufferView& normalsBufferView = getAttributeBuffer(attributeTypeNormal); + gpu::BufferView::Index numNormals = (gpu::BufferView::Index)normalsBufferView.getNumElements(); + gpu::Resource::Size normalSize = numNormals * sizeof(glm::vec3); + unsigned char* resultNormalData = new unsigned char[normalSize]; unsigned char* normalDataCursor = resultNormalData; - const gpu::BufferView& normalsBufferView = getAttributeBuffer(attributeTypeNormal); - gpu::BufferView::Index numNormals = (gpu::BufferView::Index)getNumAttributes(); for (gpu::BufferView::Index i = 0; i < numNormals; i ++) { glm::vec3 normal = normalFunc(normalsBufferView.get(i)); memcpy(normalDataCursor, &normal, sizeof(normal)); @@ -168,12 +167,12 @@ model::MeshPointer Mesh::map(std::function vertexFunc, // TODO -- other attributes // face data - gpu::Resource::Size indexSize = getNumIndices() * sizeof(uint32_t); - unsigned char* resultIndexData = new unsigned char[indexSize]; + const gpu::BufferView& indexBufferView = getIndexBuffer(); + gpu::BufferView::Index numIndexes = (gpu::BufferView::Index)getNumIndices(); + gpu::Resource::Size indexSize = numIndexes * sizeof(uint32_t); + unsigned char* resultIndexData = new unsigned char[indexSize]; unsigned char* indexDataCursor = resultIndexData; - const gpu::BufferView& indexBufferView = getIndexBuffer(); - gpu::BufferView::Index numIndexes = (gpu::BufferView::Index)getNumIndices(); for (gpu::BufferView::Index i = 0; i < numIndexes; i ++) { uint32_t index = indexFunc(indexBufferView.get(i)); memcpy(indexDataCursor, &index, sizeof(index)); @@ -229,7 +228,7 @@ void Mesh::forEach(std::function vertexFunc, // normal data const gpu::BufferView& normalsBufferView = getAttributeBuffer(attributeTypeNormal); - gpu::BufferView::Index numNormals = (gpu::BufferView::Index)getNumAttributes(); + gpu::BufferView::Index numNormals = (gpu::BufferView::Index) normalsBufferView.getNumElements(); for (gpu::BufferView::Index i = 0; i < numNormals; i ++) { normalFunc(normalsBufferView.get(i)); } @@ -237,7 +236,7 @@ void Mesh::forEach(std::function vertexFunc, // face data const gpu::BufferView& indexBufferView = getIndexBuffer(); - gpu::BufferView::Index numIndexes = (gpu::BufferView::Index)getNumIndices(); + gpu::BufferView::Index numIndexes = (gpu::BufferView::Index)getNumIndices(); for (gpu::BufferView::Index i = 0; i < numIndexes; i ++) { indexFunc(indexBufferView.get(i)); } diff --git a/libraries/script-engine/src/ModelScriptingInterface.cpp b/libraries/script-engine/src/ModelScriptingInterface.cpp index cfcb6da0dc..833ac5b64d 100644 --- a/libraries/script-engine/src/ModelScriptingInterface.cpp +++ b/libraries/script-engine/src/ModelScriptingInterface.cpp @@ -61,7 +61,12 @@ QScriptValue ModelScriptingInterface::appendMeshes(MeshProxyList in) { foreach (const MeshProxy* meshProxy, in) { MeshPointer mesh = meshProxy->getMeshPointer(); totalVertexCount += mesh->getNumVertices(); - totalAttributeCount += mesh->getNumAttributes(); + + int attributeTypeNormal = gpu::Stream::InputSlot::NORMAL; // libraries/gpu/src/gpu/Stream.h + const gpu::BufferView& normalsBufferView = mesh->getAttributeBuffer(attributeTypeNormal); + gpu::BufferView::Index numNormals = (gpu::BufferView::Index)normalsBufferView.getNumElements(); + totalAttributeCount += numNormals; + totalIndexCount += mesh->getNumIndices(); }