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 };