Compare commits

..

99 Commits

Author SHA1 Message Date
Nick Fisher
76f723c497 Makefile/README updates 2023-11-09 12:24:22 +08:00
Nick Fisher
a1f2b245ff move Makefile to macos folder and update instructions 2023-11-09 12:12:04 +08:00
Daverin
672952f8a0 cherry-pick a0671a9b6f084ee02f1f5b7000e34f884fd27241
cherry-pick a0671a9b6f084ee02f1f5b7000e34f884fd27241
2023-11-09 12:04:24 +08:00
Nick Fisher
395de95d37 more methods for projection/culling projection matrices & frustum 2023-11-09 11:41:40 +08:00
Nick Fisher
e1141098d0 example project fixes 2023-11-09 11:22:56 +08:00
Nick Fisher
2db353cc3b add getCameraFrustum() and getCameraProjectionMatrix() 2023-11-08 20:30:14 +08:00
Nick Fisher
962d53442f update macOS 2023-11-08 17:47:21 +08:00
Nick Fisher
af543f46b2 add onLoad/onUnload streams 2023-11-08 17:47:11 +08:00
Nick Fisher
7b0dcf2c1c update integration test 2023-11-08 17:46:23 +08:00
Nick Fisher
e15722b15b fix Android example project 2023-11-07 15:12:36 +08:00
Nick Fisher
0748323316 add free() method for stability on Windows 2023-11-07 17:54:57 +11:00
Nick Fisher
e42d5e6263 correctly initialize manipulatorMode to default 2023-11-07 17:49:21 +11:00
Nick Fisher
a2543aa69d fix hasViewer check in example ControllerMenu 2023-11-07 17:26:15 +11:00
Nick Fisher
921f654978 update generated_bindings with consistent assetId flutter_filament_plugin 2023-11-07 17:25:36 +11:00
Nick Fisher
914b2fad94 remove old web build folder 2023-11-07 16:58:20 +11:00
Nick Fisher
03fe1a097b update pubspec.lock 2023-11-07 13:15:27 +08:00
Nick Fisher
b5fffe617e use ffi-native for generated bindings 2023-11-07 13:15:12 +08:00
Nick Fisher
60ed8443b2 example project fixes 2023-11-07 13:14:46 +08:00
Nick Fisher
2882f9739d Merge pull request #13 from odd-io/feature-code-quality
Refactored /lib code to reduce analyze warnings
2023-11-07 08:42:49 +08:00
Nick Fisher
59936c6220 Merge pull request #12 from odd-io/feature-add-github-actions
Add GitHub Actions workflows
2023-11-07 08:41:11 +08:00
LukasPoque
509a480603 add GitHub Actions workflows for Dart Analyzer and
PubDev Score calculation
2023-11-06 17:35:31 +01:00
LukasPoque
93693788ac fix dart docs to match the method args naming 2023-11-06 17:19:40 +01:00
LukasPoque
793bc6ca32 Refactor gesture type enum to use camelCase 2023-11-06 17:13:25 +01:00
LukasPoque
9862f39bcd fix lint warnings through ignore lines 2023-11-06 17:13:13 +01:00
LukasPoque
1c55526463 Refactor FilamentControllerFFI class to use entity
instead of asset  to match overridden method
2023-11-06 17:12:03 +01:00
LukasPoque
229357d8b9 Change print to log to follow bp 2023-11-06 16:55:52 +01:00
LukasPoque
94680c6db7 Fix typos and comments in FilamentControllerFFI
and AnimationBuilder classes
2023-11-06 16:41:07 +01:00
LukasPoque
851d2df84e Run dart fix in lib 2023-11-06 14:27:16 +01:00
Nick Fisher
8120cbea6d properly free memory in model/view matrix getters 2023-11-03 22:43:04 +08:00
Nick Fisher
48be185bba start using menu for example project & add methods for getting camera model/view matrices 2023-11-03 22:17:39 +08:00
Nick Fisher
f5cc7a8174 update example project 2023-11-03 17:28:25 +08:00
Nick Fisher
58a9542121 add model/view matrix getters & manipulator options 2023-11-03 15:20:15 +08:00
Nick Fisher
83469e93b9 add new interface methods for camera 2023-11-03 13:18:04 +08:00
Nick Fisher
7700ead724 remove delay on resume 2023-11-03 13:10:22 +08:00
Nick Fisher
5ba5d7d6ea add mutex for animation updates 2023-11-03 13:10:02 +08:00
Nick Fisher
6671ced45d add delay to setRendering when coming back from inactive 2023-11-02 22:05:57 +08:00
Nick Fisher
a366867d91 correctly complete completer when resizing while unmounted and log any errors on resize 2023-11-01 14:05:49 +08:00
Nick Fisher
214510b595 remove wasm_ffi dependency 2023-11-01 13:47:25 +08:00
Nick Fisher
aa6ad3cc4b fix integration test 2023-10-28 15:21:04 +08:00
Nick Fisher
23364ba9a2 Merge branch 'develop' of github.com:nmfisher/polyvox_filament into develop 2023-10-28 15:17:32 +08:00
Nick Fisher
78094fbf61 update example project 2023-10-27 20:58:33 +08:00
Nick Fisher
4280172767 remove old Method Channel FilamentController 2023-10-27 20:57:33 +08:00
Nick Fisher
4a5c62a306 move rect ValueNotifier to interface 2023-10-27 20:57:13 +08:00
Nick Fisher
40485081bc require createViewer to be specified manually 2023-10-27 20:32:16 +08:00
Nick Fisher
42c0d96e56 add buster to example project 2023-10-27 00:19:17 +11:00
Nick Fisher
59c2f8d125 add ARCHITECTURE.md 2023-10-26 11:38:25 +08:00
Nick Fisher
cf25d8f0d7 update macOS 2023-10-26 11:12:31 +08:00
Nick Fisher
8b9e6a2b3a rename plugin from PolyvoxFilament to FlutterFilament
rename plugin from PolyvoxFilament to FlutterFilament
2023-10-26 14:08:20 +11:00
Nick Fisher
b42d31a773 fix window minimization issue on Windows 2023-10-26 12:49:24 +11:00
Nick Fisher
53c908dd0d use short timeout on front-end for resizing on Windows 2023-10-26 12:38:52 +11:00
Nick Fisher
6399ca41ed use pixelRatio properly 2023-10-26 11:33:44 +11:00
Nick Fisher
a56943fb86 use pixelRatio properly 2023-10-26 11:27:42 +11:00
Nick Fisher
38b58b6d8f set pixel ratio in FilamentWidget 2023-10-26 11:19:35 +11:00
Nick Fisher
0fdbf0b5be don't hide backing window when resizing 2023-10-26 02:14:55 +11:00
Nick Fisher
2fd6f44785 fixes for window resizing on Windows 2023-10-26 02:10:22 +11:00
Nick Fisher
0928d9d273 rendering correctly with backing window but some issues re pixel density, scroll & foregrounding on start 2023-10-25 17:52:37 +11:00
Nick Fisher
8cea106b30 refactor Windows classes to separate EGL/WGL/Backing Window 2023-10-25 13:11:58 +11:00
Nick Fisher
c4245b0dd3 remove duplicate EGL_ALPHA_SIZE on Windows 2023-10-24 13:23:41 +11:00
Nick Fisher
2107a17219 update pubspec.lock 2023-10-24 12:29:00 +11:00
Nick Fisher
e39d75824e update Windows example project 2023-10-24 12:29:00 +11:00
Nick Fisher
3f988a119c FlutterAngleTexture invoke resize callback on size change, cleanup on destruction and call glFinish in RenderCallback
FlutterAngleTexture invoke resize callback on size change, cleanup on destruction and call glFinish in RenderCallback
move OpenGlTextureBuffer cleanup to destructor
2023-10-24 12:28:57 +11:00
Nick Fisher
435ed7bee6 don't use resize callback on Windows and use ListenableBuilder for texture ID changes
don't use resize callback on Windows and use ListenableBuilder for texture ID changes
2023-10-24 12:28:54 +11:00
Nick Fisher
537f0e1c8e change TextureDetails to ValueNotifier and add MethodChannel listener on Dart side for resize (Windows only) 2023-10-24 12:23:20 +11:00
Nick Fisher
65426aa075 update README 2023-10-24 12:21:33 +11:00
Nick Fisher
7c554e871f update Windows ANGLE libs 2023-10-24 12:21:11 +11:00
Nick Fisher
72c1cbdeb3 remove custom platform creation from FlutterAngleTexture 2023-10-23 01:36:20 +11:00
Nick Fisher
69a7a07ec7 remove custom platform creation from FlutterAngleTexture 2023-10-23 01:36:03 +11:00
Nick Fisher
0a612555b8 remove custom platform creation from FlutterAngleTexture 2023-10-23 01:35:45 +11:00
Nick Fisher
600905f7f2 remove custom platform creation 2023-10-23 01:35:21 +11:00
Nick Fisher
73db953564 don't show placeholder while resizing 2023-10-23 01:34:48 +11:00
Nick Fisher
8130319801 don't null out controller textureDetails while resizing 2023-10-23 01:34:20 +11:00
Nick Fisher
34542a29ca add flushAndWait call to destroySwapChain 2023-10-23 01:33:47 +11:00
Nick Fisher
d15aa66f78 remove unnecessary bluegl from Windows/ANGLE build 2023-10-22 17:46:09 +11:00
Nick Fisher
1e6f9dcc9d initialize various FilamentViewer pointers to nullptr 2023-10-22 17:45:48 +11:00
Nick Fisher
74cfe8d9a1 store driver when creating texture 2023-10-22 17:45:26 +11:00
Nick Fisher
2b9ddef5e7 use shared EGLContext for ANGLE on Windows 2023-10-22 17:45:09 +11:00
Nick Fisher
991e09df32 update gitattributes 2023-10-19 16:40:09 +08:00
Nick Fisher
2910c34ae5 update macos/Android GLES uberz 2023-10-19 16:39:50 +08:00
Nick Fisher
67c8e503b3 update README 2023-10-19 16:37:23 +08:00
Nick Fisher
ed3555c237 reorder morph animations according to actual mesh morph targets 2023-10-18 16:04:14 +08:00
Nick Fisher
50c47fe908 move LiveLinkFace-related data loaders to viewer project 2023-10-18 14:37:45 +08:00
Nick Fisher
721726d2d5 update macOS 2023-10-18 13:48:03 +08:00
Nick Fisher
b26500af20 change default value for wasRenderingOnInactive to true 2023-10-18 13:47:11 +08:00
Nick Fisher
482ab29f49 iterate over completed animations in reverse order 2023-10-18 10:40:56 +08:00
Nick Fisher
7ff6f6eaf7 don't resize on resume 2023-10-17 22:12:39 +08:00
Nick Fisher
73b2633f4d add permissions check to example project
add permission check to example project

add permission check to example project
2023-10-17 18:25:42 +08:00
Nick Fisher
7f7eb89a45 remove debug mode delay on Android 2023-10-17 18:25:41 +08:00
Nick Fisher
3640e27324 remove superseded resize method call handler
remove superseded resize method call handler
2023-10-17 18:25:38 +08:00
Nick Fisher
53b8d352da Merge branch 'develop' of github.com:nmfisher/polyvox_filament into develop 2023-10-17 08:57:49 +08:00
Nick Fisher
2553d854e9 replace isReadyForScene with hasViewer stream and update version number/CHANGELOG 2023-10-17 08:57:00 +08:00
Nick Fisher
7f9c5a0f2d (re)set rendering on all lifecycle changes 2023-10-17 08:55:49 +08:00
Nick Fisher
7718885781 update README 2023-10-17 00:55:51 +11:00
Nick Fisher
5bf21ceaf9 update README 2023-10-17 00:54:19 +11:00
Nick Fisher
d3f84f156a update README 2023-10-16 21:46:21 +08:00
Nick Fisher
4fe79e3b92 remove golden_toolkit from test dependency 2023-10-17 00:29:21 +11:00
Nick Fisher
2a5c863506 remove golden_toolkit from test dependency 2023-10-17 00:26:11 +11:00
Nick Fisher
837a2cebc7 different timeouts for resize in debug/release 2023-10-17 00:25:30 +11:00
Nick Fisher
6ab814114e rewrite resize handler for better support on Windows 2023-10-17 00:13:44 +11:00
Nick Fisher
818d75b493 specify minimum Flutter version in README 2023-10-16 18:24:45 +11:00
434 changed files with 6505 additions and 90571 deletions

607
.gitattributes vendored
View File

@@ -1,597 +1,12 @@
linux/lib/**/* filter=lfs diff=lfs merge=lfs -text
linux/lib/libspirv-cross-msl.a filter=lfs diff=lfs merge=lfs -text
linux/lib/libbenchmark.a filter=lfs diff=lfs merge=lfs -text
linux/lib/libbluevk.a filter=lfs diff=lfs merge=lfs -text
linux/lib/libfilagui.a filter=lfs diff=lfs merge=lfs -text
linux/lib/libgltf-demo-resources.a filter=lfs diff=lfs merge=lfs -text
linux/lib/libsuzanne-resources.a filter=lfs diff=lfs merge=lfs -text
linux/lib/libzstd.a filter=lfs diff=lfs merge=lfs -text
linux/lib/libpng.a filter=lfs diff=lfs merge=lfs -text
linux/lib/libvkshaders.a filter=lfs diff=lfs merge=lfs -text
linux/lib/libbluegl.a filter=lfs diff=lfs merge=lfs -text
linux/lib/libgeometry.a filter=lfs diff=lfs merge=lfs -text
linux/lib/libktxreader.a filter=lfs diff=lfs merge=lfs -text
linux/lib/libuberzlib.a filter=lfs diff=lfs merge=lfs -text
linux/lib/libfilament.a filter=lfs diff=lfs merge=lfs -text
linux/lib/libglslang.a filter=lfs diff=lfs merge=lfs -text
linux/lib/libmathio.a filter=lfs diff=lfs merge=lfs -text
linux/lib/libOSDependent.a filter=lfs diff=lfs merge=lfs -text
linux/lib/libuberarchive.a filter=lfs diff=lfs merge=lfs -text
linux/lib/libdracodec.a filter=lfs diff=lfs merge=lfs -text
linux/lib/libmeshoptimizer.a filter=lfs diff=lfs merge=lfs -text
linux/lib/libsdl2.a filter=lfs diff=lfs merge=lfs -text
linux/lib/libfilamat_combined.a filter=lfs diff=lfs merge=lfs -text
linux/lib/libimage.a filter=lfs diff=lfs merge=lfs -text
linux/lib/libsample-resources.a filter=lfs diff=lfs merge=lfs -text
linux/lib/libSPIRV-Tools-link.a filter=lfs diff=lfs merge=lfs -text
linux/lib/libstb.a filter=lfs diff=lfs merge=lfs -text
linux/lib/libimageio.a filter=lfs diff=lfs merge=lfs -text
linux/lib/libSPIRV.a filter=lfs diff=lfs merge=lfs -text
linux/lib/libutils.a filter=lfs diff=lfs merge=lfs -text
linux/lib/libassimp.a filter=lfs diff=lfs merge=lfs -text
linux/lib/libgtest.a filter=lfs diff=lfs merge=lfs -text
linux/lib/libibl-lite.a filter=lfs diff=lfs merge=lfs -text
linux/lib/libshaders.a filter=lfs diff=lfs merge=lfs -text
linux/lib/libSPIRV-Tools-lint.a filter=lfs diff=lfs merge=lfs -text
linux/lib/libbasis_encoder.a filter=lfs diff=lfs merge=lfs -text
linux/lib/libfilamat.a filter=lfs diff=lfs merge=lfs -text
linux/lib/libfilamat_lite.a filter=lfs diff=lfs merge=lfs -text
linux/lib/libfilament-iblprefilter.a filter=lfs diff=lfs merge=lfs -text
linux/lib/libmath.a filter=lfs diff=lfs merge=lfs -text
linux/lib/libSPIRV-Tools-reduce.a filter=lfs diff=lfs merge=lfs -text
linux/lib/libviewer.a filter=lfs diff=lfs merge=lfs -text
linux/lib/libbasis_transcoder.a filter=lfs diff=lfs merge=lfs -text
linux/lib/libfilabridge.a filter=lfs diff=lfs merge=lfs -text
linux/lib/libfilamentapp.a filter=lfs diff=lfs merge=lfs -text
linux/lib/libibl.a filter=lfs diff=lfs merge=lfs -text
linux/lib/libOGLCompiler.a filter=lfs diff=lfs merge=lfs -text
linux/lib/libspirv-cross-core.a filter=lfs diff=lfs merge=lfs -text
linux/lib/libSPIRV-Tools-diff.a filter=lfs diff=lfs merge=lfs -text
linux/lib/libbenchmark_main.a filter=lfs diff=lfs merge=lfs -text
linux/lib/libcamutils.a filter=lfs diff=lfs merge=lfs -text
linux/lib/libcivetweb.a filter=lfs diff=lfs merge=lfs -text
linux/lib/libfilamentapp-resources.a filter=lfs diff=lfs merge=lfs -text
linux/lib/libfilameshio.a filter=lfs diff=lfs merge=lfs -text
linux/lib/libgetopt.a filter=lfs diff=lfs merge=lfs -text
linux/lib/libspirv-cross-glsl.a filter=lfs diff=lfs merge=lfs -text
linux/lib/libbackend.a filter=lfs diff=lfs merge=lfs -text
linux/lib/libfilaflat.a filter=lfs diff=lfs merge=lfs -text
linux/lib/libgltfio_core.a filter=lfs diff=lfs merge=lfs -text
linux/lib/libimgui.a filter=lfs diff=lfs merge=lfs -text
linux/lib/libmatdbg_resources.a filter=lfs diff=lfs merge=lfs -text
linux/lib/libmatlang.a filter=lfs diff=lfs merge=lfs -text
linux/lib/libsmol-v.a filter=lfs diff=lfs merge=lfs -text
linux/lib/libmatdbg_combined.a filter=lfs diff=lfs merge=lfs -text
linux/lib/libSPIRV-Tools.a filter=lfs diff=lfs merge=lfs -text
linux/lib/libgltfio.a filter=lfs diff=lfs merge=lfs -text
linux/lib/libtinyexr.a filter=lfs diff=lfs merge=lfs -text
linux/lib/libz.a filter=lfs diff=lfs merge=lfs -text
linux/lib/libmatdbg.a filter=lfs diff=lfs merge=lfs -text
linux/lib/libSPIRV-Tools-opt.a filter=lfs diff=lfs merge=lfs -text
windows/lib/** filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/filament/MaterialEnums.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/gltfio/materials/uberarchive.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/math filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/lib filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/math/scalar.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/backend/AcquiredImage.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/backend/Platform.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/filament filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/math/compiler.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/uberz/ArchiveEnums.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/uberz/WritableArchive.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/utils filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/lib/universal/libuberzlib.a filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/filament/Texture.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/filament/SkinningBuffer.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/math/quat.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/utils/bitset.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/filament-iblprefilter/IBLPrefilterContext.h filter=lfs diff=lfs merge=lfs -text
ios/lib/libimage.a filter=lfs diff=lfs merge=lfs -text
ios/lib/libuberzlib.a filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/backend/PresentCallable.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/camutils/compiler.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/mathio/ostream.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/utils/EntityManager.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/viewer/RemoteServer.h filter=lfs diff=lfs merge=lfs -text
ios/lib/libgeometry.a filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/backend/Program.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/backend/platforms/PlatformEGL.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/filament/Exposure.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/gltfio/materials filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/geometry/SurfaceOrientation.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/math/TQuatHelpers.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/backend/platforms/OpenGLPlatform.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/filament/ColorSpace.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/filament/RenderTarget.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/lib/universal/libmeshoptimizer.a filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/viewer/AutomationSpec.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/lib/universal/libktxreader.a filter=lfs diff=lfs merge=lfs -text
ios/lib/libibl-lite.a filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/backend/platforms/PlatformCocoaTouchGL.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/filament/Scene.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/utils/compressed_pair.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/viewer/AutomationEngine.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/math/fast.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/math/half.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/lib/universal/libfilamat.a filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/README.md filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/filament-iblprefilter filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/filament/Color.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/ktxreader/Ktx1Reader.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/camutils/Manipulator.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/geometry/Transcoder.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/lib/universal/libgeometry.a filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/lib/universal/libvkshaders.a filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/utils/Panic.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/viewer/Settings.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/lib/universal/libfilament.a filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/filament/Stream.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/filament/Viewport.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/gltfio/FilamentInstance.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/utils/NameComponentManager.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/filamat/Package.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/filament/TextureSampler.h filter=lfs diff=lfs merge=lfs -text
ios/lib/libvkshaders.a filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/math/mat2.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/lib/universal/libfilament-iblprefilter.a filter=lfs diff=lfs merge=lfs -text
ios/lib/libcivetweb.a filter=lfs diff=lfs merge=lfs -text
ios/lib/libfilament-iblprefilter.a filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/filament/View.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/tsl/robin_growth_policy.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/lib/universal/libviewer.a filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/filament/Material.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/utils/Allocator.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/lib/universal/libibl-lite.a filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/filament/VertexBuffer.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/math/TVecHelpers.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/lib/universal/libibl.a filter=lfs diff=lfs merge=lfs -text
ios/lib/libbackend.a filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/filament/ColorGrading.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/filament/Fence.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/gltfio/AssetLoader.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/utils/SpinLock.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/lib/universal/libshaders.a filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/backend/platforms/PlatformGLX.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/filamat filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/lib/universal/libgltfio_core.a filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/lib/universal/libzstd.a filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/backend/README.md filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/filament/RenderableManager.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/filament/Skybox.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/utils/memalign.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/filameshio/MeshReader.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/utils/PrivateImplementation.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/utils/generic/Mutex.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/lib/universal/libuberarchive.a filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/backend/platforms/PlatformEGLHeadless.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/filament/DebugRegistry.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/tsl/robin_set.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/backend/Handle.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/ibl/CubemapIBL.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/backend/platforms/VulkanPlatform.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/gltfio/FilamentEntity.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/LICENSE filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/backend/BufferDescriptor.h filter=lfs diff=lfs merge=lfs -text
ios/lib/libfilament.a filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/ktxreader filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/utils/Entity.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/utils/Slice.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/utils/algorithm.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/backend/SamplerDescriptor.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/filament/LightManager.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/filament/ToneMapper.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/ibl filter=lfs diff=lfs merge=lfs -text
ios/lib/libdracodec.a filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/backend/DriverEnums.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/utils/SingleInstanceComponentManager.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/filament/Engine.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/gltfio/TextureProvider.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/tsl filter=lfs diff=lfs merge=lfs -text
ios/lib/libviewer.a filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/backend/TargetBufferInfo.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/math/mathfwd.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/math/vec2.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/lib/universal/libbasis_transcoder.a filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/filament/IndexBuffer.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/image/ImageOps.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/uberz/ReadableArchive.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/utils/CallStack.h filter=lfs diff=lfs merge=lfs -text
ios/lib/libfilaflat.a filter=lfs diff=lfs merge=lfs -text
ios/lib/libuberarchive.a filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/filament/Box.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/filament/Camera.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/math/mat4.h filter=lfs diff=lfs merge=lfs -text
ios/lib/libfilabridge.a filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/filament/SwapChain.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/ibl/CubemapSH.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/backend filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/utils/BitmaskEnum.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/utils/PrivateImplementation-impl.h filter=lfs diff=lfs merge=lfs -text
ios/lib/libfilamat_lite.a filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/filament/TransformManager.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/gltfio/NodeManager.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/math/TMatHelpers.h filter=lfs diff=lfs merge=lfs -text
ios/lib/libsmol-v.a filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/backend/PipelineState.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/camutils filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/filament/FilamentAPI.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/filament/Renderer.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/lib/universal/libfilaflat.a filter=lfs diff=lfs merge=lfs -text
ios/lib/libshaders.a filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/filameshio filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/ibl/utilities.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/math/vec3.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/lib/universal/libcamutils.a filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/lib/universal/libfilameshio.a filter=lfs diff=lfs merge=lfs -text
ios/lib/filament filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/filamat/MaterialBuilder.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/utils/EntityInstance.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/lib/universal/libbackend.a filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/gltfio/ResourceLoader.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/utils/Mutex.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/backend/PixelBufferDescriptor.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/filament/Options.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/lib/universal/libfilamat_lite.a filter=lfs diff=lfs merge=lfs -text
ios/lib/libstb.a filter=lfs diff=lfs merge=lfs -text
ios/lib/libzstd.a filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/backend/platforms/PlatformWebGL.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/math/vec4.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/utils/Invocable.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/lib/universal/libsmol-v.a filter=lfs diff=lfs merge=lfs -text
ios/lib/libbasis_transcoder.a filter=lfs diff=lfs merge=lfs -text
ios/lib/libktxreader.a filter=lfs diff=lfs merge=lfs -text
ios/lib/libmeshoptimizer.a filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/backend/CallbackHandler.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/filament/BufferObject.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/image/ColorTransform.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/tsl/robin_map.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/filament/IndirectLight.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/ibl/Cubemap.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/image/LinearImage.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/mathio filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/lib/universal/libfilabridge.a filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/utils/generic filter=lfs diff=lfs merge=lfs -text
ios/lib/filament-v1.31.6-ios.tgz filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/filamat/Enums.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/uberz filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/utils/CString.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/geometry filter=lfs diff=lfs merge=lfs -text
ios/lib/libibl.a filter=lfs diff=lfs merge=lfs -text
ios/lib/libimageio.a filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/camutils/Bookmark.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/gltfio/math.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/image/ImageSampler.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/lib/universal filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/image filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/utils/StructureOfArrays.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/utils/compiler.h filter=lfs diff=lfs merge=lfs -text
ios/lib/libgltfio_core.a filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/lib/universal/libutils.a filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/backend/DriverApiForward.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/filamat/IncludeCallback.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/filament/Frustum.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/ibl/Image.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/utils/Path.h filter=lfs diff=lfs merge=lfs -text
ios/lib/libpng.a filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/image/Ktx1Bundle.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/ktxreader/Ktx2Reader.h filter=lfs diff=lfs merge=lfs -text
ios/lib/libfilamat.a filter=lfs diff=lfs merge=lfs -text
ios/lib/libutils.a filter=lfs diff=lfs merge=lfs -text
ios/lib/libtinyexr.a filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/filament/MorphTargetBuffer.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/math/norm.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/viewer/ViewerGui.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/backend/platforms filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/backend/platforms/PlatformWGL.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/filament/MaterialInstance.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/lib/universal/libdracodec.a filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/math/mat3.h filter=lfs diff=lfs merge=lfs -text
ios/lib/libfilameshio.a filter=lfs diff=lfs merge=lfs -text
ios/lib/libpng16.a filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/tsl/robin_hash.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/utils/ostream.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/lib/universal/libcivetweb.a filter=lfs diff=lfs merge=lfs -text
ios/lib/libcamutils.a filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/backend/platforms/PlatformCocoaGL.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/geometry/TangentSpaceMesh.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/gltfio filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/gltfio/Animator.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/gltfio/MaterialProvider.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/utils/FixedCapacityVector.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/utils/debug.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/lib/universal/libstb.a filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/utils/unwindows.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/viewer filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/filament/MaterialChunkType.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/ibl/CubemapUtils.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/backend/platforms/PlatformEGLAndroid.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/include/utils/Log.h filter=lfs diff=lfs merge=lfs -text
ios/lib/filament/lib/universal/libimage.a filter=lfs diff=lfs merge=lfs -text
*.a filter=lfs diff=lfs merge=lfs -text
macos/lib/libbasis_transcoder.a filter=lfs diff=lfs merge=lfs -text
macos/lib/libimage.a filter=lfs diff=lfs merge=lfs -text
macos/lib/libktxreader.a filter=lfs diff=lfs merge=lfs -text
macos/lib/libshaders.a filter=lfs diff=lfs merge=lfs -text
macos/lib/libuberzlib.a filter=lfs diff=lfs merge=lfs -text
macos/lib/libutils.a filter=lfs diff=lfs merge=lfs -text
macos/lib/libgltfio_core.a filter=lfs diff=lfs merge=lfs -text
macos/lib/libibl-lite.a filter=lfs diff=lfs merge=lfs -text
macos/lib/libimageio.a filter=lfs diff=lfs merge=lfs -text
macos/lib/libzstd.a filter=lfs diff=lfs merge=lfs -text
macos/lib/libfilaflat.a filter=lfs diff=lfs merge=lfs -text
macos/lib/libfilament.a filter=lfs diff=lfs merge=lfs -text
macos/lib/libgeometry.a filter=lfs diff=lfs merge=lfs -text
macos/lib/libmatdbg.a filter=lfs diff=lfs merge=lfs -text
macos/lib/libmeshoptimizer.a filter=lfs diff=lfs merge=lfs -text
macos/lib/libpng.a filter=lfs diff=lfs merge=lfs -text
macos/lib/libsmol-v.a filter=lfs diff=lfs merge=lfs -text
macos/lib/libviewer.a filter=lfs diff=lfs merge=lfs -text
macos/lib/libvkshaders.a filter=lfs diff=lfs merge=lfs -text
macos/lib/libcivetweb.a filter=lfs diff=lfs merge=lfs -text
macos/lib/libfilament-iblprefilter.a filter=lfs diff=lfs merge=lfs -text
macos/lib/libtinyexr.a filter=lfs diff=lfs merge=lfs -text
macos/lib/libuberarchive.a filter=lfs diff=lfs merge=lfs -text
macos/lib/libdracodec.a filter=lfs diff=lfs merge=lfs -text
macos/lib/libfilabridge.a filter=lfs diff=lfs merge=lfs -text
macos/lib/libfilamat_lite.a filter=lfs diff=lfs merge=lfs -text
macos/lib/libfilameshio.a filter=lfs diff=lfs merge=lfs -text
macos/lib/libmikktspace.a filter=lfs diff=lfs merge=lfs -text
macos/lib/libcamutils.a filter=lfs diff=lfs merge=lfs -text
macos/lib/libibl.a filter=lfs diff=lfs merge=lfs -text
macos/lib/libbackend.a filter=lfs diff=lfs merge=lfs -text
macos/lib/libbluegl.a filter=lfs diff=lfs merge=lfs -text
macos/lib/libbluevk.a filter=lfs diff=lfs merge=lfs -text
macos/lib/libfilamat.a filter=lfs diff=lfs merge=lfs -text
macos/lib/libgltfio.a filter=lfs diff=lfs merge=lfs -text
macos/lib/libstb.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/armeabi-v7a/libfilabridge.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/armeabi-v7a/libutils.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/x86/libbasis_transcoder.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/x86/libfilameshio.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/x86/libshaders.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/x86/libz.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/x86_64/libbasis_transcoder.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/armeabi-v7a/libdracodec.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/x86_64/libfilameshio.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/x86/libmikktspace.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/armeabi-v7a/libfilamat.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/armeabi-v7a/libcivetweb.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/x86/libfilabridge.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/arm64-v8a/libbluevk.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/armeabi-v7a/libcamutils.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/x86_64/libshaders.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/arm64-v8a/libgltfio_core.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/x86/libuberarchive.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/x86_64/libfilament-iblprefilter.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/x86_64/libutils.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/x86/libmeshoptimizer.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/armeabi-v7a/libimageio.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/x86/libbluevk.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/x86/libktxreader.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/x86_64/libcamutils.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/x86_64/libpng.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/armeabi-v7a/libbasis_transcoder.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/arm64-v8a/libz.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/armeabi-v7a/libfilaflat.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/armeabi-v7a/libibl-lite.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/arm64-v8a/libvkshaders.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/x86/libgeometry.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/x86/libibl-lite.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/armeabi-v7a/libuberarchive.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/armeabi-v7a/libbackend.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/x86/libvkshaders.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/x86_64/libdracodec.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/x86_64/libfilabridge.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/arm64-v8a/libfilaflat.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/x86/libfilament-iblprefilter.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/x86/libpng.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/x86/libfilamat_lite.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/armeabi-v7a/libfilamat_lite.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/x86/libbackend.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/x86_64/libfilamat.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/x86_64/libuberzlib.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/arm64-v8a/libdracodec.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/arm64-v8a/libmikktspace.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/armeabi-v7a/libbluevk.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/x86/libtinyexr.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/x86_64/libibl.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/x86_64/libzstd.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/arm64-v8a/libfilamat.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/armeabi-v7a/libfilament-iblprefilter.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/x86/libcivetweb.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/x86_64/libimage.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/arm64-v8a/libviewer.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/x86_64/libfilamat_lite.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/x86_64/libstb.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/armeabi-v7a/libfilament.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/arm64-v8a/libibl.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/arm64-v8a/libmeshoptimizer.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/armeabi-v7a/libgeometry.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/armeabi-v7a/libsmol-v.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/arm64-v8a/libfilameshio.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/arm64-v8a/libzstd.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/armeabi-v7a/libfilameshio.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/x86_64/libfilaflat.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/arm64-v8a/libshaders.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/armeabi-v7a/libtinyexr.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/x86_64/libgeometry.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/x86_64/libmeshoptimizer.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/arm64-v8a/libbasis_transcoder.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/x86/libuberzlib.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/x86_64/libviewer.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/arm64-v8a/libfilament-iblprefilter.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/x86_64/libsmol-v.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/x86_64/libuberarchive.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/x86_64/libvkshaders.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/arm64-v8a/libgeometry.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/armeabi-v7a/libz.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/x86/libcamutils.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/x86/libgltfio_core.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/x86_64/libz.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/armeabi-v7a/libstb.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/arm64-v8a/libuberarchive.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/arm64-v8a/libsmol-v.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/arm64-v8a/libutils.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/armeabi-v7a/libibl.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/x86/libfilaflat.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/x86/libimageio.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/x86_64/libmikktspace.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/arm64-v8a/libktxreader.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/arm64-v8a/libpng.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/x86/libibl.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/x86/libimage.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/x86_64/libcivetweb.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/arm64-v8a/libfilabridge.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/x86/libfilamat.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/x86/libfilament.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/x86/libutils.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/x86/libviewer.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/x86_64/libibl-lite.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/armeabi-v7a/libimage.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/armeabi-v7a/libviewer.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/x86_64/libfilament.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/x86_64/libimageio.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/arm64-v8a/libimageio.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/armeabi-v7a/libktxreader.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/armeabi-v7a/libmeshoptimizer.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/armeabi-v7a/libshaders.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/armeabi-v7a/libuberzlib.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/armeabi-v7a/libvkshaders.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/x86/libstb.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/arm64-v8a/libstb.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/arm64-v8a/libbackend.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/armeabi-v7a/libgltfio_core.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/x86/libsmol-v.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/x86_64/libgltfio_core.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/x86_64/libktxreader.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/arm64-v8a/libcamutils.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/x86_64/libtinyexr.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/armeabi-v7a/libmikktspace.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/arm64-v8a/libfilament.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/arm64-v8a/libibl-lite.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/arm64-v8a/libtinyexr.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/armeabi-v7a/libzstd.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/x86/libdracodec.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/x86/libzstd.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/arm64-v8a/libcivetweb.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/armeabi-v7a/libpng.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/x86_64/libbluevk.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/arm64-v8a/libimage.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/arm64-v8a/libuberzlib.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/x86_64/libbackend.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/arm64-v8a/libfilamat_lite.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/arm64-v8a/libOSDependent.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/arm64-v8a/libfilagui.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/arm64-v8a/libSPIRV-Tools-opt.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/arm64-v8a/libbenchmark_main.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/arm64-v8a/libglslang.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/arm64-v8a/libbenchmark.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/arm64-v8a/libgetopt.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/arm64-v8a/libspirv-cross-msl.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/arm64-v8a/libSPIRV-Tools-diff.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/arm64-v8a/libspirv-cross-glsl.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/arm64-v8a/libOGLCompiler.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/arm64-v8a/libgtest.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/arm64-v8a/libSPIRV-Tools-reduce.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/arm64-v8a/libbasis_encoder.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/arm64-v8a/libimgui.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/arm64-v8a/libgeometry_combined.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/arm64-v8a/libSPIRV-Tools-link.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/arm64-v8a/libSPIRV-Tools-lint.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/arm64-v8a/libSPIRV.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/arm64-v8a/libSPIRV-Tools.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/arm64-v8a/libfilamat_combined.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/arm64-v8a/libmath.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/arm64-v8a/libmathio.a filter=lfs diff=lfs merge=lfs -text
android/src/main/jniLibs/arm64-v8a/libspirv-cross-core.a filter=lfs diff=lfs merge=lfs -text
web/lib/libcivetweb.a filter=lfs diff=lfs merge=lfs -text
web/lib/libsmol-v.a filter=lfs diff=lfs merge=lfs -text
web/lib/libz.a filter=lfs diff=lfs merge=lfs -text
web/lib/libfilabridge.a filter=lfs diff=lfs merge=lfs -text
web/lib/libfilaflat.a filter=lfs diff=lfs merge=lfs -text
web/lib/libmathio.a filter=lfs diff=lfs merge=lfs -text
web/lib/libbackend.a filter=lfs diff=lfs merge=lfs -text
web/lib/libgeometry_combined.a filter=lfs diff=lfs merge=lfs -text
web/lib/libmeshoptimizer.a filter=lfs diff=lfs merge=lfs -text
web/lib/libutils.a filter=lfs diff=lfs merge=lfs -text
web/lib/libbasis_transcoder.a filter=lfs diff=lfs merge=lfs -text
web/lib/libimageio.a filter=lfs diff=lfs merge=lfs -text
web/lib/libktxreader.a filter=lfs diff=lfs merge=lfs -text
web/lib/libbasis_encoder.a filter=lfs diff=lfs merge=lfs -text
web/lib/libfilament.a filter=lfs diff=lfs merge=lfs -text
web/lib/libviewer.a filter=lfs diff=lfs merge=lfs -text
web/lib/libibl-lite.a filter=lfs diff=lfs merge=lfs -text
web/lib/libmath.a filter=lfs diff=lfs merge=lfs -text
web/lib/libstb.a filter=lfs diff=lfs merge=lfs -text
web/lib/libvkshaders.a filter=lfs diff=lfs merge=lfs -text
web/lib/libdracodec.a filter=lfs diff=lfs merge=lfs -text
web/lib/libfilameshio.a filter=lfs diff=lfs merge=lfs -text
web/lib/libgltfio_core.a filter=lfs diff=lfs merge=lfs -text
web/lib/libimgui.a filter=lfs diff=lfs merge=lfs -text
web/lib/libmikktspace.a filter=lfs diff=lfs merge=lfs -text
web/lib/libzstd.a filter=lfs diff=lfs merge=lfs -text
web/lib/libuberarchive.a filter=lfs diff=lfs merge=lfs -text
web/lib/libuberzlib.a filter=lfs diff=lfs merge=lfs -text
web/lib/libcamutils.a filter=lfs diff=lfs merge=lfs -text
web/lib/libfilagui.a filter=lfs diff=lfs merge=lfs -text
web/lib/libfilament-iblprefilter.a filter=lfs diff=lfs merge=lfs -text
web/lib/libgtest.a filter=lfs diff=lfs merge=lfs -text
web/lib/libimage.a filter=lfs diff=lfs merge=lfs -text
web/lib/libshaders.a filter=lfs diff=lfs merge=lfs -text
assets/materials.uberz filter=lfs diff=lfs merge=lfs -text
assets/materials_ios_arm64.uberz filter=lfs diff=lfs merge=lfs -text
example/assets/shapes/ filter=lfs diff=lfs merge=lfs -text
example/assets/shapes/*.* filter=lfs diff=lfs merge=lfs -text
ios/lib/libmikktspace.a filter=lfs diff=lfs merge=lfs -text
example/assets/shapes/texture_test.png filter=lfs diff=lfs merge=lfs -text
example/assets/BusterDrone/scene.bin filter=lfs diff=lfs merge=lfs -text
example/assets/FlightHelmet/FlightHelmet_baseColor4.png filter=lfs diff=lfs merge=lfs -text
example/assets/FlightHelmet/FlightHelmet_occlusionRoughnessMetallic.png filter=lfs diff=lfs merge=lfs -text
example/assets/default_env filter=lfs diff=lfs merge=lfs -text
example/assets/BusterDrone/scene.gltf filter=lfs diff=lfs merge=lfs -text
example/assets/shapes/shapes.gltf filter=lfs diff=lfs merge=lfs -text
example/assets/FlightHelmet filter=lfs diff=lfs merge=lfs -text
example/assets/FlightHelmet/FlightHelmet_baseColor1.png filter=lfs diff=lfs merge=lfs -text
example/assets/FlightHelmet/FlightHelmet_baseColor2.png filter=lfs diff=lfs merge=lfs -text
example/assets/FlightHelmet/FlightHelmet_occlusionRoughnessMetallic2.png filter=lfs diff=lfs merge=lfs -text
example/assets/BusterDrone/textures/Boden_normal.jpg filter=lfs diff=lfs merge=lfs -text
example/assets/BusterDrone/textures/body_baseColor.jpg filter=lfs diff=lfs merge=lfs -text
example/assets/BusterDrone/textures/body_emissive.jpg filter=lfs diff=lfs merge=lfs -text
example/assets/BusterDrone/textures/material_baseColor.jpg filter=lfs diff=lfs merge=lfs -text
example/assets/FlightHelmet/FlightHelmet_occlusionRoughnessMetallic3.png filter=lfs diff=lfs merge=lfs -text
example/assets/BusterDrone/textures/Boden_metallicRoughness.jpg filter=lfs diff=lfs merge=lfs -text
example/assets/FlightHelmet/FlightHelmet_normal.png filter=lfs diff=lfs merge=lfs -text
example/assets/FlightHelmet/FlightHelmet_normal1.png filter=lfs diff=lfs merge=lfs -text
example/assets/FlightHelmet/FlightHelmet_normal3.png filter=lfs diff=lfs merge=lfs -text
example/assets/FlightHelmet/FlightHelmet.gltf filter=lfs diff=lfs merge=lfs -text
example/assets/FlightHelmet/FlightHelmet_occlusionRoughnessMetallic4.png filter=lfs diff=lfs merge=lfs -text
example/assets/FlightHelmet/README.md filter=lfs diff=lfs merge=lfs -text
example/assets/background.ktx filter=lfs diff=lfs merge=lfs -text
example/assets/default_env/default_env_skybox.ktx filter=lfs diff=lfs merge=lfs -text
example/assets/shapes/shapes.blend filter=lfs diff=lfs merge=lfs -text
example/assets/BusterDrone filter=lfs diff=lfs merge=lfs -text
example/assets/BusterDrone/textures/material_metallicRoughness.jpg filter=lfs diff=lfs merge=lfs -text
example/assets/FlightHelmet/FlightHelmet_normal2.png filter=lfs diff=lfs merge=lfs -text
example/assets/background.png filter=lfs diff=lfs merge=lfs -text
example/assets/shapes/shapes.bin filter=lfs diff=lfs merge=lfs -text
example/assets/BusterDrone/textures filter=lfs diff=lfs merge=lfs -text
example/assets/BusterDrone/textures/body_normal.jpg filter=lfs diff=lfs merge=lfs -text
example/assets/BusterDrone/textures/material_normal.jpg filter=lfs diff=lfs merge=lfs -text
example/assets/FlightHelmet/FlightHelmet_baseColor.png filter=lfs diff=lfs merge=lfs -text
example/assets/FlightHelmet/FlightHelmet_normal4.png filter=lfs diff=lfs merge=lfs -text
example/assets/FlightHelmet/FlightHelmet_occlusionRoughnessMetallic1.png filter=lfs diff=lfs merge=lfs -text
example/assets/default_env/default_env_ibl.ktx filter=lfs diff=lfs merge=lfs -text
example/assets/shapes/shapes.glb filter=lfs diff=lfs merge=lfs -text
example/assets/BusterDrone/textures/Boden_baseColor.jpg filter=lfs diff=lfs merge=lfs -text
example/assets/BusterDrone/textures/body_metallicRoughness.jpg filter=lfs diff=lfs merge=lfs -text
example/assets/FlightHelmet/FlightHelmet.bin filter=lfs diff=lfs merge=lfs -text
example/assets/FlightHelmet/FlightHelmet_baseColor3.png filter=lfs diff=lfs merge=lfs -text
assets/default.uberz filter=lfs diff=lfs merge=lfs -text
windows/lib/**/*.* filter=lfs diff=lfs merge=lfs -text
windows/lib/Debug/angle/* filter=lfs diff=lfs merge=lfs -text
windows/lib/Debug/opengl/* filter=lfs diff=lfs merge=lfs -text
windows/lib/Release/opengl/* filter=lfs diff=lfs merge=lfs -text
windows/lib/Release/angle/* filter=lfs diff=lfs merge=lfs -text
windows/lib/**/* filter=lfs diff=lfs merge=lfs -text
*.lib filter=lfs diff=lfs merge=lfs -text
*.dll filter=lfs diff=lfs merge=lfs -text
*.pdb filter=lfs diff=lfs merge=lfs -text
*.png filter=lfs diff=lfs merge=lfs -text
*.jpg filter=lfs diff=lfs merge=lfs -text
*.uberz filter=lfs diff=lfs merge=lfs -text
*.bin filter=lfs diff=lfs merge=lfs -text
*.ktx filter=lfs diff=lfs merge=lfs -text
*.blend filter=lfs diff=lfs merge=lfs -text
*.gltf filter=lfs diff=lfs merge=lfs -text
*.glb filter=lfs diff=lfs merge=lfs -text

