feat: expose setLightDirection and setLightPosition

This commit is contained in:
Nick Fisher
2024-09-05 22:18:54 +08:00
parent c93cc296a0
commit d17cce2ca4
8 changed files with 122 additions and 19 deletions

View File

@@ -183,6 +183,28 @@ external void clear_lights(
ffi.Pointer<ffi.Void> viewer,
);
@ffi.Native<
ffi.Void Function(
ffi.Pointer<ffi.Void>, EntityId, ffi.Float, ffi.Float, ffi.Float)>()
external void set_light_position(
ffi.Pointer<ffi.Void> viewer,
int light,
double x,
double y,
double z,
);
@ffi.Native<
ffi.Void Function(
ffi.Pointer<ffi.Void>, EntityId, ffi.Float, ffi.Float, ffi.Float)>()
external void set_light_direction(
ffi.Pointer<ffi.Void> viewer,
int light,
double x,
double y,
double z,
);
@ffi.Native<
EntityId Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Char>, ffi.Int)>()
external int load_glb(

View File

@@ -2256,4 +2256,28 @@ class ThermionViewerWasm implements ThermionViewer {
[_sceneManager!, visible.toJS].toJS,
null);
}
@override
Future setLightDirection(ThermionEntity lightEntity, Vector3 direction) async {
direction.normalize();
_module!.ccall(
"set_light_direction",
"void",
["void*".toJS, "double".toJS, "double".toJS, "double".toJS].toJS,
[_viewer!, direction.x.toJS, direction.y.toJS, direction.z.toJS]
.toJS,
null);
}
@override
Future setLightPosition(
ThermionEntity lightEntity, double x, double y, double z) async {
_module!.ccall(
"set_light_position",
"void",
["void*".toJS, "double".toJS, "double".toJS, "double".toJS].toJS,
[_viewer!, x.toJS,y.toJS,z.toJS]
.toJS,
null);
}
}

View File

@@ -570,10 +570,20 @@ abstract class ThermionViewer {
Future transformToUnitCube(ThermionEntity entity);
///
/// Directly sets the world space position for [entity] to the given coordinates, skipping all collision detection.
/// Directly sets the world space position for [entity] to the given coordinates.
///
Future setPosition(ThermionEntity entity, double x, double y, double z);
///
/// Set the world space position for [lightEntity] to the given coordinates.
///
Future setLightPosition(ThermionEntity lightEntity, double x, double y, double z);
///
/// Sets the world space direction for [lightEntity] to the given vector.
///
Future setLightDirection(ThermionEntity lightEntity, Vector3 direction);
///
/// Directly sets the scale for [entity], skipping all collision detection.
///

View File

@@ -1287,6 +1287,24 @@ class ThermionViewerFFI extends ThermionViewer {
set_position(_sceneManager!, entity, x, y, z);
}
///
///
///
@override
Future setLightPosition(
ThermionEntity lightEntity, double x, double y, double z) async {
set_light_position(_viewer!, lightEntity, x, y, z);
}
///
///
///
@override
Future setLightDirection(ThermionEntity lightEntity, Vector3 direction) async {
direction.normalize();
set_light_direction(_viewer!, lightEntity, direction.x, direction.y, direction.z);
}
///
///
///

View File

@@ -147,6 +147,8 @@ namespace thermion_filament
float sunHaloSize,
float sunHaloFallof,
bool shadows);
void setLightPosition(EntityId entityId, float x, float y, float z);
void setLightDirection(EntityId entityId, float x, float y, float z);
void removeLight(EntityId entityId);
void clearLights();
void setPostProcessing(bool enabled);

View File

@@ -93,6 +93,8 @@ extern "C"
bool shadows);
EMSCRIPTEN_KEEPALIVE void remove_light(const void *const viewer, EntityId entityId);
EMSCRIPTEN_KEEPALIVE void clear_lights(const void *const viewer);
EMSCRIPTEN_KEEPALIVE void set_light_position(const void *const viewer, EntityId light, float x, float y, float z);
EMSCRIPTEN_KEEPALIVE void set_light_direction(const void *const viewer, EntityId light, float x, float y, float z);
EMSCRIPTEN_KEEPALIVE EntityId load_glb(void *sceneManager, const char *assetPath, int numInstances);
EMSCRIPTEN_KEEPALIVE EntityId load_glb_from_buffer(void *sceneManager, const void *const data, size_t length);
EMSCRIPTEN_KEEPALIVE EntityId load_gltf(void *sceneManager, const char *assetPath, const char *relativePath);

