addLight now accepts a LightType enum; added support for setting falloff, spot light radius, sun radius & halo

This commit is contained in:
Nick Fisher
2024-05-21 13:23:23 +08:00
parent 173ff4be20
commit d7edf105c4
9 changed files with 224 additions and 30 deletions

View File

@@ -1,3 +1,5 @@
import 'dart:math';
import 'package:vector_math/vector_math_64.dart'; import 'package:vector_math/vector_math_64.dart';
import 'dart:async'; import 'dart:async';
import 'package:animation_tools_dart/animation_tools_dart.dart'; import 'package:animation_tools_dart/animation_tools_dart.dart';
@@ -6,6 +8,15 @@ import 'package:dart_filament/dart_filament/entities/filament_entity.dart';
// "picking" means clicking/tapping on the viewport, and unprojecting the X/Y coordinate to determine whether any renderable entities were present at those coordinates. // "picking" means clicking/tapping on the viewport, and unprojecting the X/Y coordinate to determine whether any renderable entities were present at those coordinates.
typedef FilamentPickResult = ({FilamentEntity entity, double x, double y}); typedef FilamentPickResult = ({FilamentEntity entity, double x, double y});
enum LightType {
SUN, //!< Directional light that also draws a sun's disk in the sky.
DIRECTIONAL, //!< Directional light, emits light in a given direction.
POINT, //!< Point light, emits light from a position, in all directions.
FOCUSED_SPOT, //!< Physically correct spot light.
SPOT,
}
// copied from filament/backened/DriverEnums.h // copied from filament/backened/DriverEnums.h
enum PrimitiveType { enum PrimitiveType {
// don't change the enums values (made to match GL) // don't change the enums values (made to match GL)
@@ -119,17 +130,13 @@ abstract class AbstractFilamentViewer {
Future removeIbl(); Future removeIbl();
/// ///
/// Adds a dynamic light to the scene. /// Add a light to the scene.
/// copied from filament LightManager.h /// See LightManager.h for details
/// enum class Type : uint8_t { /// Note that [sunAngularRadius] is in degrees,
/// SUN, //!< Directional light that also draws a sun's disk in the sky. /// whereas [spotLightConeInner] and [spotLightConeOuter] are in radians
/// DIRECTIONAL, //!< Directional light, emits light in a given direction. ///
/// POINT, //!< Point light, emits light from a position, in all directions.
/// FOCUSED_SPOT, //!< Physically correct spot light.
/// SPOT, //!< Spot light with coupling of outer cone and illumination disabled.
/// };
Future<FilamentEntity> addLight( Future<FilamentEntity> addLight(
int type, LightType type,
double colour, double colour,
double intensity, double intensity,
double posX, double posX,
@@ -138,7 +145,16 @@ abstract class AbstractFilamentViewer {
double dirX, double dirX,
double dirY, double dirY,
double dirZ, double dirZ,
bool castShadows); {
double falloffRadius=1.0,
double spotLightConeInner=pi/8,
double spotLightConeOuter=pi/4,
double sunAngularRadius=0.545,
double sunHaloSize=10.0,
double sunHaloFallof=80.0,
bool castShadows=true
}
);
Future removeLight(FilamentEntity light); Future removeLight(FilamentEntity light);

View File

@@ -163,6 +163,12 @@ external void remove_ibl(
ffi.Float, ffi.Float,
ffi.Float, ffi.Float,
ffi.Float, ffi.Float,
ffi.Float,
ffi.Float,
ffi.Float,
ffi.Float,
ffi.Float,
ffi.Float,
ffi.Bool)>( ffi.Bool)>(
symbol: 'add_light', assetId: 'package:dart_filament/dart_filament.dart') symbol: 'add_light', assetId: 'package:dart_filament/dart_filament.dart')
external int add_light( external int add_light(
@@ -176,6 +182,12 @@ external int add_light(
double dirX, double dirX,
double dirY, double dirY,
double dirZ, double dirZ,
double falloffRadius,
double spotLightConeInner,
double spotLightConeOuter,
double sunAngularRadius,
double sunHaloSize,
double sunHaloFallof,
bool shadows, bool shadows,
); );
@@ -1307,6 +1319,12 @@ external void remove_ibl_ffi(
ffi.Float, ffi.Float,
ffi.Float, ffi.Float,
ffi.Float, ffi.Float,
ffi.Float,
ffi.Float,
ffi.Float,
ffi.Float,
ffi.Float,
ffi.Float,
ffi.Bool, ffi.Bool,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function(EntityId)>>)>( ffi.Pointer<ffi.NativeFunction<ffi.Void Function(EntityId)>>)>(
symbol: 'add_light_ffi', symbol: 'add_light_ffi',
@@ -1322,6 +1340,12 @@ external void add_light_ffi(
double dirX, double dirX,
double dirY, double dirY,
double dirZ, double dirZ,
double falloffRadius,
double spotLightConeInner,
double spotLightConeOuter,
double sunAngularRadius,
double sunHaloSize,
double sunHaloFallof,
bool shadows, bool shadows,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function(EntityId)>> callback, ffi.Pointer<ffi.NativeFunction<ffi.Void Function(EntityId)>> callback,
); );

View File

@@ -1,8 +1,10 @@
import 'dart:async'; import 'dart:async';
import 'dart:ffi'; import 'dart:ffi';
import 'dart:io'; import 'dart:io';
import 'dart:math';
import 'package:animation_tools_dart/animation_tools_dart.dart'; import 'package:animation_tools_dart/animation_tools_dart.dart';
import 'package:dart_filament/dart_filament/entities/filament_entity.dart'; import 'package:dart_filament/dart_filament/entities/filament_entity.dart';
import 'package:dart_filament/dart_filament/entities/gizmo.dart';
import 'package:vector_math/vector_math_64.dart'; import 'package:vector_math/vector_math_64.dart';
import 'abstract_filament_viewer.dart'; import 'abstract_filament_viewer.dart';
@@ -100,6 +102,9 @@ class FilamentViewer extends AbstractFilamentViewer {
}); });
} }
Gizmo? _gizmo;
Gizmo? get gizmo => _gizmo;
Future _initialize() async { Future _initialize() async {
final uberarchivePtr = final uberarchivePtr =
uberArchivePath?.toNativeUtf8(allocator: allocator).cast<Char>() ?? uberArchivePath?.toNativeUtf8(allocator: allocator).cast<Char>() ??
@@ -119,6 +124,11 @@ class FilamentViewer extends AbstractFilamentViewer {
_scene = SceneImpl(this); _scene = SceneImpl(this);
await setCameraManipulatorOptions(zoomSpeed: 10.0); await setCameraManipulatorOptions(zoomSpeed: 10.0);
final out = calloc<Int32>(3);
get_gizmo(_sceneManager!, out);
_gizmo = Gizmo(out[0], out[1], out[2], this);
calloc.free(out);
this._initialized.complete(true); this._initialized.complete(true);
} }
@@ -217,7 +227,7 @@ class FilamentViewer extends AbstractFilamentViewer {
@override @override
Future<FilamentEntity> addLight( Future<FilamentEntity> addLight(
int type, LightType type,
double colour, double colour,
double intensity, double intensity,
double posX, double posX,
@@ -226,10 +236,16 @@ class FilamentViewer extends AbstractFilamentViewer {
double dirX, double dirX,
double dirY, double dirY,
double dirZ, double dirZ,
bool castShadows) async { {double falloffRadius = 1.0,
double spotLightConeInner = pi / 8,
double spotLightConeOuter = pi / 4,
double sunAngularRadius = 0.545,
double sunHaloSize = 10.0,
double sunHaloFallof = 80.0,
bool castShadows = true}) async {
var entity = await withIntCallback((callback) => add_light_ffi( var entity = await withIntCallback((callback) => add_light_ffi(
_viewer!, _viewer!,
type, type.index,
colour, colour,
intensity, intensity,
posX, posX,
@@ -238,8 +254,17 @@ class FilamentViewer extends AbstractFilamentViewer {
dirX, dirX,
dirY, dirY,
dirZ, dirZ,
falloffRadius,
spotLightConeInner,
spotLightConeOuter,
sunAngularRadius = 0.545,
sunHaloSize = 10.0,
sunHaloFallof = 80.0,
castShadows, castShadows,
callback)); callback));
if (entity == _FILAMENT_ASSET_ERROR) {
throw Exception("Failed to add light to scene");
}
_scene.registerLight(entity); _scene.registerLight(entity);
return entity; return entity;
@@ -1144,6 +1169,5 @@ class FilamentViewer extends AbstractFilamentViewer {
set_priority(_sceneManager!, entityId, priority); set_priority(_sceneManager!, entityId, priority);
} }
@override
AbstractGizmo? get gizmo => null;
} }

View File

@@ -71,7 +71,24 @@ extern "C"
EMSCRIPTEN_KEEPALIVE void rotate_ibl(const void *const viewer, float *rotationMatrix); EMSCRIPTEN_KEEPALIVE void rotate_ibl(const void *const viewer, float *rotationMatrix);
EMSCRIPTEN_KEEPALIVE void remove_skybox(const void *const viewer); EMSCRIPTEN_KEEPALIVE void remove_skybox(const void *const viewer);
EMSCRIPTEN_KEEPALIVE void remove_ibl(const void *const viewer); EMSCRIPTEN_KEEPALIVE void remove_ibl(const void *const viewer);
EMSCRIPTEN_KEEPALIVE EntityId add_light(const void *const viewer, uint8_t type, float colour, float intensity, float posX, float posY, float posZ, float dirX, float dirY, float dirZ, bool shadows); EMSCRIPTEN_KEEPALIVE EntityId add_light(
const void *const viewer,
uint8_t type,
float colour,
float intensity,
float posX,
float posY,
float posZ,
float dirX,
float dirY,
float dirZ,
float falloffRadius,
float spotLightConeInner,
float spotLightConeOuter,
float sunAngularRadius,
float sunHaloSize,
float sunHaloFallof,
bool shadows);
EMSCRIPTEN_KEEPALIVE void remove_light(const void *const viewer, EntityId entityId); EMSCRIPTEN_KEEPALIVE void remove_light(const void *const viewer, EntityId entityId);
EMSCRIPTEN_KEEPALIVE void clear_lights(const void *const viewer); EMSCRIPTEN_KEEPALIVE void clear_lights(const void *const viewer);
EMSCRIPTEN_KEEPALIVE EntityId load_glb(void *sceneManager, const char *assetPath, int numInstances); EMSCRIPTEN_KEEPALIVE EntityId load_glb(void *sceneManager, const char *assetPath, int numInstances);

View File

@@ -54,6 +54,12 @@ extern "C"
float dirX, float dirX,
float dirY, float dirY,
float dirZ, float dirZ,
float falloffRadius,
float spotLightConeInner,
float spotLightConeOuter,
float sunAngularRadius,
float sunHaloSize,
float sunHaloFallof,
bool shadows, bool shadows,
void (*callback)(EntityId)); void (*callback)(EntityId));
EMSCRIPTEN_KEEPALIVE void remove_light_ffi(void *const viewer, EntityId entityId); EMSCRIPTEN_KEEPALIVE void remove_light_ffi(void *const viewer, EntityId entityId);

View File

@@ -127,7 +127,23 @@ namespace flutter_filament
void scrollEnd(); void scrollEnd();
void pick(uint32_t x, uint32_t y, void (*callback)(EntityId entityId, int x, int y)); void pick(uint32_t x, uint32_t y, void (*callback)(EntityId entityId, int x, int y));
EntityId addLight(LightManager::Type t, float colour, float intensity, float posX, float posY, float posZ, float dirX, float dirY, float dirZ, bool shadows); EntityId addLight(
LightManager::Type t,
float colour,
float intensity,
float posX,
float posY,
float posZ,
float dirX,
float dirY,
float dirZ,
float falloffRadius,
float spotLightConeInner,
float spotLightConeOuter,
float sunAngularRadius,
float sunHaloSize,
float sunHaloFallof,
bool shadows);
void removeLight(EntityId entityId); void removeLight(EntityId entityId);
void clearLights(); void clearLights();
void setPostProcessing(bool enabled); void setPostProcessing(bool enabled);

View File

@@ -99,9 +99,42 @@ extern "C"
((FilamentViewer *)viewer)->removeIbl(); ((FilamentViewer *)viewer)->removeIbl();
} }
EntityId add_light(const void *const viewer, uint8_t type, float colour, float intensity, float posX, float posY, float posZ, float dirX, float dirY, float dirZ, bool shadows) EntityId add_light(
const void *const viewer,
uint8_t type,
float colour,
float intensity,
float posX,
float posY,
float posZ,
float dirX,
float dirY,
float dirZ,
float falloffRadius,
float spotLightConeInner,
float spotLightConeOuter,
float sunAngularRadius,
float sunHaloSize,
float sunHaloFallof,
bool shadows)
{ {
return ((FilamentViewer *)viewer)->addLight((LightManager::Type)type, colour, intensity, posX, posY, posZ, dirX, dirY, dirZ, shadows); return ((FilamentViewer *)viewer)->addLight(
(LightManager::Type)type,
colour,
intensity,
posX,
posY,
posZ,
dirX,
dirY,
dirZ,
falloffRadius,
spotLightConeInner,
spotLightConeOuter,
sunAngularRadius,
sunHaloSize,
sunHaloFallof,
shadows);
} }
EMSCRIPTEN_KEEPALIVE void remove_light(const void *const viewer, int32_t entityId) EMSCRIPTEN_KEEPALIVE void remove_light(const void *const viewer, int32_t entityId)

