add model/view matrix getters & manipulator options

This commit is contained in:
Nick Fisher
2023-11-03 15:20:15 +08:00
parent 83469e93b9
commit 58a9542121
18 changed files with 833 additions and 553 deletions

View File

@@ -178,8 +178,16 @@ abstract class FilamentController {
///
Future clearLights();
///
/// Load the .glb asset at the given path and insert into the scene.
///
Future<FilamentEntity> loadGlb(String path, {bool unlit = false});
///
/// Load the .gltf asset at the given path and insert into the scene.
/// [relativeResourcePath] is the folder path where the glTF resources are stored;
/// this is usually the parent directory of the .gltf file itself.
///
Future<FilamentEntity> loadGltf(String path, String relativeResourcePath);
///
@@ -314,13 +322,28 @@ abstract class FilamentController {
///
/// Get the camera position in world space.
///
Future<Vector3> getCameraPosition(double x, double y, double z);
Future<Vector3> getCameraPosition();
///
/// Get the camera's model matrix.
///
Future<Matrix4> getCameraModelMatrix();
///
/// Get the camera's view matrix.
///
Future<Matrix4> getCameraViewMatrix();
///
/// Set the camera position in world space.
///
Future setCameraPosition(double x, double y, double z);
///
/// Get the camera rotation matrix.
///
Future<Matrix3> getCameraRotation();
///
/// Repositions the camera to the last vertex of the bounding box of [asset], looking at the penultimate vertex.
///
@@ -347,11 +370,14 @@ abstract class FilamentController {
///
Future setCameraModelMatrix(List<double> matrix);
///
/// Sets the `baseColorFactor` property for the material at index [materialIndex] in [entity] under node [meshName] to [color].
///
Future setMaterialColor(
FilamentEntity entity, String meshName, int materialIndex, Color color);
///
/// Scales [asset] up/down so it fits within a unit cube.
/// Scale [asset] to fit within the unit cube.
///
Future transformToUnitCube(FilamentEntity entity);
@@ -369,6 +395,10 @@ abstract class FilamentController {
/// Sets the scale for the given entity.
///
Future setScale(FilamentEntity entity, double scale);
///
/// Sets the rotation for [entity] to [rads] around the axis {x,y,z}.
///
Future setRotation(
FilamentEntity entity, double rads, double x, double y, double z);

View File

@@ -1,6 +1,7 @@
import 'dart:async';
import 'dart:ffi';
import 'dart:io';
import 'dart:typed_data';
import 'dart:ui' as ui;
import 'package:flutter/services.dart';
import 'package:ffi/ffi.dart';
@@ -11,6 +12,7 @@ import 'package:flutter_filament/filament_controller.dart';
import 'package:flutter_filament/animations/animation_data.dart';
import 'package:flutter_filament/generated_bindings.dart';
import 'package:flutter_filament/rendering_surface.dart';
import 'package:vector_math/vector_math_64.dart';
// ignore: constant_identifier_names
const FilamentEntity _FILAMENT_ASSET_ERROR = 0;
@@ -967,7 +969,7 @@ class FilamentControllerFFI extends FilamentController {
_lib.pick_ffi(_viewer!, x, textureDetails.value!.height - y, outPtr);
int wait = 0;
while (outPtr.value == 0) {
await Future.delayed(Duration(milliseconds: 50));
await Future.delayed(const Duration(milliseconds: 32));
wait++;
if (wait > 10) {
calloc.free(outPtr);
@@ -978,4 +980,48 @@ class FilamentControllerFFI extends FilamentController {
_pickResultController.add(entityId);
calloc.free(outPtr);
}
@override
Future<Matrix4> getCameraViewMatrix() async {
if (_viewer == null) {
throw Exception("No viewer available");
}
var arrayPtr = _lib.get_camera_view_matrix(_viewer!);
return Matrix4.fromList(arrayPtr.asTypedList(16));
}
@override
Future<Matrix4> getCameraModelMatrix() async {
if (_viewer == null) {
throw Exception("No viewer available");
}
var arrayPtr = _lib.get_camera_model_matrix(_viewer!);
return Matrix4.fromList(arrayPtr.asTypedList(16));
}
@override
Future<Vector3> getCameraPosition() async {
if (_viewer == null) {
throw Exception("No viewer available");
}
var arrayPtr = _lib.get_camera_model_matrix(_viewer!);
var doubleList = arrayPtr.asTypedList(16);
var modelMatrix = Matrix4.fromFloat64List(doubleList);
calloc.free(arrayPtr);
return modelMatrix.getColumn(3).xyz;
}
@override
Future<Matrix3> getCameraRotation() async {
if (_viewer == null) {
throw Exception("No viewer available");
}
var arrayPtr = _lib.get_camera_model_matrix(_viewer!);
var doubleList = arrayPtr.asTypedList(16);
var modelMatrix = Matrix4.fromFloat64List(doubleList);
var rotationMatrix = Matrix3.identity();
modelMatrix.copyRotation(rotationMatrix);
calloc.free(arrayPtr);
return rotationMatrix;
}
}

View File

@@ -224,9 +224,8 @@ class NativeLibrary {
}
late final _set_bloomPtr = _lookup<
ffi
.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Float)>>(
'set_bloom');
ffi.NativeFunction<
ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Float)>>('set_bloom');
late final _set_bloom =
_set_bloomPtr.asFunction<void Function(ffi.Pointer<ffi.Void>, double)>();
@@ -351,9 +350,8 @@ class NativeLibrary {
}
late final _remove_lightPtr = _lookup<
ffi
.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void>, EntityId)>>(
'remove_light');
ffi.NativeFunction<
ffi.Void Function(ffi.Pointer<ffi.Void>, EntityId)>>('remove_light');
late final _remove_light =
_remove_lightPtr.asFunction<void Function(ffi.Pointer<ffi.Void>, int)>();
@@ -991,9 +989,8 @@ class NativeLibrary {
}
late final _remove_assetPtr = _lookup<
ffi
.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void>, EntityId)>>(
'remove_asset');
ffi.NativeFunction<
ffi.Void Function(ffi.Pointer<ffi.Void>, EntityId)>>('remove_asset');
late final _remove_asset =
_remove_assetPtr.asFunction<void Function(ffi.Pointer<ffi.Void>, int)>();
@@ -1192,6 +1189,20 @@ class NativeLibrary {
late final _set_camera_position = _set_camera_positionPtr.asFunction<
void Function(ffi.Pointer<ffi.Void>, double, double, double)>();
void get_camera_position(
ffi.Pointer<ffi.Void> viewer,
) {
return _get_camera_position(
viewer,
);
}
late final _get_camera_positionPtr =
_lookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void>)>>(
'get_camera_position');
late final _get_camera_position = _get_camera_positionPtr
.asFunction<void Function(ffi.Pointer<ffi.Void>)>();
void set_camera_rotation(
ffi.Pointer<ffi.Void> viewer,
double rads,
@@ -1232,6 +1243,51 @@ class NativeLibrary {
late final _set_camera_model_matrix = _set_camera_model_matrixPtr.asFunction<
void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Float>)>();
ffi.Pointer<ffi.Double> get_camera_model_matrix(
ffi.Pointer<ffi.Void> viewer,
) {
return _get_camera_model_matrix(
viewer,
);
}
late final _get_camera_model_matrixPtr = _lookup<
ffi.NativeFunction<
ffi.Pointer<ffi.Double> Function(
ffi.Pointer<ffi.Void>)>>('get_camera_model_matrix');
late final _get_camera_model_matrix = _get_camera_model_matrixPtr
.asFunction<ffi.Pointer<ffi.Double> Function(ffi.Pointer<ffi.Void>)>();
ffi.Pointer<ffi.Double> get_camera_view_matrix(
ffi.Pointer<ffi.Void> viewer,
) {
return _get_camera_view_matrix(
viewer,
);
}
late final _get_camera_view_matrixPtr = _lookup<
ffi.NativeFunction<
ffi.Pointer<ffi.Double> Function(
ffi.Pointer<ffi.Void>)>>('get_camera_view_matrix');
late final _get_camera_view_matrix = _get_camera_view_matrixPtr
.asFunction<ffi.Pointer<ffi.Double> Function(ffi.Pointer<ffi.Void>)>();
ffi.Pointer<ffi.Double> get_camera_projection_matrix(
ffi.Pointer<ffi.Void> viewer,
) {
return _get_camera_projection_matrix(
viewer,
);
}
late final _get_camera_projection_matrixPtr = _lookup<
ffi.NativeFunction<
ffi.Pointer<ffi.Double> Function(
ffi.Pointer<ffi.Void>)>>('get_camera_projection_matrix');
late final _get_camera_projection_matrix = _get_camera_projection_matrixPtr
.asFunction<ffi.Pointer<ffi.Double> Function(ffi.Pointer<ffi.Void>)>();
void set_camera_focal_length(
ffi.Pointer<ffi.Void> viewer,
double focalLength,
@@ -1266,6 +1322,23 @@ class NativeLibrary {
late final _set_camera_focus_distance = _set_camera_focus_distancePtr
.asFunction<void Function(ffi.Pointer<ffi.Void>, double)>();
void set_camera_manipulator_mode(
ffi.Pointer<ffi.Void> viewer,
int mode,
) {
return _set_camera_manipulator_mode(
viewer,
mode,
);
}
late final _set_camera_manipulator_modePtr = _lookup<
ffi.NativeFunction<
ffi.Void Function(ffi.Pointer<ffi.Void>,
ManipulatorMode)>>('set_camera_manipulator_mode');
late final _set_camera_manipulator_mode = _set_camera_manipulator_modePtr
.asFunction<void Function(ffi.Pointer<ffi.Void>, int)>();
int hide_mesh(
ffi.Pointer<ffi.Void> assetManager,
int asset,
@@ -2383,6 +2456,7 @@ typedef FreeFilamentResourceFromOwner = ffi.Pointer<
/// This header replicates most of the methods in FlutterFilamentApi.h, and is only intended to be used to generate client FFI bindings.
/// The intention is that calling one of these methods will call its respective method in FlutterFilamentApi.h, but wrapped in some kind of thread runner to ensure thread safety.
typedef EntityId = ffi.Int32;
typedef ManipulatorMode = ffi.Int32;
typedef FilamentRenderCallback = ffi.Pointer<
ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void> owner)>>;