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.
This commit is contained in:
172
thermion_dart/native/include/scene/AnimationManager.hpp
Normal file
172
thermion_dart/native/include/scene/AnimationManager.hpp
Normal file
@@ -0,0 +1,172 @@
|
||||
#pragma once
|
||||
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
|
||||
#include <filament/Engine.h>
|
||||
#include <filament/Scene.h>
|
||||
|
||||
#include "c_api/APIBoundaryTypes.h"
|
||||
|
||||
#include "components/CollisionComponentManager.hpp"
|
||||
#include "components/AnimationComponentManager.hpp"
|
||||
#include "GltfSceneAssetInstance.hpp"
|
||||
#include "GltfSceneAsset.hpp"
|
||||
#include "SceneAsset.hpp"
|
||||
|
||||
namespace thermion
|
||||
{
|
||||
|
||||
using namespace filament;
|
||||
using namespace filament::gltfio;
|
||||
using namespace utils;
|
||||
using std::string;
|
||||
using std::unique_ptr;
|
||||
using std::vector;
|
||||
|
||||
/// @brief
|
||||
class AnimationManager
|
||||
{
|
||||
public:
|
||||
AnimationManager(
|
||||
Engine *engine,
|
||||
Scene *scene);
|
||||
~AnimationManager();
|
||||
|
||||
void update();
|
||||
|
||||
/// @brief
|
||||
/// @param asset
|
||||
/// @param childEntity
|
||||
/// @return
|
||||
vector<string> getMorphTargetNames(GltfSceneAsset *asset, EntityId childEntity);
|
||||
|
||||
/// @brief
|
||||
/// @param instance
|
||||
/// @param skinIndex
|
||||
/// @return
|
||||
vector<Entity> getBoneEntities(GltfSceneAssetInstance *instance, int skinIndex);
|
||||
|
||||
/// @brief
|
||||
/// @param sceneAsset
|
||||
/// @param morphData
|
||||
/// @param morphIndices
|
||||
/// @param numMorphTargets
|
||||
/// @param numFrames
|
||||
/// @param frameLengthInMs
|
||||
/// @return
|
||||
bool setMorphAnimationBuffer(
|
||||
utils::Entity entity,
|
||||
const float *const morphData,
|
||||
const uint32_t *const morphIndices,
|
||||
int numMorphTargets,
|
||||
int numFrames,
|
||||
float frameLengthInMs);
|
||||
|
||||
/// @brief
|
||||
/// @param entityId
|
||||
void clearMorphAnimationBuffer(
|
||||
utils::Entity entity);
|
||||
|
||||
/// @brief
|
||||
/// @param instance
|
||||
/// @param skinIndex
|
||||
/// @param boneIndex
|
||||
/// @return
|
||||
math::mat4f getInverseBindMatrix(GltfSceneAssetInstance *instance, int skinIndex, int boneIndex);
|
||||
|
||||
/// @brief Set the local transform for the bone at boneIndex/skinIndex in the given entity.
|
||||
/// @param entityId the parent entity
|
||||
/// @param entityName the name of the mesh under entityId for which the bone will be set.
|
||||
/// @param skinIndex the index of the joint skin. Currently only 0 is supported.
|
||||
/// @param boneName the name of the bone
|
||||
/// @param transform the 4x4 matrix representing the local transform for the bone
|
||||
/// @return true if the transform was successfully set, false otherwise
|
||||
bool setBoneTransform(GltfSceneAssetInstance *instance, int skinIndex, int boneIndex, math::mat4f transform);
|
||||
|
||||
/// @brief Immediately start animating the bone at [boneIndex] under the parent instance [entity] at skin [skinIndex].
|
||||
/// @param entity the mesh entity to animate
|
||||
/// @param frameData frame data as quaternions
|
||||
/// @param numFrames the number of frames
|
||||
/// @param boneName the name of the bone to animate
|
||||
/// @param frameLengthInMs the length of each frame in ms
|
||||
/// @return true if the bone animation was successfully enqueued
|
||||
bool addBoneAnimation(
|
||||
GltfSceneAssetInstance *instance,
|
||||
int skinIndex,
|
||||
int boneIndex,
|
||||
const float *const frameData,
|
||||
int numFrames,
|
||||
float frameLengthInMs,
|
||||
float fadeOutInSecs,
|
||||
float fadeInInSecs,
|
||||
float maxDelta);
|
||||
|
||||
/// @brief
|
||||
/// @param instance
|
||||
/// @param skinIndex
|
||||
/// @return
|
||||
std::vector<math::mat4f> getBoneRestTranforms(GltfSceneAssetInstance *instance, int skinIndex);
|
||||
|
||||
/// @brief
|
||||
/// @param instance
|
||||
void resetToRestPose(GltfSceneAssetInstance *instance);
|
||||
|
||||
/// @brief
|
||||
/// @param instance
|
||||
void updateBoneMatrices(GltfSceneAssetInstance *instance);
|
||||
|
||||
/// @brief
|
||||
/// @param instance
|
||||
/// @param animationIndex
|
||||
/// @param loop
|
||||
/// @param reverse
|
||||
/// @param replaceActive
|
||||
/// @param crossfade
|
||||
/// @param startOffset
|
||||
void playGltfAnimation(GltfSceneAssetInstance *instance, int animationIndex, bool loop, bool reverse, bool replaceActive, float crossfade = 0.3f, float startOffset = 0.0f);
|
||||
|
||||
/// @brief
|
||||
/// @param instance
|
||||
/// @param animationIndex
|
||||
void stopGltfAnimation(GltfSceneAssetInstance *instance, int animationIndex);
|
||||
|
||||
/// @brief
|
||||
/// @param instance
|
||||
/// @param weights
|
||||
/// @param count
|
||||
void setMorphTargetWeights(utils::Entity entity, const float *const weights, int count);
|
||||
|
||||
/// @brief
|
||||
/// @param instance
|
||||
/// @param animationIndex
|
||||
/// @param animationFrame
|
||||
void setGltfAnimationFrame(GltfSceneAssetInstance *instance, int animationIndex, int animationFrame);
|
||||
|
||||
/// @brief
|
||||
/// @param instance
|
||||
/// @return
|
||||
vector<string> getGltfAnimationNames(GltfSceneAssetInstance *instance);
|
||||
|
||||
/// @brief
|
||||
/// @param instance
|
||||
/// @param animationIndex
|
||||
/// @return
|
||||
float getGltfAnimationDuration(GltfSceneAssetInstance *instance, int animationIndex);
|
||||
|
||||
/// @brief
|
||||
/// @param entity
|
||||
/// @return
|
||||
bool addAnimationComponent(EntityId entity);
|
||||
|
||||
/// @brief
|
||||
/// @param entity
|
||||
void removeAnimationComponent(EntityId entity);
|
||||
|
||||
private:
|
||||
Engine *_engine = nullptr;
|
||||
Scene *_scene = nullptr;
|
||||
std::mutex _mutex;
|
||||
std::unique_ptr<AnimationComponentManager> _animationComponentManager = std::nullptr_t();
|
||||
};
|
||||
}
|
||||
63
thermion_dart/native/include/scene/CustomGeometry.hpp
Normal file
63
thermion_dart/native/include/scene/CustomGeometry.hpp
Normal file
@@ -0,0 +1,63 @@
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include <filament/Engine.h>
|
||||
#include <filament/Frustum.h>
|
||||
#include <filament/VertexBuffer.h>
|
||||
#include <filament/IndexBuffer.h>
|
||||
#include <filament/TransformManager.h>
|
||||
#include <filament/Texture.h>
|
||||
#include <filament/RenderableManager.h>
|
||||
#include <filament/Viewport.h>
|
||||
|
||||
#include <utils/Entity.h>
|
||||
#include <utils/EntityManager.h>
|
||||
|
||||
namespace thermion
|
||||
{
|
||||
|
||||
using namespace filament;
|
||||
|
||||
class CustomGeometry {
|
||||
public:
|
||||
CustomGeometry(
|
||||
float* vertices,
|
||||
uint32_t numVertices,
|
||||
float* normals,
|
||||
uint32_t numNormals,
|
||||
float *uvs,
|
||||
uint32_t numUvs,
|
||||
uint16_t* indices,
|
||||
uint32_t numIndices,
|
||||
MaterialInstance* materialInstance,
|
||||
RenderableManager::PrimitiveType primitiveType,
|
||||
Engine* engine);
|
||||
~CustomGeometry();
|
||||
|
||||
utils::Entity createInstance(MaterialInstance *materialInstance);
|
||||
|
||||
private:
|
||||
Engine* _engine;
|
||||
|
||||
MaterialInstance* _materialInstance = nullptr;
|
||||
|
||||
VertexBuffer* vertexBuffer;
|
||||
IndexBuffer* indexBuffer;
|
||||
|
||||
float* vertices = nullptr;
|
||||
float* normals = nullptr;
|
||||
float *uvs = nullptr;
|
||||
uint32_t numVertices = 0;
|
||||
uint16_t* indices = 0;
|
||||
uint32_t numIndices = 0;
|
||||
Box boundingBox;
|
||||
RenderableManager::PrimitiveType primitiveType;
|
||||
|
||||
void computeBoundingBox();
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
}
|
||||
143
thermion_dart/native/include/scene/GeometrySceneAsset.hpp
Normal file
143
thermion_dart/native/include/scene/GeometrySceneAsset.hpp
Normal file
@@ -0,0 +1,143 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <filament/Engine.h>
|
||||
#include <filament/RenderableManager.h>
|
||||
#include <filament/VertexBuffer.h>
|
||||
#include <filament/IndexBuffer.h>
|
||||
#include <gltfio/MaterialProvider.h>
|
||||
#include "scene/SceneAsset.hpp"
|
||||
|
||||
namespace thermion
|
||||
{
|
||||
|
||||
using namespace filament;
|
||||
|
||||
class GeometrySceneAsset : public SceneAsset
|
||||
{
|
||||
public:
|
||||
GeometrySceneAsset(bool isInstance,
|
||||
Engine *engine,
|
||||
VertexBuffer *vertexBuffer,
|
||||
IndexBuffer *indexBuffer,
|
||||
MaterialInstance **materialInstances,
|
||||
size_t materialInstanceCount,
|
||||
RenderableManager::PrimitiveType primitiveType,
|
||||
Box boundingBox);
|
||||
~GeometrySceneAsset();
|
||||
|
||||
SceneAsset *createInstance(MaterialInstance **materialInstances = nullptr, size_t materialInstanceCount = 0) override;
|
||||
|
||||
SceneAssetType getType() override
|
||||
{
|
||||
return SceneAsset::SceneAssetType::Geometry;
|
||||
}
|
||||
|
||||
bool isInstance() override
|
||||
{
|
||||
return _isInstance;
|
||||
}
|
||||
|
||||
utils::Entity getEntity() override
|
||||
{
|
||||
return _entity;
|
||||
}
|
||||
|
||||
MaterialInstance **getMaterialInstances() override
|
||||
{
|
||||
return _materialInstances;
|
||||
}
|
||||
|
||||
size_t getMaterialInstanceCount() override
|
||||
{
|
||||
return _materialInstanceCount;
|
||||
}
|
||||
|
||||
const Box &getBoundingBox() const { return _boundingBox; }
|
||||
VertexBuffer *getVertexBuffer() const { return _vertexBuffer; }
|
||||
IndexBuffer *getIndexBuffer() const { return _indexBuffer; }
|
||||
|
||||
void addAllEntities(Scene *scene) override
|
||||
{
|
||||
scene->addEntity(_entity);
|
||||
}
|
||||
|
||||
void removeAllEntities(Scene *scene) override
|
||||
{
|
||||
scene->remove(_entity);
|
||||
}
|
||||
|
||||
void setPriority(RenderableManager &rm, int priority) override
|
||||
{
|
||||
auto renderableInstance = rm.getInstance(_entity);
|
||||
rm.setPriority(renderableInstance, priority);
|
||||
}
|
||||
|
||||
void setLayer(RenderableManager &rm, int layer) override
|
||||
{
|
||||
auto renderableInstance = rm.getInstance(_entity);
|
||||
rm.setLayerMask(renderableInstance, 0xFF, 1u << (uint8_t)layer);
|
||||
}
|
||||
|
||||
SceneAsset *getInstanceByEntity(utils::Entity entity) override
|
||||
{
|
||||
for (auto &instance : _instances)
|
||||
{
|
||||
if (instance->getEntity() == entity)
|
||||
{
|
||||
return instance.get();
|
||||
}
|
||||
}
|
||||
return std::nullptr_t();
|
||||
}
|
||||
|
||||
SceneAsset *getInstanceAt(size_t index) override
|
||||
{
|
||||
auto &asset = _instances[index];
|
||||
return asset.get();
|
||||
}
|
||||
|
||||
size_t getInstanceCount() override
|
||||
{
|
||||
return _instances.size();
|
||||
}
|
||||
|
||||
size_t getChildEntityCount() override
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
const Entity *getChildEntities() override
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Entity findEntityByName(const char *name) override
|
||||
{
|
||||
return Entity(); // not currently implemented
|
||||
}
|
||||
|
||||
static std::unique_ptr<GeometrySceneAsset> create(
|
||||
float *vertices, uint32_t numVertices,
|
||||
float *normals, uint32_t numNormals,
|
||||
float *uvs, uint32_t numUvs,
|
||||
uint16_t *indices, uint32_t numIndices,
|
||||
MaterialInstance *materialInstance,
|
||||
RenderableManager::PrimitiveType primitiveType,
|
||||
Engine *engine);
|
||||
|
||||
private:
|
||||
Engine *_engine = nullptr;
|
||||
VertexBuffer *_vertexBuffer = nullptr;
|
||||
IndexBuffer *_indexBuffer = nullptr;
|
||||
MaterialInstance **_materialInstances = nullptr;
|
||||
size_t _materialInstanceCount = 0;
|
||||
Box _boundingBox;
|
||||
bool _isInstance = false;
|
||||
utils::Entity _entity;
|
||||
RenderableManager::PrimitiveType _primitiveType;
|
||||
std::vector<std::unique_ptr<GeometrySceneAsset>> _instances;
|
||||
|
||||
};
|
||||
|
||||
} // namespace thermion
|
||||
308
thermion_dart/native/include/scene/GeometrySceneAssetBuilder.hpp
Normal file
308
thermion_dart/native/include/scene/GeometrySceneAssetBuilder.hpp
Normal file
@@ -0,0 +1,308 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <filament/Engine.h>
|
||||
#include <filament/RenderableManager.h>
|
||||
#include <filament/VertexBuffer.h>
|
||||
#include <filament/IndexBuffer.h>
|
||||
#include <filament/geometry/SurfaceOrientation.h>
|
||||
#include <filament/Box.h>
|
||||
#include <gltfio/MaterialProvider.h>
|
||||
#include "GeometrySceneAsset.hpp"
|
||||
#include "Log.hpp"
|
||||
|
||||
namespace thermion
|
||||
{
|
||||
class GeometrySceneAssetBuilder
|
||||
{
|
||||
public:
|
||||
GeometrySceneAssetBuilder(filament::Engine *engine) : mEngine(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<GeometrySceneAsset> 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<GeometrySceneAsset>(
|
||||
false,
|
||||
mEngine,
|
||||
vertexBuffer,
|
||||
indexBuffer,
|
||||
mMaterialInstances,
|
||||
mMaterialInstanceCount,
|
||||
mPrimitiveType,
|
||||
boundingBox);
|
||||
|
||||
Log("Asset created: %p", asset.get());
|
||||
return asset;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
std::pair<filament::VertexBuffer *, filament::IndexBuffer *> 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<std::vector<float> *>(data);
|
||||
},
|
||||
mIndices));
|
||||
|
||||
if (mUVs->empty())
|
||||
{
|
||||
mUVs->resize(mNumVertices);
|
||||
std::fill(mUVs->begin(), mUVs->end(), 0.0f);
|
||||
}
|
||||
|
||||
auto dummyColors = new std::vector<filament::math::float4>(
|
||||
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<std::vector<float> *>(data);
|
||||
|
||||
},
|
||||
mUVs));
|
||||
|
||||
vertexBuffer->setBufferAt(*mEngine, 3,
|
||||
VertexBuffer::BufferDescriptor(
|
||||
dummyColors->data(), dummyColors->size() * sizeof(math::float4),
|
||||
[](void *, size_t, void *data)
|
||||
{
|
||||
delete static_cast<std::vector<math::float4> *>(data);
|
||||
},
|
||||
dummyColors));
|
||||
|
||||
if (!mNormals->empty())
|
||||
{
|
||||
assert(mPrimitiveType == RenderableManager::PrimitiveType::TRIANGLES);
|
||||
|
||||
std::vector<filament::math::ushort3> 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<filament::math::quatf>(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<std::vector<math::quatf> *>(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;
|
||||
}
|
||||
|
||||
filament::Engine *mEngine = nullptr;
|
||||
std::vector<float> *mVertices = new std::vector<float>();
|
||||
std::vector<float> *mNormals = new std::vector<float>();
|
||||
std::vector<float> *mUVs = new std::vector<float>();
|
||||
std::vector<uint16_t> *mIndices = new std::vector<uint16_t>;
|
||||
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;
|
||||
filament::RenderableManager::PrimitiveType mPrimitiveType =
|
||||
filament::RenderableManager::PrimitiveType::TRIANGLES;
|
||||
};
|
||||
|
||||
} // namespace thermion
|
||||
201
thermion_dart/native/include/scene/Gizmo.hpp
Normal file
201
thermion_dart/native/include/scene/Gizmo.hpp
Normal file
@@ -0,0 +1,201 @@
|
||||
#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},
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
163
thermion_dart/native/include/scene/GltfSceneAsset.hpp
Normal file
163
thermion_dart/native/include/scene/GltfSceneAsset.hpp
Normal file
@@ -0,0 +1,163 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include <filament/Engine.h>
|
||||
#include <filament/RenderableManager.h>
|
||||
#include <filament/VertexBuffer.h>
|
||||
#include <filament/IndexBuffer.h>
|
||||
#include <gltfio/AssetLoader.h>
|
||||
#include <gltfio/FilamentAsset.h>
|
||||
#include <gltfio/MaterialProvider.h>
|
||||
|
||||
#include "scene/GltfSceneAssetInstance.hpp"
|
||||
#include "components/AnimationComponentManager.hpp"
|
||||
#include "components/CollisionComponentManager.hpp"
|
||||
|
||||
#include "scene/SceneAsset.hpp"
|
||||
|
||||
namespace thermion
|
||||
{
|
||||
|
||||
using namespace filament;
|
||||
|
||||
class GltfSceneAsset : public SceneAsset
|
||||
{
|
||||
public:
|
||||
GltfSceneAsset(
|
||||
gltfio::FilamentAsset *asset,
|
||||
gltfio::AssetLoader *assetLoader,
|
||||
Engine *engine,
|
||||
MaterialInstance **materialInstances = nullptr,
|
||||
size_t materialInstanceCount = 0,
|
||||
int instanceIndex = -1) : _asset(asset),
|
||||
_assetLoader(assetLoader),
|
||||
_engine(engine),
|
||||
_materialInstances(materialInstances),
|
||||
_materialInstanceCount(materialInstanceCount)
|
||||
{
|
||||
}
|
||||
|
||||
~GltfSceneAsset();
|
||||
|
||||
SceneAsset *createInstance(MaterialInstance **materialInstances = nullptr, size_t materialInstanceCount = 0) override;
|
||||
|
||||
SceneAssetType getType() override
|
||||
{
|
||||
return SceneAsset::SceneAssetType::Gltf;
|
||||
}
|
||||
|
||||
bool isInstance() override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
utils::Entity getEntity() override
|
||||
{
|
||||
return _asset->getRoot();
|
||||
}
|
||||
|
||||
MaterialInstance **getMaterialInstances() override
|
||||
{
|
||||
return _materialInstances;
|
||||
}
|
||||
|
||||
size_t getMaterialInstanceCount() override
|
||||
{
|
||||
return _materialInstanceCount;
|
||||
}
|
||||
|
||||
gltfio::FilamentAsset *getAsset()
|
||||
{
|
||||
return _asset;
|
||||
}
|
||||
|
||||
void addAllEntities(Scene *scene) override
|
||||
{
|
||||
scene->addEntities(_asset->getEntities(), _asset->getEntityCount());
|
||||
scene->addEntities(_asset->getLightEntities(), _asset->getLightEntityCount());
|
||||
scene->addEntities(_asset->getCameraEntities(), _asset->getCameraEntityCount());
|
||||
}
|
||||
|
||||
void removeAllEntities(Scene *scene) override
|
||||
{
|
||||
scene->removeEntities(_asset->getEntities(), _asset->getEntityCount());
|
||||
scene->removeEntities(_asset->getLightEntities(), _asset->getLightEntityCount());
|
||||
scene->removeEntities(_asset->getCameraEntities(), _asset->getCameraEntityCount());
|
||||
}
|
||||
|
||||
void setPriority(RenderableManager &rm, int priority) override
|
||||
{
|
||||
const Entity *entities = _asset->getEntities();
|
||||
for (int i = 0; i < _asset->getEntityCount(); i++)
|
||||
{
|
||||
if (rm.hasComponent(entities[i]))
|
||||
{
|
||||
auto renderableInstance = rm.getInstance(entities[i]);
|
||||
rm.setPriority(renderableInstance, priority);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void setLayer(RenderableManager &rm, int layer) override
|
||||
{
|
||||
const Entity *entities = _asset->getEntities();
|
||||
for (int i = 0; i < _asset->getEntityCount(); i++)
|
||||
{
|
||||
if (rm.hasComponent(entities[i]))
|
||||
{
|
||||
auto renderableInstance = rm.getInstance(entities[i]);
|
||||
rm.setLayerMask(renderableInstance, 0xFF, 1u << (uint8_t)layer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SceneAsset *getInstanceByEntity(utils::Entity entity) override
|
||||
{
|
||||
for (auto &instance : _instances)
|
||||
{
|
||||
if (instance->getEntity() == entity)
|
||||
{
|
||||
return instance.get();
|
||||
}
|
||||
}
|
||||
return std::nullptr_t();
|
||||
}
|
||||
|
||||
SceneAsset *getInstanceAt(size_t index) override
|
||||
{
|
||||
auto &asset = _instances[index];
|
||||
return asset.get();
|
||||
}
|
||||
|
||||
size_t getInstanceCount() override
|
||||
{
|
||||
return _instances.size();
|
||||
}
|
||||
|
||||
size_t getChildEntityCount() override
|
||||
{
|
||||
return _asset->getEntityCount();
|
||||
}
|
||||
|
||||
const Entity* getChildEntities() override {
|
||||
return _asset->getEntities();
|
||||
}
|
||||
|
||||
Entity findEntityByName(const char* name) override {
|
||||
Entity entities[1];
|
||||
auto found = _asset->getEntitiesByName(name, entities, 1);
|
||||
return entities[0];
|
||||
}
|
||||
|
||||
private:
|
||||
gltfio::FilamentAsset *_asset;
|
||||
gltfio::AssetLoader *_assetLoader;
|
||||
Engine *_engine;
|
||||
MaterialInstance **_materialInstances = nullptr;
|
||||
size_t _materialInstanceCount = 0;
|
||||
std::vector<std::unique_ptr<GltfSceneAssetInstance>> _instances;
|
||||
};
|
||||
|
||||
} // namespace thermion
|
||||
143
thermion_dart/native/include/scene/GltfSceneAssetInstance.hpp
Normal file
143
thermion_dart/native/include/scene/GltfSceneAssetInstance.hpp
Normal file
@@ -0,0 +1,143 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include <filament/Engine.h>
|
||||
#include <filament/RenderableManager.h>
|
||||
#include <filament/VertexBuffer.h>
|
||||
#include <filament/IndexBuffer.h>
|
||||
#include <gltfio/FilamentAsset.h>
|
||||
#include <gltfio/FilamentInstance.h>
|
||||
#include <gltfio/MaterialProvider.h>
|
||||
|
||||
#include "scene/SceneAsset.hpp"
|
||||
|
||||
namespace thermion
|
||||
{
|
||||
|
||||
using namespace filament;
|
||||
|
||||
class GltfSceneAssetInstance : public SceneAsset
|
||||
{
|
||||
public:
|
||||
GltfSceneAssetInstance(
|
||||
gltfio::FilamentInstance *instance,
|
||||
Engine *engine,
|
||||
MaterialInstance **materialInstances = nullptr,
|
||||
size_t materialInstanceCount = 0,
|
||||
int instanceIndex = -1) : _instance(instance),
|
||||
_materialInstances(materialInstances),
|
||||
_materialInstanceCount(materialInstanceCount)
|
||||
{
|
||||
}
|
||||
|
||||
~GltfSceneAssetInstance();
|
||||
|
||||
SceneAsset *createInstance(MaterialInstance **materialInstances = nullptr, size_t materialInstanceCount = 0) override
|
||||
{
|
||||
return std::nullptr_t();
|
||||
};
|
||||
|
||||
SceneAssetType getType() override
|
||||
{
|
||||
return SceneAsset::SceneAssetType::Gltf;
|
||||
}
|
||||
|
||||
bool isInstance() override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
utils::Entity getEntity() override
|
||||
{
|
||||
return _instance->getRoot();
|
||||
}
|
||||
|
||||
MaterialInstance **getMaterialInstances() override
|
||||
{
|
||||
return _materialInstances;
|
||||
}
|
||||
|
||||
size_t getMaterialInstanceCount() override
|
||||
{
|
||||
return _materialInstanceCount;
|
||||
}
|
||||
|
||||
gltfio::FilamentInstance *getInstance()
|
||||
{
|
||||
return _instance;
|
||||
}
|
||||
|
||||
void addAllEntities(Scene *scene) override
|
||||
{
|
||||
scene->addEntities(_instance->getEntities(), _instance->getEntityCount());
|
||||
}
|
||||
|
||||
void removeAllEntities(Scene *scene) override {
|
||||
scene->removeEntities(_instance->getEntities(), _instance->getEntityCount());
|
||||
}
|
||||
|
||||
size_t getInstanceCount() override
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
SceneAsset *getInstanceAt(size_t index) override
|
||||
{
|
||||
return std::nullptr_t();
|
||||
}
|
||||
|
||||
size_t getChildEntityCount() override
|
||||
{
|
||||
return _instance->getEntityCount();
|
||||
}
|
||||
|
||||
const Entity* getChildEntities() override {
|
||||
return _instance->getEntities();
|
||||
}
|
||||
|
||||
Entity findEntityByName(const char* name) override {
|
||||
return Entity(); // not currently implemented
|
||||
}
|
||||
|
||||
SceneAsset *getInstanceByEntity(utils::Entity entity) override {
|
||||
return std::nullptr_t();
|
||||
}
|
||||
|
||||
void setPriority(RenderableManager &rm, int priority) override
|
||||
{
|
||||
const Entity *entities = _instance->getEntities();
|
||||
for (int i = 0; i < _instance->getEntityCount(); i++)
|
||||
{
|
||||
if (rm.hasComponent(entities[i]))
|
||||
{
|
||||
auto renderableInstance = rm.getInstance(entities[i]);
|
||||
rm.setPriority(renderableInstance, priority);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void setLayer(RenderableManager &rm, int layer) override
|
||||
{
|
||||
const Entity *entities = _instance->getEntities();
|
||||
for (int i = 0; i < _instance->getEntityCount(); i++)
|
||||
{
|
||||
if (rm.hasComponent(entities[i]))
|
||||
{
|
||||
auto renderableInstance = rm.getInstance(entities[i]);
|
||||
rm.setLayerMask(renderableInstance, 0xFF, 1u << (uint8_t)layer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private:
|
||||
filament::Engine *_engine;
|
||||
gltfio::FilamentInstance *_instance;
|
||||
MaterialInstance **_materialInstances = nullptr;
|
||||
size_t _materialInstanceCount = 0;
|
||||
};
|
||||
|
||||
} // namespace thermion
|
||||
49
thermion_dart/native/include/scene/GridOverlay.hpp
Normal file
49
thermion_dart/native/include/scene/GridOverlay.hpp
Normal file
@@ -0,0 +1,49 @@
|
||||
#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>
|
||||
|
||||
namespace thermion {
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
}
|
||||
53
thermion_dart/native/include/scene/SceneAsset.hpp
Normal file
53
thermion_dart/native/include/scene/SceneAsset.hpp
Normal file
@@ -0,0 +1,53 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <utils/Entity.h>
|
||||
#include <gltfio/FilamentAsset.h>
|
||||
#include <filament/Scene.h>
|
||||
|
||||
#include "CustomGeometry.hpp"
|
||||
#include "Log.hpp"
|
||||
|
||||
namespace thermion {
|
||||
|
||||
using namespace filament;
|
||||
using namespace utils;
|
||||
|
||||
class SceneAsset {
|
||||
|
||||
public:
|
||||
enum SceneAssetType { Gltf, Geometry, Light, Skybox, Ibl, Image, Gizmo };
|
||||
|
||||
virtual ~SceneAsset() {
|
||||
|
||||
}
|
||||
virtual SceneAssetType getType() = 0;
|
||||
|
||||
virtual utils::Entity getEntity() {
|
||||
return utils::Entity::import(0);
|
||||
}
|
||||
|
||||
virtual bool isInstance() = 0;
|
||||
|
||||
virtual SceneAsset* createInstance(MaterialInstance **materialInstances, size_t materialInstanceCount) = 0;
|
||||
|
||||
virtual MaterialInstance **getMaterialInstances() = 0;
|
||||
virtual size_t getMaterialInstanceCount() = 0;
|
||||
virtual void addAllEntities(Scene *scene) = 0;
|
||||
virtual void removeAllEntities(Scene *scene) = 0;
|
||||
|
||||
virtual size_t getInstanceCount() = 0;
|
||||
virtual SceneAsset *getInstanceByEntity(utils::Entity entity) = 0;
|
||||
virtual SceneAsset *getInstanceAt(size_t index) = 0;
|
||||
virtual size_t getChildEntityCount() = 0;
|
||||
virtual const Entity* getChildEntities() = 0;
|
||||
virtual Entity findEntityByName(const char* name) = 0;
|
||||
|
||||
virtual void setPriority(RenderableManager& rm, int mask) = 0;
|
||||
virtual void setLayer(RenderableManager& rm, int layer) = 0;
|
||||
|
||||
|
||||
|
||||
};
|
||||
}
|
||||
350
thermion_dart/native/include/scene/SceneManager.hpp
Normal file
350
thermion_dart/native/include/scene/SceneManager.hpp
Normal file
@@ -0,0 +1,350 @@
|
||||
#pragma once
|
||||
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
#include <filament/Scene.h>
|
||||
#include <filament/Camera.h>
|
||||
#include <filament/View.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 <utils/NameComponentManager.h>
|
||||
|
||||
#include "tsl/robin_map.h"
|
||||
|
||||
#include "AnimationManager.hpp"
|
||||
#include "CustomGeometry.hpp"
|
||||
#include "Gizmo.hpp"
|
||||
#include "GridOverlay.hpp"
|
||||
#include "ResourceBuffer.hpp"
|
||||
#include "SceneAsset.hpp"
|
||||
|
||||
#include "components/CollisionComponentManager.hpp"
|
||||
|
||||
namespace thermion
|
||||
{
|
||||
|
||||
typedef int32_t EntityId;
|
||||
|
||||
using namespace filament;
|
||||
using namespace filament::gltfio;
|
||||
using namespace utils;
|
||||
using std::string;
|
||||
using std::unique_ptr;
|
||||
using std::vector;
|
||||
|
||||
class SceneManager
|
||||
{
|
||||
public:
|
||||
SceneManager(
|
||||
const ResourceLoaderWrapperImpl *const loader,
|
||||
Engine *engine,
|
||||
Scene *scene,
|
||||
const char *uberArchivePath,
|
||||
Camera *mainCamera);
|
||||
~SceneManager();
|
||||
|
||||
enum LAYERS
|
||||
{
|
||||
DEFAULT_ASSETS = 0,
|
||||
BACKGROUND = 6,
|
||||
OVERLAY = 7,
|
||||
};
|
||||
|
||||
////
|
||||
/// @brief Load the glTF file from the specified path and adds all entities to the scene.
|
||||
/// @param uri the path to the asset. Should be either asset:// (representing a Flutter asset), or file:// (representing a filesystem file).
|
||||
/// @param relativeResourcePath the (relative) path to the asset's resources.
|
||||
/// @return the glTF entity.
|
||||
///
|
||||
SceneAsset* loadGltf(const char *uri, const char *relativeResourcePath, int numInstances = 1, bool keepData = false);
|
||||
|
||||
////
|
||||
/// @brief Load the GLB from the specified path, optionally creating multiple instances.
|
||||
/// @param uri the path to the asset. Should be either asset:// (representing a Flutter asset), or file:// (representing a filesystem file).
|
||||
/// @param numInstances the number of instances to create. Must be at least 1.
|
||||
/// @return an Entity representing the FilamentAsset associated with the loaded FilamentAsset.
|
||||
///
|
||||
SceneAsset* loadGlb(const char *uri, int numInstances, bool keepData);
|
||||
|
||||
/// @brief
|
||||
/// @param data
|
||||
/// @param length
|
||||
/// @param numInstances
|
||||
/// @param keepData
|
||||
/// @param priority
|
||||
/// @param layer
|
||||
/// @param loadResourcesAsync
|
||||
/// @return
|
||||
SceneAsset* loadGlbFromBuffer(const uint8_t *data, size_t length, int numInstances = 1, bool keepData = false, int priority = 4, int layer = 0, bool loadResourcesAsync = false);
|
||||
|
||||
///
|
||||
/// Creates an instance of the given entity.
|
||||
/// This may return an instance from a pool of inactive instances; see [remove] for more information.
|
||||
/// If [materialInstances] is provided, these wil
|
||||
///
|
||||
SceneAsset* createInstance(SceneAsset* asset, MaterialInstance **materialInstances = nullptr, size_t materialInstanceCount = 0);
|
||||
|
||||
/// @brief Removes the asset (and all its child entities) from the scene and "destroys" all resources.
|
||||
/// If the asset is not an instance, the asset will be deleted.
|
||||
/// If the asset is an instance, [remove] is not guaranted to delete the asset. It may be returned to a pool of inactive instances.
|
||||
/// From the user's perspective, this can be considered as destroyed.
|
||||
/// @param entity
|
||||
void destroy(SceneAsset* entity);
|
||||
|
||||
/// @brief Destroys all assets, scenes, materials, etc.
|
||||
///
|
||||
void destroyAll();
|
||||
|
||||
/// @brief
|
||||
/// @param entityId
|
||||
void transformToUnitCube(EntityId entityId);
|
||||
|
||||
/// @brief
|
||||
/// @param entities
|
||||
/// @param transforms
|
||||
/// @param numEntities
|
||||
void queueTransformUpdates(EntityId *entities, math::mat4 *transforms, int numEntities);
|
||||
|
||||
/// @brief
|
||||
/// @param entity
|
||||
/// @param viewportCoordX
|
||||
/// @param viewportCoordY
|
||||
/// @param x
|
||||
/// @param y
|
||||
/// @param z
|
||||
void queueRelativePositionUpdateWorldAxis(EntityId entity, float viewportCoordX, float viewportCoordY, float x, float y, float z);
|
||||
|
||||
/// @brief
|
||||
/// @param view
|
||||
/// @param entityId
|
||||
/// @param viewportCoordX
|
||||
/// @param viewportCoordY
|
||||
void queueRelativePositionUpdateFromViewportVector(View *view, EntityId entityId, float viewportCoordX, float viewportCoordY);
|
||||
|
||||
const utils::Entity *getCameraEntities(EntityId e);
|
||||
size_t getCameraEntityCount(EntityId e);
|
||||
const utils::Entity *getLightEntities(EntityId e) noexcept;
|
||||
size_t getLightEntityCount(EntityId e) noexcept;
|
||||
|
||||
/// @brief
|
||||
void update();
|
||||
|
||||
|
||||
/// @brief
|
||||
/// @param data
|
||||
/// @param length
|
||||
/// @param name
|
||||
/// @return
|
||||
Texture *createTexture(const uint8_t *data, size_t length, const char *name);
|
||||
|
||||
/// @brief
|
||||
/// @param entityId
|
||||
/// @param texture
|
||||
/// @param slotName
|
||||
/// @param materialIndex
|
||||
/// @return
|
||||
bool applyTexture(EntityId entityId, Texture *texture, const char *slotName, int materialIndex);
|
||||
|
||||
/// @brief
|
||||
/// @param texture
|
||||
void destroyTexture(Texture *texture);
|
||||
|
||||
/// @brief
|
||||
/// @param entity
|
||||
/// @return
|
||||
bool removeFromScene(EntityId entity);
|
||||
|
||||
/// @brief
|
||||
/// @param entity
|
||||
/// @return
|
||||
bool addToScene(EntityId entity);
|
||||
|
||||
/// @brief
|
||||
/// @param entity
|
||||
/// @param onCollisionCallback
|
||||
/// @param affectsCollidingTransform
|
||||
void addCollisionComponent(EntityId entity, void (*onCollisionCallback)(const EntityId entityId1, const EntityId entityId2), bool affectsCollidingTransform);
|
||||
|
||||
/// @brief
|
||||
/// @param entityId
|
||||
///
|
||||
///
|
||||
void removeCollisionComponent(EntityId entityId);
|
||||
|
||||
/// @brief
|
||||
/// @param entity
|
||||
void testCollisions(EntityId entity);
|
||||
|
||||
/// @brief returns the number of instances of the FilamentAsset represented by the given entity.
|
||||
/// @param entityId
|
||||
/// @return the number of instances
|
||||
int getInstanceCount(EntityId entityId);
|
||||
|
||||
/// @brief returns an array containing all instances of the FilamentAsset represented by the given entity.
|
||||
/// @param entityId
|
||||
void getInstances(EntityId entityId, EntityId *out);
|
||||
|
||||
///
|
||||
/// Sets the draw priority for the given entity. See RenderableManager.h for more details.
|
||||
///
|
||||
void setPriority(EntityId entity, int priority);
|
||||
|
||||
/// @brief returns the 2D min/max viewport coordinates of the bounding box for the specified enitty;
|
||||
/// @param out a pointer large enough to store four floats (the min/max coordinates of the bounding box)
|
||||
/// @return
|
||||
///
|
||||
Aabb2 getScreenSpaceBoundingBox(View *view, EntityId entity);
|
||||
|
||||
/// @brief returns the 3D bounding box of the renderable instance for the given entity.
|
||||
/// @return the bounding box
|
||||
///
|
||||
Aabb3 getRenderableBoundingBox(EntityId entity);
|
||||
|
||||
///
|
||||
/// Creates an entity with the specified geometry/material/normals and adds to the scene.
|
||||
/// If [keepData] is true, stores
|
||||
///
|
||||
SceneAsset *createGeometry(
|
||||
float *vertices,
|
||||
uint32_t numVertices,
|
||||
float *normals,
|
||||
uint32_t numNormals,
|
||||
float *uvs,
|
||||
uint32_t numUvs,
|
||||
uint16_t *indices,
|
||||
uint32_t numIndices,
|
||||
filament::RenderableManager::PrimitiveType primitiveType = RenderableManager::PrimitiveType::TRIANGLES,
|
||||
MaterialInstance **materialInstances = nullptr,
|
||||
size_t materialInstanceCount = 0,
|
||||
bool keepData = false);
|
||||
|
||||
|
||||
gltfio::MaterialProvider *const getUnlitMaterialProvider()
|
||||
{
|
||||
return _unlitMaterialProvider;
|
||||
}
|
||||
|
||||
gltfio::MaterialProvider *const getUbershaderMaterialProvider()
|
||||
{
|
||||
return _ubershaderProvider;
|
||||
}
|
||||
|
||||
/// @brief
|
||||
/// @param materialInstance
|
||||
void destroy(MaterialInstance *materialInstance);
|
||||
|
||||
/// @brief
|
||||
/// @return
|
||||
MaterialInstance *createUnlitFixedSizeMaterialInstance();
|
||||
|
||||
/// @brief
|
||||
/// @return
|
||||
MaterialInstance *createUnlitMaterialInstance();
|
||||
|
||||
/// @brief
|
||||
/// @param entityId
|
||||
/// @param layer
|
||||
void setVisibilityLayer(EntityId entityId, int layer);
|
||||
|
||||
/// @brief
|
||||
/// @return
|
||||
Camera *createCamera();
|
||||
|
||||
/// @brief
|
||||
/// @param camera
|
||||
void destroyCamera(Camera *camera);
|
||||
|
||||
/// @brief
|
||||
/// @return
|
||||
size_t getCameraCount();
|
||||
|
||||
/// @brief
|
||||
/// @param index
|
||||
/// @return
|
||||
Camera *getCameraAt(size_t index);
|
||||
|
||||
/// @brief
|
||||
/// @param view
|
||||
/// @param scene
|
||||
/// @return
|
||||
Gizmo *createGizmo(View *view, Scene *scene);
|
||||
|
||||
|
||||
/// @brief
|
||||
/// @return
|
||||
Scene *getScene()
|
||||
{
|
||||
return _scene;
|
||||
}
|
||||
|
||||
/// @brief
|
||||
/// @return
|
||||
AnimationManager *getAnimationManager() {
|
||||
return _animationManager.get();
|
||||
}
|
||||
|
||||
/// @brief
|
||||
/// @return
|
||||
NameComponentManager *getNameComponentManager() {
|
||||
return _ncm;
|
||||
}
|
||||
|
||||
Entity getOverlayEntity(size_t index) {
|
||||
if(index == 0) {
|
||||
return _gridOverlay->grid();
|
||||
} else if(index == 1) {
|
||||
return _gridOverlay->sphere();
|
||||
}
|
||||
}
|
||||
|
||||
size_t getOverlayEntityCount() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private:
|
||||
gltfio::AssetLoader *_assetLoader = nullptr;
|
||||
const ResourceLoaderWrapperImpl *const _resourceLoaderWrapper;
|
||||
Engine *_engine = nullptr;
|
||||
Scene *_scene = nullptr;
|
||||
Camera *_mainCamera;
|
||||
|
||||
gltfio::MaterialKey _defaultUnlitConfig;
|
||||
|
||||
gltfio::MaterialProvider *_ubershaderProvider = nullptr;
|
||||
gltfio::MaterialProvider *_unlitMaterialProvider = nullptr;
|
||||
gltfio::ResourceLoader *_gltfResourceLoader = nullptr;
|
||||
gltfio::TextureProvider *_stbDecoder = nullptr;
|
||||
gltfio::TextureProvider *_ktxDecoder = nullptr;
|
||||
std::mutex _mutex;
|
||||
std::vector<MaterialInstance *> _materialInstances;
|
||||
|
||||
Material *_unlitFixedSizeMaterial = nullptr;
|
||||
|
||||
utils::NameComponentManager *_ncm;
|
||||
|
||||
tsl::robin_map<EntityId, math::mat4> _transformUpdates;
|
||||
std::set<Texture *> _textures;
|
||||
std::vector<Camera *> _cameras;
|
||||
std::vector<std::unique_ptr<SceneAsset>> _sceneAssets;
|
||||
std::vector<std::unique_ptr<Gizmo>> _gizmos;
|
||||
|
||||
std::unique_ptr<AnimationManager> _animationManager = std::nullptr_t();
|
||||
std::unique_ptr<CollisionComponentManager> _collisionComponentManager = std::nullptr_t();
|
||||
|
||||
GridOverlay *_gridOverlay = std::nullptr_t();
|
||||
|
||||
void _updateTransforms();
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user