View File

@@ -480,14 +480,46 @@ extern "C"
auto fut = _rl->add_task(lambda); auto fut = _rl->add_task(lambda);
} }
void add_light_ffi(void *const viewer, uint8_t type, float colour, void add_light_ffi(
float intensity, float posX, float posY, float posZ, void *const viewer,
float dirX, float dirY, float dirZ, bool shadows, void (*callback)(EntityId)) uint8_t type,
float colour,
float intensity,
float posX,
float posY,
float posZ,
float dirX,
float dirY,
float dirZ,
float falloffRadius,
float spotLightConeInner,
float spotLightConeOuter,
float sunAngularRadius,
float sunHaloSize,
float sunHaloFallof,
bool shadows,
void (*callback)(EntityId))
{ {
std::packaged_task<EntityId()> lambda([=] std::packaged_task<EntityId()> lambda([=]
{ {
auto entity = add_light(viewer, type, colour, intensity, posX, posY, posZ, dirX, auto entity = add_light(
dirY, dirZ, shadows); viewer,
type,
colour,
intensity,
posX,
posY,
posZ,
dirX,
dirY,
dirZ,
falloffRadius,
spotLightConeInner,
spotLightConeOuter,
sunAngularRadius,
sunHaloSize,
sunHaloFallof,
shadows);
#ifdef __EMSCRIPTEN__ #ifdef __EMSCRIPTEN__
MAIN_THREAD_EM_ASM({ MAIN_THREAD_EM_ASM({
moduleArg.dartFilamentResolveCallback($0, $1); moduleArg.dartFilamentResolveCallback($0, $1);

View File

@@ -317,26 +317,52 @@ namespace flutter_filament
Log("Set frame interval to %f", frameInterval); Log("Set frame interval to %f", frameInterval);
} }
int32_t FilamentViewer::addLight(LightManager::Type t, float colour, float intensity, float posX, float posY, float posZ, float dirX, float dirY, float dirZ, bool shadows) EntityId FilamentViewer::addLight(
LightManager::Type t,
float colour,
float intensity,
float posX,
float posY,
float posZ,
float dirX,
float dirY,
float dirZ,
float falloffRadius,
float spotLightConeInner,
float spotLightConeOuter,
float sunAngularRadius,
float sunHaloSize,
float sunHaloFallof,
bool shadows)
{ {
auto light = EntityManager::get().create(); auto light = EntityManager::get().create();
auto &transformManager = _engine->getTransformManager(); auto &transformManager = _engine->getTransformManager();
transformManager.create(light); transformManager.create(light);
auto parent = transformManager.getInstance(light); auto parent = transformManager.getInstance(light);
auto builder = LightManager::Builder(t)
auto result = LightManager::Builder(t)
.color(Color::cct(colour)) .color(Color::cct(colour))
.intensity(intensity) .intensity(intensity)
.falloff(falloffRadius)
.spotLightCone(spotLightConeInner, spotLightConeOuter)
.sunAngularRadius(sunAngularRadius)
.sunHaloSize(sunHaloSize)
.sunHaloFalloff(sunHaloFallof)
.position(math::float3(posX, posY, posZ)) .position(math::float3(posX, posY, posZ))
.direction(math::float3(dirX, dirY, dirZ)) .direction(math::float3(dirX, dirY, dirZ))
.castShadows(shadows) .castShadows(shadows)
.build(*_engine, light); .build(*_engine, light);
_scene->addEntity(light); if(result != LightManager::Builder::Result::Success) {
_lights.push_back(light); Log("ERROR : failed to create light");
} else {
_scene->addEntity(light);
_lights.push_back(light);
}
auto entityId = Entity::smuggle(light); auto entityId = Entity::smuggle(light);
auto transformInstance = transformManager.getInstance(light); auto transformInstance = transformManager.getInstance(light);
transformManager.setTransform(transformInstance, math::mat4::translation(math::float3{posX, posY, posZ})); transformManager.setTransform(transformInstance, math::mat4::translation(math::float3{posX, posY, posZ}));
Log("Added light under entity ID %d of type %d with colour %f intensity %f at (%f, %f, %f) with direction (%f, %f, %f) with shadows %d", entityId, t, colour, intensity, posX, posY, posZ, dirX, dirY, dirZ, shadows); // Log("Added light under entity ID %d of type %d with colour %f intensity %f at (%f, %f, %f) with direction (%f, %f, %f) with shadows %d", entityId, t, colour, intensity, posX, posY, posZ, dirX, dirY, dirZ, shadows);
return entityId; return entityId;
} }