29
.github/workflows/analyze_project.yaml vendored Normal file
View File

@@ -0,0 +1,29 @@
name: Dart Analyzer
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-java@v1
with:
java-version: '12.x'
- name: Install Flutter
uses: subosito/flutter-action@v1
with:
flutter-version: '2.x'
- name: Get dependencies
run: flutter pub get
- name: Analyze
run: flutter analyze

View File

@@ -0,0 +1,35 @@
name: PubDev Score
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
package-analysis:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: axel-op/dart-package-analyzer@v3
id: analysis
with:
githubToken: ${{ secrets.GITHUB_TOKEN }}
# use this id to retrieve the outputs in the next steps
# exit dirty when the package doesn't reach 100%
- name: Check scores
env:
# "analysis" is the id set above
# PERCENTAGE=$(( $TOTAL * 100 / $TOTAL_MAX ))
TOTAL: ${{ steps.analysis.outputs.total }}
TOTAL_MAX: ${{ steps.analysis.outputs.total_max }}
JSON_OUT: ${{ steps.analysis.outputs.json_output }}
run: |
if (( $TOTAL != $TOTAL_MAX ))
then
echo There are missing points in the project!
echo $TOTAL from $TOTAL_MAX Points reached
echo $JSON_OUT | jq
exit 1
fi

4
.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
.vscode
macos/src
macos/include
.DS_Store

36
ARCHITECTURE.md Normal file
View File

@@ -0,0 +1,36 @@
# Rendering/plugin architecture
This is an overview of how the rendering surface is constructed, and how the Flutter plugin communicates with the Filament renderer. If you are looking to extend the plugin or add (and hopefully contribute back upstream) additional features, start here.
## Rendering surface
|Platform|Type|
|---|---|
|Windows|HWND beneath transparency (OpenGL), glTexture render target + Flutter Texture widget (GLES/ANGLE), glTexture render target + Flutter Texture widget (GLES/ANGLE)|
|Android|SurfaceTexture render target + Flutter Texture widget|
|iOS|CVPixelBuffer surface (Metal) + Flutter Texture widget|
|MacOS|CVMetalTexture render target (Metal) + Flutter Texture widget|
On most platforms, we create Filament with a headless swapchain, then render into a (hardware accelerated) texture that Flutter imports into its own widget hierarchy via a Texture widget. This allows the Filament viewport to be transformed/composed completely within the Flutter hierarchy (i.e. you could rotate/scale/translate the FilamentWidget in Flutter if you wanted, or insert other widgets above/below).
Due to performance issues on Windows, we choose a different default approach where Filament renders into its own window, which is then composed with the Flutter window via the system compositor. This only works on Windows 10.
Using this approach, you will not be able to add a Flutter widget behind the Filament viewport, or transform the viewport itself from within Flutter.
You can fall-back to the Texture/render target approach by setting `WGL_USE_BACKING_WINDOW` to `false` in `CMakeLists.txt` for Windows.
However, I don't currently have capacity to maintain this pathway so it will probably be broken on any given day.
If you want to try the fallback, you have two options for a rendering backend. With `USE_ANGLE` set to `true` in `CMakeLists.txt`, we will use the ANGLE backend (which translates GLES calls to D3D). This provides end-to-end GPU texture support, however there are some odd rendering artifacts with some of the Filament shaders (and in fact will crash with some dynamic lights).
`USE_ANGLE` set to `false` will use the OpenGL backend, but requires copying the contents of the texture from the GPU to CPU on every frame. This is not optimal for performance.
### Why not Platform Views?
Initially, performance of Platform Views was inferior to Texture widgets (and in any case, weren't supported on Windows/Linux). I suspect this is still the case (though that might be worth revisiting).
However, I am now thinking it would be better to lean towards the current Windows model (where the Flutter app is composited over a Filament viewport running in a separate window or view). I suspect that the overwhelming use case is a Flutter UI sitting on top of a Filament viewport, and that very few people will need to insert widgets beneath the viewport (or transform the viewport from within Flutter, excluding resizes or mobile orientation changes which can be handled independently). Deferring to the system compositor should deliver far better performance, at the cost of slightly more complexity in the setting up the app harness.
## Flutter <-> Platform <-> FFI
TODO

View File

@@ -1,3 +1,9 @@
## 0.0.1
## 0.6.0
* TODO: Describe initial release.
* `createViewer` is no longer called by `FilamentWidget` and must be called manually at least one frame after a FilamentWidget has been inserted into the widget hierarchy.
## 0.5.0
* Replaced `isReadyForScene` Future in `FilamentController` with the `Stream<bool>` `hasViewer`.
* Rendering is set to false when the app is hidden, inactive or paused; on resume, this will be set to the value it held prior to being hidden/inactive/paused.

27
Makefile Normal file
View File

@@ -0,0 +1,27 @@
mkfile_path := $(abspath $(lastword $(MAKEFILE_LIST)))
current_dir := $(dir $(mkfile_path))
parent_dir := $(abspath $(dir $(lastword $(MAKEFILE_LIST)))/..)
filament_build_out := $(parent_dir)/filament/out/cmake-release
# building on MacOS, we currently just delete the macos/include
# and macos/src directories and copy from iOS
sync-macos: FORCE
rm -rf ${current_dir}macos/include ${current_dir}macos/src
cp -R ${current_dir}ios/include ${current_dir}macos
cp -R ${current_dir}ios/src ${current_dir}macos
FORCE: ;
# We use a single material (no lighting and no transparency) for background images
#
# by default this assumes you have built filament in a sibling folder
# you may customize the out folder by speicifying `filament_build_out`
#
# eg: make generate-background-material filament_build_out=/filament/out/release
#
generate-background-material:
${filament_build_out}/tools/matc/matc -a opengl -a metal -o materials/image.filamat materials/image.mat
${filament_build_out}/tools/resgen/resgen -c -p image -x ios/include/material/ materials/image.filamat
rm materials/image.filamat

View File

@@ -4,35 +4,35 @@ Cross-platform, 3D PBR rendering and animation for [Flutter](https://github.com/
Wraps the [the Filament rendering library](https://github.com/google/filament).
Powers the Polyvox and odd-io engines.
Powers the [Polyvox](https://polyvox.app) and [odd-io](https://github.com/odd-io/) engines.
This is still in beta: bugs/missing features are to be expected.
https://github.com/nmfisher/polyvox_filament/assets/7238578/abaed1c8-c97b-4999-97b2-39e85e0fa7dd
https://github.com/nmfisher/flutter_filament/assets/7238578/abaed1c8-c97b-4999-97b2-39e85e0fa7dd
|Feature|Supported|
|---|---|
|Platforms|✅ iOS (arm64)<br/>✅ MacOS (arm64)<br/>✅ Android (arm64) <br/>✅ Windows (x64)<br/>⚠️ Linux (x64 - broken)<br/>⚠️ Web (planned)|
|Platforms|✅ iOS (arm64)<br/>✅ MacOS (arm64)<br/>✅ Android (arm64) <br/>✅ Windows (x64) (>= 10)<br/>⚠️ Linux (x64 - broken)<br/>⚠️ Web (planned)|
|Formats|✅ glb <br/>⚠️ glTF (partial - see Known Issues)|
|Texture support|✅ PNG <br/>✅ JPEG <br/>✅ KTX <br/>⚠️ KTX2 (planned)|
|Camera movement|✅ Desktop (mouse)<br/>✅ Mobile (swipe/pinch)|
|Animation|✅ Embedded glTF skinning animations<br/>✅ Embedded glTF morph animations<br/> ✅ Runtime/dynamic morph animations<br/> ⚠️ Runtime/dynamic skinning animations <br/>
|Entity manipulation|✅ Viewport selection<br/>⚠️ Entity/transform parenting (planned)<br/> ⚠️ Transform manipulation (mouse/gesture to rotate/translate/scale object) (partial)<br/>⚠️ Runtime material changes (planned)|
Special thanks to odd-io for sponsoring work on supporting Windows, raycasting, testing and documentation.
Special thanks to [odd-io](https://github.com/odd-io/) for sponsoring work on supporting Windows, raycasting, testing and documentation.
PRs are welcome but please create a placeholder PR to discuss before writing any code. This will help with feature planning, avoid clashes with existing work and keep the project structure consistent.
## Getting Started
This package is currently only tested on Flutter >= `3.15.0-15.2.pre`, so you will need to first switch to the `beta` channel:
This package requires Flutter >= `3.16.0-0.2.pre`, so you will need to first switch to the `beta` channel:
```
flutter channel beta
flutter upgrade
```
There are specific issues with earlier versions on Windows/MacOS (mobile should actually be fine, so if you want to experiment on your own you're free to remove the minimum version from `pubspec.yaml`).
Next, clone this repository and pull the latest binaries from Git LFS:
@@ -84,7 +84,7 @@ class MyApp extends StatelessWidget {
This is a relatively lightweight object, however its constructor will load/bind symbols from the native library. This may momentarily block the UI, so you may wish to structure your app so that this is hidden behind a static widget until it is available.
Next, create an instance of `FilamentWidget` in the widget hierarchy where you want the rendering canvas to appear. This can be sized as large or as small as you want. Flutter widgets can be positioned above or below the `FilamentWidget`.
Next, create an instance of `FilamentWidget` in the widget hierarchy where you want the rendering canvas to appear. This can be sized as large or as small as you want. On most platforms, Flutter widgets can be positioned above or below the `FilamentWidget`.
```
class MyApp extends StatelessWidget {
@@ -105,17 +105,20 @@ class MyApp extends StatelessWidget {
```
When a `FilamentWidget` is added to the widget hierarchy:
1) on the first frame, by default a Container will be rendered with solid red. If you want to change this, pass a widget as the `initial` paramer to the `FilamentWidget` constructor.
2) on the second frame, `FilamentWidget` will retrieve its actual size and request the `FilamentController` to create:
* the backing textures needed to insert a `Texture` widget into
1) by default a Container will be rendered with solid red. If you want to change this, pass a widget as the `initial` paramer to the `FilamentWidget` constructor.
2) on the second frame, `FilamentWidget` will pass its dimensions/pixel ratio to the `FilamentController`
3) You can then call `createViewer` to create:
* the rendering surface (on most platforms, a backing texture that will be registered with Flutter for use in a `Texture` widget)
* a rendering thread
* a `FilamentViewer` and an `AssetManager`, which will allow you to load assets/cameras/lighting/etc via the `FilamentController`
3) after an indeterminate number of frames, `FilamentController` will notify `FilamentWidget` when a texture is available the viewport
4) `FilamentWidget` will replace the default `initial` Widget with the viewport (which will initially be solid black or white, depending on your platform).
4) after an indeterminate number of frames, `FilamentController` will notify `FilamentWidget` when a rendering surface is available the viewport
5) `FilamentWidget` will replace the default `initial` Widget with the viewport (which will initially be solid black or white, depending on your platform).
It's important to note that there *will* be a delay between adding a `FilamentWidget` and the actual rendering viewport becoming available. This is why we fill `FilamentWidget` with red - to make it abundantly clear that you need to handle this asynchronous delay appropriately. You can call `await _filamentController.isReadyForScene` if you need to wait until the viewport is actually ready for rendering.
IMPORTANT: there *will* be a delay between adding a `FilamentWidget`, calling `createViewer` and the actual rendering viewport becoming available. This is why we fill `FilamentWidget` with red - to make it abundantly clear that you need to handle this asynchronous delay appropriately. Once `createViewer` has completed, the viewport is available for rendering.
Congratulations! You now have a scene. It's completely empty, so you probably want to add.
> Currently, the `initial` widget will also be displayed whenever the viewport is resized (including changing orientation on mobile and drag-to-resize on desktop). You probably want to change this from the default red.
Congratulations! You now have a scene. It's completely empty, so you probably want to add something visible.
### Load a background
@@ -305,12 +308,22 @@ uberz -TSHADINGMODEL=lit -TBLENDING=opaque -o lit_opaque_43.uberz lit_opaque
(note that the number in the filename corresponds to the Material version, not the Filament version. Not every Filament version requires a new Material version).
## Releasing your app
## Footguns
### Stripping in release mode
If you build your app in release mode, you will need to ensure that "Dead Strip" is set to false.
This is because we only invoke the library at runtime via FFI, so at link time these symbols are otherwise treated as redundant.
### Animations when backgrounded
Don't call playAnimation when the app is in the background (i.e inactive/hidden). This will queue, but not start, an animation, and eventually this will overflow the command buffer when the app is foregrounded/resumed.
If you have some kind of looping animation in your app code, make sure it pauses while the app is backgrounded.
## Versioning
||Android|iOS|MacOS|Windows|Linux|WebGL|
@@ -349,6 +362,13 @@ The results will depend on the actual device used to generate the golden, theref
git clone git@github.com:nmfisher/filament.git && cd filament
```
## Android/iOS/MacOS
```
git checkout flutter-filament-ios-android-macos
./build.sh -p <platform> release
```
## Windows
To support embedding GPU textures in Flutter (rather than copying to a CPU pixel buffer on every frame), we need to build a slightly customized version of Filament that uses GLES on Windows (rather than the default, which uses OpenGL).
@@ -358,6 +378,7 @@ Separately, we also force the Filament gltfio library to load assets via in-memo
```
git checkout flutter-filament-windows
mkdir out && cd out
"C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe" --build . --target gltf_viewer --config Debug
```
Building notes:
@@ -367,10 +388,10 @@ Project structure:
- most shared code/headers under ios/src (because I still can't get podspec to build a target with symlinks or relative paths)
- building on MacOS, we currently just delete the macos/include and macos/src directories and copy from iOS (for same reason),
e.g.
`rm -r ../macos/include && cp -R ../ios/include ../macos && rm -r ../macos/src && cp -R ../ios/src ../macos && pushd macos && pod update && popd && flutter run -d macos`
- Android keeps a separate copy of ALL headers (because it's currently running a different version of Filament, earlier versions have some texture filtering issues)
-- can't symlink either?
--- IMPORTANT - current version only works on Flutter 3.15.0-15.2.pre / Filament v1.43.1
```
make sync-macos
```
- Note also need to specifically build imageio/png/tinyexr
- if release build, then need to comment out -fno-exceptions
@@ -394,9 +415,9 @@ EMCC_CFLAGS="-I/Users/nickfisher/Documents/filament/libs/utils/include -I/Users/
## Materials
We use a single material (no lighting and no transparency) for background images:
```
filament/out/release/filament/bin/matc -a opengl -a metal -o materials/image.filamat materials/image.mat
filament/out/release/filament/bin/resgen -c -p image -x ios/include/material/ materials/image.filamat
make generate-background-material
```
# Known issues
@@ -406,3 +427,7 @@ On Windows, loading a glTF (but NOT a glb) may crash due to a race condition bet
This has been fixed in recent versions of Filament, but other bugs on Windows prevent upgrading.
Only workaround is to load a .glb file.
# Thanks
- https://github.com/alexmercerind/flutter-windows-ANGLE-OpenGL-ES

View File

@@ -0,0 +1,8 @@
{
"allAbis": [
"arm64-v8a"
],
"validAbis": [
"ARM64_V8A"
]
}

View File

@@ -0,0 +1 @@
[]

View File

@@ -0,0 +1,20 @@
{
"ndkHandlerSupportedAbis": [
"ARMEABI_V7A",
"ARM64_V8A",
"X86",
"X86_64"
],
"ndkHandlerDefaultAbis": [
"ARMEABI_V7A",
"ARM64_V8A",
"X86",
"X86_64"
],
"externalNativeBuildAbiFilters": [],
"ndkConfigAbiFilters": [
"arm64-v8a"
],
"splitsFilterAbis": [],
"ideBuildOnlyTargetAbi": true
}

View File

@@ -0,0 +1,11 @@
{
"ndk": "C:\\Users\\Nick\\AppData\\Local\\Android\\Sdk\\ndk\\25.2.9519653",
"revision": {
"mMajor": 25,
"mMinor": 2,
"mMicro": 9519653,
"mPreview": 0,
"mPrecision": "MICRO",
"mPreviewSeparator": " "
}
}

View File

@@ -0,0 +1,22 @@
[
{
"level": "INFO",
"message": "android.ndkVersion from module build.gradle is [25.2.9519653]"
},
{
"level": "INFO",
"message": "android.ndkPath from module build.gradle is not set"
},
{
"level": "INFO",
"message": "ndk.dir in local.properties is not set"
},
{
"level": "INFO",
"message": "Not considering ANDROID_NDK_HOME because support was removed after deprecation period."
},
{
"level": "INFO",
"message": "sdkFolder is C:\\Users\\Nick\\AppData\\Local\\Android\\Sdk"
}
]

View File

@@ -0,0 +1,17 @@
{
"ndkVersionFromDsl": "25.2.9519653",
"sdkFolder": "C:\\Users\\Nick\\AppData\\Local\\Android\\Sdk",
"sideBySideNdkFolderNames": [
"19.2.5345600",
"21.1.6352462",
"21.4.7075529",
"22.0.7026061",
"22.1.7171670",
"23.0.7599858",
"23.1.7779620",
"23.2.8568313",
"24.0.8215888",
"25.1.8937393",
"25.2.9519653"
]
}

View File

@@ -7,9 +7,9 @@ include_directories(src/main/cpp)
link_directories(src/main/jniLibs/${ANDROID_ABI})
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17")
add_library(polyvox_filament_android SHARED
"${CMAKE_CURRENT_SOURCE_DIR}/../ios/src/PolyvoxFilamentApi.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/../ios/src/PolyvoxFilamentFFIApi.cpp"
add_library(flutter_filament_android SHARED
"${CMAKE_CURRENT_SOURCE_DIR}/../ios/src/FlutterFilamentApi.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/../ios/src/FlutterFilamentFFIApi.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/main/cpp/FilamentAndroid.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/../ios/src/AssetManager.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/../ios/src/FilamentViewer.cpp"
@@ -24,7 +24,7 @@ add_library(FILAMENT_SHADERS SHARED
)
target_link_libraries(
polyvox_filament_android
flutter_filament_android
FILAMENT_SHADERS
-landroid
-llog

View File

@@ -1 +1 @@
rootProject.name = 'polyvox_filament'
rootProject.name = 'flutter_filament'

View File

@@ -3,7 +3,7 @@
extern "C" {
#include "PolyvoxFilamentFFIApi.h"
#include "FlutterFilamentFFIApi.h"
void* get_native_window_from_surface(
jobject surface,

View File

@@ -26,21 +26,21 @@ import io.flutter.view.TextureRegistry.SurfaceTextureEntry
import java.io.File
import java.util.*
class LoadFilamentResourceFromOwnerImpl(plugin:PolyvoxFilamentPlugin) : LoadFilamentResourceFromOwner {
class LoadFilamentResourceFromOwnerImpl(plugin:FlutterFilamentPlugin) : LoadFilamentResourceFromOwner {
var plugin = plugin
override fun loadResourceFromOwner(path: String?, owner: Pointer?): ResourceBuffer {
return plugin.loadResourceFromOwner(path, owner)
}
}
class FreeFilamentResourceFromOwnerImpl(plugin:PolyvoxFilamentPlugin) : FreeFilamentResourceFromOwner {
class FreeFilamentResourceFromOwnerImpl(plugin:FlutterFilamentPlugin) : FreeFilamentResourceFromOwner {
var plugin = plugin
override fun freeResourceFromOwner(rb: ResourceBuffer, owner: Pointer?) {
plugin.freeResourceFromOwner(rb, owner)
}
}
class RenderCallbackImpl(plugin:PolyvoxFilamentPlugin) : RenderCallback {
class RenderCallbackImpl(plugin:FlutterFilamentPlugin) : RenderCallback {
var plugin = plugin
override fun renderCallback(owner:Pointer?) {
plugin.renderCallback();
@@ -51,8 +51,8 @@ class RenderCallbackImpl(plugin:PolyvoxFilamentPlugin) : RenderCallback {
}
}
/** PolyvoxFilamentPlugin */
class PolyvoxFilamentPlugin: FlutterPlugin, MethodCallHandler, ActivityAware, LoadFilamentResourceFromOwner, FreeFilamentResourceFromOwner {
/** FlutterFilamentPlugin */
class FlutterFilamentPlugin: FlutterPlugin, MethodCallHandler, ActivityAware, LoadFilamentResourceFromOwner, FreeFilamentResourceFromOwner {
companion object {
const val CHANNEL_NAME = "app.polyvox.filament/event"
@@ -80,7 +80,7 @@ class PolyvoxFilamentPlugin: FlutterPlugin, MethodCallHandler, ActivityAware, Lo
this.flutterPluginBinding = flutterPluginBinding
channel = MethodChannel(flutterPluginBinding.binaryMessenger, CHANNEL_NAME)
channel.setMethodCallHandler(this)
_lib = Native.loadLibrary("polyvox_filament_android", FilamentInterop::class.java, Collections.singletonMap(Library.OPTION_ALLOW_OBJECTS, true))
_lib = Native.loadLibrary("flutter_filament_android", FilamentInterop::class.java, Collections.singletonMap(Library.OPTION_ALLOW_OBJECTS, true))
}
override fun onAttachedToActivity(binding: ActivityPluginBinding) {
@@ -93,7 +93,7 @@ class PolyvoxFilamentPlugin: FlutterPlugin, MethodCallHandler, ActivityAware, Lo
var _lastId = 1
override fun loadResourceFromOwner(path: String?, owner: Pointer?): ResourceBuffer {
Log.i("polyvox_filament", "Loading resource from path $path")
Log.i("flutter_filament", "Loading resource from path $path")
var data:ByteArray? = null
if(path!!.startsWith("file://")) {
data = File(path!!.substring(6)).readBytes()
@@ -108,14 +108,14 @@ class PolyvoxFilamentPlugin: FlutterPlugin, MethodCallHandler, ActivityAware, Lo
if (hotReloadPath != null) {
data = File(hotReloadPath).readBytes()
} else {
Log.i("polyvox_filament", "Loading resource from main asset bundle at ${assetPath}")
Log.i("flutter_filament", "Loading resource from main asset bundle at ${assetPath}")
val assetManager: AssetManager = activity.assets
try {
data = assetManager.open(key).readBytes()
Log.i("polyvox_filament", "Loaded ${data.size} bytes")
Log.i("flutter_filament", "Loaded ${data.size} bytes")
} catch (e:Exception) {
Log.e("polyvox_filament", "Failed to open asset at ${assetPath}", null)
Log.e("flutter_filament", "Failed to open asset at ${assetPath}", null)
}
}
}
@@ -135,7 +135,7 @@ class PolyvoxFilamentPlugin: FlutterPlugin, MethodCallHandler, ActivityAware, Lo
rb.data = Pointer(0)
}
} catch(e:Exception) {
Log.e("polyvox_filament", "Error setting resource buffer : $e", null);
Log.e("flutter_filament", "Error setting resource buffer : $e", null);
}
rb.write();
return rb;
@@ -153,11 +153,8 @@ class PolyvoxFilamentPlugin: FlutterPlugin, MethodCallHandler, ActivityAware, Lo
@RequiresApi(Build.VERSION_CODES.M)
override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
Log.e("polyvox_filament", call.method, null)
Log.e("flutter_filament", call.method, null)
when (call.method) {
"getSharedContext" -> {
result.success(null)
}
"createTexture" -> {
if(_surfaceTextureEntry != null) {
result.error("TEXTURE_EXISTS", "Texture already exist. Make sure you call destroyTexture first", null)
@@ -170,7 +167,7 @@ class PolyvoxFilamentPlugin: FlutterPlugin, MethodCallHandler, ActivityAware, Lo
result.error("DIMENSION_MISMATCH","Both dimensions must be greater than zero (you provided $width x $height)", null);
return;
}
Log.i("polyvox_filament", "Creating Surface Texture of size ${width}x${height}");
Log.i("flutter_filament", "Creating Surface Texture of size ${width}x${height}");
_surfaceTextureEntry = flutterPluginBinding.textureRegistry.createSurfaceTexture()
_surfaceTexture = _surfaceTextureEntry!!.surfaceTexture();
@@ -184,7 +181,7 @@ class PolyvoxFilamentPlugin: FlutterPlugin, MethodCallHandler, ActivityAware, Lo
val nativeWindow = _lib.get_native_window_from_surface(_surface!! as Object, JNIEnv.CURRENT)
val resultList = listOf(_surfaceTextureEntry!!.id(), Pointer.nativeValue(nativeWindow), null )
val resultList = listOf(_surfaceTextureEntry!!.id(), Pointer.nativeValue(nativeWindow), null, null )
result.success(resultList)
}
@@ -203,15 +200,6 @@ class PolyvoxFilamentPlugin: FlutterPlugin, MethodCallHandler, ActivityAware, Lo
_surfaceTextureEntry = null
result.success(true)
}
"resize" -> {
val args = call.arguments as List<Any>
val width = args[0] as Int
val height = args[1] as Int
val scale = args[2] as Double
_surfaceTexture!!.setDefaultBufferSize(width, height)
Log.i(TAG, "Resized to ${args[0]}x${args[1]}")
result.success(_surfaceTexture)
}
else -> {
result.notImplemented()
}

View File

@@ -11,17 +11,17 @@ class HotReloadPathHelper {
companion object {
fun getAssetPath(path: String, packageName: String): String? {
val packagePath = "/data/user/0/${packageName}/code_cache/"
Log.v("polyvox_filament", "Looking for hot reloaded asset ${path} under package path ${packagePath}")
Log.v("flutter_filament", "Looking for hot reloaded asset ${path} under package path ${packagePath}")
val files = File(packagePath).walkBottomUp().filter {
it.path.endsWith(path)
}.sortedBy {
it.lastModified()
}.toList()
if(files.size > 0) {
Log.v("polyvox_filament", "Using hot reloaded asset at ${files.last().path}")
Log.v("flutter_filament", "Using hot reloaded asset at ${files.last().path}")
return files.last().path;
}
Log.v("polyvox_filament", "No hot reloaded asset found.")
Log.v("flutter_filament", "No hot reloaded asset found.")
return null;
}
}

View File

@@ -0,0 +1,4 @@
{
"flutterSdkVersion": "3.16.0-0.2.pre",
"flavors": {}
}

3
example/.gitignore vendored
View File

@@ -46,3 +46,6 @@ app.*.map.json
/android/app/release
/android/.cxx/**/*
# fvm
.fvm/flutter_sdk

View File

@@ -1,6 +1,6 @@
# polyvox_filament_example
# flutter_filament_example
Demonstrates how to use the polyvox_filament plugin.
Demonstrates how to use the flutter_filament plugin.
## Linux

View File

@@ -45,7 +45,7 @@ android {
}
defaultConfig {
applicationId "app.polyvox.filament_example"
applicationId "app.polyvox.flutter_filament_example"
minSdkVersion 22
targetSdkVersion 31
versionCode flutterVersionCode.toInteger()

View File

@@ -1,5 +1,5 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="app.polyvox.filament_example">
package="app.polyvox.flutter_filament_example">
<!-- Flutter needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->

View File

@@ -1,8 +1,9 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="app.polyvox.filament_example">
package="app.polyvox.flutter_filament_example">
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<application
android:name="${applicationName}"
android:label="polyvox_filament_example"
android:label="flutter_filament_example"
android:icon="@mipmap/ic_launcher"
android:theme="@android:style/Theme.Translucent.NoTitleBar"
>

View File

@@ -1,4 +1,4 @@
package app.polyvox.filament_example
package app.polyvox.flutter_filament_example
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.android.TransparencyMode

View File

@@ -1,5 +1,5 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="app.polyvox.filament_example">
package="app.polyvox.flutter_filament_example">
<!-- Flutter needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->

View File

@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:cded95729bd217f86db59866042260dd8049bbff25bbde8fb52f37bd605653fa
size 212643

View File

@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:d7a46bb2bec8300cb9fcd41a9bd0fecd38c17732ff5afaaa54136c9d1d578a65
size 2596038

View File

@@ -6,8 +6,7 @@ import 'package:flutter/gestures.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:integration_test/integration_test.dart';
import 'package:golden_toolkit/golden_toolkit.dart';
import 'package:polyvox_filament/widgets/filament_widget.dart';
import 'package:flutter_filament/widgets/filament_widget.dart';
import '../lib/main.dart' as app;
void main() {
@@ -31,8 +30,7 @@ void main() {
int _counter = 0;
Future _snapshot(WidgetTester tester, Device device, String label,
[int seconds = 0]) async {
Future _snapshot(WidgetTester tester, String label, [int seconds = 0]) async {
await tester.pumpAndSettle(Duration(milliseconds: 16));
for (int i = 0; i < seconds; i++) {
await Future.delayed(Duration(seconds: 1));
@@ -50,19 +48,17 @@ void main() {
_counter++;
}
late Device device;
Future tap(WidgetTester tester, String label, [int seconds = 0]) async {
var target = find.text(label).first;
await tester.dragUntilVisible(
target,
find.byType(SingleChildScrollView),
// widget you want to scroll
const Offset(0, 500), // delta to move
duration: Duration(milliseconds: 10));
await tester.tap(target);
await _snapshot(
tester, device, label.replaceAll(RegExp("[ -:]"), ""), seconds);
var target = find.text(label, skipOffstage: false);
if (!target.hasFound) {
print("Couldn't find target, waiting 100ms");
await tester.pump(const Duration(milliseconds: 100));
target = find.text(label);
}
await tester.tap(target.first);
await _snapshot(tester, label.replaceAll(RegExp("[ -:]"), ""), seconds);
}
Future<void> pumpUntilFound(
@@ -84,22 +80,38 @@ void main() {
timer.cancel();
}
testGoldens('test', (WidgetTester tester) async {
testWidgets('test', (WidgetTester tester) async {
app.main();
await pumpUntilFound(tester, find.byType(app.ExampleWidget));
device = Device(size: Size(800, 600), name: "desktop");
await tester.pumpAndSettle();
await _snapshot(tester, device, "fresh");
await _snapshot(tester, "fresh");
await tap(tester, "create viewer (default ubershader)", 4);
await tap(tester, "Controller / Viewer");
await tap(tester, "Create FilamentController (default ubershader)");
await tap(tester, "Controller / Viewer");
await tap(tester, "Create FilamentViewer",
4); // on older devices this may take a while, so let's insert a length delay
await tap(tester, "Rendering: false", 2);
await tap(tester, "Scene");
await tap(tester, "Rendering");
await tap(tester, "Set continuous rendering to true");
await tap(tester, "load skybox", 2);
await tap(tester, "load IBL", 2);
await tap(tester, "load shapes GLB", 2);
await tap(tester, "Scene");
await tap(tester, "Assets");
await tap(tester, "Shapes");
await tap(tester, "Load GLB");
await tester.pump();
await tap(tester, "Scene");
await tap(tester, "Assets");
await tap(tester, "Load skybox", 1);
await tap(tester, "Scene");
await tap(tester, "Assets");
await tap(tester, "Load IBL", 1);
final Offset pointerLocation =
tester.getCenter(find.byType(FilamentWidget));
@@ -111,7 +123,7 @@ void main() {
await tester.pumpAndSettle();
await tester.sendEventToBinding(testPointer.scroll(const Offset(0.0, 1.0)));
await tester.pumpAndSettle();
await _snapshot(tester, device, "zoomin");
await _snapshot(tester, "zoomin");
// rotate
testPointer =
@@ -127,7 +139,7 @@ void main() {
await tester.pumpAndSettle();
await tester.sendEventToBinding(testPointer.up());
await _snapshot(tester, device, "rotate", 2);
await _snapshot(tester, "rotate", 2);
// pan
testPointer = TestPointer(1, PointerDeviceKind.mouse, null, kPrimaryButton);
@@ -144,19 +156,35 @@ void main() {
await tester.sendEventToBinding(testPointer.up());
await tester.pumpAndSettle();
await _snapshot(tester, device, "pan");
await _snapshot(tester, "pan");
await tap(tester, "transform to unit cube");
await tap(tester, "set shapes position to 1, 1, -1");
await tap(tester, "Scene");
await tap(tester, "Assets");
await tap(tester, "Shapes");
await tap(tester, "Transform to unit cube");
await tap(tester, "Scene");
await tap(tester, "Assets");
await tap(tester, "Shapes");
await tap(tester, "Set position to 1, 1, -1");
await tap(tester, "Scene");
await tap(tester, "Camera");
await tap(tester, "Disable frustum culling");
await tap(tester, "Set tone mapping to linear");
await tap(tester, "Move camera to asset");
await tap(tester, "move camera to 1, 1, -1");
await tap(tester, 'set camera to first camera in shapes GLB');
await tap(tester, 'resize');
await tap(tester, 'resize');
await tap(tester, 'resize');
await tap(tester, 'resize');
await tap(tester, "Scene");
await tap(tester, "Rendering");
await tap(tester, "Set tone mapping to linear");
await tap(tester, "Scene");
await tap(tester, "Camera");
await tap(tester, 'Set to first camera in last added asset');
await tap(tester, "Move to last added asset");
await tap(tester, "Move to 1, 1, -1");
await tap(tester, 'Toggle viewport size', 1);
await tap(tester, 'Toggle viewport size', 1);
await tap(tester, 'Toggle viewport size', 1);
});
}

View File

@@ -1,34 +1,40 @@
PODS:
- Flutter (1.0.0)
- flutter_filament (0.0.1):
- Flutter
- integration_test (0.0.1):
- Flutter
- path_provider_foundation (0.0.1):
- Flutter
- FlutterMacOS
- polyvox_filament (0.0.1):
- permission_handler_apple (9.1.1):
- Flutter
DEPENDENCIES:
- Flutter (from `Flutter`)
- flutter_filament (from `.symlinks/plugins/flutter_filament/ios`)
- integration_test (from `.symlinks/plugins/integration_test/ios`)
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
- polyvox_filament (from `.symlinks/plugins/polyvox_filament/ios`)
- permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`)
EXTERNAL SOURCES:
Flutter:
:path: Flutter
flutter_filament:
:path: ".symlinks/plugins/flutter_filament/ios"
integration_test:
:path: ".symlinks/plugins/integration_test/ios"
path_provider_foundation:
:path: ".symlinks/plugins/path_provider_foundation/darwin"
polyvox_filament:
:path: ".symlinks/plugins/polyvox_filament/ios"
permission_handler_apple:
:path: ".symlinks/plugins/permission_handler_apple/ios"
SPEC CHECKSUMS:
Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
flutter_filament: 9d744e795935e0fc5308e46a0c5947cb91714848
integration_test: 13825b8a9334a850581300559b8839134b124670
path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943
polyvox_filament: 35fece7761e74c973afd80fe3aa0ca225eaace32
permission_handler_apple: e76247795d700c14ea09e3a2d8855d41ee80a2e6
PODFILE CHECKSUM: 7adbc9d59f05e1b01f554ea99b6c79e97f2214a2

