expose getters for near/far culling distance and clean up example project for more readability on frustum

This commit is contained in:
Nick Fisher
2023-12-17 15:17:17 +08:00
parent 8c3d113ab4
commit 3e368e1a31
9 changed files with 147 additions and 62 deletions

View File

@@ -3,6 +3,7 @@ import 'dart:async';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:flutter_filament/filament_controller.dart'; import 'package:flutter_filament/filament_controller.dart';
import 'package:vector_math/vector_math_64.dart' as v;
class CameraMatrixOverlay extends StatefulWidget { class CameraMatrixOverlay extends StatefulWidget {
final FilamentController controller; final FilamentController controller;
@@ -43,6 +44,7 @@ class _CameraMatrixOverlayState extends State<CameraMatrixOverlay> {
projMatrix.storage.map((v) => v.toStringAsFixed(2)).join(","); projMatrix.storage.map((v) => v.toStringAsFixed(2)).join(",");
_cameraCullingProjectionMatrix = _cameraCullingProjectionMatrix =
cullingMatrix.storage.map((v) => v.toStringAsFixed(2)).join(","); cullingMatrix.storage.map((v) => v.toStringAsFixed(2)).join(",");
_getFrustum();
} }
setState(() {}); setState(() {});
@@ -55,6 +57,12 @@ class _CameraMatrixOverlayState extends State<CameraMatrixOverlay> {
} }
} }
v.Frustum? _frustum;
void _getFrustum() async {
_frustum = await widget.controller.getCameraFrustum();
}
@override @override
void initState() { void initState() {
super.initState(); super.initState();
@@ -87,17 +95,50 @@ class _CameraMatrixOverlayState extends State<CameraMatrixOverlay> {
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: <Widget>[
Text("Camera position : $_cameraPosition $_cameraRotation", Text("Camera position : $_cameraPosition $_cameraRotation",
style: const TextStyle(color: Colors.white, fontSize: 12)), style:
widget.showProjectionMatrices const TextStyle(color: Colors.white, fontSize: 10)),
? Text("Projection matrix : $_cameraProjectionMatrix", // widget.showProjectionMatrices
style: const TextStyle(color: Colors.white, fontSize: 12)) // ? Text("Projection matrix : $_cameraProjectionMatrix",
: Container(), // style: const TextStyle(color: Colors.white, fontSize: 12))
widget.showProjectionMatrices // : Container(),
? Text("Culling matrix : $_cameraCullingProjectionMatrix", // widget.showProjectionMatrices
style: const TextStyle(color: Colors.white, fontSize: 12)) // ? Text("Culling matrix : $_cameraCullingProjectionMatrix",
: Container(), // style: const TextStyle(color: Colors.white, fontSize: 12))
])); // : Container(),
widget.showProjectionMatrices
? const Text("Frustum matrix",
style: TextStyle(color: Colors.white, fontSize: 10))
: Container()
] +
(_frustum == null
? []
: [
_frustum!.plane0,
_frustum!.plane1,
_frustum!.plane2,
_frustum!.plane3,
_frustum!.plane4,
_frustum!.plane5
]
.map((plane) => Row(
children: [
plane.normal.x,
plane.normal.y,
plane.normal.z,
plane.constant
]
.map((v) => Text(
v.toStringAsFixed(2) + " ",
style: const TextStyle(
color: Colors.white,
fontSize: 10),
textAlign: TextAlign.center,
))
.cast<Widget>()
.toList()))
.cast<Widget>()
.toList())));
} }
} }

View File

