add grid overlay

This commit is contained in:
Nick Fisher
2024-08-24 15:59:04 +08:00
parent f6f12e2566
commit 8f2cd5a353
2 changed files with 242 additions and 0 deletions

View File

@@ -0,0 +1,53 @@
#pragma once
#include <vector>
#include <utils/Entity.h>
#include <filament/Engine.h>
#include <filament/Material.h>
#include <filament/MaterialInstance.h>
#include <filament/Scene.h>
#include <filament/Camera.h>
#include <filament/View.h>
#include <filament/Viewport.h>
#include <gltfio/AssetLoader.h>
#include <gltfio/FilamentAsset.h>
#include <gltfio/FilamentInstance.h>
#include <gltfio/ResourceLoader.h>
#include <filament/IndexBuffer.h>
#include <filament/InstanceBuffer.h>
#include "material/gizmo.h"
#include "Aabb2.h"
namespace thermion_filament {
using namespace filament;
using namespace utils;
class GridOverlay {
public:
GridOverlay(Engine& engine);
void destroy();
utils::Entity sphere() {
return _sphereEntity;
}
utils::Entity grid() {
return _gridEntity;
}
private:
Engine &_engine;
utils::Entity _gridEntity;
utils::Entity _sphereEntity;
Material* _material;
MaterialInstance* _materialInstance;
MaterialInstance* _sphereMaterialInstance;
};
}

View File

