From 8f20a8a8590906a73e838787753ae24bc267c028 Mon Sep 17 00:00:00 2001 From: Nick Fisher Date: Sat, 24 Aug 2024 15:21:36 +0800 Subject: [PATCH] chore: don't use shader to overlay gizmo --- materials/gizmo.mat | 4 +- thermion_dart/native/src/Gizmo.cpp | 259 ++++++++++++++++++----------- 2 files changed, 165 insertions(+), 98 deletions(-) diff --git a/materials/gizmo.mat b/materials/gizmo.mat index 5b7bc75b..7ee85818 100644 --- a/materials/gizmo.mat +++ b/materials/gizmo.mat @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3158461d081f058dcb9582ce19cc2daedc73abbe758ba5094c94df89028d8c4d -size 981 +oid sha256:1ce59256956f5dbb76f6ac3c51e4811f71483427db689afae5f0fd982a53b90f +size 647 diff --git a/thermion_dart/native/src/Gizmo.cpp b/thermion_dart/native/src/Gizmo.cpp index 9544699c..0bdc12f6 100644 --- a/thermion_dart/native/src/Gizmo.cpp +++ b/thermion_dart/native/src/Gizmo.cpp @@ -5,22 +5,86 @@ #include #include #include +#include #include "material/gizmo.h" #include "Log.hpp" -Gizmo::Gizmo(Engine* const engine) +namespace thermion_filament { + +using namespace filament::gltfio; + +Gizmo::Gizmo(Engine &engine) : _engine(engine) { + auto &entityManager = EntityManager::get(); + + auto &transformManager = engine.getTransformManager(); + _material = Material::Builder() .package(GIZMO_GIZMO_DATA, GIZMO_GIZMO_SIZE) - .build(*engine); + .build(engine); + + // First, create the black cube at the center + // The axes widgets will be parented to this entity + _entities[3] = entityManager.create(); + _materialInstances[3] = _material->createInstance(); + _materialInstances[3]->setParameter("color", math::float3{0.0f, 0.0f, 0.0f}); // Black color + + // Create center cube vertices + float centerCubeSize = 0.05f; + float *centerCubeVertices = new float[8 * 3]{ + -centerCubeSize, -centerCubeSize, -centerCubeSize, + centerCubeSize, -centerCubeSize, -centerCubeSize, + centerCubeSize, centerCubeSize, -centerCubeSize, + -centerCubeSize, centerCubeSize, -centerCubeSize, + -centerCubeSize, -centerCubeSize, centerCubeSize, + centerCubeSize, -centerCubeSize, centerCubeSize, + centerCubeSize, centerCubeSize, centerCubeSize, + -centerCubeSize, centerCubeSize, centerCubeSize}; + + // Create center cube indices + uint16_t *centerCubeIndices = new uint16_t[36]{ + 0, 1, 2, 2, 3, 0, + 1, 5, 6, 6, 2, 1, + 5, 4, 7, 7, 6, 5, + 4, 0, 3, 3, 7, 4, + 3, 2, 6, 6, 7, 3, + 4, 5, 1, 1, 0, 4}; + + auto centerCubeVb = VertexBuffer::Builder() + .vertexCount(8) + .bufferCount(1) + .attribute(VertexAttribute::POSITION, 0, VertexBuffer::AttributeType::FLOAT3) + .build(engine); + + centerCubeVb->setBufferAt(engine, 0, VertexBuffer::BufferDescriptor(centerCubeVertices, 8 * sizeof(filament::math::float3), [](void *buffer, size_t size, void *) + { delete[] static_cast(buffer); })); + + auto centerCubeIb = IndexBuffer::Builder().indexCount(36).bufferType(IndexBuffer::IndexType::USHORT).build(engine); + centerCubeIb->setBuffer(engine, IndexBuffer::BufferDescriptor( + centerCubeIndices, 36 * sizeof(uint16_t), + [](void *buffer, size_t size, void *) + { delete[] static_cast(buffer); })); + + RenderableManager::Builder(1) + .boundingBox({{}, {centerCubeSize, centerCubeSize, centerCubeSize}}) + .material(0, _materialInstances[3]) + .layerMask(0xFF, 2) + .priority(0) + .geometry(0, RenderableManager::PrimitiveType::TRIANGLES, centerCubeVb, centerCubeIb, 0, 36) + .culling(false) + .build(engine, _entities[3]); + + auto cubeTransformInstance = transformManager.getInstance(_entities[3]); + math::mat4f cubeTransform; + transformManager.setTransform(cubeTransformInstance, cubeTransform); // Line and arrow vertices float lineLength = 0.8f; - float lineWidth = 0.005f; + float lineWidth = 0.01f; float arrowLength = 0.2f; - float arrowWidth = 0.03f; + float arrowWidth = 0.06f; float *vertices = new float[13 * 3]{ // Line vertices (8 vertices) -lineWidth, -lineWidth, 0.0f, @@ -57,18 +121,16 @@ Gizmo::Gizmo(Engine* const engine) .vertexCount(13) .bufferCount(1) .attribute(VertexAttribute::POSITION, 0, VertexBuffer::AttributeType::FLOAT3) - .build(*engine); + .build(engine); - vb->setBufferAt(*engine, 0, VertexBuffer::BufferDescriptor(vertices, 13 * sizeof(filament::math::float3), [](void *buffer, size_t size, void *) - { delete[] static_cast(buffer); })); + vb->setBufferAt(engine, 0, VertexBuffer::BufferDescriptor(vertices, 13 * sizeof(filament::math::float3), [](void *buffer, size_t size, void *) + { delete[] static_cast(buffer); })); - auto ib = IndexBuffer::Builder().indexCount(54).bufferType(IndexBuffer::IndexType::USHORT).build(*engine); - ib->setBuffer(*engine, IndexBuffer::BufferDescriptor( - indices, 54 * sizeof(uint16_t), - [](void *buffer, size_t size, void *) - { delete[] static_cast(buffer); })); - - auto &entityManager = EntityManager::get(); + auto ib = IndexBuffer::Builder().indexCount(54).bufferType(IndexBuffer::IndexType::USHORT).build(engine); + ib->setBuffer(engine, IndexBuffer::BufferDescriptor( + indices, 54 * sizeof(uint16_t), + [](void *buffer, size_t size, void *) + { delete[] static_cast(buffer); })); // Create the three axes for (int i = 0; i < 3; i++) @@ -100,100 +162,105 @@ Gizmo::Gizmo(Engine* const engine) .boundingBox({{0, 0, (lineLength + arrowLength) / 2}, {arrowWidth / 2, arrowWidth / 2, (lineLength + arrowLength) / 2}}) .material(0, _materialInstances[i]) .geometry(0, RenderableManager::PrimitiveType::TRIANGLES, vb, ib, 0, 54) + .priority(0) + .layerMask(0xFF, 2) .culling(false) .receiveShadows(false) .castShadows(false) - .build(*engine, _entities[i]); + .build(engine, _entities[i]); + - auto &transformManager = engine->getTransformManager(); auto instance = transformManager.getInstance(_entities[i]); transformManager.setTransform(instance, transform); + + // parent the axis to the center cube + transformManager.setParent(instance, cubeTransformInstance); } - - // Create the black cube (center cube) - _entities[3] = entityManager.create(); - _materialInstances[3] = _material->createInstance(); - _materialInstances[3]->setParameter("color", math::float3{0.0f, 0.0f, 0.0f}); // Black color - - // Create center cube vertices - float centerCubeSize = 0.05f; - float *centerCubeVertices = new float[8 * 3]{ - -centerCubeSize, -centerCubeSize, -centerCubeSize, - centerCubeSize, -centerCubeSize, -centerCubeSize, - centerCubeSize, centerCubeSize, -centerCubeSize, - -centerCubeSize, centerCubeSize, -centerCubeSize, - -centerCubeSize, -centerCubeSize, centerCubeSize, - centerCubeSize, -centerCubeSize, centerCubeSize, - centerCubeSize, centerCubeSize, centerCubeSize, - -centerCubeSize, centerCubeSize, centerCubeSize}; - - // Create center cube indices - uint16_t *centerCubeIndices = new uint16_t[36]{ - 0, 1, 2, 2, 3, 0, - 1, 5, 6, 6, 2, 1, - 5, 4, 7, 7, 6, 5, - 4, 0, 3, 3, 7, 4, - 3, 2, 6, 6, 7, 3, - 4, 5, 1, 1, 0, 4}; - - auto centerCubeVb = VertexBuffer::Builder() - .vertexCount(8) - .bufferCount(1) - .attribute(VertexAttribute::POSITION, 0, VertexBuffer::AttributeType::FLOAT3) - .build(*engine); - - centerCubeVb->setBufferAt(*engine, 0, VertexBuffer::BufferDescriptor(centerCubeVertices, 8 * sizeof(filament::math::float3), [](void *buffer, size_t size, void *) - { delete[] static_cast(buffer); })); - - auto centerCubeIb = IndexBuffer::Builder().indexCount(36).bufferType(IndexBuffer::IndexType::USHORT).build(*engine); - centerCubeIb->setBuffer(*engine, IndexBuffer::BufferDescriptor( - centerCubeIndices, 36 * sizeof(uint16_t), - [](void *buffer, size_t size, void *) - { delete[] static_cast(buffer); })); - - RenderableManager::Builder(1) - .boundingBox({{}, {centerCubeSize, centerCubeSize, centerCubeSize}}) - .material(0, _materialInstances[3]) - .geometry(0, RenderableManager::PrimitiveType::TRIANGLES, centerCubeVb, centerCubeIb, 0, 36) - .culling(false) - .build(*engine, _entities[3]); - - auto &rm = engine->getRenderableManager(); - for (int i = 0; i < 4; i++) - { - rm.setPriority(rm.getInstance(_entities[i]), 7); - } - } -void Gizmo::destroy(Engine *const engine) { - - for (int i = 0; i < 4; i++) - { - engine->destroy(_entities[i]); - engine->destroy(_materialInstances[i]); - } - - engine->destroy(_material); -} - -void Gizmo::updateTransform() +void Gizmo::destroy() { - Log("Updating gizmo transform"); - // // Get screen-space position of the entity - // math::float4 entityScreenPos = _view->getViewProjectionMatrix() * entityWorldPosition; + auto& rm = _engine.getRenderableManager(); + auto& tm = _engine.getTransformManager(); + + for (int i = 0; i < 4; i++) + { + rm.destroy(_entities[i]); + tm.destroy(_entities[i]); + _engine.destroy(_entities[i]); + _engine.destroy(_materialInstances[i]); + } - // // Convert to NDC space - // entityScreenPos /= entityScreenPos.w; + _engine.destroy(_material); +} - // // Convert to screen space - // float screenX = (entityScreenPos.x * 0.5f + 0.5f) * viewportWidth; - // float screenY = (entityScreenPos.y * 0.5f + 0.5f) * viewportHeight; - // // Set gizmo position - // gizmo->setPosition({screenX, screenY, 0}); +void Gizmo::updateTransform(Camera& camera, const Viewport &vp) +{ + auto & transformManager = _engine.getTransformManager(); + auto transformInstance = transformManager.getInstance(_entities[3]); - // // Scale gizmo based on viewport size - // float scale = viewportHeight * 0.1f; // 10% of screen height, for example - // gizmo->setScale({scale, scale, 1}); + if(!transformInstance.isValid()) { + Log("No valid gizmo transform"); + return; + } + + auto worldTransform = transformManager.getWorldTransform(transformInstance); + math::float4 worldPosition { 0.0f, 0.0f, 0.0f, 1.0f }; + worldPosition = worldTransform * worldPosition; + + // Calculate distance + float distance = length(worldPosition.xyz - camera.getPosition()); + + const float desiredScreenSize = 3.0f; // Desired height in pixels + const float baseSize = 0.1f; // Base size in world units + + // Get the vertical field of view of the camera (assuming it's in radians) + float fovY = camera.getFieldOfViewInDegrees(filament::Camera::Fov::VERTICAL); + + // Calculate the scale needed to maintain the desired screen size + float newScale = (2.0f * distance * tan(fovY * 0.5f) * desiredScreenSize) / (baseSize * vp.height); + + if(std::isnan(newScale)) { + newScale = 1.0f; + } + + // Log("Distance %f, newscale %f", distance, newScale); + + auto localTransform = transformManager.getTransform(transformInstance); + + // Apply scale to gizmo + math::float3 translation; + math::quatf rotation; + math::float3 scale; + + decomposeMatrix(localTransform, &translation, &rotation, &scale); + + scale = math::float3 { newScale, newScale, newScale }; + + auto scaledTransform = composeMatrix(translation, rotation, scale); + + transformManager.setTransform(transformInstance, scaledTransform); + + // The following code for logging screen position remains unchanged + auto viewSpacePos = camera.getViewMatrix() * worldPosition; + math::float4 entityScreenPos = camera.getProjectionMatrix() * viewSpacePos; + entityScreenPos /= entityScreenPos.w; + float screenX = (entityScreenPos.x * 0.5f + 0.5f) * vp.width; + float screenY = (entityScreenPos.y * 0.5f + 0.5f) * vp.height; + // Log("gizmo %f %f", screenX, screenY); +} + + + // Log("scaledTransform %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f", + // scaledTransform[0][0], scaledTransform[0][1], scaledTransform[0][2], scaledTransform[0][3], + // scaledTransform[1][0], scaledTransform[1][1], scaledTransform[1][2], scaledTransform[1][3], + // scaledTransform[2][0], scaledTransform[2][1], scaledTransform[2][2], scaledTransform[2][3], + // scaledTransform[3][0], scaledTransform[3][1], scaledTransform[3][2], scaledTransform[3][3]); + + // Log("localTransform %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f", + // localTransform[0][0], localTransform[0][1], localTransform[0][2], localTransform[0][3], + // localTransform[1][0], localTransform[1][1], localTransform[1][2], localTransform[1][3], + // localTransform[2][0], localTransform[2][1], localTransform[2][2], localTransform[2][3], + // localTransform[3][0], localTransform[3][1], localTransform[3][2], localTransform[3][3]); } \ No newline at end of file