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 'dart:async';
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.
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
enum PrimitiveType {
// don't change the enums values (made to match GL)
@@ -119,17 +130,13 @@ abstract class AbstractFilamentViewer {
Future removeIbl();
///
/// Adds a dynamic light to the scene.
/// copied from filament LightManager.h
/// enum class Type : uint8_t {
/// 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, //!< Spot light with coupling of outer cone and illumination disabled.
/// };
/// Add a light to the scene.
/// See LightManager.h for details
/// Note that [sunAngularRadius] is in degrees,
/// whereas [spotLightConeInner] and [spotLightConeOuter] are in radians
///
Future<FilamentEntity> addLight(
int type,
LightType type,
double colour,
double intensity,
double posX,
@@ -138,7 +145,16 @@ abstract class AbstractFilamentViewer {
double dirX,
double dirY,
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);

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

View File

@@ -1,8 +1,10 @@
import 'dart:async';
import 'dart:ffi';
import 'dart:io';
import 'dart:math';
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/gizmo.dart';
import 'package:vector_math/vector_math_64.dart';
import 'abstract_filament_viewer.dart';
@@ -100,6 +102,9 @@ class FilamentViewer extends AbstractFilamentViewer {
});
}
Gizmo? _gizmo;
Gizmo? get gizmo => _gizmo;
Future _initialize() async {
final uberarchivePtr =
uberArchivePath?.toNativeUtf8(allocator: allocator).cast<Char>() ??
@@ -119,6 +124,11 @@ class FilamentViewer extends AbstractFilamentViewer {
_scene = SceneImpl(this);
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);
}
@@ -217,7 +227,7 @@ class FilamentViewer extends AbstractFilamentViewer {
@override
Future<FilamentEntity> addLight(
int type,
LightType type,
double colour,
double intensity,
double posX,
@@ -226,10 +236,16 @@ class FilamentViewer extends AbstractFilamentViewer {
double dirX,
double dirY,
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(
_viewer!,
type,
type.index,
colour,
intensity,
posX,
@@ -238,8 +254,17 @@ class FilamentViewer extends AbstractFilamentViewer {
dirX,
dirY,
dirZ,
falloffRadius,
spotLightConeInner,
spotLightConeOuter,
sunAngularRadius = 0.545,
sunHaloSize = 10.0,
sunHaloFallof = 80.0,
castShadows,
callback));
if (entity == _FILAMENT_ASSET_ERROR) {
throw Exception("Failed to add light to scene");
}
_scene.registerLight(entity);
return entity;
@@ -1144,6 +1169,5 @@ class FilamentViewer extends AbstractFilamentViewer {
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 remove_skybox(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 clear_lights(const void *const viewer);
EMSCRIPTEN_KEEPALIVE EntityId load_glb(void *sceneManager, const char *assetPath, int numInstances);

View File

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

View File

@@ -127,7 +127,23 @@ namespace flutter_filament
void scrollEnd();
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 clearLights();
void setPostProcessing(bool enabled);

View File

@@ -99,9 +99,42 @@ extern "C"
((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)

View File

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

View File

@@ -317,26 +317,52 @@ namespace flutter_filament
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 &transformManager = _engine->getTransformManager();
transformManager.create(light);
auto parent = transformManager.getInstance(light);
auto builder = LightManager::Builder(t)
auto result = LightManager::Builder(t)
.color(Color::cct(colour))
.intensity(intensity)
.falloff(falloffRadius)
.spotLightCone(spotLightConeInner, spotLightConeOuter)
.sunAngularRadius(sunAngularRadius)
.sunHaloSize(sunHaloSize)
.sunHaloFalloff(sunHaloFallof)
.position(math::float3(posX, posY, posZ))
.direction(math::float3(dirX, dirY, dirZ))
.castShadows(shadows)
.build(*_engine, light);
_scene->addEntity(light);
_lights.push_back(light);
if(result != LightManager::Builder::Result::Success) {
Log("ERROR : failed to create light");
} else {
_scene->addEntity(light);
_lights.push_back(light);
}
auto entityId = Entity::smuggle(light);
auto transformInstance = transformManager.getInstance(light);
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;
}