@@ -0,0 +1,189 @@
#include "GridOverlay.hpp"
#include <filament/Engine.h>
#include <utils/Entity.h>
#include <utils/EntityManager.h>
#include <filament/RenderableManager.h>
#include <filament/TransformManager.h>
#include <gltfio/math.h>
#include "material/gizmo.h"
#include "Log.hpp"
namespace thermion_filament {
using namespace filament::gltfio;
GridOverlay::GridOverlay(Engine &engine) : _engine(engine)
{
auto &entityManager = EntityManager::get();
auto &transformManager = engine.getTransformManager();
const int gridSize = 100;
const float gridSpacing = 1.0f;
int vertexCount = (gridSize + 1) * 4; // 2 axes, 2 vertices per line
float* gridVertices = new float[vertexCount * 3];
int index = 0;
// Create grid lines
for (int i = 0; i <= gridSize; ++i) {
float pos = i * gridSpacing - (gridSize * gridSpacing / 2);
// X-axis lines
gridVertices[index++] = pos;
gridVertices[index++] = 0;
gridVertices[index++] = -(gridSize * gridSpacing / 2);
gridVertices[index++] = pos;
gridVertices[index++] = 0;
gridVertices[index++] = (gridSize * gridSpacing / 2);
// Z-axis lines
gridVertices[index++] = -(gridSize * gridSpacing / 2);
gridVertices[index++] = 0;
gridVertices[index++] = pos;
gridVertices[index++] = (gridSize * gridSpacing / 2);
gridVertices[index++] = 0;
gridVertices[index++] = pos;
}
auto vb = VertexBuffer::Builder()
.vertexCount(vertexCount)
.bufferCount(1)
.attribute(VertexAttribute::POSITION, 0, VertexBuffer::AttributeType::FLOAT3)
.build(engine);
vb->setBufferAt(engine, 0, VertexBuffer::BufferDescriptor(
gridVertices, vertexCount * sizeof(filament::math::float3),
[](void* buffer, size_t size, void*) { delete[] static_cast<float*>(buffer); }
));
uint32_t* gridIndices = new uint32_t[vertexCount];
for (uint32_t i = 0; i < vertexCount; ++i) {
gridIndices[i] = i;
}
auto ib = IndexBuffer::Builder()
.indexCount(vertexCount)
.bufferType(IndexBuffer::IndexType::UINT)
.build(engine);
ib->setBuffer(engine, IndexBuffer::BufferDescriptor(
gridIndices, vertexCount * sizeof(uint32_t),
[](void* buffer, size_t size, void*) { delete[] static_cast<uint32_t*>(buffer); }
));
_gridEntity = entityManager.create();
// _materialInstance = _material->createInstance();
// _materialInstance->setParameter("color", math::float3{0.5f, 0.5f, 0.5f}); // Gray color for the grid
RenderableManager::Builder(1)
.boundingBox({{-gridSize * gridSpacing / 2, 0, -gridSize * gridSpacing / 2},
{gridSize * gridSpacing / 2, 0, gridSize * gridSpacing / 2}})
// .material(0, _materialInstance)
.geometry(0, RenderableManager::PrimitiveType::LINES, vb, ib, 0, vertexCount)
.priority(6)
.layerMask(0xFF, 4)
.culling(false)
.receiveShadows(false)
.castShadows(false)
.build(engine, _gridEntity);
const float sphereRadius = 0.05f;
const int sphereSegments = 16;
const int sphereRings = 16;
vertexCount = (sphereRings + 1) * (sphereSegments + 1);
int indexCount = sphereRings * sphereSegments * 6;
math::float3* vertices = new math::float3[vertexCount];
uint32_t* indices = new uint32_t[indexCount];
int vertexIndex = 0;
// Generate sphere vertices
for (int ring = 0; ring <= sphereRings; ++ring) {
float theta = ring * M_PI / sphereRings;
float sinTheta = std::sin(theta);
float cosTheta = std::cos(theta);
for (int segment = 0; segment <= sphereSegments; ++segment) {
float phi = segment * 2 * M_PI / sphereSegments;
float sinPhi = std::sin(phi);
float cosPhi = std::cos(phi);
float x = cosPhi * sinTheta;
float y = cosTheta;
float z = sinPhi * sinTheta;
vertices[vertexIndex++] = {x * sphereRadius, y * sphereRadius, z * sphereRadius};
}
}
int indexIndex = 0;
// Generate sphere indices
for (int ring = 0; ring < sphereRings; ++ring) {
for (int segment = 0; segment < sphereSegments; ++segment) {
uint32_t current = ring * (sphereSegments + 1) + segment;
uint32_t next = current + sphereSegments + 1;
indices[indexIndex++] = current;
indices[indexIndex++] = next;
indices[indexIndex++] = current + 1;
indices[indexIndex++] = current + 1;
indices[indexIndex++] = next;
indices[indexIndex++] = next + 1;
}
}
auto sphereVb = VertexBuffer::Builder()
.vertexCount(vertexCount)
.bufferCount(1)
.attribute(VertexAttribute::POSITION, 0, VertexBuffer::AttributeType::FLOAT3)
.build(engine);
sphereVb->setBufferAt(engine, 0, VertexBuffer::BufferDescriptor(
vertices, vertexCount * sizeof(math::float3),
[](void* buffer, size_t size, void*) { delete[] static_cast<math::float3*>(buffer); }
));
auto sphereIb = IndexBuffer::Builder()
.indexCount(indexCount)
.bufferType(IndexBuffer::IndexType::UINT)
.build(engine);
sphereIb->setBuffer(engine, IndexBuffer::BufferDescriptor(
indices, indexCount * sizeof(uint32_t),
[](void* buffer, size_t size, void*) { delete[] static_cast<uint32_t*>(buffer); }
));
_sphereEntity = entityManager.create();
RenderableManager::Builder(1)
.boundingBox({{-sphereRadius, -sphereRadius, -sphereRadius},
{sphereRadius, sphereRadius, sphereRadius}})
.geometry(0, RenderableManager::PrimitiveType::TRIANGLES, sphereVb, sphereIb, 0, indexCount)
.priority(6)
.layerMask(0xFF, 4)
.culling(false)
.receiveShadows(false)
.castShadows(false)
.build(engine, _sphereEntity);
}
void GridOverlay::destroy()
{
auto &rm = _engine.getRenderableManager();
auto &tm = _engine.getTransformManager();
rm.destroy(_sphereEntity);
rm.destroy(_gridEntity);
tm.destroy(_sphereEntity);
tm.destroy(_gridEntity);
_engine.destroy(_sphereEntity);
_engine.destroy(_gridEntity);
}
} // namespace thermion_filament