add setCameraCulling method to set near/far culling plane and return vector_math:Frustum from planes returned by get_camera_frustum
This commit is contained in:
@@ -6,8 +6,12 @@ import 'package:flutter_filament/filament_controller.dart';
|
||||
|
||||
class CameraMatrixOverlay extends StatefulWidget {
|
||||
final FilamentController controller;
|
||||
final bool showProjectionMatrices;
|
||||
|
||||
const CameraMatrixOverlay({super.key, required this.controller});
|
||||
const CameraMatrixOverlay(
|
||||
{super.key,
|
||||
required this.controller,
|
||||
required this.showProjectionMatrices});
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => _CameraMatrixOverlayState();
|
||||
@@ -18,21 +22,36 @@ class _CameraMatrixOverlayState extends State<CameraMatrixOverlay> {
|
||||
String? _cameraPosition;
|
||||
String? _cameraRotation;
|
||||
|
||||
String? _cameraProjectionMatrix;
|
||||
String? _cameraCullingProjectionMatrix;
|
||||
|
||||
void _tick(Timer timer) async {
|
||||
var cameraPosition = await widget.controller.getCameraPosition();
|
||||
var cameraRotation = await widget.controller.getCameraRotation();
|
||||
|
||||
_cameraPosition =
|
||||
"${cameraPosition.storage.map((v) => v.toStringAsFixed(2))}";
|
||||
_cameraRotation =
|
||||
"${cameraRotation.storage.map((v) => v.toStringAsFixed(2))}";
|
||||
|
||||
if (widget.showProjectionMatrices) {
|
||||
var projMatrix = await widget.controller.getCameraProjectionMatrix();
|
||||
var cullingMatrix =
|
||||
await widget.controller.getCameraCullingProjectionMatrix();
|
||||
|
||||
_cameraProjectionMatrix =
|
||||
projMatrix.storage.map((v) => v.toStringAsFixed(2)).join(",");
|
||||
_cameraCullingProjectionMatrix =
|
||||
cullingMatrix.storage.map((v) => v.toStringAsFixed(2)).join(",");
|
||||
}
|
||||
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
void _updateTimer() {
|
||||
_cameraTimer?.cancel();
|
||||
if (widget.controller.hasViewer.value) {
|
||||
_cameraTimer =
|
||||
Timer.periodic(const Duration(milliseconds: 50), (timer) async {
|
||||
var cameraPosition = await widget.controller.getCameraPosition();
|
||||
var cameraRotation = await widget.controller.getCameraRotation();
|
||||
|
||||
_cameraPosition =
|
||||
"${cameraPosition.storage.map((v) => v.toStringAsFixed(2))}";
|
||||
_cameraRotation =
|
||||
"${cameraRotation.storage.map((v) => v.toStringAsFixed(2))}";
|
||||
|
||||
setState(() {});
|
||||
});
|
||||
_cameraTimer = Timer.periodic(const Duration(milliseconds: 50), _tick);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,6 +64,12 @@ class _CameraMatrixOverlayState extends State<CameraMatrixOverlay> {
|
||||
widget.controller.hasViewer.addListener(_updateTimer);
|
||||
}
|
||||
|
||||
@override
|
||||
void didUpdateWidget(CameraMatrixOverlay oldWidget) {
|
||||
super.didUpdateWidget(oldWidget);
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
@@ -59,7 +84,20 @@ class _CameraMatrixOverlayState extends State<CameraMatrixOverlay> {
|
||||
color: Colors.black.withOpacity(0.5),
|
||||
borderRadius: BorderRadius.circular(29)),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5),
|
||||
child: Text("Camera position : $_cameraPosition $_cameraRotation",
|
||||
style: const TextStyle(color: Colors.white, fontSize: 12)));
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text("Camera position : $_cameraPosition $_cameraRotation",
|
||||
style: const TextStyle(color: Colors.white, fontSize: 12)),
|
||||
widget.showProjectionMatrices
|
||||
? Text("Projection matrix : $_cameraProjectionMatrix",
|
||||
style: const TextStyle(color: Colors.white, fontSize: 12))
|
||||
: Container(),
|
||||
widget.showProjectionMatrices
|
||||
? Text("Culling matrix : $_cameraCullingProjectionMatrix",
|
||||
style: const TextStyle(color: Colors.white, fontSize: 12))
|
||||
: Container(),
|
||||
]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,6 +76,7 @@ class ExampleWidgetState extends State<ExampleWidget> {
|
||||
static FilamentEntity? directionalLight;
|
||||
|
||||
static bool loop = false;
|
||||
static final showProjectionMatrices = ValueNotifier<bool>(false);
|
||||
|
||||
late StreamSubscription _listener;
|
||||
|
||||
@@ -158,7 +159,11 @@ class ExampleWidgetState extends State<ExampleWidget> {
|
||||
? Container()
|
||||
: Padding(
|
||||
padding: const EdgeInsets.only(top: 40, left: 20, right: 20),
|
||||
child: CameraMatrixOverlay(controller: _filamentController!),
|
||||
child: ValueListenableBuilder(
|
||||
valueListenable: showProjectionMatrices,
|
||||
builder: (ctx, value, child) => CameraMatrixOverlay(
|
||||
controller: _filamentController!,
|
||||
showProjectionMatrices: value)),
|
||||
),
|
||||
_filamentController == null
|
||||
? Container()
|
||||
|
||||
@@ -15,8 +15,66 @@ class CameraSubmenu extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _CameraSubmenuState extends State<CameraSubmenu> {
|
||||
double _near = 0.05;
|
||||
double _far = 1000.0;
|
||||
|
||||
final _menuController = MenuController();
|
||||
|
||||
List<Widget> _cameraMenu() {
|
||||
return [
|
||||
MenuItemButton(
|
||||
closeOnActivate: false,
|
||||
onPressed: () async {
|
||||
ExampleWidgetState.showProjectionMatrices.value =
|
||||
!ExampleWidgetState.showProjectionMatrices.value;
|
||||
print("Set to ${ExampleWidgetState.showProjectionMatrices}");
|
||||
},
|
||||
child: Text(
|
||||
'${ExampleWidgetState.showProjectionMatrices.value ? "Hide" : "Display"} camera projection/culling projection matrices',
|
||||
style: TextStyle(
|
||||
fontWeight: ExampleWidgetState.showProjectionMatrices.value
|
||||
? FontWeight.bold
|
||||
: FontWeight.normal),
|
||||
),
|
||||
),
|
||||
SubmenuButton(
|
||||
menuChildren: [1.0, 7.0, 14.0, 28.0, 56.0]
|
||||
.map((v) => MenuItemButton(
|
||||
onPressed: () {
|
||||
widget.controller.setCameraFocalLength(v);
|
||||
},
|
||||
child: Text(
|
||||
v.toStringAsFixed(2),
|
||||
),
|
||||
))
|
||||
.toList(),
|
||||
child: const Text("Set camera focal length")),
|
||||
SubmenuButton(
|
||||
menuChildren: [0.05, 0.1, 1.0, 10.0, 100.0]
|
||||
.map((v) => MenuItemButton(
|
||||
onPressed: () {
|
||||
_near = v;
|
||||
widget.controller.setCameraCulling(_near, _far);
|
||||
},
|
||||
child: Text(
|
||||
v.toStringAsFixed(2),
|
||||
),
|
||||
))
|
||||
.toList(),
|
||||
child: const Text("Set near")),
|
||||
SubmenuButton(
|
||||
menuChildren: [5.0, 50.0, 500.0, 1000.0, 100000.0]
|
||||
.map((v) => MenuItemButton(
|
||||
onPressed: () {
|
||||
_far = v;
|
||||
widget.controller.setCameraCulling(_near, _far);
|
||||
},
|
||||
child: Text(
|
||||
v.toStringAsFixed(2),
|
||||
),
|
||||
))
|
||||
.toList(),
|
||||
child: const Text("Set far")),
|
||||
MenuItemButton(
|
||||
onPressed: () async {
|
||||
widget.controller.setCameraPosition(1.0, 1.0, -1.0);
|
||||
@@ -80,7 +138,21 @@ class _CameraSubmenuState extends State<CameraSubmenu> {
|
||||
closeOnActivate: false,
|
||||
onPressed: () async {
|
||||
var frustum = await widget.controller.getCameraFrustum();
|
||||
await showDialog(
|
||||
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(
|
||||
@@ -88,8 +160,10 @@ class _CameraSubmenuState extends State<CameraSubmenu> {
|
||||
height: 300,
|
||||
width: 300,
|
||||
color: Colors.white,
|
||||
child: Text(frustum.toString())));
|
||||
child:
|
||||
Text("Frustum plane normals : $normalString ")));
|
||||
});
|
||||
_menuController.close();
|
||||
},
|
||||
child: const Text("Get frustum")),
|
||||
SubmenuButton(
|
||||
@@ -164,6 +238,7 @@ class _CameraSubmenuState extends State<CameraSubmenu> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SubmenuButton(
|
||||
controller: _menuController,
|
||||
menuChildren: _cameraMenu(),
|
||||
child: const Text("Camera"),
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user