rename setLayerEnabled to setLayerVisibility, add setVisibilityLayer method

This commit is contained in:
Nick Fisher
2024-09-20 17:34:17 +08:00
parent 686b4800aa
commit 820ad7cb28
9 changed files with 124 additions and 25 deletions

View File

@@ -1155,10 +1155,18 @@ external void get_bounding_box_to_out(
@ffi.Native<ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Int, ffi.Bool)>(
isLeaf: true)
external void set_layer_enabled(
external void set_layer_visibility(
ffi.Pointer<ffi.Void> sceneManager,
int layer,
bool enabled,
bool visible,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<ffi.Void>, EntityId, ffi.Int)>(
isLeaf: true)
external void set_visibility_layer(
ffi.Pointer<ffi.Void> sceneManager,
int entity,
int layer,
);
@ffi.Native<
@@ -1203,6 +1211,15 @@ external void remove_stencil_highlight(
int entity,
);
@ffi.Native<
ffi.Pointer<TMaterialInstance> Function(
ffi.Pointer<ffi.Void>, EntityId, ffi.Int)>(isLeaf: true)
external ffi.Pointer<TMaterialInstance> get_material_instance_at(
ffi.Pointer<ffi.Void> sceneManager,
int entity,
int materialIndex,
);
@ffi.Native<
ffi.Void Function(ffi.Pointer<ffi.Void>, EntityId, ffi.Int,
ffi.Pointer<ffi.Char>, ffi.Float)>(isLeaf: true)

View File

@@ -1920,8 +1920,17 @@ class ThermionViewerFFI extends ThermionViewer {
///
///
///
Future setLayerEnabled(int layer, bool enabled) async {
set_layer_enabled(_sceneManager!, layer, enabled);
Future setLayerVisibility(int layer, bool visible) {
set_layer_visibility(_sceneManager!, layer, visible);
return Future.value();
}
///
///
///
Future setVisibilityLayer(ThermionEntity entity, int layer) {
set_visibility_layer(_sceneManager!, entity, layer);
return Future.value();
}
///

View File

@@ -545,7 +545,7 @@ abstract class ThermionViewer {
Future moveCameraToAsset(ThermionEntity entity);
///
/// Enables/disables frustum culling. Currently we don't expose a method for manipulating the camera projection/culling matrices so this is your only option to deal with unwanted near/far clipping.
/// Enables/disables frustum culling.
///
Future setViewFrustumCulling(bool enabled);
@@ -596,14 +596,15 @@ abstract class ThermionViewer {
/// Sets the material property [propertyName] under material [materialIndex] for [entity] to [value].
/// [entity] must have a Renderable attached.
///
Future setMaterialPropertyInt(ThermionEntity entity, String propertyName,
int materialIndex, int value);
Future setMaterialPropertyInt(
ThermionEntity entity, String propertyName, int materialIndex, int value);
///
/// Sets the depthWrite material instance at [materialIndex] for [entity] to [enabled].
/// [entity] must have a Renderable attached.
///
Future setMaterialDepthWrite(ThermionEntity entity, int materialIndex, bool enabled);
Future setMaterialDepthWrite(
ThermionEntity entity, int materialIndex, bool enabled);
///
/// Scale [entity] to fit within the unit cube.
@@ -853,7 +854,12 @@ abstract class ThermionViewer {
/// We place all scene assets in layer 0 (enabled by default), gizmos in layer 1 (enabled by default), world grid in layer 2 (disabled by default).
/// Use this method to toggle visibility of the respective layer.
///
Future setLayerEnabled(int layer, bool enabled);
Future setLayerVisibility(int layer, bool visible);
///
/// Assigns [entity] to visibility layer [layer].
///
Future setVisibilityLayer(ThermionEntity entity, int layer);
///
/// Show/hide the translation gizmo.

View File

@@ -55,6 +55,7 @@ namespace thermion_filament
enum LAYERS {
DEFAULT_ASSETS = 0,
BACKGROUND = 6,
OVERLAY = 7,
};
@@ -229,11 +230,8 @@ namespace thermion_filament
///
/// Toggles the visibility of the given layer.
/// Layer 0 - regular scene assets
/// Layer 1 - unused
/// Layer 2 - grid
///
void setLayerEnabled(int layer, bool enabled);
void setLayerVisibility(SceneManager::LAYERS layer, bool enabled);
///
/// Creates an entity with the specified geometry/material/normals and adds to the scene.
@@ -284,6 +282,8 @@ namespace thermion_filament
return _assetLoader->createInstance(asset);
}
MaterialInstance* getMaterialInstanceAt(EntityId entityId, int materialIndex);
void setMaterialProperty(EntityId entity, int materialIndex, const char* property, float value);
void setMaterialProperty(EntityId entity, int materialIndex, const char* property, int32_t value);
void setMaterialProperty(EntityId entityId, int materialIndex, const char* property, filament::math::float4& value);
@@ -298,6 +298,8 @@ namespace thermion_filament
MaterialInstance* createUnlitMaterialInstance();
void setVisibilityLayer(EntityId entityId, int layer);
private:
gltfio::AssetLoader *_assetLoader = nullptr;
const ResourceLoaderWrapperImpl *const _resourceLoaderWrapper;

View File

@@ -269,11 +269,13 @@ extern "C"
EMSCRIPTEN_KEEPALIVE void get_gizmo(void *const sceneManager, EntityId *out);
EMSCRIPTEN_KEEPALIVE Aabb2 get_bounding_box(void *const sceneManager, EntityId entity);
EMSCRIPTEN_KEEPALIVE void get_bounding_box_to_out(void *const sceneManager, EntityId entity, float *minX, float *minY, float *maxX, float *maxY);
EMSCRIPTEN_KEEPALIVE void set_layer_enabled(void *const sceneManager, int layer, bool enabled);
EMSCRIPTEN_KEEPALIVE void set_layer_visibility(void *const sceneManager, int layer, bool visible);
EMSCRIPTEN_KEEPALIVE void set_visibility_layer(void *const sceneManager, EntityId entity, int layer);
EMSCRIPTEN_KEEPALIVE void pick_gizmo(void *const sceneManager, int x, int y, void (*callback)(EntityId entityId, int x, int y));
EMSCRIPTEN_KEEPALIVE void set_gizmo_visibility(void *const sceneManager, bool visible);
EMSCRIPTEN_KEEPALIVE void set_stencil_highlight(void *const sceneManager, EntityId entity, float r, float g, float b);
EMSCRIPTEN_KEEPALIVE void remove_stencil_highlight(void *const sceneManager, EntityId entity);
EMSCRIPTEN_KEEPALIVE TMaterialInstance* get_material_instance_at(void *const sceneManager, EntityId entity, int materialIndex);
EMSCRIPTEN_KEEPALIVE void set_material_property_float(void *const sceneManager, EntityId entity, int materialIndex, const char *property, float value);
EMSCRIPTEN_KEEPALIVE void set_material_property_int(void *const sceneManager, EntityId entity, int materialIndex, const char *property, int value);
EMSCRIPTEN_KEEPALIVE void set_material_property_float4(void *const sceneManager, EntityId entity, int materialIndex, const char *property, double4 value);

View File

@@ -584,6 +584,7 @@ namespace thermion_filament
.material(0, _imageMaterial->getDefaultInstance())
.geometry(0, RenderableManager::PrimitiveType::TRIANGLES, _imageVb,
_imageIb, 0, 3)
.layerMask(0xFF, 1u << SceneManager::LAYERS::BACKGROUND)
.culling(false)
.build(*_engine, _imageEntity);
_scene->addEntity(_imageEntity);
@@ -969,7 +970,11 @@ namespace thermion_filament
delete vec; },
callbackData);
_skybox =
filament::Skybox::Builder().environment(_skyboxTexture).build(*_engine);
filament::Skybox::Builder()
.environment(_skyboxTexture)
.build(*_engine);
_skybox->setLayerMask(0xFF, 1u << SceneManager::LAYERS::BACKGROUND);
_scene->setSkybox(_skybox);
}

View File

@@ -104,6 +104,7 @@ namespace thermion_filament
_scene->addEntity(_gridOverlay->grid());
_view->setLayerEnabled(SceneManager::LAYERS::DEFAULT_ASSETS, true);
_view->setLayerEnabled(SceneManager::LAYERS::BACKGROUND, true); // skybox + image
_view->setLayerEnabled(SceneManager::LAYERS::OVERLAY, false); // world grid + gizmo
}
@@ -238,6 +239,17 @@ namespace thermion_filament
return eid;
}
void SceneManager::setVisibilityLayer(EntityId entityId, int layer) {
auto& rm = _engine->getRenderableManager();
auto renderable = rm.getInstance(utils::Entity::import(entityId));
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)
{
@@ -2393,7 +2405,7 @@ namespace thermion_filament
return Aabb2{minX, minY, maxX, maxY};
}
void SceneManager::setLayerEnabled(int layer, bool enabled)
void SceneManager::setLayerVisibility(LAYERS layer, bool enabled)
{
_view->setLayerEnabled(layer, enabled);
}
@@ -2528,6 +2540,18 @@ EntityId SceneManager::createGeometry(
return entityId;
}
MaterialInstance* SceneManager::getMaterialInstanceAt(EntityId entityId, int materialIndex) {
auto entity = Entity::import(entityId);
const auto &rm = _engine->getRenderableManager();
auto renderableInstance = rm.getInstance(entity);
if (!renderableInstance.isValid())
{
Log("Error retrieving material instance: no renderable found for entity %d");
return std::nullptr_t();
}
return rm.getMaterialInstanceAt(renderableInstance, materialIndex);
}
void SceneManager::setMaterialProperty(EntityId entityId, int materialIndex, const char *property, float value)
{
auto entity = Entity::import(entityId);
@@ -2620,7 +2644,6 @@ EntityId SceneManager::createGeometry(
return;
}
auto materialInstance = rm.getMaterialInstanceAt(renderableInstance, materialIndex);
materialInstance->setDepthWrite(enabled);
}

