From ce346510e60f5c962d94ea77b8deaac517ce4a26 Mon Sep 17 00:00:00 2001 From: Nick Fisher Date: Sat, 20 Aug 2022 22:19:14 +1000 Subject: [PATCH] make Android use new API, add delete_viewer method --- android/CMakeLists.txt | 1 + android/src/main/cpp/filament_android.cpp | 158 +----------------- .../app/polyvox/filament/FilamentInterop.kt | 12 +- .../polyvox/filament/PolyvoxFilamentPlugin.kt | 81 +++++---- example/lib/main.dart | 69 ++------ ios/src/FilamentViewer.cpp | 27 ++- .../PolyvoxFilamentApi.cpp} | 9 + .../PolyvoxFilamentApi.hpp} | 1 + lib/filament_controller.dart | 5 + 9 files changed, 104 insertions(+), 259 deletions(-) rename ios/{Classes/PolyvoxFilamentApi.cc => src/PolyvoxFilamentApi.cpp} (96%) rename ios/{Classes/PolyvoxFilamentApi.h => src/PolyvoxFilamentApi.hpp} (97%) diff --git a/android/CMakeLists.txt b/android/CMakeLists.txt index 6569591a..7d006c63 100644 --- a/android/CMakeLists.txt +++ b/android/CMakeLists.txt @@ -15,6 +15,7 @@ add_library( src/main/cpp/JobSystem.cpp ../ios/src/SceneAssetLoader.cpp ../ios/src/FilamentViewer.cpp + ../ios/src/PolyvoxFilamentApi.cpp ../ios/src/StreamBufferAdapter.cpp ../ios/src/image/imagematerial.c ../ios/src/SceneAsset.cpp diff --git a/android/src/main/cpp/filament_android.cpp b/android/src/main/cpp/filament_android.cpp index 6332e3f7..51dab44f 100644 --- a/android/src/main/cpp/filament_android.cpp +++ b/android/src/main/cpp/filament_android.cpp @@ -14,8 +14,6 @@ static AAssetManager* am; static vector _assets; uint64_t id = -1; -static FilamentViewer* _viewer; - static ResourceBuffer loadResource(const char* name) { id++; @@ -51,169 +49,17 @@ static void freeResource(uint32_t id) { extern "C" { - void set_background_image(void* viewer, const char* path) { - ((FilamentViewer*)viewer)->setBackgroundImage(path); - } - - void load_skybox(void* viewer, const char* skyboxPath) { - ((FilamentViewer*)viewer)->loadSkybox(skyboxPath); - } - - void load_ibl(void* viewer, const char* iblPath) { - ((FilamentViewer*)viewer)->loadIbl(iblPath); - } - - void remove_skybox(void* viewer) { - ((FilamentViewer*)viewer)->removeSkybox(); - } - - - void remove_ibl(void* viewer) { - ((FilamentViewer*)viewer)->removeIbl(); - } - - void* load_glb(void* viewer, const char* assetPath) { - return ((FilamentViewer*)viewer)->loadGlb(assetPath); - } - - void* load_gltf(void* viewer, const char* assetPath, const char* relativePath) { - return ((FilamentViewer*)viewer)->loadGltf(assetPath, relativePath); - } - - bool set_camera(void* viewer, void* asset, const char* nodeName) { - return ((FilamentViewer*)viewer)->setCamera((SceneAsset*)asset, nodeName); - } - - void* filament_viewer_new( + void* filament_viewer_new_android( jobject surface, JNIEnv* env, jobject assetManager ) { - if(_viewer) { - return _viewer; - } ANativeWindow* layer = ANativeWindow_fromSurface(env, surface); am = AAssetManager_fromJava(env, assetManager); - _viewer = new FilamentViewer((void*)layer, loadResource, freeResource); - return _viewer; + return new FilamentViewer((void*)layer, loadResource, freeResource); } - void render( - void* viewer - ) { - ((FilamentViewer*)viewer)->render(); - } - void destroy_swap_chain(void* viewer) { - ((FilamentViewer*)viewer)->destroySwapChain(); - } - void create_swap_chain(void* viewer, jobject surface, JNIEnv* env) { - ANativeWindow* layer = ANativeWindow_fromSurface(env, surface); - if(!layer) { - __android_log_print(ANDROID_LOG_VERBOSE, "filament_api", "Couldn't get native window from surface"); - return; - } - ((FilamentViewer*)viewer)->createSwapChain(layer); - } - - void* get_renderer(void* viewer) { - return ((FilamentViewer*)viewer)->getRenderer(); - } - - void update_viewport_and_camera_projection(void* viewer, int width, int height, float scaleFactor) { - return ((FilamentViewer*)viewer)->updateViewportAndCameraProjection(width, height, scaleFactor); - - } - - void scroll(void* viewer, float x, float y , float z) { - return ((FilamentViewer*)viewer)->manipulator->scroll(x, y, z); - } - - void grab_begin(void* viewer, int x, int y, bool pan) { - __android_log_print(ANDROID_LOG_VERBOSE, "filament_api", "Grab begin at %d %d %d", x, y, pan); - ((FilamentViewer*)viewer)->manipulator->grabBegin(x, y, pan); - - } - - void grab_update(void* viewer, int x, int y) { - __android_log_print(ANDROID_LOG_VERBOSE, "filament_api", "Grab update at %d %d", x, y); - ((FilamentViewer*)viewer)->manipulator->grabUpdate(x, y); - } - - void grab_end(void* viewer) { - ((FilamentViewer*)viewer)->manipulator->grabEnd(); - } - - void apply_weights(void* asset, float* weights, int count) { - ((SceneAsset*)asset)->applyWeights(weights, count); - } - - void animate_weights(void* asset, float* data, int numWeights, int numFrames, float frameRate) { - __android_log_print(ANDROID_LOG_VERBOSE, "filament_api", "Animating %d frames, each with %d weights", numFrames, numWeights); - ((SceneAsset*)asset)->animateWeights((float*)data, numWeights, numFrames, frameRate); - } - - void play_animation(void* asset, int index, bool loop) { - __android_log_print(ANDROID_LOG_VERBOSE, "filament_api", "Playing embedded animation %d", index); - ((SceneAsset*)asset)->playAnimation(index, loop); - } - - char** get_animation_names(void* asset, int* countPtr) { - auto names = ((SceneAsset*)asset)->getAnimationNames(); - __android_log_print(ANDROID_LOG_VERBOSE, "filament_api", "Got %d animation names", names->size()); - char** names_c; - names_c = new char*[names->size()]; - for(int i = 0; i < names->size(); i++) { - names_c[i] = (char*) malloc(names->at(i).size() +1); - strcpy(names_c[i], names->at(i).c_str()); - } - (*countPtr) = names->size(); - return names_c; - } - - char** get_target_names(void* asset, char* meshName, int* countPtr ) { - unique_ptr> names = ((SceneAsset*)asset)->getTargetNames(meshName); - - __android_log_print(ANDROID_LOG_VERBOSE, "filament_api", "Got %d names", names->size()); - - *countPtr = names->size(); - - char** retval; - retval = new char*[names->size()]; - - for(int i =0; i < names->size(); i++) { - retval[i] = (char*)(names->at(i).c_str()); - } - return retval; - } - - void free_pointer(char** ptr, int num) { - free(ptr); - } - - void remove_asset(void* viewer, void* asset) { - ((FilamentViewer*)viewer)->removeAsset((SceneAsset*)asset); - } - - void clear_assets(void* viewer) { - ((FilamentViewer*)viewer)->clearAssets(); - } - - void set_texture(void* asset, const char* assetPath, int renderableIndex) { - ((SceneAsset*)asset)->setTexture(assetPath, renderableIndex); - } - - void transform_to_unit_cube(void* asset) { - ((SceneAsset*)asset)->transformToUnitCube(); - } - - void set_position(void* asset, float x, float y, float z) { - ((SceneAsset*)asset)->setPosition(x, y, z); - } - - void set_rotation(void* asset, float rads, float x, float y, float z) { - ((SceneAsset*)asset)->setRotation(rads, x, y, z); - } } diff --git a/android/src/main/kotlin/app/polyvox/filament/FilamentInterop.kt b/android/src/main/kotlin/app/polyvox/filament/FilamentInterop.kt index 25ac5a13..156117f3 100644 --- a/android/src/main/kotlin/app/polyvox/filament/FilamentInterop.kt +++ b/android/src/main/kotlin/app/polyvox/filament/FilamentInterop.kt @@ -18,12 +18,16 @@ import java.nio.ByteBuffer interface FilamentInterop : Library { - fun filament_viewer_new( + fun filament_viewer_new_android( layer:Object, env:JNIEnv, am:AssetManager ) : Pointer; + fun filament_viewer_delete( + viewer:Pointer, + ) : Pointer; + fun load_skybox(viewer:Pointer, skyboxPath:String) : Pointer; fun load_ibl(viewer:Pointer, skyboxPath:String) : Pointer; @@ -54,9 +58,11 @@ interface FilamentInterop : Library { fun animate_weights(asset:Pointer, frames:FloatArray, numWeights:Int, numFrames:Int, frameRate:Float); - fun get_target_names(asset:Pointer, meshName:String, outLen:IntByReference) : Pointer; + fun get_target_name_count(asset:Pointer, meshName:String) : Int; + fun get_target_name(asset:Pointer, meshName:String, outPtr:Pointer, index:Int); - fun get_animation_names(asset:Pointer, outLen:IntByReference) : Pointer; + fun get_animation_count(asset:Pointer) : Int; + fun get_animation_name(asset:Pointer, outPtr:Pointer, index:Int); fun play_animation(asset:Pointer, index:Int, loop:Boolean); diff --git a/android/src/main/kotlin/app/polyvox/filament/PolyvoxFilamentPlugin.kt b/android/src/main/kotlin/app/polyvox/filament/PolyvoxFilamentPlugin.kt index af943818..f5603f49 100644 --- a/android/src/main/kotlin/app/polyvox/filament/PolyvoxFilamentPlugin.kt +++ b/android/src/main/kotlin/app/polyvox/filament/PolyvoxFilamentPlugin.kt @@ -51,6 +51,7 @@ import android.util.Log import com.sun.jna.Library import com.sun.jna.Native import com.sun.jna.Pointer +import com.sun.jna.Memory import com.sun.jna.ptr.PointerByReference import com.sun.jna.ptr.IntByReference import com.sun.jna.Structure @@ -77,14 +78,20 @@ import android.view.SurfaceHolder /** PolyvoxFilamentPlugin */ class PolyvoxFilamentPlugin: FlutterPlugin, MethodCallHandler, ActivityAware { + private val lock = Object() + inner class FrameCallback : Choreographer.FrameCallback { private val startTime = System.nanoTime() override fun doFrame(frameTimeNanos: Long) { - choreographer.postFrameCallback(this) - if(!surface.isValid()) { - Log.v(TAG, "INVALID") + choreographer.postFrameCallback(this) + synchronized(lock) { + if(_viewer != null) { + if(!surface.isValid()) { + Log.v(TAG, "INVALID") + } + _lib.render(_viewer!!) + } } - _lib.render(_viewer!!) } } @@ -115,7 +122,7 @@ class PolyvoxFilamentPlugin: FlutterPlugin, MethodCallHandler, ActivityAware { private lateinit var assetManager : AssetManager private lateinit var surface: Surface - private lateinit var surfaceTexture: SurfaceTexture + private var surfaceTexture: SurfaceTexture? = null private lateinit var activity:Activity @@ -135,6 +142,18 @@ class PolyvoxFilamentPlugin: FlutterPlugin, MethodCallHandler, ActivityAware { override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) { when (call.method) { "initialize" -> { + if(_viewer != null) { + synchronized(lock) { + print("Deleting existing viewer") + _lib.filament_viewer_delete(_viewer!!); + _viewer = null; + } + } + if(surfaceTexture != null) { + print("Releasing existing texture") + surfaceTexture!!.release() + surfaceTexture = null; + } val args = call.arguments as ArrayList val width = args[0] val height = args[1] @@ -145,11 +164,11 @@ class PolyvoxFilamentPlugin: FlutterPlugin, MethodCallHandler, ActivityAware { surfaceTexture = entry.surfaceTexture() - surfaceTexture.setDefaultBufferSize(width, height) + surfaceTexture!!.setDefaultBufferSize(width, height) - surface = Surface(surfaceTexture) + surface = Surface(surfaceTexture!!) - _viewer = _lib.filament_viewer_new( + _viewer = _lib.filament_viewer_new_android( surface as Object, JNIEnv.CURRENT, (activity as Context).assets) @@ -167,7 +186,7 @@ class PolyvoxFilamentPlugin: FlutterPlugin, MethodCallHandler, ActivityAware { val width = args[0] val height = args[1] - surfaceTexture.setDefaultBufferSize(width, height) + surfaceTexture!!.setDefaultBufferSize(width, height) _lib.update_viewport_and_camera_projection(_viewer!!, width, height, 1.0f); result.success(null) } @@ -275,40 +294,28 @@ class PolyvoxFilamentPlugin: FlutterPlugin, MethodCallHandler, ActivityAware { result.success("OK"); } "getTargetNames" -> { - if(_viewer == null) - return; - - val countPtr = IntByReference(); val args = call.arguments as ArrayList<*> - val namesPtr = _lib.get_target_names(Pointer(args[0] as Long), args[1] as String, countPtr) - - val names = namesPtr.getStringArray(0, countPtr.value); - - for(i in 0..countPtr.value-1) { - Log.v(TAG, "Got target names ${names[i]} ${names[i].length}") + val assetPtr = Pointer(args[0] as Long) + val meshName = args[1] as String + val names = mutableListOf() + val outPtr = Memory(256) + for(i in 0.._lib.get_target_name_count(assetPtr, meshName) - 1) { + _lib.get_target_name(assetPtr, meshName, outPtr, i) + val name = outPtr.getString(0) + names.add(name) } - - val namesAsList = names.toCollection(ArrayList()) - - _lib.free_pointer(namesPtr, countPtr.getValue()) - - result.success(namesAsList) + result.success(names) } "getAnimationNames" -> { val assetPtr = Pointer(call.arguments as Long) - val countPtr = IntByReference(); - val arrPtr = _lib.get_animation_names(assetPtr, countPtr) - - val names = arrPtr.getStringArray(0, countPtr.value); - - for(i in 0..countPtr.value-1) { - val name = names[i]; - Log.v(TAG, "Got animation names ${name} ${name.length}") + val names = mutableListOf() + val outPtr = Memory(256) + for(i in 0.._lib.get_animation_count(assetPtr) - 1) { + _lib.get_animation_name(assetPtr, outPtr, i) + val name = outPtr.getString(0) + names.add(name) } - - _lib.free_pointer(arrPtr, 1) - - result.success(names.toCollection(ArrayList())) + result.success(names) } "applyWeights" -> { val args = call.arguments as ArrayList<*> diff --git a/example/lib/main.dart b/example/lib/main.dart index 00618aa2..36b650a5 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -22,7 +22,7 @@ class _MyAppState extends State { FilamentAsset? _flightHelmet; final weights = List.filled(255, 0.0); - List _targets = []; + List _targetNames = []; List _animationNames = []; bool _loop = false; bool _vertical = false; @@ -36,9 +36,9 @@ class _MyAppState extends State { Widget build(BuildContext context) { return MaterialApp( showPerformanceOverlay: true, - color: Colors.transparent, + color: Colors.white, home: Scaffold( - backgroundColor: Colors.transparent, + backgroundColor: Colors.white, body: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, @@ -67,6 +67,7 @@ class _MyAppState extends State { controller: _filamentController, )), )), + Text("Target names : ${_targetNames.join(",")}, Animation names : ${_animationNames.join(",")}"), Align( alignment: Alignment.bottomLeft, child: Container( @@ -174,64 +175,20 @@ class _MyAppState extends State { 1000 / framerate.toDouble()); break; case 16: - final names = await _filamentController - .getTargetNames(_cube!, "Cube"); - await showDialog( - builder: (ctx) { - return Container( - color: Colors.white, - height: 200, - width: 200, - child: Column( - mainAxisSize: - MainAxisSize.min, - children: names - .map((name) => - Text(name)) - .cast() - .toList() + - [ - ElevatedButton( - onPressed: () => - Navigator.of( - ctx) - .pop(), - child: - Text("Close")) - ])); - }, - context: context); + _targetNames = await _filamentController + .getTargetNames(_cube!, "Cube"); + setState(() { + + }); break; case 17: - final names = await _filamentController + _animationNames = await _filamentController .getAnimationNames(_cube!); + setState(() { + + }); - await showDialog( - builder: (ctx) { - return Container( - color: Colors.white, - height: 200, - width: 200, - child: Column( - mainAxisSize: - MainAxisSize.min, - children: names - .map((name) => - Text(name)) - .cast() - .toList() + - [ - ElevatedButton( - onPressed: () => - Navigator.of( - ctx) - .pop(), - child: - Text("Close")) - ])); - }, - context: context); break; case 18: await _filamentController.panStart(1, 1); diff --git a/ios/src/FilamentViewer.cpp b/ios/src/FilamentViewer.cpp index ee262d4c..4b0fd190 100644 --- a/ios/src/FilamentViewer.cpp +++ b/ios/src/FilamentViewer.cpp @@ -334,7 +334,26 @@ void FilamentViewer::setBackgroundImage(const char *resourcePath) { float3(1.0f)); } -FilamentViewer::~FilamentViewer() { cleanup(); } +FilamentViewer::~FilamentViewer() { + clearAssets(); + _resourceLoader->asyncCancelLoad(); + Log("c1"); + _materialProvider->destroyMaterials(); + Log("c2"); + AssetLoader::destroy(&_assetLoader); + Log("c3"); + delete _sceneAssetLoader; + _engine->destroy(_view); + Log("c4"); + _engine->destroy(_scene); + Log("c5"); + _engine->destroy(_renderer); + Log("c6"); + _engine->destroy(_swapChain); + Log("c7"); + Engine::destroy(&_engine); // clears engine* + Log("c8"); +} Renderer *FilamentViewer::getRenderer() { return _renderer; } @@ -529,12 +548,6 @@ void FilamentViewer::loadIbl(const char *const iblPath) { } } -void FilamentViewer::cleanup() { - _resourceLoader->asyncCancelLoad(); - _materialProvider->destroyMaterials(); - AssetLoader::destroy(&_assetLoader); -}; - void FilamentViewer::render() { if (!_view || !_mainCamera || !_swapChain) { diff --git a/ios/Classes/PolyvoxFilamentApi.cc b/ios/src/PolyvoxFilamentApi.cpp similarity index 96% rename from ios/Classes/PolyvoxFilamentApi.cc rename to ios/src/PolyvoxFilamentApi.cpp index c3bf70ed..80477590 100644 --- a/ios/Classes/PolyvoxFilamentApi.cc +++ b/ios/src/PolyvoxFilamentApi.cpp @@ -3,6 +3,7 @@ #include "ResourceBuffer.hpp" #include "FilamentViewer.hpp" +#include "Log.hpp" using namespace polyvox; @@ -15,6 +16,14 @@ extern "C" { return nullptr; } + + void filament_viewer_delete(void* viewer) { + delete((FilamentViewer*)viewer); + Log( + "deleted" + ); + } + void set_background_image(void* viewer, const char* path) { ((FilamentViewer*)viewer)->setBackgroundImage(path); } diff --git a/ios/Classes/PolyvoxFilamentApi.h b/ios/src/PolyvoxFilamentApi.hpp similarity index 97% rename from ios/Classes/PolyvoxFilamentApi.h rename to ios/src/PolyvoxFilamentApi.hpp index f640bff6..98a76204 100644 --- a/ios/Classes/PolyvoxFilamentApi.h +++ b/ios/src/PolyvoxFilamentApi.hpp @@ -7,6 +7,7 @@ typedef struct ResourceBuffer ResourceBuffer; //ResourceBuffer create_resource_buffer(const void* data, const uint32_t size, const uint32_t id); void* filament_viewer_new(void* texture, void* loadResource, void* freeResource); +void* filament_viewer_delete(void* viewer); void set_background_image(void* viewer, const char* path); void load_skybox(void* viewer, const char* skyboxPath); void load_ibl(void* viewer, const char* iblPath); diff --git a/lib/filament_controller.dart b/lib/filament_controller.dart index 1f5d9c03..1a07a9ff 100644 --- a/lib/filament_controller.dart +++ b/lib/filament_controller.dart @@ -6,6 +6,7 @@ typedef FilamentAsset = int; abstract class FilamentController { late int textureId; + Future get initialized; Future initialize(int width, int height); Future resize(int width, int height); Future setBackgroundImage(String path); @@ -52,6 +53,9 @@ abstract class FilamentController { class PolyvoxFilamentController extends FilamentController { late MethodChannel _channel = MethodChannel("app.polyvox.filament/event"); + final _initialized = Completer(); + Future get initialized => _initialized.future; + PolyvoxFilamentController() { _channel.setMethodCallHandler((call) async { print("Received Filament method channel call : ${call.method}"); @@ -61,6 +65,7 @@ class PolyvoxFilamentController extends FilamentController { Future initialize(int width, int height) async { textureId = await _channel.invokeMethod("initialize", [width, height]); + _initialized.complete(true); } Future resize(int width, int height) async {