From e6d555607719c7aceb4ec3207c5a6c0fd8d1a047 Mon Sep 17 00:00:00 2001 From: Nick Fisher Date: Thu, 1 Sep 2022 14:26:31 +1000 Subject: [PATCH] add setter for frame interval, separate FilamentController initialization from widget --- ios/src/FilamentViewer.cpp | 17 +++++-- ios/src/FilamentViewer.hpp | 3 +- ios/src/PolyvoxFilamentApi.cpp | 12 ++++- ios/src/PolyvoxFilamentApi.hpp | 3 +- lib/filament_controller.dart | 20 +++++++- lib/filament_widget.dart | 19 ++++--- lib/gesture_detecting_filament_view.dart | 30 +++++------ lib/transform_manager.dart | 63 ++++++++++++++++++++++++ 8 files changed, 134 insertions(+), 33 deletions(-) create mode 100644 lib/transform_manager.dart diff --git a/ios/src/FilamentViewer.cpp b/ios/src/FilamentViewer.cpp index 6e686643..8c2bf08f 100644 --- a/ios/src/FilamentViewer.cpp +++ b/ios/src/FilamentViewer.cpp @@ -149,12 +149,12 @@ FilamentViewer::FilamentViewer(void *layer, LoadResource loadResource, Log("Engine created"); _renderer = _engine->createRenderer(); - - _renderer->setDisplayInfo({.refreshRate = 60.0f, + float fr = 60.0f; + _renderer->setDisplayInfo({.refreshRate = fr, .presentationDeadlineNanos = (uint64_t)0, .vsyncOffsetNanos = (uint64_t)0}); Renderer::FrameRateOptions fro; - fro.interval = 60; + fro.interval = 1 / fr; _renderer->setFrameRateOptions(fro); _scene = _engine->createScene(); @@ -247,6 +247,13 @@ static constexpr float4 sFullScreenTriangleVertices[3] = { static const uint16_t sFullScreenTriangleIndices[3] = {0, 1, 2}; +void FilamentViewer::setFrameInterval(float frameInterval) { + Renderer::FrameRateOptions fro; + fro.interval = frameInterval; + _renderer->setFrameRateOptions(fro); + Log("Set framerate interval to %f", frameInterval); +} + void FilamentViewer::createImageRenderable() { if (_imageEntity) @@ -618,7 +625,7 @@ void FilamentViewer::loadIbl(const char *const iblPath) { } } -void FilamentViewer::render() { +void FilamentViewer::render(uint64_t frameTimeInNanos) { if (!_view || !_mainCamera || !_swapChain) { Log("Not ready for rendering"); @@ -637,7 +644,7 @@ void FilamentViewer::render() { } // Render the scene, unless the renderer wants to skip the frame. - if (_renderer->beginFrame(_swapChain)) { + if (_renderer->beginFrame(_swapChain, frameTimeInNanos)) { _renderer->render(_view); _renderer->endFrame(); } diff --git a/ios/src/FilamentViewer.hpp b/ios/src/FilamentViewer.hpp index 4b6bd6f7..01ee3c9e 100644 --- a/ios/src/FilamentViewer.hpp +++ b/ios/src/FilamentViewer.hpp @@ -61,7 +61,8 @@ namespace polyvox { void clearAssets(); void updateViewportAndCameraProjection(int height, int width, float scaleFactor); - void render(); + void render(uint64_t frameTimeInNanos); + void setFrameInterval(float interval); bool setFirstCamera(SceneAsset* asset); bool setCamera(SceneAsset* asset, const char* nodeName); diff --git a/ios/src/PolyvoxFilamentApi.cpp b/ios/src/PolyvoxFilamentApi.cpp index a4d4acec..8f3e7841 100644 --- a/ios/src/PolyvoxFilamentApi.cpp +++ b/ios/src/PolyvoxFilamentApi.cpp @@ -69,9 +69,17 @@ extern "C" { } void render( - void* viewer + void* viewer, + uint64_t frameTimeInNanos ) { - ((FilamentViewer*)viewer)->render(); + ((FilamentViewer*)viewer)->render(frameTimeInNanos); + } + + void set_frame_interval( + void* viewer, + float frameInterval + ) { + ((FilamentViewer*)viewer)->setFrameInterval(frameInterval); } void destroy_swap_chain(void* viewer) { diff --git a/ios/src/PolyvoxFilamentApi.hpp b/ios/src/PolyvoxFilamentApi.hpp index 46b8a08f..c0f82c1a 100644 --- a/ios/src/PolyvoxFilamentApi.hpp +++ b/ios/src/PolyvoxFilamentApi.hpp @@ -16,8 +16,9 @@ void remove_ibl(void* viewer); void* load_glb(void* viewer, const char* assetPath); void* load_gltf(void* viewer, const char* assetPath, const char* relativePath); bool set_camera(void* viewer, void* asset, const char* nodeName); -void render(void* viewer); +void render(void* viewer, uint64_t frameTimeInNanos); void destroy_swap_chain(void* viewer); +void set_frame_interval(void* viewer, float interval); void* get_renderer(void* viewer); void update_viewport_and_camera_projection(void* viewer, int width, int height, float scaleFactor); diff --git a/lib/filament_controller.dart b/lib/filament_controller.dart index c2fe6b9e..f21bc82e 100644 --- a/lib/filament_controller.dart +++ b/lib/filament_controller.dart @@ -7,7 +7,10 @@ typedef FilamentAsset = int; abstract class FilamentController { late int textureId; Future get initialized; - Future initialize(int width, int height, { double devicePixelRatio = 1}); + Stream get onInitializationRequested; + Future initialize(); + Future createTextureViewer(int width, int height, { double devicePixelRatio = 1}); + Future setFrameRate(int framerate); Future resize(int width, int height, { double devicePixelRatio = 1, double contentScaleFactor=1}); Future setBackgroundImage(String path); Future loadSkybox(String skyboxPath); @@ -64,6 +67,10 @@ class PolyvoxFilamentController extends FilamentController { late MethodChannel _channel = MethodChannel("app.polyvox.filament/event"); late double _devicePixelRatio; + + final _onInitRequestedController = StreamController(); + Stream get onInitializationRequested => _onInitRequestedController.stream; + final _initialized = Completer(); Future get initialized => _initialized.future; @@ -74,7 +81,16 @@ class PolyvoxFilamentController extends FilamentController { }); } - Future initialize(int width, int height, { double devicePixelRatio=1 }) async { + Future initialize() async { + _onInitRequestedController.add(true); + return _initialized.future; + } + + Future setFrameRate(int framerate) async { + await _channel.invokeMethod("setFrameInterval", 1/ framerate); + } + + Future createTextureViewer(int width, int height, { double devicePixelRatio=1 }) async { _devicePixelRatio = devicePixelRatio; textureId = await _channel.invokeMethod("initialize", [width*devicePixelRatio, height*devicePixelRatio]); _initialized.complete(true); diff --git a/lib/filament_widget.dart b/lib/filament_widget.dart index 79bfdfaf..8e01a317 100644 --- a/lib/filament_widget.dart +++ b/lib/filament_widget.dart @@ -55,14 +55,17 @@ class _FilamentWidgetState extends State { @override void initState() { - WidgetsBinding.instance.addPostFrameCallback((timeStamp) async { - var size = ((context.findRenderObject()) as RenderBox).size; - print("Requesting texture creation for Filament of size $size"); - await widget.controller - .initialize(size.width.toInt(), size.height.toInt()); - print("Filament texture available"); - setState(() { - _ready = true; + + widget.controller.onInitializationRequested.listen((_) { + WidgetsBinding.instance.addPostFrameCallback((timeStamp) async { + var size = ((context.findRenderObject()) as RenderBox).size; + print("Requesting texture creation for Filament of size $size"); + await widget.controller + .createTextureViewer(size.width.toInt(), size.height.toInt()); + print("Filament texture available"); + setState(() { + _ready = true; + }); }); }); diff --git a/lib/gesture_detecting_filament_view.dart b/lib/gesture_detecting_filament_view.dart index a9cf5382..321d9f51 100644 --- a/lib/gesture_detecting_filament_view.dart +++ b/lib/gesture_detecting_filament_view.dart @@ -95,20 +95,22 @@ class _GestureDetectingFilamentViewState }, child: FilamentWidget(controller: widget.controller))), widget.showControls - ? Align(alignment:Alignment.bottomRight, child:GestureDetector( - onTap: () { - setState(() { - _rotate = !_rotate; - _setFunction(); - }); - }, - child: Container( - padding: const EdgeInsets.all(50), - child: Icon(Icons.rotate_90_degrees_ccw, - color: _rotate - ? Colors.white - : Colors.white.withOpacity(0.5))), - )) + ? Align( + alignment: Alignment.bottomRight, + child: GestureDetector( + onTap: () { + setState(() { + _rotate = !_rotate; + _setFunction(); + }); + }, + child: Container( + padding: const EdgeInsets.all(50), + child: Icon(Icons.rotate_90_degrees_ccw, + color: _rotate + ? Colors.white + : Colors.white.withOpacity(0.5))), + )) : Container() ]); } diff --git a/lib/transform_manager.dart b/lib/transform_manager.dart new file mode 100644 index 00000000..d9a21ee1 --- /dev/null +++ b/lib/transform_manager.dart @@ -0,0 +1,63 @@ + +// import 'package:flutter/widgets.dart'; +// import 'package:polyvox_filament/filament_controller.dart'; +// import 'package:polyvox_filament/filament_controller.dart'; +// import 'package:vector_math/vector_math_64.dart'; + +// class Position { +// final double x; +// final double y; +// final double z; +// Position(this.x, this.y, this.z); +// Position copy({double? x, double? y, double? z}) { +// return Position(x ?? this.x, y ?? this.y, z ?? this.z); +// } + +// factory Position.zero() { +// return Position(0,0,0); +// } +// } + +// class Rotation { +// final double rads; +// final double x; +// final double y; +// final double z; +// Rotation(this.x, this.y, this.z, this.rads); +// Rotation copy({double? rads, double? x, double? y, double? z}) { +// return Rotation(x ?? this.x, y ?? this.y, z ?? this.z, rads ?? this.rads); +// } + +// factory Rotation.zero() { +// return Rotation(0, 1,0,0); +// } + +// } + + + +// /// +// /// Handles local transforms for assets/cameras. +// /// +// class TransformManager { + +// final FilamentController _controller; + +// Matrix4 transform = Matrix4.identity(); + +// TransformManager(this._controller); + +// void scale(double scale) { +// transform.scale(scale, scale, scale); +// } + + +// void translate(double x, double y, double z) { +// transform.translate(x,y,z); +// } + +// void rotate(double x, double y, double z) { +// transform.rotate(Vector3(x,y,z)); +// } + +// } \ No newline at end of file