introduce stronger native typing, camera projection/culling methods, update tests

This commit is contained in:
Nick Fisher
2024-09-21 11:36:41 +08:00
parent 60bd7498ea
commit ed5f23faf2
16 changed files with 814 additions and 399 deletions

View File

@@ -24,14 +24,15 @@ Matrix4 double4x4ToMatrix4(double4x4 mat) {
]);
}
double4x4 matrix4ToDouble4x4(Matrix4 mat, double4x4 out) {
double4x4 matrix4ToDouble4x4(Matrix4 mat) {
final out = Struct.create<double4x4>();
for (int i = 0; i < 4; i++) {
out.col1[i] = mat.storage[i];
out.col2[i] = mat.storage[i + 4];
out.col3[i] = mat.storage[i + 8];
out.col4[i] = mat.storage[i + 12];
}
return out;
}
}

View File

@@ -26,16 +26,16 @@ Future<void> withVoidCallback(
nativeCallable.close();
}
Future<int> withVoidPointerCallback(
Function(Pointer<NativeFunction<Void Function(Pointer<Void>)>>)
Future<int> withPointerCallback<T extends NativeType>(
Function(Pointer<NativeFunction<Void Function(Pointer<T>)>>)
func) async {
final completer = Completer<Pointer<Void>>();
final completer = Completer<Pointer<T>>();
// ignore: prefer_function_declarations_over_variables
void Function(Pointer<Void>) callback = (Pointer<Void> ptr) {
completer.complete(ptr);
void Function(Pointer<NativeType>) callback = (Pointer<NativeType> ptr) {
completer.complete(ptr.cast<T>());
};
final nativeCallable =
NativeCallable<Void Function(Pointer<Void>)>.listener(callback);
NativeCallable<Void Function(Pointer<NativeType>)>.listener(callback);
func.call(nativeCallable.nativeFunction);
var ptr = await completer.future;
nativeCallable.close();

View File

@@ -0,0 +1,22 @@
import 'dart:ffi';
import 'package:thermion_dart/thermion_dart/utils/matrix.dart';
import 'package:thermion_dart/thermion_dart/viewer/ffi/thermion_dart.g.dart';
import 'package:thermion_dart/thermion_dart/viewer/shared_types/camera.dart';
import 'package:vector_math/vector_math_64.dart';
class ThermionFFICamera extends Camera {
final Pointer<TCamera> pointer;
ThermionFFICamera(this.pointer);
@override
Future setProjectionMatrixWithCulling(Matrix4 projectionMatrix,
double near, double far) async {
Camera_setCustomProjectionWithCulling(
pointer,
matrix4ToDouble4x4(projectionMatrix),
near,
far);
}
}

View File

@@ -17,129 +17,141 @@ external ffi.Pointer<ffi.Void> make_resource_loader(
);
@ffi.Native<
ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
ffi.Pointer<TViewer> Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Char>)>(isLeaf: true)
external ffi.Pointer<ffi.Void> create_filament_viewer(
external ffi.Pointer<TViewer> create_filament_viewer(
ffi.Pointer<ffi.Void> context,
ffi.Pointer<ffi.Void> loader,
ffi.Pointer<ffi.Void> platform,
ffi.Pointer<ffi.Char> uberArchivePath,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<ffi.Void>)>(isLeaf: true)
@ffi.Native<ffi.Void Function(ffi.Pointer<TViewer>)>(isLeaf: true)
external void destroy_filament_viewer(
ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<TViewer> viewer,
);
@ffi.Native<ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>(isLeaf: true)
@ffi.Native<ffi.Pointer<ffi.Void> Function(ffi.Pointer<TViewer>)>(isLeaf: true)
external ffi.Pointer<ffi.Void> get_scene_manager(
ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<TViewer> viewer,
);
@ffi.Native<ffi.Pointer<TEngine> Function(ffi.Pointer<TViewer>)>(isLeaf: true)
external ffi.Pointer<TEngine> Viewer_getEngine(
ffi.Pointer<TViewer> viewer,
);
@ffi.Native<ffi.Pointer<TCamera> Function(ffi.Pointer<TEngine>, EntityId)>(
isLeaf: true)
external ffi.Pointer<TCamera> Engine_getCameraComponent(
ffi.Pointer<TEngine> tEngine,
int entityId,
);
@ffi.Native<
ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.IntPtr, ffi.Uint32,
ffi.Uint32)>(isLeaf: true)
ffi.Void Function(
ffi.Pointer<TViewer>, ffi.IntPtr, ffi.Uint32, ffi.Uint32)>(isLeaf: true)
external void create_render_target(
ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<TViewer> viewer,
int texture,
int width,
int height,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<ffi.Void>)>(isLeaf: true)
@ffi.Native<ffi.Void Function(ffi.Pointer<TViewer>)>(isLeaf: true)
external void clear_background_image(
ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<TViewer> viewer,
);
@ffi.Native<
ffi.Void Function(
ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Char>, ffi.Bool)>(isLeaf: true)
ffi.Pointer<TViewer>, ffi.Pointer<ffi.Char>, ffi.Bool)>(isLeaf: true)
external void set_background_image(
ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<TViewer> viewer,
ffi.Pointer<ffi.Char> path,
bool fillHeight,
);
@ffi.Native<
ffi.Void Function(
ffi.Pointer<ffi.Void>, ffi.Float, ffi.Float, ffi.Bool)>(isLeaf: true)
ffi.Pointer<TViewer>, ffi.Float, ffi.Float, ffi.Bool)>(isLeaf: true)
external void set_background_image_position(
ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<TViewer> viewer,
double x,
double y,
bool clamp,
);
@ffi.Native<
ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Float, ffi.Float, ffi.Float,
ffi.Void Function(ffi.Pointer<TViewer>, ffi.Float, ffi.Float, ffi.Float,
ffi.Float)>(isLeaf: true)
external void set_background_color(
ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<TViewer> viewer,
double r,
double g,
double b,
double a,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Int)>(isLeaf: true)
@ffi.Native<ffi.Void Function(ffi.Pointer<TViewer>, ffi.Int)>(isLeaf: true)
external void set_tone_mapping(
ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<TViewer> viewer,
int toneMapping,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Float)>(isLeaf: true)
@ffi.Native<ffi.Void Function(ffi.Pointer<TViewer>, ffi.Float)>(isLeaf: true)
external void set_bloom(
ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<TViewer> viewer,
double strength,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Char>)>(
@ffi.Native<ffi.Void Function(ffi.Pointer<TViewer>, ffi.Pointer<ffi.Char>)>(
isLeaf: true)
external void load_skybox(
ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<TViewer> viewer,
ffi.Pointer<ffi.Char> skyboxPath,
);
@ffi.Native<
ffi.Void Function(
ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Char>, ffi.Float)>(isLeaf: true)
ffi.Pointer<TViewer>, ffi.Pointer<ffi.Char>, ffi.Float)>(isLeaf: true)
external void load_ibl(
ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<TViewer> viewer,
ffi.Pointer<ffi.Char> iblPath,
double intensity,
);
@ffi.Native<
ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Float, ffi.Float, ffi.Float,
ffi.Void Function(ffi.Pointer<TViewer>, ffi.Float, ffi.Float, ffi.Float,
ffi.Float)>(isLeaf: true)
external void create_ibl(
ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<TViewer> viewer,
double r,
double g,
double b,
double intensity,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Float>)>(
@ffi.Native<ffi.Void Function(ffi.Pointer<TViewer>, ffi.Pointer<ffi.Float>)>(
isLeaf: true)
external void rotate_ibl(
ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<TViewer> viewer,
ffi.Pointer<ffi.Float> rotationMatrix,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<ffi.Void>)>(isLeaf: true)
@ffi.Native<ffi.Void Function(ffi.Pointer<TViewer>)>(isLeaf: true)
external void remove_skybox(
ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<TViewer> viewer,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<ffi.Void>)>(isLeaf: true)
@ffi.Native<ffi.Void Function(ffi.Pointer<TViewer>)>(isLeaf: true)
external void remove_ibl(
ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<TViewer> viewer,
);
@ffi.Native<
EntityId Function(
ffi.Pointer<ffi.Void>,
ffi.Pointer<TViewer>,
ffi.Uint8,
ffi.Float,
ffi.Float,
@@ -157,7 +169,7 @@ external void remove_ibl(
ffi.Float,
ffi.Bool)>(isLeaf: true)
external int add_light(
ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<TViewer> viewer,
int type,
double colour,
double intensity,
@@ -176,22 +188,22 @@ external int add_light(
bool shadows,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<ffi.Void>, EntityId)>(isLeaf: true)
@ffi.Native<ffi.Void Function(ffi.Pointer<TViewer>, EntityId)>(isLeaf: true)
external void remove_light(
ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<TViewer> viewer,
int entityId,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<ffi.Void>)>(isLeaf: true)
@ffi.Native<ffi.Void Function(ffi.Pointer<TViewer>)>(isLeaf: true)
external void clear_lights(
ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<TViewer> viewer,
);
@ffi.Native<
ffi.Void Function(ffi.Pointer<ffi.Void>, EntityId, ffi.Float, ffi.Float,
ffi.Void Function(ffi.Pointer<TViewer>, EntityId, ffi.Float, ffi.Float,
ffi.Float)>(isLeaf: true)
external void set_light_position(
ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<TViewer> viewer,
int light,
double x,
double y,
@@ -199,10 +211,10 @@ external void set_light_position(
);
@ffi.Native<
ffi.Void Function(ffi.Pointer<ffi.Void>, EntityId, ffi.Float, ffi.Float,
ffi.Void Function(ffi.Pointer<TViewer>, EntityId, ffi.Float, ffi.Float,
ffi.Float)>(isLeaf: true)
external void set_light_direction(
ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<TViewer> viewer,
int light,
double x,
double y,
@@ -262,34 +274,34 @@ external void get_instances(
ffi.Pointer<EntityId> out,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<ffi.Void>)>(isLeaf: true)
@ffi.Native<ffi.Void Function(ffi.Pointer<TViewer>)>(isLeaf: true)
external void set_main_camera(
ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<TViewer> viewer,
);
@ffi.Native<EntityId Function(ffi.Pointer<ffi.Void>)>(isLeaf: true)
@ffi.Native<EntityId Function(ffi.Pointer<TViewer>)>(isLeaf: true)
external int get_main_camera(
ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<TViewer> viewer,
);
@ffi.Native<
ffi.Bool Function(
ffi.Pointer<ffi.Void>, EntityId, ffi.Pointer<ffi.Char>)>(isLeaf: true)
ffi.Pointer<TViewer>, EntityId, ffi.Pointer<ffi.Char>)>(isLeaf: true)
external bool set_camera(
ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<TViewer> viewer,
int entity,
ffi.Pointer<ffi.Char> nodeName,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Bool)>(isLeaf: true)
@ffi.Native<ffi.Void Function(ffi.Pointer<TViewer>, ffi.Bool)>(isLeaf: true)
external void set_view_frustum_culling(
ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<TViewer> viewer,
bool enabled,
);
@ffi.Native<
ffi.Void Function(
ffi.Pointer<ffi.Void>,
ffi.Bool Function(
ffi.Pointer<TViewer>,
ffi.Uint64,
ffi.Pointer<ffi.Void>,
ffi.Pointer<
@@ -297,8 +309,8 @@ external void set_view_frustum_culling(
ffi.Void Function(ffi.Pointer<ffi.Void> buf, ffi.Size size,
ffi.Pointer<ffi.Void> data)>>,
ffi.Pointer<ffi.Void>)>(isLeaf: true)
external void render(
ffi.Pointer<ffi.Void> viewer,
external bool render(
ffi.Pointer<TViewer> viewer,
int frameTimeInNanos,
ffi.Pointer<ffi.Void> pixelBuffer,
ffi.Pointer<
@@ -310,84 +322,84 @@ external void render(
);
@ffi.Native<
ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Uint8>,
ffi.Void Function(ffi.Pointer<TViewer>, ffi.Pointer<ffi.Uint8>,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>)>(isLeaf: true)
external void capture(
ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<TViewer> viewer,
ffi.Pointer<ffi.Uint8> pixelBuffer,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> callback,
);
@ffi.Native<
ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>, ffi.Uint32,
ffi.Void Function(ffi.Pointer<TViewer>, ffi.Pointer<ffi.Void>, ffi.Uint32,
ffi.Uint32)>(isLeaf: true)
external void create_swap_chain(
ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<TViewer> viewer,
ffi.Pointer<ffi.Void> window,
int width,
int height,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<ffi.Void>)>(isLeaf: true)
@ffi.Native<ffi.Void Function(ffi.Pointer<TViewer>)>(isLeaf: true)
external void destroy_swap_chain(
ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<TViewer> viewer,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Float)>(isLeaf: true)
@ffi.Native<ffi.Void Function(ffi.Pointer<TViewer>, ffi.Float)>(isLeaf: true)
external void set_frame_interval(
ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<TViewer> viewer,
double interval,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Uint32, ffi.Uint32)>(
@ffi.Native<ffi.Void Function(ffi.Pointer<TViewer>, ffi.Uint32, ffi.Uint32)>(
isLeaf: true)
external void update_viewport(
ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<TViewer> viewer,
int width,
int height,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<ffi.Void>)>(isLeaf: true)
@ffi.Native<ffi.Void Function(ffi.Pointer<TViewer>)>(isLeaf: true)
external void scroll_begin(
ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<TViewer> viewer,
);
@ffi.Native<
ffi.Void Function(
ffi.Pointer<ffi.Void>, ffi.Float, ffi.Float, ffi.Float)>(isLeaf: true)
ffi.Pointer<TViewer>, ffi.Float, ffi.Float, ffi.Float)>(isLeaf: true)
external void scroll_update(
ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<TViewer> viewer,
double x,
double y,
double z,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<ffi.Void>)>(isLeaf: true)
@ffi.Native<ffi.Void Function(ffi.Pointer<TViewer>)>(isLeaf: true)
external void scroll_end(
ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<TViewer> viewer,
);
@ffi.Native<
ffi.Void Function(
ffi.Pointer<ffi.Void>, ffi.Float, ffi.Float, ffi.Bool)>(isLeaf: true)
ffi.Pointer<TViewer>, ffi.Float, ffi.Float, ffi.Bool)>(isLeaf: true)
external void grab_begin(
ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<TViewer> viewer,
double x,
double y,
bool pan,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Float, ffi.Float)>(
@ffi.Native<ffi.Void Function(ffi.Pointer<TViewer>, ffi.Float, ffi.Float)>(
isLeaf: true)
external void grab_update(
ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<TViewer> viewer,
double x,
double y,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<ffi.Void>)>(isLeaf: true)
@ffi.Native<ffi.Void Function(ffi.Pointer<TViewer>)>(isLeaf: true)
external void grab_end(
ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<TViewer> viewer,
);
@ffi.Native<
@@ -652,15 +664,15 @@ external int get_morph_target_name_count(
int childEntity,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<ffi.Void>, EntityId)>(isLeaf: true)
@ffi.Native<ffi.Void Function(ffi.Pointer<TViewer>, EntityId)>(isLeaf: true)
external void remove_entity(
ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<TViewer> viewer,
int asset,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<ffi.Void>)>(isLeaf: true)
@ffi.Native<ffi.Void Function(ffi.Pointer<TViewer>)>(isLeaf: true)
external void clear_entities(
ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<TViewer> viewer,
);
@ffi.Native<
@@ -780,10 +792,10 @@ external void set_camera_model_matrix(
double4x4 matrix,
);
@ffi.Native<ffi.Pointer<TCamera> Function(ffi.Pointer<ffi.Void>, EntityId)>(
@ffi.Native<ffi.Pointer<TCamera> Function(ffi.Pointer<TViewer>, EntityId)>(
isLeaf: true)
external ffi.Pointer<TCamera> get_camera(
ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<TViewer> viewer,
int entity,
);
@@ -874,10 +886,10 @@ external void set_camera_focus_distance(
);
@ffi.Native<
ffi.Void Function(ffi.Pointer<ffi.Void>, _ManipulatorMode, ffi.Double,
ffi.Void Function(ffi.Pointer<TViewer>, _ManipulatorMode, ffi.Double,
ffi.Double, ffi.Double)>(isLeaf: true)
external void set_camera_manipulator_options(
ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<TViewer> viewer,
int mode,
double orbitSpeedX,
double orbitSpeedY,
@@ -885,16 +897,22 @@ external void set_camera_manipulator_options(
);
@ffi.Native<
ffi.Void Function(ffi.Pointer<TCamera>, double4x4, double4x4, ffi.Double,
ffi.Double)>(isLeaf: true)
ffi.Void Function(
ffi.Pointer<TCamera>, double4x4, ffi.Double, ffi.Double)>(isLeaf: true)
external void Camera_setCustomProjectionWithCulling(
ffi.Pointer<TCamera> camera,
double4x4 projectionMatrix,
double4x4 projectionMatrixForCulling,
double near,
double far,
);
@ffi.Native<ffi.Pointer<TCamera> Function(ffi.Pointer<TEngine>, EntityId)>(
isLeaf: true)
external ffi.Pointer<TCamera> get_camera_component(
ffi.Pointer<TEngine> engine,
int entity,
);
@ffi.Native<
ffi.Int Function(
ffi.Pointer<ffi.Void>, EntityId, ffi.Pointer<ffi.Char>)>(isLeaf: true)
@@ -913,37 +931,37 @@ external int reveal_mesh(
ffi.Pointer<ffi.Char> meshName,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Bool)>(isLeaf: true)
@ffi.Native<ffi.Void Function(ffi.Pointer<TViewer>, ffi.Bool)>(isLeaf: true)
external void set_post_processing(
ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<TViewer> viewer,
bool enabled,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Bool)>(isLeaf: true)
@ffi.Native<ffi.Void Function(ffi.Pointer<TViewer>, ffi.Bool)>(isLeaf: true)
external void set_shadows_enabled(
ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<TViewer> viewer,
bool enabled,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Int)>(isLeaf: true)
@ffi.Native<ffi.Void Function(ffi.Pointer<TViewer>, ffi.Int)>(isLeaf: true)
external void set_shadow_type(
ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<TViewer> viewer,
int shadowType,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Float, ffi.Float)>(
@ffi.Native<ffi.Void Function(ffi.Pointer<TViewer>, ffi.Float, ffi.Float)>(
isLeaf: true)
external void set_soft_shadow_options(
ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<TViewer> viewer,
double penumbraScale,
double penumbraRatioScale,
);
@ffi.Native<
ffi.Void Function(
ffi.Pointer<ffi.Void>, ffi.Bool, ffi.Bool, ffi.Bool)>(isLeaf: true)
ffi.Pointer<TViewer>, ffi.Bool, ffi.Bool, ffi.Bool)>(isLeaf: true)
external void set_antialiasing(
ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<TViewer> viewer,
bool msaa,
bool fxaa,
bool taa,
@@ -951,7 +969,7 @@ external void set_antialiasing(
@ffi.Native<
ffi.Void Function(
ffi.Pointer<ffi.Void>,
ffi.Pointer<TViewer>,
ffi.Int,
ffi.Int,
ffi.Pointer<
@@ -959,7 +977,7 @@ external void set_antialiasing(
ffi.Void Function(
EntityId entityId, ffi.Int x, ffi.Int y)>>)>(isLeaf: true)
external void filament_pick(
ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<TViewer> viewer,
int x,
int y,
ffi.Pointer<
@@ -1012,16 +1030,16 @@ external ffi.Pointer<ffi.Char> get_entity_name_at(
bool renderableOnly,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Bool)>(isLeaf: true)
@ffi.Native<ffi.Void Function(ffi.Pointer<TViewer>, ffi.Bool)>(isLeaf: true)
external void set_recording(
ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<TViewer> viewer,
bool recording,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Char>)>(
@ffi.Native<ffi.Void Function(ffi.Pointer<TViewer>, ffi.Pointer<ffi.Char>)>(
isLeaf: true)
external void set_recording_output_directory(
ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<TViewer> viewer,
ffi.Pointer<ffi.Char> outputDirectory,
);
@@ -1267,7 +1285,7 @@ external void set_material_depth_write(
@ffi.Native<
ffi.Void Function(
ffi.Pointer<ffi.Void>,
ffi.Pointer<TViewer>,
EntityId,
ffi.Pointer<ffi.Uint8>,
ffi.Uint32,
@@ -1276,7 +1294,7 @@ external void set_material_depth_write(
ffi.Uint32,
ffi.Uint32)>(isLeaf: true)
external void unproject_texture(
ffi.Pointer<ffi.Void> sceneManager,
ffi.Pointer<TViewer> viewer,
int entity,
ffi.Pointer<ffi.Uint8> input,
int inputWidth,
@@ -1348,8 +1366,7 @@ external void MaterialInstance_setDepthCulling(
ffi.Pointer<ffi.Void>,
ffi.Pointer<
ffi.NativeFunction<
ffi.Void Function(
ffi.Pointer<ffi.Void> viewer)>>)>(isLeaf: true)
ffi.Void Function(ffi.Pointer<TViewer> viewer)>>)>(isLeaf: true)
external void create_filament_viewer_render_thread(
ffi.Pointer<ffi.Void> context,
ffi.Pointer<ffi.Void> platform,
@@ -1361,19 +1378,19 @@ external void create_filament_viewer_render_thread(
renderCallback,
ffi.Pointer<ffi.Void> renderCallbackOwner,
ffi.Pointer<
ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void> viewer)>>
ffi.NativeFunction<ffi.Void Function(ffi.Pointer<TViewer> viewer)>>
callback,
);
@ffi.Native<
ffi.Void Function(
ffi.Pointer<ffi.Void>,
ffi.Pointer<TViewer>,
ffi.Pointer<ffi.Void>,
ffi.Uint32,
ffi.Uint32,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>)>(isLeaf: true)
external void create_swap_chain_render_thread(
ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<TViewer> viewer,
ffi.Pointer<ffi.Void> surface,
int width,
int height,
@@ -1381,39 +1398,39 @@ external void create_swap_chain_render_thread(
);
@ffi.Native<
ffi.Void Function(ffi.Pointer<ffi.Void>,
ffi.Void Function(ffi.Pointer<TViewer>,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>)>(isLeaf: true)
external void destroy_swap_chain_render_thread(
ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<TViewer> viewer,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> onComplete,
);
@ffi.Native<
ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.IntPtr, ffi.Uint32, ffi.Uint32,
ffi.Void Function(ffi.Pointer<TViewer>, ffi.IntPtr, ffi.Uint32, ffi.Uint32,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>)>(isLeaf: true)
external void create_render_target_render_thread(
ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<TViewer> viewer,
int nativeTextureId,
int width,
int height,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> onComplete,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<ffi.Void>)>(isLeaf: true)
@ffi.Native<ffi.Void Function(ffi.Pointer<TViewer>)>(isLeaf: true)
external void destroy_filament_viewer_render_thread(
ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<TViewer> viewer,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<ffi.Void>)>(isLeaf: true)
@ffi.Native<ffi.Void Function(ffi.Pointer<TViewer>)>(isLeaf: true)
external void render_render_thread(
ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<TViewer> viewer,
);
@ffi.Native<
ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Uint8>,
ffi.Void Function(ffi.Pointer<TViewer>, ffi.Pointer<ffi.Uint8>,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>)>(isLeaf: true)
external void capture_render_thread(
ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<TViewer> viewer,
ffi.Pointer<ffi.Uint8> out,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> onComplete,
);
@@ -1425,46 +1442,46 @@ external FilamentRenderCallback make_render_callback_fn_pointer(
);
@ffi.Native<
ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Bool,
ffi.Void Function(ffi.Pointer<TViewer>, ffi.Bool,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>)>(isLeaf: true)
external void set_rendering_render_thread(
ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<TViewer> viewer,
bool rendering,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> onComplete,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<ffi.Void>)>(isLeaf: true)
@ffi.Native<ffi.Void Function(ffi.Pointer<TViewer>)>(isLeaf: true)
external void request_frame_render_thread(
ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<TViewer> viewer,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Float)>(isLeaf: true)
@ffi.Native<ffi.Void Function(ffi.Pointer<TViewer>, ffi.Float)>(isLeaf: true)
external void set_frame_interval_render_thread(
ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<TViewer> viewer,
double frameInterval,
);
@ffi.Native<
ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Float, ffi.Float, ffi.Float,
ffi.Void Function(ffi.Pointer<TViewer>, ffi.Float, ffi.Float, ffi.Float,
ffi.Float)>(isLeaf: true)
external void set_background_color_render_thread(
ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<TViewer> viewer,
double r,
double g,
double b,
double a,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<ffi.Void>)>(isLeaf: true)
@ffi.Native<ffi.Void Function(ffi.Pointer<TViewer>)>(isLeaf: true)
external void clear_background_image_render_thread(
ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<TViewer> viewer,
);
@ffi.Native<
ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Char>, ffi.Bool,
ffi.Void Function(ffi.Pointer<TViewer>, ffi.Pointer<ffi.Char>, ffi.Bool,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>)>(isLeaf: true)
external void set_background_image_render_thread(
ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<TViewer> viewer,
ffi.Pointer<ffi.Char> path,
bool fillHeight,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> onComplete,
@@ -1472,57 +1489,57 @@ external void set_background_image_render_thread(
@ffi.Native<
ffi.Void Function(
ffi.Pointer<ffi.Void>, ffi.Float, ffi.Float, ffi.Bool)>(isLeaf: true)
ffi.Pointer<TViewer>, ffi.Float, ffi.Float, ffi.Bool)>(isLeaf: true)
external void set_background_image_position_render_thread(
ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<TViewer> viewer,
double x,
double y,
bool clamp,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Int)>(isLeaf: true)
@ffi.Native<ffi.Void Function(ffi.Pointer<TViewer>, ffi.Int)>(isLeaf: true)
external void set_tone_mapping_render_thread(
ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<TViewer> viewer,
int toneMapping,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Float)>(isLeaf: true)
@ffi.Native<ffi.Void Function(ffi.Pointer<TViewer>, ffi.Float)>(isLeaf: true)
external void set_bloom_render_thread(
ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<TViewer> viewer,
double strength,
);
@ffi.Native<
ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Char>,
ffi.Void Function(ffi.Pointer<TViewer>, ffi.Pointer<ffi.Char>,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>)>(isLeaf: true)
external void load_skybox_render_thread(
ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<TViewer> viewer,
ffi.Pointer<ffi.Char> skyboxPath,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> onComplete,
);
@ffi.Native<
ffi.Void Function(
ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Char>, ffi.Float)>(isLeaf: true)
ffi.Pointer<TViewer>, ffi.Pointer<ffi.Char>, ffi.Float)>(isLeaf: true)
external void load_ibl_render_thread(
ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<TViewer> viewer,
ffi.Pointer<ffi.Char> iblPath,
double intensity,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<ffi.Void>)>(isLeaf: true)
@ffi.Native<ffi.Void Function(ffi.Pointer<TViewer>)>(isLeaf: true)
external void remove_skybox_render_thread(
ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<TViewer> viewer,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<ffi.Void>)>(isLeaf: true)
@ffi.Native<ffi.Void Function(ffi.Pointer<TViewer>)>(isLeaf: true)
external void remove_ibl_render_thread(
ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<TViewer> viewer,
);
@ffi.Native<
ffi.Void Function(
ffi.Pointer<ffi.Void>,
ffi.Pointer<TViewer>,
ffi.Uint8,
ffi.Float,
ffi.Float,
@@ -1542,7 +1559,7 @@ external void remove_ibl_render_thread(
ffi.Pointer<ffi.NativeFunction<ffi.Void Function(EntityId)>>)>(
isLeaf: true)
external void add_light_render_thread(
ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<TViewer> viewer,
int type,
double colour,
double intensity,
@@ -1562,15 +1579,15 @@ external void add_light_render_thread(
ffi.Pointer<ffi.NativeFunction<ffi.Void Function(EntityId)>> callback,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<ffi.Void>, EntityId)>(isLeaf: true)
@ffi.Native<ffi.Void Function(ffi.Pointer<TViewer>, EntityId)>(isLeaf: true)
external void remove_light_render_thread(
ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<TViewer> viewer,
int entityId,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<ffi.Void>)>(isLeaf: true)
@ffi.Native<ffi.Void Function(ffi.Pointer<TViewer>)>(isLeaf: true)
external void clear_lights_render_thread(
ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<TViewer> viewer,
);
@ffi.Native<
@@ -1638,31 +1655,28 @@ external void create_instance_render_thread(
);
@ffi.Native<
ffi.Void Function(ffi.Pointer<ffi.Void>, EntityId,
ffi.Void Function(ffi.Pointer<TViewer>, EntityId,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>)>(isLeaf: true)
external void remove_entity_render_thread(
ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<TViewer> viewer,
int asset,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> callback,
);
@ffi.Native<
ffi.Void Function(ffi.Pointer<ffi.Void>,
ffi.Void Function(ffi.Pointer<TViewer>,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>)>(isLeaf: true)
external void clear_entities_render_thread(
ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<TViewer> viewer,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> callback,
);
@ffi.Native<
ffi.Void Function(
ffi.Pointer<ffi.Void>,
EntityId,
ffi.Pointer<ffi.Char>,
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<ffi.Void> viewer,
ffi.Pointer<TViewer> viewer,
int asset,
ffi.Pointer<ffi.Char> nodeName,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Bool)>> callback,
@@ -1794,9 +1808,9 @@ external void set_bone_transform_render_thread(
ffi.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Bool)>> callback,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Bool)>(isLeaf: true)
@ffi.Native<ffi.Void Function(ffi.Pointer<TViewer>, ffi.Bool)>(isLeaf: true)
external void set_post_processing_render_thread(
ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<TViewer> viewer,
bool enabled,
);
@@ -1843,7 +1857,7 @@ external void create_geometry_render_thread(
@ffi.Native<
ffi.Void Function(
ffi.Pointer<ffi.Void>,
ffi.Pointer<TViewer>,
EntityId,
ffi.Pointer<ffi.Uint8>,
ffi.Uint32,
@@ -1853,7 +1867,7 @@ external void create_geometry_render_thread(
ffi.Uint32,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>)>(isLeaf: true)
external void unproject_texture_render_thread(
ffi.Pointer<ffi.Void> sceneManager,
ffi.Pointer<TViewer> viewer,
int entity,
ffi.Pointer<ffi.Uint8> input,
int inputWidth,
@@ -1868,6 +1882,10 @@ final class TCamera extends ffi.Opaque {}
final class TMaterialInstance extends ffi.Opaque {}
final class TEngine extends ffi.Opaque {}
final class TViewer extends ffi.Opaque {}
final class TMaterialKey extends ffi.Struct {
@ffi.Bool()
external bool doubleSided;

View File

@@ -1,5 +1,4 @@
import 'dart:async';
import 'dart:ffi';
import 'dart:math';
import 'dart:typed_data';
import 'package:animation_tools_dart/animation_tools_dart.dart';
@@ -8,6 +7,8 @@ import 'package:thermion_dart/thermion_dart/entities/gizmo.dart';
import 'package:thermion_dart/thermion_dart/utils/matrix.dart';
import 'package:thermion_dart/thermion_dart/viewer/events.dart';
import 'package:thermion_dart/thermion_dart/viewer/ffi/callbacks.dart';
import 'package:thermion_dart/thermion_dart/viewer/ffi/camera_ffi.dart';
import 'package:thermion_dart/thermion_dart/viewer/shared_types/camera.dart';
import 'package:vector_math/vector_math_64.dart';
import 'package:vector_math/vector_math_64.dart' as v64;
import '../thermion_viewer_base.dart';
@@ -25,7 +26,7 @@ class ThermionViewerFFI extends ThermionViewer {
Pointer<Void>? _sceneManager;
Pointer<Void>? _viewer;
Pointer<TViewer>? _viewer;
final String? uberArchivePath;
@@ -102,7 +103,7 @@ class ThermionViewerFFI extends ThermionViewer {
Future updateViewportAndCameraProjection(double width, double height) async {
viewportDimensions = (width * pixelRatio, height * pixelRatio);
update_viewport(_viewer!, width.toInt(), height.toInt());
var mainCamera = get_camera(_viewer!, await getMainCamera());
var mainCamera = await getMainCamera() as ThermionFFICamera;
var near = await getCameraCullingNear();
if (near.abs() < 0.000001) {
near = kNear;
@@ -113,11 +114,12 @@ class ThermionViewerFFI extends ThermionViewer {
}
var aspect = viewportDimensions.$1 / viewportDimensions.$2;
var focalLength = get_camera_focal_length(mainCamera);
var focalLength = get_camera_focal_length(mainCamera.pointer);
if (focalLength.abs() < 0.1) {
focalLength = kFocalLength;
}
set_camera_lens_projection(mainCamera, near, far, aspect, focalLength);
set_camera_lens_projection(
mainCamera.pointer, near, far, aspect, focalLength);
}
Future createSwapChain(double width, double height,
@@ -141,8 +143,8 @@ class ThermionViewerFFI extends ThermionViewer {
final uberarchivePtr =
uberArchivePath?.toNativeUtf8(allocator: allocator).cast<Char>() ??
nullptr;
var viewer = await withVoidPointerCallback(
(Pointer<NativeFunction<Void Function(Pointer<Void>)>> callback) {
var viewer = await withPointerCallback(
(Pointer<NativeFunction<Void Function(Pointer<TViewer>)>> callback) {
create_filament_viewer_render_thread(
_sharedContext,
_driver,
@@ -1144,8 +1146,25 @@ class ThermionViewerFFI extends ThermionViewer {
set_main_camera(_viewer!);
}
Future<ThermionEntity> getMainCamera() {
return Future.value(get_main_camera(_viewer!));
///
///
///
Future<ThermionEntity> getMainCameraEntity() async {
return get_main_camera(_viewer!);
}
///
///
///
Future<Camera> getMainCamera() async {
var camera = await getCameraComponent(await getMainCameraEntity());
return camera!;
}
Future<Camera?> getCameraComponent(ThermionEntity cameraEntity) async {
var engine = Viewer_getEngine(_viewer!);
var camera = Engine_getCameraComponent(engine, cameraEntity);
return ThermionFFICamera(camera);
}
///
@@ -1229,8 +1248,8 @@ class ThermionViewerFFI extends ThermionViewer {
///
///
Future<double> getCameraFov(bool horizontal) async {
var mainCamera = get_camera(_viewer!, await getMainCamera());
return get_camera_fov(mainCamera, horizontal);
var mainCamera = await getMainCamera() as ThermionFFICamera;
return get_camera_fov(mainCamera.pointer, horizontal);
}
///
@@ -1258,8 +1277,8 @@ class ThermionViewerFFI extends ThermionViewer {
}
Future<double> getCameraNear() async {
var mainCamera = get_camera(_viewer!, await getMainCamera());
return get_camera_near(mainCamera);
var mainCamera = await getMainCamera() as ThermionFFICamera;
return get_camera_near(mainCamera.pointer);
}
///
@@ -1267,8 +1286,8 @@ class ThermionViewerFFI extends ThermionViewer {
///
@override
Future<double> getCameraCullingFar() async {
var mainCamera = get_camera(_viewer!, await getMainCamera());
return get_camera_culling_far(mainCamera);
var mainCamera = await getMainCamera() as ThermionFFICamera;
return get_camera_culling_far(mainCamera.pointer);
}
///
@@ -1276,8 +1295,8 @@ class ThermionViewerFFI extends ThermionViewer {
///
@override
Future setCameraFocusDistance(double focusDistance) async {
var mainCamera = get_camera(_viewer!, await getMainCamera());
set_camera_focus_distance(mainCamera, focusDistance);
var mainCamera = await getMainCamera() as ThermionFFICamera;
set_camera_focus_distance(mainCamera.pointer, focusDistance);
}
///
@@ -1312,8 +1331,8 @@ class ThermionViewerFFI extends ThermionViewer {
@override
Future setCameraExposure(
double aperture, double shutterSpeed, double sensitivity) async {
var mainCamera = get_camera(_viewer!, await getMainCamera());
set_camera_exposure(mainCamera, aperture, shutterSpeed, sensitivity);
var mainCamera = await getMainCamera() as ThermionFFICamera;
set_camera_exposure(mainCamera.pointer, aperture, shutterSpeed, sensitivity);
}
///
@@ -1341,10 +1360,9 @@ class ThermionViewerFFI extends ThermionViewer {
///
@override
Future setCameraModelMatrix4(Matrix4 modelMatrix) async {
var mainCamera = get_camera(_viewer!, await getMainCamera());
final out = Struct.create<double4x4>();
matrix4ToDouble4x4(modelMatrix, out);
set_camera_model_matrix(mainCamera, out);
var mainCamera = await getMainCamera() as ThermionFFICamera;
final out = matrix4ToDouble4x4(modelMatrix);
set_camera_model_matrix(mainCamera.pointer, out);
}
///
@@ -1576,8 +1594,8 @@ class ThermionViewerFFI extends ThermionViewer {
if (_viewer == null) {
throw Exception("No viewer available");
}
var mainCamera = get_camera(_viewer!, await getMainCamera());
var matrixStruct = get_camera_view_matrix(mainCamera);
var mainCamera = await getMainCamera() as ThermionFFICamera;
var matrixStruct = get_camera_view_matrix(mainCamera.pointer);
return double4x4ToMatrix4(matrixStruct);
}
@@ -1589,8 +1607,8 @@ class ThermionViewerFFI extends ThermionViewer {
if (_viewer == null) {
throw Exception("No viewer available");
}
var mainCamera = get_camera(_viewer!, await getMainCamera());
var matrixStruct = get_camera_model_matrix(mainCamera);
var mainCamera = await getMainCamera() as ThermionFFICamera;
var matrixStruct = get_camera_model_matrix(mainCamera.pointer);
return double4x4ToMatrix4(matrixStruct);
}
@@ -1602,8 +1620,8 @@ class ThermionViewerFFI extends ThermionViewer {
if (_viewer == null) {
throw Exception("No viewer available");
}
var mainCamera = get_camera(_viewer!, await getMainCamera());
var matrixStruct = get_camera_projection_matrix(mainCamera);
var mainCamera = await getMainCamera() as ThermionFFICamera;
var matrixStruct = get_camera_projection_matrix(mainCamera.pointer);
return double4x4ToMatrix4(matrixStruct);
}
@@ -1615,8 +1633,8 @@ class ThermionViewerFFI extends ThermionViewer {
if (_viewer == null) {
throw Exception("No viewer available");
}
var mainCamera = get_camera(_viewer!, await getMainCamera());
var matrixStruct = get_camera_culling_projection_matrix(mainCamera);
var mainCamera = await getMainCamera() as ThermionFFICamera;
var matrixStruct = get_camera_culling_projection_matrix(mainCamera.pointer);
return double4x4ToMatrix4(matrixStruct);
}
@@ -1675,8 +1693,8 @@ class ThermionViewerFFI extends ThermionViewer {
if (_viewer == null) {
throw Exception("No viewer available");
}
var mainCamera = get_camera(_viewer!, await getMainCamera());
var arrayPtr = get_camera_frustum(mainCamera);
var mainCamera = await getMainCamera() as ThermionFFICamera;
var arrayPtr = get_camera_frustum(mainCamera.pointer);
var doubleList = arrayPtr.asTypedList(24);
var frustum = Frustum();

View File

@@ -1,6 +1,8 @@
// abstract class Camera {
// Future setProjectionMatrixWithCulling(Matrix4 projectionMatrix, Matrix4 projectionMatrixForCUlling);
// Future setDepthCullingEnabled(bool enabled);
// }
import 'package:vector_math/vector_math_64.dart';
abstract class Camera {
Future setProjectionMatrixWithCulling(Matrix4 projectionMatrix, double near, double far);
}
enum AlphaMode { OPAQUE, MASK, BLEND }

View File

@@ -1,4 +1,5 @@
import 'package:thermion_dart/thermion_dart/viewer/events.dart';
import 'package:thermion_dart/thermion_dart/viewer/shared_types/camera.dart';
import 'shared_types/shared_types.dart';
export 'shared_types/shared_types.dart';
@@ -444,9 +445,14 @@ abstract class ThermionViewer {
Future setMainCamera();
///
/// Returns the entity associated with the main camera.
/// Returns the entity associated with the main camera. You probably never need this; use getMainCamera instead.
///
Future<ThermionEntity> getMainCamera();
Future<ThermionEntity> getMainCameraEntity();
///
/// Returns the entity associated with the main camera. You probably never need this; use getMainCamera instead.
///
Future<Camera> getMainCamera();
///
/// Sets the horizontal field of view (if [horizontal] is true) or vertical field of view for the currently active camera to [degrees].
@@ -498,7 +504,10 @@ abstract class ThermionViewer {
///
///
///
Future setCameraLensProjection({double near = kNear, double far = kFar, double? aspect,
Future setCameraLensProjection(
{double near = kNear,
double far = kFar,
double? aspect,
double focalLength = kFocalLength});
///

View File

@@ -4,6 +4,7 @@ import 'dart:typed_data';
import 'package:thermion_dart/thermion_dart/entities/abstract_gizmo.dart';
import 'package:thermion_dart/thermion_dart/thermion_viewer.dart';
import 'package:thermion_dart/thermion_dart/viewer/events.dart';
import 'package:thermion_dart/thermion_dart/viewer/shared_types/camera.dart';
import 'package:thermion_dart/thermion_dart/viewer/thermion_viewer_base.dart';
import 'package:vector_math/vector_math_64.dart';
import 'dart:async';
@@ -214,12 +215,6 @@ class ThermionViewerStub extends ThermionViewer {
throw UnimplementedError();
}
@override
Future<ThermionEntity> getMainCamera() {
// TODO: implement getMainCamera
throw UnimplementedError();
}
@override
Future<List<String>> getMorphTargetNames(
ThermionEntity entity, ThermionEntity childEntity) {
@@ -958,6 +953,18 @@ class ThermionViewerStub extends ThermionViewer {
// TODO: implement setCameraLensProjection
throw UnimplementedError();
}
@override
Future<ThermionEntity> getMainCameraEntity() {
// TODO: implement getMainCameraEntity
throw UnimplementedError();
}
@override
Future<Camera> getMainCamera() {
// TODO: implement getMainCamera
throw UnimplementedError();
}
}

View File

@@ -11,6 +11,8 @@ extern "C"
typedef int32_t _ManipulatorMode;
typedef struct TCamera TCamera;
typedef struct TMaterialInstance TMaterialInstance;
typedef struct TEngine TEngine;
typedef struct TViewer TViewer;
struct TMaterialKey {
bool doubleSided = 1;

View File

@@ -112,6 +112,9 @@ namespace thermion_filament
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));
Engine* getEngine() {
return _engine;
}
EntityId addLight(
LightManager::Type t,

View File

@@ -54,24 +54,29 @@ extern "C"
{
#endif
EMSCRIPTEN_KEEPALIVE const void *create_filament_viewer(const void *const context, const void *const loader, void *const platform, const char *uberArchivePath);
EMSCRIPTEN_KEEPALIVE void destroy_filament_viewer(const void *const viewer);
EMSCRIPTEN_KEEPALIVE void *get_scene_manager(const void *const viewer);
EMSCRIPTEN_KEEPALIVE void create_render_target(const void *const viewer, intptr_t texture, uint32_t width, uint32_t height);
EMSCRIPTEN_KEEPALIVE void clear_background_image(const void *const viewer);
EMSCRIPTEN_KEEPALIVE void set_background_image(const void *const viewer, const char *path, bool fillHeight);
EMSCRIPTEN_KEEPALIVE void set_background_image_position(const void *const viewer, float x, float y, bool clamp);
EMSCRIPTEN_KEEPALIVE void set_background_color(const void *const viewer, const float r, const float g, const float b, const float a);
EMSCRIPTEN_KEEPALIVE void set_tone_mapping(const void *const viewer, int toneMapping);
EMSCRIPTEN_KEEPALIVE void set_bloom(const void *const viewer, float strength);
EMSCRIPTEN_KEEPALIVE void load_skybox(const void *const viewer, const char *skyboxPath);
EMSCRIPTEN_KEEPALIVE void load_ibl(const void *const viewer, const char *iblPath, float intensity);
EMSCRIPTEN_KEEPALIVE void create_ibl(const void *const viewer, float r, float g, float b, float intensity);
EMSCRIPTEN_KEEPALIVE void rotate_ibl(const void *const viewer, float *rotationMatrix);
EMSCRIPTEN_KEEPALIVE void remove_skybox(const void *const viewer);
EMSCRIPTEN_KEEPALIVE void remove_ibl(const void *const viewer);
EMSCRIPTEN_KEEPALIVE TViewer *create_filament_viewer(const void *const context, const void *const loader, void *const platform, const char *uberArchivePath);
EMSCRIPTEN_KEEPALIVE void destroy_filament_viewer(TViewer *viewer);
EMSCRIPTEN_KEEPALIVE void *get_scene_manager(TViewer *viewer);
// Engine
EMSCRIPTEN_KEEPALIVE TEngine *Viewer_getEngine(TViewer* viewer);
EMSCRIPTEN_KEEPALIVE TCamera *Engine_getCameraComponent(TEngine* tEngine, EntityId entityId);
EMSCRIPTEN_KEEPALIVE void create_render_target(TViewer *viewer, intptr_t texture, uint32_t width, uint32_t height);
EMSCRIPTEN_KEEPALIVE void clear_background_image(TViewer *viewer);
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);
EMSCRIPTEN_KEEPALIVE void create_ibl(TViewer *viewer, float r, float g, float b, float intensity);
EMSCRIPTEN_KEEPALIVE void rotate_ibl(TViewer *viewer, float *rotationMatrix);
EMSCRIPTEN_KEEPALIVE void remove_skybox(TViewer *viewer);
EMSCRIPTEN_KEEPALIVE void remove_ibl(TViewer *viewer);
EMSCRIPTEN_KEEPALIVE EntityId add_light(
const void *const viewer,
TViewer *viewer,
uint8_t type,
float colour,
float intensity,
@@ -88,40 +93,40 @@ extern "C"
float sunHaloSize,
float sunHaloFallof,
bool shadows);
EMSCRIPTEN_KEEPALIVE void remove_light(const void *const viewer, EntityId entityId);
EMSCRIPTEN_KEEPALIVE void clear_lights(const void *const viewer);
EMSCRIPTEN_KEEPALIVE void set_light_position(const void *const viewer, EntityId light, float x, float y, float z);
EMSCRIPTEN_KEEPALIVE void set_light_direction(const void *const viewer, EntityId light, float x, float y, float z);
EMSCRIPTEN_KEEPALIVE void remove_light(TViewer *viewer, EntityId entityId);
EMSCRIPTEN_KEEPALIVE void clear_lights(TViewer *viewer);
EMSCRIPTEN_KEEPALIVE void set_light_position(TViewer *viewer, EntityId light, float x, float y, float z);
EMSCRIPTEN_KEEPALIVE void set_light_direction(TViewer *viewer, EntityId light, float x, float y, float z);
EMSCRIPTEN_KEEPALIVE EntityId load_glb(void *sceneManager, const char *assetPath, int numInstances, bool keepData);
EMSCRIPTEN_KEEPALIVE EntityId load_glb_from_buffer(void *sceneManager, const void *const data, size_t length, bool keepData, int priority, int layer);
EMSCRIPTEN_KEEPALIVE EntityId load_gltf(void *sceneManager, const char *assetPath, const char *relativePath, bool keepData);
EMSCRIPTEN_KEEPALIVE EntityId create_instance(void *sceneManager, EntityId id);
EMSCRIPTEN_KEEPALIVE int get_instance_count(void *sceneManager, EntityId entityId);
EMSCRIPTEN_KEEPALIVE void get_instances(void *sceneManager, EntityId entityId, EntityId *out);
EMSCRIPTEN_KEEPALIVE void set_main_camera(const void *const viewer);
EMSCRIPTEN_KEEPALIVE EntityId get_main_camera(const void *const viewer);
EMSCRIPTEN_KEEPALIVE bool set_camera(const void *const viewer, EntityId entity, const char *nodeName);
EMSCRIPTEN_KEEPALIVE void set_view_frustum_culling(const void *const viewer, bool enabled);
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 bool render(
const void *const viewer,
TViewer *viewer,
uint64_t frameTimeInNanos,
void *pixelBuffer,
void (*callback)(void *buf, size_t size, void *data),
void *data);
EMSCRIPTEN_KEEPALIVE void capture(
const void *const viewer,
TViewer *viewer,
uint8_t *pixelBuffer,
void (*callback)(void));
EMSCRIPTEN_KEEPALIVE void create_swap_chain(const void *const viewer, const void *const window, uint32_t width, uint32_t height);
EMSCRIPTEN_KEEPALIVE void destroy_swap_chain(const void *const viewer);
EMSCRIPTEN_KEEPALIVE void set_frame_interval(const void *const viewer, float interval);
EMSCRIPTEN_KEEPALIVE void update_viewport(const void *const viewer, uint32_t width, uint32_t height);
EMSCRIPTEN_KEEPALIVE void scroll_begin(const void *const viewer);
EMSCRIPTEN_KEEPALIVE void scroll_update(const void *const viewer, float x, float y, float z);
EMSCRIPTEN_KEEPALIVE void scroll_end(const void *const viewer);
EMSCRIPTEN_KEEPALIVE void grab_begin(const void *const viewer, float x, float y, bool pan);
EMSCRIPTEN_KEEPALIVE void grab_update(const void *const viewer, float x, float y);
EMSCRIPTEN_KEEPALIVE void grab_end(const void *const viewer);
EMSCRIPTEN_KEEPALIVE void create_swap_chain(TViewer *viewer, const void *const window, uint32_t width, uint32_t height);
EMSCRIPTEN_KEEPALIVE void destroy_swap_chain(TViewer *viewer);
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(
void *sceneManager,
EntityId entity,
@@ -194,8 +199,8 @@ extern "C"
EMSCRIPTEN_KEEPALIVE bool update_bone_matrices(void *sceneManager, EntityId entityId);
EMSCRIPTEN_KEEPALIVE void get_morph_target_name(void *sceneManager, EntityId assetEntity, EntityId childEntity, char *const outPtr, int index);
EMSCRIPTEN_KEEPALIVE int get_morph_target_name_count(void *sceneManager, EntityId assetEntity, EntityId childEntity);
EMSCRIPTEN_KEEPALIVE void remove_entity(const void *const viewer, EntityId asset);
EMSCRIPTEN_KEEPALIVE void clear_entities(const void *const viewer);
EMSCRIPTEN_KEEPALIVE void remove_entity(TViewer *viewer, EntityId asset);
EMSCRIPTEN_KEEPALIVE void clear_entities(TViewer *viewer);
EMSCRIPTEN_KEEPALIVE bool set_material_color(void *sceneManager, EntityId entity, const char *meshName, int materialIndex, const float r, const float g, const float b, const float a);
EMSCRIPTEN_KEEPALIVE void transform_to_unit_cube(void *sceneManager, EntityId asset);
EMSCRIPTEN_KEEPALIVE void queue_position_update(void *sceneManager, EntityId entity, float x, float y, float z, bool relative);
@@ -207,10 +212,10 @@ extern "C"
EMSCRIPTEN_KEEPALIVE void set_scale(void *sceneManager, EntityId entity, float scale);
// Camera methods
EMSCRIPTEN_KEEPALIVE void set_view_frustum_culling(const void *const viewer, bool enabled);
EMSCRIPTEN_KEEPALIVE void set_view_frustum_culling(TViewer *viewer, bool enabled);
EMSCRIPTEN_KEEPALIVE void set_camera_exposure(TCamera *camera, float aperture, float shutterSpeed, float sensitivity);
EMSCRIPTEN_KEEPALIVE void set_camera_model_matrix(TCamera *camera, double4x4 matrix);
EMSCRIPTEN_KEEPALIVE TCamera *get_camera(const void *const viewer, EntityId entity);
EMSCRIPTEN_KEEPALIVE TCamera *get_camera(TViewer *viewer, EntityId entity);
EMSCRIPTEN_KEEPALIVE double get_camera_focal_length(TCamera *const camera);
EMSCRIPTEN_KEEPALIVE double4x4 get_camera_model_matrix(TCamera *const camera);
EMSCRIPTEN_KEEPALIVE double4x4 get_camera_view_matrix(TCamera *const camera);
@@ -224,25 +229,27 @@ extern "C"
EMSCRIPTEN_KEEPALIVE float get_camera_fov(TCamera *camera, bool horizontal);
EMSCRIPTEN_KEEPALIVE void set_camera_lens_projection(TCamera *camera, double near, double far, double aspect, double focalLength);
EMSCRIPTEN_KEEPALIVE void set_camera_focus_distance(TCamera *camera, float focusDistance);
EMSCRIPTEN_KEEPALIVE void set_camera_manipulator_options(const void *const viewer, _ManipulatorMode mode, double orbitSpeedX, double orbitSpeedY, double zoomSpeed);
EMSCRIPTEN_KEEPALIVE void Camera_setCustomProjectionWithCulling(TCamera* camera, double4x4 projectionMatrix, double4x4 projectionMatrixForCulling, double near, double far);
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 TCamera *get_camera_component(TEngine *engine, EntityId entity);
EMSCRIPTEN_KEEPALIVE int hide_mesh(void *sceneManager, EntityId entity, const char *meshName);
EMSCRIPTEN_KEEPALIVE int reveal_mesh(void *sceneManager, EntityId entity, const char *meshName);
EMSCRIPTEN_KEEPALIVE void set_post_processing(void *const viewer, bool enabled);
EMSCRIPTEN_KEEPALIVE void set_shadows_enabled(void *const viewer, bool enabled);
EMSCRIPTEN_KEEPALIVE void set_shadow_type(void *const viewer, int shadowType);
EMSCRIPTEN_KEEPALIVE void set_soft_shadow_options(void *const viewer, float penumbraScale, float penumbraRatioScale);
EMSCRIPTEN_KEEPALIVE void set_antialiasing(void *const viewer, bool msaa, bool fxaa, bool taa);
EMSCRIPTEN_KEEPALIVE void filament_pick(void *const viewer, int x, int y, void (*callback)(EntityId entityId, int x, int y));
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 const char *get_name_for_entity(void *const sceneManager, const EntityId entityId);
EMSCRIPTEN_KEEPALIVE EntityId find_child_entity_by_name(void *const sceneManager, const EntityId parent, const char *name);
EMSCRIPTEN_KEEPALIVE int get_entity_count(void *const sceneManager, const EntityId target, bool renderableOnly);
EMSCRIPTEN_KEEPALIVE void get_entities(void *const sceneManager, const EntityId target, bool renderableOnly, EntityId *out);
EMSCRIPTEN_KEEPALIVE const char *get_entity_name_at(void *const sceneManager, const EntityId target, int index, bool renderableOnly);
EMSCRIPTEN_KEEPALIVE void set_recording(void *const viewer, bool recording);
EMSCRIPTEN_KEEPALIVE void set_recording_output_directory(void *const viewer, const char *outputDirectory);
EMSCRIPTEN_KEEPALIVE void set_recording(TViewer *viewer, bool recording);
EMSCRIPTEN_KEEPALIVE void set_recording_output_directory(TViewer *viewer, const char *outputDirectory);
EMSCRIPTEN_KEEPALIVE void ios_dummy();
EMSCRIPTEN_KEEPALIVE void thermion_flutter_free(void *ptr);
EMSCRIPTEN_KEEPALIVE void add_collision_component(void *const sceneManager, EntityId entityId, void (*callback)(const EntityId entityId1, const EntityId entityId2), bool affectsCollidingTransform);
@@ -281,7 +288,7 @@ extern "C"
EMSCRIPTEN_KEEPALIVE void set_material_property_int(void *const sceneManager, EntityId entity, int materialIndex, const char *property, int value);
EMSCRIPTEN_KEEPALIVE void set_material_property_float4(void *const sceneManager, EntityId entity, int materialIndex, const char *property, double4 value);
EMSCRIPTEN_KEEPALIVE void set_material_depth_write(void *const sceneManager, EntityId entity, int materialIndex, bool enabled);
EMSCRIPTEN_KEEPALIVE void unproject_texture(void *const sceneManager, 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);
EMSCRIPTEN_KEEPALIVE void *const create_texture(void *const sceneManager, uint8_t *data, size_t length);
EMSCRIPTEN_KEEPALIVE void destroy_texture(void *const sceneManager, void *const texture);
EMSCRIPTEN_KEEPALIVE void apply_texture_to_material(void *const sceneManager, EntityId entity, void *const texture, const char *parameterName, int materialIndex);

View File

@@ -24,29 +24,29 @@ extern "C"
const void *const loader,
void (*renderCallback)(void *const renderCallbackOwner),
void *const renderCallbackOwner,
void (*callback)(void *const viewer));
EMSCRIPTEN_KEEPALIVE void create_swap_chain_render_thread(void *const viewer, void *const surface, uint32_t width, uint32_t height, void (*onComplete)());
EMSCRIPTEN_KEEPALIVE void destroy_swap_chain_render_thread(void *const viewer, void (*onComplete)());
EMSCRIPTEN_KEEPALIVE void create_render_target_render_thread(void *const viewer, intptr_t nativeTextureId, uint32_t width, uint32_t height, void (*onComplete)());
EMSCRIPTEN_KEEPALIVE void destroy_filament_viewer_render_thread(void *const viewer);
EMSCRIPTEN_KEEPALIVE void render_render_thread(void *const viewer);
EMSCRIPTEN_KEEPALIVE void capture_render_thread(void *const viewer, uint8_t* out, void (*onComplete)());
void (*callback)(TViewer *viewer));
EMSCRIPTEN_KEEPALIVE void create_swap_chain_render_thread(TViewer *viewer, void *const surface, uint32_t width, uint32_t height, void (*onComplete)());
EMSCRIPTEN_KEEPALIVE void destroy_swap_chain_render_thread(TViewer *viewer, void (*onComplete)());
EMSCRIPTEN_KEEPALIVE void create_render_target_render_thread(TViewer *viewer, intptr_t nativeTextureId, uint32_t width, uint32_t height, void (*onComplete)());
EMSCRIPTEN_KEEPALIVE void destroy_filament_viewer_render_thread(TViewer *viewer);
EMSCRIPTEN_KEEPALIVE void render_render_thread(TViewer *viewer);
EMSCRIPTEN_KEEPALIVE void capture_render_thread(TViewer *viewer, uint8_t* out, void (*onComplete)());
EMSCRIPTEN_KEEPALIVE FilamentRenderCallback make_render_callback_fn_pointer(FilamentRenderCallback);
EMSCRIPTEN_KEEPALIVE void set_rendering_render_thread(void *const viewer, bool rendering, void(*onComplete)());
EMSCRIPTEN_KEEPALIVE void request_frame_render_thread(void *const viewer);
EMSCRIPTEN_KEEPALIVE void set_frame_interval_render_thread(void *const viewer, float frameInterval);
EMSCRIPTEN_KEEPALIVE void set_background_color_render_thread(void *const viewer, const float r, const float g, const float b, const float a);
EMSCRIPTEN_KEEPALIVE void clear_background_image_render_thread(void *const viewer);
EMSCRIPTEN_KEEPALIVE void set_background_image_render_thread(void *const viewer, const char *path, bool fillHeight, void (*onComplete)());
EMSCRIPTEN_KEEPALIVE void set_background_image_position_render_thread(void *const viewer, float x, float y, bool clamp);
EMSCRIPTEN_KEEPALIVE void set_tone_mapping_render_thread(void *const viewer, int toneMapping);
EMSCRIPTEN_KEEPALIVE void set_bloom_render_thread(void *const viewer, float strength);
EMSCRIPTEN_KEEPALIVE void load_skybox_render_thread(void *const viewer, const char *skyboxPath, void (*onComplete)());
EMSCRIPTEN_KEEPALIVE void load_ibl_render_thread(void *const viewer, const char *iblPath, float intensity);
EMSCRIPTEN_KEEPALIVE void remove_skybox_render_thread(void *const viewer);
EMSCRIPTEN_KEEPALIVE void remove_ibl_render_thread(void *const viewer);
EMSCRIPTEN_KEEPALIVE void set_rendering_render_thread(TViewer *viewer, bool rendering, void(*onComplete)());
EMSCRIPTEN_KEEPALIVE void request_frame_render_thread(TViewer *viewer);
EMSCRIPTEN_KEEPALIVE void set_frame_interval_render_thread(TViewer *viewer, float frameInterval);
EMSCRIPTEN_KEEPALIVE void set_background_color_render_thread(TViewer *viewer, const float r, const float g, const float b, const float a);
EMSCRIPTEN_KEEPALIVE void clear_background_image_render_thread(TViewer *viewer);
EMSCRIPTEN_KEEPALIVE void set_background_image_render_thread(TViewer *viewer, const char *path, bool fillHeight, void (*onComplete)());
EMSCRIPTEN_KEEPALIVE void set_background_image_position_render_thread(TViewer *viewer, float x, float y, bool clamp);
EMSCRIPTEN_KEEPALIVE void set_tone_mapping_render_thread(TViewer *viewer, int toneMapping);
EMSCRIPTEN_KEEPALIVE void set_bloom_render_thread(TViewer *viewer, float strength);
EMSCRIPTEN_KEEPALIVE void load_skybox_render_thread(TViewer *viewer, const char *skyboxPath, void (*onComplete)());
EMSCRIPTEN_KEEPALIVE void load_ibl_render_thread(TViewer *viewer, const char *iblPath, float intensity);
EMSCRIPTEN_KEEPALIVE void remove_skybox_render_thread(TViewer *viewer);
EMSCRIPTEN_KEEPALIVE void remove_ibl_render_thread(TViewer *viewer);
EMSCRIPTEN_KEEPALIVE void add_light_render_thread(
void *const viewer,
TViewer *viewer,
uint8_t type,
float colour,
float intensity,
@@ -64,15 +64,15 @@ extern "C"
float sunHaloFallof,
bool shadows,
void (*callback)(EntityId));
EMSCRIPTEN_KEEPALIVE void remove_light_render_thread(void *const viewer, EntityId entityId);
EMSCRIPTEN_KEEPALIVE void clear_lights_render_thread(void *const viewer);
EMSCRIPTEN_KEEPALIVE void remove_light_render_thread(TViewer *viewer, EntityId entityId);
EMSCRIPTEN_KEEPALIVE void clear_lights_render_thread(TViewer *viewer);
EMSCRIPTEN_KEEPALIVE void load_glb_render_thread(void *const sceneManager, const char *assetPath, int numInstances, bool keepData, void (*callback)(EntityId));
EMSCRIPTEN_KEEPALIVE void load_glb_from_buffer_render_thread(void *const sceneManager, const uint8_t *const data, size_t length, int numInstances, bool keepData, int priority, int layer, void (*callback)(EntityId));
EMSCRIPTEN_KEEPALIVE void load_gltf_render_thread(void *const sceneManager, const char *assetPath, const char *relativePath, bool keepData, void (*callback)(EntityId));
EMSCRIPTEN_KEEPALIVE void create_instance_render_thread(void *const sceneManager, EntityId entityId, void (*callback)(EntityId));
EMSCRIPTEN_KEEPALIVE void remove_entity_render_thread(void *const viewer, EntityId asset, void (*callback)());
EMSCRIPTEN_KEEPALIVE void clear_entities_render_thread(void *const viewer, void (*callback)());
EMSCRIPTEN_KEEPALIVE void set_camera_render_thread(void *const viewer, EntityId asset, const char *nodeName, void (*callback)(bool));
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(
void *const sceneManager,
EntityId asset,
@@ -100,7 +100,7 @@ extern "C"
int boneIndex,
const float *const transform,
void (*callback)(bool));
EMSCRIPTEN_KEEPALIVE void set_post_processing_render_thread(void *const viewer, bool enabled);
EMSCRIPTEN_KEEPALIVE void set_post_processing_render_thread(TViewer *viewer, bool enabled);
EMSCRIPTEN_KEEPALIVE void reset_to_rest_pose_render_thread(void *const sceneManager, EntityId entityId, void(*callback)());
EMSCRIPTEN_KEEPALIVE void create_geometry_render_thread(
void *const sceneManager,
@@ -116,7 +116,7 @@ extern "C"
TMaterialInstance *materialInstance,
bool keepData,
void (*callback)(EntityId));
EMSCRIPTEN_KEEPALIVE void unproject_texture_render_thread(void *const sceneManager, EntityId entity, uint8_t* input, uint32_t inputWidth, uint32_t inputHeight, uint8_t* out, uint32_t outWidth, uint32_t outHeight, void(*callback)());
EMSCRIPTEN_KEEPALIVE void unproject_texture_render_thread(TViewer* viewer, EntityId entity, uint8_t* input, uint32_t inputWidth, uint32_t inputHeight, uint8_t* out, uint32_t outWidth, uint32_t outHeight, void(*callback)());
#ifdef __cplusplus

View File

@@ -44,69 +44,74 @@ extern "C"
filament::math::float4{float(d_mat.col4[0]), float(d_mat.col4[1]), float(d_mat.col4[2]), float(d_mat.col4[3])}};
}
EMSCRIPTEN_KEEPALIVE const void *create_filament_viewer(const void *context, const void *const loader, void *const platform, const char *uberArchivePath)
EMSCRIPTEN_KEEPALIVE TViewer *create_filament_viewer(const void *context, const void *const loader, void *const platform, const char *uberArchivePath)
{
const auto *loaderImpl = new ResourceLoaderWrapperImpl((ResourceLoaderWrapper *)loader);
auto viewer = (const void *)new FilamentViewer(context, loaderImpl, platform, uberArchivePath);
return viewer;
auto viewer = new FilamentViewer(context, loaderImpl, platform, uberArchivePath);
return reinterpret_cast<TViewer*>(viewer);
}
EMSCRIPTEN_KEEPALIVE void create_render_target(const void *const viewer, intptr_t texture, uint32_t width, uint32_t height)
EMSCRIPTEN_KEEPALIVE TEngine *Viewer_getEngine(TViewer* viewer) {
auto* engine = reinterpret_cast<FilamentViewer*>(viewer)->getEngine();
return reinterpret_cast<TEngine*>(engine);
}
EMSCRIPTEN_KEEPALIVE void create_render_target(TViewer *viewer, intptr_t texture, uint32_t width, uint32_t height)
{
((FilamentViewer *)viewer)->createRenderTarget(texture, width, height);
}
EMSCRIPTEN_KEEPALIVE void destroy_filament_viewer(const void *const viewer)
EMSCRIPTEN_KEEPALIVE void destroy_filament_viewer(TViewer *viewer)
{
delete ((FilamentViewer *)viewer);
}
EMSCRIPTEN_KEEPALIVE void set_background_color(const void *const viewer, const float r, const float g, const float b, const float a)
EMSCRIPTEN_KEEPALIVE void set_background_color(TViewer *viewer, const float r, const float g, const float b, const float a)
{
((FilamentViewer *)viewer)->setBackgroundColor(r, g, b, a);
}
EMSCRIPTEN_KEEPALIVE void clear_background_image(const void *const viewer)
EMSCRIPTEN_KEEPALIVE void clear_background_image(TViewer *viewer)
{
((FilamentViewer *)viewer)->clearBackgroundImage();
}
EMSCRIPTEN_KEEPALIVE void set_background_image(const void *const viewer, const char *path, bool fillHeight)
EMSCRIPTEN_KEEPALIVE void set_background_image(TViewer *viewer, const char *path, bool fillHeight)
{
((FilamentViewer *)viewer)->setBackgroundImage(path, fillHeight);
}
EMSCRIPTEN_KEEPALIVE void set_background_image_position(const void *const viewer, float x, float y, bool clamp)
EMSCRIPTEN_KEEPALIVE void set_background_image_position(TViewer *viewer, float x, float y, bool clamp)
{
((FilamentViewer *)viewer)->setBackgroundImagePosition(x, y, clamp);
}
EMSCRIPTEN_KEEPALIVE void set_tone_mapping(const void *const viewer, int toneMapping)
EMSCRIPTEN_KEEPALIVE void set_tone_mapping(TViewer *viewer, int toneMapping)
{
((FilamentViewer *)viewer)->setToneMapping((ToneMapping)toneMapping);
}
EMSCRIPTEN_KEEPALIVE void set_bloom(const void *const viewer, float strength)
EMSCRIPTEN_KEEPALIVE void set_bloom(TViewer *viewer, float strength)
{
((FilamentViewer *)viewer)->setBloom(strength);
}
EMSCRIPTEN_KEEPALIVE void load_skybox(const void *const viewer, const char *skyboxPath)
EMSCRIPTEN_KEEPALIVE void load_skybox(TViewer *viewer, const char *skyboxPath)
{
((FilamentViewer *)viewer)->loadSkybox(skyboxPath);
}
EMSCRIPTEN_KEEPALIVE void create_ibl(const void *const viewer, float r, float g, float b, float intensity)
EMSCRIPTEN_KEEPALIVE void create_ibl(TViewer *viewer, float r, float g, float b, float intensity)
{
((FilamentViewer *)viewer)->createIbl(r, g, b, intensity);
}
EMSCRIPTEN_KEEPALIVE void load_ibl(const void *const viewer, const char *iblPath, float intensity)
EMSCRIPTEN_KEEPALIVE void load_ibl(TViewer *viewer, const char *iblPath, float intensity)
{
((FilamentViewer *)viewer)->loadIbl(iblPath, intensity);
}
EMSCRIPTEN_KEEPALIVE void rotate_ibl(const void *const viewer, float *rotationMatrix)
EMSCRIPTEN_KEEPALIVE void rotate_ibl(TViewer *viewer, float *rotationMatrix)
{
math::mat3f matrix(rotationMatrix[0], rotationMatrix[1],
rotationMatrix[2],
@@ -120,18 +125,18 @@ extern "C"
((FilamentViewer *)viewer)->rotateIbl(matrix);
}
EMSCRIPTEN_KEEPALIVE void remove_skybox(const void *const viewer)
EMSCRIPTEN_KEEPALIVE void remove_skybox(TViewer *viewer)
{
((FilamentViewer *)viewer)->removeSkybox();
}
EMSCRIPTEN_KEEPALIVE void remove_ibl(const void *const viewer)
EMSCRIPTEN_KEEPALIVE void remove_ibl(TViewer *viewer)
{
((FilamentViewer *)viewer)->removeIbl();
}
EMSCRIPTEN_KEEPALIVE EntityId add_light(
const void *const viewer,
TViewer *viewer,
uint8_t type,
float colour,
float intensity,
@@ -152,22 +157,22 @@ extern "C"
return ((FilamentViewer *)viewer)->addLight((LightManager::Type)type, colour, intensity, posX, posY, posZ, dirX, dirY, dirZ, falloffRadius, spotLightConeInner, spotLightConeOuter, sunAngularRadius, sunHaloSize, sunHaloFallof, shadows);
}
EMSCRIPTEN_KEEPALIVE void set_light_position(const void *const viewer, int32_t entityId, float x, float y, float z)
EMSCRIPTEN_KEEPALIVE void set_light_position(TViewer *viewer, int32_t entityId, float x, float y, float z)
{
((FilamentViewer *)viewer)->setLightPosition(entityId, x, y, z);
}
EMSCRIPTEN_KEEPALIVE void set_light_direction(const void *const viewer, int32_t entityId, float x, float y, float z)
EMSCRIPTEN_KEEPALIVE void set_light_direction(TViewer *viewer, int32_t entityId, float x, float y, float z)
{
((FilamentViewer *)viewer)->setLightDirection(entityId, x, y, z);
}
EMSCRIPTEN_KEEPALIVE void remove_light(const void *const viewer, int32_t entityId)
EMSCRIPTEN_KEEPALIVE void remove_light(TViewer *viewer, int32_t entityId)
{
((FilamentViewer *)viewer)->removeLight(entityId);
}
EMSCRIPTEN_KEEPALIVE void clear_lights(const void *const viewer)
EMSCRIPTEN_KEEPALIVE void clear_lights(TViewer *viewer)
{
((FilamentViewer *)viewer)->clearLights();
}
@@ -202,17 +207,17 @@ extern "C"
return ((SceneManager *)sceneManager)->loadGltf(assetPath, relativePath, keepData);
}
EMSCRIPTEN_KEEPALIVE void set_main_camera(const void *const viewer)
EMSCRIPTEN_KEEPALIVE void set_main_camera(TViewer *viewer)
{
return ((FilamentViewer *)viewer)->setMainCamera();
}
EMSCRIPTEN_KEEPALIVE EntityId get_main_camera(const void *const viewer)
EMSCRIPTEN_KEEPALIVE EntityId get_main_camera(TViewer *viewer)
{
return ((FilamentViewer *)viewer)->getMainCamera();
}
EMSCRIPTEN_KEEPALIVE bool set_camera(const void *const viewer, EntityId asset, const char *nodeName)
EMSCRIPTEN_KEEPALIVE bool set_camera(TViewer *viewer, EntityId asset, const char *nodeName)
{
return ((FilamentViewer *)viewer)->setCamera(asset, nodeName);
}
@@ -235,7 +240,7 @@ extern "C"
cam->setProjection(fovInDegrees, aspect, near, far, horizontal ? Camera::Fov::HORIZONTAL : Camera::Fov::VERTICAL);
}
EMSCRIPTEN_KEEPALIVE TCamera *get_camera(const void *const viewer, EntityId entity)
EMSCRIPTEN_KEEPALIVE TCamera *get_camera(TViewer *viewer, EntityId entity)
{
auto filamentCamera = ((FilamentViewer *)viewer)->getCamera(entity);
return reinterpret_cast<TCamera *>(filamentCamera);
@@ -309,12 +314,12 @@ extern "C"
return array;
}
EMSCRIPTEN_KEEPALIVE void set_camera_manipulator_options(const void *const viewer, _ManipulatorMode mode, double orbitSpeedX, double orbitSpeedY, double zoomSpeed)
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(const void *const viewer, bool enabled)
EMSCRIPTEN_KEEPALIVE void set_view_frustum_culling(TViewer *viewer, bool enabled)
{
((FilamentViewer *)viewer)->setViewFrustumCulling(enabled);
}
@@ -339,17 +344,17 @@ extern "C"
}
EMSCRIPTEN_KEEPALIVE bool render(
const void *const viewer,
TViewer *viewer,
uint64_t frameTimeInNanos,
void *pixelBuffer,
void (*callback)(void *buf, size_t size, void *data),
void *data)
{
return ((FilamentViewer *)viewer)->render(frameTimeInNanos, pixelBuffer, callback, data);
return ((FilamentViewer *)viewer)->render(frameTimeInNanos, pixelBuffer, callback, data);
}
EMSCRIPTEN_KEEPALIVE void capture(
const void *const viewer,
TViewer *viewer,
uint8_t *pixelBuffer,
void (*callback)(void))
{
@@ -362,58 +367,58 @@ extern "C"
};
EMSCRIPTEN_KEEPALIVE void set_frame_interval(
const void *const viewer,
TViewer *viewer,
float frameInterval)
{
((FilamentViewer *)viewer)->setFrameInterval(frameInterval);
}
EMSCRIPTEN_KEEPALIVE void destroy_swap_chain(const void *const viewer)
EMSCRIPTEN_KEEPALIVE void destroy_swap_chain(TViewer *viewer)
{
((FilamentViewer *)viewer)->destroySwapChain();
}
EMSCRIPTEN_KEEPALIVE void create_swap_chain(const void *const viewer, const void *const window, uint32_t width, uint32_t height)
EMSCRIPTEN_KEEPALIVE void create_swap_chain(TViewer *viewer, const void *const window, uint32_t width, uint32_t height)
{
((FilamentViewer *)viewer)->createSwapChain(window, width, height);
}
EMSCRIPTEN_KEEPALIVE void update_viewport(const void *const viewer, uint32_t width, uint32_t height)
EMSCRIPTEN_KEEPALIVE void update_viewport(TViewer *viewer, uint32_t width, uint32_t height)
{
return ((FilamentViewer *)viewer)->updateViewport(width, height);
}
EMSCRIPTEN_KEEPALIVE void scroll_update(const void *const viewer, float x, float y, float delta)
EMSCRIPTEN_KEEPALIVE void scroll_update(TViewer *viewer, float x, float y, float delta)
{
((FilamentViewer *)viewer)->scrollUpdate(x, y, delta);
}
EMSCRIPTEN_KEEPALIVE void scroll_begin(const void *const viewer)
EMSCRIPTEN_KEEPALIVE void scroll_begin(TViewer *viewer)
{
((FilamentViewer *)viewer)->scrollBegin();
}
EMSCRIPTEN_KEEPALIVE void scroll_end(const void *const viewer)
EMSCRIPTEN_KEEPALIVE void scroll_end(TViewer *viewer)
{
((FilamentViewer *)viewer)->scrollEnd();
}
EMSCRIPTEN_KEEPALIVE void grab_begin(const void *const viewer, float x, float y, bool pan)
EMSCRIPTEN_KEEPALIVE void grab_begin(TViewer *viewer, float x, float y, bool pan)
{
((FilamentViewer *)viewer)->grabBegin(x, y, pan);
}
EMSCRIPTEN_KEEPALIVE void grab_update(const void *const viewer, float x, float y)
EMSCRIPTEN_KEEPALIVE void grab_update(TViewer *viewer, float x, float y)
{
((FilamentViewer *)viewer)->grabUpdate(x, y);
}
EMSCRIPTEN_KEEPALIVE void grab_end(const void *const viewer)
EMSCRIPTEN_KEEPALIVE void grab_end(TViewer *viewer)
{
((FilamentViewer *)viewer)->grabEnd();
}
EMSCRIPTEN_KEEPALIVE void *get_scene_manager(const void *const viewer)
EMSCRIPTEN_KEEPALIVE void *get_scene_manager(TViewer *viewer)
{
return (void *)((FilamentViewer *)viewer)->getSceneManager();
}
@@ -475,27 +480,27 @@ extern "C"
((SceneManager *)sceneManager)->addBoneAnimation(asset, skinIndex, boneIndex, frameData, numFrames, frameLengthInMs, fadeOutInSecs, fadeInInSecs, maxDelta);
}
EMSCRIPTEN_KEEPALIVE void set_post_processing(void *const viewer, bool enabled)
EMSCRIPTEN_KEEPALIVE void set_post_processing(TViewer *viewer, bool enabled)
{
((FilamentViewer *)viewer)->setPostProcessing(enabled);
}
EMSCRIPTEN_KEEPALIVE void set_shadows_enabled(void *const viewer, bool enabled)
EMSCRIPTEN_KEEPALIVE void set_shadows_enabled(TViewer *viewer, bool enabled)
{
((FilamentViewer *)viewer)->setShadowsEnabled(enabled);
}
EMSCRIPTEN_KEEPALIVE void set_shadow_type(void *const viewer, int shadowType)
EMSCRIPTEN_KEEPALIVE void set_shadow_type(TViewer *viewer, int shadowType)
{
((FilamentViewer *)viewer)->setShadowType((ShadowType)shadowType);
}
EMSCRIPTEN_KEEPALIVE void set_soft_shadow_options(void *const viewer, float penumbraScale, float penumbraRatioScale)
EMSCRIPTEN_KEEPALIVE void set_soft_shadow_options(TViewer *viewer, float penumbraScale, float penumbraRatioScale)
{
((FilamentViewer *)viewer)->setSoftShadowOptions(penumbraScale, penumbraRatioScale);
}
EMSCRIPTEN_KEEPALIVE void set_antialiasing(void *const viewer, bool msaa, bool fxaa, bool taa)
EMSCRIPTEN_KEEPALIVE void set_antialiasing(TViewer *viewer, bool msaa, bool fxaa, bool taa)
{
((FilamentViewer *)viewer)->setAntiAliasing(msaa, fxaa, taa);
}
@@ -721,12 +726,12 @@ extern "C"
strcpy(outPtr, name.c_str());
}
EMSCRIPTEN_KEEPALIVE void remove_entity(const void *const viewer, EntityId asset)
EMSCRIPTEN_KEEPALIVE void remove_entity(TViewer *viewer, EntityId asset)
{
((FilamentViewer *)viewer)->removeEntity(asset);
}
EMSCRIPTEN_KEEPALIVE void clear_entities(const void *const viewer)
EMSCRIPTEN_KEEPALIVE void clear_entities(TViewer *viewer)
{
((FilamentViewer *)viewer)->clearEntities();
}
@@ -791,7 +796,7 @@ extern "C"
return ((SceneManager *)sceneManager)->reveal(asset, meshName);
}
EMSCRIPTEN_KEEPALIVE void filament_pick(void *const viewer, int x, int y, void (*callback)(EntityId entityId, int x, int y))
EMSCRIPTEN_KEEPALIVE void filament_pick(TViewer *viewer, 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);
}
@@ -816,12 +821,12 @@ extern "C"
return ((SceneManager *)sceneManager)->getEntityNameAt(target, index, renderableOnly);
}
EMSCRIPTEN_KEEPALIVE void set_recording(void *const viewer, bool recording)
EMSCRIPTEN_KEEPALIVE void set_recording(TViewer *viewer, bool recording)
{
((FilamentViewer *)viewer)->setRecording(recording);
}
EMSCRIPTEN_KEEPALIVE void set_recording_output_directory(void *const viewer, const char *outputDirectory)
EMSCRIPTEN_KEEPALIVE void set_recording_output_directory(TViewer *viewer, const char *outputDirectory)
{
((FilamentViewer *)viewer)->setRecordingOutputDirectory(outputDirectory);
}
@@ -987,7 +992,7 @@ extern "C"
((SceneManager *)sceneManager)->setMaterialProperty(entity, materialIndex, property, filamentValue);
}
EMSCRIPTEN_KEEPALIVE void unproject_texture(void *const 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);
}
@@ -1058,7 +1063,14 @@ EMSCRIPTEN_KEEPALIVE void MaterialInstance_setDepthCulling(TMaterialInstance* ma
reinterpret_cast<MaterialInstance*>(materialInstance)->setDepthCulling(enabled);
}
EMSCRIPTEN_KEEPALIVE void Camera_setCustomProjectionWithCulling(TCamera* camera, double4x4 projectionMatrix, double4x4 projectionMatrixForCulling, double near, double far) {
reinterpret_cast<Camera*>(camera)->setCustomProjection(convert_double4x4_to_mat4(projectionMatrix), convert_double4x4_to_mat4(projectionMatrixForCulling), near, far);
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 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);
}
}

View File

@@ -133,7 +133,7 @@ public:
const ResourceLoaderWrapper *const loader,
void (*renderCallback)(void *),
void *const owner,
void (*callback)(void *const))
void (*callback)(TViewer*))
{
_renderCallback = renderCallback;
_renderCallbackOwner = owner;
@@ -155,7 +155,8 @@ public:
_viewer = (FilamentViewer *)create_filament_viewer((void *const)_context, loader, platform, uberArchivePath);
MAIN_THREAD_EM_ASM({ moduleArg.dartFilamentResolveCallback($0, $1); }, callback, _viewer);
#else
_viewer = (FilamentViewer *)create_filament_viewer(context, loader, platform, uberArchivePath);
auto viewer = (FilamentViewer *)create_filament_viewer(context, loader, platform, uberArchivePath);
_viewer = reinterpret_cast<TViewer*>(viewer);
callback(_viewer);
#endif
});
@@ -168,7 +169,7 @@ public:
{
_render = false;
_viewer = nullptr;
destroy_filament_viewer(viewer); });
destroy_filament_viewer(reinterpret_cast<TViewer*>(viewer)); });
auto fut = add_task(lambda);
fut.wait();
}
@@ -222,7 +223,7 @@ private:
void (*_renderCallback)(void *const) = nullptr;
void *_renderCallbackOwner = nullptr;
std::deque<std::function<void()>> _tasks;
FilamentViewer *_viewer = nullptr;
TViewer *_viewer = nullptr;
std::chrono::high_resolution_clock::time_point _lastFrameTime;
int _frameCount = 0;
float _accumulatedTime = 0.0f;
@@ -246,7 +247,7 @@ extern "C"
const void *const loader,
void (*renderCallback)(void *const renderCallbackOwner),
void *const renderCallbackOwner,
void (*callback)(void *const))
void (*callback)(TViewer *))
{
if (!_rl)
@@ -257,14 +258,14 @@ extern "C"
renderCallback, renderCallbackOwner, callback);
}
EMSCRIPTEN_KEEPALIVE void destroy_filament_viewer_render_thread(void *const viewer)
EMSCRIPTEN_KEEPALIVE void destroy_filament_viewer_render_thread(TViewer *viewer)
{
_rl->destroyViewer((FilamentViewer *)viewer);
delete _rl;
_rl = nullptr;
}
EMSCRIPTEN_KEEPALIVE void create_swap_chain_render_thread(void *const viewer,
EMSCRIPTEN_KEEPALIVE void create_swap_chain_render_thread(TViewer *viewer,
void *const surface,
uint32_t width,
uint32_t height,
@@ -283,7 +284,7 @@ extern "C"
auto fut = _rl->add_task(lambda);
}
EMSCRIPTEN_KEEPALIVE void destroy_swap_chain_render_thread(void *const viewer, void (*onComplete)())
EMSCRIPTEN_KEEPALIVE void destroy_swap_chain_render_thread(TViewer *viewer, void (*onComplete)())
{
std::packaged_task<void()> lambda(
[=]() mutable
@@ -298,7 +299,7 @@ extern "C"
auto fut = _rl->add_task(lambda);
}
EMSCRIPTEN_KEEPALIVE void create_render_target_render_thread(void *const viewer,
EMSCRIPTEN_KEEPALIVE void create_render_target_render_thread(TViewer *viewer,
intptr_t nativeTextureId,
uint32_t width,
uint32_t height,
@@ -316,7 +317,7 @@ extern "C"
auto fut = _rl->add_task(lambda);
}
EMSCRIPTEN_KEEPALIVE void request_frame_render_thread(void *const viewer)
EMSCRIPTEN_KEEPALIVE void request_frame_render_thread(TViewer *viewer)
{
if (!_rl)
{
@@ -329,7 +330,7 @@ extern "C"
}
EMSCRIPTEN_KEEPALIVE void
set_frame_interval_render_thread(void *const viewer, float frameIntervalInMilliseconds)
set_frame_interval_render_thread(TViewer *viewer, float frameIntervalInMilliseconds)
{
_rl->setFrameIntervalInMilliseconds(frameIntervalInMilliseconds);
std::packaged_task<void()> lambda([=]() mutable
@@ -337,14 +338,14 @@ extern "C"
auto fut = _rl->add_task(lambda);
}
EMSCRIPTEN_KEEPALIVE void render_render_thread(void *const viewer)
EMSCRIPTEN_KEEPALIVE void render_render_thread(TViewer *viewer)
{
std::packaged_task<void()> lambda([=]() mutable
{ _rl->doRender(); });
auto fut = _rl->add_task(lambda);
}
EMSCRIPTEN_KEEPALIVE void capture_render_thread(void *const viewer, uint8_t *pixelBuffer, void (*onComplete)())
EMSCRIPTEN_KEEPALIVE void capture_render_thread(TViewer *viewer, uint8_t *pixelBuffer, void (*onComplete)())
{
std::packaged_task<void()> lambda([=]() mutable
{ capture(viewer, pixelBuffer, onComplete); });
@@ -352,7 +353,7 @@ extern "C"
}
EMSCRIPTEN_KEEPALIVE void
set_background_color_render_thread(void *const viewer, const float r, const float g,
set_background_color_render_thread(TViewer *viewer, const float r, const float g,
const float b, const float a)
{
std::packaged_task<void()> lambda(
@@ -420,14 +421,14 @@ extern "C"
auto fut = _rl->add_task(lambda);
}
EMSCRIPTEN_KEEPALIVE void clear_background_image_render_thread(void *const viewer)
EMSCRIPTEN_KEEPALIVE void clear_background_image_render_thread(TViewer *viewer)
{
std::packaged_task<void()> lambda([=]
{ clear_background_image(viewer); });
auto fut = _rl->add_task(lambda);
}
EMSCRIPTEN_KEEPALIVE void set_background_image_render_thread(void *const viewer,
EMSCRIPTEN_KEEPALIVE void set_background_image_render_thread(TViewer *viewer,
const char *path,
bool fillHeight, void (*callback)())
{
@@ -443,7 +444,7 @@ extern "C"
});
auto fut = _rl->add_task(lambda);
}
EMSCRIPTEN_KEEPALIVE void set_background_image_position_render_thread(void *const viewer,
EMSCRIPTEN_KEEPALIVE void set_background_image_position_render_thread(TViewer *viewer,
float x, float y,
bool clamp)
{
@@ -452,7 +453,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(void *const viewer,
EMSCRIPTEN_KEEPALIVE void set_tone_mapping_render_thread(TViewer *viewer,
int toneMapping)
{
std::packaged_task<void()> lambda(
@@ -460,13 +461,13 @@ extern "C"
{ set_tone_mapping(viewer, toneMapping); });
auto fut = _rl->add_task(lambda);
}
EMSCRIPTEN_KEEPALIVE void set_bloom_render_thread(void *const viewer, float strength)
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(void *const viewer,
EMSCRIPTEN_KEEPALIVE void load_skybox_render_thread(TViewer *viewer,
const char *skyboxPath,
void (*onComplete)())
{
@@ -482,7 +483,7 @@ extern "C"
auto fut = _rl->add_task(lambda);
}
EMSCRIPTEN_KEEPALIVE void load_ibl_render_thread(void *const viewer, const char *iblPath,
EMSCRIPTEN_KEEPALIVE void load_ibl_render_thread(TViewer *viewer, const char *iblPath,
float intensity)
{
std::packaged_task<void()> lambda(
@@ -490,14 +491,14 @@ extern "C"
{ load_ibl(viewer, iblPath, intensity); });
auto fut = _rl->add_task(lambda);
}
EMSCRIPTEN_KEEPALIVE void remove_skybox_render_thread(void *const viewer)
EMSCRIPTEN_KEEPALIVE void remove_skybox_render_thread(TViewer *viewer)
{
std::packaged_task<void()> lambda([=]
{ remove_skybox(viewer); });
auto fut = _rl->add_task(lambda);
}
EMSCRIPTEN_KEEPALIVE void remove_ibl_render_thread(void *const viewer)
EMSCRIPTEN_KEEPALIVE void remove_ibl_render_thread(TViewer *viewer)
{
std::packaged_task<void()> lambda([=]
{ remove_ibl(viewer); });
@@ -505,7 +506,7 @@ extern "C"
}
void add_light_render_thread(
void *const viewer,
TViewer *viewer,
uint8_t type,
float colour,
float intensity,
@@ -556,7 +557,7 @@ extern "C"
auto fut = _rl->add_task(lambda);
}
EMSCRIPTEN_KEEPALIVE void remove_light_render_thread(void *const viewer,
EMSCRIPTEN_KEEPALIVE void remove_light_render_thread(TViewer *viewer,
EntityId entityId)
{
std::packaged_task<void()> lambda([=]
@@ -564,14 +565,14 @@ extern "C"
auto fut = _rl->add_task(lambda);
}
EMSCRIPTEN_KEEPALIVE void clear_lights_render_thread(void *const viewer)
EMSCRIPTEN_KEEPALIVE void clear_lights_render_thread(TViewer *viewer)
{
std::packaged_task<void()> lambda([=]
{ clear_lights(viewer); });
auto fut = _rl->add_task(lambda);
}
EMSCRIPTEN_KEEPALIVE void remove_entity_render_thread(void *const viewer,
EMSCRIPTEN_KEEPALIVE void remove_entity_render_thread(TViewer *viewer,
EntityId asset, void (*callback)())
{
std::packaged_task<void()> lambda([=]
@@ -586,7 +587,7 @@ extern "C"
auto fut = _rl->add_task(lambda);
}
EMSCRIPTEN_KEEPALIVE void clear_entities_render_thread(void *const viewer, void (*callback)())
EMSCRIPTEN_KEEPALIVE void clear_entities_render_thread(TViewer *viewer, void (*callback)())
{
std::packaged_task<void()> lambda([=]
{
@@ -600,7 +601,7 @@ extern "C"
auto fut = _rl->add_task(lambda);
}
EMSCRIPTEN_KEEPALIVE void set_camera_render_thread(void *const viewer, EntityId asset,
EMSCRIPTEN_KEEPALIVE void set_camera_render_thread(TViewer *viewer, EntityId asset,
const char *nodeName, void (*callback)(bool))
{
std::packaged_task<bool()> lambda(
@@ -707,7 +708,7 @@ extern "C"
auto fut = _rl->add_task(lambda);
}
EMSCRIPTEN_KEEPALIVE void set_post_processing_render_thread(void *const viewer,
EMSCRIPTEN_KEEPALIVE void set_post_processing_render_thread(TViewer *viewer,
bool enabled)
{
std::packaged_task<void()> lambda(
@@ -834,7 +835,7 @@ extern "C"
auto fut = _rl->add_task(lambda);
}
EMSCRIPTEN_KEEPALIVE void unproject_texture_render_thread(void *const viewer, EntityId entity, uint8_t *input, uint32_t inputWidth, uint32_t inputHeight, uint8_t *out, uint32_t outWidth, uint32_t outHeight, void (*callback)())
EMSCRIPTEN_KEEPALIVE void unproject_texture_render_thread(TViewer* viewer, EntityId entity, uint8_t *input, uint32_t inputWidth, uint32_t inputHeight, uint8_t *out, uint32_t outWidth, uint32_t outHeight, void (*callback)())
{
std::packaged_task<void()> lambda(
[=]

View File

@@ -10,8 +10,7 @@ import 'package:thermion_dart/thermion_dart/utils/dart_resources.dart';
import 'package:thermion_dart/thermion_dart/thermion_viewer.dart';
import 'package:thermion_dart/thermion_dart/viewer/ffi/thermion_dart.g.dart';
import 'package:thermion_dart/thermion_dart/viewer/ffi/thermion_viewer_ffi.dart';
final viewportDimensions = (width: 500, height: 500);
import 'package:vector_math/vector_math_64.dart';
/// Test files are run in a variety of ways, find this package root in all.
///
@@ -107,7 +106,8 @@ Future<Uint8List> pixelBufferToBmp(
return data;
}
Future<Uint8List> bmpToPng(Uint8List pixelBuffer, int width, int height) async {
Future<Uint8List> pixelsToPng(Uint8List pixelBuffer, int width, int height,
{bool linearToSrgb = false}) async {
final image = img.Image(width: width, height: height);
for (int y = 0; y < height; y++) {
@@ -126,13 +126,23 @@ Future<Uint8List> bmpToPng(Uint8List pixelBuffer, int width, int height) async {
b = _inverseACESToneMapping(b);
}
// Convert from linear to sRGB
final int sRgbR = _linearToSRGB(r);
final int sRgbG = _linearToSRGB(g);
final int sRgbB = _linearToSRGB(b);
if (linearToSrgb) {
// Convert from linear to sRGB
image.setPixel(
x, y, img.ColorUint8(4)..setRgba(sRgbR, sRgbG, sRgbB, 1.0));
image.setPixel(
x,
y,
img.ColorUint8(4)
..setRgba(
_linearToSRGB(r), _linearToSRGB(g), _linearToSRGB(b), 1.0));
} else {
image.setPixel(
x,
y,
img.ColorUint8(4)
..setRgba((r * 255).toInt(), (g * 255).toInt(), (b * 255).toInt(),
1.0));
}
}
}
@@ -163,7 +173,10 @@ int _linearToSRGB(double linearValue) {
}
}
Future<ThermionViewer> createViewer() async {
Future<ThermionViewer> createViewer(
{img.Color? bg,
Vector3? cameraPosition,
viewportDimensions = (width: 500, height: 500)}) async {
final packageUri = findPackageRoot('thermion_dart');
final lib = ThermionDartTexture1(DynamicLibrary.open(
@@ -192,5 +205,280 @@ Future<ThermionViewer> createViewer() async {
await viewer.updateViewportAndCameraProjection(
viewportDimensions.width.toDouble(),
viewportDimensions.height.toDouble());
if (bg != null) {
await viewer.setBackgroundColor(
bg.r.toDouble(), bg.g.toDouble(), bg.b.toDouble(), bg.a.toDouble());
}
if (cameraPosition != null) {
await viewer.setCameraPosition(
cameraPosition.x, cameraPosition.y, cameraPosition.z);
}
return viewer;
}
Uint8List poissonBlend(List<Uint8List> textures, int width, int height) {
final int numTextures = textures.length;
final int size = width * height;
// Initialize the result
List<Vector4> result = List.generate(size, (_) => Vector4(0, 0, 0, 0));
List<bool> validPixel = List.generate(size, (_) => false);
// Compute gradients and perform simplified Poisson blending
for (int y = 1; y < height - 1; y++) {
for (int x = 1; x < width - 1; x++) {
int index = y * width + x;
Vector4 gradX = Vector4(0, 0, 0, 0);
Vector4 gradY = Vector4(0, 0, 0, 0);
bool hasValidData = false;
for (int t = 0; t < numTextures; t++) {
int i = index * 4;
if (textures[t][i] == 0 &&
textures[t][i + 1] == 0 &&
textures[t][i + 2] == 0 &&
textures[t][i + 3] == 0) {
continue; // Skip this texture if the pixel is empty
}
hasValidData = true;
int iLeft = (y * width + x - 1) * 4;
int iRight = (y * width + x + 1) * 4;
int iUp = ((y - 1) * width + x) * 4;
int iDown = ((y + 1) * width + x) * 4;
Vector4 gx = Vector4(
(textures[t][iRight] - textures[t][iLeft]) / 2,
(textures[t][iRight + 1] - textures[t][iLeft + 1]) / 2,
(textures[t][iRight + 2] - textures[t][iLeft + 2]) / 2,
(textures[t][iRight + 3] - textures[t][iLeft + 3]) / 2);
Vector4 gy = Vector4(
(textures[t][iDown] - textures[t][iUp]) / 2,
(textures[t][iDown + 1] - textures[t][iUp + 1]) / 2,
(textures[t][iDown + 2] - textures[t][iUp + 2]) / 2,
(textures[t][iDown + 3] - textures[t][iUp + 3]) / 2);
// Select the gradient with larger magnitude
double magX = gx.r * gx.r + gx.g * gx.g + gx.b * gx.b + gx.a * gx.a;
double magY = gy.r * gy.r + gy.g * gy.g + gy.b * gy.b + gy.a * gy.a;
if (magX >
gradX.r * gradX.r +
gradX.g * gradX.g +
gradX.b * gradX.b +
gradX.a * gradX.a) {
gradX = gx;
}
if (magY >
gradY.r * gradY.r +
gradY.g * gradY.g +
gradY.b * gradY.b +
gradY.a * gradY.a) {
gradY = gy;
}
}
if (hasValidData) {
validPixel[index] = true;
// Simplified Poisson equation solver (Jacobi iteration)
result[index].r = (result[index - 1].r +
result[index + 1].r +
result[index - width].r +
result[index + width].r +
gradX.r -
gradY.r) /
4;
result[index].g = (result[index - 1].g +
result[index + 1].g +
result[index - width].g +
result[index + width].g +
gradX.g -
gradY.g) /
4;
result[index].b = (result[index - 1].b +
result[index + 1].b +
result[index - width].b +
result[index + width].b +
gradX.b -
gradY.b) /
4;
result[index].a = (result[index - 1].a +
result[index + 1].a +
result[index - width].a +
result[index + width].a +
gradX.a -
gradY.a) /
4;
}
}
}
// Fill in gaps and normalize
Uint8List finalResult = Uint8List(size * 4);
for (int i = 0; i < size; i++) {
if (validPixel[i]) {
finalResult[i * 4] = (result[i].r.clamp(0, 255)).toInt();
finalResult[i * 4 + 1] = (result[i].g.clamp(0, 255)).toInt();
finalResult[i * 4 + 2] = (result[i].b.clamp(0, 255)).toInt();
finalResult[i * 4 + 3] = (result[i].a.clamp(0, 255)).toInt();
} else {
// For invalid pixels, try to interpolate from neighbors
List<int> validNeighbors = [];
if (i > width && validPixel[i - width]) validNeighbors.add(i - width);
if (i < size - width && validPixel[i + width])
validNeighbors.add(i + width);
if (i % width > 0 && validPixel[i - 1]) validNeighbors.add(i - 1);
if (i % width < width - 1 && validPixel[i + 1]) validNeighbors.add(i + 1);
if (validNeighbors.isNotEmpty) {
double r = 0, g = 0, b = 0, a = 0;
for (int neighbor in validNeighbors) {
r += result[neighbor].r;
g += result[neighbor].g;
b += result[neighbor].b;
a += result[neighbor].a;
}
finalResult[i * 4] = (r / validNeighbors.length).clamp(0, 255).toInt();
finalResult[i * 4 + 1] =
(g / validNeighbors.length).clamp(0, 255).toInt();
finalResult[i * 4 + 2] =
(b / validNeighbors.length).clamp(0, 255).toInt();
finalResult[i * 4 + 3] =
(a / validNeighbors.length).clamp(0, 255).toInt();
} else {
// If no valid neighbors, set to transparent black
finalResult[i * 4] = 0;
finalResult[i * 4 + 1] = 0;
finalResult[i * 4 + 2] = 0;
finalResult[i * 4 + 3] = 0;
}
}
}
return finalResult;
}
Uint8List medianImages(List<Uint8List> images) {
if (images.isEmpty) {
return Uint8List(0);
}
int imageSize = images[0].length;
Uint8List result = Uint8List(imageSize);
int numImages = images.length;
for (int i = 0; i < imageSize; i++) {
List<int> pixelValues = [];
for (int j = 0; j < numImages; j++) {
pixelValues.add(images[j][i]);
}
pixelValues.sort();
int medianIndex = numImages ~/ 2;
result[i] = pixelValues[medianIndex];
}
return result;
}
Uint8List maxIntensityProjection(
List<Uint8List> textures, int width, int height) {
final int numTextures = textures.length;
final int size = width * height;
// Initialize the result with the first texture
Uint8List result = Uint8List.fromList(textures[0]);
// Iterate through all textures and perform max intensity projection
for (int t = 1; t < numTextures; t++) {
for (int i = 0; i < size * 4; i += 4) {
// Calculate intensity (using luminance formula)
double intensityCurrent =
0.299 * result[i] + 0.587 * result[i + 1] + 0.114 * result[i + 2];
double intensityNew = 0.299 * textures[t][i] +
0.587 * textures[t][i + 1] +
0.114 * textures[t][i + 2];
// If the new texture has higher intensity, use its values
if (intensityNew > intensityCurrent) {
result[i] = textures[t][i]; // R
result[i + 1] = textures[t][i + 1]; // G
result[i + 2] = textures[t][i + 2]; // B
result[i + 3] = textures[t][i + 3]; // A
}
}
}
return result;
}
// Helper function to blend MIP result with Poisson blending
Uint8List blendMIPWithPoisson(
Uint8List mipResult, Uint8List poissonResult, double alpha) {
final int size = mipResult.length;
Uint8List blendedResult = Uint8List(size);
for (int i = 0; i < size; i++) {
blendedResult[i] = (mipResult[i] * (1 - alpha) + poissonResult[i] * alpha)
.round()
.clamp(0, 255);
}
return blendedResult;
}
Uint8List pngToPixelBuffer(Uint8List pngData) {
// Decode the PNG image
final image = img.decodePng(pngData);
if (image == null) {
throw Exception('Failed to decode PNG image');
}
// Create a buffer for the raw pixel data
final rawPixels = Uint8List(image.width * image.height * 4);
// Convert the image to RGBA format
for (int y = 0; y < image.height; y++) {
for (int x = 0; x < image.width; x++) {
final pixel = image.getPixel(x, y);
final i = (y * image.width + x) * 4;
rawPixels[i] = pixel.r.toInt(); // Red
rawPixels[i + 1] = pixel.g.toInt(); // Green
rawPixels[i + 2] = pixel.b.toInt(); // Blue
rawPixels[i + 3] = pixel.a.toInt(); // Alpha
}
}
return rawPixels;
}
Uint8List medianBlending(List<Uint8List> textures, int width, int height) {
final int numTextures = textures.length;
final int size = width * height;
Uint8List result = Uint8List(size * 4);
for (int i = 0; i < size; i++) {
List<int> values = [];
for (int t = 0; t < numTextures; t++) {
if (textures[t][i * 4] != 0 ||
textures[t][i * 4 + 1] != 0 ||
textures[t][i * 4 + 2] != 0 ||
textures[t][i * 4 + 3] != 0) {
values.addAll(textures[t].sublist(i * 4, i * 4 + 4));
}
}
if (values.isNotEmpty) {
values.sort();
result[i] = values[values.length ~/ 2];
} else {
result[i] = 0; // If no valid data, set to transparent
}
}
return result;
}

View File

@@ -3,6 +3,7 @@ import 'dart:io';
import 'dart:math';
import 'dart:typed_data';
import 'package:image/image.dart';
import 'package:thermion_dart/thermion_dart.dart';
import 'package:test/test.dart';
import 'package:animation_tools_dart/animation_tools_dart.dart';
@@ -14,6 +15,9 @@ import 'package:vector_math/vector_math_64.dart';
import 'helpers.dart';
Color kWhite = ColorFloat32(4)..setRgba(1.0, 1.0, 1.0, 1.0);
Color kRed = ColorFloat32(4)..setRgba(1.0, 0.0, 0.0, 1.0);
void main() async {
final packageUri = findPackageRoot('thermion_dart');
testDir = Directory("${packageUri.toFilePath()}/test").path;
@@ -98,6 +102,27 @@ void main() async {
print(frustum.plane5.normal);
print(frustum.plane5.constant);
});
test('set custom projection/culling matrix', () async {
var viewer = await createViewer(bg:kRed, cameraPosition:Vector3(0,0,4));
var camera = await viewer.getMainCamera();
final cube = await viewer.createGeometry(GeometryHelper.cube());
// cube is visible when inside the frustum, cube is visible
var projectionMatrix =
makeOrthographicMatrix(-10.0, 10.0, -10.0, 10.0, 0.05, 10000);
await camera.setProjectionMatrixWithCulling(
projectionMatrix, 0.05, 10000);
await _capture(viewer, "camera_projection_culling_matrix_object_in_frustum");
// cube no longer visible when the far plane is moved closer to camera so cube is outside
projectionMatrix =
makeOrthographicMatrix(-10.0, 10.0, -10.0, 10.0, 0.05, 1);
await camera.setProjectionMatrixWithCulling(
projectionMatrix, 0.05, 1);
await _capture(viewer, "camera_projection_culling_matrix_object_outside_frustum");
});
});
group('background', () {