feat: Rename Gizmo material to UnlitFixedSize, and expose methods for using this material on other entities. Also exposes new methods for setting single float parameters.

This commit is contained in:
Nick Fisher
2024-10-31 22:34:51 +08:00
parent 91d653b288
commit bfdda4a7cc
31 changed files with 1813 additions and 1634 deletions

View File

@@ -23,7 +23,7 @@ bindings:
#
materials: FORCE
@echo "Using Filament build from ${FILAMENT_PATH}"
@for material in unlit image gizmo grid; do \
@for material in unlit image unlit_fixed_size grid; do \
${FILAMENT_PATH}/matc -a opengl -a metal -o materials/$$material.filamat materials/$$material.mat; \
$(FILAMENT_PATH)/resgen -c -p $$material -x thermion_dart/native/include/material/ materials/$$material.filamat; \
echo '#include "'$$material'.h"' | cat - thermion_dart/native/include/material/$$material.c > thermion_dart/native/include/material/$$material.c.new; \

View File

@@ -1,5 +1,5 @@
material {
name : Gizmo,
name : UnlitFixedSize,
parameters : [
{
type : mat4,
@@ -8,8 +8,13 @@
},
{
type : float4,
name : color,
name : baseColorFactor,
precision : low
},
{
type: float, // the number of world-space units between the camera and the (unscaled) gizmo
name: scale,
precision: low
}
],
depthWrite : true,
@@ -24,14 +29,13 @@
vertex {
void materialVertex(inout MaterialVertexInputs material) {
// we want to ensure the gizmo has the same size (in screen-space), no matter the distance from the camera
// we do this by scaling the model-space vertex positions by the distance from the camera
// the object should have the same size (in screen-space), no matter the distance from the camera
// scale the model-space vertex positions by the distance from the camera
vec4 modelSpace = getPosition();
vec4 worldSpace = getWorldFromModelMatrix() * modelSpace;
vec4 viewSpace = getViewFromWorldMatrix() * worldSpace;
float distanceFromCamera = length(viewSpace.xyz);
modelSpace.xyz *= (distanceFromCamera / 4.0f); // divide by 4 so that the size is equivalent to the camera being 4 world-space units away from the (unscaled) gizmo
modelSpace.xyz *= (distanceFromCamera / materialParams.scale);
worldSpace = getWorldFromModelMatrix() * modelSpace;
material.worldPosition = worldSpace;
@@ -44,7 +48,7 @@
fragment {
void material(inout MaterialInputs material) {
prepareMaterial(material);
material.baseColor = materialParams.color;
material.baseColor = materialParams.baseColorFactor;
}
}

View File

@@ -60,7 +60,7 @@ void main(List<String> args) async {
.map((f) => f.path)
.toList();
sources.addAll([
path.join(pkgRootFilePath, "native", "include", "material", "gizmo_material.c"),
path.join(pkgRootFilePath, "native", "include", "material", "unlit_fixed_size.c"),
path.join(pkgRootFilePath, "native", "include", "material", "image.c"),
path.join(pkgRootFilePath, "native", "include", "material", "grid.c"),
path.join(pkgRootFilePath, "native", "include", "material", "unlit.c"),

View File

@@ -621,6 +621,15 @@ external int get_bone(
int boneIndex,
);
@ffi.Native<
ffi.Pointer<TGizmo> Function(ffi.Pointer<TSceneManager>, ffi.Pointer<TView>,
ffi.Pointer<TScene>)>(isLeaf: true)
external ffi.Pointer<TGizmo> SceneManager_createGizmo(
ffi.Pointer<TSceneManager> tSceneManager,
ffi.Pointer<TView> tView,
ffi.Pointer<TScene> tScene,
);
@ffi.Native<
EntityId Function(
ffi.Pointer<TSceneManager>,
@@ -658,6 +667,14 @@ external ffi.Pointer<TMaterialInstance>
ffi.Pointer<TSceneManager> sceneManager,
);
@ffi.Native<
ffi.Pointer<TMaterialInstance> Function(
ffi.Pointer<TSceneManager>)>(isLeaf: true)
external ffi.Pointer<TMaterialInstance>
SceneManager_createUnlitFixedSizeMaterialInstance(
ffi.Pointer<TSceneManager> sceneManager,
);
@ffi.Native<
ffi.Bool Function(ffi.Pointer<TSceneManager>, EntityId,
ffi.Pointer<ffi.Double>)>(isLeaf: true)
@@ -1206,6 +1223,15 @@ external void MaterialInstance_setParameterFloat2(
double y,
);
@ffi.Native<
ffi.Void Function(ffi.Pointer<TMaterialInstance>, ffi.Pointer<ffi.Char>,
ffi.Double)>(isLeaf: true)
external void MaterialInstance_setParameterFloat(
ffi.Pointer<TMaterialInstance> materialInstance,
ffi.Pointer<ffi.Char> name,
double value,
);
@ffi.Native<TViewport Function(ffi.Pointer<TView>)>(isLeaf: true)
external TViewport View_getViewport(
ffi.Pointer<TView> view,
@@ -1608,6 +1634,20 @@ external void SceneManager_createUnlitMaterialInstanceRenderThread(
callback,
);
@ffi.Native<
ffi.Void Function(
ffi.Pointer<TSceneManager>,
ffi.Pointer<
ffi.NativeFunction<
ffi.Void Function(
ffi.Pointer<TMaterialInstance>)>>)>(isLeaf: true)
external void SceneManager_createUnlitFixedSizeMaterialInstanceRenderThread(
ffi.Pointer<TSceneManager> sceneManager,
ffi.Pointer<
ffi.NativeFunction<ffi.Void Function(ffi.Pointer<TMaterialInstance>)>>
callback,
);
@ffi.Native<
ffi.Void Function(
ffi.Pointer<TSceneManager>,
@@ -2028,15 +2068,6 @@ void Camera_setProjection(
far,
);
@ffi.Native<
ffi.Pointer<TGizmo> Function(ffi.Pointer<TEngine>, ffi.Pointer<TView>,
ffi.Pointer<TScene>)>(isLeaf: true)
external ffi.Pointer<TGizmo> Gizmo_new(
ffi.Pointer<TEngine> tEngine,
ffi.Pointer<TView> tView,
ffi.Pointer<TScene> tScene,
);
@ffi.Native<
ffi.Void Function(ffi.Pointer<TGizmo>, ffi.Uint32, ffi.Uint32,
GizmoPickCallback)>(isLeaf: true)

View File

@@ -2035,6 +2035,9 @@ class ThermionViewerFFI extends ThermionViewer {
destroy_material_instance(_sceneManager!, materialInstance._pointer);
}
///
///
///
Future<ThermionFFIMaterialInstance> createUnlitMaterialInstance() async {
var instance = await withPointerCallback<TMaterialInstance>((cb) {
SceneManager_createUnlitMaterialInstanceRenderThread(_sceneManager!, cb);
@@ -2045,6 +2048,19 @@ class ThermionViewerFFI extends ThermionViewer {
return ThermionFFIMaterialInstance(instance);
}
///
///
///
Future<ThermionFFIMaterialInstance> createUnlitFixedSizeMaterialInstance() async {
var instance = await withPointerCallback<TMaterialInstance>((cb) {
SceneManager_createUnlitFixedSizeMaterialInstanceRenderThread(_sceneManager!, cb);
});
if (instance == nullptr) {
throw Exception("Failed to create material instance");
}
return ThermionFFIMaterialInstance(instance);
}
@override
Future setMaterialPropertyInt(ThermionEntity entity, String propertyName,
int materialIndex, int value) {
@@ -2163,7 +2179,7 @@ class ThermionViewerFFI extends ThermionViewer {
Future<Gizmo> createGizmo(FFIView view) async {
var view = (await getViewAt(0)) as FFIView;
var scene = View_getScene(view.view);
final gizmo = Gizmo_new(Viewer_getEngine(_viewer!), view.view, scene);
final gizmo = SceneManager_createGizmo(_sceneManager!, view.view, scene);
return FFIGizmo(gizmo, this);
}
}
@@ -2194,6 +2210,12 @@ class ThermionFFIMaterialInstance extends MaterialInstance {
MaterialInstance_setParameterFloat2(
_pointer, name.toNativeUtf8().cast<Char>(), x, y);
}
@override
Future setParameterFloat(String name, double value) async {
MaterialInstance_setParameterFloat(
_pointer, name.toNativeUtf8().cast<Char>(), value);
}
}
class FFIRenderTarget extends RenderTarget {

View File

@@ -2,6 +2,7 @@ abstract class MaterialInstance {
Future setDepthWriteEnabled(bool enabled);
Future setDepthCullingEnabled(bool enabled);
Future setParameterFloat2(String name, double x, double y);
Future setParameterFloat(String name, double x);
}
enum AlphaMode { OPAQUE, MASK, BLEND }

View File

@@ -895,6 +895,11 @@ abstract class ThermionViewer {
///
Future<MaterialInstance> createUnlitMaterialInstance();
///
///
///
Future<MaterialInstance> createUnlitFixedSizeMaterialInstance();
///
///
///

View File

@@ -21,4 +21,10 @@ class ThermionWasmMaterialInstance extends MaterialInstance {
// TODO: implement setParameterFloat2
throw UnimplementedError();
}
@override
Future setParameterFloat(String name, double x) {
// TODO: implement setParameterFloat
throw UnimplementedError();
}
}

View File

@@ -17,8 +17,6 @@
#include <filament/IndexBuffer.h>
#include <filament/InstanceBuffer.h>
#include "material/gizmo.h"
#include "ThermionDartApi.h"
namespace thermion {
@@ -31,7 +29,7 @@ class Gizmo {
enum Axis { X, Y, Z};
public:
Gizmo(Engine *engine, View *view, Scene *scene);
Gizmo(Engine *engine, View *view, Scene *scene, Material* material);
~Gizmo();
typedef void (*PickCallback)(EntityId entityId, uint32_t x, uint32_t y, View *view);
@@ -91,8 +89,10 @@ class Gizmo {
Engine *_engine;
Scene *_scene;
View *_view;
utils::Entity _entities[7] = { utils::Entity(), utils::Entity(), utils::Entity(), utils::Entity(), utils::Entity(), utils::Entity(), utils::Entity() };
Material* _material;
utils::Entity _entities[7] = { utils::Entity(), utils::Entity(), utils::Entity(), utils::Entity(), utils::Entity(), utils::Entity(), utils::Entity() };
MaterialInstance* _materialInstances[7];
math::float4 inactiveColors[3] {
math::float4 { 1.0f, 0.0f, 0.0f, 0.5f },

View File

@@ -19,9 +19,6 @@
#include <filament/IndexBuffer.h>
#include <filament/InstanceBuffer.h>
#include "material/gizmo.h"
namespace thermion {
using namespace filament;

View File

@@ -19,16 +19,17 @@
#include <filament/InstanceBuffer.h>
#include <utils/NameComponentManager.h>
#include "CustomGeometry.hpp"
#include "tsl/robin_map.h"
#include "APIBoundaryTypes.h"
#include "CustomGeometry.hpp"
#include "Gizmo.hpp"
#include "GridOverlay.hpp"
#include "ResourceBuffer.hpp"
#include "components/CollisionComponentManager.hpp"
#include "components/AnimationComponentManager.hpp"
#include "tsl/robin_map.h"
namespace thermion
{
@@ -287,6 +288,8 @@ namespace thermion
return _ubershaderProvider;
}
MaterialInstance* createUnlitFixedSizeMaterialInstance();
MaterialInstance* createUnlitMaterialInstance();
void setVisibilityLayer(EntityId entityId, int layer);
@@ -298,6 +301,8 @@ namespace thermion
size_t getCameraCount();
Camera* getCameraAt(size_t index);
Gizmo *createGizmo(View *view, Scene *scene);
bool isGizmoEntity(utils::Entity entity);
@@ -321,6 +326,8 @@ namespace thermion
std::mutex _stencilMutex;
std::vector<MaterialInstance*> _materialInstances;
Material* _gizmoMaterial = nullptr;
utils::NameComponentManager *_ncm;
tsl::robin_map<

View File

@@ -10,7 +10,6 @@ extern "C"
typedef void (*GizmoPickCallback)(EntityId entityId, uint32_t x, uint32_t y, TView* view);
EMSCRIPTEN_KEEPALIVE TGizmo* Gizmo_new(TEngine *tEngine, TView *tView, TScene *tScene);
EMSCRIPTEN_KEEPALIVE void Gizmo_pick(TGizmo *tGizmo, uint32_t x, uint32_t y, GizmoPickCallback callback);
EMSCRIPTEN_KEEPALIVE void Gizmo_setVisibility(TGizmo *tGizmo, bool visible);

View File

@@ -198,6 +198,7 @@ extern "C"
int skinIndex,
int boneIndex);
EMSCRIPTEN_KEEPALIVE TGizmo* SceneManager_createGizmo(TSceneManager *tSceneManager, TView *tView, TScene *tScene);
EMSCRIPTEN_KEEPALIVE EntityId SceneManager_createGeometry(
TSceneManager *sceneManager,
float *vertices,
@@ -212,6 +213,7 @@ extern "C"
TMaterialInstance *materialInstance,
bool keepData);
EMSCRIPTEN_KEEPALIVE TMaterialInstance *SceneManager_createUnlitMaterialInstance(TSceneManager *sceneManager);
EMSCRIPTEN_KEEPALIVE TMaterialInstance *SceneManager_createUnlitFixedSizeMaterialInstance(TSceneManager *sceneManager);
EMSCRIPTEN_KEEPALIVE bool SceneManager_setTransform(TSceneManager *sceneManager, EntityId entityId, const double *const transform);
EMSCRIPTEN_KEEPALIVE void SceneManager_queueTransformUpdates(TSceneManager *sceneManager, EntityId* entities, const double* const transforms, int numEntities);
EMSCRIPTEN_KEEPALIVE TCamera* SceneManager_findCameraByName(TSceneManager* tSceneManager, EntityId entity, const char* name);
@@ -295,6 +297,7 @@ extern "C"
EMSCRIPTEN_KEEPALIVE void MaterialInstance_setDepthWrite(TMaterialInstance* materialInstance, bool enabled);
EMSCRIPTEN_KEEPALIVE void MaterialInstance_setDepthCulling(TMaterialInstance* materialInstance, bool enabled);
EMSCRIPTEN_KEEPALIVE void MaterialInstance_setParameterFloat2(TMaterialInstance* materialInstance, const char* name, double x, double y);
EMSCRIPTEN_KEEPALIVE void MaterialInstance_setParameterFloat(TMaterialInstance* materialInstance, const char* name, double value);
#ifdef __cplusplus

View File

@@ -67,6 +67,7 @@ extern "C"
void (*callback)(EntityId));
EMSCRIPTEN_KEEPALIVE void SceneManager_loadGlbFromBufferRenderThread(TSceneManager *sceneManager, const uint8_t *const data, size_t length, int numInstances, bool keepData, int priority, int layer, bool loadResourcesAsync, void (*callback)(EntityId));
EMSCRIPTEN_KEEPALIVE void SceneManager_createUnlitMaterialInstanceRenderThread(TSceneManager *sceneManager, void (*callback)(TMaterialInstance*));
EMSCRIPTEN_KEEPALIVE void SceneManager_createUnlitFixedSizeMaterialInstanceRenderThread(TSceneManager *sceneManager, void (*callback)(TMaterialInstance*));
EMSCRIPTEN_KEEPALIVE void load_glb_render_thread(TSceneManager *sceneManager, const char *assetPath, int numInstances, bool keepData, void (*callback)(EntityId));
EMSCRIPTEN_KEEPALIVE void load_gltf_render_thread(TSceneManager *sceneManager, const char *assetPath, const char *relativePath, bool keepData, void (*callback)(EntityId));
EMSCRIPTEN_KEEPALIVE void create_instance_render_thread(TSceneManager *sceneManager, EntityId entityId, void (*callback)(EntityId));

View File

@@ -1,12 +0,0 @@
.global GIZMO_GIZMO_OFFSET;
.global GIZMO_GIZMO_SIZE;
.global GIZMO_PACKAGE
.section .rodata
GIZMO_PACKAGE:
.incbin "gizmo.bin"
GIZMO_GIZMO_OFFSET:
.int 0
GIZMO_GIZMO_SIZE:
.int 27809

View File

@@ -1,12 +0,0 @@
.global _GIZMO_GIZMO_OFFSET;
.global _GIZMO_GIZMO_SIZE;
.global _GIZMO_PACKAGE
.section __TEXT,__const
_GIZMO_PACKAGE:
.incbin "gizmo.bin"
_GIZMO_GIZMO_OFFSET:
.int 0
_GIZMO_GIZMO_SIZE:
.int 27809

View File

@@ -1,13 +0,0 @@
#ifndef GIZMO_H_
#define GIZMO_H_
#include <stdint.h>
extern "C" {
extern const uint8_t GIZMO_PACKAGE[];
extern int GIZMO_GIZMO_OFFSET;
extern int GIZMO_GIZMO_SIZE;
}
#define GIZMO_GIZMO_DATA (GIZMO_PACKAGE + GIZMO_GIZMO_OFFSET)
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,12 @@
.global UNLIT_FIXED_SIZE_UNLIT_FIXED_SIZE_OFFSET;
.global UNLIT_FIXED_SIZE_UNLIT_FIXED_SIZE_SIZE;
.global UNLIT_FIXED_SIZE_PACKAGE
.section .rodata
UNLIT_FIXED_SIZE_PACKAGE:
.incbin "unlit_fixed_size.bin"
UNLIT_FIXED_SIZE_UNLIT_FIXED_SIZE_OFFSET:
.int 0
UNLIT_FIXED_SIZE_UNLIT_FIXED_SIZE_SIZE:
.int 28235

View File

@@ -0,0 +1,12 @@
.global _UNLIT_FIXED_SIZE_UNLIT_FIXED_SIZE_OFFSET;
.global _UNLIT_FIXED_SIZE_UNLIT_FIXED_SIZE_SIZE;
.global _UNLIT_FIXED_SIZE_PACKAGE
.section __TEXT,__const
_UNLIT_FIXED_SIZE_PACKAGE:
.incbin "unlit_fixed_size.bin"
_UNLIT_FIXED_SIZE_UNLIT_FIXED_SIZE_OFFSET:
.int 0
_UNLIT_FIXED_SIZE_UNLIT_FIXED_SIZE_SIZE:
.int 28235

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,13 @@
#ifndef UNLIT_FIXED_SIZE_H_
#define UNLIT_FIXED_SIZE_H_
#include <stdint.h>
extern "C" {
extern const uint8_t UNLIT_FIXED_SIZE_PACKAGE[];
extern int UNLIT_FIXED_SIZE_UNLIT_FIXED_SIZE_OFFSET;
extern int UNLIT_FIXED_SIZE_UNLIT_FIXED_SIZE_SIZE;
}
#define UNLIT_FIXED_SIZE_UNLIT_FIXED_SIZE_DATA (UNLIT_FIXED_SIZE_PACKAGE + UNLIT_FIXED_SIZE_UNLIT_FIXED_SIZE_OFFSET)
#endif

View File

@@ -7,31 +7,26 @@
#include <filament/TransformManager.h>
#include <gltfio/math.h>
#include "SceneManager.hpp"
#include "material/gizmo.h"
#include "material/unlit_fixed_size.h"
#include "Log.hpp"
namespace thermion {
using namespace filament::gltfio;
Gizmo::Gizmo(Engine *engine, View *view, Scene* scene) : _engine(engine), _view(view), _scene(scene)
Gizmo::Gizmo(Engine *engine, View *view, Scene* scene, Material* material) : _engine(engine), _view(view), _scene(scene), _material(material)
{
auto &entityManager = EntityManager::get();
auto &transformManager = _engine->getTransformManager();
_material =
Material::Builder()
.package(GIZMO_GIZMO_DATA, GIZMO_GIZMO_SIZE)
.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::float4{0.0f, 0.0f, 0.0f, 1.0f}); // Black color
_materialInstances[3]->setParameter("baseColorFactor", math::float4{0.0f, 0.0f, 0.0f, 1.0f}); // Black color
// Create center cube vertices
float centerCubeSize = 0.01f;
@@ -160,7 +155,7 @@ Gizmo::Gizmo(Engine *engine, View *view, Scene* scene) : _engine(engine), _view(
break;
}
_materialInstances[i]->setParameter("color", baseColor);
_materialInstances[i]->setParameter("baseColorFactor", baseColor);
RenderableManager::Builder(1)
.boundingBox({{-arrowWidth, -arrowWidth, 0},

View File

@@ -33,9 +33,12 @@
#include "CustomGeometry.hpp"
#include "UnprojectTexture.hpp"
#include "Gizmo.hpp"
extern "C"
{
#include "material/image.h"
#include "material/unlit_fixed_size.h"
}
namespace thermion
@@ -52,9 +55,8 @@ namespace thermion
Engine *engine,
Scene *scene,
const char *uberArchivePath,
Camera *mainCamera)
:
_resourceLoaderWrapper(resourceLoaderWrapper),
Camera *mainCamera)
: _resourceLoaderWrapper(resourceLoaderWrapper),
_engine(engine),
_scene(scene),
_mainCamera(mainCamera)
@@ -103,17 +105,22 @@ namespace thermion
_scene->addEntity(_gridOverlay->sphere());
_scene->addEntity(_gridOverlay->grid());
_gizmoMaterial =
Material::Builder()
.package(UNLIT_FIXED_SIZE_UNLIT_FIXED_SIZE_DATA, UNLIT_FIXED_SIZE_UNLIT_FIXED_SIZE_SIZE)
.build(*_engine);
}
SceneManager::~SceneManager()
{
for(auto camera : _cameras) {
for (auto camera : _cameras)
{
auto entity = camera->getEntity();
_engine->destroyCameraComponent(entity);
_engine->getEntityManager().destroy(entity);
}
_cameras.clear();
_gridOverlay->destroy();
destroyAll();
@@ -131,8 +138,14 @@ namespace thermion
AssetLoader::destroy(&_assetLoader);
}
bool SceneManager::isGizmoEntity(Entity entity) {
return false; // TODO
Gizmo *SceneManager::createGizmo(View *view, Scene *scene)
{
return new Gizmo(_engine, view, scene, _gizmoMaterial);
}
bool SceneManager::isGizmoEntity(Entity entity)
{
return false; // TODO
}
int SceneManager::getInstanceCount(EntityId entityId)
@@ -246,15 +259,16 @@ namespace thermion
return eid;
}
void SceneManager::setVisibilityLayer(EntityId entityId, int layer) {
auto& rm = _engine->getRenderableManager();
void SceneManager::setVisibilityLayer(EntityId entityId, int layer)
{
auto &rm = _engine->getRenderableManager();
auto renderable = rm.getInstance(utils::Entity::import(entityId));
if(!renderable.isValid()) {
if (!renderable.isValid())
{
Log("Warning: no renderable found");
}
rm.setLayerMask(renderable, 0xFF, 1u << layer);
}
EntityId SceneManager::loadGlbFromBuffer(const uint8_t *data, size_t length, int numInstances, bool keepData, int priority, int layer, bool loadResourcesAsync)
@@ -281,11 +295,13 @@ namespace thermion
_scene->addEntities(asset->getEntities(), entityCount);
auto & rm = _engine->getRenderableManager();
auto &rm = _engine->getRenderableManager();
for(int i=0; i < entityCount; i++) {
for (int i = 0; i < entityCount; i++)
{
auto instance = rm.getInstance(asset->getEntities()[i]);
if(!instance.isValid()) {
if (!instance.isValid())
{
Log("No valid renderable for entity");
continue;
}
@@ -304,13 +320,16 @@ namespace thermion
_gltfResourceLoader->asyncUpdateLoad();
}
#else
if(loadResourcesAsync) {
if (loadResourcesAsync)
{
if (!_gltfResourceLoader->asyncBeginLoad(asset))
{
Log("Unknown error loading glb asset");
return 0;
}
} else {
}
else
{
if (!_gltfResourceLoader->loadResources(asset))
{
Log("Unknown error loading glb asset");
@@ -539,11 +558,13 @@ namespace thermion
asset.second->getLightEntityCount());
_assetLoader->destroyAsset(asset.second);
}
for(auto *texture : _textures) {
for (auto *texture : _textures)
{
_engine->destroy(texture);
}
for(auto *materialInstance : _materialInstances) {
for (auto *materialInstance : _materialInstances)
{
_engine->destroy(materialInstance);
}
@@ -661,7 +682,6 @@ namespace thermion
auto entity = Entity::import(entityId);
if (_animationComponentManager->hasComponent(entity))
{
_animationComponentManager->removeComponent(entity);
@@ -674,7 +694,8 @@ namespace thermion
_scene->remove(entity);
if(isGeometryEntity(entityId)) {
if (isGeometryEntity(entityId))
{
return;
}
@@ -1412,7 +1433,7 @@ namespace thermion
return texture;
}
bool SceneManager::applyTexture(EntityId entityId, Texture *texture, const char* parameterName, int materialIndex)
bool SceneManager::applyTexture(EntityId entityId, Texture *texture, const char *parameterName, int materialIndex)
{
auto entity = Entity::import(entityId);
@@ -1446,10 +1467,12 @@ namespace thermion
return true;
}
void SceneManager::destroyTexture(Texture* texture) {
if(_textures.find(texture) == _textures.end()) {
void SceneManager::destroyTexture(Texture *texture)
{
if (_textures.find(texture) == _textures.end())
{
Log("Warning: couldn't find texture");
}
}
_textures.erase(texture);
_engine->destroy(texture);
}
@@ -1904,7 +1927,7 @@ namespace thermion
tm.setTransform(transformInstance, newTransform);
}
void SceneManager::queueRelativePositionUpdateFromViewportVector(View* view, EntityId entityId, float viewportCoordX, float viewportCoordY)
void SceneManager::queueRelativePositionUpdateFromViewportVector(View *view, EntityId entityId, float viewportCoordX, float viewportCoordY)
{
// Get the camera and viewport
const auto &camera = view->getCamera();
@@ -1941,14 +1964,14 @@ namespace thermion
auto entityPlaneInWorldSpace = camera.getModelMatrix() * entityPlaneInCameraSpace;
// Queue the position update (as a relative movement)
}
void SceneManager::queueTransformUpdates(EntityId* entities, math::mat4* transforms, int numEntities)
void SceneManager::queueTransformUpdates(EntityId *entities, math::mat4 *transforms, int numEntities)
{
std::lock_guard lock(_mutex);
for(int i= 0; i < numEntities; i++) {
for (int i = 0; i < numEntities; i++)
{
auto entity = entities[i];
const auto &pos = _transformUpdates.find(entity);
if (pos == _transformUpdates.end())
@@ -2279,112 +2302,117 @@ namespace thermion
}
}
EntityId SceneManager::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,
filament::MaterialInstance* materialInstance,
bool keepData)
{
auto geometry = std::make_unique<CustomGeometry>(vertices, numVertices, normals, numNormals, uvs, numUvs, indices, numIndices, primitiveType, _engine);
auto entity = utils::EntityManager::get().create();
RenderableManager::Builder builder(1);
builder.boundingBox(geometry->getBoundingBox())
.geometry(0, primitiveType, geometry->vertexBuffer(), geometry->indexBuffer(), 0, numIndices)
.culling(true)
.receiveShadows(true)
.castShadows(true);
filament::Material *mat = nullptr;
if (!materialInstance) {
Log("Using default ubershader material");
filament::gltfio::MaterialKey config;
memset(&config, 0, sizeof(config)); // Initialize all bits to zero
config.unlit = false;
config.doubleSided = false;
config.useSpecularGlossiness = false;
config.alphaMode = filament::gltfio::AlphaMode::OPAQUE;
config.hasBaseColorTexture = numUvs > 0;
config.hasClearCoat = false;
config.hasClearCoatNormalTexture = false;
config.hasClearCoatRoughnessTexture = false;
config.hasEmissiveTexture = false;
config.hasIOR = false;
config.hasMetallicRoughnessTexture = false;
config.hasNormalTexture = false;
config.hasOcclusionTexture = false;
config.hasSheen = false;
config.hasSheenColorTexture = false;
config.hasSheenRoughnessTexture = false;
config.hasSpecularGlossinessTexture = false;
config.hasTextureTransforms = false;
config.hasTransmission = false;
config.hasTransmissionTexture = false;
config.hasVolume = false;
config.hasVolumeThicknessTexture = false;
config.baseColorUV = 0;
config.hasVertexColors = false;
config.hasVolume = false;
materialInstance = createUbershaderMaterialInstance(config);
if(!materialInstance) {
Log("Failed to create material instance");
return Entity::smuggle(Entity());
}
}
// Set up texture and sampler if UVs are available
if (uvs != nullptr && numUvs > 0)
EntityId SceneManager::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,
filament::MaterialInstance *materialInstance,
bool keepData)
{
// Create a default white texture
static constexpr uint32_t textureSize = 1;
static constexpr uint32_t white = 0x00ffffff;
Texture* texture = Texture::Builder()
.width(textureSize)
.height(textureSize)
.levels(1)
.format(Texture::InternalFormat::RGBA8)
.build(*_engine);
auto geometry = std::make_unique<CustomGeometry>(vertices, numVertices, normals, numNormals, uvs, numUvs, indices, numIndices, primitiveType, _engine);
_textures.insert(texture);
filament::backend::PixelBufferDescriptor pbd(&white, 4, Texture::Format::RGBA, Texture::Type::UBYTE);
texture->setImage(*_engine, 0, std::move(pbd));
auto entity = utils::EntityManager::get().create();
RenderableManager::Builder builder(1);
// Create a sampler
TextureSampler sampler(TextureSampler::MinFilter::NEAREST, TextureSampler::MagFilter::NEAREST);
sampler.setWrapModeS(TextureSampler::WrapMode::REPEAT);
sampler.setWrapModeT(TextureSampler::WrapMode::REPEAT);
builder.boundingBox(geometry->getBoundingBox())
.geometry(0, primitiveType, geometry->vertexBuffer(), geometry->indexBuffer(), 0, numIndices)
.culling(true)
.receiveShadows(true)
.castShadows(true);
// Set the texture and sampler to the material instance
materialInstance->setParameter("baseColorMap", texture, sampler);
filament::Material *mat = nullptr;
if (!materialInstance)
{
Log("Using default ubershader material");
filament::gltfio::MaterialKey config;
memset(&config, 0, sizeof(config)); // Initialize all bits to zero
config.unlit = false;
config.doubleSided = false;
config.useSpecularGlossiness = false;
config.alphaMode = filament::gltfio::AlphaMode::OPAQUE;
config.hasBaseColorTexture = numUvs > 0;
config.hasClearCoat = false;
config.hasClearCoatNormalTexture = false;
config.hasClearCoatRoughnessTexture = false;
config.hasEmissiveTexture = false;
config.hasIOR = false;
config.hasMetallicRoughnessTexture = false;
config.hasNormalTexture = false;
config.hasOcclusionTexture = false;
config.hasSheen = false;
config.hasSheenColorTexture = false;
config.hasSheenRoughnessTexture = false;
config.hasSpecularGlossinessTexture = false;
config.hasTextureTransforms = false;
config.hasTransmission = false;
config.hasTransmissionTexture = false;
config.hasVolume = false;
config.hasVolumeThicknessTexture = false;
config.baseColorUV = 0;
config.hasVertexColors = false;
config.hasVolume = false;
materialInstance = createUbershaderMaterialInstance(config);
if (!materialInstance)
{
Log("Failed to create material instance");
return Entity::smuggle(Entity());
}
}
// Set up texture and sampler if UVs are available
if (uvs != nullptr && numUvs > 0)
{
if(materialInstance->getMaterial()->hasParameter("baseColorMap")) {
// Create a default white texture
static constexpr uint32_t textureSize = 1;
static constexpr uint32_t white = 0x00ffffff;
Texture *texture = Texture::Builder()
.width(textureSize)
.height(textureSize)
.levels(1)
.format(Texture::InternalFormat::RGBA8)
.build(*_engine);
_textures.insert(texture);
filament::backend::PixelBufferDescriptor pbd(&white, 4, Texture::Format::RGBA, Texture::Type::UBYTE);
texture->setImage(*_engine, 0, std::move(pbd));
// Create a sampler
TextureSampler sampler(TextureSampler::MinFilter::NEAREST, TextureSampler::MagFilter::NEAREST);
sampler.setWrapModeS(TextureSampler::WrapMode::REPEAT);
sampler.setWrapModeT(TextureSampler::WrapMode::REPEAT);
// Set the texture and sampler to the material instance
materialInstance->setParameter("baseColorMap", texture, sampler);
}
}
builder.material(0, materialInstance);
builder.build(*_engine, entity);
_scene->addEntity(entity);
auto entityId = Entity::smuggle(entity);
_geometry.emplace(entityId, std::move(geometry));
return entityId;
}
builder.material(0, materialInstance);
builder.build(*_engine, entity);
_scene->addEntity(entity);
auto entityId = Entity::smuggle(entity);
_geometry.emplace(entityId, std::move(geometry));
return entityId;
}
MaterialInstance* SceneManager::getMaterialInstanceAt(EntityId entityId, int materialIndex) {
MaterialInstance *SceneManager::getMaterialInstanceAt(EntityId entityId, int materialIndex)
{
auto entity = Entity::import(entityId);
const auto &rm = _engine->getRenderableManager();
auto renderableInstance = rm.getInstance(entity);
@@ -2436,7 +2464,7 @@ EntityId SceneManager::createGeometry(
materialInstance->setParameter(property, value);
}
void SceneManager::setMaterialProperty(EntityId entityId, int materialIndex, const char *property, filament::math::float4& value)
void SceneManager::setMaterialProperty(EntityId entityId, int materialIndex, const char *property, filament::math::float4 &value)
{
auto entity = Entity::import(entityId);
const auto &rm = _engine->getRenderableManager();
@@ -2453,17 +2481,20 @@ EntityId SceneManager::createGeometry(
Log("Parameter %s not found", property);
return;
}
materialInstance->setParameter(property, filament::math::float4 { value.x, value.y, value.z, value.w });
materialInstance->setParameter(property, filament::math::float4{value.x, value.y, value.z, value.w});
}
void SceneManager::destroy(MaterialInstance* instance) {
void SceneManager::destroy(MaterialInstance *instance)
{
_engine->destroy(instance);
}
MaterialInstance* SceneManager::createUbershaderMaterialInstance(filament::gltfio::MaterialKey config) {
filament::gltfio::UvMap uvmap {};
auto * materialInstance = _ubershaderProvider->createMaterialInstance(&config, &uvmap);
if(!materialInstance) {
MaterialInstance *SceneManager::createUbershaderMaterialInstance(filament::gltfio::MaterialKey config)
{
filament::gltfio::UvMap uvmap{};
auto *materialInstance = _ubershaderProvider->createMaterialInstance(&config, &uvmap);
if (!materialInstance)
{
Log("Invalid material configuration");
return nullptr;
}
@@ -2473,44 +2504,58 @@ EntityId SceneManager::createGeometry(
return materialInstance;
}
MaterialInstance* SceneManager::createUnlitMaterialInstance() {
MaterialInstance *SceneManager::createUnlitFixedSizeMaterialInstance()
{
auto instance = _gizmoMaterial->createInstance();
instance->setParameter("scale", 1.0f);
return instance;
}
MaterialInstance *SceneManager::createUnlitMaterialInstance()
{
UvMap uvmap;
auto instance = _unlitMaterialProvider->createMaterialInstance(nullptr, &uvmap);
instance->setParameter("uvScale", filament::math::float2 { 1.0f, 1.0f });
instance->setParameter("uvScale", filament::math::float2{1.0f, 1.0f});
_materialInstances.push_back(instance);
return instance;
}
Camera* SceneManager::createCamera() {
Camera *SceneManager::createCamera()
{
auto entity = EntityManager::get().create();
auto camera = _engine->createCamera(entity);
_cameras.push_back(camera);
return camera;
}
void SceneManager::destroyCamera(Camera* camera) {
void SceneManager::destroyCamera(Camera *camera)
{
auto entity = camera->getEntity();
_engine->destroyCameraComponent(entity);
_engine->getEntityManager().destroy(entity);
auto it = std::find(_cameras.begin(), _cameras.end(), camera);
if(it != _cameras.end()) {
if (it != _cameras.end())
{
_cameras.erase(it);
}
}
size_t SceneManager::getCameraCount() {
size_t SceneManager::getCameraCount()
{
return _cameras.size() + 1;
}
Camera* SceneManager::getCameraAt(size_t index) {
if(index == 0) {
Camera *SceneManager::getCameraAt(size_t index)
{
if (index == 0)
{
return _mainCamera;
}
if(index - 1 > _cameras.size() - 1) {
if (index - 1 > _cameras.size() - 1)
{
return nullptr;
}
return _cameras[index-1];
return _cameras[index - 1];
}
} // namespace thermion

View File

@@ -14,15 +14,6 @@ extern "C"
using namespace filament;
#endif
EMSCRIPTEN_KEEPALIVE TGizmo* Gizmo_new(TEngine *tEngine, TView *tView, TScene *tScene)
{
auto *view = reinterpret_cast<View*>(tView);
auto *engine = reinterpret_cast<Engine*>(tEngine);
auto *scene = reinterpret_cast<Scene*>(tScene);
auto gizmo = new Gizmo(engine, view, scene);
return reinterpret_cast<TGizmo*>(gizmo);
}
EMSCRIPTEN_KEEPALIVE void Gizmo_pick(TGizmo *tGizmo, uint32_t x, uint32_t y, GizmoPickCallback callback)
{
auto *gizmo = reinterpret_cast<Gizmo*>(tGizmo);

View File

@@ -173,6 +173,14 @@ extern "C"
return ((SceneManager *)sceneManager)->loadGlb(assetPath, numInstances, keepData);
}
EMSCRIPTEN_KEEPALIVE TGizmo* SceneManager_createGizmo(TSceneManager *tSceneManager, TView *tView, TScene *tScene) {
auto sceneManager = reinterpret_cast<SceneManager*>(tSceneManager);
auto *scene = reinterpret_cast<Scene*>(tScene);
auto *view = reinterpret_cast<View*>(tView);
auto gizmo = sceneManager->createGizmo(view, scene);
return reinterpret_cast<TGizmo*>(gizmo);
}
EMSCRIPTEN_KEEPALIVE EntityId SceneManager_loadGlbFromBuffer(TSceneManager *sceneManager, const uint8_t *const data, size_t length, bool keepData, int priority, int layer, bool loadResourcesAsync)
{
return ((SceneManager *)sceneManager)->loadGlbFromBuffer((const uint8_t *)data, length, 1, keepData, priority, layer, loadResourcesAsync);
@@ -1026,6 +1034,12 @@ extern "C"
return reinterpret_cast<TMaterialInstance *>(instance);
}
EMSCRIPTEN_KEEPALIVE TMaterialInstance *SceneManager_createUnlitFixedSizeMaterialInstance(TSceneManager *sceneManager)
{
auto *instance = ((SceneManager *)sceneManager)->createUnlitFixedSizeMaterialInstance();
return reinterpret_cast<TMaterialInstance *>(instance);
}
EMSCRIPTEN_KEEPALIVE void destroy_material_instance(TSceneManager *sceneManager, TMaterialInstance *instance)
{
((SceneManager *)sceneManager)->destroy(reinterpret_cast<MaterialInstance *>(instance));
@@ -1047,6 +1061,10 @@ extern "C"
reinterpret_cast<MaterialInstance *>(materialInstance)->setParameter(propertyName, data);
}
EMSCRIPTEN_KEEPALIVE void MaterialInstance_setParameterFloat(TMaterialInstance *materialInstance, const char *propertyName, double value)
{
reinterpret_cast<MaterialInstance *>(materialInstance)->setParameter(propertyName, static_cast<float>(value));
}
EMSCRIPTEN_KEEPALIVE TCamera *Engine_getCameraComponent(TEngine *tEngine, EntityId entityId)
{

View File

@@ -371,6 +371,16 @@ extern "C"
auto fut = _rl->add_task(lambda);
}
EMSCRIPTEN_KEEPALIVE void SceneManager_createUnlitFixedSizeMaterialInstanceRenderThread(TSceneManager *sceneManager, void (*callback)(TMaterialInstance*)) {
std::packaged_task<void()> lambda(
[=]() mutable
{
auto instance = SceneManager_createUnlitFixedSizeMaterialInstance(sceneManager);
callback(instance);
});
auto fut = _rl->add_task(lambda);
}
EMSCRIPTEN_KEEPALIVE void SceneManager_loadGlbFromBufferRenderThread(TSceneManager *sceneManager,
const uint8_t *const data,
size_t length,

View File

@@ -62,7 +62,7 @@ add_executable(${MODULE_NAME}
"${CMAKE_CURRENT_SOURCE_DIR}/../src/camutils/Manipulator.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/../src/camutils/Bookmark.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/../include/material/image.c"
"${CMAKE_CURRENT_SOURCE_DIR}/../include/material/gizmo.c"
"${CMAKE_CURRENT_SOURCE_DIR}/../include/material/unlit_fixed_size.c"
"${CMAKE_CURRENT_SOURCE_DIR}/src/cpp/ThermionDartWebApi.cpp"
)
set_target_properties(${MODULE_NAME} PROPERTIES

View File

@@ -31,6 +31,29 @@ void main() async {
await viewer.dispose();
});
test('unlit fixed size material', () async {
var viewer = await testHelper.createViewer();
await viewer.setCameraPosition(0, 0, 6);
await viewer.setBackgroundColor(1.0, 0.0, 0.0, 1.0);
await viewer.setPostProcessing(true);
await viewer.setToneMapping(ToneMapper.LINEAR);
var materialInstance = await viewer.createUnlitFixedSizeMaterialInstance();
var cube = await viewer.createGeometry(GeometryHelper.cube(),
materialInstance: materialInstance);
await viewer.setMaterialPropertyFloat4(
cube, "baseColorFactor", 0, 0.0, 1.0, 0.0, 1.0);
await testHelper.capture(viewer, "unlit_fixed_size_default_scale");
await materialInstance.setParameterFloat("scale", 10.0);
await testHelper.capture(viewer, "unlit_fixed_size_scale_10");
await viewer.dispose();
});
test('apply texture to custom ubershader material instance', () async {
var viewer = await testHelper.createViewer();
await viewer.addLight(LightType.SUN, 6500, 1000000, 0, 0, 0, 0, 0, -1);