Files
cup_edit/thermion_dart/native/include/scene/Gizmo.hpp
Nick Fisher ed444b0615 feature!:
This is a breaking change needed to fully implement instancing and stencil highlighting.

Previously, users would work directly with entities (on the Dart side, ThermionEntity), e.g.

final entity = await viewer.loadGlb("some.glb");

However, Filament "entities" are a lower-level abstraction.

Loading a glTF file, for example, inserts multiple entities into the scene.

For example, each mesh, light, and camera within a glTF asset will be assigned an entity. A top-level (non-renderable) entity will also be created for the glTF asset, which can be used to transform the entire hierarchy.

"Asset" is a better representation for loading/inserting objects into the scene; think of this as a bundle of entities.

Unless you need to work directly with transforms, instancing, materials and renderables, you can work directly with ThermionAsset.
2024-11-27 15:02:37 +11:00

201 lines
6.0 KiB
C++

#pragma once
#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 <filament/RenderableManager.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 "c_api/ThermionDartApi.h"
#include "scene/SceneAsset.hpp"
namespace thermion
{
using namespace filament;
using namespace utils;
class Gizmo : public SceneAsset
{
public:
Gizmo(Engine *engine, View *view, Scene *scene, Material *material);
~Gizmo() override;
enum Axis
{
X,
Y,
Z
};
enum GizmoPickResultType {
AxisX,
AxisY,
AxisZ,
Parent,
None
};
typedef void (*GizmoPickCallback)(Gizmo::GizmoPickResultType result, float x, float y, float z);
void pick(uint32_t x, uint32_t y, GizmoPickCallback callback);
bool isGizmoEntity(Entity entity);
SceneAssetType getType() override { return SceneAssetType::Gizmo; }
utils::Entity getEntity() override { return _entities[0]; }
bool isInstance() override { return false; }
SceneAsset *createInstance(MaterialInstance **materialInstances, size_t materialInstanceCount) override { return nullptr; }
MaterialInstance **getMaterialInstances() override { return _materialInstances.data(); }
size_t getMaterialInstanceCount() override { return _materialInstances.size(); }
void addAllEntities(Scene *scene) override
{
for (const auto &entity : _entities)
{
if (entity.isNull())
{
continue;
}
scene->addEntity(entity);
}
}
void removeAllEntities(Scene *scene) override
{
for (const auto &entity : _entities)
{
scene->remove(entity);
}
}
size_t getInstanceCount() override { return 0; }
SceneAsset *getInstanceByEntity(utils::Entity entity) override { return nullptr; }
SceneAsset *getInstanceAt(size_t index) override { return nullptr; }
size_t getChildEntityCount() override { return _entities.size() - 1; }
const Entity *getChildEntities() override { return _entities.data() + 1; }
Entity findEntityByName(const char *name) override
{
return utils::Entity::import(0);
}
void setPriority(RenderableManager &rm, int mask) override
{
}
void setLayer(RenderableManager &rm, int layer) override
{
}
void highlight(Gizmo::Axis axis);
void unhighlight(Gizmo::Axis axis);
private:
class PickCallbackHandler
{
public:
PickCallbackHandler(Gizmo *gizmo, GizmoPickCallback callback)
: _gizmo(gizmo), _callback(callback) {}
void handle(filament::View::PickingQueryResult const &result)
{
_gizmo->unhighlight(Gizmo::Axis::X);
_gizmo->unhighlight(Gizmo::Axis::Y);
_gizmo->unhighlight(Gizmo::Axis::Z);
Gizmo::GizmoPickResultType resultType;
if (result.renderable == _gizmo->_parent)
{
resultType = Gizmo::GizmoPickResultType::Parent;
}
else if (result.renderable == _gizmo->_x || result.renderable == _gizmo->_xHitTest)
{
resultType = Gizmo::GizmoPickResultType::AxisX;
_gizmo->highlight(Gizmo::Axis::X);
}
else if (result.renderable == _gizmo->_y || result.renderable == _gizmo->_yHitTest)
{
_gizmo->highlight(Gizmo::Axis::Y);
resultType = Gizmo::GizmoPickResultType::AxisY;
}
else if (result.renderable == _gizmo->_z || result.renderable == _gizmo->_zHitTest)
{
_gizmo->highlight(Gizmo::Axis::Z);
resultType = Gizmo::GizmoPickResultType::AxisZ;
} else {
resultType = Gizmo::GizmoPickResultType::None;
}
_callback(resultType, result.fragCoords.x, result.fragCoords.y, result.fragCoords.z);
}
private:
Gizmo *_gizmo;
GizmoPickCallback _callback;
};
Entity createParentEntity();
Entity createHitTestEntity(Gizmo::Axis axis, Entity parent);
Entity createAxisEntity(Gizmo::Axis axis, Entity parent);
math::mat4f getRotationForAxis(Gizmo::Axis axis);
Entity getEntityForAxis(Gizmo::Axis axis)
{
switch (axis)
{
case Gizmo::Axis::X:
return _x;
case Gizmo::Axis::Y:
return _y;
case Gizmo::Axis::Z:
return _z;
}
}
Engine *_engine;
Scene *_scene;
View *_view;
Material *_material;
utils::Entity _parent;
utils::Entity _x;
utils::Entity _y;
utils::Entity _z;
utils::Entity _xHitTest;
utils::Entity _yHitTest;
utils::Entity _zHitTest;
std::vector<utils::Entity> _entities;
std::vector<MaterialInstance *> _materialInstances;
math::float4 activeColors[3]{
math::float4{1.0f, 1.0f, 0.0f, 0.5f},
math::float4{1.0f, 1.0f, 0.0f, 0.5f},
math::float4{1.0f, 1.0f, 0.0f, 0.5f},
};
math::float4 inactiveColors[3]{
math::float4{1.0f, 0.0f, 0.0f, 1.0f},
math::float4{0.0f, 1.0f, 0.0f, 1.0f},
math::float4{0.0f, 0.0f, 1.0f, 1.0f},
};
};
}