@@ -15,8 +15,20 @@ class CameraSubmenu extends StatefulWidget {
} }
class _CameraSubmenuState extends State<CameraSubmenu> { class _CameraSubmenuState extends State<CameraSubmenu> {
double _near = 0.05; double? _near;
double _far = 1000.0; double? _far;
@override
void initState() {
super.initState();
widget.controller.getCameraCullingNear().then((v) {
_near = v;
widget.controller.getCameraCullingFar().then((v) {
_far = v;
setState(() {});
});
});
}
final _menuController = MenuController(); final _menuController = MenuController();
@@ -30,7 +42,7 @@ class _CameraSubmenuState extends State<CameraSubmenu> {
print("Set to ${ExampleWidgetState.showProjectionMatrices}"); print("Set to ${ExampleWidgetState.showProjectionMatrices}");
}, },
child: Text( child: Text(
'${ExampleWidgetState.showProjectionMatrices.value ? "Hide" : "Display"} camera projection/culling projection matrices', '${ExampleWidgetState.showProjectionMatrices.value ? "Hide" : "Display"} camera frustum',
style: TextStyle( style: TextStyle(
fontWeight: ExampleWidgetState.showProjectionMatrices.value fontWeight: ExampleWidgetState.showProjectionMatrices.value
? FontWeight.bold ? FontWeight.bold
@@ -54,7 +66,9 @@ class _CameraSubmenuState extends State<CameraSubmenu> {
.map((v) => MenuItemButton( .map((v) => MenuItemButton(
onPressed: () { onPressed: () {
_near = v; _near = v;
widget.controller.setCameraCulling(_near, _far); print("Setting camera culling to $_near $_far!");
widget.controller.setCameraCulling(_near!, _far!);
}, },
child: Text( child: Text(
v.toStringAsFixed(2), v.toStringAsFixed(2),
@@ -67,7 +81,8 @@ class _CameraSubmenuState extends State<CameraSubmenu> {
.map((v) => MenuItemButton( .map((v) => MenuItemButton(
onPressed: () { onPressed: () {
_far = v; _far = v;
widget.controller.setCameraCulling(_near, _far); print("Setting camera culling to $_near! $_far");
widget.controller.setCameraCulling(_near!, _far!);
}, },
child: Text( child: Text(
v.toStringAsFixed(2), v.toStringAsFixed(2),
@@ -79,7 +94,14 @@ class _CameraSubmenuState extends State<CameraSubmenu> {
onPressed: () async { onPressed: () async {
widget.controller.setCameraPosition(1.0, 1.0, -1.0); widget.controller.setCameraPosition(1.0, 1.0, -1.0);
}, },
child: const Text('Move to 1, 1, -1'), child: const Text('Set position to 1, 1, -1 (leave rotation as-is)'),
),
MenuItemButton(
onPressed: () async {
widget.controller.setCameraPosition(0.0, 0.0, 0.0);
widget.controller.setCameraRotation(0, 0.0, 1.0, 0.0);
},
child: const Text('Move to 0,0,0, facing towards 0,0,-1'),
), ),
MenuItemButton( MenuItemButton(
onPressed: () async { onPressed: () async {
@@ -130,38 +152,6 @@ class _CameraSubmenuState extends State<CameraSubmenu> {
}); });
}, },
child: const Text("Get projection matrix")), child: const Text("Get projection matrix")),
MenuItemButton(
closeOnActivate: false,
onPressed: () async {
var frustum = await widget.controller.getCameraFrustum();
var normalString = [
frustum.plane0,
frustum.plane1,
frustum.plane2,
frustum.plane3,
frustum.plane4,
frustum.plane5
]
.map((plane) =>
plane.normal.storage
.map((v) => v.toStringAsFixed(2))
.join(",") +
",${plane.constant}")
.join("\n");
showDialog(
context: context,
builder: (ctx) {
return Center(
child: Container(
height: 300,
width: 300,
color: Colors.white,
child:
Text("Frustum plane normals : $normalString ")));
});
_menuController.close();
},
child: const Text("Get frustum")),
SubmenuButton( SubmenuButton(
menuChildren: ManipulatorMode.values.map((mm) { menuChildren: ManipulatorMode.values.map((mm) {
return MenuItemButton( return MenuItemButton(
@@ -233,6 +223,9 @@ class _CameraSubmenuState extends State<CameraSubmenu> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
if (_near == null || _far == null) {
return Container();
}
return SubmenuButton( return SubmenuButton(
controller: _menuController, controller: _menuController,
menuChildren: _cameraMenu(), menuChildren: _cameraMenu(),

View File

@@ -109,6 +109,8 @@ namespace polyvox
void setCameraProjectionMatrix(const double *const matrix, double near, double far); void setCameraProjectionMatrix(const double *const matrix, double near, double far);
void setCameraFocalLength(float focalLength); void setCameraFocalLength(float focalLength);
void setCameraCulling(double near, double far); void setCameraCulling(double near, double far);
double getCameraCullingNear();
double getCameraCullingFar();
void setCameraFocusDistance(float focusDistance); void setCameraFocusDistance(float focusDistance);
void setCameraManipulatorOptions(filament::camutils::Mode mode, double orbitSpeedX, double orbitSpeedY, double zoomSpeed); void setCameraManipulatorOptions(filament::camutils::Mode mode, double orbitSpeedX, double orbitSpeedY, double zoomSpeed);
void grabBegin(float x, float y, bool pan); void grabBegin(float x, float y, bool pan);

View File

@@ -157,6 +157,8 @@ extern "C"
FLUTTER_PLUGIN_EXPORT const double *const get_camera_projection_matrix(const void *const viewer); FLUTTER_PLUGIN_EXPORT const double *const get_camera_projection_matrix(const void *const viewer);
FLUTTER_PLUGIN_EXPORT void set_camera_projection_matrix(const void *const viewer, const double *const matrix, double near, double far); FLUTTER_PLUGIN_EXPORT void set_camera_projection_matrix(const void *const viewer, const double *const matrix, double near, double far);
FLUTTER_PLUGIN_EXPORT void set_camera_culling(const void *const viewer, double near, double far); FLUTTER_PLUGIN_EXPORT void set_camera_culling(const void *const viewer, double near, double far);
FLUTTER_PLUGIN_EXPORT double get_camera_culling_near(const void *const viewer);
FLUTTER_PLUGIN_EXPORT double get_camera_culling_far(const void *const viewer);
FLUTTER_PLUGIN_EXPORT const double *const get_camera_culling_projection_matrix(const void *const viewer); FLUTTER_PLUGIN_EXPORT const double *const get_camera_culling_projection_matrix(const void *const viewer);
FLUTTER_PLUGIN_EXPORT const double *const get_camera_frustum(const void *const viewer); FLUTTER_PLUGIN_EXPORT const double *const get_camera_frustum(const void *const viewer);
FLUTTER_PLUGIN_EXPORT void set_camera_focal_length(const void *const viewer, float focalLength); FLUTTER_PLUGIN_EXPORT void set_camera_focal_length(const void *const viewer, float focalLength);

View File

@@ -757,8 +757,17 @@ namespace polyvox
Camera &cam = _view->getCamera(); Camera &cam = _view->getCamera();
_near = near; _near = near;
_far = far; _far = far;
cam.setLensProjection(_cameraFocalLength, 1.0f, _near, cam.setLensProjection(_cameraFocalLength, 1.0f, _near, _far);
_far); Log("Set lens projection to focal length %f, near %f and far %f", _cameraFocalLength, _near, _far);
}
double FilamentViewer::getCameraCullingNear() {
Camera &cam = _view->getCamera();
return cam.getNear();
}
double FilamentViewer::getCameraCullingFar() {
Camera &cam = _view->getCamera();
return cam.getCullingFar();
} }
/// ///

View File

@@ -158,6 +158,14 @@ extern "C"
((FilamentViewer *)viewer)->setCameraCulling(near, far); ((FilamentViewer *)viewer)->setCameraCulling(near, far);
} }
double get_camera_culling_near(const void *const viewer) {
return ((FilamentViewer*)viewer)->getCameraCullingNear();
}
double get_camera_culling_far(const void *const viewer) {
return ((FilamentViewer*)viewer)->getCameraCullingFar();
}
const double *const get_camera_frustum(const void *const viewer) const double *const get_camera_frustum(const void *const viewer)
{ {
const auto frustum = ((FilamentViewer *)viewer)->getCameraFrustum(); const auto frustum = ((FilamentViewer *)viewer)->getCameraFrustum();
@@ -165,10 +173,11 @@ extern "C"
double *array = (double *)calloc(24, sizeof(double)); double *array = (double *)calloc(24, sizeof(double));
for (int i = 0; i < 6; i++) for (int i = 0; i < 6; i++)
{ {
array[i * 4] = planes[i].x; auto plane = planes[i];
array[i * 4 + 1] = planes[i].y; array[i * 4] = double(plane.x);
array[i * 4 + 2] = planes[i].z; array[i * 4 + 1] = double(plane.y);
array[i * 4 + 3] = planes[i].w; array[i * 4 + 2] = double(plane.z);
array[i * 4 + 3] = double(plane.w);
} }
return array; return array;

View File

@@ -345,10 +345,20 @@ abstract class FilamentController {
Future setCameraFocalLength(double focalLength); Future setCameraFocalLength(double focalLength);
/// ///
/// Sets the near/far culling planes for the active camera. Default values are 0.05/1000.0. See Camera.h for details. /// Sets the distance (in world units) to the near/far planes for the active camera. Default values are 0.05/1000.0. See Camera.h for details.
/// ///
Future setCameraCulling(double near, double far); Future setCameraCulling(double near, double far);
///
/// Get the distance (in world units) to the near culling plane for the active camera.
///
Future<double> getCameraCullingNear();
///
/// Get the distance (in world units) to the far culling plane for the active camera.
///
Future<double> getCameraCullingFar();
/// ///
/// Sets the focus distance for the camera. /// Sets the focus distance for the camera.
/// ///

View File

@@ -867,6 +867,16 @@ class FilamentControllerFFI extends FilamentController {
set_camera_culling(_viewer!, near, far); set_camera_culling(_viewer!, near, far);
} }
@override
Future<double> getCameraCullingNear() async {
return get_camera_culling_near(_viewer!);
}
@override
Future<double> getCameraCullingFar() async {
return get_camera_culling_far(_viewer!);
}
@override @override
Future setCameraFocusDistance(double focusDistance) async { Future setCameraFocusDistance(double focusDistance) async {
if (_viewer == null) { if (_viewer == null) {
@@ -1147,10 +1157,7 @@ class FilamentControllerFFI extends FilamentController {
} }
var arrayPtr = get_camera_frustum(_viewer!); var arrayPtr = get_camera_frustum(_viewer!);
var doubleList = arrayPtr.asTypedList(24); var doubleList = arrayPtr.asTypedList(24);
var planeNormals = []; print(doubleList);
for (int i = 0; i < 6; i++) {
planeNormals.add(Vector3.array(doubleList.sublist(i * 3, (i + 1) * 3)));
}
var frustum = Frustum(); var frustum = Frustum();
frustum.plane0.setFromComponents( frustum.plane0.setFromComponents(
@@ -1165,7 +1172,7 @@ class FilamentControllerFFI extends FilamentController {
doubleList[16], doubleList[17], doubleList[18], doubleList[19]); doubleList[16], doubleList[17], doubleList[18], doubleList[19]);
frustum.plane5.setFromComponents( frustum.plane5.setFromComponents(
doubleList[20], doubleList[21], doubleList[22], doubleList[23]); doubleList[20], doubleList[21], doubleList[22], doubleList[23]);
flutter_filament_free(arrayPtr.cast<Void>());
return frustum; return frustum;
} }

View File

@@ -651,6 +651,18 @@ external void set_camera_culling(
double far, double far,
); );
@ffi.Native<ffi.Double Function(ffi.Pointer<ffi.Void>)>(
symbol: 'get_camera_culling_near', assetId: 'flutter_filament_plugin')
external double get_camera_culling_near(
ffi.Pointer<ffi.Void> viewer,
);
@ffi.Native<ffi.Double Function(ffi.Pointer<ffi.Void>)>(
symbol: 'get_camera_culling_far', assetId: 'flutter_filament_plugin')
external double get_camera_culling_far(
ffi.Pointer<ffi.Void> viewer,
);
@ffi.Native<ffi.Pointer<ffi.Double> Function(ffi.Pointer<ffi.Void>)>( @ffi.Native<ffi.Pointer<ffi.Double> Function(ffi.Pointer<ffi.Void>)>(
symbol: 'get_camera_culling_projection_matrix', symbol: 'get_camera_culling_projection_matrix',
assetId: 'flutter_filament_plugin') assetId: 'flutter_filament_plugin')