View File

@@ -927,9 +927,14 @@ extern "C"
*maxY = box.maxY;
}
EMSCRIPTEN_KEEPALIVE void set_layer_enabled(void *const sceneManager, int layer, bool enabled)
EMSCRIPTEN_KEEPALIVE void set_visibility_layer(void *const sceneManager, EntityId entity, int layer) {
((SceneManager*)sceneManager)->setVisibilityLayer(entity, layer);
}
EMSCRIPTEN_KEEPALIVE void set_layer_visibility(void *const sceneManager, int layer, bool visible)
{
((SceneManager *)sceneManager)->setLayerEnabled(layer, enabled);
((SceneManager *)sceneManager)->setLayerVisibility((SceneManager::LAYERS)layer, visible);
}
EMSCRIPTEN_KEEPALIVE void thermion_flutter_free(void *ptr)
@@ -962,9 +967,13 @@ extern "C"
((SceneManager *)sceneManager)->setMaterialProperty(entity, materialIndex, property, value);
}
EMSCRIPTEN_KEEPALIVE TMaterialInstance* get_material_instance_at(void *const sceneManager, EntityId entity, int materialIndex) {
auto instance = ((SceneManager *)sceneManager)->getMaterialInstanceAt(entity, materialIndex);
return reinterpret_cast<TMaterialInstance*>(instance);
}
EMSCRIPTEN_KEEPALIVE void set_material_property_int(void *const sceneManager, EntityId entity, int materialIndex, const char *property, int32_t value)
{
((SceneManager *)sceneManager)->setMaterialProperty(entity, materialIndex, property, value);
}