View File

@@ -2,7 +2,7 @@ import Flutter
import UIKit
import XCTest
@testable import polyvox_filament
@testable import flutter_filament
// This demonstrates a simple unit test of the Swift portion of this plugin's implementation.
//
@@ -11,7 +11,7 @@ import XCTest
class RunnerTests: XCTestCase {
func testGetPlatformVersion() {
let plugin = PolyvoxFilamentPlugin()
let plugin = FlutterFilamentPlugin()
let call = FlutterMethodCall(methodName: "getPlatformVersion", arguments: [])

View File

@@ -0,0 +1,65 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_filament/filament_controller.dart';
class CameraMatrixOverlay extends StatefulWidget {
final FilamentController controller;
const CameraMatrixOverlay({super.key, required this.controller});
@override
State<StatefulWidget> createState() => _CameraMatrixOverlayState();
}
class _CameraMatrixOverlayState extends State<CameraMatrixOverlay> {
Timer? _cameraTimer;
String? _cameraPosition;
String? _cameraRotation;
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(() {});
});
}
}
@override
void initState() {
super.initState();
_updateTimer();
widget.controller.hasViewer.addListener(_updateTimer);
}
@override
void dispose() {
super.dispose();
widget.controller.hasViewer.removeListener(_updateTimer);
_cameraTimer?.cancel();
}
@override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
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)));
}
}

View File

@@ -0,0 +1,26 @@
import 'package:flutter/widgets.dart';
import 'package:flutter_filament/filament_controller.dart';
import 'package:flutter_filament/widgets/filament_gesture_detector.dart';
import 'package:flutter_filament/widgets/filament_widget.dart';
class ExampleViewport extends StatelessWidget {
final FilamentController? controller;
final EdgeInsets padding;
const ExampleViewport(
{super.key, required this.controller, required this.padding});
@override
Widget build(BuildContext context) {
return controller != null
? Padding(
padding: padding,
child: FilamentGestureDetector(
showControlOverlay: true,
controller: controller!,
child: FilamentWidget(
controller: controller!,
)))
: Container();
}
}

View File

@@ -1,19 +1,20 @@
import 'dart:async';
import 'dart:io';
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:flutter_filament/filament_controller_ffi.dart';
import 'package:flutter_filament_example/camera_matrix_overlay.dart';
import 'package:flutter_filament_example/menus/controller_menu.dart';
import 'package:flutter_filament_example/example_viewport.dart';
import 'package:flutter_filament_example/picker_result_widget.dart';
import 'package:flutter_filament_example/menus/scene_menu.dart';
import 'package:polyvox_filament/filament_controller.dart';
import 'package:polyvox_filament/animations/bone_animation_data.dart';
import 'package:polyvox_filament/filament_controller_ffi.dart';
import 'package:polyvox_filament/animations/animation_builder.dart';
import 'package:flutter_filament/filament_controller.dart';
import 'package:path_provider/path_provider.dart';
import 'package:polyvox_filament/widgets/filament_gesture_detector.dart';
import 'package:polyvox_filament/widgets/filament_widget.dart';
const loadDefaultScene = bool.hasEnvironment('--load-default-scene');
void main() {
runApp(const MyApp());
void main() async {
print(loadDefaultScene);
runApp(MyApp());
}
class MyApp extends StatefulWidget {
@@ -27,508 +28,144 @@ class _MyAppState extends State<MyApp> with SingleTickerProviderStateMixin {
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(useMaterial3: true),
// showPerformanceOverlay: true,
color: Colors.white,
home: Scaffold(backgroundColor: Colors.white, body: ExampleWidget()));
home: const Scaffold(body: ExampleWidget()));
}
}
class ExampleWidget extends StatefulWidget {
const ExampleWidget({super.key});
@override
State<StatefulWidget> createState() {
return _ExampleWidgetState();
return ExampleWidgetState();
}
}
class _ExampleWidgetState extends State<ExampleWidget> {
enum MenuType { controller, assets, camera, misc }
class ExampleWidgetState extends State<ExampleWidget> {
FilamentController? _filamentController;
FilamentEntity? _shapes;
FilamentEntity? _flightHelmet;
List<String>? _animations;
FilamentEntity? _light;
StreamSubscription? _pickResultListener;
String? picked;
final weights = List.filled(255, 0.0);
bool _loop = false;
EdgeInsets _viewportMargin = EdgeInsets.zero;
bool _readyForScene = false;
// these are all the options that can be set via the menu
// we store them here
static bool rendering = false;
static int framerate = 60;
static bool postProcessing = true;
static bool frustumCulling = true;
static ManipulatorMode cameraManipulatorMode = ManipulatorMode.ORBIT;
bool _rendering = false;
int _framerate = 60;
bool _postProcessing = true;
static double zoomSpeed = 0.01;
static double orbitSpeedX = 0.01;
static double orbitSpeedY = 0.01;
bool _coneHidden = false;
bool _frustumCulling = true;
static FilamentEntity? last;
static bool hasSkybox = false;
static bool coneHidden = false;
static FilamentEntity? shapes;
static FilamentEntity? flightHelmet;
static FilamentEntity? buster;
static List<String>? animations;
static FilamentEntity? directionalLight;
static bool loop = false;
late StreamSubscription _listener;
@override
void initState() {
super.initState();
if (loadDefaultScene) {
WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
setState(() {
_filamentController = FilamentControllerFFI();
});
await Future.delayed(const Duration(milliseconds: 100));
WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
await _filamentController!.createViewer();
await _filamentController!
.loadSkybox("assets/default_env/default_env_skybox.ktx");
await _filamentController!.setRendering(true);
await _filamentController!.loadGlb("assets/shapes/shapes.glb");
});
});
}
}
@override
void dispose() {
super.dispose();
_pickResultListener?.cancel();
}
Widget _item(void Function() onTap, String text) {
return GestureDetector(
onTap: () {
setState(() {
onTap();
});
},
child: Container(
color: Colors.transparent,
padding: EdgeInsets.symmetric(vertical: 10, horizontal: 10),
child: Text(text)));
}
void _createController({String? uberArchivePath}) {
_filamentController =
FilamentControllerFFI(uberArchivePath: uberArchivePath);
_filamentController!.pickResult.listen((entityId) {
setState(() {
picked = _filamentController!.getNameForEntity(entityId!);
});
});
_filamentController!.isReadyForScene.then((readyForScene) {
setState(() {
_readyForScene = readyForScene;
});
});
_listener.cancel();
}
@override
Widget build(BuildContext context) {
var children = <Widget>[];
if (_filamentController == null) {
children.addAll([
_item(() {
_createController();
}, "create viewer (default ubershader)"),
_item(() {
_createController(
uberArchivePath: Platform.isWindows
? "assets/lit_opaque_32.uberz"
: "assets/lit_opaque_43.uberz");
}, "create viewer (custom ubershader - lit opaque only)"),
]);
}
if (_readyForScene) {
children.addAll([
_item(() {
_filamentController!.destroy();
_filamentController = null;
}, "destroy viewer/texture"),
_item(() {
_filamentController!.render();
}, "render"),
_item(() {
setState(() {
_rendering = !_rendering;
_filamentController!.setRendering(_rendering);
});
}, "Rendering: $_rendering"),
_item(() {
setState(() {
_framerate = _framerate == 60 ? 30 : 60;
_filamentController!.setFrameRate(_framerate);
});
}, "$_framerate fps"),
_item(() {
_filamentController!.setBackgroundColor(Color(0xFF73C9FA));
}, "set background color"),
_item(() {
_filamentController!.setBackgroundImage('assets/background.ktx');
}, "load background image"),
_item(() {
_filamentController!
.setBackgroundImage('assets/background.ktx', fillHeight: true);
}, "load background image (fill height)"),
_item(() {
_filamentController!
.loadSkybox('assets/default_env/default_env_skybox.ktx');
}, 'load skybox'),
_item(() {
_filamentController!
.loadIbl('assets/default_env/default_env_ibl.ktx');
}, 'load IBL'),
_item(() async {
_light = await _filamentController!
.addLight(1, 6500, 150000, 0, 1, 0, 0, -1, 0, true);
}, "add directional light"),
_item(() async {
await _filamentController!.clearLights();
}, "clear lights"),
_item(() {
setState(() {
_postProcessing = !_postProcessing;
});
_filamentController!.setPostProcessing(_postProcessing);
}, "${_postProcessing ? "Disable" : "Enable"} postprocessing"),
_item(
() {
_filamentController!.removeSkybox();
},
'remove skybox',
),
_item(() async {
_shapes =
await _filamentController!.loadGlb('assets/shapes/shapes.glb');
_animations = await _filamentController!.getAnimationNames(_shapes!);
setState(() {});
}, 'load shapes GLB'),
_item(() async {
_animations = await _filamentController!.setCamera(_shapes!, null);
setState(() {});
}, 'set camera to first camera in shapes GLB'),
_item(() async {
if (_coneHidden) {
_filamentController!.reveal(_shapes!, "Cone");
} else {
_filamentController!.hide(_shapes!, "Cone");
}
setState(() {
_coneHidden = !_coneHidden;
});
}, _coneHidden ? 'show cone' : 'hide cone'),
_item(() async {
if (_shapes != null) {
_filamentController!.removeAsset(_shapes!);
}
_shapes = await _filamentController!
.loadGltf('assets/shapes/shapes.gltf', 'assets/shapes');
}, 'load shapes GLTF'),
_item(() async {
_filamentController!.transformToUnitCube(_shapes!);
}, 'transform to unit cube'),
_item(() async {
_filamentController!.setPosition(_shapes!, 1.0, 1.0, -1.0);
}, 'set shapes position to 1, 1, -1'),
_item(() async {
_filamentController!.setCameraPosition(1.0, 1.0, -1.0);
}, 'move camera to 1, 1, -1'),
_item(() async {
var frameData = Float32List.fromList(
List<double>.generate(120, (i) => i / 120).expand((x) {
var vals = List<double>.filled(7, x);
vals[3] = 1.0;
// vals[4] = 0;
vals[5] = 0;
vals[6] = 0;
return vals;
}).toList());
_filamentController!.setBoneAnimation(
_shapes!,
BoneAnimationData(
"Bone.001", ["Cube.001"], frameData, 1000.0 / 60.0));
// ,
// "Bone.001",
// "Cube.001",
// BoneTransform([Vec3(x: 0, y: 0.0, z: 0.0)],
// [Quaternion(x: 1, y: 1, z: 1, w: 1)]));
}, 'construct bone animation'),
_item(() async {
_filamentController!.removeAsset(_shapes!);
_shapes = null;
}, 'remove shapes'),
_item(() async {
_filamentController!.clearAssets();
_shapes = null;
}, 'clear all assets'),
_item(() async {
var names = await _filamentController!
.getMorphTargetNames(_shapes!, "Cylinder");
await showDialog(
context: context,
builder: (ctx) {
return Container(
height: 100,
width: 100,
color: Colors.white,
child: Text(names.join(",")));
});
}, "show morph target names for Cylinder"),
_item(() {
_filamentController!
.setMorphTargetWeights(_shapes!, "Cylinder", List.filled(4, 1.0));
}, "set Cylinder morph weights to 1"),
_item(() {
_filamentController!
.setMorphTargetWeights(_shapes!, "Cylinder", List.filled(4, 0.0));
}, "set Cylinder morph weights to 0.0"),
_item(() async {
var morphs = await _filamentController!
.getMorphTargetNames(_shapes!, "Cylinder");
final animation = AnimationBuilder(
availableMorphs: morphs, framerate: 30, meshName: "Cylinder")
.setDuration(4)
.setMorphTargets(["Key 1", "Key 2"])
.interpolateMorphWeights(0, 4, 0, 1)
.build();
_filamentController!.setMorphAnimationData(_shapes!, animation);
}, "animate cylinder morph weights #1 and #2"),
_item(() async {
var morphs = await _filamentController!
.getMorphTargetNames(_shapes!, "Cylinder");
final animation = AnimationBuilder(
availableMorphs: morphs, framerate: 30, meshName: "Cylinder")
.setDuration(4)
.setMorphTargets(["Key 3", "Key 4"])
.interpolateMorphWeights(0, 4, 0, 1)
.build();
_filamentController!.setMorphAnimationData(_shapes!, animation);
}, "animate cylinder morph weights #3 and #4"),
_item(() async {
var morphs =
await _filamentController!.getMorphTargetNames(_shapes!, "Cube");
final animation = AnimationBuilder(
availableMorphs: morphs, framerate: 30, meshName: "Cube")
.setDuration(4)
.setMorphTargets(["Key 1", "Key 2"])
.interpolateMorphWeights(0, 4, 0, 1)
.build();
_filamentController!.setMorphAnimationData(_shapes!, animation);
}, "animate shapes morph weights #1 and #2"),
_item(() {
_filamentController!
.setMaterialColor(_shapes!, "Cone", 0, Colors.purple);
}, "set cone material color to purple"),
_item(() {
_loop = !_loop;
setState(() {});
}, "toggle animation looping ${_loop ? "OFF" : "ON"}"),
_item(() {
setState(() {
_viewportMargin = _viewportMargin == EdgeInsets.zero
? EdgeInsets.all(50)
: EdgeInsets.zero;
});
}, "resize")
]);
if (_animations != null) {
children.addAll(_animations!.map((a) => _item(() {
_filamentController!.playAnimation(
_shapes!, _animations!.indexOf(a),
replaceActive: true, crossfade: 0.5, loop: _loop);
}, "play animation ${_animations!.indexOf(a)} (replace/fade)")));
children.addAll(_animations!.map((a) => _item(() {
_filamentController!.playAnimation(
_shapes!, _animations!.indexOf(a),
replaceActive: false, loop: _loop);
}, "play animation ${_animations!.indexOf(a)} (noreplace)")));
}
children.add(_item(() {
_filamentController!.setToneMapping(ToneMapper.LINEAR);
}, "Set tone mapping to linear"));
children.add(_item(() {
_filamentController!.moveCameraToAsset(_shapes!);
}, "Move camera to asset"));
children.add(_item(() {
setState(() {
_frustumCulling = !_frustumCulling;
});
_filamentController!.setViewFrustumCulling(_frustumCulling);
}, "${_frustumCulling ? "Disable" : "Enable"} frustum culling"));
}
return Stack(children: [
_filamentController != null
? Positioned.fill(
child: Padding(
Positioned.fill(
child: ExampleViewport(
controller: _filamentController,
padding: _viewportMargin,
child: FilamentGestureDetector(
showControlOverlay: true,
controller: _filamentController!,
child: FilamentWidget(
controller: _filamentController!,
))))
: Container(),
Positioned(
right: 50,
top: 50,
child: Text(picked ?? "",
style: const TextStyle(color: Colors.green, fontSize: 24))),
),
),
Align(
alignment: Alignment.bottomCenter,
child: OrientationBuilder(builder: (ctx, orientation) {
return Container(
alignment: Alignment.bottomCenter,
height: orientation == Orientation.landscape ? 100 : 200,
color: Colors.white.withOpacity(0.75),
child: SingleChildScrollView(child: Wrap(children: children)));
}))
child: Container(
padding: const EdgeInsets.only(bottom: 30),
height: 100,
color: Colors.white,
child: Row(crossAxisAlignment: CrossAxisAlignment.end, children: [
ControllerMenu(
controller: _filamentController,
onControllerDestroyed: () {},
onControllerCreated: (controller) {
setState(() {
_filamentController = controller;
_listener = _filamentController!.onLoad
.listen((FilamentEntity entity) {
print("Set last to $entity");
last = entity;
if (mounted) {
setState(() {});
}
print(_filamentController!.getNameForEntity(entity) ??
"NAME NOT FOUND");
});
});
}),
SceneMenu(
controller: _filamentController,
),
Expanded(child: Container()),
TextButton(
child: const Text("Toggle viewport size"),
onPressed: () {
setState(() {
_viewportMargin = (_viewportMargin == EdgeInsets.zero)
? const EdgeInsets.all(30)
: EdgeInsets.zero;
});
},
)
]))),
_filamentController == null
? Container()
: Padding(
padding: const EdgeInsets.only(top: 40, left: 20, right: 20),
child: CameraMatrixOverlay(controller: _filamentController!),
),
_filamentController == null
? Container()
: Align(
alignment: Alignment.topRight,
child: PickerResultWidget(controller: _filamentController!),
)
]);
}
}
// _item(24 () async { 'rotate by pi around Y axis'),
// _item(5 () async { 'load flight helmet'),
// _item(7 () async { 'set all weights to 1'),
// _item(8 () async { 'set all weights to 0'),
// _item(9 () async { 'play all animations'),
// _item(34 () async { 'play animation 0'),
// _item(34 () async { 'play animation 0 (noreplace)'),
// _item(35 () async { 'play animation 1'),
// _item(34 () async { 'play animation 0 (noreplace)'),
// _item(36 () async { 'play animation 2'),
// _item(34 () async { 'play animation 0 (noreplace)'),
// _item(36 () async { 'play animation 3'),
// _item(34 () async { 'play animation 3 (noreplace)'),
// _item(37 () async { 'stop animation 0'),
// _item(14 () async { 'set camera'),
// _item(15 () async { 'animate weights'),
// _item(16 () async { 'get target names'),
// _item(17 () async { 'get animation names'),
// _item(18 () async { 'pan left'),
// _item(19 () async { 'pan right'),
// _item(25 () async {
// Text(_vertical ? 'set horizontal' : 'set vertical')),
// _item(26 () async { 'set camera pos to 0,0,3'),
// _item(27 () async { 'toggle framerate'),
// _item(28 () async { 'set bg image pos'),
// _item(29 () async { 'add light'),
// _item(30 () async { 'remove light'),
// _item(31 () async { 'clear all lights'),
// _item(32 () async { 'set camera model matrix'),
// case -1:
// break;
// case -2:
// _filamentController!.render();
// break;
// case -4:
// setState(() {
// _rendering = !_rendering;
// _filamentController!.setRendering(_rendering);
// });
// break;
// case -5:
// setState(() {
// _framerate = _framerate == 60 ? 30 : 60;
// _filamentController!.setFrameRate(_framerate);
// });
// break;
// case -6:
// _filamentController!.setBackgroundColor(Color(0xFF73C9FA));
// break;
// case 5:
// _flightHelmet ??= await _filamentController!.loadGltf(
// 'assets/FlightHelmet/FlightHelmet.gltf', 'assets/FlightHelmet');
// break;
// case 11:
// setState(() {
// _loop = !_loop;
// });
// break;
// case 14:
// _filamentController!.setCamera(_shapes!, "Camera_Orientation");
// break;
// case 15:
// break;
// case 17:
// var animationNames =
// await _filamentController!.getAnimationNames(_shapes!);
// await showDialog(
// context: context,
// builder: (ctx) {
// return Container(
// height: 100,
// width: 100,
// color: Colors.white,
// child: Text(animationNames.join(",")));
// });
// break;
// case 18:
// _filamentController!.panStart(1, 1);
// _filamentController!.panUpdate(1, 2);
// _filamentController!.panEnd();
// break;
// case 19:
// _filamentController!.panStart(1, 1);
// _filamentController!.panUpdate(0, 0);
// _filamentController!.panEnd();
// break;
// case 20:
// _filamentController!.clearAssets();
// break;
// case 21:
// break;
// case 22:
// break;
// case 23:
// break;
// case 24:
// _filamentController!.setRotation(_shapes!, pi / 2, 0.0, 1.0, 0.0);
// break;
// case 26:
// _filamentController!.setCameraPosition(0, 0, 3);
// _filamentController!.setCameraRotation(0, 0, 1, 0);
// break;
// case 27:
// _framerate = _framerate == 60 ? 30 : 60;
// _filamentController!.setFrameRate(_framerate);
// break;
// case 28:
// _filamentController!.setBackgroundImagePosition(25, 25);
// break;
// case 30:
// if (_light != null) {
// _filamentController!.removeLight(_light!);
// _light = null;
// }
// break;
// case 31:
// break;
// case 32:
// // break;
// break;
// case 33:
// break;
// case 34:
// var duration =
// await _filamentController!.getAnimationDuration(_shapes!, 0);
// _filamentController!.playAnimation(_shapes!, 0,
// loop: false, crossfade: 0.5);
// await Future.delayed(
// Duration(milliseconds: (duration * 1000.0).toInt()));
// print("animation complete");
// // showDialog(
// // context: context,
// // builder: (context) {
// // return Container(
// // width: 100,
// // height: 100,
// // color: Colors.white,
// // child: "animation complete!");
// // });
// break;
// case 35:
// _filamentController!.playAnimation(_shapes!, 1,
// loop: false, crossfade: 0.5);
// break;
// case 36:
// _filamentController!.playAnimation(_shapes!, 2,
// loop: false, crossfade: 0.5);
// break;
// case 37:
// _filamentController!.stopAnimation(_shapes!, 0);
// break;

View File

@@ -0,0 +1,309 @@
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_filament/filament_controller.dart';
import 'package:flutter_filament_example/main.dart';
import 'package:permission_handler/permission_handler.dart';
class AssetSubmenu extends StatefulWidget {
final FilamentController controller;
const AssetSubmenu({super.key, required this.controller});
@override
State<StatefulWidget> createState() => _AssetSubmenuState();
}
class _AssetSubmenuState extends State<AssetSubmenu> {
@override
void initState() {
super.initState();
}
Widget _shapesSubmenu() {
var children = [
MenuItemButton(
onPressed: () async {
if (ExampleWidgetState.shapes == null) {
ExampleWidgetState.shapes =
await widget.controller.loadGlb('assets/shapes/shapes.glb');
ExampleWidgetState.animations = await widget.controller
.getAnimationNames(ExampleWidgetState.shapes!);
} else {
await widget.controller.removeAsset(ExampleWidgetState.shapes!);
ExampleWidgetState.shapes = null;
ExampleWidgetState.animations = null;
}
},
child: const Text('Load GLB')),
MenuItemButton(
onPressed: ExampleWidgetState.shapes != null
? null
: () async {
if (ExampleWidgetState.shapes != null) {
widget.controller.removeAsset(ExampleWidgetState.shapes!);
}
ExampleWidgetState.shapes = await widget.controller
.loadGltf('assets/shapes/shapes.gltf', 'assets/shapes');
},
child: const Text('Load GLTF')),
MenuItemButton(
onPressed: ExampleWidgetState.shapes == null
? null
: () async {
await widget.controller
.transformToUnitCube(ExampleWidgetState.shapes!);
},
child: const Text('Transform to unit cube')),
MenuItemButton(
onPressed: () async {
var names = await widget.controller
.getMorphTargetNames(ExampleWidgetState.shapes!, "Cylinder");
await showDialog(
context: context,
builder: (ctx) {
return Container(
height: 100,
width: 100,
color: Colors.white,
child: Text(names.join(",")));
});
},
child: const Text("Show morph target names for Cylinder")),
MenuItemButton(
onPressed: () async {
widget.controller.setMorphTargetWeights(
ExampleWidgetState.shapes!, "Cylinder", List.filled(4, 1.0));
},
child: const Text("set Cylinder morph weights to 1")),
MenuItemButton(
onPressed: () async {
widget.controller.setMorphTargetWeights(
ExampleWidgetState.shapes!, "Cylinder", List.filled(4, 0.0));
},
child: const Text("Set Cylinder morph weights to 0")),
MenuItemButton(
onPressed: () async {
widget.controller
.setPosition(ExampleWidgetState.shapes!, 1.0, 1.0, -1.0);
},
child: const Text('Set position to 1, 1, -1'),
),
MenuItemButton(
onPressed: () async {
if (ExampleWidgetState.coneHidden) {
widget.controller.reveal(ExampleWidgetState.shapes!, "Cone");
} else {
widget.controller.hide(ExampleWidgetState.shapes!, "Cone");
}
ExampleWidgetState.coneHidden = !ExampleWidgetState.coneHidden;
},
child:
Text(ExampleWidgetState.coneHidden ? 'show cone' : 'hide cone')),
MenuItemButton(
onPressed: ExampleWidgetState.shapes == null
? null
: () async {
widget.controller.setMaterialColor(
ExampleWidgetState.shapes!, "Cone", 0, Colors.purple);
},
child: const Text("Set cone material color to purple")),
MenuItemButton(
onPressed: () async {
ExampleWidgetState.loop = !ExampleWidgetState.loop;
},
child: Text(
"Toggle animation looping ${ExampleWidgetState.loop ? "OFF" : "ON"}"))
];
if (ExampleWidgetState.animations != null) {
children.addAll(ExampleWidgetState.animations!.map((a) => MenuItemButton(
onPressed: () {
widget.controller.playAnimation(ExampleWidgetState.shapes!,
ExampleWidgetState.animations!.indexOf(a),
replaceActive: true,
crossfade: 0.5,
loop: ExampleWidgetState.loop);
},
child: Text(
"play animation ${ExampleWidgetState.animations!.indexOf(a)} (replace/fade)"))));
children.addAll(ExampleWidgetState.animations!.map((a) => MenuItemButton(
onPressed: () {
widget.controller.playAnimation(ExampleWidgetState.shapes!,
ExampleWidgetState.animations!.indexOf(a),
replaceActive: false, loop: ExampleWidgetState.loop);
},
child: Text(
"Play animation ${ExampleWidgetState.animations!.indexOf(a)} (noreplace)"))));
}
return SubmenuButton(menuChildren: children, child: const Text("Shapes"));
}
@override
Widget build(BuildContext context) {
return SubmenuButton(
menuChildren: [
_shapesSubmenu(),
MenuItemButton(
onPressed: () async {
ExampleWidgetState.directionalLight = await widget.controller
.addLight(1, 6500, 150000, 0, 1, 0, 0, -1, 0, true);
},
child: const Text("Add directional light"),
),
MenuItemButton(
onPressed: () async {
await widget.controller.clearLights();
},
child: const Text("Clear lights"),
),
MenuItemButton(
onPressed: () async {
if (ExampleWidgetState.buster == null) {
ExampleWidgetState.buster = await widget.controller.loadGltf(
"assets/BusterDrone/scene.gltf", "assets/BusterDrone",
force: true);
await widget.controller
.playAnimation(ExampleWidgetState.buster!, 0, loop: true);
ExampleWidgetState.animations = await widget.controller
.getAnimationNames(ExampleWidgetState.shapes!);
} else {
await widget.controller.removeAsset(ExampleWidgetState.buster!);
ExampleWidgetState.buster = null;
}
},
child: Text(ExampleWidgetState.buster == null
? 'Load buster'
: 'Remove buster')),
MenuItemButton(
onPressed: () async {
if (ExampleWidgetState.flightHelmet == null) {
ExampleWidgetState.flightHelmet ??= await widget.controller
.loadGltf('assets/FlightHelmet/FlightHelmet.gltf',
'assets/FlightHelmet',
force: true);
} else {
await widget.controller
.removeAsset(ExampleWidgetState.flightHelmet!);
ExampleWidgetState.flightHelmet = null;
}
},
child: Text(ExampleWidgetState.flightHelmet == null
? 'Load flight helmet'
: 'Remove flight helmet')),
MenuItemButton(
onPressed: () {
widget.controller.setBackgroundColor(const Color(0xFF73C9FA));
},
child: const Text("Set background color")),
MenuItemButton(
onPressed: () {
widget.controller.setBackgroundImage('assets/background.ktx');
},
child: const Text("Load background image")),
MenuItemButton(
onPressed: () {
widget.controller.setBackgroundImage('assets/background.ktx',
fillHeight: true);
},
child: const Text("Load background image (fill height)")),
MenuItemButton(
onPressed: () {
if (ExampleWidgetState.hasSkybox) {
widget.controller.removeSkybox();
} else {
widget.controller
.loadSkybox('assets/default_env/default_env_skybox.ktx');
}
ExampleWidgetState.hasSkybox = !ExampleWidgetState.hasSkybox;
},
child: Text(ExampleWidgetState.hasSkybox
? 'Remove skybox'
: 'Load skybox')),
MenuItemButton(
onPressed: () {
widget.controller
.loadIbl('assets/default_env/default_env_ibl.ktx');
},
child: const Text('Load IBL')),
MenuItemButton(
onPressed: () async {
await Permission.microphone.request();
},
child: const Text("Request permissions (tests inactive->resume)")),
MenuItemButton(
onPressed: () async {
await widget.controller.clearAssets();
ExampleWidgetState.flightHelmet = null;
ExampleWidgetState.buster = null;
ExampleWidgetState.shapes = null;
},
child: const Text('Clear assets')),
],
child: const Text("Assets"),
);
}
}
// _item(() async {
// var frameData = Float32List.fromList(
// List<double>.generate(120, (i) => i / 120).expand((x) {
// var vals = List<double>.filled(7, x);
// vals[3] = 1.0;
// // vals[4] = 0;
// vals[5] = 0;
// vals[6] = 0;
// return vals;
// }).toList());
// widget.controller!.setBoneAnimation(
// _shapes!,
// BoneAnimationData(
// "Bone.001", ["Cube.001"], frameData, 1000.0 / 60.0));
// // ,
// // "Bone.001",
// // "Cube.001",
// // BoneTransform([Vec3(x: 0, y: 0.0, z: 0.0)],
// // [Quaternion(x: 1, y: 1, z: 1, w: 1)]));
// }, 'construct bone animation'),
// _item(() async {
// var morphs = await widget.controller!
// .getMorphTargetNames(_shapes!, "Cylinder");
// final animation = AnimationBuilder(
// availableMorphs: morphs,
// framerate: 30,
// meshName: "Cylinder")
// .setDuration(4)
// .setMorphTargets(["Key 1", "Key 2"])
// .interpolateMorphWeights(0, 4, 0, 1)
// .build();
// widget.controller!.setMorphAnimationData(_shapes!, animation);
// }, "animate cylinder morph weights #1 and #2"),
// _item(() async {
// var morphs = await widget.controller!
// .getMorphTargetNames(_shapes!, "Cylinder");
// final animation = AnimationBuilder(
// availableMorphs: morphs,
// framerate: 30,
// meshName: "Cylinder")
// .setDuration(4)
// .setMorphTargets(["Key 3", "Key 4"])
// .interpolateMorphWeights(0, 4, 0, 1)
// .build();
// widget.controller!.setMorphAnimationData(_shapes!, animation);
// }, "animate cylinder morph weights #3 and #4"),
// _item(() async {
// var morphs = await widget.controller!
// .getMorphTargetNames(_shapes!, "Cube");
// final animation = AnimationBuilder(
// availableMorphs: morphs, framerate: 30, meshName: "Cube")
// .setDuration(4)
// .setMorphTargets(["Key 1", "Key 2"])
// .interpolateMorphWeights(0, 4, 0, 1)
// .build();
// widget.controller!.setMorphAnimationData(_shapes!, animation);
// }, "animate shapes morph weights #1 and #2"),

View File

