refactor!: refactor to support multiple Views/Render Targets

This commit is contained in:
Nick Fisher
2024-09-27 23:16:01 +08:00
parent a6d2f2ecf9
commit 7f11250b79
25 changed files with 1137 additions and 1304 deletions

View File

@@ -3,10 +3,14 @@ headers:
entry-points:
- '../native/include/ThermionDartRenderThreadApi.h'
- '../native/include/ThermionDartApi.h'
- '../native/include/TView.h'
- '../native/include/TGizmo.h'
- '../native/include/ResourceBuffer.h'
include-directives:
- '../native/include/ThermionDartRenderThreadApi.h'
- '../native/include/ThermionDartApi.h'
- '../native/include/TView.h'
- '../native/include/TGizmo.h'
- '../native/include/ResourceBuffer.h'
- '../native/include/APIBoundaryTypes.h'
ffi-native:

View File

@@ -45,14 +45,6 @@ external void Viewer_destroyRenderTarget(
ffi.Pointer<TRenderTarget> tRenderTarget,
);
@ffi.Native<
ffi.Void Function(
ffi.Pointer<TViewer>, ffi.Pointer<TRenderTarget>)>(isLeaf: true)
external void Viewer_setRenderTarget(
ffi.Pointer<TViewer> viewer,
ffi.Pointer<TRenderTarget> tRenderTarget,
);
@ffi.Native<
ffi.Pointer<TSwapChain> Function(ffi.Pointer<TViewer>,
ffi.Pointer<ffi.Void>, ffi.Uint32, ffi.Uint32)>(isLeaf: true)
@@ -73,6 +65,7 @@ external void Viewer_destroySwapChain(
@ffi.Native<
ffi.Bool Function(
ffi.Pointer<TViewer>,
ffi.Pointer<TView>,
ffi.Pointer<TSwapChain>,
ffi.Uint64,
ffi.Pointer<ffi.Void>,
@@ -83,6 +76,7 @@ external void Viewer_destroySwapChain(
ffi.Pointer<ffi.Void>)>(isLeaf: true)
external bool Viewer_render(
ffi.Pointer<TViewer> viewer,
ffi.Pointer<TView> view,
ffi.Pointer<TSwapChain> swapChain,
int frameTimeInNanos,
ffi.Pointer<ffi.Void> pixelBuffer,
@@ -97,11 +91,13 @@ external bool Viewer_render(
@ffi.Native<
ffi.Void Function(
ffi.Pointer<TViewer>,
ffi.Pointer<TView>,
ffi.Pointer<TSwapChain>,
ffi.Pointer<ffi.Uint8>,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>)>(isLeaf: true)
external void Viewer_capture(
ffi.Pointer<TViewer> viewer,
ffi.Pointer<TView> view,
ffi.Pointer<TSwapChain> swapChain,
ffi.Pointer<ffi.Uint8> pixelBuffer,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> callback,
@@ -110,18 +106,39 @@ external void Viewer_capture(
@ffi.Native<
ffi.Void Function(
ffi.Pointer<TViewer>,
ffi.Pointer<TView>,
ffi.Pointer<TSwapChain>,
ffi.Pointer<TRenderTarget>,
ffi.Pointer<ffi.Uint8>,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>)>(isLeaf: true)
external void Viewer_captureRenderTarget(
ffi.Pointer<TViewer> viewer,
ffi.Pointer<TView> view,
ffi.Pointer<TSwapChain> swapChain,
ffi.Pointer<TRenderTarget> renderTarget,
ffi.Pointer<ffi.Uint8> pixelBuffer,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> callback,
);
@ffi.Native<ffi.Pointer<TView> Function(ffi.Pointer<TViewer>)>(isLeaf: true)
external ffi.Pointer<TView> Viewer_createView(
ffi.Pointer<TViewer> viewer,
);
@ffi.Native<ffi.Pointer<TView> Function(ffi.Pointer<TViewer>, ffi.Int)>(
isLeaf: true)
external ffi.Pointer<TView> Viewer_getViewAt(
ffi.Pointer<TViewer> viewer,
int index,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TViewer>, ffi.Pointer<TView>)>(
isLeaf: true)
external void Viewer_setMainCamera(
ffi.Pointer<TViewer> tViewer,
ffi.Pointer<TView> tView,
);
@ffi.Native<ffi.Pointer<TEngine> Function(ffi.Pointer<TViewer>)>(isLeaf: true)
external ffi.Pointer<TEngine> Viewer_getEngine(
ffi.Pointer<TViewer> viewer,
@@ -177,12 +194,6 @@ external void set_background_color(
double a,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TViewer>, ffi.Int)>(isLeaf: true)
external void set_tone_mapping(
ffi.Pointer<TViewer> viewer,
int toneMapping,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TViewer>, ffi.Float)>(isLeaf: true)
external void set_bloom(
ffi.Pointer<TViewer> viewer,
@@ -360,25 +371,11 @@ external void get_instances(
ffi.Pointer<EntityId> out,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TViewer>)>(isLeaf: true)
external void set_main_camera(
ffi.Pointer<TViewer> viewer,
);
@ffi.Native<EntityId Function(ffi.Pointer<TViewer>)>(isLeaf: true)
external int get_main_camera(
ffi.Pointer<TViewer> viewer,
);
@ffi.Native<
ffi.Bool Function(
ffi.Pointer<TViewer>, EntityId, ffi.Pointer<ffi.Char>)>(isLeaf: true)
external bool set_camera(
ffi.Pointer<TViewer> viewer,
int entity,
ffi.Pointer<ffi.Char> nodeName,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TViewer>, ffi.Bool)>(isLeaf: true)
external void set_view_frustum_culling(
ffi.Pointer<TViewer> viewer,
@@ -391,57 +388,6 @@ external void set_frame_interval(
double interval,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TViewer>, ffi.Uint32, ffi.Uint32)>(
isLeaf: true)
external void update_viewport(
ffi.Pointer<TViewer> viewer,
int width,
int height,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TViewer>)>(isLeaf: true)
external void scroll_begin(
ffi.Pointer<TViewer> viewer,
);
@ffi.Native<
ffi.Void Function(
ffi.Pointer<TViewer>, ffi.Float, ffi.Float, ffi.Float)>(isLeaf: true)
external void scroll_update(
ffi.Pointer<TViewer> viewer,
double x,
double y,
double z,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TViewer>)>(isLeaf: true)
external void scroll_end(
ffi.Pointer<TViewer> viewer,
);
@ffi.Native<
ffi.Void Function(
ffi.Pointer<TViewer>, ffi.Float, ffi.Float, ffi.Bool)>(isLeaf: true)
external void grab_begin(
ffi.Pointer<TViewer> viewer,
double x,
double y,
bool pan,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TViewer>, ffi.Float, ffi.Float)>(
isLeaf: true)
external void grab_update(
ffi.Pointer<TViewer> viewer,
double x,
double y,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TViewer>)>(isLeaf: true)
external void grab_end(
ffi.Pointer<TViewer> viewer,
);
@ffi.Native<
ffi.Void Function(ffi.Pointer<TSceneManager>, EntityId,
ffi.Pointer<ffi.Char>, ffi.Pointer<ffi.Float>, ffi.Int)>(isLeaf: true)
@@ -699,6 +645,29 @@ external void SceneManager_queueTransformUpdates(
int numEntities,
);
@ffi.Native<
ffi.Pointer<TCamera> Function(ffi.Pointer<TSceneManager>, EntityId,
ffi.Pointer<ffi.Char>)>(isLeaf: true)
external ffi.Pointer<TCamera> SceneManager_findCameraByName(
ffi.Pointer<TSceneManager> tSceneManager,
int entity,
ffi.Pointer<ffi.Char> name,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TSceneManager>, EntityId, ffi.Int)>(
isLeaf: true)
external void SceneManager_setVisibilityLayer(
ffi.Pointer<TSceneManager> tSceneManager,
int entity,
int layer,
);
@ffi.Native<ffi.Pointer<TGizmo> Function(ffi.Pointer<TSceneManager>)>(
isLeaf: true)
external ffi.Pointer<TGizmo> SceneManager_getGizmo(
ffi.Pointer<TSceneManager> tSceneManager,
);
@ffi.Native<ffi.Bool Function(ffi.Pointer<TSceneManager>, EntityId)>(
isLeaf: true)
external bool update_bone_matrices(
@@ -778,10 +747,11 @@ external void queue_relative_position_update_world_axis(
);
@ffi.Native<
ffi.Void Function(ffi.Pointer<TSceneManager>, EntityId, ffi.Float,
ffi.Float)>(isLeaf: true)
ffi.Void Function(ffi.Pointer<TSceneManager>, ffi.Pointer<TView>, EntityId,
ffi.Float, ffi.Float)>(isLeaf: true)
external void queue_position_update_from_viewport_coords(
ffi.Pointer<TSceneManager> sceneManager,
ffi.Pointer<TView> view,
int entity,
double viewportX,
double viewportY,
@@ -942,17 +912,6 @@ external void set_camera_focus_distance(
double focusDistance,
);
@ffi.Native<
ffi.Void Function(ffi.Pointer<TViewer>, _ManipulatorMode, ffi.Double,
ffi.Double, ffi.Double)>(isLeaf: true)
external void set_camera_manipulator_options(
ffi.Pointer<TViewer> viewer,
int mode,
double orbitSpeedX,
double orbitSpeedY,
double zoomSpeed,
);
@ffi.Native<
ffi.Void Function(
ffi.Pointer<TCamera>, double4x4, ffi.Double, ffi.Double)>(isLeaf: true)
@@ -1005,14 +964,6 @@ external void SceneManager_destroyCamera(
ffi.Pointer<TCamera> camera,
);
@ffi.Native<
ffi.Void Function(
ffi.Pointer<TSceneManager>, ffi.Pointer<TCamera>)>(isLeaf: true)
external void SceneManager_setCamera(
ffi.Pointer<TSceneManager> sceneManager,
ffi.Pointer<TCamera> camera,
);
@ffi.Native<ffi.Size Function(ffi.Pointer<TSceneManager>)>(isLeaf: true)
external int SceneManager_getCameraCount(
ffi.Pointer<TSceneManager> sceneManager,
@@ -1026,12 +977,6 @@ external ffi.Pointer<TCamera> SceneManager_getCameraAt(
int index,
);
@ffi.Native<ffi.Pointer<TCamera> Function(ffi.Pointer<TSceneManager>)>(
isLeaf: true)
external ffi.Pointer<TCamera> SceneManager_getActiveCamera(
ffi.Pointer<TSceneManager> sceneManager,
);
@ffi.Native<
ffi.Int Function(ffi.Pointer<TSceneManager>, EntityId,
ffi.Pointer<ffi.Char>)>(isLeaf: true)
@@ -1050,45 +995,10 @@ external int reveal_mesh(
ffi.Pointer<ffi.Char> meshName,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TViewer>, ffi.Bool)>(isLeaf: true)
external void set_post_processing(
ffi.Pointer<TViewer> viewer,
bool enabled,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TViewer>, ffi.Bool)>(isLeaf: true)
external void set_shadows_enabled(
ffi.Pointer<TViewer> viewer,
bool enabled,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TViewer>, ffi.Int)>(isLeaf: true)
external void set_shadow_type(
ffi.Pointer<TViewer> viewer,
int shadowType,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TViewer>, ffi.Float, ffi.Float)>(
isLeaf: true)
external void set_soft_shadow_options(
ffi.Pointer<TViewer> viewer,
double penumbraScale,
double penumbraRatioScale,
);
@ffi.Native<
ffi.Void Function(
ffi.Pointer<TViewer>, ffi.Bool, ffi.Bool, ffi.Bool)>(isLeaf: true)
external void set_antialiasing(
ffi.Pointer<TViewer> viewer,
bool msaa,
bool fxaa,
bool taa,
);
@ffi.Native<
ffi.Void Function(
ffi.Pointer<TViewer>,
ffi.Pointer<TView>,
ffi.Int,
ffi.Int,
ffi.Pointer<
@@ -1097,6 +1007,7 @@ external void set_antialiasing(
EntityId entityId, ffi.Int x, ffi.Int y)>>)>(isLeaf: true)
external void filament_pick(
ffi.Pointer<TViewer> viewer,
ffi.Pointer<TView> tView,
int x,
int y,
ffi.Pointer<
@@ -1273,15 +1184,19 @@ external void get_gizmo(
ffi.Pointer<EntityId> out,
);
@ffi.Native<Aabb2 Function(ffi.Pointer<TSceneManager>, EntityId)>(isLeaf: true)
@ffi.Native<
Aabb2 Function(
ffi.Pointer<TSceneManager>, ffi.Pointer<TView>, EntityId)>(isLeaf: true)
external Aabb2 get_bounding_box(
ffi.Pointer<TSceneManager> sceneManager,
ffi.Pointer<TView> view,
int entity,
);
@ffi.Native<
ffi.Void Function(
ffi.Pointer<TSceneManager>,
ffi.Pointer<TView>,
EntityId,
ffi.Pointer<ffi.Float>,
ffi.Pointer<ffi.Float>,
@@ -1289,6 +1204,7 @@ external Aabb2 get_bounding_box(
ffi.Pointer<ffi.Float>)>(isLeaf: true)
external void get_bounding_box_to_out(
ffi.Pointer<TSceneManager> sceneManager,
ffi.Pointer<TView> view,
int entity,
ffi.Pointer<ffi.Float> minX,
ffi.Pointer<ffi.Float> minY,
@@ -1296,41 +1212,6 @@ external void get_bounding_box_to_out(
ffi.Pointer<ffi.Float> maxY,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TSceneManager>, ffi.Int, ffi.Bool)>(
isLeaf: true)
external void set_layer_visibility(
ffi.Pointer<TSceneManager> sceneManager,
int layer,
bool visible,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TSceneManager>, EntityId, ffi.Int)>(
isLeaf: true)
external void set_visibility_layer(
ffi.Pointer<TSceneManager> sceneManager,
int entity,
int layer,
);
@ffi.Native<
ffi.Void Function(
ffi.Pointer<TSceneManager>,
ffi.Int,
ffi.Int,
ffi.Pointer<
ffi.NativeFunction<
ffi.Void Function(
EntityId entityId, ffi.Int x, ffi.Int y)>>)>(isLeaf: true)
external void pick_gizmo(
ffi.Pointer<TSceneManager> sceneManager,
int x,
int y,
ffi.Pointer<
ffi.NativeFunction<
ffi.Void Function(EntityId entityId, ffi.Int x, ffi.Int y)>>
callback,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TSceneManager>, ffi.Bool)>(
isLeaf: true)
external void set_gizmo_visibility(
@@ -1537,21 +1418,25 @@ external void Viewer_destroySwapChainRenderThread(
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> onComplete,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TViewer>, ffi.Pointer<TSwapChain>)>(
isLeaf: true)
@ffi.Native<
ffi.Void Function(ffi.Pointer<TViewer>, ffi.Pointer<TView>,
ffi.Pointer<TSwapChain>)>(isLeaf: true)
external void Viewer_renderRenderThread(
ffi.Pointer<TViewer> viewer,
ffi.Pointer<TView> view,
ffi.Pointer<TSwapChain> swapChain,
);
@ffi.Native<
ffi.Void Function(
ffi.Pointer<TViewer>,
ffi.Pointer<TView>,
ffi.Pointer<TSwapChain>,
ffi.Pointer<ffi.Uint8>,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>)>(isLeaf: true)
external void Viewer_captureRenderThread(
ffi.Pointer<TViewer> viewer,
ffi.Pointer<TView> view,
ffi.Pointer<TSwapChain> swapChain,
ffi.Pointer<ffi.Uint8> out,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> onComplete,
@@ -1560,12 +1445,14 @@ external void Viewer_captureRenderThread(
@ffi.Native<
ffi.Void Function(
ffi.Pointer<TViewer>,
ffi.Pointer<TView>,
ffi.Pointer<TSwapChain>,
ffi.Pointer<TRenderTarget>,
ffi.Pointer<ffi.Uint8>,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>)>(isLeaf: true)
external void Viewer_captureRenderTargetRenderThread(
ffi.Pointer<TViewer> viewer,
ffi.Pointer<TView> view,
ffi.Pointer<TSwapChain> swapChain,
ffi.Pointer<TRenderTarget> renderTarget,
ffi.Pointer<ffi.Uint8> out,
@@ -1749,17 +1636,6 @@ external void clear_entities_render_thread(
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> callback,
);
@ffi.Native<
ffi.Void Function(ffi.Pointer<TViewer>, EntityId, ffi.Pointer<ffi.Char>,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Bool)>>)>(
isLeaf: true)
external void set_camera_render_thread(
ffi.Pointer<TViewer> viewer,
int asset,
ffi.Pointer<ffi.Char> nodeName,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Bool)>> callback,
);
@ffi.Native<
ffi.Void Function(ffi.Pointer<TSceneManager>, EntityId,
ffi.Pointer<ffi.Char>, ffi.Pointer<ffi.Float>, ffi.Int)>(isLeaf: true)
@@ -1956,6 +1832,119 @@ external void unproject_texture_render_thread(
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> callback,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TView>, ffi.Pointer<TRenderTarget>)>(
isLeaf: true)
external void View_setRenderTarget(
ffi.Pointer<TView> view,
ffi.Pointer<TRenderTarget> renderTarget,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TView>, ffi.Bool)>(isLeaf: true)
external void View_setFrustumCullingEnabled(
ffi.Pointer<TView> view,
bool enabled,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TView>, ffi.Uint32, ffi.Uint32)>(
isLeaf: true)
external void View_updateViewport(
ffi.Pointer<TView> tView,
int width,
int height,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TView>, ffi.Bool)>(isLeaf: true)
external void View_setPostProcessing(
ffi.Pointer<TView> tView,
bool enabled,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TView>, ffi.Bool)>(isLeaf: true)
external void View_setShadowsEnabled(
ffi.Pointer<TView> tView,
bool enabled,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TView>, ffi.Int)>(isLeaf: true)
external void View_setShadowType(
ffi.Pointer<TView> tView,
int shadowType,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TView>, ffi.Float, ffi.Float)>(
isLeaf: true)
external void View_setSoftShadowOptions(
ffi.Pointer<TView> tView,
double penumbraScale,
double penumbraRatioScale,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TView>, ffi.Float)>(isLeaf: true)
external void View_setBloom(
ffi.Pointer<TView> tView,
double strength,
);
@ffi.Native<
ffi.Void Function(
ffi.Pointer<TView>, ffi.Pointer<TEngine>, ffi.Int)>(isLeaf: true)
external void View_setToneMapping(
ffi.Pointer<TView> tView,
ffi.Pointer<TEngine> tEngine,
int toneMapping,
);
@ffi.Native<
ffi.Void Function(
ffi.Pointer<TView>, ffi.Bool, ffi.Bool, ffi.Bool)>(isLeaf: true)
external void View_setAntiAliasing(
ffi.Pointer<TView> tView,
bool msaa,
bool fxaa,
bool taa,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TView>, ffi.Int, ffi.Bool)>(
isLeaf: true)
external void View_setLayerEnabled(
ffi.Pointer<TView> tView,
int layer,
bool visible,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TView>, ffi.Pointer<TCamera>)>(
isLeaf: true)
external void View_setCamera(
ffi.Pointer<TView> tView,
ffi.Pointer<TCamera> tCamera,
);
@ffi.Native<ffi.Pointer<TCamera> Function(ffi.Pointer<TView>)>(isLeaf: true)
external ffi.Pointer<TCamera> View_getCamera(
ffi.Pointer<TView> tView,
);
@ffi.Native<
ffi.Void Function(
ffi.Pointer<TGizmo>,
ffi.Pointer<TView>,
ffi.Int,
ffi.Int,
ffi.Pointer<
ffi.NativeFunction<
ffi.Void Function(
EntityId entityId, ffi.Int x, ffi.Int y)>>)>(isLeaf: true)
external void Gizmo_pick(
ffi.Pointer<TGizmo> tGizmo,
ffi.Pointer<TView> tView,
int x,
int y,
ffi.Pointer<
ffi.NativeFunction<
ffi.Void Function(EntityId entityId, ffi.Int x, ffi.Int y)>>
callback,
);
final class TCamera extends ffi.Opaque {}
final class TMaterialInstance extends ffi.Opaque {}
@@ -1972,6 +1961,10 @@ final class TRenderTarget extends ffi.Opaque {}
final class TSwapChain extends ffi.Opaque {}
final class TView extends ffi.Opaque {}
final class TGizmo extends ffi.Opaque {}
final class TMaterialKey extends ffi.Struct {
@ffi.Bool()
external bool doubleSided;
@@ -2197,8 +2190,6 @@ typedef DartLoadFilamentResourceIntoOutPointerFunction = void Function(
/// - setting up a render loop
typedef EntityId = ffi.Int32;
typedef DartEntityId = int;
typedef _ManipulatorMode = ffi.Int32;
typedef Dart_ManipulatorMode = int;
typedef FilamentRenderCallback
= ffi.Pointer<ffi.NativeFunction<FilamentRenderCallbackFunction>>;
typedef FilamentRenderCallbackFunction = ffi.Void Function(

View File

@@ -10,6 +10,7 @@ import '../../../../entities/gizmo.dart';
import '../../../../utils/matrix.dart';
import '../../events.dart';
import '../../shared_types/camera.dart';
import '../../shared_types/view.dart';
import '../../thermion_viewer_base.dart';
import 'package:logging/logging.dart';
@@ -111,12 +112,28 @@ class ThermionViewerFFI extends ThermionViewer {
///
///
Future setRenderTarget(FFIRenderTarget renderTarget) async {
Viewer_setRenderTarget(_viewer!, renderTarget.renderTarget);
final view = (await getViewAt(0)) as FFIView;
View_setRenderTarget(view.view, renderTarget.renderTarget);
}
///
///
///
Future<View> createView() async {
var view = Viewer_createView(_viewer!);
if (view == nullptr) {
throw Exception("Failed to create view");
}
return FFIView(view, _viewer!);
}
///
///
///
Future updateViewportAndCameraProjection(double width, double height) async {
viewportDimensions = (width * pixelRatio, height * pixelRatio);
update_viewport(_viewer!, width.toInt(), height.toInt());
var mainView = FFIView(Viewer_getViewAt(_viewer!, 0), _viewer!);
mainView.updateViewport(width.toInt(), height.toInt());
final cameraCount = await getCameraCount();
@@ -176,8 +193,6 @@ class ThermionViewerFFI extends ThermionViewer {
_sceneManager = Viewer_getSceneManager(_viewer!);
await setCameraManipulatorOptions(zoomSpeed: 1.0);
final gizmoEntities = allocator<Int32>(4);
get_gizmo(_sceneManager!, gizmoEntities);
_gizmo = Gizmo(gizmoEntities[0], gizmoEntities[1], gizmoEntities[2],
@@ -210,7 +225,8 @@ class ThermionViewerFFI extends ThermionViewer {
///
@override
Future render(FFISwapChain swapChain) async {
Viewer_renderRenderThread(_viewer!, swapChain.swapChain);
final view = (await getViewAt(0)) as FFIView;
Viewer_renderRenderThread(_viewer!, view.view, swapChain.swapChain);
}
///
@@ -223,13 +239,14 @@ class ThermionViewerFFI extends ThermionViewer {
this.viewportDimensions.$2.toInt() *
4;
final out = Uint8List(length);
final view = (await getViewAt(0)) as FFIView;
await withVoidCallback((cb) {
if (renderTarget != null) {
Viewer_captureRenderTargetRenderThread(
_viewer!, swapChain.swapChain, renderTarget.renderTarget, out.address, cb);
Viewer_captureRenderTargetRenderThread(_viewer!, view.view,
swapChain.swapChain, renderTarget.renderTarget, out.address, cb);
} else {
Viewer_captureRenderThread(
_viewer!, swapChain.swapChain, out.address, cb);
_viewer!, view.view, swapChain.swapChain, out.address, cb);
}
});
return out;
@@ -569,54 +586,6 @@ class ThermionViewerFFI extends ThermionViewer {
return entity;
}
///
///
///
@override
Future panStart(double x, double y) async {
grab_begin(_viewer!, x * pixelRatio, y * pixelRatio, true);
}
///
///
///
@override
Future panUpdate(double x, double y) async {
grab_update(_viewer!, x * pixelRatio, y * pixelRatio);
}
///
///
///
@override
Future panEnd() async {
grab_end(_viewer!);
}
///
///
///
@override
Future rotateStart(double x, double y) async {
grab_begin(_viewer!, x * pixelRatio, y * pixelRatio, false);
}
///
///
///
@override
Future rotateUpdate(double x, double y) async {
grab_update(_viewer!, x * pixelRatio, y * pixelRatio);
}
///
///
///
@override
Future rotateEnd() async {
grab_end(_viewer!);
}
///
///
///
@@ -1072,33 +1041,6 @@ class ThermionViewerFFI extends ThermionViewer {
});
}
///
///
///
///
///
///
@override
Future zoomBegin() async {
scroll_begin(_viewer!);
}
///
///
///
@override
Future zoomUpdate(double x, double y, double z) async {
scroll_update(_viewer!, x, y, z);
}
///
///
///
@override
Future zoomEnd() async {
scroll_end(_viewer!);
}
///
///
///
@@ -1167,7 +1109,8 @@ class ThermionViewerFFI extends ThermionViewer {
///
@override
Future setMainCamera() async {
set_main_camera(_viewer!);
final view = (await getViewAt(0)) as FFIView;
Viewer_setMainCamera(_viewer!, view.view);
}
///
@@ -1198,11 +1141,14 @@ class ThermionViewerFFI extends ThermionViewer {
Future setCamera(ThermionEntity entity, String? name) async {
var cameraNamePtr =
name?.toNativeUtf8(allocator: allocator).cast<Char>() ?? nullptr;
var result = set_camera(_viewer!, entity, cameraNamePtr);
allocator.free(cameraNamePtr);
if (!result) {
final camera =
SceneManager_findCameraByName(_sceneManager!, entity, cameraNamePtr);
if (camera == nullptr) {
throw Exception("Failed to set camera");
}
final view = (await getViewAt(0)) as FFIView;
View_setCamera(view.view, camera);
allocator.free(cameraNamePtr);
}
///
@@ -1218,7 +1164,8 @@ class ThermionViewerFFI extends ThermionViewer {
///
@override
Future setPostProcessing(bool enabled) async {
set_post_processing_render_thread(_viewer!, enabled);
final view = await getViewAt(0) as FFIView;
View_setPostProcessing(view.view, enabled);
}
///
@@ -1226,14 +1173,16 @@ class ThermionViewerFFI extends ThermionViewer {
///
@override
Future setShadowsEnabled(bool enabled) async {
set_shadows_enabled(_viewer!, enabled);
final view = await getViewAt(0) as FFIView;
View_setShadowsEnabled(view.view, enabled);
}
///
///
///
Future setShadowType(ShadowType shadowType) async {
set_shadow_type(_viewer!, shadowType.index);
final view = await getViewAt(0) as FFIView;
View_setShadowType(view.view, shadowType.index);
}
///
@@ -1241,7 +1190,8 @@ class ThermionViewerFFI extends ThermionViewer {
///
Future setSoftShadowOptions(
double penumbraScale, double penumbraRatioScale) async {
set_soft_shadow_options(_viewer!, penumbraScale, penumbraRatioScale);
final view = await getViewAt(0) as FFIView;
View_setSoftShadowOptions(view.view, penumbraScale, penumbraRatioScale);
}
///
@@ -1249,7 +1199,8 @@ class ThermionViewerFFI extends ThermionViewer {
///
@override
Future setAntiAliasing(bool msaa, bool fxaa, bool taa) async {
set_antialiasing(_viewer!, msaa, fxaa, taa);
final view = await getViewAt(0) as FFIView;
View_setAntiAliasing(view.view, msaa, fxaa, taa);
}
///
@@ -1257,7 +1208,8 @@ class ThermionViewerFFI extends ThermionViewer {
///
@override
Future setBloom(double bloom) async {
set_bloom_render_thread(_viewer!, bloom);
final view = await getViewAt(0) as FFIView;
View_setBloom(view.view, bloom);
}
///
@@ -1489,7 +1441,9 @@ class ThermionViewerFFI extends ThermionViewer {
///
Future queuePositionUpdateFromViewportCoords(
ThermionEntity entity, double x, double y) async {
queue_position_update_from_viewport_coords(_sceneManager!, entity, x, y);
final view = (await getViewAt(0)) as FFIView;
queue_position_update_from_viewport_coords(
_sceneManager!, view.view, entity, x, y);
}
///
@@ -1566,8 +1520,9 @@ class ThermionViewerFFI extends ThermionViewer {
void pick(int x, int y) async {
x = (x * pixelRatio).ceil();
y = (viewportDimensions.$2 - (y * pixelRatio)).ceil();
filament_pick(_viewer!, x, y, _onPickResultCallable.nativeFunction);
final view = (await getViewAt(0)) as FFIView;
filament_pick(
_viewer!, view.view, x, y, _onPickResultCallable.nativeFunction);
}
///
@@ -1577,7 +1532,10 @@ class ThermionViewerFFI extends ThermionViewer {
void pickGizmo(int x, int y) async {
x = (x * pixelRatio).ceil();
y = (viewportDimensions.$2 - (y * pixelRatio)).ceil();
pick_gizmo(_sceneManager!, x, y, _onGizmoPickResultCallable.nativeFunction);
final view = (await getViewAt(0)) as FFIView;
final gizmo = SceneManager_getGizmo(_sceneManager!);
Gizmo_pick(
gizmo, view.view, x, y, _onGizmoPickResultCallable.nativeFunction);
}
///
@@ -1658,27 +1616,6 @@ class ThermionViewerFFI extends ThermionViewer {
return rotationMatrix;
}
ManipulatorMode _cameraMode = ManipulatorMode.ORBIT;
///
///
///
@override
Future setCameraManipulatorOptions(
{ManipulatorMode? mode,
double orbitSpeedX = 0.01,
double orbitSpeedY = 0.01,
double zoomSpeed = 0.01}) async {
if (mode != null) {
_cameraMode = mode;
}
if (_cameraMode != ManipulatorMode.ORBIT) {
throw Exception("Manipulator mode $mode not yet implemented");
}
set_camera_manipulator_options(
_viewer!, _cameraMode.index, orbitSpeedX, orbitSpeedX, zoomSpeed);
}
///
///
///
@@ -1908,7 +1845,8 @@ class ThermionViewerFFI extends ThermionViewer {
///
@override
Future<v64.Aabb2> getViewportBoundingBox(ThermionEntity entityId) async {
final result = get_bounding_box(_sceneManager!, entityId);
final view = (await getViewAt(0)) as FFIView;
final result = get_bounding_box(_sceneManager!, view.view, entityId);
return v64.Aabb2.minMax(v64.Vector2(result.minX, result.minY),
v64.Vector2(result.maxX, result.maxY));
}
@@ -1916,17 +1854,16 @@ class ThermionViewerFFI extends ThermionViewer {
///
///
///
Future setLayerVisibility(int layer, bool visible) {
set_layer_visibility(_sceneManager!, layer, visible);
return Future.value();
Future setLayerVisibility(int layer, bool visible) async {
final view = (await getViewAt(0)) as FFIView;
View_setLayerEnabled(view.view, layer, visible);
}
///
///
///
Future setVisibilityLayer(ThermionEntity entity, int layer) {
set_visibility_layer(_sceneManager!, entity, layer);
return Future.value();
Future setVisibilityLayer(ThermionEntity entity, int layer) async {
SceneManager_setVisibilityLayer(_sceneManager!, entity, layer);
}
///
@@ -2171,14 +2108,16 @@ class ThermionViewerFFI extends ThermionViewer {
///
///
Future setActiveCamera(ThermionFFICamera camera) async {
SceneManager_setCamera(_sceneManager!, camera.camera);
final view = (await getViewAt(0)) as FFIView;
View_setCamera(view.view, camera.camera);
}
///
///
///
Future<Camera> getActiveCamera() async {
final ptr = SceneManager_getActiveCamera(_sceneManager!);
final view = (await getViewAt(0)) as FFIView;
final ptr = View_getCamera(view.view);
return ThermionFFICamera(ptr, Viewer_getEngine(_viewer!));
}
@@ -2216,6 +2155,15 @@ class ThermionViewerFFI extends ThermionViewer {
}
return ThermionFFICamera(camera, Viewer_getEngine(_viewer!));
}
@override
Future<View> getViewAt(int index) async {
var view = Viewer_getViewAt(_viewer!, index);
if (view == nullptr) {
throw Exception("Failed to get view");
}
return FFIView(view, _viewer!);
}
}
class ThermionFFITexture extends ThermionTexture {
@@ -2270,3 +2218,20 @@ class FFISwapChain extends SwapChain {
});
}
}
class FFIView extends View {
final Pointer<TView> view;
final Pointer<TViewer> viewer;
FFIView(this.view, this.viewer);
@override
Future updateViewport(int width, int height) async {
View_updateViewport(view, width, height);
}
@override
Future setRenderTarget(covariant FFIRenderTarget renderTarget) async {
View_setRenderTarget(view, renderTarget.renderTarget);
}
}

View File

@@ -0,0 +1,6 @@
import 'package:thermion_dart/thermion_dart.dart';
abstract class View {
Future updateViewport(int width, int height);
Future setRenderTarget(covariant RenderTarget renderTarget);
}

View File

@@ -11,6 +11,7 @@ import 'dart:async';
import 'package:animation_tools_dart/animation_tools_dart.dart';
import 'shared_types/swap_chain.dart';
import 'shared_types/view.dart';
const double kNear = 0.05;
const double kFar = 1000.0;
@@ -72,7 +73,8 @@ abstract class ThermionViewer {
///
/// Render a single frame and copy the pixel buffer to [out].
///
Future<Uint8List> capture(covariant SwapChain swapChain, { covariant RenderTarget? renderTarget });
Future<Uint8List> capture(covariant SwapChain swapChain,
{covariant RenderTarget? renderTarget});
///
///
@@ -82,13 +84,23 @@ abstract class ThermionViewer {
///
///
///
Future<RenderTarget> createRenderTarget(int width, int height, int textureHandle);
Future<RenderTarget> createRenderTarget(
int width, int height, int textureHandle);
///
///
///
Future setRenderTarget(covariant RenderTarget renderTarget);
///
///
///
Future<View> createView();
///
///
///
Future<View> getViewAt(int index);
///
/// Sets the framerate for continuous rendering when [setRendering] is enabled.
@@ -246,36 +258,6 @@ abstract class ThermionViewer {
Future<ThermionEntity> loadGltf(String path, String relativeResourcePath,
{bool keepData = false});
///
/// Called by `FilamentGestureDetector`. You probably don't want to call this yourself.
///
Future panStart(double x, double y);
///
/// Called by `FilamentGestureDetector`. You probably don't want to call this yourself.
///
Future panUpdate(double x, double y);
///
/// Called by `FilamentGestureDetector`. You probably don't want to call this yourself.
///
Future panEnd();
///
/// Called by `FilamentGestureDetector`. You probably don't want to call this yourself.
///
Future rotateStart(double x, double y);
///
/// Called by `FilamentGestureDetector`. You probably don't want to call this yourself.
///
Future rotateUpdate(double x, double y);
///
/// Called by `FilamentGestureDetector`. You probably don't want to call this yourself.
///
Future rotateEnd();
///
/// Set the weights for all morph targets in [entity] to [weights].
/// Note that [weights] must contain values for ALL morph targets, but no exception will be thrown if you don't do so (you'll just get incorrect results).
@@ -418,20 +400,6 @@ abstract class ThermionViewer {
///
Future clearEntities();
///
/// Called by `FilamentGestureDetector`. You probably don't want to call this yourself.
///
Future zoomBegin();
///
/// Called by `FilamentGestureDetector`. You probably don't want to call this yourself.
///
Future zoomUpdate(double x, double y, double z);
///
/// Called by `FilamentGestureDetector`. You probably don't want to call this yourself.
///
Future zoomEnd();
///
/// Schedules the glTF animation at [index] in [entity] to start playing on the next frame.
@@ -746,17 +714,6 @@ abstract class ThermionViewer {
///
String? getNameForEntity(ThermionEntity entity);
///
/// Sets the options for manipulating the camera via the viewport.
/// ManipulatorMode.FREE_FLIGHT and ManipulatorMode.MAP are currently unsupported and will throw an exception.
///
@Deprecated("Use InputHandler instead")
Future setCameraManipulatorOptions(
{ManipulatorMode mode = ManipulatorMode.ORBIT,
double orbitSpeedX = 0.01,
double orbitSpeedY = 0.01,
double zoomSpeed = 0.01});
///
/// Returns all child entities under [parent].
///

View File

@@ -2,6 +2,7 @@ import 'dart:math';
import 'dart:typed_data';
import 'package:thermion_dart/src/viewer/src/shared_types/swap_chain.dart';
import 'package:thermion_dart/src/viewer/src/shared_types/view.dart';
import 'package:thermion_dart/thermion_dart.dart';
import 'package:vector_math/vector_math_64.dart';
import 'dart:async';
@@ -385,12 +386,7 @@ class ThermionViewerStub extends ThermionViewer {
throw UnimplementedError();
}
@override
Future render() {
// TODO: implement render
throw UnimplementedError();
}
@override
// TODO: implement rendering
bool get rendering => throw UnimplementedError();
@@ -1032,6 +1028,30 @@ class ThermionViewerStub extends ThermionViewer {
// TODO: implement setRenderTarget
throw UnimplementedError();
}
@override
Future<Uint8List> capture(covariant SwapChain swapChain, {covariant RenderTarget? renderTarget}) {
// TODO: implement capture
throw UnimplementedError();
}
@override
Future<View> createView() {
// TODO: implement createView
throw UnimplementedError();
}
@override
Future<View> getViewAt(int index) {
// TODO: implement getViewAt
throw UnimplementedError();
}
@override
Future render(covariant SwapChain swapChain) {
// TODO: implement render
throw UnimplementedError();
}
}

View File

@@ -1803,26 +1803,6 @@ class ThermionViewerWasm implements ThermionViewer {
null);
}
@override
Future setCameraManipulatorOptions(
{ManipulatorMode mode = ManipulatorMode.ORBIT,
double orbitSpeedX = 0.01,
double orbitSpeedY = 0.01,
double zoomSpeed = 0.01}) async {
_module!.ccall(
"set_camera_manipulator_options",
"void",
["void*".toJS, "int".toJS, "double".toJS, "double".toJS, "double".toJS]
.toJS,
[
_viewer!,
mode.index.toJS,
orbitSpeedX.toJS,
orbitSpeedY.toJS,
zoomSpeed.toJS
].toJS,
null);
}
@override
Future setCameraModelMatrix(List<double> matrix) async {

View File

@@ -17,6 +17,8 @@ extern "C"
typedef struct TSceneManager TSceneManager;
typedef struct TRenderTarget TRenderTarget;
typedef struct TSwapChain TSwapChain;
typedef struct TView TView;
typedef struct TGizmo TGizmo;
struct TMaterialKey {
bool doubleSided = 1;

View File

@@ -61,8 +61,9 @@ namespace thermion_filament
FilamentViewer(const void *context, const ResourceLoaderWrapperImpl *const resourceLoaderWrapper, void *const platform = nullptr, const char *uberArchivePath = nullptr);
~FilamentViewer();
void setToneMapping(ToneMapping toneMapping);
void setBloom(float strength);
View* createView();
View* getViewAt(int index);
void loadSkybox(const char *const skyboxUri);
void removeSkybox();
@@ -74,17 +75,16 @@ namespace thermion_filament
void removeEntity(EntityId asset);
void clearEntities();
void updateViewport(uint32_t width, uint32_t height);
bool render(
uint64_t frameTimeInNanos,
View* view,
SwapChain* swapChain,
void *pixelBuffer,
void (*callback)(void *buf, size_t size, void *data),
void *data);
void setFrameInterval(float interval);
bool setCamera(EntityId asset, const char *nodeName);
void setMainCamera();
void setMainCamera(View *view);
EntityId getMainCamera();
Camera* getCamera(EntityId entity);
@@ -96,25 +96,15 @@ namespace thermion_filament
RenderTarget* createRenderTarget(intptr_t textureId, uint32_t width, uint32_t height);
void destroyRenderTarget(RenderTarget* renderTarget);
void setRenderTarget(RenderTarget* renderTarget);
Renderer *getRenderer();
void setBackgroundColor(const float r, const float g, const float b, const float a);
void setBackgroundImage(const char *resourcePath, bool fillHeight);
void setBackgroundImage(const char *resourcePath, bool fillHeight, uint32_t width, uint32_t height);
void clearBackgroundImage();
void setBackgroundImagePosition(float x, float y, bool clamp);
void setViewFrustumCulling(bool enabled);
void setCameraManipulatorOptions(filament::camutils::Mode mode, double orbitSpeedX, double orbitSpeedY, double zoomSpeed);
void grabBegin(float x, float y, bool pan);
void grabUpdate(float x, float y);
void grabEnd();
void scrollBegin();
void scrollUpdate(float x, float y, float delta);
void scrollEnd();
void pick(uint32_t x, uint32_t y, void (*callback)(EntityId entityId, int x, int y));
void setBackgroundImagePosition(float x, float y, bool clamp, uint32_t width, uint32_t height);
void pick(View *view, uint32_t x, uint32_t y, void (*callback)(EntityId entityId, int x, int y));
Engine* getEngine() {
return _engine;
}
@@ -140,16 +130,9 @@ namespace thermion_filament
void setLightDirection(EntityId entityId, float x, float y, float z);
void removeLight(EntityId entityId);
void clearLights();
void setPostProcessing(bool enabled);
void capture(uint8_t *out, bool useFence, SwapChain* swapChain, void (*onComplete)());
void capture(uint8_t *out, bool useFence, SwapChain* swapChain, RenderTarget* renderTarget, void (*onComplete)());
void setAntiAliasing(bool msaaEnabled, bool fxaaEnabled, bool taaEnabled);
void setDepthOfField();
void setShadowsEnabled(bool enabled);
void setShadowType(ShadowType shadowType);
void setSoftShadowOptions( float penumbraScale, float penumbraRatioScale);
void capture(View* view, uint8_t *out, bool useFence, SwapChain* swapChain, void (*onComplete)());
void capture(View* view, uint8_t *out, bool useFence, SwapChain* swapChain, RenderTarget* renderTarget, void (*onComplete)());
SceneManager *const getSceneManager()
{
@@ -162,13 +145,13 @@ namespace thermion_filament
const ResourceLoaderWrapperImpl *const _resourceLoaderWrapper;
void* _context = nullptr;
Scene *_scene = nullptr;
View *_view = nullptr;
Engine *_engine = nullptr;
thermion_filament::ThreadPool *_tp = nullptr;
Renderer *_renderer = nullptr;
SceneManager *_sceneManager = nullptr;
std::vector<RenderTarget*> _renderTargets;
std::vector<SwapChain*> _swapChains;
std::vector<View*> _views;
std::mutex _renderMutex; // mutex to ensure thread safety when removing assets
@@ -183,16 +166,6 @@ namespace thermion_filament
// Camera properties
Camera *_mainCamera = nullptr; // the default camera added to every scene. If you want the *active* camera, access via View.
Manipulator<double> *_manipulator = nullptr;
filament::camutils::Mode _manipulatorMode = filament::camutils::Mode::ORBIT;
double _orbitSpeedX = 0.01;
double _orbitSpeedY = 0.01;
double _zoomSpeed = 0.01;
void _createManipulator();
ColorGrading *colorGrading = nullptr;
// background image properties
uint32_t _imageHeight = 0;
uint32_t _imageWidth = 0;

View File

@@ -58,7 +58,7 @@ class Gizmo {
};
public:
Gizmo(Engine& engine, View *view, Scene *scene);
Gizmo(Engine& engine, Scene *scene);
~Gizmo();
Entity x() {
@@ -73,15 +73,12 @@ class Gizmo {
Entity center() {
return _entities[3];
};
View* view() {
return _view;
}
bool isActive() {
return _isActive;
}
void pick(uint32_t x, uint32_t y, void (*callback)(EntityId entityId, int x, int y));
void pick(View* view, uint32_t x, uint32_t y, void (*callback)(EntityId entityId, int x, int y));
bool isGizmoEntity(Entity entity);
void setVisibility(bool visible);
@@ -90,9 +87,7 @@ class Gizmo {
void highlight(Entity entity);
void unhighlight();
Engine &_engine;
View *_view;
Scene *_scene;
filament::Camera *_camera;
utils::Entity _entities[7] = { utils::Entity(), utils::Entity(), utils::Entity(), utils::Entity(), utils::Entity(), utils::Entity(), utils::Entity() };
Material* _material;
MaterialInstance* _materialInstances[7];

View File

@@ -46,7 +46,7 @@ namespace thermion_filament
class SceneManager
{
public:
SceneManager(View* view,
SceneManager(
const ResourceLoaderWrapperImpl *const loader,
Engine *engine,
Scene *scene,
@@ -111,9 +111,9 @@ namespace thermion_filament
void setRotation(EntityId e, float rads, float x, float y, float z, float w);
void queueTransformUpdates(EntityId* entities, math::mat4* transforms, int numEntities);
void queueRelativePositionUpdateWorldAxis(EntityId entity, float viewportCoordX, float viewportCoordY, float x, float y, float z);
void queueRelativePositionUpdateFromViewportVector(EntityId entityId, float viewportCoordX, float viewportCoordY);
void queueRelativePositionUpdateFromViewportVector(View* view, EntityId entityId, float viewportCoordX, float viewportCoordY);
const utils::Entity *getCameraEntities(EntityId e);
size_t getCameraEntityCount(EntityId e);
const utils::Entity *getLightEntities(EntityId e) noexcept;
@@ -231,12 +231,7 @@ namespace thermion_filament
/// @param out a pointer large enough to store four floats (the min/max coordinates of the bounding box)
/// @return
///
Aabb2 getBoundingBox(EntityId entity);
///
/// Toggles the visibility of the given layer.
///
void setLayerVisibility(SceneManager::LAYERS layer, bool enabled);
Aabb2 getBoundingBox(View* view, EntityId entity);
///
/// Creates an entity with the specified geometry/material/normals and adds to the scene.
@@ -308,20 +303,15 @@ namespace thermion_filament
void destroyCamera(Camera* camera);
void setCamera(Camera* camera);
size_t getCameraCount();
Camera* getCameraAt(size_t index);
Camera* getActiveCamera();
private:
gltfio::AssetLoader *_assetLoader = nullptr;
const ResourceLoaderWrapperImpl *const _resourceLoaderWrapper;
Engine *_engine = nullptr;
Scene *_scene = nullptr;
View* _view = nullptr;
Camera* _mainCamera;
gltfio::MaterialProvider *_ubershaderProvider = nullptr;

View File

@@ -0,0 +1,15 @@
#pragma once
#ifdef __cplusplus
extern "C"
{
#endif
#include "ThermionDartApi.h"
EMSCRIPTEN_KEEPALIVE void Gizmo_pick(TGizmo *tGizmo, TView *tView, int x, int y, void (*callback)(EntityId entityId, int x, int y));
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,79 @@
#ifndef _FLUTTER_FILAMENT_API_H
#define _FLUTTER_FILAMENT_API_H
#ifdef _WIN32
#ifdef IS_DLL
#define EMSCRIPTEN_KEEPALIVE __declspec(dllimport)
#else
#define EMSCRIPTEN_KEEPALIVE __declspec(dllexport)
#endif
#else
#ifndef EMSCRIPTEN_KEEPALIVE
#define EMSCRIPTEN_KEEPALIVE __attribute__((visibility("default")))
#endif
#endif
// we copy the LLVM <stdbool.h> here rather than including,
// because on Windows it's difficult to pin the exact location which confuses dart ffigen
#ifndef __STDBOOL_H
#define __STDBOOL_H
#define __bool_true_false_are_defined 1
#if defined(__STDC_VERSION__) && __STDC_VERSION__ > 201710L
/* FIXME: We should be issuing a deprecation warning here, but cannot yet due
* to system headers which include this header file unconditionally.
*/
#elif !defined(__cplusplus)
#define bool _Bool
#define true 1
#define false 0
#elif defined(__GNUC__) && !defined(__STRICT_ANSI__)
/* Define _Bool as a GNU extension. */
#define _Bool bool
#if defined(__cplusplus) && __cplusplus < 201103L
/* For C++98, define bool, false, true as a GNU extension. */
#define bool bool
#define false false
#define true true
#endif
#endif
#endif /* __STDBOOL_H */
#if defined(__APPLE__) || defined(__EMSCRIPTEN__)
#include <stddef.h>
#endif
#include "APIBoundaryTypes.h"
#include "ResourceBuffer.hpp"
#ifdef __cplusplus
extern "C"
{
#endif
// View
EMSCRIPTEN_KEEPALIVE void View_updateViewport(TView *view, uint32_t width, uint32_t height);
EMSCRIPTEN_KEEPALIVE void View_setRenderTarget(TView *view, TRenderTarget *renderTarget);
EMSCRIPTEN_KEEPALIVE void View_setFrustumCullingEnabled(TView *view, bool enabled);
EMSCRIPTEN_KEEPALIVE void View_updateViewport(TView* tView, uint32_t width, uint32_t height);
EMSCRIPTEN_KEEPALIVE void View_setRenderTarget(TView* tView, TRenderTarget* tRenderTarget);
EMSCRIPTEN_KEEPALIVE void View_setFrustumCullingEnabled(TView* tView, bool enabled);
EMSCRIPTEN_KEEPALIVE void View_setPostProcessing(TView* tView, bool enabled);
EMSCRIPTEN_KEEPALIVE void View_setShadowsEnabled(TView* tView, bool enabled);
EMSCRIPTEN_KEEPALIVE void View_setShadowType(TView* tView, int shadowType);
EMSCRIPTEN_KEEPALIVE void View_setSoftShadowOptions(TView* tView, float penumbraScale, float penumbraRatioScale);
EMSCRIPTEN_KEEPALIVE void View_setBloom(TView* tView, float strength);
EMSCRIPTEN_KEEPALIVE void View_setToneMapping(TView* tView, TEngine* tEngine, int toneMapping);
EMSCRIPTEN_KEEPALIVE void View_setAntiAliasing(TView *tView, bool msaa, bool fxaa, bool taa);
EMSCRIPTEN_KEEPALIVE void View_setLayerEnabled(TView *tView, int layer, bool visible);
EMSCRIPTEN_KEEPALIVE void View_setCamera(TView *tView, TCamera *tCamera);
EMSCRIPTEN_KEEPALIVE TCamera* View_getCamera(TView *tView);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -59,11 +59,11 @@ extern "C"
EMSCRIPTEN_KEEPALIVE TSceneManager *Viewer_getSceneManager(TViewer *viewer);
EMSCRIPTEN_KEEPALIVE TRenderTarget* Viewer_createRenderTarget(TViewer *viewer, intptr_t texture, uint32_t width, uint32_t height);
EMSCRIPTEN_KEEPALIVE void Viewer_destroyRenderTarget(TViewer *viewer, TRenderTarget* tRenderTarget);
EMSCRIPTEN_KEEPALIVE void Viewer_setRenderTarget(TViewer *viewer, TRenderTarget* tRenderTarget);
EMSCRIPTEN_KEEPALIVE TSwapChain *Viewer_createSwapChain(TViewer *viewer, const void *const window, uint32_t width, uint32_t height);
EMSCRIPTEN_KEEPALIVE void Viewer_destroySwapChain(TViewer *viewer, TSwapChain* swapChain);
EMSCRIPTEN_KEEPALIVE bool Viewer_render(
TViewer *viewer,
TView *view,
TSwapChain *swapChain,
uint64_t frameTimeInNanos,
void *pixelBuffer,
@@ -71,16 +71,20 @@ extern "C"
void *data);
EMSCRIPTEN_KEEPALIVE void Viewer_capture(
TViewer *viewer,
TView *view,
TSwapChain *swapChain,
uint8_t *pixelBuffer,
void (*callback)(void));
EMSCRIPTEN_KEEPALIVE void Viewer_captureRenderTarget(
TViewer *viewer,
TView *view,
TSwapChain *swapChain,
TRenderTarget *renderTarget,
uint8_t *pixelBuffer,
void (*callback)(void));
EMSCRIPTEN_KEEPALIVE TView* Viewer_createView(TViewer *viewer);
EMSCRIPTEN_KEEPALIVE TView* Viewer_getViewAt(TViewer *viewer, int index);
EMSCRIPTEN_KEEPALIVE void Viewer_setMainCamera(TViewer *tViewer, TView *tView);
// Engine
EMSCRIPTEN_KEEPALIVE TEngine *Viewer_getEngine(TViewer* viewer);
@@ -92,7 +96,7 @@ extern "C"
EMSCRIPTEN_KEEPALIVE void set_background_image(TViewer *viewer, const char *path, bool fillHeight);
EMSCRIPTEN_KEEPALIVE void set_background_image_position(TViewer *viewer, float x, float y, bool clamp);
EMSCRIPTEN_KEEPALIVE void set_background_color(TViewer *viewer, const float r, const float g, const float b, const float a);
EMSCRIPTEN_KEEPALIVE void set_tone_mapping(TViewer *viewer, int toneMapping);
EMSCRIPTEN_KEEPALIVE void set_bloom(TViewer *viewer, float strength);
EMSCRIPTEN_KEEPALIVE void load_skybox(TViewer *viewer, const char *skyboxPath);
EMSCRIPTEN_KEEPALIVE void load_ibl(TViewer *viewer, const char *iblPath, float intensity);
@@ -128,20 +132,12 @@ extern "C"
EMSCRIPTEN_KEEPALIVE EntityId create_instance(TSceneManager *sceneManager, EntityId id);
EMSCRIPTEN_KEEPALIVE int get_instance_count(TSceneManager *sceneManager, EntityId entityId);
EMSCRIPTEN_KEEPALIVE void get_instances(TSceneManager *sceneManager, EntityId entityId, EntityId *out);
EMSCRIPTEN_KEEPALIVE void set_main_camera(TViewer *viewer);
EMSCRIPTEN_KEEPALIVE EntityId get_main_camera(TViewer *viewer);
EMSCRIPTEN_KEEPALIVE bool set_camera(TViewer *viewer, EntityId entity, const char *nodeName);
EMSCRIPTEN_KEEPALIVE void set_view_frustum_culling(TViewer *viewer, bool enabled);
EMSCRIPTEN_KEEPALIVE void set_frame_interval(TViewer *viewer, float interval);
EMSCRIPTEN_KEEPALIVE void update_viewport(TViewer *viewer, uint32_t width, uint32_t height);
EMSCRIPTEN_KEEPALIVE void scroll_begin(TViewer *viewer);
EMSCRIPTEN_KEEPALIVE void scroll_update(TViewer *viewer, float x, float y, float z);
EMSCRIPTEN_KEEPALIVE void scroll_end(TViewer *viewer);
EMSCRIPTEN_KEEPALIVE void grab_begin(TViewer *viewer, float x, float y, bool pan);
EMSCRIPTEN_KEEPALIVE void grab_update(TViewer *viewer, float x, float y);
EMSCRIPTEN_KEEPALIVE void grab_end(TViewer *viewer);
EMSCRIPTEN_KEEPALIVE void apply_weights(
TSceneManager *sceneManager,
EntityId entity,
@@ -213,6 +209,9 @@ extern "C"
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);
EMSCRIPTEN_KEEPALIVE void SceneManager_setVisibilityLayer(TSceneManager *tSceneManager, EntityId entity, int layer);
EMSCRIPTEN_KEEPALIVE TGizmo* SceneManager_getGizmo(TSceneManager *tSceneManager);
EMSCRIPTEN_KEEPALIVE bool update_bone_matrices(TSceneManager *sceneManager, EntityId entityId);
EMSCRIPTEN_KEEPALIVE void get_morph_target_name(TSceneManager *sceneManager, EntityId assetEntity, EntityId childEntity, char *const outPtr, int index);
@@ -223,7 +222,7 @@ extern "C"
EMSCRIPTEN_KEEPALIVE void transform_to_unit_cube(TSceneManager *sceneManager, EntityId asset);
EMSCRIPTEN_KEEPALIVE void queue_relative_position_update_world_axis(TSceneManager *sceneManager, EntityId entity, float viewportX, float viewportY, float x, float y, float z);
EMSCRIPTEN_KEEPALIVE void queue_position_update_from_viewport_coords(TSceneManager *sceneManager, EntityId entity, float viewportX, float viewportY);
EMSCRIPTEN_KEEPALIVE void queue_position_update_from_viewport_coords(TSceneManager *sceneManager, TView *view, EntityId entity, float viewportX, float viewportY);
EMSCRIPTEN_KEEPALIVE void set_position(TSceneManager *sceneManager, EntityId entity, float x, float y, float z);
EMSCRIPTEN_KEEPALIVE void set_rotation(TSceneManager *sceneManager, EntityId entity, float rads, float x, float y, float z, float w);
@@ -252,7 +251,6 @@ extern "C"
EMSCRIPTEN_KEEPALIVE double get_camera_culling_far(TCamera *camera);
EMSCRIPTEN_KEEPALIVE float get_camera_fov(TCamera *camera, bool horizontal);
EMSCRIPTEN_KEEPALIVE void set_camera_focus_distance(TCamera *camera, float focusDistance);
EMSCRIPTEN_KEEPALIVE void set_camera_manipulator_options(TViewer *viewer, _ManipulatorMode mode, double orbitSpeedX, double orbitSpeedY, double zoomSpeed);
EMSCRIPTEN_KEEPALIVE void Camera_setCustomProjectionWithCulling(TCamera* camera, double4x4 projectionMatrix, double near, double far);
EMSCRIPTEN_KEEPALIVE void Camera_setModelMatrix(TCamera* camera, double4x4 modelMatrix);
@@ -264,22 +262,15 @@ extern "C"
EMSCRIPTEN_KEEPALIVE TEntityManager *Engine_getEntityManager(TEngine *engine);
// SceneManager
EMSCRIPTEN_KEEPALIVE TCamera* SceneManager_createCamera(TSceneManager *sceneManager);
EMSCRIPTEN_KEEPALIVE void SceneManager_destroyCamera(TSceneManager *sceneManager, TCamera* camera);
EMSCRIPTEN_KEEPALIVE void SceneManager_setCamera(TSceneManager *sceneManager, TCamera* camera);
EMSCRIPTEN_KEEPALIVE size_t SceneManager_getCameraCount(TSceneManager *sceneManager);
EMSCRIPTEN_KEEPALIVE TCamera* SceneManager_getCameraAt(TSceneManager *sceneManager, size_t index);
EMSCRIPTEN_KEEPALIVE TCamera* SceneManager_getActiveCamera(TSceneManager *sceneManager);
EMSCRIPTEN_KEEPALIVE int hide_mesh(TSceneManager *sceneManager, EntityId entity, const char *meshName);
EMSCRIPTEN_KEEPALIVE int reveal_mesh(TSceneManager *sceneManager, EntityId entity, const char *meshName);
EMSCRIPTEN_KEEPALIVE void set_post_processing(TViewer *viewer, bool enabled);
EMSCRIPTEN_KEEPALIVE void set_shadows_enabled(TViewer *viewer, bool enabled);
EMSCRIPTEN_KEEPALIVE void set_shadow_type(TViewer *viewer, int shadowType);
EMSCRIPTEN_KEEPALIVE void set_soft_shadow_options(TViewer *viewer, float penumbraScale, float penumbraRatioScale);
EMSCRIPTEN_KEEPALIVE void set_antialiasing(TViewer *viewer, bool msaa, bool fxaa, bool taa);
EMSCRIPTEN_KEEPALIVE void filament_pick(TViewer *viewer, int x, int y, void (*callback)(EntityId entityId, int x, int y));
EMSCRIPTEN_KEEPALIVE void filament_pick(TViewer *viewer, TView* tView, int x, int y, void (*callback)(EntityId entityId, int x, int y));
EMSCRIPTEN_KEEPALIVE const char *get_name_for_entity(TSceneManager *sceneManager, const EntityId entityId);
EMSCRIPTEN_KEEPALIVE EntityId find_child_entity_by_name(TSceneManager *sceneManager, const EntityId parent, const char *name);
EMSCRIPTEN_KEEPALIVE int get_entity_count(TSceneManager *sceneManager, const EntityId target, bool renderableOnly);
@@ -312,11 +303,9 @@ extern "C"
EMSCRIPTEN_KEEPALIVE void test_collisions(TSceneManager *sceneManager, EntityId entity);
EMSCRIPTEN_KEEPALIVE void set_priority(TSceneManager *sceneManager, EntityId entityId, int priority);
EMSCRIPTEN_KEEPALIVE void get_gizmo(TSceneManager *sceneManager, EntityId *out);
EMSCRIPTEN_KEEPALIVE Aabb2 get_bounding_box(TSceneManager *sceneManager, EntityId entity);
EMSCRIPTEN_KEEPALIVE void get_bounding_box_to_out(TSceneManager *sceneManager, EntityId entity, float *minX, float *minY, float *maxX, float *maxY);
EMSCRIPTEN_KEEPALIVE void set_layer_visibility(TSceneManager *sceneManager, int layer, bool visible);
EMSCRIPTEN_KEEPALIVE void set_visibility_layer(TSceneManager *sceneManager, EntityId entity, int layer);
EMSCRIPTEN_KEEPALIVE void pick_gizmo(TSceneManager *sceneManager, int x, int y, void (*callback)(EntityId entityId, int x, int y));
EMSCRIPTEN_KEEPALIVE Aabb2 get_bounding_box(TSceneManager *sceneManager, TView *view, EntityId entity);
EMSCRIPTEN_KEEPALIVE void get_bounding_box_to_out(TSceneManager *sceneManager, TView *view, EntityId entity, float *minX, float *minY, float *maxX, float *maxY);
EMSCRIPTEN_KEEPALIVE void set_gizmo_visibility(TSceneManager *sceneManager, bool visible);
EMSCRIPTEN_KEEPALIVE void set_stencil_highlight(TSceneManager *sceneManager, EntityId entity, float r, float g, float b);
EMSCRIPTEN_KEEPALIVE void remove_stencil_highlight(TSceneManager *sceneManager, EntityId entity);

View File

@@ -27,9 +27,9 @@ extern "C"
void (*callback)(TViewer *viewer));
EMSCRIPTEN_KEEPALIVE void Viewer_createSwapChainRenderThread(TViewer *viewer, void *const surface, uint32_t width, uint32_t height, void (*onComplete)(TSwapChain*));
EMSCRIPTEN_KEEPALIVE void Viewer_destroySwapChainRenderThread(TViewer *viewer, TSwapChain* swapChain, void (*onComplete)());
EMSCRIPTEN_KEEPALIVE void Viewer_renderRenderThread(TViewer *viewer, TSwapChain* swapChain);
EMSCRIPTEN_KEEPALIVE void Viewer_captureRenderThread(TViewer *viewer, TSwapChain* swapChain, uint8_t* out, void (*onComplete)());
EMSCRIPTEN_KEEPALIVE void Viewer_captureRenderTargetRenderThread(TViewer *viewer, TSwapChain* swapChain, TRenderTarget* renderTarget, uint8_t* out, void (*onComplete)());
EMSCRIPTEN_KEEPALIVE void Viewer_renderRenderThread(TViewer *viewer, TView* view, TSwapChain* swapChain);
EMSCRIPTEN_KEEPALIVE void Viewer_captureRenderThread(TViewer *viewer, TView* view, TSwapChain* swapChain, uint8_t* out, void (*onComplete)());
EMSCRIPTEN_KEEPALIVE void Viewer_captureRenderTargetRenderThread(TViewer *viewer, TView* view, TSwapChain* swapChain, TRenderTarget* renderTarget, uint8_t* out, void (*onComplete)());
EMSCRIPTEN_KEEPALIVE void destroy_filament_viewer_render_thread(TViewer *viewer);
@@ -52,7 +52,7 @@ extern "C"
EMSCRIPTEN_KEEPALIVE void create_instance_render_thread(TSceneManager *sceneManager, EntityId entityId, void (*callback)(EntityId));
EMSCRIPTEN_KEEPALIVE void remove_entity_render_thread(TViewer *viewer, EntityId asset, void (*callback)());
EMSCRIPTEN_KEEPALIVE void clear_entities_render_thread(TViewer *viewer, void (*callback)());
EMSCRIPTEN_KEEPALIVE void set_camera_render_thread(TViewer *viewer, EntityId asset, const char *nodeName, void (*callback)(bool));
EMSCRIPTEN_KEEPALIVE void apply_weights_render_thread(
TSceneManager *sceneManager,
EntityId asset,

View File

@@ -164,31 +164,7 @@ namespace thermion_filament
_mainCamera = _engine->createCamera(camera);
_view = _engine->createView();
_view->setBlendMode(filament::View::BlendMode::TRANSLUCENT);
_view->setStencilBufferEnabled(true);
setToneMapping(ToneMapping::ACES);
// there's a glitch on certain iGPUs where nothing will render when postprocessing is enabled and bloom is disabled
// set bloom to a small value here
setBloom(0.01);
_view->setAmbientOcclusionOptions({.enabled = false});
_view->setDynamicResolutionOptions({.enabled = false});
#if defined(_WIN32)
_view->setStereoscopicOptions({.enabled = true});
#endif
_view->setDithering(filament::Dithering::NONE);
setAntiAliasing(false, false, false);
_view->setShadowingEnabled(false);
_view->setScreenSpaceRefractionEnabled(false);
setPostProcessing(false);
_view->setScene(_scene);
_view->setCamera(_mainCamera);
createView();
const float aperture = _mainCamera->getAperture();
const float shutterSpeed = _mainCamera->getShutterSpeed();
@@ -197,7 +173,6 @@ namespace thermion_filament
EntityManager &em = EntityManager::get();
_sceneManager = new SceneManager(
_view,
_resourceLoaderWrapper,
_engine,
_scene,
@@ -205,80 +180,6 @@ namespace thermion_filament
_mainCamera);
}
void FilamentViewer::setAntiAliasing(bool msaa, bool fxaa, bool taa)
{
View::MultiSampleAntiAliasingOptions multiSampleAntiAliasingOptions;
multiSampleAntiAliasingOptions.enabled = msaa;
_view->setMultiSampleAntiAliasingOptions(multiSampleAntiAliasingOptions);
TemporalAntiAliasingOptions taaOpts;
taaOpts.enabled = taa;
_view->setTemporalAntiAliasingOptions(taaOpts);
_view->setAntiAliasing(fxaa ? AntiAliasing::FXAA : AntiAliasing::NONE);
}
void FilamentViewer::setPostProcessing(bool enabled)
{
_view->setPostProcessingEnabled(enabled);
}
void FilamentViewer::setShadowsEnabled(bool enabled)
{
_view->setShadowingEnabled(enabled);
}
void FilamentViewer::setShadowType(ShadowType shadowType)
{
_view->setShadowType(shadowType);
}
void FilamentViewer::setSoftShadowOptions(float penumbraScale, float penumbraRatioScale)
{
SoftShadowOptions opts;
opts.penumbraRatioScale = penumbraRatioScale;
opts.penumbraScale = penumbraScale;
_view->setSoftShadowOptions(opts);
}
void FilamentViewer::setBloom(float strength)
{
#ifndef __EMSCRIPTEN__
decltype(_view->getBloomOptions()) opts;
opts.enabled = true;
opts.strength = strength;
_view->setBloomOptions(opts);
#endif
}
void FilamentViewer::setToneMapping(ToneMapping toneMapping)
{
ToneMapper *tm;
switch (toneMapping)
{
case ToneMapping::ACES:
Log("Setting tone mapping to ACES");
tm = new ACESToneMapper();
break;
case ToneMapping::LINEAR:
Log("Setting tone mapping to Linear");
tm = new LinearToneMapper();
break;
case ToneMapping::FILMIC:
Log("Setting tone mapping to Filmic");
tm = new FilmicToneMapper();
break;
default:
Log("ERROR: Unsupported tone mapping");
return;
}
auto newColorGrading = ColorGrading::Builder().toneMapper(tm).build(*_engine);
_view->setColorGrading(newColorGrading);
_engine->destroy(colorGrading);
delete tm;
}
void FilamentViewer::setFrameInterval(float frameInterval)
{
_frameInterval = frameInterval;
@@ -307,7 +208,7 @@ namespace thermion_filament
bool shadows)
{
auto light = EntityManager::get().create();
auto result = LightManager::Builder(t)
.color(Color::cct(colour))
.intensity(intensity)
@@ -333,36 +234,38 @@ namespace thermion_filament
return Entity::smuggle(light);
}
void FilamentViewer::setLightPosition(EntityId entityId, float x, float y, float z) {
void FilamentViewer::setLightPosition(EntityId entityId, float x, float y, float z)
{
auto light = Entity::import(entityId);
if(light.isNull()) {
if (light.isNull())
{
Log("Light not found for entity %d", entityId);
return;
}
auto& lm = _engine->getLightManager();
auto &lm = _engine->getLightManager();
auto instance = lm.getInstance(light);
lm.setPosition(instance, filament::math::float3 { x, y, z });
lm.setPosition(instance, filament::math::float3{x, y, z});
}
void FilamentViewer::setLightDirection(EntityId entityId, float x, float y, float z) {
void FilamentViewer::setLightDirection(EntityId entityId, float x, float y, float z)
{
auto light = Entity::import(entityId);
if(light.isNull()) {
if (light.isNull())
{
Log("Light not found for entity %d", entityId);
return;
}
auto& lm = _engine->getLightManager();
auto &lm = _engine->getLightManager();
auto instance = lm.getInstance(light);
lm.setDirection(instance, filament::math::float3 { x, y, z });
lm.setDirection(instance, filament::math::float3{x, y, z});
}
void FilamentViewer::removeLight(EntityId entityId)
@@ -608,7 +511,7 @@ namespace thermion_filament
}
}
void FilamentViewer::setBackgroundImage(const char *resourcePath, bool fillHeight)
void FilamentViewer::setBackgroundImage(const char *resourcePath, bool fillHeight, uint32_t width, uint32_t height)
{
std::lock_guard lock(_imageMutex);
@@ -624,9 +527,7 @@ namespace thermion_filament
// This currently just anchors the image at the bottom left of the viewport at its original size
// TODO - implement stretch/etc
const Viewport &vp = _view->getViewport();
float xScale = float(vp.width) / float(_imageWidth);
float xScale = float(width) / float(_imageWidth);
float yScale;
if (fillHeight)
@@ -635,7 +536,7 @@ namespace thermion_filament
}
else
{
yScale = float(vp.height) / float(_imageHeight);
yScale = float(height) / float(_imageHeight);
}
_imageScale = mat4f{xScale, 0.0f, 0.0f, 0.0f, 0.0f, yScale, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
@@ -643,7 +544,6 @@ namespace thermion_filament
_imageMaterial->setDefaultParameter("transform", _imageScale);
_imageMaterial->setDefaultParameter("image", _imageTexture, _imageSampler);
_imageMaterial->setDefaultParameter("showImage", 1);
}
///
@@ -652,7 +552,7 @@ namespace thermion_filament
/// are positioned at a max/min of -1/1 respectively
/// (i.e. you cannot set a position where the left/top or right/bottom sides would be "inside" the screen coordinate space).
///
void FilamentViewer::setBackgroundImagePosition(float x, float y, bool clamp = false)
void FilamentViewer::setBackgroundImagePosition(float x, float y, bool clamp = false, uint32_t width = 0, uint32_t height = 0)
{
std::lock_guard lock(_imageMutex);
@@ -678,8 +578,8 @@ namespace thermion_filament
{
Log("Clamping background image translation");
// first, clamp x/y
auto xScale = float(_imageWidth) / _view->getViewport().width;
auto yScale = float(_imageHeight) / _view->getViewport().height;
auto xScale = float(_imageWidth) / width;
auto yScale = float(_imageHeight) / height;
float xMin = 0;
float xMax = 0;
@@ -720,31 +620,30 @@ namespace thermion_filament
// i.e. translating the image right by 0.5 units means translating the UV coordinates left by 0.5 units.
x = -x;
y = -y;
Log("x %f y %f", x, y);
Log("imageScale %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f ", _imageScale[0][0], _imageScale[0][1], _imageScale[0][2], _imageScale[0][3],
_imageScale[1][0], _imageScale[1][1], _imageScale[1][2], _imageScale[1][3],
_imageScale[2][0], _imageScale[2][1], _imageScale[2][2], _imageScale[2][3],
_imageScale[3][0], _imageScale[3][1], _imageScale[3][2], _imageScale[3][3]);
auto transform = math::mat4f::translation(filament::math::float3(x, y, 0.0f)) * _imageScale;
Log("transform %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f ", transform[0][0], transform[0][1], transform[0][2], transform[0][3],
transform[1][0], transform[1][1], transform[1][2], transform[1][3],
transform[2][0], transform[2][1], transform[2][2], transform[2][3],
transform[3][0], transform[3][1], transform[3][2], transform[3][3]);
_imageMaterial->setDefaultParameter("transform", transform);
}
FilamentViewer::~FilamentViewer()
{
clearLights();
for(auto swapChain : _swapChains) {
for (auto view : _views)
{
_engine->destroy(view);
}
_views.clear();
for (auto swapChain : _swapChains)
{
_engine->destroy(swapChain);
}
_swapChains.clear();
if (!_imageEntity.isNull())
{
_engine->destroy(_imageEntity);
@@ -756,7 +655,6 @@ namespace thermion_filament
delete _sceneManager;
_engine->destroyCameraComponent(_mainCamera->getEntity());
_mainCamera = nullptr;
_engine->destroy(_view);
_engine->destroy(_scene);
_engine->destroy(_renderer);
Engine::destroy(&_engine);
@@ -765,10 +663,10 @@ namespace thermion_filament
Renderer *FilamentViewer::getRenderer() { return _renderer; }
SwapChain* FilamentViewer::createSwapChain(const void *window, uint32_t width, uint32_t height)
SwapChain *FilamentViewer::createSwapChain(const void *window, uint32_t width, uint32_t height)
{
std::lock_guard lock(_renderMutex);
SwapChain* swapChain;
SwapChain *swapChain;
#if TARGET_OS_IPHONE
swapChain = _engine->createSwapChain((void *)window, filament::backend::SWAP_CHAIN_CONFIG_TRANSPARENT | filament::backend::SWAP_CHAIN_CONFIG_APPLE_CVPIXELBUFFER);
#else
@@ -787,58 +685,58 @@ namespace thermion_filament
return swapChain;
}
RenderTarget* FilamentViewer::createRenderTarget(intptr_t texture, uint32_t width, uint32_t height)
RenderTarget *FilamentViewer::createRenderTarget(intptr_t texture, uint32_t width, uint32_t height)
{
// Create filament textures and render targets (note the color buffer has the import call)
auto rtColor = filament::Texture::Builder()
.width(width)
.height(height)
.levels(1)
.usage(filament::Texture::Usage::COLOR_ATTACHMENT | filament::Texture::Usage::SAMPLEABLE)
.format(filament::Texture::InternalFormat::RGBA8)
.import(texture)
.build(*_engine);
.width(width)
.height(height)
.levels(1)
.usage(filament::Texture::Usage::COLOR_ATTACHMENT | filament::Texture::Usage::SAMPLEABLE)
.format(filament::Texture::InternalFormat::RGBA8)
.import(texture)
.build(*_engine);
auto rtDepth = filament::Texture::Builder()
.width(width)
.height(height)
.levels(1)
.usage(filament::Texture::Usage::DEPTH_ATTACHMENT | filament::Texture::Usage::SAMPLEABLE)
.format(filament::Texture::InternalFormat::DEPTH32F)
.build(*_engine);
.width(width)
.height(height)
.levels(1)
.usage(filament::Texture::Usage::DEPTH_ATTACHMENT | filament::Texture::Usage::SAMPLEABLE)
.format(filament::Texture::InternalFormat::DEPTH32F)
.build(*_engine);
auto rt = filament::RenderTarget::Builder()
.texture(RenderTarget::AttachmentPoint::COLOR, rtColor)
.texture(RenderTarget::AttachmentPoint::DEPTH, rtDepth)
.build(*_engine);
return rt;
.texture(RenderTarget::AttachmentPoint::COLOR, rtColor)
.texture(RenderTarget::AttachmentPoint::DEPTH, rtDepth)
.build(*_engine);
return rt;
}
void FilamentViewer::destroyRenderTarget(RenderTarget* renderTarget) {
void FilamentViewer::destroyRenderTarget(RenderTarget *renderTarget)
{
std::lock_guard lock(_renderMutex);
auto rtDepth = renderTarget->getTexture(RenderTarget::AttachmentPoint::DEPTH);
if(rtDepth) {
if (rtDepth)
{
_engine->destroy(rtDepth);
}
auto rtColor = renderTarget->getTexture(RenderTarget::AttachmentPoint::COLOR);
if(rtColor) {
if (rtColor)
{
_engine->destroy(rtColor);
}
_engine->destroy(renderTarget);
_engine->destroy(renderTarget);
auto it = std::find(_renderTargets.begin(), _renderTargets.end(), renderTarget);
if(it != _renderTargets.end()) {
if (it != _renderTargets.end())
{
_renderTargets.erase(it);
}
}
void FilamentViewer::setRenderTarget(RenderTarget *renderTarget) {
std::lock_guard lock(_renderMutex);
_view->setRenderTarget(renderTarget);
}
void FilamentViewer::destroySwapChain(SwapChain *swapChain)
{
std::lock_guard lock(_renderMutex);
auto it = std::find(_swapChains.begin(), _swapChains.end(), swapChain);
if(it != _swapChains.end()) {
if (it != _swapChains.end())
{
_swapChains.erase(it);
}
_engine->destroy(swapChain);
@@ -850,9 +748,55 @@ namespace thermion_filament
#endif
}
///
///
///
View *FilamentViewer::createView()
{
auto *view = _engine->createView();
view->setLayerEnabled(SceneManager::LAYERS::DEFAULT_ASSETS, true);
view->setLayerEnabled(SceneManager::LAYERS::BACKGROUND, true); // skybox + image
view->setLayerEnabled(SceneManager::LAYERS::OVERLAY, false); // world grid + gizmo
view->setBlendMode(filament::View::BlendMode::TRANSLUCENT);
view->setStencilBufferEnabled(true);
view->setAmbientOcclusionOptions({.enabled = false});
view->setDynamicResolutionOptions({.enabled = false});
#if defined(_WIN32)
view->setStereoscopicOptions({.enabled = true});
#endif
// there's a glitch on certain iGPUs where nothing will render when postprocessing is enabled and bloom is disabled
// set bloom to a small value here
view->setBloomOptions({.strength = 0.01});
view->setDithering(filament::Dithering::NONE);
view->setShadowingEnabled(false);
view->setScreenSpaceRefractionEnabled(false);
view->setPostProcessingEnabled(false);
view->setScene(_scene);
view->setCamera(_mainCamera);
_views.push_back(view);
return view;
}
///
///
///
View *FilamentViewer::getViewAt(int32_t index)
{
Log("Getting view at %d", index);
if (index < _views.size())
{
return _views[index];
}
return nullptr;
}
/// @brief
///
///
void FilamentViewer::clearEntities()
{
_view->setCamera(_mainCamera);
_sceneManager->destroyAll();
}
@@ -867,9 +811,9 @@ namespace thermion_filament
///
///
///
void FilamentViewer::setMainCamera()
void FilamentViewer::setMainCamera(View *view)
{
_view->setCamera(_mainCamera);
view->setCamera(_mainCamera);
}
///
@@ -880,73 +824,6 @@ namespace thermion_filament
return Entity::smuggle(_mainCamera->getEntity());
}
///
/// Sets the active camera to the GLTF camera node specified by [name] (or if null, the first camera found under that node).
/// N.B. Blender will generally export a three-node hierarchy -
/// Camera1->Camera_Orientation->Camera2. The correct name will be the Camera_Orientation.
///
bool FilamentViewer::setCamera(EntityId entityId, const char *cameraName)
{
auto asset = _sceneManager->getAssetByEntityId(entityId);
if (!asset)
{
Log("Failed to find asset under entity id %d.", entityId);
return false;
}
size_t count = asset->getCameraEntityCount();
if (count == 0)
{
Log("No cameras found attached to specified entity.");
return false;
}
const utils::Entity *cameras = asset->getCameraEntities();
utils::Entity target;
if (!cameraName)
{
target = cameras[0];
const char *name = asset->getName(target);
Log("No camera specified, using first camera node found (%s)", name);
}
else
{
for (int j = 0; j < count; j++)
{
const char *name = asset->getName(cameras[j]);
if (strcmp(name, cameraName) == 0)
{
target = cameras[j];
break;
}
}
}
if (target.isNull())
{
Log("Unable to locate camera under name %s ", cameraName);
return false;
}
Camera *camera = _engine->getCameraComponent(target);
if (!camera)
{
Log("Failed to retrieve camera component for target");
return false;
}
_view->setCamera(camera);
const Viewport &vp = _view->getViewport();
const double aspect = (double)vp.width / vp.height;
camera->setScaling({1.0 / aspect, 1.0});
Log("Successfully set view camera to target");
return true;
}
void FilamentViewer::loadSkybox(const char *const skyboxPath)
{
@@ -990,8 +867,8 @@ namespace thermion_filament
callbackData);
_skybox =
filament::Skybox::Builder()
.environment(_skyboxTexture)
.build(*_engine);
.environment(_skyboxTexture)
.build(*_engine);
_skybox->setLayerMask(0xFF, 1u << SceneManager::LAYERS::BACKGROUND);
@@ -1046,13 +923,25 @@ namespace thermion_filament
.build(*_engine);
// Create a copy of the cubemap data
float *pixelData = new float[18] {
r, g, b,
r, g, b,
r, g, b,
r, g, b,
r, g, b,
r, g, b,
float *pixelData = new float[18]{
r,
g,
b,
r,
g,
b,
r,
g,
b,
r,
g,
b,
r,
g,
b,
r,
g,
b,
};
Texture::PixelBufferDescriptor::Callback freeCallback = [](void *buf, size_t, void *data)
@@ -1126,13 +1015,14 @@ namespace thermion_filament
bool FilamentViewer::render(
uint64_t frameTimeInNanos,
SwapChain* swapChain,
View *view,
SwapChain *swapChain,
void *pixelBuffer,
void (*callback)(void *buf, size_t size, void *data),
void *data)
{
if (!_view || !swapChain)
if (!view || !swapChain)
{
return false;
}
@@ -1155,15 +1045,6 @@ namespace thermion_filament
_cumulativeAnimationUpdateTime += tmr.elapsed();
// if a manipulator is active, update the active camera orientation
if (_manipulator)
{
math::double3 eye, target, upward;
Camera &cam = _view->getCamera();
_manipulator->getLookAt(&eye, &target, &upward);
cam.lookAt(eye, target, upward);
}
// Render the scene, unless the renderer wants to skip the frame.
bool beginFrame = _renderer->beginFrame(swapChain, frameTimeInNanos);
if (!beginFrame)
@@ -1174,7 +1055,7 @@ namespace thermion_filament
if (beginFrame)
{
_renderer->render(_view);
_renderer->render(view);
_frameCount++;
@@ -1186,21 +1067,24 @@ namespace thermion_filament
return beginFrame;
}
class CaptureCallbackHandler : public filament::backend::CallbackHandler {
void post(void* user, Callback callback) {
callback(user);
}
class CaptureCallbackHandler : public filament::backend::CallbackHandler
{
void post(void *user, Callback callback)
{
callback(user);
}
};
void FilamentViewer::capture(uint8_t *out, bool useFence, SwapChain* swapChain, void (*onComplete)())
void FilamentViewer::capture(View *view, uint8_t *out, bool useFence, SwapChain *swapChain, void (*onComplete)())
{
if(!swapChain) {
if (!swapChain)
{
Log("NO SWAPCHAIN");
return;
}
Viewport const &vp = _view->getViewport();
Viewport const &vp = view->getViewport();
size_t pixelBufferSize = vp.width * vp.height * 4;
auto *pixelBuffer = new uint8_t[pixelBufferSize];
auto callback = [](void *buf, size_t size, void *data)
@@ -1211,15 +1095,17 @@ namespace thermion_filament
memcpy(out, buf, size);
delete frameCallbackData;
if(callbackPtr) {
if (callbackPtr)
{
void (*callback)(void) = (void (*)(void))callbackPtr;
callback();
}
};
// Create a fence
Fence* fence = nullptr;
if(useFence) {
Fence *fence = nullptr;
if (useFence)
{
fence = _engine->createFence();
}
@@ -1232,7 +1118,7 @@ namespace thermion_filament
Texture::Format::RGBA,
Texture::Type::UBYTE, dispatcher, callback, userData);
_renderer->beginFrame(swapChain, 0);
_renderer->render(_view);
_renderer->render(view);
_renderer->readPixels(0, 0, vp.width, vp.height, std::move(pbd));
_renderer->endFrame();
@@ -1240,20 +1126,22 @@ namespace thermion_filament
_engine->execute();
emscripten_webgl_commit_frame();
#endif
if(fence) {
Fence::waitAndDestroy(fence);
}
if (fence)
{
Fence::waitAndDestroy(fence);
}
}
void FilamentViewer::capture(uint8_t *out, bool useFence, SwapChain* swapChain, RenderTarget* renderTarget, void (*onComplete)())
void FilamentViewer::capture(View *view, uint8_t *out, bool useFence, SwapChain *swapChain, RenderTarget *renderTarget, void (*onComplete)())
{
if(!renderTarget) {
if (!renderTarget)
{
Log("NO SWAPCHAIN");
return;
}
Viewport const &vp = _view->getViewport();
Viewport const &vp = view->getViewport();
size_t pixelBufferSize = vp.width * vp.height * 4;
auto *pixelBuffer = new uint8_t[pixelBufferSize];
auto callback = [](void *buf, size_t size, void *data)
@@ -1264,15 +1152,17 @@ namespace thermion_filament
memcpy(out, buf, size);
delete frameCallbackData;
if(callbackPtr) {
if (callbackPtr)
{
void (*callback)(void) = (void (*)(void))callbackPtr;
callback();
}
};
// Create a fence
Fence* fence = nullptr;
if(useFence) {
Fence *fence = nullptr;
if (useFence)
{
fence = _engine->createFence();
}
@@ -1285,7 +1175,7 @@ namespace thermion_filament
Texture::Format::RGBA,
Texture::Type::UBYTE, dispatcher, callback, userData);
_renderer->beginFrame(swapChain, 0);
_renderer->render(_view);
_renderer->render(view);
_renderer->readPixels(renderTarget, 0, 0, vp.width, vp.height, std::move(pbd));
_renderer->endFrame();
@@ -1293,138 +1183,22 @@ namespace thermion_filament
_engine->execute();
emscripten_webgl_commit_frame();
#endif
if(fence) {
Fence::waitAndDestroy(fence);
}
if (fence)
{
Fence::waitAndDestroy(fence);
}
}
Camera* FilamentViewer::getCamera(EntityId entity) {
Camera *FilamentViewer::getCamera(EntityId entity)
{
return _engine->getCameraComponent(Entity::import(entity));
}
void FilamentViewer::updateViewport(
uint32_t width, uint32_t height)
{
_view->setViewport({0, 0, width, height});
}
void FilamentViewer::setViewFrustumCulling(bool enabled)
{
_view->setFrustumCullingEnabled(enabled);
}
void FilamentViewer::_createManipulator()
{
Camera &cam = _view->getCamera();
math::double3 home = cam.getPosition();
math::double3 up = cam.getUpVector();
auto fv = cam.getForwardVector();
math::double3 target = home + fv;
Viewport const &vp = _view->getViewport();
_manipulator = Manipulator<double>::Builder()
.viewport(vp.width, vp.height)
.upVector(up.x, up.y, up.z)
.zoomSpeed(_zoomSpeed)
.targetPosition(target[0], target[1], target[2])
// only applicable to Mode::ORBIT
.orbitHomePosition(home[0], home[1], home[2])
.orbitSpeed(_orbitSpeedX, _orbitSpeedY)
// only applicable to Mode::FREE_FLIGHT
.flightStartPosition(home[0], home[1], home[2])
.build(_manipulatorMode);
}
void FilamentViewer::setCameraManipulatorOptions(filament::camutils::Mode mode, double orbitSpeedX, double orbitSpeedY, double zoomSpeed)
{
_manipulatorMode = mode;
_orbitSpeedX = orbitSpeedX;
_orbitSpeedY = orbitSpeedY;
_zoomSpeed = zoomSpeed;
}
void FilamentViewer::grabBegin(float x, float y, bool pan)
{
if (!_view || !_mainCamera)
{
Log("View not ready, ignoring grab");
return;
}
if (!_manipulator)
{
_createManipulator();
}
_manipulator->grabBegin(x, y, pan);
}
void FilamentViewer::grabUpdate(float x, float y)
{
if (!_view )
{
Log("View not ready, ignoring grab");
return;
}
if (_manipulator)
{
_manipulator->grabUpdate(x, y);
}
else
{
Log("Error - trying to use a manipulator when one is not available. Ensure you call grabBegin before grabUpdate/grabEnd");
}
}
void FilamentViewer::grabEnd()
{
if (!_view || !_mainCamera )
{
Log("View not ready, ignoring grab");
return;
}
if (_manipulator)
{
_manipulator->grabEnd();
}
else
{
Log("Error - trying to use a manipulator when one is not available. Ensure you call grabBegin before grabUpdate/grabEnd");
}
delete _manipulator;
_manipulator = nullptr;
}
void FilamentViewer::scrollBegin()
{
if (!_manipulator)
{
_createManipulator();
}
}
void FilamentViewer::scrollUpdate(float x, float y, float delta)
{
if (_manipulator)
{
_manipulator->scroll(int(x), int(y), delta);
}
else
{
Log("Error - trying to use a manipulator when one is not available. Ensure you call grabBegin before grabUpdate/grabEnd");
}
}
void FilamentViewer::scrollEnd()
{
delete _manipulator;
_manipulator = nullptr;
}
void FilamentViewer::pick(uint32_t x, uint32_t y, void (*callback)(EntityId entityId, int x, int y))
void FilamentViewer::pick(View *view, uint32_t x, uint32_t y, void (*callback)(EntityId entityId, int x, int y))
{
_view->pick(x, y, [=](filament::View::PickingQueryResult const &result) {
view->pick(x, y, [=](filament::View::PickingQueryResult const &result)
{
if(_sceneManager->gizmo->isGizmoEntity(result.renderable)) {
Log("Gizmo entity, ignoring");
@@ -1438,24 +1212,23 @@ namespace thermion_filament
if (nonPickableEntities.find(result.renderable) == nonPickableEntities.end()) {
callback(Entity::smuggle(result.renderable), x, y);
}
});
} });
}
void FilamentViewer::unprojectTexture(EntityId entityId, uint8_t* input, uint32_t inputWidth, uint32_t inputHeight, uint8_t* out, uint32_t outWidth, uint32_t outHeight) {
const auto * geometry = _sceneManager->getGeometry(entityId);
if(!geometry->uvs) {
Log("No UVS");
return;
void FilamentViewer::unprojectTexture(EntityId entityId, uint8_t *input, uint32_t inputWidth, uint32_t inputHeight, uint8_t *out, uint32_t outWidth, uint32_t outHeight)
{
const auto *geometry = _sceneManager->getGeometry(entityId);
if (!geometry->uvs)
{
Log("No UVS");
return;
}
UnprojectTexture unproject(geometry, _view->getCamera(), _engine);
// UnprojectTexture unproject(geometry, _view->getCamera(), _engine);
// TODO - check that input dimensions match viewport?
unproject.unproject(utils::Entity::import(entityId), input, out, inputWidth, inputHeight, outWidth, outHeight);
// unproject.unproject(utils::Entity::import(entityId), input, out, inputWidth, inputHeight, outWidth, outHeight);
}
} // namespace thermion_filament

View File

@@ -14,12 +14,10 @@ namespace thermion_filament {
using namespace filament::gltfio;
Gizmo::Gizmo(Engine &engine, View* view, Scene* scene) : _engine(engine)
Gizmo::Gizmo(Engine &engine, Scene* scene) : _engine(engine)
{
_scene = scene;
_view = view;
_camera = &(_view->getCamera());
auto &entityManager = EntityManager::get();
@@ -326,10 +324,10 @@ void Gizmo::unhighlight() {
}
}
void Gizmo::pick(uint32_t x, uint32_t y, void (*callback)(EntityId entityId, int x, int y))
void Gizmo::pick(View *view, uint32_t x, uint32_t y, void (*callback)(EntityId entityId, int x, int y))
{
auto handler = new Gizmo::PickCallbackHandler(this, callback);
_view->pick(x, y, [=](filament::View::PickingQueryResult const &result) {
view->pick(x, y, [=](filament::View::PickingQueryResult const &result) {
handler->handle(result);
});
}

View File

@@ -48,13 +48,12 @@ namespace thermion_filament
using namespace filament::gltfio;
using std::unique_ptr;
SceneManager::SceneManager(View *view,
const ResourceLoaderWrapperImpl *const resourceLoaderWrapper,
SceneManager::SceneManager(const ResourceLoaderWrapperImpl *const resourceLoaderWrapper,
Engine *engine,
Scene *scene,
const char *uberArchivePath,
Camera *mainCamera)
: _view(view),
:
_resourceLoaderWrapper(resourceLoaderWrapper),
_engine(engine),
_scene(scene),
@@ -99,21 +98,16 @@ namespace thermion_filament
_collisionComponentManager = new CollisionComponentManager(tm);
_animationComponentManager = new AnimationComponentManager(tm, _engine->getRenderableManager());
gizmo = new Gizmo(*_engine, _view, _scene);
gizmo = new Gizmo(*_engine, _scene);
_gridOverlay = new GridOverlay(*_engine);
_scene->addEntity(_gridOverlay->sphere());
_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
}
SceneManager::~SceneManager()
{
_view->setScene(nullptr);
_view->setCamera(nullptr);
for(auto camera : _cameras) {
auto entity = camera->getEntity();
_engine->destroyCameraComponent(entity);
@@ -1894,11 +1888,11 @@ namespace thermion_filament
tm.setTransform(transformInstance, newTransform);
}
void SceneManager::queueRelativePositionUpdateFromViewportVector(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();
const auto &vp = _view->getViewport();
const auto &camera = view->getCamera();
const auto &vp = view->getViewport();
// Convert viewport coordinates to NDC space
float ndcX = (2.0f * viewportCoordX) / vp.width - 1.0f;
@@ -2170,10 +2164,10 @@ namespace thermion_filament
rm.setPriority(renderableInstance, priority);
}
Aabb2 SceneManager::getBoundingBox(EntityId entityId)
Aabb2 SceneManager::getBoundingBox(View *view, EntityId entityId)
{
const auto &camera = _view->getCamera();
const auto &viewport = _view->getViewport();
const auto &camera = view->getCamera();
const auto &viewport = view->getViewport();
auto &tcm = _engine->getTransformManager();
auto &rcm = _engine->getRenderableManager();
@@ -2242,11 +2236,6 @@ namespace thermion_filament
return Aabb2{minX, minY, maxX, maxY};
}
void SceneManager::setLayerVisibility(LAYERS layer, bool enabled)
{
_view->setLayerEnabled(layer, enabled);
}
void SceneManager::removeStencilHighlight(EntityId entityId)
{
std::lock_guard lock(_stencilMutex);
@@ -2491,10 +2480,6 @@ EntityId SceneManager::createGeometry(
}
}
void SceneManager::setCamera(Camera* camera) {
_view->setCamera(camera);
}
size_t SceneManager::getCameraCount() {
return _cameras.size() + 1;
}
@@ -2508,11 +2493,6 @@ EntityId SceneManager::createGeometry(
}
return _cameras[index-1];
}
Camera* SceneManager::getActiveCamera() {
auto& camera = _view->getCamera();
return &camera;
}
} // namespace thermion_filament

View File

@@ -0,0 +1,29 @@
#ifdef _WIN32
#pragma comment(lib, "Shlwapi.lib")
#pragma comment(lib, "opengl32.lib")
#endif
#include "ResourceBuffer.hpp"
#include "FilamentViewer.hpp"
#include "filament/LightManager.h"
#include "Log.hpp"
#include "ThreadPool.hpp"
#include <thread>
#include <functional>
#ifdef __EMSCRIPTEN__
#include <emscripten/emscripten.h>
#endif
using namespace thermion_filament;
extern "C"
{
EMSCRIPTEN_KEEPALIVE void Gizmo_pick(TGizmo *tGizmo, TView *tView, int x, int y, void (*callback)(EntityId entityId, int x, int y))
{
auto *gizmo = reinterpret_cast<Gizmo*>(tGizmo);
auto *view = reinterpret_cast<View*>(tView);
gizmo->pick(view, x, y, callback);
}
}

View File

@@ -0,0 +1,142 @@
#ifdef _WIN32
#pragma comment(lib, "Shlwapi.lib")
#pragma comment(lib, "opengl32.lib")
#endif
#include "ResourceBuffer.hpp"
#include "FilamentViewer.hpp"
#include "filament/LightManager.h"
#include "Log.hpp"
#include "ThreadPool.hpp"
#include <thread>
#include <functional>
#ifdef __EMSCRIPTEN__
#include <emscripten/emscripten.h>
#endif
using namespace thermion_filament;
extern "C"
{
#include "ThermionDartApi.h"
EMSCRIPTEN_KEEPALIVE void View_updateViewport(TView *tView, uint32_t width, uint32_t height)
{
auto view = reinterpret_cast<View *>(tView);
view->setViewport({0, 0, width, height});
}
EMSCRIPTEN_KEEPALIVE void View_setRenderTarget(TView *tView, TRenderTarget *tRenderTarget)
{
auto view = reinterpret_cast<View *>(tView);
auto renderTarget = reinterpret_cast<RenderTarget *>(tRenderTarget);
view->setRenderTarget(renderTarget);
}
EMSCRIPTEN_KEEPALIVE void View_setFrustumCullingEnabled(TView *tView, bool enabled)
{
auto view = reinterpret_cast<View *>(tView);
view->setFrustumCullingEnabled(enabled);
}
EMSCRIPTEN_KEEPALIVE void View_setPostProcessing(TView *tView, bool enabled)
{
auto view = reinterpret_cast<View *>(tView);
view->setPostProcessingEnabled(enabled);
}
EMSCRIPTEN_KEEPALIVE void View_setShadowsEnabled(TView *tView, bool enabled)
{
auto view = reinterpret_cast<View *>(tView);
view->setShadowingEnabled(enabled);
}
EMSCRIPTEN_KEEPALIVE void View_setShadowType(TView *tView, ShadowType shadowType)
{
auto view = reinterpret_cast<View *>(tView);
view->setShadowType(shadowType);
}
EMSCRIPTEN_KEEPALIVE void View_setSoftShadowOptions(TView *tView, float penumbraScale, float penumbraRatioScale)
{
auto view = reinterpret_cast<View *>(tView);
SoftShadowOptions opts;
opts.penumbraRatioScale = penumbraRatioScale;
opts.penumbraScale = penumbraScale;
view->setSoftShadowOptions(opts);
}
EMSCRIPTEN_KEEPALIVE void View_setBloom(TView *tView, float strength)
{
auto view = reinterpret_cast<View *>(tView);
#ifndef __EMSCRIPTEN__
decltype(view->getBloomOptions()) opts;
opts.enabled = true;
opts.strength = strength;
view->setBloomOptions(opts);
#endif
}
EMSCRIPTEN_KEEPALIVE void View_setToneMapping(TView *tView, TEngine *tEngine, int toneMapping)
{
auto view = reinterpret_cast<View *>(tView);
auto engine = reinterpret_cast<Engine *>(tEngine);
ToneMapper *tm;
switch (toneMapping)
{
case ToneMapping::ACES:
Log("Setting tone mapping to ACES");
tm = new ACESToneMapper();
break;
case ToneMapping::LINEAR:
Log("Setting tone mapping to Linear");
tm = new LinearToneMapper();
break;
case ToneMapping::FILMIC:
Log("Setting tone mapping to Filmic");
tm = new FilmicToneMapper();
break;
default:
Log("ERROR: Unsupported tone mapping");
return;
}
auto newColorGrading = ColorGrading::Builder().toneMapper(tm).build(*engine);
auto oldColorGrading = view->getColorGrading();
view->setColorGrading(newColorGrading);
if (oldColorGrading)
{
engine->destroy(oldColorGrading);
}
delete tm;
}
void View_setAntiAliasing(TView *tView, bool msaa, bool fxaa, bool taa)
{
auto view = reinterpret_cast<View *>(tView);
View::MultiSampleAntiAliasingOptions multiSampleAntiAliasingOptions;
multiSampleAntiAliasingOptions.enabled = msaa;
view->setMultiSampleAntiAliasingOptions(multiSampleAntiAliasingOptions);
TemporalAntiAliasingOptions taaOpts;
taaOpts.enabled = taa;
view->setTemporalAntiAliasingOptions(taaOpts);
view->setAntiAliasing(fxaa ? AntiAliasing::FXAA : AntiAliasing::NONE);
}
EMSCRIPTEN_KEEPALIVE void View_setLayerEnabled(TView* tView, int layer, bool enabled) {
auto view = reinterpret_cast<View *>(tView);
view->setLayerEnabled(layer, enabled);
}
EMSCRIPTEN_KEEPALIVE void View_setCamera(TView *tView, TCamera *tCamera) {
auto view = reinterpret_cast<View *>(tView);
auto *camera = reinterpret_cast<Camera *>(tCamera);
view->setCamera(camera);
}
}

View File

@@ -48,32 +48,28 @@ extern "C"
{
const auto *loaderImpl = new ResourceLoaderWrapperImpl((ResourceLoaderWrapper *)loader);
auto viewer = new FilamentViewer(context, loaderImpl, platform, uberArchivePath);
return reinterpret_cast<TViewer*>(viewer);
return reinterpret_cast<TViewer *>(viewer);
}
EMSCRIPTEN_KEEPALIVE TEngine *Viewer_getEngine(TViewer* viewer) {
auto* engine = reinterpret_cast<FilamentViewer*>(viewer)->getEngine();
return reinterpret_cast<TEngine*>(engine);
EMSCRIPTEN_KEEPALIVE TEngine *Viewer_getEngine(TViewer *viewer)
{
auto *engine = reinterpret_cast<FilamentViewer *>(viewer)->getEngine();
return reinterpret_cast<TEngine *>(engine);
}
EMSCRIPTEN_KEEPALIVE TRenderTarget* Viewer_createRenderTarget(TViewer *tViewer, intptr_t texture, uint32_t width, uint32_t height)
EMSCRIPTEN_KEEPALIVE TRenderTarget *Viewer_createRenderTarget(TViewer *tViewer, intptr_t texture, uint32_t width, uint32_t height)
{
auto viewer = reinterpret_cast<FilamentViewer *>(tViewer);
auto renderTarget = viewer->createRenderTarget(texture, width, height);
return reinterpret_cast<TRenderTarget*>(renderTarget);
return reinterpret_cast<TRenderTarget *>(renderTarget);
}
EMSCRIPTEN_KEEPALIVE void Viewer_destroyRenderTarget(TViewer *tViewer, TRenderTarget* tRenderTarget) {
EMSCRIPTEN_KEEPALIVE void Viewer_destroyRenderTarget(TViewer *tViewer, TRenderTarget *tRenderTarget)
{
auto viewer = reinterpret_cast<FilamentViewer *>(tViewer);
auto renderTarget = reinterpret_cast<RenderTarget*>(tRenderTarget);
auto renderTarget = reinterpret_cast<RenderTarget *>(tRenderTarget);
viewer->destroyRenderTarget(renderTarget);
}
EMSCRIPTEN_KEEPALIVE void Viewer_setRenderTarget(TViewer *tViewer, TRenderTarget* tRenderTarget) {
auto viewer = reinterpret_cast<FilamentViewer *>(tViewer);
auto renderTarget = reinterpret_cast<RenderTarget*>(tRenderTarget);
viewer->setRenderTarget(renderTarget);
}
EMSCRIPTEN_KEEPALIVE void destroy_filament_viewer(TViewer *viewer)
{
@@ -92,23 +88,14 @@ extern "C"
EMSCRIPTEN_KEEPALIVE void set_background_image(TViewer *viewer, const char *path, bool fillHeight)
{
((FilamentViewer *)viewer)->setBackgroundImage(path, fillHeight);
((FilamentViewer *)viewer)->setBackgroundImage(path, fillHeight, 100, 100);
}
EMSCRIPTEN_KEEPALIVE void set_background_image_position(TViewer *viewer, float x, float y, bool clamp)
{
((FilamentViewer *)viewer)->setBackgroundImagePosition(x, y, clamp);
((FilamentViewer *)viewer)->setBackgroundImagePosition(x, y, clamp, 100, 100);
}
EMSCRIPTEN_KEEPALIVE void set_tone_mapping(TViewer *viewer, int toneMapping)
{
((FilamentViewer *)viewer)->setToneMapping((ToneMapping)toneMapping);
}
EMSCRIPTEN_KEEPALIVE void set_bloom(TViewer *viewer, float strength)
{
((FilamentViewer *)viewer)->setBloom(strength);
}
EMSCRIPTEN_KEEPALIVE void load_skybox(TViewer *viewer, const char *skyboxPath)
{
@@ -221,9 +208,11 @@ extern "C"
return ((SceneManager *)sceneManager)->loadGltf(assetPath, relativePath, keepData);
}
EMSCRIPTEN_KEEPALIVE void set_main_camera(TViewer *viewer)
EMSCRIPTEN_KEEPALIVE void Viewer_setMainCamera(TViewer *tViewer, TView *tView)
{
return ((FilamentViewer *)viewer)->setMainCamera();
auto *viewer = reinterpret_cast<FilamentViewer*>(tViewer);
auto *view = reinterpret_cast<View*>(tView);
viewer->setMainCamera(view);
}
EMSCRIPTEN_KEEPALIVE EntityId get_main_camera(TViewer *viewer)
@@ -231,11 +220,6 @@ extern "C"
return ((FilamentViewer *)viewer)->getMainCamera();
}
EMSCRIPTEN_KEEPALIVE bool set_camera(TViewer *viewer, EntityId asset, const char *nodeName)
{
return ((FilamentViewer *)viewer)->setCamera(asset, nodeName);
}
EMSCRIPTEN_KEEPALIVE float get_camera_fov(TCamera *camera, bool horizontal)
{
auto cam = reinterpret_cast<filament::Camera *>(camera);
@@ -334,15 +318,7 @@ extern "C"
return array;
}
EMSCRIPTEN_KEEPALIVE void set_camera_manipulator_options(TViewer *viewer, _ManipulatorMode mode, double orbitSpeedX, double orbitSpeedY, double zoomSpeed)
{
((FilamentViewer *)viewer)->setCameraManipulatorOptions((filament::camutils::Mode)mode, orbitSpeedX, orbitSpeedY, zoomSpeed);
}
EMSCRIPTEN_KEEPALIVE void set_view_frustum_culling(TViewer *viewer, bool enabled)
{
((FilamentViewer *)viewer)->setViewFrustumCulling(enabled);
}
EMSCRIPTEN_KEEPALIVE void set_camera_focus_distance(TCamera *camera, float distance)
{
@@ -365,20 +341,23 @@ extern "C"
EMSCRIPTEN_KEEPALIVE bool Viewer_render(
TViewer *tViewer,
TView *tView,
TSwapChain *tSwapChain,
uint64_t frameTimeInNanos,
void *pixelBuffer,
void (*callback)(void *buf, size_t size, void *data),
void *data)
{
auto swapChain = reinterpret_cast<SwapChain*>(tSwapChain);
auto viewer = reinterpret_cast<FilamentViewer*>(tViewer);
return viewer->render(frameTimeInNanos, swapChain, pixelBuffer, callback, data);
auto swapChain = reinterpret_cast<SwapChain *>(tSwapChain);
auto viewer = reinterpret_cast<FilamentViewer *>(tViewer);
auto *view = reinterpret_cast<View*>(tView);
return viewer->render(frameTimeInNanos, view, swapChain, pixelBuffer, callback, data);
}
EMSCRIPTEN_KEEPALIVE void Viewer_capture(
TViewer *tViewer,
TSwapChain* tSwapChain,
TView *tView,
TSwapChain *tSwapChain,
uint8_t *pixelBuffer,
void (*callback)(void))
{
@@ -387,14 +366,16 @@ extern "C"
#else
bool useFence = false;
#endif
auto swapChain = reinterpret_cast<SwapChain*>(tSwapChain);
auto viewer = reinterpret_cast<FilamentViewer*>(tViewer);
viewer->capture(pixelBuffer, useFence, swapChain, callback);
auto swapChain = reinterpret_cast<SwapChain *>(tSwapChain);
auto viewer = reinterpret_cast<FilamentViewer *>(tViewer);
auto *view = reinterpret_cast<View*>(tView);
viewer->capture(view, pixelBuffer, useFence, swapChain, callback);
};
EMSCRIPTEN_KEEPALIVE void Viewer_captureRenderTarget(
TViewer *tViewer,
TSwapChain* tSwapChain,
TView *tView,
TSwapChain *tSwapChain,
TRenderTarget *tRenderTarget,
uint8_t *pixelBuffer,
void (*callback)(void))
@@ -404,10 +385,11 @@ extern "C"
#else
bool useFence = false;
#endif
auto swapChain = reinterpret_cast<SwapChain*>(tSwapChain);
auto renderTarget = reinterpret_cast<RenderTarget*>(tRenderTarget);
auto viewer = reinterpret_cast<FilamentViewer*>(tViewer);
viewer->capture(pixelBuffer, useFence, swapChain, renderTarget, callback);
auto swapChain = reinterpret_cast<SwapChain *>(tSwapChain);
auto renderTarget = reinterpret_cast<RenderTarget *>(tRenderTarget);
auto viewer = reinterpret_cast<FilamentViewer *>(tViewer);
auto *view = reinterpret_cast<View*>(tView);
viewer->capture(view, pixelBuffer, useFence, swapChain, renderTarget, callback);
};
EMSCRIPTEN_KEEPALIVE void set_frame_interval(
@@ -417,59 +399,41 @@ extern "C"
((FilamentViewer *)viewer)->setFrameInterval(frameInterval);
}
EMSCRIPTEN_KEEPALIVE void Viewer_destroySwapChain(TViewer *tViewer, TSwapChain* tSwapChain)
EMSCRIPTEN_KEEPALIVE void Viewer_destroySwapChain(TViewer *tViewer, TSwapChain *tSwapChain)
{
auto viewer = reinterpret_cast<FilamentViewer*>(tViewer);
auto swapChain = reinterpret_cast<SwapChain*>(tSwapChain);
auto viewer = reinterpret_cast<FilamentViewer *>(tViewer);
auto swapChain = reinterpret_cast<SwapChain *>(tSwapChain);
viewer->destroySwapChain(swapChain);
}
EMSCRIPTEN_KEEPALIVE TSwapChain *Viewer_createSwapChain(TViewer *tViewer, const void *const window, uint32_t width, uint32_t height) {
auto viewer = reinterpret_cast<FilamentViewer*>(tViewer);
EMSCRIPTEN_KEEPALIVE TSwapChain *Viewer_createSwapChain(TViewer *tViewer, const void *const window, uint32_t width, uint32_t height)
{
auto viewer = reinterpret_cast<FilamentViewer *>(tViewer);
auto swapChain = viewer->createSwapChain(window, width, height);
return reinterpret_cast<TSwapChain*>(swapChain);
return reinterpret_cast<TSwapChain *>(swapChain);
}
EMSCRIPTEN_KEEPALIVE void update_viewport(TViewer *viewer, uint32_t width, uint32_t height)
EMSCRIPTEN_KEEPALIVE TView *Viewer_createView(TViewer *tViewer)
{
return ((FilamentViewer *)viewer)->updateViewport(width, height);
auto viewer = reinterpret_cast<FilamentViewer *>(tViewer);
auto view = viewer->createView();
return reinterpret_cast<TView *>(view);
}
EMSCRIPTEN_KEEPALIVE void scroll_update(TViewer *viewer, float x, float y, float delta)
EMSCRIPTEN_KEEPALIVE TView *Viewer_getViewAt(TViewer *tViewer, int32_t index)
{
((FilamentViewer *)viewer)->scrollUpdate(x, y, delta);
auto viewer = reinterpret_cast<FilamentViewer *>(tViewer);
auto view = viewer->getViewAt(index);
return reinterpret_cast<TView *>(view);
}
EMSCRIPTEN_KEEPALIVE void scroll_begin(TViewer *viewer)
{
((FilamentViewer *)viewer)->scrollBegin();
}
EMSCRIPTEN_KEEPALIVE void scroll_end(TViewer *viewer)
EMSCRIPTEN_KEEPALIVE TSceneManager *Viewer_getSceneManager(TViewer *tViewer)
{
((FilamentViewer *)viewer)->scrollEnd();
}
EMSCRIPTEN_KEEPALIVE void grab_begin(TViewer *viewer, float x, float y, bool pan)
{
((FilamentViewer *)viewer)->grabBegin(x, y, pan);
}
EMSCRIPTEN_KEEPALIVE void grab_update(TViewer *viewer, float x, float y)
{
((FilamentViewer *)viewer)->grabUpdate(x, y);
}
EMSCRIPTEN_KEEPALIVE void grab_end(TViewer *viewer)
{
((FilamentViewer *)viewer)->grabEnd();
}
EMSCRIPTEN_KEEPALIVE TSceneManager* Viewer_getSceneManager(TViewer *tViewer)
{
auto * viewer = reinterpret_cast<FilamentViewer*>(tViewer);
auto * sceneManager = viewer->getSceneManager();
return reinterpret_cast<TSceneManager*>(sceneManager);
auto *viewer = reinterpret_cast<FilamentViewer *>(tViewer);
auto *sceneManager = viewer->getSceneManager();
return reinterpret_cast<TSceneManager *>(sceneManager);
}
EMSCRIPTEN_KEEPALIVE void apply_weights(
@@ -529,31 +493,6 @@ extern "C"
((SceneManager *)sceneManager)->addBoneAnimation(asset, skinIndex, boneIndex, frameData, numFrames, frameLengthInMs, fadeOutInSecs, fadeInInSecs, maxDelta);
}
EMSCRIPTEN_KEEPALIVE void set_post_processing(TViewer *viewer, bool enabled)
{
((FilamentViewer *)viewer)->setPostProcessing(enabled);
}
EMSCRIPTEN_KEEPALIVE void set_shadows_enabled(TViewer *viewer, bool enabled)
{
((FilamentViewer *)viewer)->setShadowsEnabled(enabled);
}
EMSCRIPTEN_KEEPALIVE void set_shadow_type(TViewer *viewer, int shadowType)
{
((FilamentViewer *)viewer)->setShadowType((ShadowType)shadowType);
}
EMSCRIPTEN_KEEPALIVE void set_soft_shadow_options(TViewer *viewer, float penumbraScale, float penumbraRatioScale)
{
((FilamentViewer *)viewer)->setSoftShadowOptions(penumbraScale, penumbraRatioScale);
}
EMSCRIPTEN_KEEPALIVE void set_antialiasing(TViewer *viewer, bool msaa, bool fxaa, bool taa)
{
((FilamentViewer *)viewer)->setAntiAliasing(msaa, fxaa, taa);
}
EMSCRIPTEN_KEEPALIVE EntityId get_bone(TSceneManager *sceneManager,
EntityId entityId,
int skinIndex,
@@ -737,6 +676,17 @@ extern "C"
}
}
EMSCRIPTEN_KEEPALIVE TCamera* SceneManager_getCameraByName(TSceneManager *tSceneManager, EntityId entityId, const char* name) {
auto *sceneManager = reinterpret_cast<SceneManager*>(tSceneManager);
return nullptr;
}
EMSCRIPTEN_KEEPALIVE TGizmo* SceneManager_getGizmo(TSceneManager *tSceneManager) {
auto *sceneManager = reinterpret_cast<SceneManager*>(tSceneManager);
auto *gizmo = sceneManager->gizmo;
return reinterpret_cast<TGizmo*>(gizmo);
}
EMSCRIPTEN_KEEPALIVE bool SceneManager_setTransform(TSceneManager *sceneManager, EntityId entityId, const double *const transform)
{
auto matrix = math::mat4(
@@ -757,25 +707,27 @@ extern "C"
return ((SceneManager *)sceneManager)->setTransform(entityId, matrix);
}
EMSCRIPTEN_KEEPALIVE void SceneManager_queueTransformUpdates(TSceneManager *tSceneManager, EntityId* entities, const double* const transforms, int numEntities) {
auto * sceneManager = reinterpret_cast<SceneManager*>(tSceneManager);
EMSCRIPTEN_KEEPALIVE void SceneManager_queueTransformUpdates(TSceneManager *tSceneManager, EntityId *entities, const double *const transforms, int numEntities)
{
auto *sceneManager = reinterpret_cast<SceneManager *>(tSceneManager);
math::mat4 matrices[numEntities];
for(int i = 0; i < numEntities; i++) {
matrices[i] = math::mat4(
transforms[i * 16], transforms[i*16+1], transforms[i*16+2],
transforms[i*16+3],
transforms[i*16+4],
transforms[i*16+5],
transforms[i*16+6],
transforms[i*16+7],
transforms[i*16+8],
transforms[i*16+9],
transforms[i*16+10],
transforms[i*16+11],
transforms[i*16+12],
transforms[i*16+13],
transforms[i*16+14],
transforms[i*16+15]);
for (int i = 0; i < numEntities; i++)
{
matrices[i] = math::mat4(
transforms[i * 16], transforms[i * 16 + 1], transforms[i * 16 + 2],
transforms[i * 16 + 3],
transforms[i * 16 + 4],
transforms[i * 16 + 5],
transforms[i * 16 + 6],
transforms[i * 16 + 7],
transforms[i * 16 + 8],
transforms[i * 16 + 9],
transforms[i * 16 + 10],
transforms[i * 16 + 11],
transforms[i * 16 + 12],
transforms[i * 16 + 13],
transforms[i * 16 + 14],
transforms[i * 16 + 15]);
}
sceneManager->queueTransformUpdates(entities, matrices, numEntities);
}
@@ -833,9 +785,10 @@ extern "C"
((SceneManager *)sceneManager)->setScale(asset, scale);
}
EMSCRIPTEN_KEEPALIVE void queue_position_update_from_viewport_coords(TSceneManager *sceneManager, EntityId entity, float viewportX, float viewportY)
EMSCRIPTEN_KEEPALIVE void queue_position_update_from_viewport_coords(TSceneManager *sceneManager, TView *tView, EntityId entity, float viewportX, float viewportY)
{
((SceneManager *)sceneManager)->queueRelativePositionUpdateFromViewportVector(entity, viewportX, viewportY);
auto *view = reinterpret_cast<View*>(tView);
((SceneManager *)sceneManager)->queueRelativePositionUpdateFromViewportVector(view, entity, viewportX, viewportY);
}
EMSCRIPTEN_KEEPALIVE void stop_animation(TSceneManager *sceneManager, EntityId asset, int index)
@@ -853,9 +806,11 @@ extern "C"
return ((SceneManager *)sceneManager)->reveal(asset, meshName);
}
EMSCRIPTEN_KEEPALIVE void filament_pick(TViewer *viewer, int x, int y, void (*callback)(EntityId entityId, int x, int y))
EMSCRIPTEN_KEEPALIVE void filament_pick(TViewer *tViewer, TView* tView, int x, int y, void (*callback)(EntityId entityId, int x, int y))
{
((FilamentViewer *)viewer)->pick(static_cast<uint32_t>(x), static_cast<uint32_t>(y), callback);
auto *viewer = reinterpret_cast<FilamentViewer*>(tViewer);
auto *view = reinterpret_cast<View*>(tView);
((FilamentViewer *)viewer)->pick(view, static_cast<uint32_t>(x), static_cast<uint32_t>(y), callback);
}
EMSCRIPTEN_KEEPALIVE const char *get_name_for_entity(TSceneManager *sceneManager, const EntityId entityId)
@@ -965,28 +920,26 @@ extern "C"
out[3] = Entity::smuggle(gizmo->center());
}
EMSCRIPTEN_KEEPALIVE Aabb2 get_bounding_box(TSceneManager *sceneManager, EntityId entity)
EMSCRIPTEN_KEEPALIVE Aabb2 get_bounding_box(TSceneManager *sceneManager, TView *tView, EntityId entity)
{
return ((SceneManager *)sceneManager)->getBoundingBox(entity);
auto view = reinterpret_cast<View*>(tView);
return ((SceneManager *)sceneManager)->getBoundingBox(view, entity);
}
EMSCRIPTEN_KEEPALIVE void get_bounding_box_to_out(TSceneManager *sceneManager, EntityId entity, float *minX, float *minY, float *maxX, float *maxY)
EMSCRIPTEN_KEEPALIVE void get_bounding_box_to_out(TSceneManager *sceneManager, TView *tView, EntityId entity, float *minX, float *minY, float *maxX, float *maxY)
{
auto box = ((SceneManager *)sceneManager)->getBoundingBox(entity);
auto view = reinterpret_cast<View*>(tView);
auto box = ((SceneManager *)sceneManager)->getBoundingBox(view, entity);
*minX = box.minX;
*minY = box.minY;
*maxX = box.maxX;
*maxY = box.maxY;
}
EMSCRIPTEN_KEEPALIVE void set_visibility_layer(TSceneManager *sceneManager, EntityId entity, int layer) {
((SceneManager*)sceneManager)->setVisibilityLayer(entity, layer);
}
EMSCRIPTEN_KEEPALIVE void set_layer_visibility(TSceneManager *sceneManager, int layer, bool visible)
EMSCRIPTEN_KEEPALIVE void SceneManager_setVisibilityLayer(TSceneManager *tSceneManager, EntityId entity, int layer)
{
((SceneManager *)sceneManager)->setLayerVisibility((SceneManager::LAYERS)layer, visible);
auto *sceneManager = reinterpret_cast<SceneManager*>(tSceneManager);
sceneManager->setVisibilityLayer(entity, layer);
}
EMSCRIPTEN_KEEPALIVE void thermion_flutter_free(void *ptr)
@@ -994,11 +947,6 @@ extern "C"
free(ptr);
}
EMSCRIPTEN_KEEPALIVE void pick_gizmo(TSceneManager *sceneManager, int x, int y, void (*callback)(EntityId entityId, int x, int y))
{
((SceneManager *)sceneManager)->gizmo->pick(x, y, callback);
}
EMSCRIPTEN_KEEPALIVE void set_gizmo_visibility(TSceneManager *sceneManager, bool visible)
{
((SceneManager *)sceneManager)->gizmo->setVisibility(visible);
@@ -1019,9 +967,10 @@ extern "C"
((SceneManager *)sceneManager)->setMaterialProperty(entity, materialIndex, property, value);
}
EMSCRIPTEN_KEEPALIVE TMaterialInstance* get_material_instance_at(TSceneManager *sceneManager, EntityId entity, int materialIndex) {
EMSCRIPTEN_KEEPALIVE TMaterialInstance *get_material_instance_at(TSceneManager *sceneManager, EntityId entity, int materialIndex)
{
auto instance = ((SceneManager *)sceneManager)->getMaterialInstanceAt(entity, materialIndex);
return reinterpret_cast<TMaterialInstance*>(instance);
return reinterpret_cast<TMaterialInstance *>(instance);
}
EMSCRIPTEN_KEEPALIVE void set_material_property_int(TSceneManager *sceneManager, EntityId entity, int materialIndex, const char *property, int32_t value)
@@ -1030,7 +979,7 @@ extern "C"
}
EMSCRIPTEN_KEEPALIVE void set_material_property_float4(TSceneManager *sceneManager, EntityId entity, int materialIndex, const char *property, double4 value)
{
{
filament::math::float4 filamentValue;
filamentValue.x = static_cast<float32_t>(value.x);
filamentValue.y = static_cast<float32_t>(value.y);
@@ -1039,7 +988,7 @@ extern "C"
((SceneManager *)sceneManager)->setMaterialProperty(entity, materialIndex, property, filamentValue);
}
EMSCRIPTEN_KEEPALIVE void unproject_texture(TViewer *viewer, EntityId entity, uint8_t* input, uint32_t inputWidth, uint32_t inputHeight, uint8_t *out, uint32_t outWidth, uint32_t outHeight)
EMSCRIPTEN_KEEPALIVE void unproject_texture(TViewer *viewer, EntityId entity, uint8_t *input, uint32_t inputWidth, uint32_t inputHeight, uint8_t *out, uint32_t outWidth, uint32_t outHeight)
{
((FilamentViewer *)viewer)->unprojectTexture(entity, input, inputWidth, inputHeight, out, outWidth, outHeight);
}
@@ -1059,146 +1008,154 @@ extern "C"
((SceneManager *)sceneManager)->destroyTexture(reinterpret_cast<Texture *>(texture));
}
EMSCRIPTEN_KEEPALIVE TMaterialInstance *create_material_instance(TSceneManager *sceneManager, TMaterialKey materialConfig)
{
EMSCRIPTEN_KEEPALIVE TMaterialInstance* create_material_instance(TSceneManager *sceneManager, TMaterialKey materialConfig)
{
filament::gltfio::MaterialKey config;
memset(&config, 0, sizeof(MaterialKey));
filament::gltfio::MaterialKey config;
memset(&config, 0, sizeof(MaterialKey));
// Set and log each field
config.unlit = materialConfig.unlit;
config.doubleSided = materialConfig.doubleSided;
config.useSpecularGlossiness = materialConfig.useSpecularGlossiness;
config.alphaMode = static_cast<filament::gltfio::AlphaMode>(materialConfig.alphaMode);
config.hasBaseColorTexture = materialConfig.hasBaseColorTexture;
config.hasClearCoat = materialConfig.hasClearCoat;
config.hasClearCoatNormalTexture = materialConfig.hasClearCoatNormalTexture;
config.hasClearCoatRoughnessTexture = materialConfig.hasClearCoatRoughnessTexture;
config.hasEmissiveTexture = materialConfig.hasEmissiveTexture;
config.hasIOR = materialConfig.hasIOR;
config.hasMetallicRoughnessTexture = materialConfig.hasMetallicRoughnessTexture;
config.hasNormalTexture = materialConfig.hasNormalTexture;
config.hasOcclusionTexture = materialConfig.hasOcclusionTexture;
config.hasSheen = materialConfig.hasSheen;
config.hasSheenColorTexture = materialConfig.hasSheenColorTexture;
config.hasSheenRoughnessTexture = materialConfig.hasSheenRoughnessTexture;
config.hasTextureTransforms = materialConfig.hasTextureTransforms;
config.hasTransmission = materialConfig.hasTransmission;
config.hasTransmissionTexture = materialConfig.hasTransmissionTexture;
config.hasVolume = materialConfig.hasVolume;
config.hasVolumeThicknessTexture = materialConfig.hasVolumeThicknessTexture;
config.baseColorUV = materialConfig.baseColorUV;
config.hasVertexColors = materialConfig.hasVertexColors;
auto materialInstance = ((SceneManager *)sceneManager)->createUbershaderMaterialInstance(config);
return reinterpret_cast<TMaterialInstance*>(materialInstance);
}
EMSCRIPTEN_KEEPALIVE TMaterialInstance *create_unlit_material_instance(TSceneManager *sceneManager) {
auto * instance = ((SceneManager*)sceneManager)->createUnlitMaterialInstance();
return reinterpret_cast<TMaterialInstance*>(instance);
}
EMSCRIPTEN_KEEPALIVE void destroy_material_instance(TSceneManager *sceneManager, TMaterialInstance *instance) {
((SceneManager *)sceneManager)->destroy(reinterpret_cast<MaterialInstance*>(instance));
}
EMSCRIPTEN_KEEPALIVE void MaterialInstance_setDepthWrite(TMaterialInstance* materialInstance, bool enabled) {
reinterpret_cast<MaterialInstance*>(materialInstance)->setDepthWrite(enabled);
}
EMSCRIPTEN_KEEPALIVE void MaterialInstance_setDepthCulling(TMaterialInstance* materialInstance, bool enabled) {
reinterpret_cast<MaterialInstance*>(materialInstance)->setDepthCulling(enabled);
}
EMSCRIPTEN_KEEPALIVE void MaterialInstance_setParameterFloat2(TMaterialInstance* materialInstance, const char* propertyName, double x, double y) {
filament::math::float2 data { static_cast<float>(x), static_cast<float>(y) };
reinterpret_cast<MaterialInstance*>(materialInstance)->setParameter(propertyName, data);
}
EMSCRIPTEN_KEEPALIVE void Camera_setCustomProjectionWithCulling(TCamera* tCamera, double4x4 projectionMatrix, double near, double far) {
auto * camera = reinterpret_cast<Camera*>(tCamera);
camera->setCustomProjection(convert_double4x4_to_mat4(projectionMatrix), near, far);
}
EMSCRIPTEN_KEEPALIVE double4x4 Camera_getModelMatrix(TCamera* tCamera) {
auto * camera = reinterpret_cast<Camera*>(tCamera);
return convert_mat4_to_double4x4(camera->getModelMatrix());
}
EMSCRIPTEN_KEEPALIVE double4x4 Camera_getViewMatrix(TCamera *const tCamera) {
auto * camera = reinterpret_cast<Camera*>(tCamera);
return convert_mat4_to_double4x4(camera->getViewMatrix());
}
EMSCRIPTEN_KEEPALIVE EntityId Camera_getEntity(TCamera* tCamera) {
auto * camera = reinterpret_cast<Camera*>(tCamera);
return Entity::smuggle(camera->getEntity());
}
EMSCRIPTEN_KEEPALIVE double Camera_getFocalLength(TCamera *const tCamera) {
auto * camera = reinterpret_cast<Camera*>(tCamera);
return camera->getFocalLength();
}
EMSCRIPTEN_KEEPALIVE double Camera_getNear(TCamera *const tCamera) {
auto * camera = reinterpret_cast<Camera*>(tCamera);
return camera->getNear();
}
EMSCRIPTEN_KEEPALIVE double Camera_getCullingFar(TCamera *const tCamera) {
auto * camera = reinterpret_cast<Camera*>(tCamera);
return camera->getCullingFar();
}
EMSCRIPTEN_KEEPALIVE TCamera *Engine_getCameraComponent(TEngine* tEngine, EntityId entityId) {
auto * engine = reinterpret_cast<Engine*>(tEngine);
auto * camera = engine->getCameraComponent(utils::Entity::import(entityId));
return reinterpret_cast<TCamera*>(camera);
}
EMSCRIPTEN_KEEPALIVE void Engine_setTransform(TEngine* tEngine, EntityId entity, double4x4 transform) {
auto * engine = reinterpret_cast<Engine*>(tEngine);
auto& transformManager = engine->getTransformManager();
auto transformInstance = transformManager.getInstance(utils::Entity::import(entity));
if(!transformInstance.isValid()) {
Log("Transform instance not valid");
// Set and log each field
config.unlit = materialConfig.unlit;
config.doubleSided = materialConfig.doubleSided;
config.useSpecularGlossiness = materialConfig.useSpecularGlossiness;
config.alphaMode = static_cast<filament::gltfio::AlphaMode>(materialConfig.alphaMode);
config.hasBaseColorTexture = materialConfig.hasBaseColorTexture;
config.hasClearCoat = materialConfig.hasClearCoat;
config.hasClearCoatNormalTexture = materialConfig.hasClearCoatNormalTexture;
config.hasClearCoatRoughnessTexture = materialConfig.hasClearCoatRoughnessTexture;
config.hasEmissiveTexture = materialConfig.hasEmissiveTexture;
config.hasIOR = materialConfig.hasIOR;
config.hasMetallicRoughnessTexture = materialConfig.hasMetallicRoughnessTexture;
config.hasNormalTexture = materialConfig.hasNormalTexture;
config.hasOcclusionTexture = materialConfig.hasOcclusionTexture;
config.hasSheen = materialConfig.hasSheen;
config.hasSheenColorTexture = materialConfig.hasSheenColorTexture;
config.hasSheenRoughnessTexture = materialConfig.hasSheenRoughnessTexture;
config.hasTextureTransforms = materialConfig.hasTextureTransforms;
config.hasTransmission = materialConfig.hasTransmission;
config.hasTransmissionTexture = materialConfig.hasTransmissionTexture;
config.hasVolume = materialConfig.hasVolume;
config.hasVolumeThicknessTexture = materialConfig.hasVolumeThicknessTexture;
config.baseColorUV = materialConfig.baseColorUV;
config.hasVertexColors = materialConfig.hasVertexColors;
auto materialInstance = ((SceneManager *)sceneManager)->createUbershaderMaterialInstance(config);
return reinterpret_cast<TMaterialInstance *>(materialInstance);
}
transformManager.setTransform(transformInstance, convert_double4x4_to_mat4(transform));
}
EMSCRIPTEN_KEEPALIVE TCamera *SceneManager_createCamera(TSceneManager* tSceneManager) {
auto * sceneManager = reinterpret_cast<SceneManager*>(tSceneManager);
return reinterpret_cast<TCamera*>(sceneManager->createCamera());
}
EMSCRIPTEN_KEEPALIVE TMaterialInstance *create_unlit_material_instance(TSceneManager *sceneManager)
{
auto *instance = ((SceneManager *)sceneManager)->createUnlitMaterialInstance();
return reinterpret_cast<TMaterialInstance *>(instance);
}
EMSCRIPTEN_KEEPALIVE void SceneManager_destroyCamera(TSceneManager* tSceneManager, TCamera* tCamera) {
auto * sceneManager = reinterpret_cast<SceneManager*>(tSceneManager);
auto * camera = reinterpret_cast<Camera*>(tCamera);
sceneManager->destroyCamera(camera);
}
EMSCRIPTEN_KEEPALIVE void destroy_material_instance(TSceneManager *sceneManager, TMaterialInstance *instance)
{
((SceneManager *)sceneManager)->destroy(reinterpret_cast<MaterialInstance *>(instance));
}
EMSCRIPTEN_KEEPALIVE void SceneManager_setCamera(TSceneManager* tSceneManager, TCamera* tCamera) {
auto * sceneManager = reinterpret_cast<SceneManager*>(tSceneManager);
auto * camera = reinterpret_cast<Camera*>(tCamera);
sceneManager->setCamera(camera);
}
EMSCRIPTEN_KEEPALIVE void MaterialInstance_setDepthWrite(TMaterialInstance *materialInstance, bool enabled)
{
reinterpret_cast<MaterialInstance *>(materialInstance)->setDepthWrite(enabled);
}
EMSCRIPTEN_KEEPALIVE size_t SceneManager_getCameraCount(TSceneManager *tSceneManager) {
auto * sceneManager = reinterpret_cast<SceneManager*>(tSceneManager);
return sceneManager->getCameraCount();
}
EMSCRIPTEN_KEEPALIVE TCamera* SceneManager_getCameraAt(TSceneManager *tSceneManager, size_t index) {
auto * sceneManager = reinterpret_cast<SceneManager*>(tSceneManager);
auto * camera = sceneManager->getCameraAt(index);
return reinterpret_cast<TCamera*>(camera);
}
EMSCRIPTEN_KEEPALIVE void MaterialInstance_setDepthCulling(TMaterialInstance *materialInstance, bool enabled)
{
reinterpret_cast<MaterialInstance *>(materialInstance)->setDepthCulling(enabled);
}
EMSCRIPTEN_KEEPALIVE void MaterialInstance_setParameterFloat2(TMaterialInstance *materialInstance, const char *propertyName, double x, double y)
{
filament::math::float2 data{static_cast<float>(x), static_cast<float>(y)};
reinterpret_cast<MaterialInstance *>(materialInstance)->setParameter(propertyName, data);
}
EMSCRIPTEN_KEEPALIVE void Camera_setCustomProjectionWithCulling(TCamera *tCamera, double4x4 projectionMatrix, double near, double far)
{
auto *camera = reinterpret_cast<Camera *>(tCamera);
camera->setCustomProjection(convert_double4x4_to_mat4(projectionMatrix), near, far);
}
EMSCRIPTEN_KEEPALIVE double4x4 Camera_getModelMatrix(TCamera *tCamera)
{
auto *camera = reinterpret_cast<Camera *>(tCamera);
return convert_mat4_to_double4x4(camera->getModelMatrix());
}
EMSCRIPTEN_KEEPALIVE double4x4 Camera_getViewMatrix(TCamera *const tCamera)
{
auto *camera = reinterpret_cast<Camera *>(tCamera);
return convert_mat4_to_double4x4(camera->getViewMatrix());
}
EMSCRIPTEN_KEEPALIVE EntityId Camera_getEntity(TCamera *tCamera)
{
auto *camera = reinterpret_cast<Camera *>(tCamera);
return Entity::smuggle(camera->getEntity());
}
EMSCRIPTEN_KEEPALIVE double Camera_getFocalLength(TCamera *const tCamera)
{
auto *camera = reinterpret_cast<Camera *>(tCamera);
return camera->getFocalLength();
}
EMSCRIPTEN_KEEPALIVE double Camera_getNear(TCamera *const tCamera)
{
auto *camera = reinterpret_cast<Camera *>(tCamera);
return camera->getNear();
}
EMSCRIPTEN_KEEPALIVE double Camera_getCullingFar(TCamera *const tCamera)
{
auto *camera = reinterpret_cast<Camera *>(tCamera);
return camera->getCullingFar();
}
EMSCRIPTEN_KEEPALIVE TCamera *Engine_getCameraComponent(TEngine *tEngine, EntityId entityId)
{
auto *engine = reinterpret_cast<Engine *>(tEngine);
auto *camera = engine->getCameraComponent(utils::Entity::import(entityId));
return reinterpret_cast<TCamera *>(camera);
}
EMSCRIPTEN_KEEPALIVE void Engine_setTransform(TEngine *tEngine, EntityId entity, double4x4 transform)
{
auto *engine = reinterpret_cast<Engine *>(tEngine);
auto &transformManager = engine->getTransformManager();
auto transformInstance = transformManager.getInstance(utils::Entity::import(entity));
if (!transformInstance.isValid())
{
Log("Transform instance not valid");
}
transformManager.setTransform(transformInstance, convert_double4x4_to_mat4(transform));
}
EMSCRIPTEN_KEEPALIVE TCamera *SceneManager_createCamera(TSceneManager *tSceneManager)
{
auto *sceneManager = reinterpret_cast<SceneManager *>(tSceneManager);
return reinterpret_cast<TCamera *>(sceneManager->createCamera());
}
EMSCRIPTEN_KEEPALIVE void SceneManager_destroyCamera(TSceneManager *tSceneManager, TCamera *tCamera)
{
auto *sceneManager = reinterpret_cast<SceneManager *>(tSceneManager);
auto *camera = reinterpret_cast<Camera *>(tCamera);
sceneManager->destroyCamera(camera);
}
EMSCRIPTEN_KEEPALIVE size_t SceneManager_getCameraCount(TSceneManager *tSceneManager)
{
auto *sceneManager = reinterpret_cast<SceneManager *>(tSceneManager);
return sceneManager->getCameraCount();
}
EMSCRIPTEN_KEEPALIVE TCamera *SceneManager_getCameraAt(TSceneManager *tSceneManager, size_t index)
{
auto *sceneManager = reinterpret_cast<SceneManager *>(tSceneManager);
auto *camera = sceneManager->getCameraAt(index);
return reinterpret_cast<TCamera *>(camera);
}
EMSCRIPTEN_KEEPALIVE TCamera* SceneManager_getActiveCamera(TSceneManager *tSceneManager) {
auto * sceneManager = reinterpret_cast<SceneManager*>(tSceneManager);
auto * camera = sceneManager->getActiveCamera();
return reinterpret_cast<TCamera*>(camera);
}
}

View File

@@ -82,9 +82,10 @@ public:
}
}
void requestFrame(SwapChain* swapChain, void (*callback)())
void requestFrame(TView* tView, TSwapChain* tSwapChain, void (*callback)())
{
this->target = swapChain;
this->target = tSwapChain;
this->view = tView;
this->_requestFrameRenderCallback = callback;
}
@@ -93,7 +94,7 @@ public:
std::unique_lock<std::mutex> lock(_mutex);
if (target)
{
doRender(target);
doRender(view, target);
this->_requestFrameRenderCallback();
target = nullptr;
@@ -176,7 +177,7 @@ public:
fut.wait();
}
bool doRender(SwapChain *swapChain)
bool doRender(TView* tView, TSwapChain *tSwapChain)
{
#ifdef __EMSCRIPTEN__
if (emscripten_is_webgl_context_lost(_context) == EM_TRUE)
@@ -187,8 +188,7 @@ public:
return;
}
#endif
TSwapChain *tSwapChain = reinterpret_cast<TSwapChain*>(swapChain);
auto rendered = Viewer_render(_viewer, tSwapChain, 0, nullptr, nullptr, nullptr);
auto rendered = Viewer_render(_viewer, tView, tSwapChain, 0, nullptr, nullptr, nullptr);
if (_renderCallback)
{
_renderCallback(_renderCallbackOwner);
@@ -218,7 +218,8 @@ public:
}
public:
SwapChain* target;
TSwapChain *target;
TView *view;
private:
void(*_requestFrameRenderCallback)() = nullptr;
@@ -306,7 +307,7 @@ extern "C"
}
EMSCRIPTEN_KEEPALIVE void Viewer_requestFrameRenderThread(TViewer *viewer, TSwapChain* tSwapChain, void(*onComplete)())
EMSCRIPTEN_KEEPALIVE void Viewer_requestFrameRenderThread(TViewer *viewer, TView* view, TSwapChain* tSwapChain, void(*onComplete)())
{
if (!_rl)
{
@@ -314,7 +315,7 @@ extern "C"
}
else
{
_rl->requestFrame(reinterpret_cast<SwapChain*>(tSwapChain), onComplete);
_rl->requestFrame(view, tSwapChain, onComplete);
}
}
@@ -327,24 +328,24 @@ extern "C"
auto fut = _rl->add_task(lambda);
}
EMSCRIPTEN_KEEPALIVE void Viewer_renderRenderThread(TViewer *viewer, TSwapChain *tSwapChain)
EMSCRIPTEN_KEEPALIVE void Viewer_renderRenderThread(TViewer *viewer, TView *tView, TSwapChain *tSwapChain)
{
std::packaged_task<void()> lambda([=]() mutable
{ _rl->doRender(reinterpret_cast<SwapChain*>(tSwapChain)); });
{ _rl->doRender(tView, tSwapChain); });
auto fut = _rl->add_task(lambda);
}
EMSCRIPTEN_KEEPALIVE void Viewer_captureRenderThread(TViewer *viewer, TSwapChain *tSwapChain, uint8_t *pixelBuffer, void (*onComplete)())
EMSCRIPTEN_KEEPALIVE void Viewer_captureRenderThread(TViewer *viewer, TView *view, TSwapChain *tSwapChain, uint8_t *pixelBuffer, void (*onComplete)())
{
std::packaged_task<void()> lambda([=]() mutable
{ Viewer_capture(viewer, tSwapChain, pixelBuffer, onComplete); });
{ Viewer_capture(viewer, view, tSwapChain, pixelBuffer, onComplete); });
auto fut = _rl->add_task(lambda);
}
EMSCRIPTEN_KEEPALIVE void Viewer_captureRenderTargetRenderThread(TViewer *viewer, TSwapChain *tSwapChain, TRenderTarget* tRenderTarget, uint8_t *pixelBuffer, void (*onComplete)())
EMSCRIPTEN_KEEPALIVE void Viewer_captureRenderTargetRenderThread(TViewer *viewer, TView *view, TSwapChain *tSwapChain, TRenderTarget* tRenderTarget, uint8_t *pixelBuffer, void (*onComplete)())
{
std::packaged_task<void()> lambda([=]() mutable
{ Viewer_captureRenderTarget(viewer, tSwapChain, tRenderTarget, pixelBuffer, onComplete); });
{ Viewer_captureRenderTarget(viewer, view, tSwapChain, tRenderTarget, pixelBuffer, onComplete); });
auto fut = _rl->add_task(lambda);
}
@@ -449,20 +450,7 @@ extern "C"
{ set_background_image_position(viewer, x, y, clamp); });
auto fut = _rl->add_task(lambda);
}
EMSCRIPTEN_KEEPALIVE void set_tone_mapping_render_thread(TViewer *viewer,
int toneMapping)
{
std::packaged_task<void()> lambda(
[=]
{ set_tone_mapping(viewer, toneMapping); });
auto fut = _rl->add_task(lambda);
}
EMSCRIPTEN_KEEPALIVE void set_bloom_render_thread(TViewer *viewer, float strength)
{
std::packaged_task<void()> lambda([=]
{ set_bloom(viewer, strength); });
auto fut = _rl->add_task(lambda);
}
EMSCRIPTEN_KEEPALIVE void load_skybox_render_thread(TViewer *viewer,
const char *skyboxPath,
void (*onComplete)())
@@ -530,22 +518,6 @@ extern "C"
auto fut = _rl->add_task(lambda);
}
EMSCRIPTEN_KEEPALIVE void set_camera_render_thread(TViewer *viewer, EntityId asset,
const char *nodeName, void (*callback)(bool))
{
std::packaged_task<bool()> lambda(
[=]
{
auto success = set_camera(viewer, asset, nodeName);
#ifdef __EMSCRIPTEN__
MAIN_THREAD_EM_ASM({ moduleArg.dartFilamentResolveCallback($0, $1); }, callback, success);
#else
callback(success);
#endif
return success;
});
auto fut = _rl->add_task(lambda);
}
EMSCRIPTEN_KEEPALIVE void
get_morph_target_name_render_thread(TSceneManager *sceneManager, EntityId assetEntity,
@@ -637,15 +609,6 @@ extern "C"
auto fut = _rl->add_task(lambda);
}
EMSCRIPTEN_KEEPALIVE void set_post_processing_render_thread(TViewer *viewer,
bool enabled)
{
std::packaged_task<void()> lambda(
[=]
{ set_post_processing(viewer, enabled); });
auto fut = _rl->add_task(lambda);
}
EMSCRIPTEN_KEEPALIVE void
get_name_for_entity_render_thread(TSceneManager *sceneManager, const EntityId entityId, void (*callback)(const char *))
{

View File

@@ -79,10 +79,11 @@ class TestHelper {
outDir.createSync();
}
Future capture(ThermionViewer viewer, String outputFilename) async {
Future capture(ThermionViewer viewer, String outputFilename, { SwapChain? swapChain, RenderTarget? renderTarget}) async {
await Future.delayed(Duration(milliseconds: 10));
var outPath = p.join(outDir.path, "$outputFilename.bmp");
var pixelBuffer = await viewer.capture(swapChain); //, renderTarget: renderTarget);
var pixelBuffer =
await viewer.capture(swapChain ?? this.swapChain, renderTarget: renderTarget);
await savePixelBufferToBmp(
pixelBuffer,
viewer.viewportDimensions.$1.toInt(),
@@ -91,17 +92,21 @@ class TestHelper {
return pixelBuffer;
}
Future<int> createTexture(int width, int height) async {
final packageUri = findPackageRoot('thermion_dart');
final lib = ThermionDartTexture1(DynamicLibrary.open(
'${packageUri.toFilePath()}/native/lib/macos/swift/libthermion_swift.dylib'));
final object = ThermionDartTexture.new1(lib);
object.initWithWidth_height_(width, height);
return object.metalTextureAddress;
}
Future<ThermionViewer> createViewer(
{img.Color? bg,
Vector3? cameraPosition,
viewportDimensions = (width: 500, height: 500)}) async {
final packageUri = findPackageRoot('thermion_dart');
final lib = ThermionDartTexture1(DynamicLibrary.open(
'${packageUri.toFilePath()}/native/lib/macos/swift/libthermion_swift.dylib'));
final object = ThermionDartTexture.new1(lib);
object.initWithWidth_height_(
viewportDimensions.width, viewportDimensions.height);
final texture =
await createTexture(viewportDimensions.width, viewportDimensions.height);
final resourceLoader = calloc<ResourceLoaderWrapper>(1);
var loadToOut = NativeCallable<
@@ -118,11 +123,10 @@ class TestHelper {
await viewer.initialized;
swapChain = await viewer.createSwapChain(
viewportDimensions.width, viewportDimensions.height);
renderTarget = await viewer.createRenderTarget(
viewportDimensions.width,
viewportDimensions.height,
object.metalTextureAddress);
await viewer.setRenderTarget(renderTarget as FFIRenderTarget);
renderTarget = await viewer.createRenderTarget(viewportDimensions.width,
viewportDimensions.height, texture);
// await viewer.setRenderTarget(renderTarget as FFIRenderTarget);
await viewer.updateViewportAndCameraProjection(
viewportDimensions.width.toDouble(),
viewportDimensions.height.toDouble());

View File

@@ -0,0 +1,21 @@
import 'package:test/test.dart';
import 'helpers.dart';
void main() async {
final testHelper = TestHelper("view");
group('view tests', () {
test('create view', () async {
var viewer = await testHelper.createViewer();
final renderTarget = await viewer.createRenderTarget(
200, 400, await testHelper.createTexture(200, 400));
final view = await viewer.createView();
await view.updateViewport(200, 400);
await view.setRenderTarget(renderTarget);
await viewer.setBackgroundColor(1.0, 0.0, 0.0, 1.0);
await testHelper.capture(viewer, "create_view_with_render_target", renderTarget: renderTarget);
await viewer.dispose();
});
});
}

View File

@@ -240,7 +240,7 @@ class ThermionFlutterFFI extends ThermionFlutterPlatform {
if (newTexture.hardwareTextureId != null) {
// ignore: unused_local_variable
var renderTarget = await _viewer!.createRenderTarget(
width.toDouble(), height.toDouble(), newTexture.hardwareTextureId!);
width, height, newTexture.hardwareTextureId!);
}
await _viewer!
.updateViewportAndCameraProjection(width.toDouble(), height.toDouble());