View File

@@ -569,10 +569,9 @@ void main() async {
await viewer.setMaterialDepthWrite(cube2, 0, true);
await _capture(viewer, "geometry_enable_depth_write");
// with depth write disabled on both materials, the red cube will render in front of the white cube
// with depth write disabled on the first material, the red cube will render in front of the white cube
// (relying on insertion order)
await viewer.setMaterialDepthWrite(cube1, 0, false);
await viewer.setMaterialDepthWrite(cube2, 0, false);
await _capture(viewer, "geometry_disable_depth_write_insertion_order");
@@ -649,9 +648,9 @@ void main() async {
.setCameraRotation(Quaternion.axisAngle(Vector3(1, 0, 0), -pi / 8));
await viewer.setCameraPosition(0, 2, 0);
await _capture(viewer, "grid_overlay_default");
await viewer.setLayerEnabled(7, true);
await viewer.setLayerVisibility(7, true);
await _capture(viewer, "grid_overlay_enabled");
await viewer.setLayerEnabled(7, false);
await viewer.setLayerVisibility(7, false);
await _capture(viewer, "grid_overlay_disabled");
});
@@ -666,9 +665,36 @@ void main() async {
var buffer = File("$testDir/cube.glb").readAsBytesSync();
var model = await viewer.loadGlbFromBuffer(buffer, layer: 1);
await _capture(viewer, "load_glb_from_buffer_with_layer_disabled");
await viewer.setLayerEnabled(1, true);
await viewer.setLayerVisibility(1, true);
await _capture(viewer, "load_glb_from_buffer_with_layer_enabled");
});
test('change layer visibility at runtime', () async {
var viewer = await createViewer();
await viewer.setBackgroundColor(1, 0, 1, 1);
await viewer.setCameraPosition(0, 2, 5);
await viewer
.setCameraRotation(Quaternion.axisAngle(Vector3(1, 0, 0), -0.5));
var cube = await viewer.createGeometry(GeometryHelper.cube());
await _capture(viewer, "change_layer_visibility_at_runtime_default");
// all entities set to layer 0 by default, so this should now be invisible
await viewer.setLayerVisibility(0, false);
await _capture(
viewer, "change_layer_visibility_at_runtime_layer0_invisible");
// now change the visibility layer to 5, should be invisible
await viewer.setVisibilityLayer(cube, 5);
await _capture(
viewer, "change_layer_visibility_at_runtime_layer5_invisible");
// now toggle layer 5 visibility, cube should now be visible
await viewer.setLayerVisibility(5, true);
await _capture(
viewer, "change_layer_visibility_at_runtime_layer5_visible");
});
});
// test('point light', () async {