@@ -0,0 +1,171 @@
import 'dart:async';
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:flutter_filament/filament_controller.dart';
import 'package:flutter_filament_example/main.dart';
class CameraSubmenu extends StatefulWidget {
final FilamentController controller;
const CameraSubmenu({super.key, required this.controller});
@override
State<StatefulWidget> createState() => _CameraSubmenuState();
}
class _CameraSubmenuState extends State<CameraSubmenu> {
List<Widget> _cameraMenu() {
return [
MenuItemButton(
onPressed: () async {
widget.controller.setCameraPosition(1.0, 1.0, -1.0);
},
child: const Text('Move to 1, 1, -1'),
),
MenuItemButton(
onPressed: ExampleWidgetState.last == null
? null
: () async {
await widget.controller
.setCamera(ExampleWidgetState.last!, null);
},
child: const Text('Set to first camera in last added asset'),
),
MenuItemButton(
onPressed: ExampleWidgetState.last == null
? null
: () async {
await widget.controller
.moveCameraToAsset(ExampleWidgetState.last!);
},
child: const Text("Move to last added asset"),
),
MenuItemButton(
onPressed: () {
widget.controller.setCameraRotation(pi / 4, 0.0, 1.0, 0.0);
},
child: const Text("Rotate camera 45 degrees around y axis"),
),
MenuItemButton(
onPressed: () {
ExampleWidgetState.frustumCulling =
!ExampleWidgetState.frustumCulling;
widget.controller
.setViewFrustumCulling(ExampleWidgetState.frustumCulling);
},
child: Text(
"${ExampleWidgetState.frustumCulling ? "Disable" : "Enable"} frustum culling"),
),
MenuItemButton(
closeOnActivate: false,
onPressed: () async {
var projMatrix =
await widget.controller.getCameraProjectionMatrix();
await showDialog(
context: context,
builder: (ctx) {
return Center(
child: Container(
height: 100,
width: 300,
color: Colors.white,
child: Text(projMatrix.storage
.map((v) => v.toStringAsFixed(2))
.join(","))));
});
},
child: const Text("Get projection matrix")),
MenuItemButton(
closeOnActivate: false,
onPressed: () async {
var frustum = await widget.controller.getCameraFrustum();
await showDialog(
context: context,
builder: (ctx) {
return Center(
child: Container(
height: 300,
width: 300,
color: Colors.white,
child: Text(frustum.toString())));
});
},
child: const Text("Get frustum")),
SubmenuButton(
menuChildren: ManipulatorMode.values.map((mm) {
return MenuItemButton(
onPressed: () {
ExampleWidgetState.cameraManipulatorMode = mm;
widget.controller.setCameraManipulatorOptions(
mode: ExampleWidgetState.cameraManipulatorMode,
orbitSpeedX: ExampleWidgetState.orbitSpeedX,
orbitSpeedY: ExampleWidgetState.orbitSpeedY,
zoomSpeed: ExampleWidgetState.zoomSpeed);
},
child: Text(
mm.name,
style: TextStyle(
fontWeight: ExampleWidgetState.cameraManipulatorMode == mm
? FontWeight.bold
: FontWeight.normal),
),
);
}).toList(),
child: const Text("Manipulator mode")),
SubmenuButton(
menuChildren: [0.01, 0.1, 1.0, 10.0, 100.0].map((speed) {
return MenuItemButton(
onPressed: () {
ExampleWidgetState.zoomSpeed = speed;
widget.controller.setCameraManipulatorOptions(
mode: ExampleWidgetState.cameraManipulatorMode,
orbitSpeedX: ExampleWidgetState.orbitSpeedX,
orbitSpeedY: ExampleWidgetState.orbitSpeedY,
zoomSpeed: ExampleWidgetState.zoomSpeed);
},
child: Text(
speed.toString(),
style: TextStyle(
fontWeight:
(speed - ExampleWidgetState.zoomSpeed).abs() < 0.0001
? FontWeight.bold
: FontWeight.normal),
),
);
}).toList(),
child: const Text("Zoom speed")),
SubmenuButton(
menuChildren: [0.001, 0.01, 0.1, 1.0].map((speed) {
return MenuItemButton(
onPressed: () {
ExampleWidgetState.orbitSpeedX = speed;
ExampleWidgetState.orbitSpeedY = speed;
widget.controller.setCameraManipulatorOptions(
mode: ExampleWidgetState.cameraManipulatorMode,
orbitSpeedX: ExampleWidgetState.orbitSpeedX,
orbitSpeedY: ExampleWidgetState.orbitSpeedY,
zoomSpeed: ExampleWidgetState.zoomSpeed);
},
child: Text(
speed.toString(),
style: TextStyle(
fontWeight:
(speed - ExampleWidgetState.orbitSpeedX).abs() < 0.0001
? FontWeight.bold
: FontWeight.normal),
),
);
}).toList(),
child: const Text("Orbit speed (X & Y)"))
];
}
@override
Widget build(BuildContext context) {
return SubmenuButton(
menuChildren: _cameraMenu(),
child: const Text("Camera"),
);
}
}

View File

@@ -0,0 +1,117 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_filament/filament_controller.dart';
import 'package:flutter_filament/filament_controller_ffi.dart';
class ControllerMenu extends StatefulWidget {
final FilamentController? controller;
final void Function(FilamentController controller) onControllerCreated;
final void Function() onControllerDestroyed;
ControllerMenu(
{this.controller,
required this.onControllerCreated,
required this.onControllerDestroyed});
@override
State<StatefulWidget> createState() => _ControllerMenuState();
}
class _ControllerMenuState extends State<ControllerMenu> {
FilamentController? _filamentController;
final FocusNode _buttonFocusNode = FocusNode(debugLabel: 'Camera Menu');
void _createController({String? uberArchivePath}) {
if (_filamentController != null) {
throw Exception("Controller already exists");
}
_filamentController =
FilamentControllerFFI(uberArchivePath: uberArchivePath);
widget.onControllerCreated(_filamentController!);
}
@override
void initState() {
super.initState();
_filamentController = widget.controller;
}
@override
void didUpdateWidget(ControllerMenu oldWidget) {
super.didUpdateWidget(oldWidget);
if (widget.controller != _filamentController) {
setState(() {
_filamentController = widget.controller;
});
}
}
@override
Widget build(BuildContext context) {
var items = <Widget>[];
if (_filamentController?.hasViewer.value != true) {
items.addAll([
MenuItemButton(
child: const Text("Create FilamentViewer"),
onPressed: _filamentController == null
? null
: () {
_filamentController!.createViewer();
},
),
MenuItemButton(
child: const Text("Create FilamentController (default ubershader)"),
onPressed: () {
_createController();
},
),
MenuItemButton(
child: const Text(
"Create FilamentController (custom ubershader - lit opaque only)"),
onPressed: () {
_createController(
uberArchivePath: Platform.isWindows
? "assets/lit_opaque_32.uberz"
: Platform.isMacOS
? "assets/lit_opaque_43.uberz"
: Platform.isIOS
? "assets/lit_opaque_43.uberz"
: "assets/lit_opaque_43_gles.uberz");
},
)
]);
} else {
items.addAll([
MenuItemButton(
child: const Text("Destroy viewer"),
onPressed: () {
_filamentController!.destroy();
_filamentController = null;
widget.onControllerDestroyed();
setState(() {});
},
)
]);
}
return MenuAnchor(
childFocusNode: _buttonFocusNode,
menuChildren: items,
builder:
(BuildContext context, MenuController controller, Widget? child) {
return Align(
alignment: Alignment.bottomLeft,
child: TextButton(
onPressed: () {
if (controller.isOpen) {
controller.close();
} else {
controller.open();
}
},
child: const Text("Controller / Viewer"),
));
});
}
}

View File

@@ -0,0 +1,63 @@
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_filament/filament_controller.dart';
import 'package:flutter_filament_example/main.dart';
class RenderingSubmenu extends StatefulWidget {
final FilamentController controller;
const RenderingSubmenu({super.key, required this.controller});
@override
State<StatefulWidget> createState() => _RenderingSubmenuState();
}
class _RenderingSubmenuState extends State<RenderingSubmenu> {
@override
Widget build(BuildContext context) {
return SubmenuButton(
menuChildren: [
MenuItemButton(
onPressed: () {
widget.controller.render();
},
child: const Text("Render single frame"),
),
MenuItemButton(
onPressed: () {
ExampleWidgetState.rendering = !ExampleWidgetState.rendering;
widget.controller.setRendering(ExampleWidgetState.rendering);
},
child: Text(
"Set continuous rendering to ${!ExampleWidgetState.rendering}"),
),
MenuItemButton(
onPressed: () {
ExampleWidgetState.framerate =
ExampleWidgetState.framerate == 60 ? 30 : 60;
widget.controller.setFrameRate(ExampleWidgetState.framerate);
},
child: Text(
"Toggle framerate (currently $ExampleWidgetState.framerate) "),
),
MenuItemButton(
onPressed: () {
widget.controller.setToneMapping(ToneMapper.LINEAR);
},
child: const Text("Set tone mapping to linear"),
),
MenuItemButton(
onPressed: () {
ExampleWidgetState.postProcessing =
!ExampleWidgetState.postProcessing;
widget.controller
.setPostProcessing(ExampleWidgetState.postProcessing);
},
child: Text(
"${ExampleWidgetState.postProcessing ? "Disable" : "Enable"} postprocessing"),
),
],
child: const Text("Rendering"),
);
}
}

View File

@@ -0,0 +1,68 @@
import 'package:flutter/material.dart';
import 'package:flutter_filament/filament_controller.dart';
import 'package:flutter_filament_example/menus/asset_submenu.dart';
import 'package:flutter_filament_example/menus/camera_submenu.dart';
import 'package:flutter_filament_example/menus/rendering_submenu.dart';
class SceneMenu extends StatefulWidget {
final FilamentController? controller;
const SceneMenu({super.key, required this.controller});
@override
State<StatefulWidget> createState() {
return _SceneMenuState();
}
}
class _SceneMenuState extends State<SceneMenu> {
@override
void didUpdateWidget(SceneMenu oldWidget) {
super.didUpdateWidget(oldWidget);
if (widget.controller != null &&
widget.controller != oldWidget.controller ||
widget.controller!.hasViewer != oldWidget.controller!.hasViewer) {
setState(() {});
}
}
@override
Widget build(BuildContext context) {
return ValueListenableBuilder(
valueListenable:
widget.controller?.hasViewer ?? ValueNotifier<bool>(false),
builder: (BuildContext ctx, bool hasViewer, Widget? child) {
return MenuAnchor(
menuChildren: widget.controller == null
? []
: <Widget>[
RenderingSubmenu(
controller: widget.controller!,
),
AssetSubmenu(controller: widget.controller!),
CameraSubmenu(
controller: widget.controller!,
),
],
builder: (BuildContext context, MenuController controller,
Widget? child) {
return Align(
alignment: Alignment.bottomLeft,
child: TextButton(
onPressed: !hasViewer
? null
: () {
if (controller.isOpen) {
controller.close();
} else {
controller.open();
}
},
child: const Text("Scene"),
));
},
);
});
}
}

View File

@@ -0,0 +1,23 @@
import 'package:flutter/material.dart';
import 'package:flutter_filament/filament_controller.dart';
class PickerResultWidget extends StatelessWidget {
final FilamentController controller;
const PickerResultWidget({required this.controller, super.key});
@override
Widget build(BuildContext context) {
return StreamBuilder(
stream: controller.pickResult.map((FilamentEntity? entityId) {
if (entityId == null) {
return null;
}
return controller.getNameForEntity(entityId);
}),
builder: (ctx, snapshot) => snapshot.data == null
? Container()
: Text(snapshot.data!,
style: const TextStyle(color: Colors.green, fontSize: 24)));
}
}

View File

@@ -4,10 +4,10 @@ project(runner LANGUAGES CXX)
# The name of the executable created for the application. Change this to change
# the on-disk name of your application.
set(BINARY_NAME "polyvox_filament_example")
set(BINARY_NAME "flutter_filament_example")
# The unique GTK application identifier for this application. See:
# https://wiki.gnome.org/HowDoI/ChooseApplicationID
set(APPLICATION_ID "app.polyvox.polyvox_filament")
set(APPLICATION_ID "app.polyvox.flutter_filament")
# Explicitly opt in to modern CMake behaviors to avoid warnings with recent
# versions of CMake.

View File

@@ -6,10 +6,10 @@
#include "generated_plugin_registrant.h"
#include <polyvox_filament/polyvox_filament_plugin.h>
#include <flutter_filament/flutter_filament_plugin.h>
void fl_register_plugins(FlPluginRegistry* registry) {
g_autoptr(FlPluginRegistrar) polyvox_filament_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "PolyvoxFilamentPlugin");
polyvox_filament_plugin_register_with_registrar(polyvox_filament_registrar);
g_autoptr(FlPluginRegistrar) flutter_filament_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterFilamentPlugin");
flutter_filament_plugin_register_with_registrar(flutter_filament_registrar);
}

View File

@@ -3,7 +3,7 @@
#
list(APPEND FLUTTER_PLUGIN_LIST
polyvox_filament
flutter_filament
)
list(APPEND FLUTTER_FFI_PLUGIN_LIST

View File

@@ -40,11 +40,11 @@ static void my_application_activate(GApplication* application) {
if (use_header_bar) {
GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new());
gtk_widget_show(GTK_WIDGET(header_bar));
gtk_header_bar_set_title(header_bar, "polyvox_filament_example");
gtk_header_bar_set_title(header_bar, "flutter_filament_example");
gtk_header_bar_set_show_close_button(header_bar, TRUE);
gtk_window_set_titlebar(window, GTK_WIDGET(header_bar));
} else {
gtk_window_set_title(window, "polyvox_filament_example");
gtk_window_set_title(window, "flutter_filament_example");
}
gtk_window_set_default_size(window, 1280, 720);

View File

@@ -5,10 +5,10 @@
import FlutterMacOS
import Foundation
import flutter_filament
import path_provider_foundation
import polyvox_filament
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
SwiftFlutterFilamentPlugin.register(with: registry.registrar(forPlugin: "SwiftFlutterFilamentPlugin"))
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
SwiftPolyvoxFilamentPlugin.register(with: registry.registrar(forPlugin: "SwiftPolyvoxFilamentPlugin"))
}

View File

