From d53a8b20b8aef0869c31354bdbcb0e97a2ce6994 Mon Sep 17 00:00:00 2001 From: Nick Fisher Date: Sat, 30 Nov 2024 13:58:02 +0800 Subject: [PATCH] move Geometry asset builder from header to own implementation --- .../scene/GeometrySceneAssetBuilder.hpp | 297 ++--------------- .../src/scene/GeometrySceneAssetBuilder.cpp | 299 ++++++++++++++++++ 2 files changed, 322 insertions(+), 274 deletions(-) create mode 100644 thermion_dart/native/src/scene/GeometrySceneAssetBuilder.cpp diff --git a/thermion_dart/native/include/scene/GeometrySceneAssetBuilder.hpp b/thermion_dart/native/include/scene/GeometrySceneAssetBuilder.hpp index 75815b42..c391cc1c 100644 --- a/thermion_dart/native/include/scene/GeometrySceneAssetBuilder.hpp +++ b/thermion_dart/native/include/scene/GeometrySceneAssetBuilder.hpp @@ -17,287 +17,36 @@ namespace thermion class GeometrySceneAssetBuilder { public: - GeometrySceneAssetBuilder(filament::Engine *engine) : mEngine(engine) {} + GeometrySceneAssetBuilder(filament::Engine *engine); - GeometrySceneAssetBuilder &vertices(const float *vertices, uint32_t count) - { - mVertices->resize(count); - std::copy(vertices, vertices + count, mVertices->data()); - mNumVertices = count; - return *this; - } - - GeometrySceneAssetBuilder &normals(const float *normals, uint32_t count) - { - if (normals) - { - mNormals->resize(count); - std::copy(normals, normals + count, mNormals->data()); - } - else - { - mNormals->clear(); - } - mNumNormals = count; - return *this; - } - - GeometrySceneAssetBuilder &uvs(const float *uvs, uint32_t count) - { - if (uvs) - { - mUVs->resize(count); - std::copy(uvs, uvs + count, mUVs->data()); - } - else - { - mUVs->clear(); - } - mNumUVs = count; - return *this; - } - - GeometrySceneAssetBuilder &indices(const uint16_t *indices, uint32_t count) - { - mIndices->resize(count); - std::copy(indices, indices + count, mIndices->data()); - mNumIndices = count; - return *this; - } - - GeometrySceneAssetBuilder &materials(filament::MaterialInstance **materials, size_t materialInstanceCount) - { - mMaterialInstances = materials; - mMaterialInstanceCount = materialInstanceCount; - return *this; - } - - GeometrySceneAssetBuilder &primitiveType(filament::RenderableManager::PrimitiveType type) - { - mPrimitiveType = type; - return *this; - } - - std::unique_ptr build() - { - Log("Starting build. Validating inputs..."); - if (!validate()) - { - Log("Validation failed!"); - return nullptr; - } - - Log("Creating buffers..."); - auto [vertexBuffer, indexBuffer] = createBuffers(); - if (!vertexBuffer || !indexBuffer) - { - Log("Failed to create buffers: VB=%p, IB=%p", vertexBuffer, indexBuffer); - return nullptr; - } - Log("Buffers created successfully: VB=%p, IB=%p", vertexBuffer, indexBuffer); - - Log("Creating entity..."); - auto entity = utils::EntityManager::get().create(); - Log("Entity created: %d", entity.getId()); - - Box boundingBox = computeBoundingBox(); - Log("Computed bounding box: min={%f,%f,%f}, max={%f,%f,%f}", - boundingBox.getMin().x, boundingBox.getMin().y, boundingBox.getMin().z, - boundingBox.getMax().x, boundingBox.getMax().y, boundingBox.getMax().z); - - auto asset = std::make_unique( - false, - mEngine, - vertexBuffer, - indexBuffer, - mMaterialInstances, - mMaterialInstanceCount, - mPrimitiveType, - boundingBox); - - Log("Asset created: %p", asset.get()); - return asset; - } + GeometrySceneAssetBuilder &vertices(const float *vertices, uint32_t count); + + GeometrySceneAssetBuilder &normals(const float *normals, uint32_t count); + + GeometrySceneAssetBuilder &uvs(const float *uvs, uint32_t count); + + GeometrySceneAssetBuilder &indices(const uint16_t *indices, uint32_t count); + + GeometrySceneAssetBuilder &materials(filament::MaterialInstance **materials, size_t materialInstanceCount); + + GeometrySceneAssetBuilder &primitiveType(filament::RenderableManager::PrimitiveType type); + + std::unique_ptr build(); + private: - Box computeBoundingBox() - { - float minX = FLT_MAX, minY = FLT_MAX, minZ = FLT_MAX; - float maxX = -FLT_MAX, maxY = -FLT_MAX, maxZ = -FLT_MAX; - Box box; - for (uint32_t i = 0; i < mNumVertices; i += 3) - { - minX = std::min(mVertices->at(i), minX); - minY = std::min(mVertices->at(i + 1), minY); - minZ = std::min(mVertices->at(i + 2), minZ); - maxX = std::max(mVertices->at(i), maxX); - maxY = std::max(mVertices->at(i + 1), maxY); - maxZ = std::max(mVertices->at(i + 2), maxZ); - } - const filament::math::float3 min {minX, minY, minZ}; - const filament::math::float3 max {maxX, maxY, maxZ}; - box.set(min, max); - return box; - } + Box computeBoundingBox(); + + std::pair createBuffers(); + - std::pair createBuffers() - { - auto indexBuffer = IndexBuffer::Builder() - .indexCount(mNumIndices) - .bufferType(IndexBuffer::IndexType::USHORT) - .build(*mEngine); - - indexBuffer->setBuffer(*mEngine, - IndexBuffer::BufferDescriptor( - mIndices->data(), - mNumIndices * sizeof(uint16_t), - [](void *, size_t, void *data) - { - delete static_cast *>(data); - }, - mIndices)); - - if (mUVs->empty()) - { - mUVs->resize(mNumVertices); - std::fill(mUVs->begin(), mUVs->end(), 0.0f); - } - - auto dummyColors = new std::vector( - mNumVertices, filament::math::float4{1.0f, 1.0f, 1.0f, 1.0f}); - - auto vertexBufferBuilder = - VertexBuffer::Builder() - .vertexCount(mNumVertices) - .attribute(VertexAttribute::POSITION, 0, VertexBuffer::AttributeType::FLOAT3) - .attribute(VertexAttribute::UV0, 1, VertexBuffer::AttributeType::FLOAT2) - .attribute(VertexAttribute::UV1, 2, VertexBuffer::AttributeType::FLOAT2) - .attribute(VertexAttribute::COLOR, 3, VertexBuffer::AttributeType::FLOAT4); - - if (!mNormals->empty()) - { - vertexBufferBuilder.bufferCount(5) - .attribute(VertexAttribute::TANGENTS, 4, VertexBuffer::AttributeType::FLOAT4); - } - else - { - vertexBufferBuilder = vertexBufferBuilder.bufferCount(4); - } - - auto vertexBuffer = vertexBufferBuilder.build(*mEngine); - - vertexBuffer->setBufferAt(*mEngine, 0, - VertexBuffer::BufferDescriptor( - mVertices->data(), mNumVertices * sizeof(float), - [](void *, size_t, void *) {})); - - vertexBuffer->setBufferAt(*mEngine, 1, - VertexBuffer::BufferDescriptor( - mUVs->data(), mUVs->size() * sizeof(float), - [](void *, size_t, void *data) - { - }, - mUVs)); - - vertexBuffer->setBufferAt(*mEngine, 2, - VertexBuffer::BufferDescriptor( - mUVs->data(), mUVs->size() * sizeof(float), - [](void *, size_t, void *data) { - delete static_cast *>(data); - - }, - mUVs)); - - vertexBuffer->setBufferAt(*mEngine, 3, - VertexBuffer::BufferDescriptor( - dummyColors->data(), dummyColors->size() * sizeof(math::float4), - [](void *, size_t, void *data) - { - delete static_cast *>(data); - }, - dummyColors)); - - if (!mNormals->empty()) - { - assert(mPrimitiveType == RenderableManager::PrimitiveType::TRIANGLES); - - std::vector triangles; - for (uint32_t i = 0; i < mNumIndices; i += 3) - { - triangles.push_back({mIndices->at(i), - mIndices->at(i + 1), - mIndices->at(i + 2)}); - } - - auto &builder = geometry::SurfaceOrientation::Builder() - .vertexCount(mNumVertices) - .normals((filament::math::float3 *)mNormals->data()) - .positions((filament::math::float3 *)mVertices->data()) - .triangleCount(triangles.size()) - .triangles(triangles.data()); - - auto orientation = builder.build(); - auto quats = new std::vector(mNumVertices); - orientation->getQuats(quats->data(), mNumVertices); - - vertexBuffer->setBufferAt(*mEngine, 4, - VertexBuffer::BufferDescriptor( - quats->data(), quats->size() * sizeof(math::quatf), - [](void *, size_t, void *data) - { - delete static_cast *>(data); - }, - quats)); - } - - return {vertexBuffer, indexBuffer}; - } - - bool validate() const - { - if (!mEngine) - { - Log("Validation failed: No engine"); - return false; - } - if (mVertices->empty() || mNumVertices == 0) - { - Log("Validation failed: No vertices (empty=%d, count=%d)", mVertices->empty(), mNumVertices); - return false; - } - if (mNumNormals > 0 && !mNormals->empty() && mNumNormals != mNumVertices) - { - Log("Validation failed: Normal count mismatch (normals=%d, vertices=%d)", mNumNormals, mNumVertices); - return false; - } - if (mNumUVs > 0 && !mUVs->empty() && mNumUVs != mNumVertices) - { - Log("Validation failed: UV count mismatch (uvs=%d, vertices=%d)", mNumUVs, mNumVertices); - return false; - } - if (mIndices->empty() || mNumIndices == 0) - { - Log("Validation failed: No indices (empty=%d, count=%d)", mIndices->empty(), mNumIndices); - return false; - } - - Log("Validation passed: vertices=%d, normals=%s, uvs=%d, indices=%d", - mNumVertices, - (!mNormals->empty() ? "yes" : "no"), - mNumUVs, - mNumIndices); - return true; - } + bool validate() const; filament::Engine *mEngine = nullptr; - std::vector *mVertices = new std::vector(); - std::vector *mNormals = new std::vector(); - std::vector *mUVs = new std::vector(); + std::vector *mVertices = new std::vector(); + std::vector *mNormals = new std::vector(); + std::vector *mUVs = new std::vector(); std::vector *mIndices = new std::vector; - uint32_t mNumVertices = 0; - uint32_t mNumNormals = 0; - uint32_t mNumUVs = 0; - uint32_t mNumIndices = 0; filament::MaterialInstance **mMaterialInstances = nullptr; size_t mMaterialInstanceCount = 0; filament::gltfio::MaterialProvider *mMaterialProvider = nullptr; diff --git a/thermion_dart/native/src/scene/GeometrySceneAssetBuilder.cpp b/thermion_dart/native/src/scene/GeometrySceneAssetBuilder.cpp new file mode 100644 index 00000000..255d5482 --- /dev/null +++ b/thermion_dart/native/src/scene/GeometrySceneAssetBuilder.cpp @@ -0,0 +1,299 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "scene/GeometrySceneAssetBuilder.hpp" +#include "scene/GeometrySceneAsset.hpp" +#include "Log.hpp" + +namespace thermion +{ + GeometrySceneAssetBuilder::GeometrySceneAssetBuilder(filament::Engine *engine) : mEngine(engine) + { + } + + GeometrySceneAssetBuilder &GeometrySceneAssetBuilder::vertices(const float *vertices, uint32_t count) + { + if (count > 0) + { + mVertices->resize(count / 3); + for (int i = 0; i < mVertices->size(); i++) + { + mVertices->at(i) = filament::math::float3{vertices[(i * 3)], vertices[(i * 3) + 1], vertices[(i * 3) + 2]}; + } + } + return *this; + } + + GeometrySceneAssetBuilder &GeometrySceneAssetBuilder::normals(const float *normals, uint32_t count) + { + if (count > 0) + { + mNormals->resize(count / 3); + for (int i = 0; i < mNormals->size(); i++) + { + mNormals->at(i) = filament::math::float3{normals[i * 3], normals[(i * 3) + 1], normals[(i * 3) + 2]}; + } + } + return *this; + } + + GeometrySceneAssetBuilder &GeometrySceneAssetBuilder::uvs(const float *uvs, uint32_t count) + { + if (count > 0) + { + mUVs->resize(count / 2); + for (int i = 0; i < mUVs->size(); i++) + { + mUVs->at(i) = filament::math::float2{uvs[i * 2], uvs[(i * 2) + 1]}; + } + } + return *this; + } + + GeometrySceneAssetBuilder &GeometrySceneAssetBuilder::indices(const uint16_t *indices, uint32_t count) + { + if (count > 0) + { + mIndices->resize(count); + for (int i = 0; i < mIndices->size(); i++) + { + mIndices->at(i) = indices[i]; + } + } + return *this; + } + + GeometrySceneAssetBuilder &GeometrySceneAssetBuilder::materials(filament::MaterialInstance **materials, size_t materialInstanceCount) + { + mMaterialInstances = materials; + mMaterialInstanceCount = materialInstanceCount; + return *this; + } + + GeometrySceneAssetBuilder &GeometrySceneAssetBuilder::primitiveType(filament::RenderableManager::PrimitiveType type) + { + mPrimitiveType = type; + return *this; + } + + std::unique_ptr GeometrySceneAssetBuilder::build() + { + Log("Starting build. Validating inputs..."); + if (!validate()) + { + Log("Validation failed!"); + return nullptr; + } + + Log("Creating buffers..."); + auto [vertexBuffer, indexBuffer] = createBuffers(); + if (!vertexBuffer || !indexBuffer) + { + Log("Failed to create buffers: VB=%p, IB=%p", vertexBuffer, indexBuffer); + return nullptr; + } + Log("Buffers created successfully: VB=%p, IB=%p", vertexBuffer, indexBuffer); + + Box boundingBox = computeBoundingBox(); + Log("Computed bounding box: min={%f,%f,%f}, max={%f,%f,%f}", + boundingBox.getMin().x, boundingBox.getMin().y, boundingBox.getMin().z, + boundingBox.getMax().x, boundingBox.getMax().y, boundingBox.getMax().z); + + auto asset = std::make_unique( + false, + mEngine, + vertexBuffer, + indexBuffer, + mMaterialInstances, + mMaterialInstanceCount, + mPrimitiveType, + boundingBox); + + Log("Asset created: %p", asset.get()); + return asset; + } + + Box GeometrySceneAssetBuilder::computeBoundingBox() + { + float minX = FLT_MAX, minY = FLT_MAX, minZ = FLT_MAX; + float maxX = -FLT_MAX, maxY = -FLT_MAX, maxZ = -FLT_MAX; + Box box; + for (auto &vertex : *mVertices) + { + minX = std::min(vertex.x, minX); + minY = std::min(vertex.y, minY); + minZ = std::min(vertex.z, minZ); + maxX = std::max(vertex.x, maxX); + maxY = std::max(vertex.y, maxY); + maxZ = std::max(vertex.z, maxZ); + } + const filament::math::float3 min{minX, minY, minZ}; + const filament::math::float3 max{maxX, maxY, maxZ}; + box.set(min, max); + return box; + } + + std::pair GeometrySceneAssetBuilder::createBuffers() + { + auto indexBuffer = IndexBuffer::Builder() + .indexCount(mIndices->size()) + .bufferType(IndexBuffer::IndexType::USHORT) + .build(*mEngine); + + indexBuffer->setBuffer(*mEngine, + IndexBuffer::BufferDescriptor( + mIndices->data(), + mIndices->size() * sizeof(uint16_t), + [](void *, size_t, void *data) + { + delete static_cast *>(data); + }, + mIndices)); + + if (mUVs->empty()) + { + mUVs->resize(mVertices->size()); + std::fill(mUVs->begin(), mUVs->end(), filament::math::float2{0.0f, 0.0f}); + } + + auto vertexBufferBuilder = + VertexBuffer::Builder() + .vertexCount(mVertices->size()) + .attribute(VertexAttribute::POSITION, 0, VertexBuffer::AttributeType::FLOAT3) + .attribute(VertexAttribute::UV0, 1, VertexBuffer::AttributeType::FLOAT2) + .attribute(VertexAttribute::UV1, 2, VertexBuffer::AttributeType::FLOAT2) + .attribute(VertexAttribute::COLOR, 3, VertexBuffer::AttributeType::FLOAT4); + + if (!mNormals->empty()) + { + vertexBufferBuilder.bufferCount(5) + .attribute(VertexAttribute::TANGENTS, 4, VertexBuffer::AttributeType::FLOAT4); + } + else + { + vertexBufferBuilder = vertexBufferBuilder.bufferCount(4); + } + + auto vertexBuffer = vertexBufferBuilder.build(*mEngine); + + vertexBuffer->setBufferAt(*mEngine, 0, + VertexBuffer::BufferDescriptor( + mVertices->data(), mVertices->size() * sizeof(filament::math::float3), + [](void *, size_t, void *) { + + })); + + vertexBuffer->setBufferAt(*mEngine, 1, + VertexBuffer::BufferDescriptor( + mUVs->data(), mUVs->size() * sizeof(filament::math::float2), + [](void *, size_t, void *data) { + + }, + mUVs)); + + vertexBuffer->setBufferAt(*mEngine, 2, + VertexBuffer::BufferDescriptor( + mUVs->data(), mUVs->size() * sizeof(filament::math::float2), + [](void *, size_t, void *data) + { + delete static_cast *>(data); + }, + mUVs)); + + auto dummyColors = new std::vector( + mVertices->size(), filament::math::float4{1.0f, 1.0f, 1.0f, 1.0f}); + vertexBuffer->setBufferAt(*mEngine, 3, + VertexBuffer::BufferDescriptor( + dummyColors->data(), dummyColors->size() * sizeof(math::float4), + [](void *, size_t, void *data) + { + delete static_cast *>(data); + }, + dummyColors)); + if (mNormals->size() > 0) + { + + std::vector triangles; + + for (uint32_t i = 0; i < mIndices->size(); i += 3) + { + triangles.push_back({mIndices->at(i), + mIndices->at(i + 1), + mIndices->at(i + 2)}); + } + + geometry::SurfaceOrientation::Builder builder; + builder.vertexCount(mVertices->size()); + builder.normals(mNormals->data()); + builder.positions(mVertices->data()); + builder.triangleCount(triangles.size()); + builder.triangles(triangles.data()); + + auto orientation = builder.build(); + auto quats = new std::vector(mVertices->size()); + orientation->getQuats(quats->data(), mVertices->size()); + + vertexBuffer->setBufferAt(*mEngine, 4, + VertexBuffer::BufferDescriptor( + quats->data(), quats->size() * sizeof(math::quatf), + [](void *, size_t, void *data) + { + delete static_cast *>(data); + }, + quats)); + } + + return {vertexBuffer, indexBuffer}; + } + + bool GeometrySceneAssetBuilder::validate() const + { + if (!mEngine) + { + Log("Validation failed: No engine"); + return false; + } + if (mVertices->empty()) + { + Log("Validation failed: No vertices (empty=%d, count=%d)", mVertices->empty(), mVertices->size()); + return false; + } + + if (!mNormals->empty()) + { + assert(mPrimitiveType == RenderableManager::PrimitiveType::TRIANGLES); + } + if (!mNormals->empty() && mNormals->size() != mVertices->size()) + { + Log("Validation failed: Normal count mismatch (normals=%d, vertices=%d)", mNormals->size(), mVertices->size()); + return false; + } + if (!mUVs->empty() && mUVs->size() != mVertices->size() * 2) + { + Log("Validation failed: UV count mismatch (uvs=%d, vertices=%d)", mUVs->size(), mVertices->size()); + return false; + } + if (mIndices->empty()) + { + Log("Validation failed: No indices (empty=%d, count=%d)", mIndices->empty(), mIndices->size()); + return false; + } + + Log("Validation passed: vertices=%d, normals=%s, uvs=%d, indices=%d", + mVertices->size(), + (!mNormals->empty() ? "yes" : "no"), + mUVs->size(), + mIndices->size()); + return true; + } + +} // namespace thermion \ No newline at end of file