feat: create transparent overlay for gizmo for easier picking

This commit is contained in:
Nick Fisher
2024-08-27 21:45:19 +08:00
parent 2fc54ae343
commit 727ac7d9df
8 changed files with 1419 additions and 1265 deletions

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:f467a6361958bd8a3381dcd5895665c09932daf37e606b06c7f584de484b0d5d oid sha256:634f5806365b20f05a3736b5b87c1ba6a49b94e39d3defbd6f22f9784d718388
size 1572 size 1754

View File

@@ -35,7 +35,6 @@ class Gizmo {
Gizmo(Engine& engine, View *view, Scene *scene); Gizmo(Engine& engine, View *view, Scene *scene);
~Gizmo(); ~Gizmo();
void updateTransform();
void destroy(); void destroy();
Entity x() { Entity x() {
return _entities[0]; return _entities[0];
@@ -57,18 +56,21 @@ class Gizmo {
return _isActive; return _isActive;
} }
void highlight(Entity entity);
void unhighlight();
void pick(uint32_t x, uint32_t y, void (*callback)(EntityId entityId, int x, int y)); void pick(uint32_t x, uint32_t y, void (*callback)(EntityId entityId, int x, int y));
bool isGizmoEntity(Entity entity);
void setVisibility(bool visible);
private: private:
void createTransparentRectangles();
void highlight(Entity entity);
void unhighlight();
Engine &_engine; Engine &_engine;
View *_view; View *_view;
Scene *_scene; Scene *_scene;
Camera *_camera; Camera *_camera;
utils::Entity _entities[4] = { utils::Entity(), utils::Entity(), utils::Entity(), utils::Entity() }; utils::Entity _entities[7] = { utils::Entity(), utils::Entity(), utils::Entity(), utils::Entity(), utils::Entity(), utils::Entity(), utils::Entity() };
Material* _material; Material* _material;
MaterialInstance* _materialInstances[4]; MaterialInstance* _materialInstances[7];
math::float4 inactiveColors[3] { math::float4 inactiveColors[3] {
math::float4 { 0.75f, 0.0f, 0.0f, 1.0f }, math::float4 { 0.75f, 0.0f, 0.0f, 1.0f },
math::float4 { 0.0f, 0.75f, 0.0f, 1.0f }, math::float4 { 0.0f, 0.75f, 0.0f, 1.0f },
@@ -80,6 +82,7 @@ class Gizmo {
math::float4 { 0.0f, 0.0f, 1.0f, 1.0f }, math::float4 { 0.0f, 0.0f, 1.0f, 1.0f },
}; };
bool _isActive = true; bool _isActive = true;
}; };
} }

View File

@@ -8,5 +8,5 @@ GIZMO_PACKAGE:
GIZMO_GIZMO_OFFSET: GIZMO_GIZMO_OFFSET:
.int 0 .int 0
GIZMO_GIZMO_SIZE: GIZMO_GIZMO_SIZE:
.int 26876 .int 28800

View File