@@ -1,28 +1,28 @@
PODS:
- flutter_filament (0.0.1):
- FlutterMacOS
- FlutterMacOS (1.0.0)
- path_provider_foundation (0.0.1):
- Flutter
- FlutterMacOS
- polyvox_filament (0.0.1):
- FlutterMacOS
DEPENDENCIES:
- flutter_filament (from `Flutter/ephemeral/.symlinks/plugins/flutter_filament/macos`)
- FlutterMacOS (from `Flutter/ephemeral`)
- path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin`)
- polyvox_filament (from `Flutter/ephemeral/.symlinks/plugins/polyvox_filament/macos`)
EXTERNAL SOURCES:
flutter_filament:
:path: Flutter/ephemeral/.symlinks/plugins/flutter_filament/macos
FlutterMacOS:
:path: Flutter/ephemeral
path_provider_foundation:
:path: Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin
polyvox_filament:
:path: Flutter/ephemeral/.symlinks/plugins/polyvox_filament/macos
SPEC CHECKSUMS:
flutter_filament: ddf9db01d70cce6c8f3a34f414562ebdb43c7f36
FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24
path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943
polyvox_filament: 410c2b06ba59f1182e2fa4338b583903631fb95f
PODFILE CHECKSUM: 9cc8fc8fc62b1d9a89fd6f974ad4157b35254030

7
example/makefile Normal file
View File

@@ -0,0 +1,7 @@
include ../makefile
# building on MacOS, we currently just delete the macos/include
# and macos/src directories and copy from iOS
sync-libs-macos-and-update-pods: sync-libs-macos
pushd macos && pod update

View File

@@ -1,6 +1,14 @@
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
archive:
dependency: transitive
description:
name: archive
sha256: "7e0d52067d05f2e0324268097ba723b71cb41ac8a6a2b24d1edf9c536b987b03"
url: "https://pub.dev"
source: hosted
version: "3.4.6"
async:
dependency: transitive
description:
@@ -37,10 +45,26 @@ packages:
dependency: transitive
description:
name: collection
sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687
sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a
url: "https://pub.dev"
source: hosted
version: "1.17.2"
version: "1.18.0"
convert:
dependency: transitive
description:
name: convert
sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592"
url: "https://pub.dev"
source: hosted
version: "3.1.1"
crypto:
dependency: "direct dev"
description:
name: crypto
sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab
url: "https://pub.dev"
source: hosted
version: "3.0.3"
cupertino_icons:
dependency: "direct main"
description:
@@ -65,11 +89,31 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.1.0"
file:
dependency: transitive
description:
name: file
sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c"
url: "https://pub.dev"
source: hosted
version: "7.0.0"
flutter:
dependency: "direct main"
description: flutter
source: sdk
version: "0.0.0"
flutter_driver:
dependency: transitive
description: flutter
source: sdk
version: "0.0.0"
flutter_filament:
dependency: "direct main"
description:
path: ".."
relative: true
source: path
version: "0.5.0"
flutter_lints:
dependency: "direct dev"
description:
@@ -88,6 +132,40 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
fuchsia_remote_debug_protocol:
dependency: transitive
description: flutter
source: sdk
version: "0.0.0"
image:
dependency: transitive
description:
name: image
sha256: "8e9d133755c3e84c73288363e6343157c383a0c6c56fc51afcc5d4d7180306d6"
url: "https://pub.dev"
source: hosted
version: "3.3.0"
image_compare:
dependency: "direct dev"
description:
name: image_compare
sha256: "774e9ef1558ca328191fe9690e8e024159a3a2db6ea4ef6b65bea0faa3631b74"
url: "https://pub.dev"
source: hosted
version: "1.1.2"
integration_test:
dependency: "direct dev"
description: flutter
source: sdk
version: "0.0.0"
intl:
dependency: transitive
description:
name: intl
sha256: "3bc132a9dbce73a7e4a21a17d06e1878839ffbf975568bc875c60537824b0c4d"
url: "https://pub.dev"
source: hosted
version: "0.18.1"
js:
dependency: transitive
description:
@@ -96,6 +174,30 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.6.7"
leak_tracker:
dependency: transitive
description:
name: leak_tracker
sha256: f38a2c91c12f31726ca13015fbab3d2e9440edcb7c17b8b36ed9b85ed6eee6a2
url: "https://pub.dev"
source: hosted
version: "9.0.11"
leak_tracker_flutter_testing:
dependency: transitive
description:
name: leak_tracker_flutter_testing
sha256: "23770c69594f5260a79fe9d84e29f8b175d1b05d128e751c904b3cdf910e5dfc"
url: "https://pub.dev"
source: hosted
version: "1.0.9"
leak_tracker_testing:
dependency: transitive
description:
name: leak_tracker_testing
sha256: b06739349ec2477e943055aea30172c5c7000225f79dad4702e2ec0eda79a6ff
url: "https://pub.dev"
source: hosted
version: "1.0.5"
lints:
dependency: transitive
description:
@@ -116,18 +218,18 @@ packages:
dependency: transitive
description:
name: material_color_utilities
sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41"
sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a"
url: "https://pub.dev"
source: hosted
version: "0.5.0"
version: "0.8.0"
meta:
dependency: transitive
description:
name: meta
sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3"
sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04
url: "https://pub.dev"
source: hosted
version: "1.9.1"
version: "1.11.0"
path:
dependency: transitive
description:
@@ -184,14 +286,62 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.2.1"
permission_handler:
dependency: "direct main"
description:
name: permission_handler
sha256: "284a66179cabdf942f838543e10413246f06424d960c92ba95c84439154fcac8"
url: "https://pub.dev"
source: hosted
version: "11.0.1"
permission_handler_android:
dependency: transitive
description:
name: permission_handler_android
sha256: f9fddd3b46109bd69ff3f9efa5006d2d309b7aec0f3c1c5637a60a2d5659e76e
url: "https://pub.dev"
source: hosted
version: "11.1.0"
permission_handler_apple:
dependency: transitive
description:
name: permission_handler_apple
sha256: "99e220bce3f8877c78e4ace901082fb29fa1b4ebde529ad0932d8d664b34f3f5"
url: "https://pub.dev"
source: hosted
version: "9.1.4"
permission_handler_platform_interface:
dependency: transitive
description:
name: permission_handler_platform_interface
sha256: "6760eb5ef34589224771010805bea6054ad28453906936f843a8cc4d3a55c4a4"
url: "https://pub.dev"
source: hosted
version: "3.12.0"
permission_handler_windows:
dependency: transitive
description:
name: permission_handler_windows
sha256: cc074aace208760f1eee6aa4fae766b45d947df85bc831cde77009cdb4720098
url: "https://pub.dev"
source: hosted
version: "0.1.3"
petitparser:
dependency: transitive
description:
name: petitparser
sha256: eeb2d1428ee7f4170e2bd498827296a18d4e7fc462b71727d111c0ac7707cfa6
url: "https://pub.dev"
source: hosted
version: "6.0.1"
platform:
dependency: transitive
description:
name: platform
sha256: ae68c7bfcd7383af3629daafb32fb4e8681c7154428da4febcff06200585f102
sha256: "0a279f0707af40c890e80b1e9df8bb761694c074ba7e1d4ab1bc4b728e200b59"
url: "https://pub.dev"
source: hosted
version: "3.1.2"
version: "3.1.3"
plugin_platform_interface:
dependency: transitive
description:
@@ -200,13 +350,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.1.6"
polyvox_filament:
dependency: "direct main"
pointycastle:
dependency: transitive
description:
path: ".."
relative: true
source: path
version: "0.0.1"
name: pointycastle
sha256: "7c1e5f0d23c9016c5bbd8b1473d0d3fb3fc851b876046039509e18e0c7485f2c"
url: "https://pub.dev"
source: hosted
version: "3.7.3"
process:
dependency: transitive
description:
name: process
sha256: "266ca5be5820feefc777793d0a583acfc8c40834893c87c00c6c09e2cf58ea42"
url: "https://pub.dev"
source: hosted
version: "5.0.1"
sky_engine:
dependency: transitive
description: flutter
@@ -224,18 +383,18 @@ packages:
dependency: transitive
description:
name: stack_trace
sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5
sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b"
url: "https://pub.dev"
source: hosted
version: "1.11.0"
version: "1.11.1"
stream_channel:
dependency: transitive
description:
name: stream_channel
sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8"
sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7
url: "https://pub.dev"
source: hosted
version: "2.1.1"
version: "2.1.2"
string_scanner:
dependency: transitive
description:
@@ -244,6 +403,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.2.0"
sync_http:
dependency: transitive
description:
name: sync_http
sha256: "7f0cd72eca000d2e026bcd6f990b81d0ca06022ef4e32fb257b30d3d1014a961"
url: "https://pub.dev"
source: hosted
version: "0.3.1"
term_glyph:
dependency: transitive
description:
@@ -256,10 +423,10 @@ packages:
dependency: transitive
description:
name: test_api
sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8"
sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b"
url: "https://pub.dev"
source: hosted
version: "0.6.0"
version: "0.6.1"
tuple:
dependency: transitive
description:
@@ -268,6 +435,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.0.2"
typed_data:
dependency: transitive
description:
name: typed_data
sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c
url: "https://pub.dev"
source: hosted
version: "1.3.2"
universal_io:
dependency: transitive
description:
name: universal_io
sha256: "1722b2dcc462b4b2f3ee7d188dad008b6eb4c40bbd03a3de451d82c78bba9aad"
url: "https://pub.dev"
source: hosted
version: "2.2.2"
vector_math:
dependency: transitive
description:
@@ -276,30 +459,46 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.1.4"
wasm_ffi:
vm_service:
dependency: transitive
description:
name: wasm_ffi
sha256: "5da66560305dd659d62caef535c5314abd9302c122e6eef8681e6879fbbfe358"
name: vm_service
sha256: a13d5503b4facefc515c8c587ce3cf69577a7b064a9f1220e005449cf1f64aad
url: "https://pub.dev"
source: hosted
version: "0.9.4"
version: "12.0.0"
web:
dependency: transitive
description:
name: web
sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10
sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152
url: "https://pub.dev"
source: hosted
version: "0.1.4-beta"
version: "0.3.0"
web_socket_channel:
dependency: transitive
description:
name: web_socket_channel
sha256: d88238e5eac9a42bb43ca4e721edba3c08c6354d4a53063afaa568516217621b
url: "https://pub.dev"
source: hosted
version: "2.4.0"
webdriver:
dependency: transitive
description:
name: webdriver
sha256: "003d7da9519e1e5f329422b36c4dcdf18d7d2978d1ba099ea4e45ba490ed845e"
url: "https://pub.dev"
source: hosted
version: "3.0.3"
win32:
dependency: transitive
description:
name: win32
sha256: c97defd418eef4ec88c0d1652cdce84b9f7b63dd7198e266d06ac1710d527067
sha256: "350a11abd2d1d97e0cc7a28a81b781c08002aa2864d9e3f192ca0ffa18b06ed3"
url: "https://pub.dev"
source: hosted
version: "5.0.8"
version: "5.0.9"
xdg_directories:
dependency: transitive
description:
@@ -308,6 +507,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.0.3"
xml:
dependency: transitive
description:
name: xml
sha256: af5e77e9b83f2f4adc5d3f0a4ece1c7f45a2467b695c2540381bac793e34e556
url: "https://pub.dev"
source: hosted
version: "6.4.2"
sdks:
dart: ">=3.1.0-185.0.dev <3.11.0"
flutter: ">=3.7.0"
dart: ">=3.2.0-194.0.dev <4.0.0"
flutter: ">=3.16.0-0.2.pre"

View File

@@ -1,12 +1,12 @@
name: polyvox_filament_example
description: Demonstrates how to use the polyvox_filament plugin.
name: flutter_filament_example
description: Demonstrates how to use the flutter_filament plugin.
# The following line prevents the package from being accidentally published to
# pub.dev using `flutter pub publish`. This is preferred for private packages.
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
environment:
sdk: ">=2.12.0 <4.0.0"
sdk: ">=3.0.0 <4.0.0"
# Dependencies specify other packages that your package needs in order to work.
# To automatically upgrade your package dependencies to the latest versions
@@ -18,9 +18,9 @@ dependencies:
flutter:
sdk: flutter
path_provider:
polyvox_filament:
flutter_filament:
path: ../
permission_handler:
cupertino_icons: ^1.0.2
dev_dependencies:
@@ -29,7 +29,6 @@ dev_dependencies:
integration_test:
sdk: flutter
flutter_lints: ^1.0.0
golden_toolkit: ^0.15.0
crypto:
image_compare: ^1.1.2

View File

@@ -8,7 +8,7 @@
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:polyvox_filament_example/main.dart';
import 'package:flutter_filament_example/main.dart';
void main() {
testWidgets('Verify Platform version', (WidgetTester tester) async {

View File

@@ -18,18 +18,18 @@
<meta charset="UTF-8">
<meta content="IE=Edge" http-equiv="X-UA-Compatible">
<meta name="description" content="Demonstrates how to use the polyvox_filament plugin.">
<meta name="description" content="Demonstrates how to use the flutter_filament plugin.">
<!-- iOS meta tags & icons -->
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="apple-mobile-web-app-title" content="polyvox_filament_example">
<meta name="apple-mobile-web-app-title" content="flutter_filament_example">
<link rel="apple-touch-icon" href="icons/Icon-192.png">
<!-- Favicon -->
<link rel="icon" type="image/png" href="favicon.png"/>
<title>polyvox_filament_example</title>
<title>flutter_filament_example</title>
<link rel="manifest" href="manifest.json">
<script>

View File

@@ -1,11 +1,11 @@
{
"name": "polyvox_filament_example",
"short_name": "polyvox_filament_example",
"name": "flutter_filament_example",
"short_name": "flutter_filament_example",
"start_url": ".",
"display": "standalone",
"background_color": "#0175C2",
"theme_color": "#0175C2",
"description": "Demonstrates how to use the polyvox_filament plugin.",
"description": "Demonstrates how to use the flutter_filament plugin.",
"orientation": "portrait-primary",
"prefer_related_applications": false,
"icons": [

View File

@@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.14)
project(polyvox_filament_example LANGUAGES CXX)
project(flutter_filament_example LANGUAGES CXX)
set(BINARY_NAME "polyvox_filament_example")
set(BINARY_NAME "flutter_filament_example")
cmake_policy(SET CMP0063 NEW)

View File

@@ -6,9 +6,12 @@
#include "generated_plugin_registrant.h"
#include <polyvox_filament/polyvox_filament_plugin_c_api.h>
#include <flutter_filament/flutter_filament_plugin_c_api.h>
#include <permission_handler_windows/permission_handler_windows_plugin.h>
void RegisterPlugins(flutter::PluginRegistry* registry) {
PolyvoxFilamentPluginCApiRegisterWithRegistrar(
registry->GetRegistrarForPlugin("PolyvoxFilamentPluginCApi"));
FlutterFilamentPluginCApiRegisterWithRegistrar(
registry->GetRegistrarForPlugin("FlutterFilamentPluginCApi"));
PermissionHandlerWindowsPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("PermissionHandlerWindowsPlugin"));
}

View File

@@ -3,7 +3,8 @@
#
list(APPEND FLUTTER_PLUGIN_LIST
polyvox_filament
flutter_filament
permission_handler_windows
)
list(APPEND FLUTTER_FFI_PLUGIN_LIST

View File

@@ -90,12 +90,12 @@ BEGIN
BLOCK "040904e4"
BEGIN
VALUE "CompanyName", "app.polyvox" "\0"
VALUE "FileDescription", "polyvox_filament_example" "\0"
VALUE "FileDescription", "flutter_filament_example" "\0"
VALUE "FileVersion", VERSION_AS_STRING "\0"
VALUE "InternalName", "polyvox_filament_example" "\0"
VALUE "InternalName", "flutter_filament_example" "\0"
VALUE "LegalCopyright", "Copyright (C) 2022 app.polyvox. All rights reserved." "\0"
VALUE "OriginalFilename", "polyvox_filament_example.exe" "\0"
VALUE "ProductName", "polyvox_filament_example" "\0"
VALUE "OriginalFilename", "flutter_filament_example.exe" "\0"
VALUE "ProductName", "flutter_filament_example" "\0"
VALUE "ProductVersion", VERSION_AS_STRING "\0"
END
END

View File

@@ -27,7 +27,7 @@ int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev,
FlutterWindow window(project);
Win32Window::Point origin(10, 10);
Win32Window::Size size(1280, 720);
if (!window.CreateAndShow(L"polyvox_filament_example", origin, size)) {
if (!window.CreateAndShow(L"flutter_filament_example", origin, size)) {
return EXIT_FAILURE;
}
window.SetQuitOnClose(true);

View File

@@ -1,4 +1,4 @@
#import <Flutter/Flutter.h>
@interface PolyvoxFilamentPlugin : NSObject<FlutterPlugin>
@interface FlutterFilamentPlugin : NSObject<FlutterPlugin>
@end

View File

@@ -1,18 +1,18 @@
#import "PolyvoxFilamentPlugin.h"
#if __has_include(<polyvox_filament/polyvox_filament-Swift.h>)
#import <polyvox_filament/polyvox_filament-Swift.h>
#import "FlutterFilamentPlugin.h"
#if __has_include(<flutter_filament/flutter_filament-Swift.h>)
#import <flutter_filament/flutter_filament-Swift.h>
#else
// Support project import fallback if the generated compatibility header
// is not copied when this plugin is created as a library.
// https://forums.swift.org/t/swift-static-libraries-dont-copy-generated-objective-c-header/19816
#import "polyvox_filament-Swift.h"
#import "flutter_filament-Swift.h"
#endif
#include "PolyvoxFilamentApi.h"
#include "FlutterFilamentApi.h"
@implementation PolyvoxFilamentPlugin
@implementation FlutterFilamentPlugin
+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
[SwiftPolyvoxFilamentPlugin registerWithRegistrar:registrar];
[SwiftFlutterFilamentPlugin registerWithRegistrar:registrar];
ios_dummy();
}
@end

View File

@@ -2,7 +2,7 @@ import Flutter
import UIKit
import GLKit
public class SwiftPolyvoxFilamentPlugin: NSObject, FlutterPlugin, FlutterTexture {
public class SwiftFlutterFilamentPlugin: NSObject, FlutterPlugin, FlutterTexture {
var registrar : FlutterPluginRegistrar
var flutterTextureId: Int64?
@@ -25,7 +25,7 @@ public class SwiftPolyvoxFilamentPlugin: NSObject, FlutterPlugin, FlutterTexture
var loadResource : @convention(c) (UnsafePointer<Int8>?, UnsafeMutableRawPointer?) -> ResourceBuffer = { uri, resourcesPtr in
let instance:SwiftPolyvoxFilamentPlugin = Unmanaged<SwiftPolyvoxFilamentPlugin>.fromOpaque(resourcesPtr!).takeUnretainedValue()
let instance:SwiftFlutterFilamentPlugin = Unmanaged<SwiftFlutterFilamentPlugin>.fromOpaque(resourcesPtr!).takeUnretainedValue()
let uriString = String(cString:uri!)
@@ -121,12 +121,12 @@ public class SwiftPolyvoxFilamentPlugin: NSObject, FlutterPlugin, FlutterTexture
}
var freeResource : @convention(c) (ResourceBuffer,UnsafeMutableRawPointer?) -> () = { rbuf, resourcesPtr in
let instance:SwiftPolyvoxFilamentPlugin = Unmanaged<SwiftPolyvoxFilamentPlugin>.fromOpaque(resourcesPtr!).takeUnretainedValue()
let instance:SwiftFlutterFilamentPlugin = Unmanaged<SwiftFlutterFilamentPlugin>.fromOpaque(resourcesPtr!).takeUnretainedValue()
instance.resources.removeObject(forKey:rbuf.id)
}
var markTextureFrameAvailable : @convention(c) (UnsafeMutableRawPointer?) -> () = { instancePtr in
let instance:SwiftPolyvoxFilamentPlugin = Unmanaged<SwiftPolyvoxFilamentPlugin>.fromOpaque(instancePtr!).takeUnretainedValue()
let instance:SwiftFlutterFilamentPlugin = Unmanaged<SwiftFlutterFilamentPlugin>.fromOpaque(instancePtr!).takeUnretainedValue()
instance.registry.textureFrameAvailable(instance.flutterTextureId!)
}
@@ -145,7 +145,7 @@ public class SwiftPolyvoxFilamentPlugin: NSObject, FlutterPlugin, FlutterTexture
let _messenger = registrar.messenger();
messenger = _messenger;
let channel = FlutterMethodChannel(name: "app.polyvox.filament/event", binaryMessenger: _messenger)
let instance = SwiftPolyvoxFilamentPlugin(textureRegistry: registrar.textures(), registrar:registrar)
let instance = SwiftFlutterFilamentPlugin(textureRegistry: registrar.textures(), registrar:registrar)
registrar.addMethodCallDelegate(instance, channel: channel)
}
@@ -166,8 +166,6 @@ public class SwiftPolyvoxFilamentPlugin: NSObject, FlutterPlugin, FlutterTexture
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
let methodName = call.method;
switch methodName {
case "getSharedContext":
result(nil)
case "getResourceLoaderWrapper":
let resourceLoaderWrapper = make_resource_loader(loadResource, freeResource, Unmanaged.passUnretained(self).toOpaque())
result(unsafeBitCast(resourceLoaderWrapper, to:Int64.self))
@@ -180,7 +178,7 @@ public class SwiftPolyvoxFilamentPlugin: NSObject, FlutterPlugin, FlutterTexture
createPixelBuffer(width:Int(args[0]), height:Int(args[1]))
let pixelBufferPtr = unsafeBitCast(pixelBuffer!, to:UnsafeRawPointer.self)
let pixelBufferAddress = Int(bitPattern:pixelBufferPtr);
result([self.flutterTextureId, pixelBufferAddress, nil])
result([self.flutterTextureId, pixelBufferAddress, nil, nil])
case "destroyTexture":
if(self.flutterTextureId != nil) {
self.registry.unregisterTexture(self.flutterTextureId!)
@@ -188,17 +186,6 @@ public class SwiftPolyvoxFilamentPlugin: NSObject, FlutterPlugin, FlutterTexture
self.flutterTextureId = nil
self.pixelBuffer = nil
result(true)
case "resize":
let args = call.arguments as! [Any]
let width = UInt32(args[0] as! Int64)
let height = UInt32(args[1] as! Int64)
if(self.flutterTextureId != nil) {
self.registry.unregisterTexture(self.flutterTextureId!)
}
createPixelBuffer(width: Int(width), height:Int(height))
var pixelBufferTextureId = unsafeBitCast(pixelBuffer!, to: UnsafeRawPointer.self)
print("Resized to \(args[0])x\(args[1])")
result(self.flutterTextureId);
case "dummy":
ios_dummy()
ios_dummy_ffi()

View File

@@ -1,9 +1,9 @@
#
# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html.
# Run `pod lib lint polyvox_filament.podspec` to validate before publishing.
# Run `pod lib lint flutter_filament.podspec` to validate before publishing.
#
Pod::Spec.new do |s|
s.name = 'polyvox_filament'
s.name = 'flutter_filament'
s.version = '0.0.1'
s.summary = 'A new flutter plugin project.'
s.description = <<-DESC
@@ -14,7 +14,7 @@ A new flutter plugin project.
s.author = { 'Your Company' => 'email@example.com' }
s.source = { :path => '.' }
s.source_files = 'Classes/*', 'src/*', "src/camutils/*", 'src/ios/*', 'include/filament/*', 'include/*', 'include/material/*.c'
s.public_header_files = 'include/SwiftPolyvoxFilamentPlugin-Bridging-Header.h', 'include/PolyvoxFilamentApi.h', 'include/PolyvoxFilamentFFIApi.h', 'include/ResourceBuffer.hpp', 'include/Log.hpp'
s.public_header_files = 'include/SwiftFlutterFilamentPlugin-Bridging-Header.h', 'include/FlutterFilamentApi.h', 'include/FlutterFilamentFFIApi.h', 'include/ResourceBuffer.hpp', 'include/Log.hpp'
s.dependency 'Flutter'
s.platform = :ios, '12.1'
s.static_framework = true
@@ -24,10 +24,10 @@ A new flutter plugin project.
'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386',
"CLANG_CXX_LANGUAGE_STANDARD" => "c++17",
'OTHER_CFLAGS' => '"-fvisibility=default" "$(inherited)"',
'USER_HEADER_SEARCH_PATHS' => '"${PODS_ROOT}/../.symlinks/plugins/polyvox_filament/ios/include" "${PODS_ROOT}/../.symlinks/plugins/polyvox_filament/ios/include/filament" "${PODS_ROOT}/../.symlinks/plugins/polyvox_filament/ios/src" "${PODS_ROOT}/../.symlinks/plugins/polyvox_filament/ios/src/image" "${PODS_ROOT}/../.symlinks/plugins/polyvox_filament/ios/src/shaders" "$(inherited)"',
'USER_HEADER_SEARCH_PATHS' => '"${PODS_ROOT}/../.symlinks/plugins/flutter_filament/ios/include" "${PODS_ROOT}/../.symlinks/plugins/flutter_filament/ios/include/filament" "${PODS_ROOT}/../.symlinks/plugins/flutter_filament/ios/src" "${PODS_ROOT}/../.symlinks/plugins/flutter_filament/ios/src/image" "${PODS_ROOT}/../.symlinks/plugins/flutter_filament/ios/src/shaders" "$(inherited)"',
'ALWAYS_SEARCH_USER_PATHS' => 'YES',
"OTHER_LDFLAGS" => '-lfilament -lbackend -lfilameshio -lviewer -lfilamat -lgeometry -lutils -lfilabridge -lgltfio_core -lfilament-iblprefilter -limage -limageio -ltinyexr -lgltfio_core -lfilaflat -ldracodec -libl -lktxreader -lpng -lpng16 -lz -lstb -luberzlib -lsmol-v -luberarchive -lzstd -lstdc++',
'LIBRARY_SEARCH_PATHS' => '"${PODS_ROOT}/../.symlinks/plugins/polyvox_filament/ios/lib" "$(inherited)"',
'LIBRARY_SEARCH_PATHS' => '"${PODS_ROOT}/../.symlinks/plugins/flutter_filament/ios/lib" "$(inherited)"',
}
s.pod_target_xcconfig = {
@@ -36,10 +36,10 @@ A new flutter plugin project.
"CLANG_CXX_LANGUAGE_STANDARD" => "c++17",
'OTHER_CXXFLAGS' => '"--std=c++17" "-fmodules" "-fcxx-modules" "-fvisibility=default" "$(inherited)"',
'OTHER_CFLAGS' => '"-fvisibility=default" "$(inherited)"',
'USER_HEADER_SEARCH_PATHS' => '"${PODS_ROOT}/../.symlinks/plugins/polyvox_filament/ios/include" "${PODS_ROOT}/../.symlinks/plugins/polyvox_filament/ios/include/filament" "${PODS_ROOT}/../.symlinks/plugins/polyvox_filament/ios/src" "${PODS_ROOT}/../.symlinks/plugins/polyvox_filament/ios/src/image" "${PODS_ROOT}/../.symlinks/plugins/polyvox_filament/ios/src/shaders" "$(inherited)"',
'USER_HEADER_SEARCH_PATHS' => '"${PODS_ROOT}/../.symlinks/plugins/flutter_filament/ios/include" "${PODS_ROOT}/../.symlinks/plugins/flutter_filament/ios/include/filament" "${PODS_ROOT}/../.symlinks/plugins/flutter_filament/ios/src" "${PODS_ROOT}/../.symlinks/plugins/flutter_filament/ios/src/image" "${PODS_ROOT}/../.symlinks/plugins/flutter_filament/ios/src/shaders" "$(inherited)"',
'ALWAYS_SEARCH_USER_PATHS' => 'YES',
"OTHER_LDFLAGS" => '-lfilament -lbackend -lfilameshio -lviewer -lfilamat -lgeometry -lutils -lfilabridge -lgltfio_core -lfilament-iblprefilter -limage -limageio -ltinyexr -lgltfio_core -lfilaflat -ldracodec -libl -lktxreader -lpng -lpng16 -lz -lstb -luberzlib -lsmol-v -luberarchive -lzstd -lstdc++',
'LIBRARY_SEARCH_PATHS' => '"${PODS_ROOT}/../.symlinks/plugins/polyvox_filament/ios/lib" "$(inherited)"',
'LIBRARY_SEARCH_PATHS' => '"${PODS_ROOT}/../.symlinks/plugins/flutter_filament/ios/lib" "$(inherited)"',
}
s.swift_version = '5.0'

View File

@@ -1,5 +1,7 @@
#pragma once
#include <mutex>
#include <filament/Scene.h>
#include <gltfio/AssetLoader.h>
@@ -82,6 +84,7 @@ namespace polyvox {
gltfio::ResourceLoader* _gltfResourceLoader = nullptr;
gltfio::TextureProvider* _stbDecoder = nullptr;
gltfio::TextureProvider* _ktxDecoder = nullptr;
std::mutex _animationMutex;
vector<SceneAsset> _assets;
tsl::robin_map<EntityId, int> _entityIdLookup;

View File

@@ -1,6 +1,7 @@
#pragma once
#include <filament/Camera.h>
#include <filament/Frustum.h>
#include <filament/ColorGrading.h>
#include <filament/Engine.h>
#include <filament/IndexBuffer.h>
@@ -41,13 +42,18 @@ using namespace camutils;
typedef int32_t EntityId;
namespace polyvox {
namespace polyvox
{
enum ToneMapping {
ACES, FILMIC, LINEAR
enum ToneMapping
{
ACES,
FILMIC,
LINEAR
};
class FilamentViewer {
class FilamentViewer
{
public:
FilamentViewer(const void *context, const ResourceLoaderWrapper *const resourceLoaderWrapper, void *const platform = nullptr, const char *uberArchivePath = nullptr);
~FilamentViewer();
@@ -61,7 +67,6 @@ namespace polyvox {
void removeIbl();
void removeAsset(EntityId asset);
// removes all add assets from the current scene
void clearAssets();
void updateViewportAndCameraProjection(int height, int width, float scaleFactor);
@@ -69,13 +74,11 @@ namespace polyvox {
uint64_t frameTimeInNanos,
void *pixelBuffer,
void (*callback)(void *buf, size_t size, void *data),
void* data
);
void *data);
void setFrameInterval(float interval);
bool setCamera(EntityId asset, const char *nodeName);
void createSwapChain(const void *surface, uint32_t width, uint32_t height);
void destroySwapChain();
@@ -87,57 +90,54 @@ namespace polyvox {
void setBackgroundImage(const char *resourcePath, bool fillHeight);
void clearBackgroundImage();
void setBackgroundImagePosition(float x, float y, bool clamp);
// Camera methods
void moveCameraToAsset(EntityId entityId);
void setViewFrustumCulling(bool enabled);
void setCameraExposure(float aperture, float shutterSpeed, float sensitivity);
void setCameraPosition(float x, float y, float z);
void setCameraRotation(float rads, float x, float y, float z);
const math::mat4 getCameraModelMatrix();
const math::mat4 getCameraViewMatrix();
const math::mat4 getCameraProjectionMatrix();
const math::mat4 getCameraCullingProjectionMatrix();
const filament::Frustum getCameraFrustum();
void setCameraModelMatrix(const float *const matrix);
void setCameraProjectionMatrix(const double *const matrix, double near, double far);
void setCameraFocalLength(float fl);
void setCameraFocusDistance(float focusDistance);
void setCameraManipulatorOptions(filament::camutils::Mode mode, double orbitSpeedX, double orbitSpeedY, double zoomSpeed);
void grabBegin(float x, float y, bool pan);
void grabUpdate(float x, float y);
void grabEnd();
void scrollBegin();
void scrollUpdate(float x, float y, float delta);
void scrollEnd();
void pick(uint32_t x, uint32_t y, EntityId *entityId);
int32_t addLight(LightManager::Type t, float colour, float intensity, float posX, float posY, float posZ, float dirX, float dirY, float dirZ, bool shadows);
EntityId addLight(LightManager::Type t, float colour, float intensity, float posX, float posY, float posZ, float dirX, float dirY, float dirZ, bool shadows);
void removeLight(EntityId entityId);
void clearLights();
void setPostProcessing(bool enabled);
void pick(uint32_t x, uint32_t y, EntityId* entityId);
AssetManager* const getAssetManager() {
AssetManager *const getAssetManager()
{
return (AssetManager *const)_assetManager;
}
private:
void createImageRenderable();
void loadResources(std::string relativeResourcePath);
void cleanup();
bool _panning = false;
float _startX;
float _startY;
math::mat4f _cameraPosition;
math::mat4f _cameraRotation;
const ResourceLoaderWrapper *const _resourceLoaderWrapper;
Scene* _scene;
View* _view;
Engine* _engine;
Scene *_scene = nullptr;
View *_view = nullptr;
Engine *_engine = nullptr;
// a default camera that we add to every scene
Camera* _mainCamera;
Renderer* _renderer;
RenderTarget* _rt;
Texture* _rtColor;
Texture* _rtDepth;
Renderer *_renderer = nullptr;
RenderTarget *_rt = nullptr;
Texture *_rtColor = nullptr;
Texture *_rtDepth = nullptr;
SwapChain *_swapChain = nullptr;
@@ -157,8 +157,18 @@ namespace polyvox {
bool _actualSize = false;
// Camera properties
Camera *_mainCamera = nullptr; // the default camera added to every scene. If you want the *active* camera, access via View.
float _cameraFocalLength = 28.0f;
float _cameraFocusDistance = 0.0f;
Manipulator<double> *_manipulator = nullptr;
filament::camutils::Mode _manipulatorMode = filament::camutils::Mode::ORBIT;
double _orbitSpeedX = 0.01;
double _orbitSpeedY = 0.01;
double _zoomSpeed = 0.01;
math::mat4f _cameraPosition;
math::mat4f _cameraRotation;
void _createManipulator();
ColorGrading *colorGrading = nullptr;
@@ -177,13 +187,8 @@ namespace polyvox {
void loadPngTexture(string path, ResourceBuffer data);
void loadTextureFromPath(string path);
Manipulator<double>* _manipulator = nullptr;
void _createManipulator();
uint32_t _lastFrameTimeInNanos;
};
}

View File

@@ -1,5 +1,5 @@
#ifndef _POLYVOX_FILAMENT_API_H
#define _POLYVOX_FILAMENT_API_H
#ifndef _FLUTTER_FILAMENT_API_H
#define _FLUTTER_FILAMENT_API_H
#ifdef _WIN32
#ifdef IS_DLL
@@ -47,11 +47,11 @@
#include "ResourceBuffer.hpp"
typedef int32_t EntityId;
typedef int32_t _ManipulatorMode;
#ifdef __cplusplus
extern "C" {
#endif
typedef int32_t EntityId;
FLUTTER_PLUGIN_EXPORT const void* create_filament_viewer(const void* const context, const ResourceLoaderWrapper* const loader, void* const platform, const char* uberArchivePath);
FLUTTER_PLUGIN_EXPORT void destroy_filament_viewer(const void* const viewer);
@@ -140,20 +140,33 @@ FLUTTER_PLUGIN_EXPORT void transform_to_unit_cube(void* assetManager, EntityId a
FLUTTER_PLUGIN_EXPORT void set_position(void* assetManager, EntityId asset, float x, float y, float z);
FLUTTER_PLUGIN_EXPORT void set_rotation(void* assetManager, EntityId asset, float rads, float x, float y, float z);
FLUTTER_PLUGIN_EXPORT void set_scale(void* assetManager, EntityId asset, float scale);
// Camera methods
FLUTTER_PLUGIN_EXPORT void move_camera_to_asset(const void* const viewer, EntityId asset);
FLUTTER_PLUGIN_EXPORT void set_view_frustum_culling(const void* const viewer, bool enabled);
FLUTTER_PLUGIN_EXPORT void set_camera_exposure(const void* const viewer, float aperture, float shutterSpeed, float sensitivity);
FLUTTER_PLUGIN_EXPORT void set_camera_position(const void* const viewer, float x, float y, float z);
FLUTTER_PLUGIN_EXPORT void get_camera_position(const void* const viewer);
FLUTTER_PLUGIN_EXPORT void set_camera_rotation(const void* const viewer, float rads, float x, float y, float z);
FLUTTER_PLUGIN_EXPORT void set_camera_model_matrix(const void* const viewer, const float *const matrix);
FLUTTER_PLUGIN_EXPORT const double* const get_camera_model_matrix(const void* const viewer);
FLUTTER_PLUGIN_EXPORT const double* const get_camera_view_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 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 void set_camera_focal_length(const void* const viewer, float focalLength);
FLUTTER_PLUGIN_EXPORT void set_camera_focus_distance(const void* const viewer, float focusDistance);
FLUTTER_PLUGIN_EXPORT void set_camera_manipulator_options(const void* const viewer, _ManipulatorMode mode, double orbitSpeedX, double orbitSpeedY, double zoomSpeed);
FLUTTER_PLUGIN_EXPORT int hide_mesh(void* assetManager, EntityId asset, const char* meshName);
FLUTTER_PLUGIN_EXPORT int reveal_mesh(void* assetManager, EntityId asset, const char* meshName);
FLUTTER_PLUGIN_EXPORT void set_post_processing(void* const viewer, bool enabled);
FLUTTER_PLUGIN_EXPORT void pick(void* const viewer, int x, int y, EntityId* entityId);
FLUTTER_PLUGIN_EXPORT const char* get_name_for_entity(void* const assetManager, const EntityId entityId);
FLUTTER_PLUGIN_EXPORT void ios_dummy();
FLUTTER_PLUGIN_EXPORT void flutter_filament_free(void* ptr);
#ifdef __cplusplus
}
#endif

View File

@@ -1,15 +1,15 @@
#ifndef _POLYVOX_FILAMENT_FFI_API_H
#define _POLYVOX_FILAMENT_FFI_API_H
#ifndef _FLUTTER_FILAMENT_FFI_API_H
#define _FLUTTER_FILAMENT_FFI_API_H
#include "PolyvoxFilamentApi.h"
#include "FlutterFilamentApi.h"
#ifdef __cplusplus
extern "C" {
#endif
///
/// This header replicates most of the methods in PolyvoxFilamentApi.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 PolyvoxFilamentApi.h, but wrapped in some kind of thread runner to ensure thread safety.
/// 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 int32_t EntityId;
@@ -92,4 +92,4 @@ FLUTTER_PLUGIN_EXPORT void ios_dummy_ffi();
}
#endif
#endif // _POLYVOX_FILAMENT_FFI_API_H
#endif // _FLUTTER_FILAMENT_FFI_API_H

View File

@@ -0,0 +1,4 @@
#import <Flutter/Flutter.h>
@interface FlutterFilamentPlugin : NSObject<FlutterPlugin>
@end

View File

@@ -1,13 +1,13 @@
#pragma once
#ifndef POLYVOX_FILAMENT_LOG_H
#define POLYVOX_FILAMENT_LOG_H
#ifndef FLUTTER_FILAMENT_LOG_H
#define FLUTTER_FILAMENT_LOG_H
#ifdef __OBJC__
#import <Foundation/Foundation.h>
#elif defined __ANDROID__
#include <android/log.h>
#define LOGTAG "PolyvoxFilament"
#define LOGTAG "FlutterFilament"
#else
#include <stdarg.h>
#include <stdio.h>

View File

@@ -1,4 +0,0 @@
#import <Flutter/Flutter.h>
@interface PolyvoxFilamentPlugin : NSObject<FlutterPlugin>
@end

View File

@@ -20,7 +20,7 @@
#include <utils/NameComponentManager.h>
extern "C" {
#include "PolyvoxFilamentApi.h"
#include "FlutterFilamentApi.h"
}
template class std::vector<float>;
namespace polyvox {

View File

@@ -0,0 +1,8 @@
#ifndef SwiftFlutterFilamentPlugin_Bridging_Header_h
#define SwiftFlutterFilamentPlugin_Bridging_Header_h
#import "FlutterFilamentApi.h"
#import "FlutterFilamentFFIApi.h"
#endif

View File

@@ -1,8 +0,0 @@
#ifndef SwiftPolyvoxFilamentPlugin_Bridging_Header_h
#define SwiftPolyvoxFilamentPlugin_Bridging_Header_h
#import "PolyvoxFilamentApi.h"
#import "PolyvoxFilamentFFIApi.h"
#endif

View File

@@ -15,7 +15,7 @@
#ifndef _THREADPOOL_HPP
#define _THREADPOOL_HPP
namespace polyvox_filament {
namespace flutter_filament {
class ThreadPool {
std::vector<std::thread> pool;

View File

@@ -1,6 +1,7 @@
#include <string>
#include <sstream>
#include <thread>
#include <vector>
#include <filament/Engine.h>
#include <filament/TransformManager.h>
@@ -256,16 +257,18 @@ FilamentAsset* AssetManager::getAssetByEntityId(EntityId entityId) {
void AssetManager::updateAnimations() {
auto now = high_resolution_clock::now();
std::lock_guard lock(_animationMutex);
RenderableManager &rm = _engine->getRenderableManager();
for (auto& asset : _assets) {
vector<int> completed;
std::vector<int> completed;
int index = 0;
for(auto& anim : asset.mAnimations) {
auto now = high_resolution_clock::now();
auto elapsed = float(std::chrono::duration_cast<std::chrono::milliseconds>(now - anim.mStart).count()) / 1000.0f;
if(anim.mLoop || elapsed < anim.mDuration) {
@@ -333,8 +336,9 @@ void AssetManager::updateAnimations() {
asset.mAnimator->updateBoneMatrices();
index++;
}
for(auto& it : completed) {
asset.mAnimations.erase(asset.mAnimations.begin() + it);
for(int i = completed.size() - 1; i >= 0; i--) {
asset.mAnimations.erase(asset.mAnimations.begin() + i);
}
}
}
@@ -463,6 +467,7 @@ bool AssetManager::setMorphAnimationBuffer(
int numMorphTargets,
int numFrames,
float frameLengthInMs) {
std::lock_guard lock(_animationMutex);
const auto& pos = _entityIdLookup.find(entityId);
if(pos == _entityIdLookup.end()) {
@@ -539,6 +544,7 @@ bool AssetManager::setBoneAnimationBuffer(
const char** const meshNames,
int numMeshTargets,
float frameLengthInMs) {
std::lock_guard lock(_animationMutex);
const auto& pos = _entityIdLookup.find(entityId);
if(pos == _entityIdLookup.end()) {
@@ -628,6 +634,8 @@ bool AssetManager::setBoneAnimationBuffer(
void AssetManager::playAnimation(EntityId e, int index, bool loop, bool reverse, bool replaceActive, float crossfade) {
std::lock_guard lock(_animationMutex);
if(index < 0) {
Log("ERROR: glTF animation index must be greater than zero.");
return;
@@ -682,6 +690,8 @@ void AssetManager::playAnimation(EntityId e, int index, bool loop, bool reverse,
}
void AssetManager::stopAnimation(EntityId entityId, int index) {
std::lock_guard lock(_animationMutex);
const auto& pos = _entityIdLookup.find(entityId);
if(pos == _entityIdLookup.end()) {
Log("ERROR: asset not found for entity.");

View File

@@ -677,10 +677,8 @@ namespace polyvox
.texture(RenderTarget::AttachmentPoint::DEPTH, _rtDepth)
.build(*_engine);
// Make a specific viewport just for our render target
_view->setRenderTarget(_rt);
Log("Set render target for texture id %u to %u x %u", texture, width, height);
Log("Created render target for texture id %u (%u x %u)", texture, width, height);
}
void FilamentViewer::destroySwapChain()
@@ -701,6 +699,7 @@ namespace polyvox
_swapChain = nullptr;
Log("Swapchain destroyed.");
}
_engine->flushAndWait();
}
void FilamentViewer::clearAssets()
@@ -983,29 +982,30 @@ namespace polyvox
_frameCount++;
// if a manipulator is active, update the active camera orientation
if(_manipulator) {
if (_manipulator)
{
math::double3 eye, target, upward;
Camera &cam = _view->getCamera();
_manipulator->getLookAt(&eye, &target, &upward);
cam.lookAt(eye, target, upward);
}
// TODO - this was an experiment but probably useful to keep for debugging
// if pixelBuffer is provided, we will copy the framebuffer into the pixelBuffer.
if (pixelBuffer)
{
auto pbd = Texture::PixelBufferDescriptor(
pixelBuffer, size_t(1024 * 768 * 4),
Texture::Format::RGBA,
Texture::Type::BYTE, nullptr, callback, data);
// // TODO - this was an experiment but probably useful to keep for debugging
// // if pixelBuffer is provided, we will copy the framebuffer into the pixelBuffer.
// if (pixelBuffer)
// {
// auto pbd = Texture::PixelBufferDescriptor(
// pixelBuffer, size_t(1024 * 768 * 4),
// Texture::Format::RGBA,
// Texture::Type::BYTE, nullptr, callback, data);
_renderer->beginFrame(_swapChain, 0);
_renderer->render(_view);
_renderer->readPixels(0, 0, 1024, 768, std::move(pbd));
_renderer->endFrame();
}
else
{
// _renderer->beginFrame(_swapChain, 0);
// _renderer->render(_view);
// _renderer->readPixels(0, 0, 1024, 768, std::move(pbd));
// _renderer->endFrame();
// }
// else
// {
// Render the scene, unless the renderer wants to skip the frame.
if (_renderer->beginFrame(_swapChain, frameTimeInNanos))
{
@@ -1014,9 +1014,10 @@ namespace polyvox
}
else
{
// std::cout << "Skipped" << std::endl;
// skipped frame
}
}
// }
}
void FilamentViewer::updateViewportAndCameraProjection(
@@ -1106,25 +1107,93 @@ namespace polyvox
cam.setModelMatrix(modelMatrix);
}
void FilamentViewer::setCameraProjectionMatrix(const double *const matrix, double near, double far)
{
Camera &cam = _view->getCamera();
mat4 projectionMatrix(
matrix[0],
matrix[1],
matrix[2],
matrix[3],
matrix[4],
matrix[5],
matrix[6],
matrix[7],
matrix[8],
matrix[9],
matrix[10],
matrix[11],
matrix[12],
matrix[13],
matrix[14],
matrix[15]);
cam.setCustomProjection(projectionMatrix, near, far);
}
const math::mat4 FilamentViewer::getCameraModelMatrix()
{
const auto &cam = _view->getCamera();
return cam.getModelMatrix();
}
const math::mat4 FilamentViewer::getCameraViewMatrix()
{
const auto &cam = _view->getCamera();
return cam.getViewMatrix();
}
const math::mat4 FilamentViewer::getCameraProjectionMatrix()
{
const auto &cam = _view->getCamera();
return cam.getProjectionMatrix();
}
const math::mat4 FilamentViewer::getCameraCullingProjectionMatrix()
{
const auto &cam = _view->getCamera();
return cam.getCullingProjectionMatrix();
}
const filament::Frustum FilamentViewer::getCameraFrustum()
{
const auto &cam = _view->getCamera();
return cam.getFrustum();
}
void FilamentViewer::_createManipulator()
{
Camera &cam = _view->getCamera();
auto &tm = _engine->getTransformManager();
auto transformInstance = tm.getInstance(cam.getEntity());
auto transform = tm.getTransform(transformInstance);
math::double3 home = cam.getPosition();
math::double3 up = cam.getUpVector();
math::double3 target = home + cam.getForwardVector();
auto fv = cam.getForwardVector();
math::double3 target = home + fv;
Viewport const &vp = _view->getViewport();
Log("Creating manipulator for viewport size %dx%d with camera norm %f", vp.width, vp.height, norm(home));
float zoomSpeed = norm(home) / 10;
zoomSpeed = math::clamp(zoomSpeed, 0.1f, 100000.0f);
Log("Creating manipulator for viewport size %dx%d at home %f %f %f, fv %f %f %f, up %f %f %f target %f %f %f (norm %f) with _zoomSpeed %f", vp.width, vp.height, home[0], home[1], home[2], fv[0], fv[1], fv[2], up[0], up[1], up[2], target[0], target[1], target[2], norm(home), _zoomSpeed);
_manipulator = Manipulator<double>::Builder()
.viewport(vp.width, vp.height)
.orbitHomePosition(home[0], home[1], home[2])
.upVector(up.x, up.y, up.z)
.zoomSpeed(zoomSpeed)
// .orbitSpeed(0.0001, 0.0001)
.zoomSpeed(_zoomSpeed)
.targetPosition(target[0], target[1], target[2])
.build(Mode::ORBIT);
// only applicable to Mode::ORBIT
.orbitHomePosition(home[0], home[1], home[2])
.orbitSpeed(_orbitSpeedX, _orbitSpeedY)
// only applicable to Mode::FREE_FLIGHT
.flightStartPosition(home[0], home[1], home[2])
.build(_manipulatorMode);
}
void FilamentViewer::setCameraManipulatorOptions(filament::camutils::Mode mode, double orbitSpeedX, double orbitSpeedY, double zoomSpeed)
{
_manipulatorMode = mode;
_orbitSpeedX = orbitSpeedX;
_orbitSpeedY = orbitSpeedY;
_zoomSpeed = zoomSpeed;
}
void FilamentViewer::grabBegin(float x, float y, bool pan)
@@ -1138,9 +1207,12 @@ namespace polyvox
{
_createManipulator();
}
if(pan) {
if (pan)
{
Log("Beginning pan at %f %f", x, y);
} else {
}
else
{
Log("Beginning rotate at %f %f", x, y);
}
@@ -1212,9 +1284,8 @@ namespace polyvox
void FilamentViewer::pick(uint32_t x, uint32_t y, EntityId *entityId)
{
_view->pick(x, y, [=](filament::View::PickingQueryResult const &result) {
*entityId = Entity::smuggle(result.renderable);
});
_view->pick(x, y, [=](filament::View::PickingQueryResult const &result)
{ *entityId = Entity::smuggle(result.renderable); });
}
} // namespace polyvox

View File

@@ -0,0 +1,493 @@
#include "ResourceBuffer.hpp"
#include "FilamentViewer.hpp"
#include "filament/LightManager.h"
#include "Log.hpp"
#include "ThreadPool.hpp"
#include <thread>
#include <functional>
using namespace polyvox;
extern "C"
{
#include "FlutterFilamentApi.h"
FLUTTER_PLUGIN_EXPORT const void *create_filament_viewer(const void *context, const ResourceLoaderWrapper *const loader, void *const platform, const char *uberArchivePath)
{
return (const void *)new FilamentViewer(context, loader, platform, uberArchivePath);
}
FLUTTER_PLUGIN_EXPORT ResourceLoaderWrapper *make_resource_loader(LoadFilamentResourceFromOwner loadFn, FreeFilamentResourceFromOwner freeFn, void *const owner)
{
return new ResourceLoaderWrapper(loadFn, freeFn, owner);
}
FLUTTER_PLUGIN_EXPORT void create_render_target(const void *const viewer, intptr_t texture, uint32_t width, uint32_t height)
{
((FilamentViewer *)viewer)->createRenderTarget(texture, width, height);
}
FLUTTER_PLUGIN_EXPORT void destroy_filament_viewer(const void *const viewer)
{
delete ((FilamentViewer *)viewer);
}
FLUTTER_PLUGIN_EXPORT void set_background_color(const void *const viewer, const float r, const float g, const float b, const float a)
{
((FilamentViewer *)viewer)->setBackgroundColor(r, g, b, a);
}
FLUTTER_PLUGIN_EXPORT void clear_background_image(const void *const viewer)
{
((FilamentViewer *)viewer)->clearBackgroundImage();
}
FLUTTER_PLUGIN_EXPORT void set_background_image(const void *const viewer, const char *path, bool fillHeight)
{
((FilamentViewer *)viewer)->setBackgroundImage(path, fillHeight);
}
FLUTTER_PLUGIN_EXPORT void set_background_image_position(const void *const viewer, float x, float y, bool clamp)
{
((FilamentViewer *)viewer)->setBackgroundImagePosition(x, y, clamp);
}
FLUTTER_PLUGIN_EXPORT void set_tone_mapping(const void *const viewer, int toneMapping)
{
((FilamentViewer *)viewer)->setToneMapping((ToneMapping)toneMapping);
}
FLUTTER_PLUGIN_EXPORT void set_bloom(const void *const viewer, float strength)
{
Log("Setting bloom to %f", strength);
((FilamentViewer *)viewer)->setBloom(strength);
}
FLUTTER_PLUGIN_EXPORT void load_skybox(const void *const viewer, const char *skyboxPath)
{
((FilamentViewer *)viewer)->loadSkybox(skyboxPath);
}
FLUTTER_PLUGIN_EXPORT void load_ibl(const void *const viewer, const char *iblPath, float intensity)
{
((FilamentViewer *)viewer)->loadIbl(iblPath, intensity);
}
FLUTTER_PLUGIN_EXPORT void remove_skybox(const void *const viewer)
{
((FilamentViewer *)viewer)->removeSkybox();
}
FLUTTER_PLUGIN_EXPORT void remove_ibl(const void *const viewer)
{
((FilamentViewer *)viewer)->removeIbl();
}
EntityId add_light(const void *const viewer, uint8_t type, float colour, float intensity, float posX, float posY, float posZ, float dirX, float dirY, float dirZ, bool shadows)
{
return ((FilamentViewer *)viewer)->addLight((LightManager::Type)type, colour, intensity, posX, posY, posZ, dirX, dirY, dirZ, shadows);
}
FLUTTER_PLUGIN_EXPORT void remove_light(const void *const viewer, int32_t entityId)
{
((FilamentViewer *)viewer)->removeLight(entityId);
}
FLUTTER_PLUGIN_EXPORT void clear_lights(const void *const viewer)
{
((FilamentViewer *)viewer)->clearLights();
}
FLUTTER_PLUGIN_EXPORT EntityId load_glb(void *assetManager, const char *assetPath, bool unlit)
{
return ((AssetManager *)assetManager)->loadGlb(assetPath, unlit);
}
FLUTTER_PLUGIN_EXPORT EntityId load_gltf(void *assetManager, const char *assetPath, const char *relativePath)
{
return ((AssetManager *)assetManager)->loadGltf(assetPath, relativePath);
}
FLUTTER_PLUGIN_EXPORT bool set_camera(const void *const viewer, EntityId asset, const char *nodeName)
{
return ((FilamentViewer *)viewer)->setCamera(asset, nodeName);
}
const double *const get_camera_model_matrix(const void *const viewer)
{
const auto &modelMatrix = ((FilamentViewer *)viewer)->getCameraModelMatrix();
double *array = (double *)calloc(16, sizeof(double));
memcpy(array, modelMatrix.asArray(), 16 * sizeof(double));
return array;
}
const double *const get_camera_view_matrix(const void *const viewer)
{
const auto &matrix = ((FilamentViewer *)viewer)->getCameraViewMatrix();
double *array = (double *)calloc(16, sizeof(double));
memcpy(array, matrix.asArray(), 16 * sizeof(double));
return array;
}
const double *const get_camera_projection_matrix(const void *const viewer)
{
const auto &matrix = ((FilamentViewer *)viewer)->getCameraProjectionMatrix();
double *array = (double *)calloc(16, sizeof(double));
memcpy(array, matrix.asArray(), 16 * sizeof(double));
return array;
}
const double *const get_camera_culling_projection_matrix(const void *const viewer)
{
const auto &matrix = ((FilamentViewer *)viewer)->getCameraCullingProjectionMatrix();
double *array = (double *)calloc(16, sizeof(double));
memcpy(array, matrix.asArray(), 16 * sizeof(double));
return array;
}
void set_camera_projection_matrix(const void *const viewer, const double* const matrix, double near, double far)
{
((FilamentViewer *)viewer)->setCameraProjectionMatrix(matrix, near, far);
}
const double *const get_camera_frustum(const void *const viewer)
{
const auto frustum = ((FilamentViewer *)viewer)->getCameraFrustum();
const math::float4* planes = frustum.getNormalizedPlanes();
double *array = (double *)calloc(24, sizeof(double));
for(int i =0; i < 6; i++) {
array[i*4] = planes[i].x;
array[i*4+1] = planes[i].y;
array[i*4+2] = planes[i].z;
array[i*4+3] = planes[i].w;
}
return array;
}
FLUTTER_PLUGIN_EXPORT void set_camera_manipulator_options(const void *const viewer, _ManipulatorMode mode, double orbitSpeedX, double orbitSpeedY, double zoomSpeed)
{
((FilamentViewer *)viewer)->setCameraManipulatorOptions((filament::camutils::Mode)mode, orbitSpeedX, orbitSpeedY, zoomSpeed);
}
FLUTTER_PLUGIN_EXPORT void set_view_frustum_culling(const void *const viewer, bool enabled)
{
((FilamentViewer *)viewer)->setViewFrustumCulling(enabled);
}
FLUTTER_PLUGIN_EXPORT void move_camera_to_asset(const void *const viewer, EntityId asset)
{
((FilamentViewer *)viewer)->moveCameraToAsset(asset);
}
FLUTTER_PLUGIN_EXPORT void set_camera_focus_distance(const void *const viewer, float distance)
{
((FilamentViewer *)viewer)->setCameraFocusDistance(distance);
}
FLUTTER_PLUGIN_EXPORT void set_camera_exposure(const void *const viewer, float aperture, float shutterSpeed, float sensitivity)
{
((FilamentViewer *)viewer)->setCameraExposure(aperture, shutterSpeed, sensitivity);
}
FLUTTER_PLUGIN_EXPORT void set_camera_position(const void *const viewer, float x, float y, float z)
{
((FilamentViewer *)viewer)->setCameraPosition(x, y, z);
}
FLUTTER_PLUGIN_EXPORT void set_camera_rotation(const void *const viewer, float rads, float x, float y, float z)
{
((FilamentViewer *)viewer)->setCameraRotation(rads, x, y, z);
}
FLUTTER_PLUGIN_EXPORT void set_camera_model_matrix(const void *const viewer, const float *const matrix)
{
((FilamentViewer *)viewer)->setCameraModelMatrix(matrix);
}
FLUTTER_PLUGIN_EXPORT void set_camera_focal_length(const void *const viewer, float focalLength)
{
((FilamentViewer *)viewer)->setCameraFocalLength(focalLength);
}
FLUTTER_PLUGIN_EXPORT void render(
const void *const viewer,
uint64_t frameTimeInNanos,
void *pixelBuffer,
void (*callback)(void *buf, size_t size, void *data),
void *data)
{
((FilamentViewer *)viewer)->render(frameTimeInNanos, pixelBuffer, callback, data);
}
FLUTTER_PLUGIN_EXPORT void set_frame_interval(
const void *const viewer,
float frameInterval)
{
((FilamentViewer *)viewer)->setFrameInterval(frameInterval);
}
FLUTTER_PLUGIN_EXPORT void destroy_swap_chain(const void *const viewer)
{
((FilamentViewer *)viewer)->destroySwapChain();
}
FLUTTER_PLUGIN_EXPORT void create_swap_chain(const void *const viewer, const void *const window, uint32_t width, uint32_t height)
{
((FilamentViewer *)viewer)->createSwapChain(window, width, height);
}
FLUTTER_PLUGIN_EXPORT void update_viewport_and_camera_projection(const void *const viewer, uint32_t width, uint32_t height, float scaleFactor)
{
return ((FilamentViewer *)viewer)->updateViewportAndCameraProjection(width, height, scaleFactor);
}
FLUTTER_PLUGIN_EXPORT void scroll_update(const void *const viewer, float x, float y, float delta)
{
((FilamentViewer *)viewer)->scrollUpdate(x, y, delta);
}
FLUTTER_PLUGIN_EXPORT void scroll_begin(const void *const viewer)
{
((FilamentViewer *)viewer)->scrollBegin();
}
FLUTTER_PLUGIN_EXPORT void scroll_end(const void *const viewer)
{
((FilamentViewer *)viewer)->scrollEnd();
}
FLUTTER_PLUGIN_EXPORT void grab_begin(const void *const viewer, float x, float y, bool pan)
{
((FilamentViewer *)viewer)->grabBegin(x, y, pan);
}
FLUTTER_PLUGIN_EXPORT void grab_update(const void *const viewer, float x, float y)
{
((FilamentViewer *)viewer)->grabUpdate(x, y);
}
FLUTTER_PLUGIN_EXPORT void grab_end(const void *const viewer)
{
((FilamentViewer *)viewer)->grabEnd();
}
FLUTTER_PLUGIN_EXPORT void *get_asset_manager(const void *const viewer)
{
return (void *)((FilamentViewer *)viewer)->getAssetManager();
}
FLUTTER_PLUGIN_EXPORT void apply_weights(
void *assetManager,
EntityId asset,
const char *const entityName,
float *const weights,
int count)
{
// ((AssetManager*)assetManager)->setMorphTargetWeights(asset, entityName, weights, count);
}
FLUTTER_PLUGIN_EXPORT void set_morph_target_weights(
void *assetManager,
EntityId asset,
const char *const entityName,
const float *const weights,
const int numWeights)
{
return ((AssetManager *)assetManager)->setMorphTargetWeights(asset, entityName, weights, numWeights);
}
bool set_morph_animation(
void *assetManager,
EntityId asset,
const char *const entityName,
const float *const morphData,
const int *const morphIndices,
int numMorphTargets,
int numFrames,
float frameLengthInMs)
{
return ((AssetManager *)assetManager)->setMorphAnimationBuffer(asset, entityName, morphData, morphIndices, numMorphTargets, numFrames, frameLengthInMs);
}
FLUTTER_PLUGIN_EXPORT void set_bone_animation(
void *assetManager,
EntityId asset,
const float *const frameData,
int numFrames,
int numBones,
const char **const boneNames,
const char **const meshNames,
int numMeshTargets,
float frameLengthInMs)
{
((AssetManager *)assetManager)->setBoneAnimationBuffer(asset, frameData, numFrames, numBones, boneNames, meshNames, numMeshTargets, frameLengthInMs);
}
FLUTTER_PLUGIN_EXPORT void set_post_processing(void *const viewer, bool enabled)
{
((FilamentViewer *)viewer)->setPostProcessing(enabled);
}
// void set_bone_transform(
// EntityId asset,
// const char* boneName,
// const char* entityName,
// float transX,
// float transY,
// float transZ,
// float quatX,
// float quatY,
// float quatZ,
// float quatW
// ) {
// ((AssetManager*)assetManager)->setBoneTransform(
// boneName,
// entityName,
// transX,
// transY,
// transZ,
// quatX,
// quatY,
// quatZ,
// quatW,
// false
// );
// }
FLUTTER_PLUGIN_EXPORT void play_animation(
void *assetManager,
EntityId asset,
int index,
bool loop,
bool reverse,
bool replaceActive,
float crossfade)
{
((AssetManager *)assetManager)->playAnimation(asset, index, loop, reverse, replaceActive, crossfade);
}
FLUTTER_PLUGIN_EXPORT void set_animation_frame(
void *assetManager,
EntityId asset,
int animationIndex,
int animationFrame)
{
// ((AssetManager*)assetManager)->setAnimationFrame(asset, animationIndex, animationFrame);
}
float get_animation_duration(void *assetManager, EntityId asset, int animationIndex)
{
return ((AssetManager *)assetManager)->getAnimationDuration(asset, animationIndex);
}
int get_animation_count(
void *assetManager,
EntityId asset)
{
auto names = ((AssetManager *)assetManager)->getAnimationNames(asset);
return (int)names->size();
}
FLUTTER_PLUGIN_EXPORT void get_animation_name(
void *assetManager,
EntityId asset,
char *const outPtr,
int index)
{
auto names = ((AssetManager *)assetManager)->getAnimationNames(asset);
string name = names->at(index);
strcpy(outPtr, name.c_str());
}
FLUTTER_PLUGIN_EXPORT int get_morph_target_name_count(void *assetManager, EntityId asset, const char *meshName)
{
unique_ptr<vector<string>> names = ((AssetManager *)assetManager)->getMorphTargetNames(asset, meshName);
return (int)names->size();
}
FLUTTER_PLUGIN_EXPORT void get_morph_target_name(void *assetManager, EntityId asset, const char *meshName, char *const outPtr, int index)
{
unique_ptr<vector<string>> names = ((AssetManager *)assetManager)->getMorphTargetNames(asset, meshName);
string name = names->at(index);
strcpy(outPtr, name.c_str());
}
FLUTTER_PLUGIN_EXPORT void remove_asset(const void *const viewer, EntityId asset)
{
((FilamentViewer *)viewer)->removeAsset(asset);
}
FLUTTER_PLUGIN_EXPORT void clear_assets(const void *const viewer)
{
((FilamentViewer *)viewer)->clearAssets();
}
bool set_material_color(void *assetManager, EntityId asset, const char *meshName, int materialIndex, const float r, const float g, const float b, const float a)
{
return ((AssetManager *)assetManager)->setMaterialColor(asset, meshName, materialIndex, r, g, b, a);
}
FLUTTER_PLUGIN_EXPORT void transform_to_unit_cube(void *assetManager, EntityId asset)
{
((AssetManager *)assetManager)->transformToUnitCube(asset);
}
FLUTTER_PLUGIN_EXPORT void set_position(void *assetManager, EntityId asset, float x, float y, float z)
{
((AssetManager *)assetManager)->setPosition(asset, x, y, z);
}
FLUTTER_PLUGIN_EXPORT void set_rotation(void *assetManager, EntityId asset, float rads, float x, float y, float z)
{
((AssetManager *)assetManager)->setRotation(asset, rads, x, y, z);
}
FLUTTER_PLUGIN_EXPORT void set_scale(void *assetManager, EntityId asset, float scale)
{
((AssetManager *)assetManager)->setScale(asset, scale);
}
FLUTTER_PLUGIN_EXPORT void stop_animation(void *assetManager, EntityId asset, int index)
{
((AssetManager *)assetManager)->stopAnimation(asset, index);
}
FLUTTER_PLUGIN_EXPORT int hide_mesh(void *assetManager, EntityId asset, const char *meshName)
{
return ((AssetManager *)assetManager)->hide(asset, meshName);
}
FLUTTER_PLUGIN_EXPORT int reveal_mesh(void *assetManager, EntityId asset, const char *meshName)
{
return ((AssetManager *)assetManager)->reveal(asset, meshName);
}
FLUTTER_PLUGIN_EXPORT void pick(void *const viewer, int x, int y, EntityId *entityId)
{
((FilamentViewer *)viewer)->pick(static_cast<uint32_t>(x), static_cast<uint32_t>(y), static_cast<int32_t *>(entityId));
}
FLUTTER_PLUGIN_EXPORT const char *get_name_for_entity(void *const assetManager, const EntityId entityId)
{
return ((AssetManager *)assetManager)->getNameForEntity(entityId);
}
FLUTTER_PLUGIN_EXPORT void ios_dummy()
{
Log("Dummy called");
}
FLUTTER_PLUGIN_EXPORT void flutter_filament_free(void* ptr)
{
free(ptr);
}
}

View File

@@ -1,5 +1,5 @@
#include "PolyvoxFilamentFFIApi.h"
#include "FlutterFilamentFFIApi.h"
#include "FilamentViewer.hpp"
#include "Log.hpp"
@@ -77,8 +77,10 @@ public:
void doRender() {
render(_viewer, 0, nullptr, nullptr, nullptr);
if(_renderCallback) {
_renderCallback(_renderCallbackOwner);
}
}
void setFrameIntervalInMilliseconds(float frameIntervalInMilliseconds) {
_frameIntervalInMilliseconds = frameIntervalInMilliseconds;

View File

@@ -1,396 +0,0 @@
#include "ResourceBuffer.hpp"
#include "FilamentViewer.hpp"
#include "filament/LightManager.h"
#include "Log.hpp"
#include "ThreadPool.hpp"
#include <thread>
#include <functional>
using namespace polyvox;
extern "C" {
#include "PolyvoxFilamentApi.h"
FLUTTER_PLUGIN_EXPORT const void* create_filament_viewer(const void* context, const ResourceLoaderWrapper* const loader, void* const platform, const char* uberArchivePath) {
return (const void*) new FilamentViewer(context, loader, platform, uberArchivePath);
}
FLUTTER_PLUGIN_EXPORT ResourceLoaderWrapper* make_resource_loader(LoadFilamentResourceFromOwner loadFn, FreeFilamentResourceFromOwner freeFn, void* const owner) {
return new ResourceLoaderWrapper(loadFn, freeFn, owner);
}
FLUTTER_PLUGIN_EXPORT void create_render_target(const void* const viewer, intptr_t texture, uint32_t width, uint32_t height) {
((FilamentViewer*)viewer)->createRenderTarget(texture, width, height);
}
FLUTTER_PLUGIN_EXPORT void destroy_filament_viewer(const void* const viewer) {
delete((FilamentViewer*)viewer);
}
FLUTTER_PLUGIN_EXPORT void set_background_color(const void* const viewer, const float r, const float g, const float b, const float a) {
((FilamentViewer*)viewer)->setBackgroundColor(r, g, b, a);
}
FLUTTER_PLUGIN_EXPORT void clear_background_image(const void* const viewer) {
((FilamentViewer*)viewer)->clearBackgroundImage();
}
FLUTTER_PLUGIN_EXPORT void set_background_image(const void* const viewer, const char* path, bool fillHeight) {
((FilamentViewer*)viewer)->setBackgroundImage(path, fillHeight);
}
FLUTTER_PLUGIN_EXPORT void set_background_image_position(const void* const viewer, float x, float y, bool clamp) {
((FilamentViewer*)viewer)->setBackgroundImagePosition(x, y, clamp);
}
FLUTTER_PLUGIN_EXPORT void set_tone_mapping(const void* const viewer, int toneMapping) {
((FilamentViewer*)viewer)->setToneMapping((ToneMapping)toneMapping);
}
FLUTTER_PLUGIN_EXPORT void set_bloom(const void* const viewer, float strength) {
Log("Setting bloom to %f", strength);
((FilamentViewer*)viewer)->setBloom(strength);
}
FLUTTER_PLUGIN_EXPORT void load_skybox(const void* const viewer, const char* skyboxPath) {
((FilamentViewer*)viewer)->loadSkybox(skyboxPath);
}
FLUTTER_PLUGIN_EXPORT void load_ibl(const void* const viewer, const char* iblPath, float intensity) {
((FilamentViewer*)viewer)->loadIbl(iblPath, intensity);
}
FLUTTER_PLUGIN_EXPORT void remove_skybox(const void* const viewer) {
((FilamentViewer*)viewer)->removeSkybox();
}
FLUTTER_PLUGIN_EXPORT void remove_ibl(const void* const viewer) {
((FilamentViewer*)viewer)->removeIbl();
}
EntityId add_light(const void* const viewer, uint8_t type, float colour, float intensity, float posX, float posY, float posZ, float dirX, float dirY, float dirZ, bool shadows) {
return ((FilamentViewer*)viewer)->addLight((LightManager::Type)type, colour, intensity, posX, posY, posZ, dirX, dirY, dirZ, shadows);
}
FLUTTER_PLUGIN_EXPORT void remove_light(const void* const viewer, int32_t entityId) {
((FilamentViewer*)viewer)->removeLight(entityId);
}
FLUTTER_PLUGIN_EXPORT void clear_lights(const void* const viewer) {
((FilamentViewer*)viewer)->clearLights();
}
EntityId load_glb(void* assetManager, const char* assetPath, bool unlit) {
return ((AssetManager*)assetManager)->loadGlb(assetPath, unlit);
}
EntityId load_gltf(void* assetManager, const char* assetPath, const char* relativePath) {
return ((AssetManager*)assetManager)->loadGltf(assetPath, relativePath);
}
bool set_camera(const void* const viewer, EntityId asset, const char* nodeName) {
return ((FilamentViewer*)viewer)->setCamera(asset, nodeName);
}
FLUTTER_PLUGIN_EXPORT void set_view_frustum_culling(const void* const viewer, bool enabled) {
((FilamentViewer*)viewer)->setViewFrustumCulling(enabled);
}
FLUTTER_PLUGIN_EXPORT void move_camera_to_asset(const void* const viewer, EntityId asset) {
((FilamentViewer*)viewer)->moveCameraToAsset(asset);
}
FLUTTER_PLUGIN_EXPORT void set_camera_focus_distance(const void* const viewer, float distance) {
((FilamentViewer*)viewer)->setCameraFocusDistance(distance);
}
FLUTTER_PLUGIN_EXPORT void set_camera_exposure(const void* const viewer, float aperture, float shutterSpeed, float sensitivity) {
((FilamentViewer*)viewer)->setCameraExposure(aperture, shutterSpeed, sensitivity);
}
FLUTTER_PLUGIN_EXPORT void set_camera_position(const void* const viewer, float x, float y, float z) {
((FilamentViewer*)viewer)->setCameraPosition(x, y, z);
}
FLUTTER_PLUGIN_EXPORT void set_camera_rotation(const void* const viewer, float rads, float x, float y, float z) {
((FilamentViewer*)viewer)->setCameraRotation(rads, x, y, z);
}
FLUTTER_PLUGIN_EXPORT void set_camera_model_matrix(const void* const viewer, const float* const matrix) {
((FilamentViewer*)viewer)->setCameraModelMatrix(matrix);
}
FLUTTER_PLUGIN_EXPORT void set_camera_focal_length(const void* const viewer, float focalLength) {
((FilamentViewer*)viewer)->setCameraFocalLength(focalLength);
}
FLUTTER_PLUGIN_EXPORT void render(
const void* const viewer,
uint64_t frameTimeInNanos,
void* pixelBuffer,
void (*callback)(void *buf, size_t size, void *data),
void* data) {
((FilamentViewer*)viewer)->render(frameTimeInNanos, pixelBuffer, callback, data);
}
FLUTTER_PLUGIN_EXPORT void set_frame_interval(
const void* const viewer,
float frameInterval
) {
((FilamentViewer*)viewer)->setFrameInterval(frameInterval);
}
FLUTTER_PLUGIN_EXPORT void destroy_swap_chain(const void* const viewer) {
((FilamentViewer*)viewer)->destroySwapChain();
}
FLUTTER_PLUGIN_EXPORT void create_swap_chain(const void* const viewer, const void* const window, uint32_t width, uint32_t height) {
((FilamentViewer*)viewer)->createSwapChain(window, width, height);
}
FLUTTER_PLUGIN_EXPORT void update_viewport_and_camera_projection(const void* const viewer, uint32_t width, uint32_t height, float scaleFactor) {
return ((FilamentViewer*)viewer)->updateViewportAndCameraProjection(width, height, scaleFactor);
}
FLUTTER_PLUGIN_EXPORT void scroll_update(const void* const viewer, float x, float y, float delta) {
((FilamentViewer*)viewer)->scrollUpdate(x, y, delta);
}
FLUTTER_PLUGIN_EXPORT void scroll_begin(const void* const viewer) {
((FilamentViewer*)viewer)->scrollBegin();
}
FLUTTER_PLUGIN_EXPORT void scroll_end(const void* const viewer) {
((FilamentViewer*)viewer)->scrollEnd();
}
FLUTTER_PLUGIN_EXPORT void grab_begin(const void* const viewer, float x, float y, bool pan) {
((FilamentViewer*)viewer)->grabBegin(x, y, pan);
}
FLUTTER_PLUGIN_EXPORT void grab_update(const void* const viewer, float x, float y) {
((FilamentViewer*)viewer)->grabUpdate(x, y);
}
FLUTTER_PLUGIN_EXPORT void grab_end(const void* const viewer) {
((FilamentViewer*)viewer)->grabEnd();
}
FLUTTER_PLUGIN_EXPORT void * get_asset_manager(const void* const viewer) {
return (void*)((FilamentViewer*)viewer)->getAssetManager();
}
FLUTTER_PLUGIN_EXPORT void apply_weights(
void* assetManager,
EntityId asset,
const char* const entityName,
float* const weights,
int count) {
// ((AssetManager*)assetManager)->setMorphTargetWeights(asset, entityName, weights, count);
}
FLUTTER_PLUGIN_EXPORT void set_morph_target_weights(
void* assetManager,
EntityId asset,
const char* const entityName,
const float* const weights,
const int numWeights
) {
return ((AssetManager*)assetManager)->setMorphTargetWeights(
asset,
entityName,
weights,
numWeights
);
}
bool set_morph_animation(
void* assetManager,
EntityId asset,
const char* const entityName,
const float* const morphData,
const int* const morphIndices,
int numMorphTargets,
int numFrames,
float frameLengthInMs) {
return ((AssetManager*)assetManager)->setMorphAnimationBuffer(
asset,
entityName,
morphData,
morphIndices,
numMorphTargets,
numFrames,
frameLengthInMs
);
}
FLUTTER_PLUGIN_EXPORT void set_bone_animation(
void* assetManager,
EntityId asset,
const float* const frameData,
int numFrames,
int numBones,
const char** const boneNames,
const char** const meshNames,
int numMeshTargets,
float frameLengthInMs) {
((AssetManager*)assetManager)->setBoneAnimationBuffer(
asset,
frameData,
numFrames,
numBones,
boneNames,
meshNames,
numMeshTargets,
frameLengthInMs
);
}
FLUTTER_PLUGIN_EXPORT void set_post_processing(void* const viewer, bool enabled) {
((FilamentViewer*)viewer)->setPostProcessing(enabled);
}
// void set_bone_transform(
// EntityId asset,
// const char* boneName,
// const char* entityName,
// float transX,
// float transY,
// float transZ,
// float quatX,
// float quatY,
// float quatZ,
// float quatW
// ) {
// ((AssetManager*)assetManager)->setBoneTransform(
// boneName,
// entityName,
// transX,
// transY,
// transZ,
// quatX,
// quatY,
// quatZ,
// quatW,
// false
// );
// }
FLUTTER_PLUGIN_EXPORT void play_animation(
void* assetManager,
EntityId asset,
int index,
bool loop,
bool reverse,
bool replaceActive,
float crossfade) {
((AssetManager*)assetManager)->playAnimation(asset, index, loop, reverse, replaceActive, crossfade);
}
FLUTTER_PLUGIN_EXPORT void set_animation_frame(
void* assetManager,
EntityId asset,
int animationIndex,
int animationFrame) {
// ((AssetManager*)assetManager)->setAnimationFrame(asset, animationIndex, animationFrame);
}
float get_animation_duration(void* assetManager, EntityId asset, int animationIndex) {
return ((AssetManager*)assetManager)->getAnimationDuration(asset, animationIndex);
}
int get_animation_count(
void* assetManager,
EntityId asset) {
auto names = ((AssetManager*)assetManager)->getAnimationNames(asset);
return (int)names->size();
}
FLUTTER_PLUGIN_EXPORT void get_animation_name(
void* assetManager,
EntityId asset,
char* const outPtr,
int index
) {
auto names = ((AssetManager*)assetManager)->getAnimationNames(asset);
string name = names->at(index);
strcpy(outPtr, name.c_str());
}
FLUTTER_PLUGIN_EXPORT int get_morph_target_name_count(void* assetManager, EntityId asset, const char* meshName) {
unique_ptr<vector<string>> names = ((AssetManager*)assetManager)->getMorphTargetNames(asset, meshName);
return (int)names->size();
}
FLUTTER_PLUGIN_EXPORT void get_morph_target_name(void* assetManager, EntityId asset, const char* meshName, char* const outPtr, int index ) {
unique_ptr<vector<string>> names = ((AssetManager*)assetManager)->getMorphTargetNames(asset, meshName);
string name = names->at(index);
strcpy(outPtr, name.c_str());
}
FLUTTER_PLUGIN_EXPORT void remove_asset(const void* const viewer, EntityId asset) {
((FilamentViewer*)viewer)->removeAsset(asset);
}
FLUTTER_PLUGIN_EXPORT void clear_assets(const void* const viewer) {
((FilamentViewer*)viewer)->clearAssets();
}
bool set_material_color(void* assetManager, EntityId asset, const char* meshName, int materialIndex, const float r, const float g, const float b, const float a) {
return ((AssetManager*)assetManager)->setMaterialColor(asset, meshName, materialIndex, r, g, b, a);
}
FLUTTER_PLUGIN_EXPORT void transform_to_unit_cube(void* assetManager, EntityId asset) {
((AssetManager*)assetManager)->transformToUnitCube(asset);
}
FLUTTER_PLUGIN_EXPORT void set_position(void* assetManager, EntityId asset, float x, float y, float z) {
((AssetManager*)assetManager)->setPosition(asset, x, y, z);
}
FLUTTER_PLUGIN_EXPORT void set_rotation(void* assetManager, EntityId asset, float rads, float x, float y, float z) {
((AssetManager*)assetManager)->setRotation(asset, rads, x, y, z);
}
FLUTTER_PLUGIN_EXPORT void set_scale(void* assetManager, EntityId asset, float scale) {
((AssetManager*)assetManager)->setScale(asset, scale);
}
FLUTTER_PLUGIN_EXPORT void stop_animation(void* assetManager, EntityId asset, int index) {
((AssetManager*)assetManager)->stopAnimation(asset, index);
}
FLUTTER_PLUGIN_EXPORT int hide_mesh(void* assetManager, EntityId asset, const char* meshName) {
return ((AssetManager*)assetManager)->hide(asset, meshName);
}
FLUTTER_PLUGIN_EXPORT int reveal_mesh(void* assetManager, EntityId asset, const char* meshName) {
return ((AssetManager*)assetManager)->reveal(asset, meshName);
}
FLUTTER_PLUGIN_EXPORT void pick(void* const viewer, int x, int y, EntityId* entityId) {
((FilamentViewer*)viewer)->pick(static_cast<uint32_t>(x), static_cast<uint32_t>(y), static_cast<int32_t*>(entityId));
}
FLUTTER_PLUGIN_EXPORT const char* get_name_for_entity(void* const assetManager, const EntityId entityId) {
return ((AssetManager*)assetManager)->getNameForEntity(entityId);
}
FLUTTER_PLUGIN_EXPORT void ios_dummy() {
Log("Dummy called");
}
}

View File

@@ -11,15 +11,15 @@ import 'generated_bindings_web.dart';
import 'package:flutter/services.dart';
import 'package:flutter_web_plugins/flutter_web_plugins.dart';
/// A web implementation of the PolyvoxFilamentPlatform of the PolyvoxFilament plugin.
class PolyvoxFilamentPluginWeb {
/// A web implementation of the FlutterFilamentPlatform of the FlutterFilament plugin.
class FlutterFilamentPluginWeb {
// late html.CanvasElement _canvas;
late RenderingContext _gl;
DynamicLibrary _nativeLib;
dynamic _texture;
PolyvoxFilamentPluginWeb() {
FlutterFilamentPluginWeb() {
var canvas = document.querySelector('#drawHere') as CanvasElement;
_gl = canvas.getContext("webgl") as RenderingContext;
@@ -50,7 +50,7 @@ class PolyvoxFilamentPluginWeb {
static void registerWith(Registrar registrar) {
final MethodChannel channel = MethodChannel("app.polyvox.filament/event",
const StandardMethodCodec(), registrar.messenger);
final PolyvoxFilamentPluginWeb instance = PolyvoxFilamentPluginWeb();
final FlutterFilamentPluginWeb instance = FlutterFilamentPluginWeb();
channel.setMethodCallHandler(instance.handleMethodCall);
}

View File

@@ -1,7 +1,4 @@
import 'package:polyvox_filament/animations/morph_animation_data.dart';
import 'package:polyvox_filament/filament_controller_method_channel.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_filament/animations/animation_data.dart';
import 'package:vector_math/vector_math.dart';
class AnimationBuilder {
@@ -28,8 +25,9 @@ class AnimationBuilder {
}
MorphAnimationData build() {
if (availableMorphs.isEmpty == 0 || _duration == 0 || _frameLengthInMs == 0)
if (availableMorphs.isEmpty || _duration == 0 || _frameLengthInMs == 0) {
throw Exception();
}
int numFrames = _duration * 1000 ~/ _frameLengthInMs;
@@ -52,7 +50,6 @@ class AnimationBuilder {
meshName,
morphData,
_morphTargets.map((i) => availableMorphs[i]).toList(),
_morphTargets,
_frameLengthInMs);
}
@@ -68,10 +65,10 @@ class AnimationBuilder {
AnimationBuilder interpolateMorphWeights(
double start, double end, double startValue, double endValue) {
this._interpMorphStart = start;
this._interpMorphEnd = end;
this._interpMorphStartValue = startValue;
this._interpMorphEndValue = endValue;
_interpMorphStart = start;
_interpMorphEnd = end;
_interpMorphStartValue = startValue;
_interpMorphEndValue = endValue;
return this;
}
@@ -128,7 +125,7 @@ class AnimationBuilder {
// _BoneAnimationDatas!.add(DartBoneAnimationData([boneName], [meshName], animData));
return this;
// return this;
}
}

View File

@@ -0,0 +1,47 @@
import 'dart:typed_data';
///
/// Specifies frame data (i.e. weights) to animate the morph targets contained in [morphTargets] under a mesh named [mesh].
/// [data] is laid out as numFrames x numMorphTargets.
/// Each frame is [numMorphTargets] in length, where the index of each weight corresponds to the respective index in [morphTargets].
/// [morphTargets] must be some subset of the actual morph targets under [mesh] (though the order of these does not need to match).
///
class MorphAnimationData {
final String meshName;
final List<String> morphTargets;
final List<double> data;
MorphAnimationData(
this.meshName, this.data, this.morphTargets, this.frameLengthInMs) {
assert(data.length == morphTargets.length * numFrames);
}
int get numMorphTargets => morphTargets.length;
int get numFrames => data.length ~/ numMorphTargets;
final double frameLengthInMs;
Iterable<double> getData(String morphName) sync* {
int index = morphTargets.indexOf(morphName);
for (int i = 0; i < numFrames; i++) {
yield data[(i * numMorphTargets) + index];
}
}
}
///
/// Model class for bone animation frame data.
/// To create dynamic/runtime bone animations (as distinct from animations embedded in a glTF asset), create an instance containing the relevant
/// data and pass to the [setBoneAnimation] method on a [FilamentController].
/// [frameData] is laid out as [locX, locY, locZ, rotW, rotX, rotY, rotZ]
///
class BoneAnimationData {
final String boneName;
final List<String> meshNames;
final Float32List frameData;
double frameLengthInMs;
BoneAnimationData(
this.boneName, this.meshNames, this.frameData, this.frameLengthInMs);
}

View File

@@ -1,17 +0,0 @@
import 'dart:typed_data';
import 'package:vector_math/vector_math.dart';
///
/// Model class for bone animation frame data.
/// To create dynamic/runtime bone animations (as distinct from animations embedded in a glTF asset), create an instance containing the relevant
/// data and pass to the [setBoneAnimation] method on a [FilamentController].
/// [frameData] is laid out as [locX, locY, locZ, rotW, rotX, rotY, rotZ]
///
class BoneAnimationData {
final String boneName;
final List<String> meshNames;
final Float32List frameData;
double frameLengthInMs;
BoneAnimationData(
this.boneName, this.meshNames, this.frameData, this.frameLengthInMs);
}

View File

@@ -1,79 +0,0 @@
import 'dart:convert';
import 'package:vector_math/vector_math.dart';
import 'package:flutter/foundation.dart';
import 'package:vector_math/vector_math.dart';
///
/// Some animation data may be specified as blendshape weights (say, between -1 and 1)
/// but at runtime we want to retarget this to drive a bone translation/rotation (say, between -pi/2 and pi/2).
/// A [BoneDriver] is our mechanism for translating the former to the latter, containing:
/// 1) a blendshape name
/// 2) a bone name
/// 3) min/max translation values (corresponding to -1/1 on the blendshape), and
/// 4) min/max rotation values (corresponding to -1/1 on the blendshape)
///
class Transformation {
final Quaternion rotation;
late final Vector3 translation;
Transformation(this.rotation, {Vector3? translation}) {
this.translation = translation ?? Vector3.zero();
}
}
class BoneDriver {
final String bone;
final Map<String, Transformation>
transformations; // maps a blendshape key to a Transformation
BoneDriver(this.bone, this.transformations);
//
// Accepts a Float32List containing [numFrames] frames of data for a single morph target weight (for efficiency, this must be unravelled to a single contiguous Float32List).
// Returns a generator that yields [numFrames] Quaternions, each representing the (weighted) rotation/translation specified by the mapping of this BoneDriver.
//
Iterable<Quaternion> transform(
Map<String, List<double>> morphTargetFrameData) sync* {
assert(setEquals(
morphTargetFrameData.keys.toSet(), transformations.keys.toSet()));
var numFrames = morphTargetFrameData.values.first.length;
assert(morphTargetFrameData.values.every((x) => x.length == numFrames));
for (int frameNum = 0; frameNum < numFrames; frameNum++) {
var rotations = transformations.keys.map((blendshape) {
var weight = morphTargetFrameData[blendshape]![frameNum];
var rotation = transformations[blendshape]!.rotation.clone();
rotation.x *= weight;
rotation.y *= weight;
rotation.z *= weight;
rotation.w = 1;
return rotation;
}).toList();
var result = rotations.fold(
rotations.first, (Quaternion a, Quaternion b) => a + b);
result.w = 1;
yield result;
}
}
factory BoneDriver.fromJsonObject(dynamic jsonObject) {
throw Exception("TODO");
// return BoneDriver(
// jsonObject["bone"],
// Map<String,Transformation>.fromIterable(jsonObject["blendshape"].map((bsName, quats) {
// var q = quats.map(())
// MapEntry(k,
}
}
// }
// yield Quaternion(
// rotMin.x + (weight * (rotMax.x - rotMin.x)),
// rotMin.y + (weight * (rotMax.y - rotMin.y)),
// rotMin.z + (weight * (rotMax.z - rotMin.z)),
// 1.0);

View File

@@ -1,141 +0,0 @@
import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';
import 'package:tuple/tuple.dart';
import 'package:polyvox_filament/animations/bone_animation_data.dart';
import 'package:polyvox_filament/animations/bone_driver.dart';
import 'package:polyvox_filament/animations/morph_animation_data.dart';
import 'package:vector_math/vector_math.dart';
///
/// A class for loading animation data from a single CSV and allocating between morph/bone animation.
///
class DynamicAnimation {
final MorphAnimationData? morphAnimation;
final List<BoneAnimationData> boneAnimation;
factory DynamicAnimation.load(String? meshName, String csvPath,
{List<BoneDriver>? boneDrivers,
List<String>? boneMeshes,
String? boneDriverConfigPath,
double? framerate}) {
// create a MorphAnimationData instance from the given CSV
var llf = _loadLiveLinkFaceCSV(csvPath);
var frameLengthInMs = 1000 / (framerate ?? 60.0);
var morphNames = llf.item1;
if (boneDrivers != null) {
morphNames = morphNames
.where((name) =>
boneDrivers!.any((element) => element.bone == name) == false)
.toList();
}
var morphAnimationData = MorphAnimationData(
meshName ?? "NULL",
llf.item2,
morphNames,
List<int>.generate(morphNames.length, (index) => index),
frameLengthInMs);
final boneAnimations = <BoneAnimationData>[];
// if applicable, load the bone driver config
if (boneDriverConfigPath != null) {
if (boneDrivers != null) {
throw Exception(
"Specify either boneDrivers, or the config path, not both");
}
boneDrivers = [
json
.decode(File(boneDriverConfigPath).readAsStringSync())
.map(BoneDriver.fromJsonObject)
.toList()
];
}
// iterate over every bone driver
if (boneDrivers != null) {
for (var driver in boneDrivers) {
// collect the frame data for the blendshapes that this driver uses
var morphData = driver.transformations
.map((String blendshape, Transformation transformation) {
return MapEntry(
blendshape, morphAnimationData.getData(blendshape).toList());
});
// apply the driver to the frame data
var transformedQ = driver.transform(morphData).toList();
// transform the quaternion to a Float32List
var transformedF = _quaternionToFloatList(transformedQ);
// add to the list of boneAnimations
boneAnimations.add(BoneAnimationData(
driver.bone, boneMeshes!, transformedF, frameLengthInMs));
}
}
return DynamicAnimation(morphAnimationData, boneAnimations);
}
static Float32List _quaternionToFloatList(List<Quaternion> quats) {
var data = Float32List(quats.length * 7);
int i = 0;
for (var quat in quats) {
data.setRange(i, i + 7, [0, 0, 0, quat.w, quat.x, quat.y, quat.z]);
i += 7;
}
return data;
}
DynamicAnimation(this.morphAnimation, this.boneAnimation);
///
/// Load visemes fom a CSV file formatted according to the following header:
/// "Timecode,BlendShapeCount,EyeBlinkLeft,EyeLookDownLeft,EyeLookInLeft,EyeLookOutLeft,EyeLookUpLeft,EyeSquintLeft,EyeWideLeft,EyeBlinkRight,EyeLookDownRight,EyeLookInRight,EyeLookOutRight,EyeLookUpRight,EyeSquintRight,EyeWideRight,JawForward,JawRight,JawLeft,JawOpen,MouthClose,MouthFunnel,MouthPucker,MouthRight,MouthLeft,MouthSmileLeft,MouthSmileRight,MouthFrownLeft,MouthFrownRight,MouthDimpleLeft,MouthDimpleRight,MouthStretchLeft,MouthStretchRight,MouthRollLower,MouthRollUpper,MouthShrugLower,MouthShrugUpper,MouthPressLeft,MouthPressRight,MouthLowerDownLeft,MouthLowerDownRight,MouthUpperUpLeft,MouthUpperUpRight,BrowDownLeft,BrowDownRight,BrowInnerUp,BrowOuterUpLeft,BrowOuterUpRight,CheekPuff,CheekSquintLeft,CheekSquintRight,NoseSneerLeft,NoseSneerRight,TongueOut,HeadYaw,HeadPitch,HeadRoll,LeftEyeYaw,LeftEyePitch,LeftEyeRoll,RightEyeYaw,RightEyePitch,RightEyeRoll"
/// Returns two elements:
/// - a list containing the names of each blendshape/morph key
/// - a Float32List of length TxN, where T is the number of frames and N is the number of morph keys (i.e. the length of the list in the first element of the returned tuple).
///
static Tuple2<List<String>, Float32List> _loadLiveLinkFaceCSV(String path) {
final data = File(path)
.readAsLinesSync()
.where((l) => l.length > 1)
.map((l) => l.split(","));
final header = data.first;
final numBlendShapes = header.length - 2;
final _data = <double>[];
for (var frame in data.skip(1)) {
int numFrameWeights = frame.length - 2;
// CSVs may contain rows where the "BlendShapeCount" column is set to "0" and/or the weight columns are simply missing.
// This can happen when something went wrong while recording via an app (e.g. LiveLinkFace)
// Whenever we encounter this type of row, we consider that all weights should be set to zero for that frame.
if (numFrameWeights != int.parse(frame[1])) {
_data.addAll(List<double>.filled(numBlendShapes, 0.0));
continue;
}
//
// Now, we check that the actual number of weight columns matches the header
// we ignore the "BlendShapeCount" column (and just count the number of columns)
// This is due to some legacy issues where we generated CSVs that had 61 weight columns, but accidentally left the "BlendShapeCount" column at 55
// This is probably fine as we always have either zero weights (handled above), or all weights (handled below).
// In other words, if this throws, we have a serious problem.
if (numFrameWeights != numBlendShapes) {
throw Exception(
"Malformed CSV, header specifies ${numBlendShapes} columns but frame specified only $numFrameWeights weights");
}
_data.addAll(frame
.skip(2)
.map((weight) => double.parse(weight))
.cast<double>()
.toList());
}
return Tuple2(header.skip(2).toList(), Float32List.fromList(_data));
}
}

View File

@@ -1,13 +0,0 @@
import 'dart:math';
import 'package:polyvox_filament/animations/bone_driver.dart';
import 'package:vector_math/vector_math.dart';
BoneDriver getLiveLinkFaceBoneDrivers(String bone) {
return BoneDriver(bone, {
"HeadPitch":
Transformation(Quaternion.axisAngle(Vector3(0, 0, -1), pi / 3)),
"HeadRoll": Transformation(Quaternion.axisAngle(Vector3(1, 0, 0), pi / 2)),
"HeadYaw": Transformation(Quaternion.axisAngle(Vector3(0, 1, 0), pi / 2)),
});
}

View File

@@ -1,32 +0,0 @@
//
// A wrapper for morph target animation data.
// [data] is laid out as numFrames x numMorphTargets (where each morph target is ordered according to [animatedMorphNames]).
// [data] frame data for the morph weights used to animate the morph targets [animatedMorphNames] in mesh [meshName].
// the morph targets specified in [morphNames] attached to mesh [meshName].
// [animatedMorphNames] must be provided but is not used directly; this is only used to check that the eventual asset being animated contains the same morph targets in the same order.
//
class MorphAnimationData {
final String meshName;
final List<String> animatedMorphNames;
final List<int> animatedMorphIndices;
final List<double> data;
MorphAnimationData(this.meshName, this.data, this.animatedMorphNames,
this.animatedMorphIndices, this.frameLengthInMs) {
assert(data.length == animatedMorphNames.length * numFrames);
}
int get numMorphTargets => animatedMorphNames.length;
int get numFrames => data.length ~/ numMorphTargets;
final double frameLengthInMs;
Iterable<double> getData(String morphName) sync* {
int index = animatedMorphNames.indexOf(morphName);
for (int i = 0; i < numFrames; i++) {
yield data[(i * numMorphTargets) + index];
}
}
}

View File

@@ -1,26 +1,68 @@
// ignore_for_file: constant_identifier_names
import 'dart:async';
import 'dart:ui' as ui;
import 'package:flutter/services.dart';
import 'package:polyvox_filament/animations/bone_animation_data.dart';
import 'package:polyvox_filament/animations/morph_animation_data.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_filament/animations/animation_data.dart';
import 'package:vector_math/vector_math_64.dart';
// a handle that can be safely passed back to the rendering layer to manipulate an Entity
typedef FilamentEntity = int;
enum ToneMapper { ACES, FILMIC, LINEAR }
// see filament Manipulator.h for more details
enum ManipulatorMode { ORBIT, MAP, FREE_FLIGHT }
class TextureDetails {
final int textureId;
// both width and height are in physical, not logical pixels
final int width;
final int height;
TextureDetails({required this.textureId, required this.width, required this.height});
TextureDetails(
{required this.textureId, required this.width, required this.height});
}
abstract class FilamentController {
// the current target size of the viewport, in logical pixels
ui.Size size = ui.Size.zero;
///
/// A Stream containing every FilamentEntity added to the scene (i.e. via [loadGlb], [loadGltf] or [addLight]).
/// This is provided for convenience so you can set listeners in front-end widgets that can respond to entity loads without manually passing around the FilamentEntity returned from those methods.
///
Stream<FilamentEntity> get onLoad;
Future get isReadyForScene;
///
/// A Stream containing every FilamentEntity removed from the scene (i.e. via [removeAsset], [clearAssets], [removeLight] or [clearLights]).
Stream<FilamentEntity> get onUnload;
///
/// A [ValueNotifier] that holds the current dimensions (in physical pixels, after multiplying by pixel ratio) of the FilamentWidget.
/// If you need to perform work as early as possible, add a listener to this property before a [FilamentWidget] has been inserted into the widget hierarchy.
///
ValueNotifier<Rect?> get rect;
///
/// A [ValueNotifier] to indicate whether a FilamentViewer is currently available.
/// (FilamentViewer is a C++ type, hence why it is not referenced) here.
/// Call [createViewer]/[destroyViewer] to create/destroy a FilamentViewer.
///
ValueNotifier<bool> get hasViewer;
///
/// Whether a Flutter Texture widget should be inserted into the widget hierarchy.
/// This will be false on certain platforms where we use a transparent window underlay.
/// Used internally by [FilamentWidget]; you probably don't need to access this property directly.
///
bool get requiresTextureWidget;
///
/// The Flutter texture ID and dimensions for current texture in use.
/// This is only used by [FilamentWidget]; you shouldn't need to access directly yourself.
///
final textureDetails = ValueNotifier<TextureDetails?>(null);
///
/// The result(s) of calling [pick] (see below).
@@ -29,6 +71,11 @@ abstract class FilamentController {
///
Stream<FilamentEntity?> get pickResult;
///
/// Whether the controller is currently rendering at [framerate].
///
bool get rendering;
///
/// Set to true to continuously render the scene at the framerate specified by [setFrameRate] (60 fps by default).
///
@@ -44,13 +91,6 @@ abstract class FilamentController {
///
Future setFrameRate(int framerate);
///
/// Called by FilamentGestureDetector to set the pixel ratio (obtained from [MediaQuery]) before creating the texture/viewport.
/// You may call this yourself if you want to increase/decrease the pixel density of the viewport, but calling this method won't do anything on its own.
/// You will need to manually recreate the texture/viewer afterwards.
///
void setPixelRatio(double ratio);
///
/// Destroys the viewer and all backing textures. You can leave the FilamentWidget in the hierarchy after this is called, but you will need to manually call [createViewer] to
///
@@ -61,31 +101,32 @@ abstract class FilamentController {
///
Future destroyViewer();
///
/// Destroys the backing texture. You probably want to call [destroy] instead of this; this is exposed mostly for lifecycle changes which are handled by FilamentWidget.
/// Destroys the specified backing texture. You probably want to call [destroy] instead of this; this is exposed mostly for lifecycle changes which are handled by FilamentWidget.
///
Future destroyTexture();
///
/// Called by [FilamentWidget]; you generally will not need to call this yourself.
/// To recap, you can create a viewport is created in the Flutter rendering hierarchy by:
/// 1) Create a FilamentController
/// 2) Insert a FilamentWidget into the rendering tree, passing your FilamentController
/// 3) Initially, the FilamentWidget will only contain an empty Container (by default, with a solid red background).
/// This widget will render a single frame to get its actual size, then will itself call [createViewer]. You do not need to call [createViewer] yourself.
/// This will dispatch a request to the native platform to create a hardware texture (Metal on iOS, OpenGL on Linux, GLES on Android and Windows) and a FilamentViewer (the main interface for manipulating the 3D scene) .
/// 4) The FilamentController will notify FilamentWidget that a texture is available
/// 5) The FilamentWidget will replace the empty Container with a Texture widget
/// If you need to wait until a FilamentViewer has been created, [await] the [isReadyForScene] Future.
/// Create a FilamentViewer. Must be called at least one frame after a [FilamentWidget] has been inserted into the rendering hierarchy.
///
Future<TextureDetails> createViewer(int width, int height);
/// Before a FilamentViewer is created, the FilamentWidget will only contain an empty Container (by default, with a solid red background).
/// FilamentWidget will then call [setDimensions] with dimensions/pixel ratio of the viewport
/// Calling [createViewer] will then dispatch a request to the native platform to create a hardware texture (Metal on iOS, OpenGL on Linux, GLES on Android and Windows) and a FilamentViewer (the main interface for manipulating the 3D scene) .
/// [FilamentWidget] will be notified that a texture is available and will replace the empty Container with a Texture widget
///
Future createViewer();
///
/// Resize the viewport & backing texture.
/// Sets the dimensions of the viewport and pixel ratio (obtained from [MediaQuery]) to be used the next time [resize] or [createViewer] is called.
/// This is called by FilamentWidget; you shouldn't need to invoke this manually.
///
Future<TextureDetails> resize(int width, int height, {double scaleFactor = 1.0});
Future setDimensions(ui.Rect rect, double pixelRatio);
///
/// Resize the viewport & backing texture to the current dimensions (as last set by [setDimensions]).
/// This is called by FilamentWidget; you shouldn't need to invoke this manually.
///
Future resize();
///
/// Set the background image to [path] (which should have a file extension .png, .jpg, or .ktx).
@@ -161,9 +202,18 @@ 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});
Future<FilamentEntity> loadGltf(String path, String relativeResourcePath);
///
/// 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,
{bool force = false});
///
/// Called by `FilamentGestureDetector`. You probably don't want to call this yourself.
@@ -196,7 +246,7 @@ abstract class FilamentController {
Future rotateEnd();
///
/// Set the weights for all morph targets under node [meshName] in [asset] to [weights].
/// Set the weights for all morph targets under node [meshName] in [entity] to [weights].
///
Future setMorphTargetWeights(
FilamentEntity entity, String meshName, List<double> weights);
@@ -213,10 +263,10 @@ abstract class FilamentController {
FilamentEntity entity, int animationIndex);
///
/// Create/start a dynamic morph target animation for [asset].
/// Animates morph target weights/bone transforms (where each frame requires a duration of [frameLengthInMs].
/// [morphWeights] is a list of doubles in frame-major format.
/// Each frame is [numWeights] in length, and each entry is the weight to be applied to the morph target located at that index in the mesh primitive at that frame.
/// Animate the morph targets in [entity]. See [MorphTargetAnimation] for an explanation as to how to construct the animation frame data.
/// This method will check the morph target names specified in [animation] against the morph target names that actually exist exist under [meshName] in [entity],
/// throwing an exception if any cannot be found.
/// It is permissible for [animation] to omit any targets that do exist under [meshName]; these simply won't be animated.
///
Future setMorphAnimationData(
FilamentEntity entity, MorphAnimationData animation);
@@ -231,7 +281,7 @@ abstract class FilamentController {
///
/// Removes/destroys the specified entity from the scene.
/// [asset] will no longer be a valid handle after this method is called; ensure you immediately discard all references once this method is complete.
/// [entity] will no longer be a valid handle after this method is called; ensure you immediately discard all references once this method is complete.
///
Future removeAsset(FilamentEntity entity);
@@ -257,19 +307,20 @@ abstract class FilamentController {
Future zoomEnd();
///
/// Schedules the glTF animation at [index] in [asset] to start playing on the next frame.
/// Schedules the glTF animation at [index] in [entity] to start playing on the next frame.
///
Future playAnimation(FilamentEntity entity, int index,
{bool loop = false,
bool reverse = false,
bool replaceActive = true,
double crossfade = 0.0});
Future setAnimationFrame(
FilamentEntity entity, int index, int animationFrame);
Future stopAnimation(FilamentEntity entity, int animationIndex);
///
/// Sets the current scene camera to the glTF camera under [name] in [asset].
/// Sets the current scene camera to the glTF camera under [name] in [entity].
///
Future setCamera(FilamentEntity entity, String? name);
@@ -282,12 +333,59 @@ abstract class FilamentController {
/// Sets the strength of the bloom.
///
Future setBloom(double bloom);
///
/// Sets the focal length of the camera.
///
Future setCameraFocalLength(double focalLength);
///
/// Sets the focus distance for the camera.
///
Future setCameraFocusDistance(double focusDistance);
///
/// Get the camera position in world space.
///
Future<Vector3> getCameraPosition();
///
/// Get the camera's model matrix.
///
Future<Matrix4> getCameraModelMatrix();
///
/// Get the camera's view matrix. See Camera.h for more details.
///
Future<Matrix4> getCameraViewMatrix();
///
/// Get the camera's projection matrix. See Camera.h for more details.
///
Future<Matrix4> getCameraProjectionMatrix();
///
/// Get the camera's culling projection matrix. See Camera.h for more details.
///
Future<Matrix4> getCameraCullingProjectionMatrix();
///
/// Get the camera's culling frustum in world space. Returns six Vector4s defining the left, right, bottom, top, far and near planes respectively. See Camera.h and Frustum.h for more details.
///
Future<Frustum> getCameraFrustum();
///
/// Set the camera position in world space. Note this is not persistent - any viewport navigation will reset the camera transform.
///
Future setCameraPosition(double x, double y, double z);
///
/// Repositions the camera to the last vertex of the bounding box of [asset], looking at the penultimate vertex.
/// Get the camera rotation matrix.
///
Future<Matrix3> getCameraRotation();
///
/// Repositions the camera to the last vertex of the bounding box of [entity], looking at the penultimate vertex.
///
Future moveCameraToAsset(FilamentEntity entity);
@@ -295,21 +393,36 @@ abstract class FilamentController {
/// Enables/disables frustum culling. Currently we don't expose a method for manipulating the camera projection/culling matrices so this is your only option to deal with unwanted near/far clipping.
///
Future setViewFrustumCulling(bool enabled);
///
/// Sets the camera exposure.
///
Future setCameraExposure(
double aperture, double shutterSpeed, double sensitivity);
///
/// Rotate the camera by [rads] around the given axis. Note this is not persistent - any viewport navigation will reset the camera transform.
///
Future setCameraRotation(double rads, double x, double y, double z);
///
/// Sets the camera model matrix.
///
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 [entity] to fit within the unit cube.
///
Future transformToUnitCube(FilamentEntity entity);
///
/// Sets the world space position for [asset] to the given coordinates.
/// Sets the world space position for [entity] to the given coordinates.
///
Future setPosition(FilamentEntity entity, double x, double y, double z);
@@ -322,6 +435,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);
@@ -347,4 +464,14 @@ abstract class FilamentController {
/// Retrieves the name assigned to the given FilamentEntity (usually corresponds to the glTF mesh name).
///
String? getNameForEntity(FilamentEntity entity);
///
/// Sets the options for manipulating the camera via the viewport.
/// ManipulatorMode.FREE_FLIGHT and ManipulatorMode.MAP are currently unsupported and will throw an exception.
///
Future setCameraManipulatorOptions(
{ManipulatorMode mode = ManipulatorMode.ORBIT,
double orbitSpeedX = 0.01,
double orbitSpeedY = 0.01,
double zoomSpeed = 0.01});
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,673 +0,0 @@
import 'dart:async';
import 'dart:ui' as ui;
import 'package:flutter/services.dart';
import 'package:polyvox_filament/filament_controller.dart';
import 'package:polyvox_filament/animations/bone_animation_data.dart';
import 'package:polyvox_filament/animations/morph_animation_data.dart';
import 'package:polyvox_filament/generated_bindings_web.dart';
import 'filament_controller.dart';
typedef AssetManager = int;
const FilamentEntity _FILAMENT_ASSET_ERROR = 0;
///
/// This is a previous iteration of FilamentController that used platform channels for every distinct platform.
/// This is no longer used; currently kept only for reference/posterity.
///
class FilamentControllerMethodChannel extends FilamentController {
late MethodChannel _channel = MethodChannel("app.polyvox.filament/event");
double _pixelRatio = 1.0;
ui.Size size = ui.Size.zero;
int? _textureId;
final _textureIdController = StreamController<int?>.broadcast();
Stream<int?> get textureId => _textureIdController.stream;
Completer _isReadyForScene = Completer();
Future get isReadyForScene => _isReadyForScene.future;
late AssetManager _assetManager;
int? _viewer;
///
/// This controller uses platform channels to bridge Dart with the C/C++ code for the Filament API.
/// Setting up the context/texture (since this is platform-specific) and the render ticker are platform-specific; all other methods are passed through by the platform channel to the methods specified in PolyvoxFilamentApi.h.
///
FilamentController() {
_channel.setMethodCallHandler((call) async {
throw Exception("Unknown method channel invocation ${call.method}");
});
}
Future setPostProcessing(bool enabled) async {
throw Exception();
}
Future setRendering(bool render) async {
if (_viewer == null || _resizing) {
throw Exception("No viewer available, ignoring");
}
return _channel.invokeMethod("setRendering", render);
}
Future render() async {
if (_viewer == null || _resizing) {
throw Exception("No viewer available, ignoring");
}
await _channel.invokeMethod("render");
}
Future setFrameRate(int framerate) async {
await _channel.invokeMethod("setFrameInterval", 1.0 / framerate);
}
void setPixelRatio(double ratio) {
_pixelRatio = ratio;
}
Future destroyViewer() async {
if (_viewer == null || _resizing) {
throw Exception("No viewer available, ignoring");
}
_viewer = null;
await _channel.invokeMethod("destroyViewer");
_isReadyForScene = Completer();
}
Future destroyTexture() async {
await _channel.invokeMethod("destroyTexture");
_textureId = null;
_assetManager = 0;
_textureIdController.add(null);
}
///
/// The process for creating/initializing the Filament layer is as follows:
/// 1) Create a FilamentController
/// 2) Insert a FilamentWidget into the rendering tree
/// 3) Initially, this widget will only contain an empty Container. After the first frame is rendered, the widget itself will automatically call [createViewer] with the width/height from its constraints
/// 4) The FilamentWidget will replace the empty Container with the Texture widget.
///
Future<TextureDetails> createViewer(int width, int height) async {
throw Exception();
if (_viewer != null) {
throw Exception(
"Viewer already exists, make sure you call destroyViewer first");
}
if (_isReadyForScene.isCompleted) {
throw Exception(
"Do not call createViewer when a viewer has already been created without calling destroyViewer");
}
size = ui.Size(width * _pixelRatio, height * _pixelRatio);
_textureId =
await _channel.invokeMethod("createTexture", [size.width, size.height]);
_viewer = await _channel
.invokeMethod("createFilamentViewer", [size.width, size.height]);
await _channel.invokeMethod("updateViewportAndCameraProjection",
[size.width.toInt(), size.height.toInt(), 1.0]);
_assetManager = await _channel.invokeMethod("getAssetManager");
_textureIdController.add(_textureId);
_isReadyForScene.complete(true);
}
bool _resizing = false;
Future<TextureDetails> resize(int width, int height, {double scaleFactor = 1.0}) async {
throw Exception();
_resizing = true;
_textureId = await _channel.invokeMethod(
"resize", [width * _pixelRatio, height * _pixelRatio, scaleFactor]);
_textureIdController.add(_textureId);
_resizing = false;
}
Future clearBackgroundImage() async {
if (_viewer == null || _resizing) {
throw Exception("No viewer available, ignoring");
}
await _channel.invokeMethod("clearBackgroundImage");
}
Future setBackgroundImage(String path, {bool fillHeight = false}) async {
if (_viewer == null || _resizing) {
throw Exception("No viewer available, ignoring");
}
await _channel.invokeMethod("setBackgroundImage", [path, fillHeight]);
}
Future setBackgroundColor(Color color) async {
if (_viewer == null || _resizing) {
throw Exception("No viewer available, ignoring");
}
await _channel.invokeMethod("setBackgroundColor", [
color.red.toDouble() / 255.0,
color.green.toDouble() / 255.0,
color.blue.toDouble() / 255.0,
color.alpha.toDouble() / 255.0
]);
}
Future setBackgroundImagePosition(double x, double y,
{bool clamp = false}) async {
if (_viewer == null || _resizing) {
throw Exception("No viewer available, ignoring");
}
await _channel
.invokeMethod("setBackgroundImagePosition", [x, y, clamp ? 1 : 0]);
}
Future loadSkybox(String skyboxPath) async {
if (_viewer == null || _resizing) {
throw Exception("No viewer available, ignoring");
}
await _channel.invokeMethod("loadSkybox", skyboxPath);
}
Future loadIbl(String lightingPath, {double intensity = 30000}) async {
if (_viewer == null || _resizing) {
throw Exception("No viewer available, ignoring");
}
await _channel.invokeMethod("loadIbl", [lightingPath, intensity]);
}
Future removeSkybox() async {
if (_viewer == null || _resizing) {
throw Exception("No viewer available, ignoring");
}
await _channel.invokeMethod("removeSkybox");
}
Future removeIbl() async {
if (_viewer == null || _resizing) {
throw Exception("No viewer available, ignoring");
}
await _channel.invokeMethod("removeIbl");
}
// copied from LightManager.h
// enum class Type : uint8_t {
// SUN, //!< Directional light that also draws a sun's disk in the sky.
// DIRECTIONAL, //!< Directional light, emits light in a given direction.
// POINT, //!< Point light, emits light from a position, in all directions.
// FOCUSED_SPOT, //!< Physically correct spot light.
// SPOT, //!< Spot light with coupling of outer cone and illumination disabled.
// };
Future<FilamentEntity> addLight(
int type,
double colour,
double intensity,
double posX,
double posY,
double posZ,
double dirX,
double dirY,
double dirZ,
bool castShadows) async {
if (_viewer == null || _resizing) {
throw Exception("No viewer available, ignoring");
}
var entity = await _channel.invokeMethod("addLight", [
type,
colour,
intensity,
posX,
posY,
posZ,
dirX,
dirY,
dirZ,
castShadows ? 1 : 0
]);
return entity as FilamentEntity;
}
Future removeLight(FilamentEntity light) async {
if (_viewer == null || _resizing) {
throw Exception("No viewer available, ignoring");
}
await _channel.invokeMethod("removeLight", light);
}
Future clearLights() async {
if (_viewer == null || _resizing) {
throw Exception("No viewer available, ignoring");
}
await _channel.invokeMethod("clearLights");
}
Future<FilamentEntity> loadGlb(String path, {bool unlit = false}) async {
if (_viewer == null || _resizing) {
throw Exception("No viewer available, ignoring");
}
var asset =
await _channel.invokeMethod("loadGlb", [_assetManager, path, unlit]);
if (asset == _FILAMENT_ASSET_ERROR) {
throw Exception("An error occurred loading the asset at $path");
}
return asset;
}
Future<FilamentEntity> loadGltf(
String path, String relativeResourcePath) async {
if (_viewer == null || _resizing) {
throw Exception("No viewer available, ignoring");
}
var entity = await _channel
.invokeMethod("loadGltf", [_assetManager, path, relativeResourcePath]);
return entity as FilamentEntity;
}
Future panStart(double x, double y) async {
if (_viewer == null || _resizing) {
throw Exception("No viewer available, ignoring");
}
await _channel
.invokeMethod("grabBegin", [x * _pixelRatio, y * _pixelRatio, 1]);
}
Future panUpdate(double x, double y) async {
if (_viewer == null || _resizing) {
throw Exception("No viewer available, ignoring");
}
await _channel
.invokeMethod("grabUpdate", [x * _pixelRatio, y * _pixelRatio]);
}
Future panEnd() async {
if (_viewer == null || _resizing) {
throw Exception("No viewer available, ignoring");
}
await _channel.invokeMethod("grabEnd");
}
Future rotateStart(double x, double y) async {
if (_viewer == null || _resizing) {
throw Exception("No viewer available, ignoring");
}
await _channel
.invokeMethod("grabBegin", [x * _pixelRatio, y * _pixelRatio, 0]);
}
Future rotateUpdate(double x, double y) async {
if (_viewer == null || _resizing) {
throw Exception("No viewer available, ignoring");
}
await _channel
.invokeMethod("grabUpdate", [x * _pixelRatio, y * _pixelRatio]);
}
Future rotateEnd() async {
if (_viewer == null || _resizing) {
throw Exception("No viewer available, ignoring");
}
await _channel.invokeMethod("grabEnd");
}
Future setMorphTargetWeights(
FilamentEntity asset, String meshName, List<double> weights) async {
if (_viewer == null || _resizing) {
throw Exception("No viewer available, ignoring");
}
await _channel.invokeMethod("setMorphTargetWeights",
[_assetManager, asset, meshName, weights, weights.length]);
}
Future<List<String>> getMorphTargetNames(
FilamentEntity asset, String meshName) async {
if (_viewer == null || _resizing) {
throw Exception("No viewer available, ignoring");
}
var names = await _channel
.invokeMethod("getMorphTargetNames", [_assetManager, asset, meshName]);
return names.cast<String>();
}
Future<List<String>> getAnimationNames(FilamentEntity asset) async {
if (_viewer == null || _resizing) {
throw Exception("No viewer available, ignoring");
}
var names = await _channel
.invokeMethod("getAnimationNames", [_assetManager, asset]);
return names.cast<String>();
}
///
/// Returns the length (in seconds) of the animation at the given index.
///
Future<double> getAnimationDuration(
FilamentEntity asset, int animationIndex) async {
if (_viewer == null || _resizing) {
throw Exception("No viewer available, ignoring");
}
var duration = await _channel.invokeMethod(
"getAnimationDuration", [_assetManager, asset, animationIndex]);
return duration as double;
}
///
/// Animates morph target weights/bone transforms (where each frame requires a duration of [frameLengthInMs].
/// [morphWeights] is a list of doubles in frame-major format.
/// Each frame is [numWeights] in length, and each entry is the weight to be applied to the morph target located at that index in the mesh primitive at that frame.
///
Future setMorphAnimationData(
FilamentEntity asset, MorphAnimationData animation) async {
if (_viewer == null || _resizing) {
throw Exception("No viewer available, ignoring");
}
await _channel.invokeMethod("setMorphAnimation", [
_assetManager,
asset,
animation.meshName,
animation.data,
animation.animatedMorphIndices,
animation.numMorphTargets,
animation.numFrames,
animation.frameLengthInMs
]);
}
///
/// Animates morph target weights/bone transforms (where each frame requires a duration of [frameLengthInMs].
/// [morphWeights] is a list of doubles in frame-major format.
/// Each frame is [numWeights] in length, and each entry is the weight to be applied to the morph target located at that index in the mesh primitive at that frame.
/// for now we only allow animating a single bone (though multiple skinned targets are supported)
///
Future setBoneAnimation(
FilamentEntity asset, BoneAnimationData animation) async {
if (_viewer == null || _resizing) {
throw Exception("No viewer available, ignoring");
}
// var data = calloc<Float>(animation.frameData.length);
// int offset = 0;
// var numFrames = animation.frameData.length ~/ 7;
// var boneNames = calloc<Pointer<Char>>(1);
// boneNames.elementAt(0).value =
// animation.boneName.toNativeUtf8().cast<Char>();
// var meshNames = calloc<Pointer<Char>>(animation.meshNames.length);
// for (int i = 0; i < animation.meshNames.length; i++) {
// meshNames.elementAt(i).value =
// animation.meshNames[i].toNativeUtf8().cast<Char>();
// }
// for (int i = 0; i < animation.frameData.length; i++) {
// data.elementAt(offset).value = animation.frameData[i];
// offset += 1;
// }
// await _channel.invokeMethod("setBoneAnimation", [
// _assetManager,
// asset,
// data,
// numFrames,
// 1,
// boneNames,
// meshNames,
// animation.meshNames.length,
// animation.frameLengthInMs
// ]);
// calloc.free(data);
}
Future removeAsset(FilamentEntity asset) async {
if (_viewer == null || _resizing) {
throw Exception("No viewer available, ignoring");
}
await _channel.invokeMethod("removeAsset", asset);
}
Future clearAssets() async {
if (_viewer == null || _resizing) {
throw Exception("No viewer available, ignoring");
}
await _channel.invokeMethod("clearAssets");
}
Future zoomBegin() async {
if (_viewer == null || _resizing) {
throw Exception("No viewer available, ignoring");
}
await _channel.invokeMethod("scrollBegin");
}
Future zoomUpdate(double x, double y, double z) async {
if (_viewer == null || _resizing) {
throw Exception("No viewer available, ignoring");
}
await _channel.invokeMethod("scrollUpdate", [x, y, z]);
}
Future zoomEnd() async {
if (_viewer == null || _resizing) {
throw Exception("No viewer available, ignoring");
}
await _channel.invokeMethod("scrollEnd");
}
Future playAnimation(FilamentEntity asset, int index,
{bool loop = false,
bool reverse = false,
bool replaceActive = true,
double crossfade = 0.0}) async {
if (_viewer == null || _resizing) {
throw Exception("No viewer available, ignoring");
}
await _channel.invokeMethod("playAnimation",
[_assetManager, asset, index, loop, reverse, replaceActive, crossfade]);
}
Future setAnimationFrame(
FilamentEntity asset, int index, int animationFrame) async {
if (_viewer == null || _resizing) {
throw Exception("No viewer available, ignoring");
}
await _channel.invokeMethod(
"setAnimationFrame", [_assetManager, asset, index, animationFrame]);
}
Future stopAnimation(FilamentEntity asset, int animationIndex) async {
if (_viewer == null || _resizing) {
throw Exception("No viewer available, ignoring");
}
await _channel
.invokeMethod("stopAnimation", [_assetManager, asset, animationIndex]);
}
Future setCamera(FilamentEntity asset, String? name) async {
if (_viewer == null || _resizing) {
throw Exception("No viewer available, ignoring");
}
if (await _channel.invokeMethod("setCamera", [asset, name]) != true) {
throw Exception("Failed to set camera");
}
}
Future setToneMapping(ToneMapper mapper) async {
if (_viewer == null || _resizing) {
throw Exception("No viewer available, ignoring");
}
if (!await _channel.invokeMethod("setToneMapping", mapper.index)) {
throw Exception("Failed to set tone mapper");
}
}
Future setBloom(double bloom) async {
if (_viewer == null || _resizing) {
throw Exception("No viewer available, ignoring");
}
if (!await _channel.invokeMethod("setBloom", bloom)) {
throw Exception("Failed to set bloom");
}
}
Future setCameraFocalLength(double focalLength) async {
if (_viewer == null || _resizing) {
throw Exception("No viewer available, ignoring");
}
await _channel.invokeMethod("setCameraFocalLength", focalLength);
}
Future setCameraFocusDistance(double focusDistance) async {
if (_viewer == null || _resizing) {
throw Exception("No viewer available, ignoring");
}
await _channel.invokeMethod("setCameraFocusDistance", focusDistance);
}
Future setCameraPosition(double x, double y, double z) async {
if (_viewer == null || _resizing) {
throw Exception("No viewer available, ignoring");
}
await _channel.invokeMethod("setCameraPosition", [x, y, z]);
}
Future moveCameraToAsset(FilamentEntity asset) async {
if (_viewer == null || _resizing) {
throw Exception("No viewer available, ignoring");
}
await _channel.invokeMethod("moveCameraToAsset", asset);
}
Future setViewFrustumCulling(bool enabled) async {
if (_viewer == null || _resizing) {
throw Exception("No viewer available, ignoring");
}
await _channel.invokeMethod("setViewFrustumCulling", enabled);
}
Future setCameraExposure(
double aperture, double shutterSpeed, double sensitivity) async {
if (_viewer == null || _resizing) {
throw Exception("No viewer available, ignoring");
}
await _channel.invokeMethod(
"setCameraExposure", [aperture, shutterSpeed, sensitivity]);
}
Future setCameraRotation(double rads, double x, double y, double z) async {
if (_viewer == null || _resizing) {
throw Exception("No viewer available, ignoring");
}
await _channel.invokeMethod("setCameraRotation", [rads, x, y, z]);
}
Future setCameraModelMatrix(List<double> matrix) async {
if (_viewer == null || _resizing) {
throw Exception("No viewer available, ignoring");
}
assert(matrix.length == 16);
await _channel.invokeMethod("setCameraModelMatrix", matrix);
}
Future setTexture(FilamentEntity asset, String assetPath,
{int renderableIndex = 0}) async {
if (_viewer == null || _resizing) {
throw Exception("No viewer available, ignoring");
}
await _channel.invokeMethod("setTexture", [_assetManager, asset]);
}
Future setMaterialColor(FilamentEntity asset, String meshName,
int materialIndex, Color color) async {
if (_viewer == null || _resizing) {
throw Exception("No viewer available, ignoring");
}
var result = await _channel.invokeMethod("setMaterialColor", [
_assetManager,
asset,
meshName,
materialIndex,
[
color.red.toDouble() / 255.0,
color.green.toDouble() / 255.0,
color.blue.toDouble() / 255.0,
color.alpha.toDouble() / 255.0
]
]);
if (!result) {
throw Exception("Failed to set material color");
}
}
Future transformToUnitCube(FilamentEntity asset) async {
if (_viewer == null || _resizing) {
throw Exception("No viewer available, ignoring");
}
await _channel.invokeMethod("transformToUnitCube", [_assetManager, asset]);
}
Future setPosition(FilamentEntity asset, double x, double y, double z) async {
if (_viewer == null || _resizing) {
throw Exception("No viewer available, ignoring");
}
await _channel.invokeMethod("setPosition", [_assetManager, asset, x, y, z]);
}
Future setScale(FilamentEntity asset, double scale) async {
if (_viewer == null || _resizing) {
throw Exception("No viewer available, ignoring");
}
await _channel.invokeMethod("setScale", [_assetManager, asset, scale]);
}
Future setRotation(
FilamentEntity asset, double rads, double x, double y, double z) async {
if (_viewer == null || _resizing) {
throw Exception("No viewer available, ignoring");
}
await _channel
.invokeMethod("setRotation", [_assetManager, asset, rads, x, y, z]);
}
Future hide(FilamentEntity asset, String meshName) async {
if (_viewer == null || _resizing) {
throw Exception("No viewer available, ignoring");
}
if (await _channel
.invokeMethod("hideMesh", [_assetManager, asset, meshName]) !=
1) {
throw Exception("Failed to hide mesh $meshName");
}
}
Future reveal(FilamentEntity asset, String meshName) async {
if (_viewer == null || _resizing) {
throw Exception("No viewer available, ignoring");
}
if (await _channel
.invokeMethod("revealMesh", [_assetManager, asset, meshName]) !=
1) {
throw Exception("Failed to reveal mesh $meshName");
}
}
@override
Future destroy() {
// TODO: implement destroy
throw UnimplementedError();
}
@override
void pick(int x, int y) {
// TODO: implement pick
}
@override
// TODO: implement pickResult
Stream<FilamentEntity?> get pickResult => throw UnimplementedError();
@override
String? getNameForEntity(FilamentEntity entity) {
// TODO: implement getNameForEntity
throw UnimplementedError();
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,39 @@
import 'dart:ffi';
import 'dart:developer' as dev;
class RenderingSurface {
final int flutterTextureId;
final Pointer<Void> surface;
final int textureHandle;
final int sharedContext;
factory RenderingSurface.from(dynamic platformMessage) {
var flutterTextureId = platformMessage[0];
// void* on iOS (pointer to pixel buffer), Android (pointer to native window), null on macOS/Windows
var surfaceAddress = platformMessage[1] as int? ?? 0;
// null on iOS/Android, void* on MacOS (pointer to metal texture), GLuid on Windows/Linux
var nativeTexture = platformMessage[2] as int? ?? 0;
if (nativeTexture != 0) {
assert(surfaceAddress == 0);
}
var sharedContext = platformMessage[3] as int? ?? 0;
dev.log(
"Using flutterTextureId $flutterTextureId, surface $surfaceAddress nativeTexture $nativeTexture and sharedContext $sharedContext");
return RenderingSurface(
sharedContext: sharedContext,
flutterTextureId: flutterTextureId,
surface: Pointer<Void>.fromAddress(surfaceAddress),
textureHandle: nativeTexture);
}
RenderingSurface(
{required this.sharedContext,
required this.flutterTextureId,
required this.surface,
required this.textureHandle});
}

View File

@@ -1,14 +1,12 @@
import 'dart:async';
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:polyvox_filament/widgets/filament_gesture_detector_desktop.dart';
import 'package:polyvox_filament/widgets/filament_gesture_detector_mobile.dart';
import 'package:flutter_filament/widgets/filament_gesture_detector_desktop.dart';
import 'package:flutter_filament/widgets/filament_gesture_detector_mobile.dart';
import '../filament_controller.dart';
enum GestureType { RotateCamera, PanCamera, PanBackground }
enum GestureType { rotateCamera, panCamera, panBackground }
///
/// A widget that translates finger/mouse gestures to zoom/pan/rotate actions.

View File

@@ -49,7 +49,8 @@ class _FilamentGestureDetectorDesktopState
///
///
///
bool _scaling = false;
// ignore: unused_field
final bool _scaling = false;
bool _pointerMoving = false;
@@ -78,7 +79,7 @@ class _FilamentGestureDetectorDesktopState
// we don't want to end the zoom in the same frame, because this will destroy the camera manipulator (and cancel the zoom update).
// here, we just defer calling [zoomEnd] for 100ms to ensure the update is propagated through.
_scrollTimer = Timer(Duration(milliseconds: 100), () async {
_scrollTimer = Timer(const Duration(milliseconds: 100), () async {
await widget.controller.zoomEnd();
});
}

View File

@@ -2,7 +2,7 @@ import 'dart:async';
import 'package:flutter/material.dart';
import '../filament_controller.dart';
enum GestureType { RotateCamera, PanCamera, PanBackground }
enum GestureType { rotateCamera, panCamera, panBackground }
///
/// A widget that translates finger/mouse gestures to zoom/pan/rotate actions.
@@ -49,12 +49,12 @@ class FilamentGestureDetectorMobile extends StatefulWidget {
class _FilamentGestureDetectorMobileState
extends State<FilamentGestureDetectorMobile> {
GestureType gestureType = GestureType.PanCamera;
GestureType gestureType = GestureType.panCamera;
final _icons = {
GestureType.PanBackground: Icons.image,
GestureType.PanCamera: Icons.pan_tool,
GestureType.RotateCamera: Icons.rotate_90_degrees_ccw
GestureType.panBackground: Icons.image,
GestureType.panCamera: Icons.pan_tool,
GestureType.rotateCamera: Icons.rotate_90_degrees_ccw
};
// on mobile, we can't differentiate between pointer down events like we do on desktop with primary/secondary/tertiary buttons
@@ -69,8 +69,11 @@ class _FilamentGestureDetectorMobileState
// to avoid duplicating code for pan/rotate (panStart, panUpdate, panEnd, rotateStart, rotateUpdate etc)
// we have only a single function for start/update/end.
// when the gesture type is changed, these properties are updated to point to the correct function.
// ignore: unused_field
late Function(double x, double y) _functionStart;
// ignore: unused_field
late Function(double x, double y) _functionUpdate;
// ignore: unused_field
late Function() _functionEnd;
@override
@@ -81,18 +84,18 @@ class _FilamentGestureDetectorMobileState
void _setFunction() {
switch (gestureType) {
case GestureType.RotateCamera:
case GestureType.rotateCamera:
_functionStart = widget.controller.rotateStart;
_functionUpdate = widget.controller.rotateUpdate;
_functionEnd = widget.controller.rotateEnd;
break;
case GestureType.PanCamera:
case GestureType.panCamera:
_functionStart = widget.controller.panStart;
_functionUpdate = widget.controller.panUpdate;
_functionEnd = widget.controller.panEnd;
break;
// TODO
case GestureType.PanBackground:
case GestureType.panBackground:
_functionStart = (x, y) async {};
_functionUpdate = (x, y) async {};
_functionEnd = () async {};
@@ -109,6 +112,7 @@ class _FilamentGestureDetectorMobileState
super.didUpdateWidget(oldWidget);
}
// ignore: unused_field
Timer? _scrollTimer;
double _lastScale = 0;

View File

@@ -1,15 +1,16 @@
import 'dart:io';
import 'dart:math';
import 'dart:developer' as dev;
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:polyvox_filament/filament_controller.dart';
import 'package:flutter_filament/filament_controller.dart';
import 'dart:async';
typedef ResizeCallback = void Function(Size oldSize, Size newSize);
typedef ResizeCallback = void Function(Size newSize);
class ResizeObserver extends SingleChildRenderObjectWidget {
final ResizeCallback onResized;
@@ -36,14 +37,14 @@ class _RenderResizeObserver extends RenderProxyBox {
required this.onLayoutChangedCallback,
}) : super(child);
late var _oldSize = size;
Size _oldSize = Size.zero;
@override
void performLayout() {
void performLayout() async {
super.performLayout();
if (size != _oldSize) {
onLayoutChangedCallback(_oldSize, size);
_oldSize = size;
if (size.width != _oldSize.width || size.height != _oldSize.height) {
onLayoutChangedCallback(size);
_oldSize = Size(size.width, size.height);
}
}
}
@@ -65,92 +66,190 @@ class FilamentWidget extends StatefulWidget {
}
class _FilamentWidgetState extends State<FilamentWidget> {
TextureDetails? _textureDetails;
late final AppLifecycleListener _listener;
AppLifecycleState? _lastState;
String? _error;
int? _width;
int? _height;
void _handleStateChange(AppLifecycleState state) async {
switch (state) {
case AppLifecycleState.detached:
print("Detached");
_textureDetails = null;
await widget.controller.destroyViewer();
await widget.controller.destroyTexture();
break;
case AppLifecycleState.hidden:
print("Hidden");
if (Platform.isIOS) {
_textureDetails = null;
await widget.controller.destroyViewer();
await widget.controller.destroyTexture();
}
break;
case AppLifecycleState.inactive:
print("Inactive");
break;
case AppLifecycleState.paused:
print("Paused");
break;
case AppLifecycleState.resumed:
print("Resumed");
if (!Platform.isWindows) {
if (_textureDetails == null) {
@override
void initState() {
WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
var size = ((context.findRenderObject()) as RenderBox).size;
print("Size after resuming : $size");
_height = size.height.ceil();
_width = size.width.ceil();
await widget.controller.createViewer(_width!, _height!);
print("Created viewer Size after resuming");
_height = size.height.ceil();
setState(() {});
});
super.initState();
}
@override
Widget build(BuildContext context) {
if (_width == null || _height == null) {
return widget.initial ?? Container(color: Colors.red);
}
return ResizeObserver(
onResized: (newSize) {
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
setState(() {
_width = newSize.width.ceil();
_height = newSize.height.ceil();
});
});
},
child: _SizedFilamentWidget(
initial: widget.initial,
width: _width!,
height: _height!,
controller: widget.controller,
));
}
}
break;
class _SizedFilamentWidget extends StatefulWidget {
final int width;
final int height;
final Widget? initial;
final FilamentController controller;
const _SizedFilamentWidget(
{required this.width,
required this.height,
this.initial,
required this.controller});
@override
State<StatefulWidget> createState() => _SizedFilamentWidgetState();
}
_lastState = state;
class _SizedFilamentWidgetState extends State<_SizedFilamentWidget> {
String? _error;
late final AppLifecycleListener _appLifecycleListener;
late double _pixelRatio;
Rect get _rect {
final renderBox = (context.findRenderObject()) as RenderBox;
final size = renderBox.size;
final translation = renderBox.getTransformTo(null).getTranslation();
return Rect.fromLTWH(translation.x, translation.y, size.width, size.height);
}
@override
void initState() {
_listener = AppLifecycleListener(
_appLifecycleListener = AppLifecycleListener(
onStateChange: _handleStateChange,
);
WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
// when attaching a debugger via Android Studio on startup, this can delay presentation of the widget
// (meaning the widget may attempt to create a viewer with size 0x0).
// we just add a small delay here which should avoid this
if (!kReleaseMode) {
await Future.delayed(Duration(seconds: 2));
}
var size = ((context.findRenderObject()) as RenderBox).size;
_width = size.width.ceil();
_height = size.height.ceil();
try {
_textureDetails =
await widget.controller.createViewer(_width!, _height!);
_pixelRatio = MediaQuery.of(context).devicePixelRatio;
widget.controller.setDimensions(_rect, _pixelRatio);
} catch (err) {
setState(() {
dev.log("Fatal error : $err");
_error = err.toString();
});
}
setState(() {});
});
super.initState();
}
Timer? _resizeTimer;
bool _resizing = false;
Future _resize() {
dev.log("Resizing widget");
final completer = Completer();
// resizing the window can be sluggish (particular in debug mode), exacerbated when simultaneously recreating the swapchain and resize the window.
// to address this, whenever the widget is resized, we set a timer for Xms in the future.
// this timer will call [resize] with the widget size at that point in time.
// any subsequent widget resizes will cancel the timer and replace with a new one.
// debug mode does need a longer timeout.
_resizeTimer?.cancel();
_resizeTimer = Timer(
Duration(milliseconds: (kReleaseMode || Platform.isWindows) ? 10 : 100),
() async {
if (!mounted) {
completer.complete();
return;
}
try {
while (_resizing) {
await Future.delayed(const Duration(milliseconds: 20));
}
_resizing = true;
await widget.controller.setDimensions(_rect, _pixelRatio);
await widget.controller.resize();
_resizeTimer = null;
setState(() {});
_resizing = false;
} catch (err) {
dev.log("Error resizing FilamentWidget: $err");
} finally {
completer.complete();
}
});
return completer.future;
}
@override
void didUpdateWidget(_SizedFilamentWidget oldWidget) {
super.didUpdateWidget(oldWidget);
if (oldWidget.height != widget.height || oldWidget.width != widget.width) {
_resize();
}
}
@override
void dispose() {
_listener.dispose();
_appLifecycleListener.dispose();
super.dispose();
}
Timer? _resizeTimer;
bool _wasRenderingOnInactive = true;
void _handleStateChange(AppLifecycleState state) async {
switch (state) {
case AppLifecycleState.detached:
dev.log("Detached");
if (!_wasRenderingOnInactive) {
_wasRenderingOnInactive = widget.controller.rendering;
}
await widget.controller.setRendering(false);
break;
case AppLifecycleState.hidden:
dev.log("Hidden");
if (!_wasRenderingOnInactive) {
_wasRenderingOnInactive = widget.controller.rendering;
}
await widget.controller.setRendering(false);
break;
case AppLifecycleState.inactive:
dev.log("Inactive");
if (!_wasRenderingOnInactive) {
_wasRenderingOnInactive = widget.controller.rendering;
}
// on Windows in particular, restoring a window after minimizing stalls the renderer (and the whole application) for a considerable length of time.
// disabling rendering on minimize seems to fix the issue (so I wonder if there's some kind of command buffer that's filling up while the window is minimized).
await widget.controller.setRendering(false);
break;
case AppLifecycleState.paused:
dev.log("Paused");
if (!_wasRenderingOnInactive) {
_wasRenderingOnInactive = widget.controller.rendering;
}
await widget.controller.setRendering(false);
break;
case AppLifecycleState.resumed:
dev.log("Resumed");
await widget.controller.setRendering(_wasRenderingOnInactive);
break;
}
}
@override
Widget build(BuildContext context) {
@@ -164,51 +263,55 @@ class _FilamentWidgetState extends State<FilamentWidget> {
]));
}
// if no texture ID is available, display the [initial] widget (solid red by default)
late Widget content;
if (!widget.controller.requiresTextureWidget) {
return Stack(children: [
Positioned.fill(child: CustomPaint(painter: TransparencyPainter()))
]);
}
if (_textureDetails == null ||
_textureDetails!.height != _height ||
_textureDetails!.width != _width) {
content = widget.initial ?? Container(color: Colors.red);
} else {
content = Texture(
key: ObjectKey("texture_${_textureDetails!.textureId}"),
textureId: _textureDetails!.textureId,
return ListenableBuilder(
listenable: widget.controller.textureDetails,
builder: (BuildContext ctx, Widget? wdgt) {
if (widget.controller.textureDetails.value == null) {
return Stack(children: [
Positioned.fill(
child: widget.initial ?? Container(color: Colors.red))
]);
}
// see [FilamentControllerFFI.resize] for an explanation of how we deal with resizing
var texture = Texture(
key: ObjectKey(
"texture_${widget.controller.textureDetails.value!.textureId}"),
textureId: widget.controller.textureDetails.value!.textureId,
filterQuality: FilterQuality.none,
freeze: false,
);
}
// see [FilamentControllerFFI.resize] for an explanation of how we deal with resizing
return ResizeObserver(
onResized: (Size oldSize, Size newSize) async {
_resizeTimer?.cancel();
_resizeTimer = Timer(const Duration(milliseconds: 50), () async {
var newWidth = newSize.width.ceil();
var newHeight = newSize.height.ceil();
try {
_textureDetails =
await widget.controller.resize(newWidth, newHeight);
setState(() {
_width = newWidth;
_height = newHeight;
});
} catch (err) {
print(err);
}
});
},
child: Stack(children: [
return Stack(children: [
Positioned.fill(
child: Platform.isLinux || Platform.isWindows
? Transform(
alignment: Alignment.center,
transform: Matrix4.rotationX(
pi), // TODO - this rotation is due to OpenGL texture coordinate working in a different space from Flutter, can we move this to the C++ side somewhere?
child: content)
: content)
]));
child: texture)
: texture)
]);
});
}
}
class TransparencyPainter extends CustomPainter {
@override
void paint(Canvas canvas, Size size) {
canvas.drawRect(
Rect.fromLTWH(0, 0, size.width, size.height),
Paint()
..blendMode = BlendMode.clear
..color = const Color(0x00000000),
);
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) => true;
}

View File

@@ -4,7 +4,7 @@
cmake_minimum_required(VERSION 3.10)
# Project-level configuration.
set(PROJECT_NAME "polyvox_filament")
set(PROJECT_NAME "flutter_filament")
project(${PROJECT_NAME})
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++ -fPIC -Wno-unused-variable -Wno-unused-function")
@@ -12,7 +12,7 @@ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC -Wno-unused-variable -Wno-unused-funct
# This value is used when generating builds using this plugin, so it must
# not be changed.
set(PLUGIN_NAME "polyvox_filament_plugin")
set(PLUGIN_NAME "flutter_filament_plugin")
link_directories("${CMAKE_CURRENT_SOURCE_DIR}/lib")
@@ -26,12 +26,12 @@ add_library(FILAMENT_SHADERS SHARED
#
# Any new source files that you add to the plugin should be added here.
add_library(${PLUGIN_NAME} SHARED
"polyvox_filament_plugin.cc"
"flutter_filament_plugin.cc"
"filament_texture.cc"
"filament_pb_texture.cc"
"${CMAKE_CURRENT_SOURCE_DIR}/../ios/src/AssetManager.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/../ios/src/FilamentViewer.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/../ios/src/PolyvoxFilamentApi.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/../ios/src/FlutterFilamentApi.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/../ios/src/StreamBufferAdapter.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/../ios/src/TimeIt.cpp"
)
@@ -161,7 +161,7 @@ target_link_libraries(${PLUGIN_NAME} PRIVATE
# List of absolute paths to libraries that should be bundled with the plugin.
# This list could contain prebuilt libraries, or libraries created by an
# external build triggered from this build file.
set(polyvox_filament_bundled_libraries
set(flutter_filament_bundled_libraries
""
PARENT_SCOPE
lib/libgeometry.a

View File

@@ -7,7 +7,7 @@
#include <sys/utsname.h>
#include <epoxy/gl.h>
#include "include/polyvox_filament/filament_pb_texture.h"
#include "include/flutter_filament/filament_pb_texture.h"
#include <iostream>
#include <vector>

View File

@@ -6,7 +6,7 @@
#include <sys/utsname.h>
#include <epoxy/gl.h>
#include "include/polyvox_filament/filament_texture.h"
#include "include/flutter_filament/filament_texture.h"
#include <iostream>
#include <vector>

View File

@@ -1,4 +1,4 @@
#include "include/polyvox_filament/polyvox_filament_plugin.h"
#include "include/flutter_filament/flutter_filament_plugin.h"
#include <flutter_linux/flutter_linux.h>
#include <flutter_linux/fl_texture_registrar.h>
@@ -16,26 +16,26 @@
#include <map>
#include <unistd.h>
#include "include/polyvox_filament/filament_texture.h"
#include "include/polyvox_filament/filament_pb_texture.h"
#include "include/polyvox_filament/resource_loader.hpp"
#include "include/flutter_filament/filament_texture.h"
#include "include/flutter_filament/filament_pb_texture.h"
#include "include/flutter_filament/resource_loader.hpp"
#include "FilamentViewer.hpp"
#include "Log.hpp"
extern "C" {
#include "PolyvoxFilamentApi.h"
#include "FlutterFilamentApi.h"
}
#include <epoxy/gl.h>
#include <epoxy/glx.h>
#define POLYVOX_FILAMENT_PLUGIN(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj), polyvox_filament_plugin_get_type(), \
PolyvoxFilamentPlugin))
#define FLUTTER_FILAMENT_PLUGIN(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj), flutter_filament_plugin_get_type(), \
FlutterFilamentPlugin))
struct _PolyvoxFilamentPlugin {
struct _FlutterFilamentPlugin {
GObject parent_instance;
FlTextureRegistrar* texture_registrar;
FlView* fl_view;
@@ -46,10 +46,10 @@ struct _PolyvoxFilamentPlugin {
polyvox::FilamentViewer* viewer;
};
G_DEFINE_TYPE(PolyvoxFilamentPlugin, polyvox_filament_plugin, g_object_get_type())
G_DEFINE_TYPE(FlutterFilamentPlugin, flutter_filament_plugin, g_object_get_type())
static gboolean on_frame_tick(GtkWidget* widget, GdkFrameClock* frame_clock, gpointer self) {
PolyvoxFilamentPlugin* plugin = (PolyvoxFilamentPlugin*)self;
FlutterFilamentPlugin* plugin = (FlutterFilamentPlugin*)self;
if(plugin->rendering) {
render(plugin->viewer, 0);
@@ -59,7 +59,7 @@ static gboolean on_frame_tick(GtkWidget* widget, GdkFrameClock* frame_clock, gpo
return TRUE;
}
static FlMethodResponse* _create_filament_viewer(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) {
static FlMethodResponse* _create_filament_viewer(FlutterFilamentPlugin* self, FlMethodCall* method_call) {
auto callback = new ResourceLoaderWrapper(loadResource, freeResource);
FlValue* args = fl_method_call_get_args(method_call);
@@ -89,7 +89,7 @@ static FlMethodResponse* _create_filament_viewer(PolyvoxFilamentPlugin* self, Fl
return FL_METHOD_RESPONSE(fl_method_success_response_new(result));
}
static FlMethodResponse* _create_texture(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) {
static FlMethodResponse* _create_texture(FlutterFilamentPlugin* self, FlMethodCall* method_call) {
if(self->texture) {
Log("Error - create_texture called when texture exists.");
}
@@ -115,7 +115,7 @@ static FlMethodResponse* _create_texture(PolyvoxFilamentPlugin* self, FlMethodCa
}
static FlMethodResponse* _update_viewport_and_camera_projection(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) {
static FlMethodResponse* _update_viewport_and_camera_projection(FlutterFilamentPlugin* self, FlMethodCall* method_call) {
FlValue* args = fl_method_call_get_args(method_call);
auto width = fl_value_get_int(fl_value_get_list_value(args, 0));
@@ -128,12 +128,12 @@ static FlMethodResponse* _update_viewport_and_camera_projection(PolyvoxFilamentP
}
static FlMethodResponse* _get_asset_manager(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) {
static FlMethodResponse* _get_asset_manager(FlutterFilamentPlugin* self, FlMethodCall* method_call) {
auto assetManager = get_asset_manager(self->viewer);
return FL_METHOD_RESPONSE(fl_method_success_response_new(fl_value_new_int(reinterpret_cast<int64_t>(assetManager))));
}
static FlMethodResponse* _resize(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) {
static FlMethodResponse* _resize(FlutterFilamentPlugin* self, FlMethodCall* method_call) {
FlValue* args = fl_method_call_get_args(method_call);
const double width = fl_value_get_float(fl_value_get_list_value(args, 0));
@@ -154,7 +154,7 @@ static FlMethodResponse* _resize(PolyvoxFilamentPlugin* self, FlMethodCall* meth
return FL_METHOD_RESPONSE(fl_method_success_response_new(result));
}
static FlMethodResponse* _loadSkybox(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) {
static FlMethodResponse* _loadSkybox(FlutterFilamentPlugin* self, FlMethodCall* method_call) {
FlValue* args = fl_method_call_get_args(method_call);
const gchar* path = fl_value_get_string(args);
@@ -165,13 +165,13 @@ static FlMethodResponse* _loadSkybox(PolyvoxFilamentPlugin* self, FlMethodCall*
return FL_METHOD_RESPONSE(fl_method_success_response_new(result));
}
static FlMethodResponse* _remove_ibl(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) {
static FlMethodResponse* _remove_ibl(FlutterFilamentPlugin* self, FlMethodCall* method_call) {
remove_ibl(self->viewer);
g_autoptr(FlValue) result = fl_value_new_string("OK");
return FL_METHOD_RESPONSE(fl_method_success_response_new(result));
}
static FlMethodResponse* _loadIbl(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) {
static FlMethodResponse* _loadIbl(FlutterFilamentPlugin* self, FlMethodCall* method_call) {
FlValue* args = fl_method_call_get_args(method_call);
auto path = fl_value_get_string(fl_value_get_list_value(args, 0));
@@ -183,14 +183,14 @@ static FlMethodResponse* _loadIbl(PolyvoxFilamentPlugin* self, FlMethodCall* met
return FL_METHOD_RESPONSE(fl_method_success_response_new(result));
}
static FlMethodResponse* _removeSkybox(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) {
static FlMethodResponse* _removeSkybox(FlutterFilamentPlugin* self, FlMethodCall* method_call) {
std::cout << "Removing skybox" << std::endl;
remove_skybox(self->viewer);
g_autoptr(FlValue) result = fl_value_new_string("OK");
return FL_METHOD_RESPONSE(fl_method_success_response_new(result));
}
static FlMethodResponse* _set_background_image(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) {
static FlMethodResponse* _set_background_image(FlutterFilamentPlugin* self, FlMethodCall* method_call) {
FlValue* args = fl_method_call_get_args(method_call);
@@ -202,7 +202,7 @@ static FlMethodResponse* _set_background_image(PolyvoxFilamentPlugin* self, FlMe
return FL_METHOD_RESPONSE(fl_method_success_response_new(result));
}
static FlMethodResponse* _set_background_color(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) {
static FlMethodResponse* _set_background_color(FlutterFilamentPlugin* self, FlMethodCall* method_call) {
FlValue* args = fl_method_call_get_args(method_call);
const float r = fl_value_get_float(fl_value_get_list_value(args, 0));
const float g = fl_value_get_float(fl_value_get_list_value(args, 1));
@@ -214,7 +214,7 @@ static FlMethodResponse* _set_background_color(PolyvoxFilamentPlugin* self, FlMe
return FL_METHOD_RESPONSE(fl_method_success_response_new(result));
}
static FlMethodResponse* _add_light(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) {
static FlMethodResponse* _add_light(FlutterFilamentPlugin* self, FlMethodCall* method_call) {
FlValue* args = fl_method_call_get_args(method_call);
@@ -235,7 +235,7 @@ static FlMethodResponse* _add_light(PolyvoxFilamentPlugin* self, FlMethodCall* m
}
static FlMethodResponse* _load_glb(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) {
static FlMethodResponse* _load_glb(FlutterFilamentPlugin* self, FlMethodCall* method_call) {
FlValue* args = fl_method_call_get_args(method_call);
auto assetManager = (void*)fl_value_get_int(fl_value_get_list_value(args, 0));
auto path = fl_value_get_string(fl_value_get_list_value(args, 1));
@@ -245,7 +245,7 @@ static FlMethodResponse* _load_glb(PolyvoxFilamentPlugin* self, FlMethodCall* me
return FL_METHOD_RESPONSE(fl_method_success_response_new(result));
}
static FlMethodResponse* _get_animation_names(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) {
static FlMethodResponse* _get_animation_names(FlutterFilamentPlugin* self, FlMethodCall* method_call) {
FlValue* args = fl_method_call_get_args(method_call);
auto assetManager = (void*)fl_value_get_int(fl_value_get_list_value(args, 0));
@@ -263,7 +263,7 @@ static FlMethodResponse* _get_animation_names(PolyvoxFilamentPlugin* self, FlMet
return FL_METHOD_RESPONSE(fl_method_success_response_new(result));
}
static FlMethodResponse* _remove_asset(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) {
static FlMethodResponse* _remove_asset(FlutterFilamentPlugin* self, FlMethodCall* method_call) {
FlValue* args = fl_method_call_get_args(method_call);
auto asset = (EntityId)fl_value_get_int(fl_value_get_list_value(args, 1));
remove_asset(self->viewer, asset);
@@ -271,7 +271,7 @@ static FlMethodResponse* _remove_asset(PolyvoxFilamentPlugin* self, FlMethodCall
return FL_METHOD_RESPONSE(fl_method_success_response_new(result));
}
static FlMethodResponse* _transform_to_unit_cube(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) {
static FlMethodResponse* _transform_to_unit_cube(FlutterFilamentPlugin* self, FlMethodCall* method_call) {
FlValue* args = fl_method_call_get_args(method_call);
auto assetManager = (void*)fl_value_get_int(fl_value_get_list_value(args, 0));
auto asset = (EntityId)fl_value_get_int(fl_value_get_list_value(args, 1));
@@ -280,7 +280,7 @@ static FlMethodResponse* _transform_to_unit_cube(PolyvoxFilamentPlugin* self, Fl
return FL_METHOD_RESPONSE(fl_method_success_response_new(result));
}
static FlMethodResponse* _rotate_start(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) {
static FlMethodResponse* _rotate_start(FlutterFilamentPlugin* self, FlMethodCall* method_call) {
FlValue* args = fl_method_call_get_args(method_call);
auto x = (float)fl_value_get_float(fl_value_get_list_value(args, 0));
@@ -292,13 +292,13 @@ static FlMethodResponse* _rotate_start(PolyvoxFilamentPlugin* self, FlMethodCall
return FL_METHOD_RESPONSE(fl_method_success_response_new(result));
}
static FlMethodResponse* _rotate_end(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) {
static FlMethodResponse* _rotate_end(FlutterFilamentPlugin* self, FlMethodCall* method_call) {
grab_end(self->viewer);
g_autoptr(FlValue) result = fl_value_new_string("OK");
return FL_METHOD_RESPONSE(fl_method_success_response_new(result));
}
static FlMethodResponse* _rotate_update(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) {
static FlMethodResponse* _rotate_update(FlutterFilamentPlugin* self, FlMethodCall* method_call) {
FlValue* args = fl_method_call_get_args(method_call);
auto x = (float)fl_value_get_float(fl_value_get_list_value(args, 0));
auto y = (float)fl_value_get_float(fl_value_get_list_value(args, 1));
@@ -309,7 +309,7 @@ static FlMethodResponse* _rotate_update(PolyvoxFilamentPlugin* self, FlMethodCal
return FL_METHOD_RESPONSE(fl_method_success_response_new(result));
}
static FlMethodResponse* _pan_start(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) {
static FlMethodResponse* _pan_start(FlutterFilamentPlugin* self, FlMethodCall* method_call) {
FlValue* args = fl_method_call_get_args(method_call);
@@ -321,7 +321,7 @@ static FlMethodResponse* _pan_start(PolyvoxFilamentPlugin* self, FlMethodCall* m
return FL_METHOD_RESPONSE(fl_method_success_response_new(result));
}
static FlMethodResponse* _pan_update(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) {
static FlMethodResponse* _pan_update(FlutterFilamentPlugin* self, FlMethodCall* method_call) {
FlValue* args = fl_method_call_get_args(method_call);
auto x = (float)fl_value_get_float(fl_value_get_list_value(args, 0));
auto y = (float)fl_value_get_float(fl_value_get_list_value(args, 1));
@@ -331,13 +331,13 @@ static FlMethodResponse* _pan_update(PolyvoxFilamentPlugin* self, FlMethodCall*
return FL_METHOD_RESPONSE(fl_method_success_response_new(result));
}
static FlMethodResponse* _pan_end(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) {
static FlMethodResponse* _pan_end(FlutterFilamentPlugin* self, FlMethodCall* method_call) {
grab_end(self->viewer);
g_autoptr(FlValue) result = fl_value_new_string("OK");
return FL_METHOD_RESPONSE(fl_method_success_response_new(result));
}
static FlMethodResponse* _set_position(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) {
static FlMethodResponse* _set_position(FlutterFilamentPlugin* self, FlMethodCall* method_call) {
FlValue* args = fl_method_call_get_args(method_call);
auto assetManager = (void*)fl_value_get_int(fl_value_get_list_value(args, 0));
auto asset = (EntityId)fl_value_get_int(fl_value_get_list_value(args, 1));
@@ -353,7 +353,7 @@ static FlMethodResponse* _set_position(PolyvoxFilamentPlugin* self, FlMethodCall
return FL_METHOD_RESPONSE(fl_method_success_response_new(result));
}
static FlMethodResponse* _set_rotation(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) {
static FlMethodResponse* _set_rotation(FlutterFilamentPlugin* self, FlMethodCall* method_call) {
FlValue* args = fl_method_call_get_args(method_call);
auto assetManager = (void*)fl_value_get_int(fl_value_get_list_value(args, 0));
@@ -373,7 +373,7 @@ static FlMethodResponse* _set_rotation(PolyvoxFilamentPlugin* self, FlMethodCall
static FlMethodResponse* _set_bone_transform(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) {
static FlMethodResponse* _set_bone_transform(FlutterFilamentPlugin* self, FlMethodCall* method_call) {
throw std::invalid_argument( "received negative value" );
// FlValue* args = fl_method_call_get_args(method_call);
// auto assetPtr = (void*)fl_value_get_int(fl_value_get_list_value(args, 0));
@@ -396,7 +396,7 @@ static FlMethodResponse* _set_bone_transform(PolyvoxFilamentPlugin* self, FlMeth
// return FL_METHOD_RESPONSE(fl_method_success_response_new(result));
}
static FlMethodResponse* _set_camera(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) {
static FlMethodResponse* _set_camera(FlutterFilamentPlugin* self, FlMethodCall* method_call) {
FlValue* args = fl_method_call_get_args(method_call);
auto asset = (EntityId)fl_value_get_int(fl_value_get_list_value(args, 0));
auto cameraName = fl_value_get_string(fl_value_get_list_value(args, 1)) ;
@@ -406,14 +406,14 @@ static FlMethodResponse* _set_camera(PolyvoxFilamentPlugin* self, FlMethodCall*
return FL_METHOD_RESPONSE(fl_method_success_response_new(result));
}
static FlMethodResponse* _set_camera_model_matrix(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) {
static FlMethodResponse* _set_camera_model_matrix(FlutterFilamentPlugin* self, FlMethodCall* method_call) {
FlValue* args = fl_method_call_get_args(method_call);
set_camera_model_matrix(self->viewer, fl_value_get_float32_list(args));
g_autoptr(FlValue) result = fl_value_new_string("OK");
return FL_METHOD_RESPONSE(fl_method_success_response_new(result));
}
static FlMethodResponse* _set_camera_exposure(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) {
static FlMethodResponse* _set_camera_exposure(FlutterFilamentPlugin* self, FlMethodCall* method_call) {
FlValue* args = fl_method_call_get_args(method_call);
auto aperture = (float)fl_value_get_float(fl_value_get_list_value(args, 0));
auto shutter_speed = (float)fl_value_get_float(fl_value_get_list_value(args, 1));
@@ -423,7 +423,7 @@ static FlMethodResponse* _set_camera_exposure(PolyvoxFilamentPlugin* self, FlMet
return FL_METHOD_RESPONSE(fl_method_success_response_new(result));
}
static FlMethodResponse* _set_camera_position(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) {
static FlMethodResponse* _set_camera_position(FlutterFilamentPlugin* self, FlMethodCall* method_call) {
FlValue* args = fl_method_call_get_args(method_call);
auto x = (float)fl_value_get_float(fl_value_get_list_value(args, 0));
auto y = (float)fl_value_get_float(fl_value_get_list_value(args, 1));
@@ -433,7 +433,7 @@ static FlMethodResponse* _set_camera_position(PolyvoxFilamentPlugin* self, FlMet
return FL_METHOD_RESPONSE(fl_method_success_response_new(result));
}
static FlMethodResponse* _set_camera_rotation(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) {
static FlMethodResponse* _set_camera_rotation(FlutterFilamentPlugin* self, FlMethodCall* method_call) {
FlValue* args = fl_method_call_get_args(method_call);
auto rads = (float)fl_value_get_float(fl_value_get_list_value(args,0 ));
auto x = (float)fl_value_get_float(fl_value_get_list_value(args, 1));
@@ -445,14 +445,14 @@ static FlMethodResponse* _set_camera_rotation(PolyvoxFilamentPlugin* self, FlMet
return FL_METHOD_RESPONSE(fl_method_success_response_new(result));
}
static FlMethodResponse* _set_rendering(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) {
static FlMethodResponse* _set_rendering(FlutterFilamentPlugin* self, FlMethodCall* method_call) {
FlValue* args = fl_method_call_get_args(method_call);
self->rendering = (bool)fl_value_get_bool(args);
g_autoptr(FlValue) result = fl_value_new_string("OK");
return FL_METHOD_RESPONSE(fl_method_success_response_new(result));
}
static FlMethodResponse* _set_frame_interval(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) {
static FlMethodResponse* _set_frame_interval(FlutterFilamentPlugin* self, FlMethodCall* method_call) {
FlValue* args = fl_method_call_get_args(method_call);
auto val = (float) fl_value_get_float(args);
set_frame_interval(self->viewer, val);
@@ -460,7 +460,7 @@ static FlMethodResponse* _set_frame_interval(PolyvoxFilamentPlugin* self, FlMeth
return FL_METHOD_RESPONSE(fl_method_success_response_new(result));
}
static FlMethodResponse* _grab_begin(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) {
static FlMethodResponse* _grab_begin(FlutterFilamentPlugin* self, FlMethodCall* method_call) {
FlValue* args = fl_method_call_get_args(method_call);
auto x = (float)fl_value_get_float(fl_value_get_list_value(args, 0));
auto y = (float)fl_value_get_float(fl_value_get_list_value(args, 1));
@@ -470,13 +470,13 @@ static FlMethodResponse* _grab_begin(PolyvoxFilamentPlugin* self, FlMethodCall*
return FL_METHOD_RESPONSE(fl_method_success_response_new(result));
}
static FlMethodResponse* _grab_end(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) {
static FlMethodResponse* _grab_end(FlutterFilamentPlugin* self, FlMethodCall* method_call) {
grab_end(self->viewer);
g_autoptr(FlValue) result = fl_value_new_string("OK");
return FL_METHOD_RESPONSE(fl_method_success_response_new(result));
}
static FlMethodResponse* _grab_update(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) {
static FlMethodResponse* _grab_update(FlutterFilamentPlugin* self, FlMethodCall* method_call) {
FlValue* args = fl_method_call_get_args(method_call);
auto x = (float)fl_value_get_float(fl_value_get_list_value(args, 0));
auto y = (float)fl_value_get_float(fl_value_get_list_value(args, 1));
@@ -486,19 +486,19 @@ static FlMethodResponse* _grab_update(PolyvoxFilamentPlugin* self, FlMethodCall*
return FL_METHOD_RESPONSE(fl_method_success_response_new(result));
}
static FlMethodResponse* _scroll_begin(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) {
static FlMethodResponse* _scroll_begin(FlutterFilamentPlugin* self, FlMethodCall* method_call) {
scroll_begin(self->viewer);
g_autoptr(FlValue) result = fl_value_new_string("OK");
return FL_METHOD_RESPONSE(fl_method_success_response_new(result));
}
static FlMethodResponse* _scroll_end(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) {
static FlMethodResponse* _scroll_end(FlutterFilamentPlugin* self, FlMethodCall* method_call) {
scroll_end(self->viewer);
g_autoptr(FlValue) result = fl_value_new_string("OK");
return FL_METHOD_RESPONSE(fl_method_success_response_new(result));
}
static FlMethodResponse* _scroll_update(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) {
static FlMethodResponse* _scroll_update(FlutterFilamentPlugin* self, FlMethodCall* method_call) {
FlValue* args = fl_method_call_get_args(method_call);
auto x = (float)fl_value_get_float(fl_value_get_list_value(args, 0));
auto y = (float)fl_value_get_float(fl_value_get_list_value(args, 1));
@@ -509,7 +509,7 @@ static FlMethodResponse* _scroll_update(PolyvoxFilamentPlugin* self, FlMethodCal
return FL_METHOD_RESPONSE(fl_method_success_response_new(result));
}
static FlMethodResponse* _play_animation(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) {
static FlMethodResponse* _play_animation(FlutterFilamentPlugin* self, FlMethodCall* method_call) {
FlValue* args = fl_method_call_get_args(method_call);
auto assetManager = (void*)fl_value_get_int(fl_value_get_list_value(args, 0));
auto asset = (EntityId)fl_value_get_int(fl_value_get_list_value(args, 1));
@@ -524,7 +524,7 @@ static FlMethodResponse* _play_animation(PolyvoxFilamentPlugin* self, FlMethodCa
}
static FlMethodResponse* _stop_animation(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) {
static FlMethodResponse* _stop_animation(FlutterFilamentPlugin* self, FlMethodCall* method_call) {
FlValue* args = fl_method_call_get_args(method_call);
auto assetManager = (void*)fl_value_get_int(fl_value_get_list_value(args, 0));
auto asset = (EntityId)fl_value_get_int(fl_value_get_list_value(args, 1));
@@ -535,7 +535,7 @@ static FlMethodResponse* _stop_animation(PolyvoxFilamentPlugin* self, FlMethodCa
}
static FlMethodResponse* _set_morph_target_weights(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) {
static FlMethodResponse* _set_morph_target_weights(FlutterFilamentPlugin* self, FlMethodCall* method_call) {
FlValue* args = fl_method_call_get_args(method_call);
auto assetManager = (void*)fl_value_get_int(fl_value_get_list_value(args, 0));
auto asset = (EntityId)fl_value_get_int(fl_value_get_list_value(args, 1));
@@ -557,7 +557,7 @@ static FlMethodResponse* _set_morph_target_weights(PolyvoxFilamentPlugin* self,
template class std::vector<int>;
static FlMethodResponse* _set_morph_animation(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) {
static FlMethodResponse* _set_morph_animation(FlutterFilamentPlugin* self, FlMethodCall* method_call) {
FlValue* args = fl_method_call_get_args(method_call);
auto assetManager = (void*)fl_value_get_int(fl_value_get_list_value(args, 0));
auto asset = (EntityId)fl_value_get_int(fl_value_get_list_value(args, 1));
@@ -599,7 +599,7 @@ static FlMethodResponse* _set_morph_animation(PolyvoxFilamentPlugin* self, FlMet
return FL_METHOD_RESPONSE(fl_method_success_response_new(result));
}
static FlMethodResponse* _set_animation(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) {
static FlMethodResponse* _set_animation(FlutterFilamentPlugin* self, FlMethodCall* method_call) {
throw std::invalid_argument( "received negative value" );
// FlValue* args = fl_method_call_get_args(method_call);
// auto assetPtr = (void*)fl_value_get_int(fl_value_get_list_value(args, 0));
@@ -677,7 +677,7 @@ static FlMethodResponse* _set_animation(PolyvoxFilamentPlugin* self, FlMethodCal
// return FL_METHOD_RESPONSE(fl_method_success_response_new(result));
}
static FlMethodResponse* _get_morph_target_names(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) {
static FlMethodResponse* _get_morph_target_names(FlutterFilamentPlugin* self, FlMethodCall* method_call) {
FlValue* args = fl_method_call_get_args(method_call);
auto assetManager = (void*)fl_value_get_int(fl_value_get_list_value(args, 0));
auto asset = (EntityId)fl_value_get_int(fl_value_get_list_value(args, 1));
@@ -696,22 +696,22 @@ static FlMethodResponse* _get_morph_target_names(PolyvoxFilamentPlugin* self, Fl
return FL_METHOD_RESPONSE(fl_method_success_response_new(result));
}
static FlMethodResponse* _set_tone_mapping(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) {
static FlMethodResponse* _set_tone_mapping(FlutterFilamentPlugin* self, FlMethodCall* method_call) {
FlValue* args = fl_method_call_get_args(method_call);
polyvox::ToneMapping toneMapping = static_cast<polyvox::ToneMapping>(fl_value_get_int(args));
set_tone_mapping(self->viewer, toneMapping);
return FL_METHOD_RESPONSE(fl_method_success_response_new(fl_value_new_bool(true)));
}
static FlMethodResponse* _set_bloom(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) {
static FlMethodResponse* _set_bloom(FlutterFilamentPlugin* self, FlMethodCall* method_call) {
FlValue* args = fl_method_call_get_args(method_call);
set_bloom(self->viewer, fl_value_get_float(args));
return FL_METHOD_RESPONSE(fl_method_success_response_new(fl_value_new_bool(true)));
}
// Called when a method call is received from Flutter.
static void polyvox_filament_plugin_handle_method_call(
PolyvoxFilamentPlugin* self,
static void flutter_filament_plugin_handle_method_call(
FlutterFilamentPlugin* self,
FlMethodCall* method_call) {
g_autoptr(FlMethodResponse) response = nullptr;
@@ -842,25 +842,25 @@ static void polyvox_filament_plugin_handle_method_call(
}
static void polyvox_filament_plugin_dispose(GObject* object) {
G_OBJECT_CLASS(polyvox_filament_plugin_parent_class)->dispose(object);
static void flutter_filament_plugin_dispose(GObject* object) {
G_OBJECT_CLASS(flutter_filament_plugin_parent_class)->dispose(object);
}
static void polyvox_filament_plugin_class_init(PolyvoxFilamentPluginClass* klass) {
G_OBJECT_CLASS(klass)->dispose = polyvox_filament_plugin_dispose;
static void flutter_filament_plugin_class_init(FlutterFilamentPluginClass* klass) {
G_OBJECT_CLASS(klass)->dispose = flutter_filament_plugin_dispose;
}
static void polyvox_filament_plugin_init(PolyvoxFilamentPlugin* self) {}
static void flutter_filament_plugin_init(FlutterFilamentPlugin* self) {}
static void method_call_cb(FlMethodChannel* channel, FlMethodCall* method_call,
gpointer user_data) {
PolyvoxFilamentPlugin* plugin = POLYVOX_FILAMENT_PLUGIN(user_data);
polyvox_filament_plugin_handle_method_call(plugin, method_call);
FlutterFilamentPlugin* plugin = FLUTTER_FILAMENT_PLUGIN(user_data);
flutter_filament_plugin_handle_method_call(plugin, method_call);
}
void polyvox_filament_plugin_register_with_registrar(FlPluginRegistrar* registrar) {
PolyvoxFilamentPlugin* plugin = POLYVOX_FILAMENT_PLUGIN(
g_object_new(polyvox_filament_plugin_get_type(), nullptr));
void flutter_filament_plugin_register_with_registrar(FlPluginRegistrar* registrar) {
FlutterFilamentPlugin* plugin = FLUTTER_FILAMENT_PLUGIN(
g_object_new(flutter_filament_plugin_get_type(), nullptr));
FlView* fl_view = fl_plugin_registrar_get_view(registrar);
plugin->fl_view = fl_view;

View File

@@ -1,6 +1,6 @@
#include <flutter_linux/flutter_linux.h>
#include "include/polyvox_filament/polyvox_filament_plugin.h"
#include "include/flutter_filament/flutter_filament_plugin.h"
// This file exposes some plugin internals for unit testing. See
// https://github.com/flutter/flutter/issues/88724 for current limitations

Some files were not shown because too many files have changed in this diff Show More