View File

@@ -288,7 +288,6 @@ namespace thermion_filament
fro.interval = 1; // frameInterval;
fro.history = 5;
_renderer->setFrameRateOptions(fro);
Log("Set frame interval to %f", frameInterval);
}
EntityId FilamentViewer::addLight(
@@ -310,9 +309,6 @@ namespace thermion_filament
bool shadows)
{
auto light = EntityManager::get().create();
auto &transformManager = _engine->getTransformManager();
transformManager.create(light);
auto parent = transformManager.getInstance(light);
auto result = LightManager::Builder(t)
.color(Color::cct(colour))
@@ -336,16 +332,43 @@ namespace thermion_filament
_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);
return entityId;
return Entity::smuggle(light);
}
void FilamentViewer::setLightPosition(EntityId entityId, float x, float y, float z) {
auto light = Entity::import(entityId);
if(light.isNull()) {
Log("Light not found for entity %d", entityId);
return;
}
auto& lm = _engine->getLightManager();
auto instance = lm.getInstance(light);
lm.setPosition(instance, filament::math::float3 { x, y, z });
}
void FilamentViewer::setLightDirection(EntityId entityId, float x, float y, float z) {
auto light = Entity::import(entityId);
if(light.isNull()) {
Log("Light not found for entity %d", entityId);
return;
}
auto& lm = _engine->getLightManager();
auto instance = lm.getInstance(light);
lm.setDirection(instance, filament::math::float3 { x, y, z });
}
void FilamentViewer::removeLight(EntityId entityId)
{
Log("Removing light with entity ID %d", entityId);
auto entity = utils::Entity::import(entityId);
if (entity.isNull())
{
@@ -361,7 +384,6 @@ namespace thermion_filament
void FilamentViewer::clearLights()
{
Log("Removing all lights");
_scene->removeEntities(_lights.data(), _lights.size());
EntityManager::get().destroy(_lights.size(), _lights.data());
_lights.clear();
@@ -1364,7 +1386,6 @@ namespace thermion_filament
{
if (!_view || !_mainCamera)
{
Log("Skipping camera update, no view or camrea");
return;
}
@@ -1379,8 +1400,6 @@ namespace thermion_filament
cam.setLensProjection(_cameraFocalLength, aspect, _near,
_far);
Log("Set viewport to width: %d height: %d aspect %f scaleFactor : %f", width, height, aspect,
contentScaleFactor);
}
void FilamentViewer::setViewFrustumCulling(bool enabled)
@@ -1398,7 +1417,7 @@ namespace thermion_filament
{
Camera &cam = _view->getCamera();
const auto &vp = _view->getViewport();
auto aspect = vp.width / vp.height;
const float aspect = static_cast<float>(vp.width) / static_cast<float>(vp.height);
cam.setProjection(fovInDegrees, aspect, _near, _far, horizontal ? Camera::Fov::HORIZONTAL : Camera::Fov::VERTICAL);
}
@@ -1672,7 +1691,7 @@ namespace thermion_filament
if (materialPath)
{
auto matData = _resourceLoaderWrapper->load(materialPath);
auto mat = Material::Builder().package(matData.data, matData.size).build(*_engine);
mat = Material::Builder().package(matData.data, matData.size).build(*_engine);
_resourceLoaderWrapper->free(matData);
}
@@ -1706,8 +1725,6 @@ namespace thermion_filament
_scene->addEntity(renderable);
Log("Created geometry with primitive type %d (result %d)", primitiveType, result);
return Entity::smuggle(renderable);
}

View File

@@ -148,6 +148,14 @@ extern "C"
shadows);
}
EMSCRIPTEN_KEEPALIVE void set_light_position(const void *const viewer, int32_t entityId, float x, float y, float z) {
((FilamentViewer*)viewer)->setLightPosition(entityId, x, y, z);
}
EMSCRIPTEN_KEEPALIVE void set_light_direction(const void *const viewer, int32_t entityId, float x, float y, float z) {
((FilamentViewer*)viewer)->setLightDirection(entityId, x, y, z);
}
EMSCRIPTEN_KEEPALIVE void remove_light(const void *const viewer, int32_t entityId)
{
((FilamentViewer *)viewer)->removeLight(entityId);