@@ -8,5 +8,5 @@ _GIZMO_PACKAGE:
_GIZMO_GIZMO_OFFSET: _GIZMO_GIZMO_OFFSET:
.int 0 .int 0
_GIZMO_GIZMO_SIZE: _GIZMO_GIZMO_SIZE:
.int 26876 .int 28800

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,6 @@
#include <stdint.h>
#include "image.h" #include "image.h"
#include <stdint.h>
const uint8_t IMAGE_PACKAGE[] = { const uint8_t IMAGE_PACKAGE[] = {
// IMAGE // IMAGE
0x53, 0x52, 0x45, 0x56, 0x5f, 0x54, 0x41, 0x4d, 0x04, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x54, 0x41, 0x45, 0x46, 0x53, 0x52, 0x45, 0x56, 0x5f, 0x54, 0x41, 0x4d, 0x04, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x54, 0x41, 0x45, 0x46,

View File

@@ -45,8 +45,9 @@ Gizmo::Gizmo(Engine &engine, View* view, Scene* scene) : _engine(engine)
// First, create the black cube at the center // First, create the black cube at the center
// The axes widgets will be parented to this entity // The axes widgets will be parented to this entity
_entities[3] = entityManager.create(); _entities[3] = entityManager.create();
_materialInstances[3] = _material->createInstance(); _materialInstances[3] = _material->createInstance();
_materialInstances[3]->setParameter("color", math::float3{0.0f, 0.0f, 0.0f}); // Black color _materialInstances[3]->setParameter("color", math::float4{0.0f, 0.0f, 0.0f, 1.0f}); // Black color
// Create center cube vertices // Create center cube vertices
float centerCubeSize = 0.05f; float centerCubeSize = 0.05f;
@@ -89,7 +90,7 @@ Gizmo::Gizmo(Engine &engine, View* view, Scene* scene) : _engine(engine)
{centerCubeSize, centerCubeSize, centerCubeSize}}) {centerCubeSize, centerCubeSize, centerCubeSize}})
.material(0, _materialInstances[3]) .material(0, _materialInstances[3])
.layerMask(0xFF, 2) .layerMask(0xFF, 2)
.priority(7) .priority(6)
.geometry(0, RenderableManager::PrimitiveType::TRIANGLES, centerCubeVb, centerCubeIb, 0, 36) .geometry(0, RenderableManager::PrimitiveType::TRIANGLES, centerCubeVb, centerCubeIb, 0, 36)
.culling(false) .culling(false)
.build(engine, _entities[3]); .build(engine, _entities[3]);
@@ -198,7 +199,7 @@ Gizmo::Gizmo(Engine &engine, View* view, Scene* scene) : _engine(engine)
} }
_scene->addEntities(_entities,4); createTransparentRectangles();
_view->setLayerEnabled(0, true); // scene assets _view->setLayerEnabled(0, true); // scene assets
_view->setLayerEnabled(1, true); // gizmo _view->setLayerEnabled(1, true); // gizmo
@@ -206,12 +207,12 @@ Gizmo::Gizmo(Engine &engine, View* view, Scene* scene) : _engine(engine)
} }
Gizmo::~Gizmo() { Gizmo::~Gizmo() {
_scene->removeEntities(_entities, 4); _scene->removeEntities(_entities, 7);
for(int i = 0; i < 4; i++) { for(int i = 0; i < 7; i++) {
_engine.destroy(_materialInstances[i]); _engine.destroy(_materialInstances[i]);
} }
_engine.destroy(_material); _engine.destroy(_material);
for(int i = 0; i < 4; i++) { for(int i = 0; i < 7; i++) {
_engine.destroy(_entities[i]); _engine.destroy(_entities[i]);
} }
@@ -221,6 +222,95 @@ Gizmo::~Gizmo() {
} }
void Gizmo::createTransparentRectangles()
{
auto &entityManager = EntityManager::get();
auto &transformManager = _engine.getTransformManager();
float volumeWidth = 0.2f;
float volumeLength = 1.2f;
float volumeDepth = 0.2f;
float *volumeVertices = new float[8 * 3]{
-volumeWidth / 2, -volumeDepth / 2, 0,
volumeWidth / 2, -volumeDepth / 2, 0,
volumeWidth / 2, -volumeDepth / 2, volumeLength,
-volumeWidth / 2, -volumeDepth / 2, volumeLength,
-volumeWidth / 2, volumeDepth / 2, 0,
volumeWidth / 2, volumeDepth / 2, 0,
volumeWidth / 2, volumeDepth / 2, volumeLength,
-volumeWidth / 2, volumeDepth / 2, volumeLength
};
uint16_t *volumeIndices = new uint16_t[36]{
0, 1, 2, 2, 3, 0, // Bottom face
4, 5, 6, 6, 7, 4, // Top face
0, 4, 7, 7, 3, 0, // Left face
1, 5, 6, 6, 2, 1, // Right face
0, 1, 5, 5, 4, 0, // Front face
3, 2, 6, 6, 7, 3 // Back face
};
auto volumeVb = VertexBuffer::Builder()
.vertexCount(8)
.bufferCount(1)
.attribute(VertexAttribute::POSITION, 0, VertexBuffer::AttributeType::FLOAT3)
.build(_engine);
volumeVb->setBufferAt(_engine, 0, VertexBuffer::BufferDescriptor(
volumeVertices, 8 * sizeof(filament::math::float3),
[](void *buffer, size_t size, void *) { delete[] static_cast<float *>(buffer); }
));
auto volumeIb = IndexBuffer::Builder()
.indexCount(36)
.bufferType(IndexBuffer::IndexType::USHORT)
.build(_engine);
volumeIb->setBuffer(_engine, IndexBuffer::BufferDescriptor(
volumeIndices, 36 * sizeof(uint16_t),
[](void *buffer, size_t size, void *) { delete[] static_cast<uint16_t *>(buffer); }
));
for (int i = 4; i < 7; i++)
{
_entities[i] = entityManager.create();
_materialInstances[i] = _material->createInstance();
_materialInstances[i]->setParameter("color", math::float4{0.0f, 0.0f, 0.0f, 0.0f});
math::mat4f transform;
switch (i-4)
{
case Axis::X:
transform = math::mat4f::rotation(math::F_PI_2, math::float3{0, 1, 0});
break;
case Axis::Y:
transform = math::mat4f::rotation(-math::F_PI_2, math::float3{1, 0, 0});
break;
case Axis::Z:
break;
}
RenderableManager::Builder(1)
.boundingBox({{-volumeWidth / 2, -volumeDepth / 2, 0}, {volumeWidth / 2, volumeDepth / 2, volumeLength}})
.material(0, _materialInstances[i])
.geometry(0, RenderableManager::PrimitiveType::TRIANGLES, volumeVb, volumeIb, 0, 36)
.priority(7)
.layerMask(0xFF, 2)
.culling(false)
.receiveShadows(false)
.castShadows(false)
.build(_engine, _entities[i]);
auto instance = transformManager.getInstance(_entities[i]);
transformManager.setTransform(instance, transform);
// Parent the picking volume to the center cube
transformManager.setParent(instance, transformManager.getInstance(_entities[3]));
}
}
void Gizmo::highlight(Entity entity) { void Gizmo::highlight(Entity entity) {
auto &rm = _engine.getRenderableManager(); auto &rm = _engine.getRenderableManager();
auto renderableInstance = rm.getInstance(entity); auto renderableInstance = rm.getInstance(entity);
@@ -270,73 +360,37 @@ void Gizmo::destroy()
} }
void Gizmo::updateTransform()
{
return;
// auto & transformManager = _engine.getTransformManager();
// auto transformInstance = transformManager.getInstance(_entities[3]);
// 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);
// 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;
}
void Gizmo::pick(uint32_t x, uint32_t y, void (*callback)(EntityId entityId, int x, int y)) void Gizmo::pick(uint32_t x, uint32_t y, void (*callback)(EntityId entityId, int x, int y))
{ {
auto * gizmo = this; auto * gizmo = this;
_view->pick(x, y, [=](filament::View::PickingQueryResult const &result) { _view->pick(x, y, [=](filament::View::PickingQueryResult const &result) {
if(result.renderable == gizmo->x() || result.renderable == gizmo->y() || result.renderable == gizmo->z()) { for(int i = 4; i < 7; i++) {
gizmo->highlight(result.renderable); if(_entities[i] == result.renderable) {
callback(Entity::smuggle(result.renderable), x, y); gizmo->highlight(_entities[i - 4]);
} else { callback(Entity::smuggle(_entities[i - 4]), x, y);
gizmo->unhighlight(); return;
} }
}
gizmo->unhighlight();
callback(0, x, y);
}); });
} }
bool Gizmo::isGizmoEntity(Entity e) {
for(int i = 0; i < 7; i++) {
if(e == _entities[i]) {
return true;
}
}
return false;
} }
void Gizmo::setVisibility(bool visible) {
if(visible) {
_scene->addEntities(_entities, 7);
} else {
_scene->removeEntities(_entities, 7);
}
}
}