add android integration & make iOS API consistent
add pubspec android plugin update android CMakeLists add filament android libs for linking
This commit is contained in:
21
android/CMakeLists.txt
Normal file
21
android/CMakeLists.txt
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.4.1)
|
||||||
|
|
||||||
|
include_directories(../ios/src)
|
||||||
|
include_directories(../ios/include)
|
||||||
|
include_directories(src/main/cpp)
|
||||||
|
link_directories(src/main/libs/${ANDROID_ABI}) # don't use jniLibs here because we just want to link against these libraries, the actual .so files will be copied by the AAR dependencies
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17")
|
||||||
|
add_library(
|
||||||
|
filament_interop
|
||||||
|
SHARED
|
||||||
|
src/main/cpp/filament_api.cpp
|
||||||
|
../ios/src/FilamentViewer.cpp
|
||||||
|
# ../ios/src/Utils.cpp
|
||||||
|
# ../ios/src/HDRLoader.cpp
|
||||||
|
# ../ios/include/common/NioUtils.cpp
|
||||||
|
#../ios/src/morph/GPUMorphHelper.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
target_link_libraries(filament_interop -landroid -llog -lfilament-jni -lfilament-utils-jni -lgltfio-jni )
|
||||||
|
|
||||||
@@ -2,7 +2,7 @@ group 'app.polyvox.filament'
|
|||||||
version '1.0-SNAPSHOT'
|
version '1.0-SNAPSHOT'
|
||||||
|
|
||||||
buildscript {
|
buildscript {
|
||||||
ext.kotlin_version = '1.3.50'
|
ext.kotlin_version = '1.6.0'
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
@@ -23,9 +23,14 @@ rootProject.allprojects {
|
|||||||
|
|
||||||
apply plugin: 'com.android.library'
|
apply plugin: 'com.android.library'
|
||||||
apply plugin: 'kotlin-android'
|
apply plugin: 'kotlin-android'
|
||||||
|
apply plugin: 'kotlin-android-extensions'
|
||||||
|
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 30
|
compileSdkVersion 31
|
||||||
|
|
||||||
|
//ndkVersion '21.1.6352462'
|
||||||
|
ndkVersion '23.1.7779620'
|
||||||
|
|
||||||
compileOptions {
|
compileOptions {
|
||||||
sourceCompatibility JavaVersion.VERSION_1_8
|
sourceCompatibility JavaVersion.VERSION_1_8
|
||||||
@@ -41,10 +46,23 @@ android {
|
|||||||
}
|
}
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
minSdkVersion 16
|
minSdkVersion 21
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
externalNativeBuild {
|
||||||
|
cmake {
|
||||||
|
path "CMakeLists.txt"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
||||||
|
compile 'net.java.dev.jna:jna:5.10.0@aar'
|
||||||
|
implementation "com.google.android.filament:filament-android:1.17.0"
|
||||||
|
implementation "com.google.android.filament:filament-utils-android:1.17.0"
|
||||||
|
implementation "com.google.android.filament:gltfio-android:1.17.0"
|
||||||
|
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.2"
|
||||||
|
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.2"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
rootProject.name = 'filament'
|
rootProject.name = 'polyvox_filament'
|
||||||
|
|||||||
146
android/src/main/cpp/filament_api.cpp
Normal file
146
android/src/main/cpp/filament_api.cpp
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
#include "FilamentViewer.hpp"
|
||||||
|
#include <android/asset_manager.h>
|
||||||
|
#include <android/asset_manager_jni.h>
|
||||||
|
#include <android/native_window_jni.h>
|
||||||
|
#include <android/log.h>
|
||||||
|
#include <android/native_activity.h>
|
||||||
|
|
||||||
|
using namespace polyvox;
|
||||||
|
|
||||||
|
static AAssetManager* am;
|
||||||
|
|
||||||
|
std::vector<AAsset*> _assets;
|
||||||
|
uint64_t id = -1;
|
||||||
|
|
||||||
|
static polyvox::ResourceBuffer loadResource(const char* name) {
|
||||||
|
|
||||||
|
id++;
|
||||||
|
|
||||||
|
AAsset *asset = AAssetManager_open(am, name, AASSET_MODE_BUFFER);
|
||||||
|
if(asset == nullptr) {
|
||||||
|
__android_log_print(ANDROID_LOG_VERBOSE, "filament_api", "Couldn't locate asset [ %s ]", name);
|
||||||
|
return polyvox::ResourceBuffer(nullptr, 0, 0);
|
||||||
|
}
|
||||||
|
__android_log_print(ANDROID_LOG_VERBOSE, "filament_api", "Loading asset [ %s ]", name);
|
||||||
|
off_t length = AAsset_getLength(asset);
|
||||||
|
const void * buffer = AAsset_getBuffer(asset);
|
||||||
|
__android_log_print(ANDROID_LOG_VERBOSE, "filament_api", "Read [ %lu ] bytes into buffer", length);
|
||||||
|
_assets.push_back(asset);
|
||||||
|
__android_log_print(ANDROID_LOG_VERBOSE, "filament_api", "Loaded asset [ %s ] of length %zu", name, length);
|
||||||
|
return ResourceBuffer(buffer, length, id);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void freeResource(ResourceBuffer rb) {
|
||||||
|
AAsset_close(_assets.at(rb.id));
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
void load_skybox(void* viewer, const char* skyboxPath, const char* iblPath) {
|
||||||
|
((FilamentViewer*)viewer)->loadSkybox(skyboxPath, iblPath, am);
|
||||||
|
}
|
||||||
|
|
||||||
|
void load_glb(void* viewer, const char* assetPath) {
|
||||||
|
((FilamentViewer*)viewer)->loadGlb(assetPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
void load_gltf(void* viewer, const char* assetPath, const char* relativePath) {
|
||||||
|
((FilamentViewer*)viewer)->loadGltf(assetPath, relativePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_camera(void* viewer, const char* nodeName) {
|
||||||
|
((FilamentViewer*)viewer)->setCamera(nodeName);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* filament_viewer_new(
|
||||||
|
jobject surface,
|
||||||
|
const char* opaqueShaderPath,
|
||||||
|
const char* fadeShaderPath,
|
||||||
|
JNIEnv* env,
|
||||||
|
jobject assetManager
|
||||||
|
) {
|
||||||
|
ANativeWindow* layer = ANativeWindow_fromSurface(env, surface);
|
||||||
|
am = AAssetManager_fromJava(env, assetManager);
|
||||||
|
|
||||||
|
return new FilamentViewer((void*)layer, opaqueShaderPath, fadeShaderPath, 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 %d", x, y);
|
||||||
|
((FilamentViewer*)viewer)->manipulator->grabUpdate(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void grab_end(void* viewer) {
|
||||||
|
((FilamentViewer*)viewer)->manipulator->grabEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
void apply_weights(void* viewer, float* weights, int count) {
|
||||||
|
((FilamentViewer*)viewer)->applyWeights(weights, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
void get_target_names(void* viewer, char* meshName, char*** outPtr, int* countPtr ) {
|
||||||
|
StringList names = ((FilamentViewer*)viewer)->getTargetNames(meshName);
|
||||||
|
|
||||||
|
*countPtr = names.count;
|
||||||
|
|
||||||
|
*outPtr = (char**)malloc(sizeof(char*) * names.count);
|
||||||
|
|
||||||
|
__android_log_print(ANDROID_LOG_VERBOSE, "filament_api", "Got %d names", names.count);
|
||||||
|
|
||||||
|
for(int i = 0; i < names.count; i++) {
|
||||||
|
std::string as_str(names.strings[i]);
|
||||||
|
(*outPtr)[i] = (char*)malloc(sizeof(char) * as_str.length());
|
||||||
|
strcpy((*outPtr)[i], as_str.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void free_pointer(void** ptr, int size) {
|
||||||
|
for(int i = 0; i < size; i++) {
|
||||||
|
free(ptr[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void release_source_assets(void* viewer) {
|
||||||
|
((FilamentViewer*)viewer)->releaseSourceAssets();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
15
android/src/main/cpp/filament_api.h
Normal file
15
android/src/main/cpp/filament_api.h
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
#include "FilamentViewer.hpp"
|
||||||
|
#include <android/asset_manager.h>
|
||||||
|
#include <android/asset_manager_jni.h>
|
||||||
|
#include <android/native_window_jni.h>
|
||||||
|
#include <android/log.h>
|
||||||
|
|
||||||
|
void load_skybox(void* viewer, const char* skyboxPath, const char* iblPath);
|
||||||
|
|
||||||
|
void* filament_viewer_new(
|
||||||
|
void* layer,
|
||||||
|
const char* opaqueShaderPath,
|
||||||
|
const char* fadeShaderPath,
|
||||||
|
void* assetManager
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
package app.polyvox.filament
|
||||||
|
|
||||||
|
import com.sun.jna.Library
|
||||||
|
import com.sun.jna.Native
|
||||||
|
import com.sun.jna.Pointer
|
||||||
|
import com.sun.jna.ptr.PointerByReference
|
||||||
|
import com.sun.jna.ptr.IntByReference
|
||||||
|
import com.sun.jna.Structure
|
||||||
|
import com.sun.jna.NativeLibrary
|
||||||
|
import com.sun.jna.StringArray
|
||||||
|
import com.sun.jna.JNIEnv
|
||||||
|
|
||||||
|
import android.view.Surface
|
||||||
|
|
||||||
|
import android.content.res.AssetManager
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer
|
||||||
|
|
||||||
|
interface FilamentInterop : Library {
|
||||||
|
|
||||||
|
fun filament_viewer_new(
|
||||||
|
layer:Object,
|
||||||
|
opaqueShaderPath:String,
|
||||||
|
fadeShaderPath:String,
|
||||||
|
env:JNIEnv,
|
||||||
|
am:AssetManager
|
||||||
|
) : Pointer;
|
||||||
|
|
||||||
|
fun load_skybox(viewer:Pointer, skyboxPath:String, iblPath:String) : Pointer;
|
||||||
|
|
||||||
|
fun load_glb(viewer:Pointer, uri:String) : Pointer;
|
||||||
|
|
||||||
|
fun load_gltf(viewer:Pointer, uri:String, relativeResourcePath:String) : Pointer;
|
||||||
|
|
||||||
|
fun set_camera(viewer:Pointer, nodeName:String) : Pointer;
|
||||||
|
|
||||||
|
fun render(viewer:Pointer);
|
||||||
|
|
||||||
|
fun create_swap_chain(viewer:Pointer, surface:Surface, env:JNIEnv);
|
||||||
|
|
||||||
|
fun destroy_swap_chain(viewer:Pointer);
|
||||||
|
|
||||||
|
fun update_viewport_and_camera_projection(viewer:Pointer, width:Int, height:Int, scaleFactor:Float);
|
||||||
|
|
||||||
|
fun scroll(viewer:Pointer, x:Float, y:Float, z:Float);
|
||||||
|
|
||||||
|
fun grab_begin(viewer:Pointer, x:Int, y:Int, pan:Boolean)
|
||||||
|
|
||||||
|
fun grab_update(viewer:Pointer, x:Int, y:Int)
|
||||||
|
|
||||||
|
fun grab_end(viewer:Pointer)
|
||||||
|
|
||||||
|
fun apply_weights(viewer:Pointer, weights:FloatArray, size:Int);
|
||||||
|
|
||||||
|
fun get_target_names(viewer:Pointer, meshName:String, outPtr:PointerByReference, outLen:IntByReference);
|
||||||
|
|
||||||
|
fun free_pointer(ptr:Pointer, size:Int)
|
||||||
|
|
||||||
|
fun release_source_assets(viewer:Pointer)
|
||||||
|
|
||||||
|
}
|
||||||
298
android/src/main/kotlin/app/polyvox/filament/FilamentView.kt
Normal file
298
android/src/main/kotlin/app/polyvox/filament/FilamentView.kt
Normal file
@@ -0,0 +1,298 @@
|
|||||||
|
package app.polyvox.filament
|
||||||
|
import android.content.res.AssetManager
|
||||||
|
|
||||||
|
import android.Manifest
|
||||||
|
import android.app.Activity
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.pm.PackageManager
|
||||||
|
import android.graphics.Color
|
||||||
|
import android.graphics.SurfaceTexture
|
||||||
|
import android.graphics.PixelFormat
|
||||||
|
|
||||||
|
import io.flutter.FlutterInjector
|
||||||
|
|
||||||
|
import android.opengl.GLU
|
||||||
|
import javax.microedition.khronos.egl.EGLConfig
|
||||||
|
import javax.microedition.khronos.opengles.GL10
|
||||||
|
import java.nio.ByteBuffer
|
||||||
|
import java.nio.ByteOrder
|
||||||
|
import java.nio.FloatBuffer
|
||||||
|
import android.hardware.Camera
|
||||||
|
import android.opengl.GLSurfaceView
|
||||||
|
import android.view.SurfaceView
|
||||||
|
import android.view.TextureView
|
||||||
|
import android.view.View
|
||||||
|
import android.view.Surface
|
||||||
|
import android.widget.TextView
|
||||||
|
import androidx.core.app.ActivityCompat
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
|
import androidx.lifecycle.DefaultLifecycleObserver
|
||||||
|
import io.flutter.plugin.common.BinaryMessenger
|
||||||
|
import io.flutter.plugin.common.MethodCall
|
||||||
|
import io.flutter.plugin.common.MethodChannel
|
||||||
|
import io.flutter.plugin.platform.PlatformView
|
||||||
|
import java.io.IOException
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
|
|
||||||
|
import com.sun.jna.Library
|
||||||
|
import com.sun.jna.Native
|
||||||
|
import com.sun.jna.Pointer
|
||||||
|
import com.sun.jna.ptr.PointerByReference
|
||||||
|
import com.sun.jna.ptr.IntByReference
|
||||||
|
import com.sun.jna.Structure
|
||||||
|
import com.sun.jna.NativeLibrary
|
||||||
|
import com.sun.jna.StringArray
|
||||||
|
import com.sun.jna.JNIEnv
|
||||||
|
|
||||||
|
import android.R.attr.path
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
|
import com.google.android.filament.android.DisplayHelper
|
||||||
|
|
||||||
|
import android.hardware.display.DisplayManager
|
||||||
|
|
||||||
|
import com.google.android.filament.android.*
|
||||||
|
import com.google.android.filament.*
|
||||||
|
import com.google.android.filament.SwapChain
|
||||||
|
import com.google.android.filament.utils.*
|
||||||
|
|
||||||
|
import android.view.Choreographer
|
||||||
|
import android.view.SurfaceHolder
|
||||||
|
|
||||||
|
|
||||||
|
class FilamentView(
|
||||||
|
private val viewId: Int,
|
||||||
|
private val context: Context,
|
||||||
|
private val activity: Activity,
|
||||||
|
private val binaryMessenger: BinaryMessenger,
|
||||||
|
private val creationParams : Map<String?, Any?>?
|
||||||
|
) : DefaultLifecycleObserver,
|
||||||
|
MethodChannel.MethodCallHandler,
|
||||||
|
PlatformView {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val TAG = "FilamentView"
|
||||||
|
}
|
||||||
|
|
||||||
|
private val _view = SurfaceView(context)
|
||||||
|
|
||||||
|
override fun getView(): View {
|
||||||
|
return _view
|
||||||
|
}
|
||||||
|
|
||||||
|
private val _methodChannel: MethodChannel
|
||||||
|
|
||||||
|
private lateinit var _lib : FilamentInterop
|
||||||
|
|
||||||
|
private var _viewer : Pointer? = null
|
||||||
|
|
||||||
|
private lateinit var choreographer: Choreographer
|
||||||
|
private lateinit var displayHelper : DisplayHelper
|
||||||
|
private val frameScheduler = FrameCallback()
|
||||||
|
|
||||||
|
private lateinit var uiHelper : UiHelper
|
||||||
|
|
||||||
|
private lateinit var assetManager : AssetManager
|
||||||
|
|
||||||
|
init {
|
||||||
|
MethodChannel(binaryMessenger, PolyvoxFilamentPlugin.VIEW_TYPE + '_' + viewId).also {
|
||||||
|
_methodChannel = it
|
||||||
|
it.setMethodCallHandler(this)
|
||||||
|
}
|
||||||
|
_lib = Native.loadLibrary("filament_interop", FilamentInterop::class.java, Collections.singletonMap(Library.OPTION_ALLOW_OBJECTS, true))
|
||||||
|
|
||||||
|
|
||||||
|
choreographer = Choreographer.getInstance()
|
||||||
|
|
||||||
|
_view.setZOrderOnTop(false)
|
||||||
|
_view.holder.setFormat(PixelFormat.OPAQUE)
|
||||||
|
|
||||||
|
_view.holder.addCallback (object : SurfaceHolder.Callback {
|
||||||
|
override fun surfaceChanged(holder:SurfaceHolder, format:Int, width:Int, height:Int) {
|
||||||
|
_lib.update_viewport_and_camera_projection(_viewer!!, width, height, 1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun surfaceCreated(holder:SurfaceHolder) {
|
||||||
|
_lib.destroy_swap_chain(_viewer!!)
|
||||||
|
_lib.create_swap_chain(_viewer!!, _view.holder.surface, JNIEnv.CURRENT)
|
||||||
|
}
|
||||||
|
override fun surfaceDestroyed(holder:SurfaceHolder) {
|
||||||
|
_lib.destroy_swap_chain(_viewer!!)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
assetManager = context.assets
|
||||||
|
_viewer = _lib.filament_viewer_new(
|
||||||
|
_view.holder.surface as Object,
|
||||||
|
"unused",
|
||||||
|
"unused",
|
||||||
|
JNIEnv.CURRENT,
|
||||||
|
assetManager)
|
||||||
|
|
||||||
|
choreographer.postFrameCallback(frameScheduler)
|
||||||
|
|
||||||
|
val mDisplayManager = context.getSystemService(Context.DISPLAY_SERVICE) as DisplayManager
|
||||||
|
|
||||||
|
activity.window.setFormat(PixelFormat.RGBA_8888)
|
||||||
|
|
||||||
|
uiHelper = UiHelper(UiHelper.ContextErrorPolicy.DONT_CHECK)
|
||||||
|
uiHelper.renderCallback = SurfaceCallback()
|
||||||
|
uiHelper.attachTo(_view)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onFlutterViewAttached(flutterView:View) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun dispose() {
|
||||||
|
_methodChannel.setMethodCallHandler(null)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
|
||||||
|
when (call.method) {
|
||||||
|
"loadSkybox" -> {
|
||||||
|
val args = call.arguments as ArrayList<Any?>
|
||||||
|
val loader = FlutterInjector.instance().flutterLoader()
|
||||||
|
_lib.load_skybox(_viewer!!, loader.getLookupKeyForAsset(args[0] as String), loader.getLookupKeyForAsset(args[1] as String))
|
||||||
|
result.success("OK");
|
||||||
|
}
|
||||||
|
"loadGlb" -> {
|
||||||
|
if (_viewer == null)
|
||||||
|
return;
|
||||||
|
val loader = FlutterInjector.instance().flutterLoader()
|
||||||
|
_lib.load_glb(
|
||||||
|
_viewer!!,
|
||||||
|
loader.getLookupKeyForAsset(call.arguments as String)
|
||||||
|
)
|
||||||
|
result.success("OK");
|
||||||
|
}
|
||||||
|
"loadGltf" -> {
|
||||||
|
if (_viewer == null)
|
||||||
|
return;
|
||||||
|
val args = call.arguments as ArrayList<Any?>
|
||||||
|
val loader = FlutterInjector.instance().flutterLoader()
|
||||||
|
_lib.load_gltf(
|
||||||
|
_viewer!!,
|
||||||
|
loader.getLookupKeyForAsset(args[0] as String),
|
||||||
|
loader.getLookupKeyForAsset(args[1] as String)
|
||||||
|
)
|
||||||
|
result.success("OK");
|
||||||
|
}
|
||||||
|
"setCamera" -> {
|
||||||
|
if (_viewer == null)
|
||||||
|
return;
|
||||||
|
_lib.set_camera(
|
||||||
|
_viewer!!,
|
||||||
|
call.arguments as String
|
||||||
|
)
|
||||||
|
result.success("OK");
|
||||||
|
}
|
||||||
|
"zoom" -> {
|
||||||
|
if(_viewer == null)
|
||||||
|
return;
|
||||||
|
_lib.scroll(_viewer!!, 0.0f, 0.0f, (call.arguments as Double).toFloat())
|
||||||
|
result.success("OK");
|
||||||
|
}
|
||||||
|
"getTargetNames" -> {
|
||||||
|
if(_viewer == null)
|
||||||
|
return;
|
||||||
|
val arrPtr = PointerByReference();
|
||||||
|
val countPtr = IntByReference();
|
||||||
|
_lib.get_target_names(_viewer!!, call.arguments as String, arrPtr, countPtr)
|
||||||
|
|
||||||
|
val names = arrPtr.value.getStringArray(0, countPtr.value);
|
||||||
|
|
||||||
|
_lib.free_pointer(arrPtr.value, countPtr.getValue())
|
||||||
|
val namesAsList = names.toCollection(ArrayList())
|
||||||
|
result.success(namesAsList)
|
||||||
|
}
|
||||||
|
"applyWeights" -> {
|
||||||
|
if(_viewer == null)
|
||||||
|
return;
|
||||||
|
val weights = call.arguments as ArrayList<Float>;
|
||||||
|
|
||||||
|
_lib.apply_weights(_viewer!!, weights.toFloatArray(), weights.size)
|
||||||
|
result.success("OK");
|
||||||
|
}
|
||||||
|
"panStart" -> {
|
||||||
|
val args = call.arguments as ArrayList<Any?>
|
||||||
|
_lib.grab_begin(_viewer!!, args[0] as Int, args[1] as Int, true)
|
||||||
|
result.success("OK");
|
||||||
|
}
|
||||||
|
"panUpdate" -> {
|
||||||
|
val args = call.arguments as ArrayList<Any?>
|
||||||
|
_lib.grab_update(_viewer!!, args[0] as Int, args[1] as Int)
|
||||||
|
result.success("OK");
|
||||||
|
}
|
||||||
|
"panEnd" -> {
|
||||||
|
_lib.grab_end(_viewer!!)
|
||||||
|
result.success("OK");
|
||||||
|
}
|
||||||
|
"rotateStart" -> {
|
||||||
|
val args = call.arguments as ArrayList<Any?>
|
||||||
|
_lib.grab_begin(_viewer!!, args[0] as Int, args[1] as Int, false)
|
||||||
|
result.success("OK");
|
||||||
|
}
|
||||||
|
"rotateUpdate" -> {
|
||||||
|
val args = call.arguments as ArrayList<Any?>
|
||||||
|
_lib.grab_update(_viewer!!, args[0] as Int, args[1] as Int)
|
||||||
|
result.success("OK");
|
||||||
|
}
|
||||||
|
"rotateEnd" -> {
|
||||||
|
_lib.grab_end(_viewer!!)
|
||||||
|
result.success("OK");
|
||||||
|
}
|
||||||
|
"grabStart" -> {
|
||||||
|
val args = call.arguments as ArrayList<Any?>
|
||||||
|
_lib.grab_begin(_viewer!!, args[0] as Int, args[1] as Int, true)
|
||||||
|
result.success("OK");
|
||||||
|
}
|
||||||
|
"grabUpdate" -> {
|
||||||
|
val args = call.arguments as ArrayList<Any?>
|
||||||
|
_lib.grab_update(_viewer!!, args[0] as Int, args[1] as Int)
|
||||||
|
result.success("OK");
|
||||||
|
}
|
||||||
|
"grabEnd" -> {
|
||||||
|
_lib.grab_end(_viewer!!)
|
||||||
|
result.success("OK");
|
||||||
|
}
|
||||||
|
"releaseSourceAssets" -> {
|
||||||
|
_lib.release_source_assets(_viewer!!)
|
||||||
|
result.success("OK");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inner class SurfaceCallback : UiHelper.RendererCallback {
|
||||||
|
override fun onNativeWindowChanged(surface: Surface) {
|
||||||
|
_lib.destroy_swap_chain(_viewer!!)
|
||||||
|
_lib.create_swap_chain(_viewer!!, surface, JNIEnv.CURRENT)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDetachedFromSurface() {
|
||||||
|
_lib.destroy_swap_chain(_viewer!!)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResized(width: Int, height: Int) {
|
||||||
|
_lib.update_viewport_and_camera_projection(_viewer!!, width, height, 1.0f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inner class FrameCallback : Choreographer.FrameCallback {
|
||||||
|
private val startTime = System.nanoTime()
|
||||||
|
override fun doFrame(frameTimeNanos: Long) {
|
||||||
|
choreographer.postFrameCallback(this)
|
||||||
|
|
||||||
|
// modelViewer.animator?.apply {
|
||||||
|
// if (animationCount > 0) {
|
||||||
|
// val elapsedTimeSeconds = (frameTimeNanos - startTime).toDouble() / 1_000_000_000
|
||||||
|
// applyAnimation(0, elapsedTimeSeconds.toFloat())
|
||||||
|
// }
|
||||||
|
// updateBoneMatrices()
|
||||||
|
// }
|
||||||
|
_lib.render(_viewer!!)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package app.polyvox.filament
|
||||||
|
|
||||||
|
import io.flutter.plugin.common.BinaryMessenger
|
||||||
|
import android.app.Activity
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.view.View
|
||||||
|
import io.flutter.plugin.common.StandardMessageCodec
|
||||||
|
import io.flutter.plugin.platform.PlatformView
|
||||||
|
import io.flutter.plugin.platform.PlatformViewFactory
|
||||||
|
|
||||||
|
class FilamentViewFactory(
|
||||||
|
private val activity: Activity,
|
||||||
|
private val binaryMessenger: BinaryMessenger
|
||||||
|
) : PlatformViewFactory(StandardMessageCodec.INSTANCE) {
|
||||||
|
override fun create(context: Context, viewId: Int, args: Any?): PlatformView {
|
||||||
|
val creationParams = args as Map<String?, Any?>?
|
||||||
|
return FilamentView(viewId, context, activity, binaryMessenger, creationParams)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,26 +2,53 @@ package app.polyvox.filament
|
|||||||
|
|
||||||
import androidx.annotation.NonNull
|
import androidx.annotation.NonNull
|
||||||
|
|
||||||
|
import androidx.lifecycle.Lifecycle
|
||||||
|
|
||||||
|
import io.flutter.embedding.engine.plugins.activity.ActivityAware
|
||||||
|
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
|
||||||
import io.flutter.embedding.engine.plugins.FlutterPlugin
|
import io.flutter.embedding.engine.plugins.FlutterPlugin
|
||||||
import io.flutter.plugin.common.MethodCall
|
import io.flutter.plugin.common.MethodCall
|
||||||
import io.flutter.plugin.common.MethodChannel
|
import io.flutter.plugin.common.MethodChannel
|
||||||
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
|
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
|
||||||
import io.flutter.plugin.common.MethodChannel.Result
|
import io.flutter.plugin.common.MethodChannel.Result
|
||||||
|
|
||||||
|
import io.flutter.embedding.engine.plugins.lifecycle.HiddenLifecycleReference
|
||||||
|
|
||||||
|
|
||||||
/** PolyvoxFilamentPlugin */
|
/** PolyvoxFilamentPlugin */
|
||||||
class PolyvoxFilamentPlugin: FlutterPlugin, MethodCallHandler {
|
class PolyvoxFilamentPlugin: FlutterPlugin, MethodCallHandler, ActivityAware {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val VIEW_TYPE = "app.polyvox.filament/filament_view"
|
||||||
|
}
|
||||||
|
|
||||||
/// The MethodChannel that will the communication between Flutter and native Android
|
/// The MethodChannel that will the communication between Flutter and native Android
|
||||||
///
|
///
|
||||||
/// This local reference serves to register the plugin with the Flutter Engine and unregister it
|
/// This local reference serves to register the plugin with the Flutter Engine and unregister it
|
||||||
/// when the Flutter Engine is detached from the Activity
|
/// when the Flutter Engine is detached from the Activity
|
||||||
private lateinit var channel : MethodChannel
|
private lateinit var channel : MethodChannel
|
||||||
|
|
||||||
|
/// Keep a referene to the plugin binding so we can defer construction of a FilamentViewFactory
|
||||||
|
/// until Activity is attached.
|
||||||
|
private lateinit var flutterPluginBinding : FlutterPlugin.FlutterPluginBinding
|
||||||
|
|
||||||
|
private var lifecycle: Lifecycle? = null
|
||||||
|
|
||||||
override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
|
override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
|
||||||
channel = MethodChannel(flutterPluginBinding.binaryMessenger, "polyvox_filament")
|
this.flutterPluginBinding = flutterPluginBinding
|
||||||
|
channel = MethodChannel(flutterPluginBinding.binaryMessenger, "app.polyvox.filament")
|
||||||
channel.setMethodCallHandler(this)
|
channel.setMethodCallHandler(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onAttachedToActivity(binding: ActivityPluginBinding) {
|
||||||
|
lifecycle = (binding.lifecycle as? HiddenLifecycleReference)?.lifecycle
|
||||||
|
flutterPluginBinding
|
||||||
|
.platformViewRegistry
|
||||||
|
.registerViewFactory(VIEW_TYPE, FilamentViewFactory(binding.activity, flutterPluginBinding.binaryMessenger))
|
||||||
|
}
|
||||||
|
|
||||||
override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) {
|
override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) {
|
||||||
|
|
||||||
if (call.method == "getPlatformVersion") {
|
if (call.method == "getPlatformVersion") {
|
||||||
result.success("Android ${android.os.Build.VERSION.RELEASE}")
|
result.success("Android ${android.os.Build.VERSION.RELEASE}")
|
||||||
} else {
|
} else {
|
||||||
@@ -32,4 +59,17 @@ class PolyvoxFilamentPlugin: FlutterPlugin, MethodCallHandler {
|
|||||||
override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) {
|
override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) {
|
||||||
channel.setMethodCallHandler(null)
|
channel.setMethodCallHandler(null)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override fun onReattachedToActivityForConfigChanges(binding: ActivityPluginBinding) {
|
||||||
|
onAttachedToActivity(binding)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDetachedFromActivityForConfigChanges() {
|
||||||
|
onDetachedFromActivity()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDetachedFromActivity() {
|
||||||
|
lifecycle = null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
3
android/src/main/libs/arm64-v8a/libfilament-jni.so
Normal file
3
android/src/main/libs/arm64-v8a/libfilament-jni.so
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:a8f24f2cb744814f1502a1a29164ca9d08c7f844a83e9d077f3831a1fd13c67a
|
||||||
|
size 1723112
|
||||||
3
android/src/main/libs/arm64-v8a/libfilament-utils-jni.so
Normal file
3
android/src/main/libs/arm64-v8a/libfilament-utils-jni.so
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:8cbdbc57e41114b428fbd6e417a4cafbffd83be8994ea0da44b2cdad6abc4e4f
|
||||||
|
size 430944
|
||||||
3
android/src/main/libs/arm64-v8a/libfilament_interop.so
Normal file
3
android/src/main/libs/arm64-v8a/libfilament_interop.so
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:1d2c3b8bf5dae7441fc7d16a345fd7a3fd170e0bcd0f0f054b16ba4e64a289d0
|
||||||
|
size 2152000
|
||||||
3
android/src/main/libs/arm64-v8a/libgltfio-jni.so
Normal file
3
android/src/main/libs/arm64-v8a/libgltfio-jni.so
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:fa2185681699dc2f72ed79bf0f3b227c8a936047e1d0f35edf2854e2dbb0319d
|
||||||
|
size 8758184
|
||||||
3
android/src/main/libs/armeabi-v7a/libfilament-jni.so
Normal file
3
android/src/main/libs/armeabi-v7a/libfilament-jni.so
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:16fbe91a5f417dab44046090e918e3f3fb119cc7aa7ce72e68b1692687915c90
|
||||||
|
size 1378344
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:8cf27e32b857a98c8b8a0862ec55d8b4eb06d2f22d6d7502865f8ed5dd21db78
|
||||||
|
size 344268
|
||||||
3
android/src/main/libs/armeabi-v7a/libfilament_interop.so
Normal file
3
android/src/main/libs/armeabi-v7a/libfilament_interop.so
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:30734d9a58740c04ee282843c2a0db455d4daa239a5d15bf2f5d8c3ef04f21c8
|
||||||
|
size 2346424
|
||||||
3
android/src/main/libs/armeabi-v7a/libgltfio-jni.so
Normal file
3
android/src/main/libs/armeabi-v7a/libgltfio-jni.so
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:b1498fff038d1bcdb7e52d4369b61e71ea33154ebf769934dbcadafb0bbb814b
|
||||||
|
size 8463116
|
||||||
3
android/src/main/libs/x86/libfilament-jni.so
Normal file
3
android/src/main/libs/x86/libfilament-jni.so
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:134ff007e621892b60c01be75173b94fd02be5b94f6818f76c0e639d85003446
|
||||||
|
size 1880488
|
||||||
3
android/src/main/libs/x86/libfilament-utils-jni.so
Normal file
3
android/src/main/libs/x86/libfilament-utils-jni.so
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:a1699bf6ab28d55e49d0a8d4d7ace8043b9477036ae8760f14c4c14deeba94d6
|
||||||
|
size 461552
|
||||||
3
android/src/main/libs/x86/libfilament_interop.so
Normal file
3
android/src/main/libs/x86/libfilament_interop.so
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:bc2e220862a8179129fbfd5fe944e725eec57335c7014bea7ba538d62f6d93de
|
||||||
|
size 2327272
|
||||||
3
android/src/main/libs/x86/libgltfio-jni.so
Normal file
3
android/src/main/libs/x86/libgltfio-jni.so
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:8a82bd46c8f0e3ed5970e873c92f219cdbed2d02d75855ffb889ac3821cf53c8
|
||||||
|
size 8846488
|
||||||
3
android/src/main/libs/x86_64/libfilament-jni.so
Normal file
3
android/src/main/libs/x86_64/libfilament-jni.so
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:e227eefd03b2ef8b79366fc443efe11ec87768c284f33dcfdc8906e3985fc7a6
|
||||||
|
size 1840928
|
||||||
3
android/src/main/libs/x86_64/libfilament-utils-jni.so
Normal file
3
android/src/main/libs/x86_64/libfilament-utils-jni.so
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:43fa88beba41cce0ffa2f25418cee021946818882b91ad6da63194e19b34fca6
|
||||||
|
size 469208
|
||||||
3
android/src/main/libs/x86_64/libfilament_interop.so
Normal file
3
android/src/main/libs/x86_64/libfilament_interop.so
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:f5c0abca686c763b814af96ada136cb872b9d776ebad063b8293bb20488c4a13
|
||||||
|
size 2141136
|
||||||
3
android/src/main/libs/x86_64/libgltfio-jni.so
Normal file
3
android/src/main/libs/x86_64/libgltfio-jni.so
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:39eaf4b8d74194db66401e754527fe3d01a457f829de559ef2503e76b8ffd9e6
|
||||||
|
size 8859584
|
||||||
@@ -23,10 +23,12 @@ if (flutterVersionName == null) {
|
|||||||
|
|
||||||
apply plugin: 'com.android.application'
|
apply plugin: 'com.android.application'
|
||||||
apply plugin: 'kotlin-android'
|
apply plugin: 'kotlin-android'
|
||||||
|
apply plugin: 'kotlin-android-extensions'
|
||||||
|
|
||||||
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
|
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 30
|
compileSdkVersion 31
|
||||||
|
|
||||||
compileOptions {
|
compileOptions {
|
||||||
sourceCompatibility JavaVersion.VERSION_1_8
|
sourceCompatibility JavaVersion.VERSION_1_8
|
||||||
@@ -43,8 +45,8 @@ android {
|
|||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
|
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
|
||||||
applicationId "app.polyvox.polyvox_filament_example"
|
applicationId "app.polyvox.filament_example"
|
||||||
minSdkVersion 16
|
minSdkVersion 21
|
||||||
targetSdkVersion 30
|
targetSdkVersion 30
|
||||||
versionCode flutterVersionCode.toInteger()
|
versionCode flutterVersionCode.toInteger()
|
||||||
versionName flutterVersionName
|
versionName flutterVersionName
|
||||||
@@ -57,6 +59,14 @@ android {
|
|||||||
signingConfig signingConfigs.debug
|
signingConfig signingConfigs.debug
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
packagingOptions {
|
||||||
|
merge "**/libfilament-jni.so"
|
||||||
|
merge "**/libgltfio-jni.so"
|
||||||
|
merge "**/libfilament-utils-jni.so"
|
||||||
|
}
|
||||||
|
aaptOptions {
|
||||||
|
noCompress "ktx"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
flutter {
|
flutter {
|
||||||
@@ -64,5 +74,13 @@ flutter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
|
||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||||
|
implementation "com.google.android.filament:filament-android:1.17.0"
|
||||||
|
implementation "com.google.android.filament:filament-utils-android:1.17.0"
|
||||||
|
implementation "com.google.android.filament:gltfio-android:1.17.0"
|
||||||
|
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.2"
|
||||||
|
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.2"
|
||||||
|
implementation "androidx.annotation:annotation:1.3.0"
|
||||||
|
implementation "androidx.core:core:1.7.0"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="app.polyvox.polyvox_filament_example">
|
package="app.polyvox.filament_example">
|
||||||
<application
|
<application
|
||||||
|
android:name="${applicationName}"
|
||||||
android:label="polyvox_filament_example"
|
android:label="polyvox_filament_example"
|
||||||
android:icon="@mipmap/ic_launcher">
|
android:icon="@mipmap/ic_launcher"
|
||||||
|
android:theme="@android:style/Theme.Translucent.NoTitleBar"
|
||||||
|
>
|
||||||
<activity
|
<activity
|
||||||
android:name=".MainActivity"
|
android:name=".MainActivity"
|
||||||
android:launchMode="singleTop"
|
android:launchMode="singleTop"
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ static polyvox::ResourceBuffer loadResourceGlobal(const char* name) {
|
|||||||
return [_handler loadResource:name];
|
return [_handler loadResource:name];
|
||||||
}
|
}
|
||||||
|
|
||||||
static void* freeResourceGlobal(void* mem, size_t size, void* misc) {
|
static void* freeResourceGlobal(ResourceBuffer rb) {
|
||||||
[_handler freeResource:mem size:size misc:misc ];
|
[_handler freeResource:rb ];
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -37,19 +37,16 @@ static void* freeResourceGlobal(void* mem, size_t size, void* misc) {
|
|||||||
[self handleMethodCall:call result:result];
|
[self handleMethodCall:call result:result];
|
||||||
}];
|
}];
|
||||||
_handler = self;
|
_handler = self;
|
||||||
|
|
||||||
|
_viewer = new polyvox::FilamentViewer(_layer, nullptr, nullptr, loadResourceGlobal, freeResourceGlobal);
|
||||||
|
[_controller setViewer:_viewer];
|
||||||
|
[_controller startDisplayLink];
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)handleMethodCall:(FlutterMethodCall* _Nonnull)call result:(FlutterResult _Nonnull )result {
|
- (void)handleMethodCall:(FlutterMethodCall* _Nonnull)call result:(FlutterResult _Nonnull )result {
|
||||||
if([@"initialize" isEqualToString:call.method]) {
|
if([@"loadSkybox" isEqualToString:call.method]) {
|
||||||
if(!call.arguments)
|
|
||||||
_viewer = new polyvox::FilamentViewer(_layer, nullptr, nullptr, loadResourceGlobal, freeResourceGlobal);
|
|
||||||
else
|
|
||||||
_viewer = new polyvox::FilamentViewer(_layer, [call.arguments[0] UTF8String], [call.arguments[1] UTF8String], loadResourceGlobal, freeResourceGlobal);
|
|
||||||
[_controller setViewer:_viewer];
|
|
||||||
[_controller startDisplayLink];
|
|
||||||
result(@"OK");
|
|
||||||
} else if([@"loadSkybox" isEqualToString:call.method]) {
|
|
||||||
if(!_viewer)
|
if(!_viewer)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -65,6 +62,11 @@ static void* freeResourceGlobal(void* mem, size_t size, void* misc) {
|
|||||||
return; // TODO should throw exception here
|
return; // TODO should throw exception here
|
||||||
_viewer->loadGltf([call.arguments[0] UTF8String], [call.arguments[1] UTF8String]);
|
_viewer->loadGltf([call.arguments[0] UTF8String], [call.arguments[1] UTF8String]);
|
||||||
result(@"OK");
|
result(@"OK");
|
||||||
|
} else if([@"setCamera" isEqualToString:call.method]) {
|
||||||
|
if(!_viewer)
|
||||||
|
return; // TODO should throw exception here
|
||||||
|
_viewer->setCamera([call.arguments UTF8String]);
|
||||||
|
result(@"OK");
|
||||||
} else if([@"panStart" isEqualToString:call.method]) {
|
} else if([@"panStart" isEqualToString:call.method]) {
|
||||||
if(!_viewer)
|
if(!_viewer)
|
||||||
return;
|
return;
|
||||||
@@ -169,8 +171,8 @@ static void* freeResourceGlobal(void* mem, size_t size, void* misc) {
|
|||||||
return rbuf;
|
return rbuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)freeResource:(void*)mem size:(size_t)s misc:(void *)m {
|
- (void)freeResource:(ResourceBuffer)rb {
|
||||||
free(mem);
|
free(rb.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)ready {
|
- (void)ready {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import UIKit
|
|||||||
|
|
||||||
public class SwiftPolyvoxFilamentPlugin: NSObject, FlutterPlugin {
|
public class SwiftPolyvoxFilamentPlugin: NSObject, FlutterPlugin {
|
||||||
public static func register(with registrar: FlutterPluginRegistrar) {
|
public static func register(with registrar: FlutterPluginRegistrar) {
|
||||||
let channel = FlutterMethodChannel(name: "polyvox_filament", binaryMessenger: registrar.messenger())
|
let channel = FlutterMethodChannel(name: "app.polyvox.filament", binaryMessenger: registrar.messenger())
|
||||||
let instance = SwiftPolyvoxFilamentPlugin()
|
let instance = SwiftPolyvoxFilamentPlugin()
|
||||||
registrar.addMethodCallDelegate(instance, channel: channel)
|
registrar.addMethodCallDelegate(instance, channel: channel)
|
||||||
}
|
}
|
||||||
|
|||||||
6327
ios/Classes/cgltf.h
6327
ios/Classes/cgltf.h
File diff suppressed because it is too large
Load Diff
@@ -44,7 +44,9 @@
|
|||||||
#include <utils/JobSystem.h>
|
#include <utils/JobSystem.h>
|
||||||
|
|
||||||
#include "math.h"
|
#include "math.h"
|
||||||
#include "upcast.h"
|
|
||||||
|
#include "FFilamentInstance.h"
|
||||||
|
#include "FFilamentAsset.h"
|
||||||
|
|
||||||
#include <math/mat4.h>
|
#include <math/mat4.h>
|
||||||
#include <math/quat.h>
|
#include <math/quat.h>
|
||||||
@@ -57,13 +59,21 @@
|
|||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "Log.h"
|
||||||
|
|
||||||
|
#include <android/asset_manager.h>
|
||||||
|
#include <android/asset_manager_jni.h>
|
||||||
|
#include <android/native_window_jni.h>
|
||||||
|
#include <android/log.h>
|
||||||
|
#include <android/native_activity.h>
|
||||||
|
|
||||||
using namespace filament;
|
using namespace filament;
|
||||||
using namespace filament::math;
|
using namespace filament::math;
|
||||||
using namespace gltfio;
|
using namespace gltfio;
|
||||||
using namespace utils;
|
using namespace utils;
|
||||||
using namespace std::chrono;
|
using namespace std::chrono;
|
||||||
|
|
||||||
namespace foo {
|
namespace gltfio {
|
||||||
MaterialProvider* createUbershaderLoader(filament::Engine* engine);
|
MaterialProvider* createUbershaderLoader(filament::Engine* engine);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,11 +137,16 @@ FilamentViewer::FilamentViewer(
|
|||||||
FreeResource freeResource) : _layer(layer),
|
FreeResource freeResource) : _layer(layer),
|
||||||
_loadResource(loadResource),
|
_loadResource(loadResource),
|
||||||
_freeResource(freeResource),
|
_freeResource(freeResource),
|
||||||
opaqueShaderResources(nullptr, 0),
|
opaqueShaderResources(nullptr, 0, 0),
|
||||||
fadeShaderResources(nullptr, 0) {
|
fadeShaderResources(nullptr, 0, 0),
|
||||||
|
_assetBuffer(nullptr, 0, 0) {
|
||||||
_engine = Engine::create(Engine::Backend::OPENGL);
|
_engine = Engine::create(Engine::Backend::OPENGL);
|
||||||
|
|
||||||
_renderer = _engine->createRenderer();
|
_renderer = _engine->createRenderer();
|
||||||
|
|
||||||
|
_renderer->setDisplayInfo({ .refreshRate = 60.0f,
|
||||||
|
.presentationDeadlineNanos = (uint64_t)0,
|
||||||
|
.vsyncOffsetNanos = (uint64_t)0 });
|
||||||
_scene = _engine->createScene();
|
_scene = _engine->createScene();
|
||||||
Entity camera = EntityManager::get().create();
|
Entity camera = EntityManager::get().create();
|
||||||
_mainCamera = _engine->createCamera(camera);
|
_mainCamera = _engine->createCamera(camera);
|
||||||
@@ -144,18 +159,22 @@ FilamentViewer::FilamentViewer(
|
|||||||
|
|
||||||
_swapChain = _engine->createSwapChain(_layer);
|
_swapChain = _engine->createSwapChain(_layer);
|
||||||
|
|
||||||
// if(shaderPath) {
|
View::DynamicResolutionOptions options;
|
||||||
opaqueShaderResources = _loadResource(opaqueShaderPath);
|
options.enabled = true;
|
||||||
fadeShaderResources = _loadResource(fadeShaderPath);
|
// options.homogeneousScaling = homogeneousScaling;
|
||||||
_materialProvider = createGPUMorphShaderLoader(
|
// options.minScale = filament::math::float2{ minScale };
|
||||||
opaqueShaderResources.data,
|
// options.maxScale = filament::math::float2{ maxScale };
|
||||||
opaqueShaderResources.size,
|
//options.sharpness = sharpness;
|
||||||
fadeShaderResources.data,
|
options.quality = View::QualityLevel::MEDIUM;;
|
||||||
fadeShaderResources.size,
|
_view->setDynamicResolutionOptions(options);
|
||||||
_engine);
|
|
||||||
// } else {
|
View::MultiSampleAntiAliasingOptions multiSampleAntiAliasingOptions;
|
||||||
// _materialProvider = foo::createUbershaderLoader(_engine);
|
multiSampleAntiAliasingOptions.enabled = true;
|
||||||
// }
|
|
||||||
|
_view->setMultiSampleAntiAliasingOptions(multiSampleAntiAliasingOptions);
|
||||||
|
|
||||||
|
_materialProvider = gltfio::createUbershaderLoader(_engine);
|
||||||
|
|
||||||
EntityManager& em = EntityManager::get();
|
EntityManager& em = EntityManager::get();
|
||||||
_ncm = new NameComponentManager(em);
|
_ncm = new NameComponentManager(em);
|
||||||
_assetLoader = AssetLoader::create({_engine, _materialProvider, _ncm, &em});
|
_assetLoader = AssetLoader::create({_engine, _materialProvider, _ncm, &em});
|
||||||
@@ -163,7 +182,7 @@ FilamentViewer::FilamentViewer(
|
|||||||
{.engine = _engine, .normalizeSkinningWeights = true, .recomputeBoundingBoxes = false});
|
{.engine = _engine, .normalizeSkinningWeights = true, .recomputeBoundingBoxes = false});
|
||||||
|
|
||||||
manipulator =
|
manipulator =
|
||||||
Manipulator<float>::Builder().orbitHomePosition(0.0f, -1.4f, 1.0f).targetPosition(0.0f, -0.5f, 0.75f).build(Mode::ORBIT);
|
Manipulator<float>::Builder().orbitHomePosition(0.0f, 0.0f, 0.0f).targetPosition(0.0f, 0.0f, -4.0f).build(Mode::ORBIT);
|
||||||
_asset = nullptr;
|
_asset = nullptr;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -172,21 +191,54 @@ FilamentViewer::~FilamentViewer() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void printWeights(float* weights, int numWeights) {
|
Renderer* FilamentViewer::getRenderer() {
|
||||||
for(int i =0; i < numWeights; i++) {
|
return _renderer;
|
||||||
// std::cout << weights[i];
|
}
|
||||||
|
|
||||||
|
void FilamentViewer::createSwapChain(void* surface) {
|
||||||
|
_swapChain = _engine->createSwapChain(surface);
|
||||||
|
// Log("swapchain created.");
|
||||||
|
}
|
||||||
|
|
||||||
|
void FilamentViewer::destroySwapChain() {
|
||||||
|
if(_swapChain) {
|
||||||
|
_engine->destroy(_swapChain);
|
||||||
|
_swapChain = nullptr;
|
||||||
|
}
|
||||||
|
// Log("swapchain destroyed.");
|
||||||
|
}
|
||||||
|
|
||||||
|
void FilamentViewer::applyWeights(float* weights, int count) {
|
||||||
|
|
||||||
|
for (size_t i = 0, c = _asset->getEntityCount(); i != c; ++i) {
|
||||||
|
_asset->setMorphWeights(
|
||||||
|
_asset->getEntities()[i],
|
||||||
|
weights,
|
||||||
|
count
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FilamentViewer::loadResources(string relativeResourcePath) {
|
void FilamentViewer::loadResources(string relativeResourcePath) {
|
||||||
const char* const* const resourceUris = _asset->getResourceUris();
|
const char* const* const resourceUris = _asset->getResourceUris();
|
||||||
const size_t resourceUriCount = _asset->getResourceUriCount();
|
const size_t resourceUriCount = _asset->getResourceUriCount();
|
||||||
|
|
||||||
|
Log("Loading %d resources for asset", resourceUriCount);
|
||||||
|
|
||||||
for (size_t i = 0; i < resourceUriCount; i++) {
|
for (size_t i = 0; i < resourceUriCount; i++) {
|
||||||
string uri = relativeResourcePath + string(resourceUris[i]);
|
string uri = relativeResourcePath + string(resourceUris[i]);
|
||||||
ResourceBuffer buf = _loadResource(uri.c_str());
|
ResourceBuffer buf = _loadResource(uri.c_str());
|
||||||
|
|
||||||
|
// using FunctionCallback = std::function<void(void*, unsigned int, void *)>;
|
||||||
|
|
||||||
|
// auto cb = [&] (void * ptr, unsigned int len, void * misc) {
|
||||||
|
|
||||||
|
// };
|
||||||
|
// FunctionCallback fcb = cb;
|
||||||
ResourceLoader::BufferDescriptor b(
|
ResourceLoader::BufferDescriptor b(
|
||||||
buf.data, buf.size, (ResourceLoader::BufferDescriptor::Callback)&_freeResource, nullptr);
|
buf.data, buf.size);
|
||||||
_resourceLoader->addResourceData(resourceUris[i], std::move(b));
|
_resourceLoader->addResourceData(resourceUris[i], std::move(b));
|
||||||
|
_freeResource(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
_resourceLoader->loadResources(_asset);
|
_resourceLoader->loadResources(_asset);
|
||||||
@@ -204,26 +256,22 @@ void FilamentViewer::loadResources(string relativeResourcePath) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
void FilamentViewer::releaseSourceAssets() {
|
void FilamentViewer::releaseSourceAssets() {
|
||||||
std::cout << "Releasing source data" << std::endl;
|
Log("Releasing source data");
|
||||||
_asset->releaseSourceData();
|
_asset->releaseSourceData();
|
||||||
_freeResource((void*)opaqueShaderResources.data, opaqueShaderResources.size, nullptr);
|
// _freeResource(opaqueShaderResources);
|
||||||
_freeResource((void*)fadeShaderResources.data, fadeShaderResources.size, nullptr);
|
// _freeResource(fadeShaderResources);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FilamentViewer::animateWeights(float* data, int numWeights, int length, float frameRate) {
|
|
||||||
// transformToUnitCube();
|
|
||||||
morphAnimationBuffer = std::make_unique<MorphAnimationBuffer>(data, numWeights, length / numWeights, 1000 / frameRate );
|
|
||||||
}
|
|
||||||
|
|
||||||
void FilamentViewer::loadGlb(const char* const uri) {
|
void FilamentViewer::loadGlb(const char* const uri) {
|
||||||
|
|
||||||
std::cerr << "Loading GLB at URI " << uri << std::endl;
|
Log("Loading GLB at URI %s", uri);
|
||||||
|
|
||||||
if(_asset) {
|
if(_asset) {
|
||||||
_resourceLoader->evictResourceData();
|
_resourceLoader->evictResourceData();
|
||||||
_scene->removeEntities(_asset->getEntities(), _asset->getEntityCount());
|
_scene->removeEntities(_asset->getEntities(), _asset->getEntityCount());
|
||||||
_assetLoader->destroyAsset(_asset);
|
_assetLoader->destroyAsset(_asset);
|
||||||
|
_freeResource(_assetBuffer);
|
||||||
}
|
}
|
||||||
_asset = nullptr;
|
_asset = nullptr;
|
||||||
_animator = nullptr;
|
_animator = nullptr;
|
||||||
@@ -234,7 +282,7 @@ void FilamentViewer::loadGlb(const char* const uri) {
|
|||||||
(const uint8_t*)rbuf.data, rbuf.size);
|
(const uint8_t*)rbuf.data, rbuf.size);
|
||||||
|
|
||||||
if (!_asset) {
|
if (!_asset) {
|
||||||
std::cerr << "Unknown error loading GLB asset." << std::endl;
|
Log("Unknown error loading GLB asset.");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -242,7 +290,7 @@ void FilamentViewer::loadGlb(const char* const uri) {
|
|||||||
|
|
||||||
_scene->addEntities(_asset->getEntities(), entityCount);
|
_scene->addEntities(_asset->getEntities(), entityCount);
|
||||||
|
|
||||||
std::cerr << "Added " << entityCount << " entities to scene" << std::endl;
|
Log("Added %d entities to scene", entityCount);
|
||||||
_resourceLoader->loadResources(_asset);
|
_resourceLoader->loadResources(_asset);
|
||||||
_animator = _asset->getAnimator();
|
_animator = _asset->getAnimator();
|
||||||
|
|
||||||
@@ -254,56 +302,58 @@ void FilamentViewer::loadGlb(const char* const uri) {
|
|||||||
rm.setCulling(inst, false);
|
rm.setCulling(inst, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
_freeResource((void*)rbuf.data, rbuf.size, nullptr);
|
_freeResource(rbuf);
|
||||||
|
|
||||||
// transformToUnitCube();
|
Log("Successfully loaded GLB.");
|
||||||
|
|
||||||
setCamera("Camera.001"); // TODO - expose this for external invocation
|
|
||||||
|
|
||||||
|
|
||||||
std::cerr << "Successfully loaded GLB." << std::endl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FilamentViewer::loadGltf(const char* const uri, const char* const relativeResourcePath) {
|
void FilamentViewer::loadGltf(const char* const uri, const char* const relativeResourcePath) {
|
||||||
|
|
||||||
|
Log("Loading GLTF at URI %s", uri);
|
||||||
|
|
||||||
if(_asset) {
|
if(_asset) {
|
||||||
|
Log("Asset already exists");
|
||||||
_resourceLoader->evictResourceData();
|
_resourceLoader->evictResourceData();
|
||||||
_scene->removeEntities(_asset->getEntities(), _asset->getEntityCount());
|
_scene->removeEntities(_asset->getEntities(), _asset->getEntityCount());
|
||||||
_assetLoader->destroyAsset(_asset);
|
_assetLoader->destroyAsset(_asset);
|
||||||
|
_freeResource(_assetBuffer);
|
||||||
}
|
}
|
||||||
_asset = nullptr;
|
_asset = nullptr;
|
||||||
_animator = nullptr;
|
_animator = nullptr;
|
||||||
|
|
||||||
ResourceBuffer rbuf = _loadResource(uri);
|
_assetBuffer = _loadResource(uri);
|
||||||
|
|
||||||
// Parse the glTF file and create Filament entities.
|
// Parse the glTF file and create Filament entities.
|
||||||
_asset = _assetLoader->createAssetFromJson((uint8_t*)rbuf.data, rbuf.size);
|
Log("Creating asset from JSON");
|
||||||
|
_asset = _assetLoader->createAssetFromJson((uint8_t*)_assetBuffer.data, _assetBuffer.size);
|
||||||
|
Log("Created asset from JSON");
|
||||||
|
|
||||||
if (!_asset) {
|
if (!_asset) {
|
||||||
std::cerr << "Unable to parse asset" << std::endl;
|
Log("Unable to parse asset");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
Log("Loading relative resources");
|
||||||
loadResources(string(relativeResourcePath) + string("/"));
|
loadResources(string(relativeResourcePath) + string("/"));
|
||||||
|
Log("Loaded relative resources");
|
||||||
|
// _asset->releaseSourceData();
|
||||||
|
|
||||||
_freeResource((void*)rbuf.data, rbuf.size, nullptr);
|
Log("Load complete for GLTF at URI %s", uri);
|
||||||
|
|
||||||
|
transformToUnitCube();
|
||||||
|
|
||||||
// transformToUnitCube();
|
|
||||||
|
|
||||||
setCamera("Camera.001"); // TODO - expose this for external invocation
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FilamentViewer::setCamera(const char* cameraName) {
|
void FilamentViewer::setCamera(const char* cameraName) {
|
||||||
FFilamentAsset* asset = (FFilamentAsset*)_asset;
|
FFilamentAsset* asset = (FFilamentAsset*)_asset;
|
||||||
|
|
||||||
NodeMap &sourceNodes = asset->isInstanced() ? asset->mInstances[0]->nodeMap
|
gltfio::NodeMap &sourceNodes = asset->isInstanced() ? asset->mInstances[0]->nodeMap
|
||||||
: asset->mNodeMap;
|
: asset->mNodeMap;
|
||||||
|
|
||||||
for (auto pair : sourceNodes) {
|
for (auto pair : sourceNodes) {
|
||||||
cgltf_node const *node = pair.first;
|
cgltf_node const *node = pair.first;
|
||||||
|
|
||||||
if(node->camera) {
|
if(node->camera) {
|
||||||
std::cout << "Got camera " << node->camera->name << " of type " << node->camera->type << std::endl;
|
Log("Got camera %s of type %s ", node->camera->name, node->camera->type);
|
||||||
|
|
||||||
if(strcmp(cameraName, node->camera->name) == 0) {
|
if(strcmp(cameraName, node->camera->name) == 0) {
|
||||||
filament::math::mat4 mat(
|
filament::math::mat4 mat(
|
||||||
@@ -342,84 +392,48 @@ void FilamentViewer::setCamera(const char* cameraName) {
|
|||||||
|
|
||||||
StringList FilamentViewer::getTargetNames(const char* meshName) {
|
StringList FilamentViewer::getTargetNames(const char* meshName) {
|
||||||
FFilamentAsset* asset = (FFilamentAsset*)_asset;
|
FFilamentAsset* asset = (FFilamentAsset*)_asset;
|
||||||
|
NodeMap &sourceNodes = asset->isInstanced() ? asset->mInstances[0]->nodeMap : asset->mNodeMap;
|
||||||
|
|
||||||
|
if(sourceNodes.empty()) {
|
||||||
|
Log("Asset source nodes empty?");
|
||||||
|
return StringList(nullptr, 0);
|
||||||
|
}
|
||||||
|
Log("Fetching morph target names for mesh %s", meshName);
|
||||||
|
|
||||||
NodeMap &sourceNodes = asset->isInstanced() ? asset->mInstances[0]->nodeMap
|
|
||||||
: asset->mNodeMap;
|
|
||||||
FilamentInstance** instances = asset->getAssetInstances();
|
|
||||||
std::cout << "Fetching morph target names for mesh " << meshName;
|
|
||||||
for (auto pair : sourceNodes) {
|
for (auto pair : sourceNodes) {
|
||||||
cgltf_node const *node = pair.first;
|
cgltf_node const *node = pair.first;
|
||||||
cgltf_mesh const *mesh = node->mesh;
|
cgltf_mesh const *mesh = node->mesh;
|
||||||
|
|
||||||
if(node->camera) {
|
if(node->camera) {
|
||||||
std::cout << "Got camera " << node->camera->name << " of type " << node->camera->type << std::endl;
|
Log("Got camera %s of type %s", node->camera->name, node->camera->type);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mesh) {
|
if (mesh) {
|
||||||
std::cout << "Mesh : " << mesh->name;
|
Log("Mesh : %s ",mesh->name);
|
||||||
if(strcmp(meshName, mesh->name) == 0) {
|
if(strcmp(meshName, mesh->name) == 0) {
|
||||||
return StringList((const char**)mesh->target_names, (int) mesh->target_names_count);
|
return StringList((const char**)mesh->target_names, (int) mesh->target_names_count);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
std::cout << "No mesh attached to node";
|
Log("No mesh attached to node");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return StringList(nullptr, 0);
|
return StringList(nullptr, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FilamentViewer::createMorpher(const char* meshName, int* primitives, int numPrimitives) {
|
|
||||||
morphHelper = new gltfio::GPUMorphHelper((FFilamentAsset*)_asset, meshName, primitives, numPrimitives);
|
|
||||||
// morphHelper = new gltfio::CPUMorpher(((FFilamentAsset)*_asset, (FFilamentInstance*)_asset));
|
|
||||||
}
|
|
||||||
|
|
||||||
void FilamentViewer::applyWeights(float* weights, int count) {
|
void FilamentViewer::loadSkybox(const char* const skyboxPath, const char* const iblPath, AAssetManager* am) {
|
||||||
morphHelper->applyWeights(weights, count);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FilamentViewer::animateBones() {
|
|
||||||
Entity entity = _asset->getFirstEntityByName("CC_Base_JawRoot");
|
|
||||||
if(!entity) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
TransformManager& transformManager = _engine->getTransformManager();
|
|
||||||
|
|
||||||
TransformManager::Instance node = transformManager.getInstance( entity);
|
|
||||||
|
|
||||||
mat4f xform = transformManager.getTransform(node);
|
|
||||||
float3 scale;
|
|
||||||
quatf rotation;
|
|
||||||
float3 translation;
|
|
||||||
decomposeMatrix(xform, &translation, &rotation, &scale);
|
|
||||||
|
|
||||||
// const quatf srcQuat { weights[0] * 0.9238,0,weights[0] * 0.3826, 0 };
|
|
||||||
// float3 { scale[0] * (1.0f - weights[0]), scale[1] * (1.0f - weights[1]), scale[2] * (1.0f - weights[2]) }
|
|
||||||
// xform = composeMatrix(translation + float3 { weights[0], weights[1], weights[2] }, rotation, scale );
|
|
||||||
transformManager.setTransform(node, xform);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void FilamentViewer::playAnimation(int index) {
|
|
||||||
embeddedAnimationBuffer = make_unique<EmbeddedAnimationBuffer>(index, _animator->getAnimationDuration(index));
|
|
||||||
}
|
|
||||||
|
|
||||||
void FilamentViewer::loadSkybox(const char* const skyboxPath, const char* const iblPath) {
|
|
||||||
|
|
||||||
std::cout << "Loading skybox from " << skyboxPath << std::endl;
|
|
||||||
|
|
||||||
ResourceBuffer skyboxBuffer = _loadResource(skyboxPath);
|
ResourceBuffer skyboxBuffer = _loadResource(skyboxPath);
|
||||||
|
|
||||||
std::cout << "Loaded skybox resource buffer of size " << skyboxBuffer.size << std::endl;
|
|
||||||
|
|
||||||
image::KtxBundle* skyboxBundle =
|
image::KtxBundle* skyboxBundle =
|
||||||
new image::KtxBundle(static_cast<const uint8_t*>(skyboxBuffer.data),
|
new image::KtxBundle(static_cast<const uint8_t*>(skyboxBuffer.data), static_cast<uint32_t>(skyboxBuffer.size));
|
||||||
static_cast<uint32_t>(skyboxBuffer.size));
|
_skyboxTexture = image::ktx::createTexture(_engine, skyboxBundle, false);
|
||||||
_skyboxTexture = image::ktx::createTexture(_engine, skyboxBundle, true);
|
|
||||||
_skybox = filament::Skybox::Builder().environment(_skyboxTexture).build(*_engine);
|
_skybox = filament::Skybox::Builder().environment(_skyboxTexture).build(*_engine);
|
||||||
|
// _skybox = Skybox::Builder().color({0.1, 0.125, 0.25, 1.0}).build(*_engine);
|
||||||
_scene->setSkybox(_skybox);
|
_scene->setSkybox(_skybox);
|
||||||
_freeResource((void*)skyboxBuffer.data, skyboxBuffer.size, nullptr);
|
_freeResource(skyboxBuffer);
|
||||||
|
|
||||||
std::cout << "Loading IBL from " << iblPath << std::endl;
|
Log("Loading IBL from %s", iblPath);
|
||||||
|
|
||||||
// Load IBL.
|
// Load IBL.
|
||||||
ResourceBuffer iblBuffer = _loadResource(iblPath);
|
ResourceBuffer iblBuffer = _loadResource(iblPath);
|
||||||
@@ -436,7 +450,7 @@ void FilamentViewer::loadSkybox(const char* const skyboxPath, const char* const
|
|||||||
.build(*_engine);
|
.build(*_engine);
|
||||||
_scene->setIndirectLight(_indirectLight);
|
_scene->setIndirectLight(_indirectLight);
|
||||||
|
|
||||||
_freeResource((void*)iblBuffer.data, iblBuffer.size, nullptr);
|
_freeResource(iblBuffer);
|
||||||
|
|
||||||
// Always add a direct light source since it is required for shadowing.
|
// Always add a direct light source since it is required for shadowing.
|
||||||
_sun = EntityManager::get().create();
|
_sun = EntityManager::get().create();
|
||||||
@@ -447,10 +461,14 @@ void FilamentViewer::loadSkybox(const char* const skyboxPath, const char* const
|
|||||||
.castShadows(true)
|
.castShadows(true)
|
||||||
.build(*_engine, _sun);
|
.build(*_engine, _sun);
|
||||||
_scene->addEntity(_sun);
|
_scene->addEntity(_sun);
|
||||||
|
|
||||||
|
Log("Skybox/IBL load complete.");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FilamentViewer::transformToUnitCube() {
|
void FilamentViewer::transformToUnitCube() {
|
||||||
if (!_asset) {
|
if (!_asset) {
|
||||||
|
Log("No asset, cannot transform.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto& tm = _engine->getTransformManager();
|
auto& tm = _engine->getTransformManager();
|
||||||
@@ -468,36 +486,47 @@ void FilamentViewer::cleanup() {
|
|||||||
_assetLoader->destroyAsset(_asset);
|
_assetLoader->destroyAsset(_asset);
|
||||||
_materialProvider->destroyMaterials();
|
_materialProvider->destroyMaterials();
|
||||||
AssetLoader::destroy(&_assetLoader);
|
AssetLoader::destroy(&_assetLoader);
|
||||||
|
_freeResource(_assetBuffer);
|
||||||
};
|
};
|
||||||
|
|
||||||
void FilamentViewer::render() {
|
void FilamentViewer::render() {
|
||||||
if (!_view || !_mainCamera || !manipulator || !_animator) {
|
if (!_view || !_mainCamera || !_swapChain) {
|
||||||
|
Log("Not ready for rendering");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Extract the camera basis from the helper and push it to the Filament camera.
|
|
||||||
//math::float3 eye, target, upward;
|
|
||||||
//manipulator->getLookAt(&eye, &target, &upward);
|
|
||||||
|
|
||||||
//_mainCamera->lookAt(eye, target, upward);
|
math::float3 eye, target, upward;
|
||||||
|
manipulator->getLookAt(&eye, &target, &upward);
|
||||||
if(morphAnimationBuffer) {
|
_mainCamera->lookAt(eye, target, upward);
|
||||||
updateMorphAnimation();
|
|
||||||
}
|
|
||||||
|
|
||||||
if(embeddedAnimationBuffer) {
|
|
||||||
updateEmbeddedAnimation();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Render the scene, unless the renderer wants to skip the frame.
|
// Render the scene, unless the renderer wants to skip the frame.
|
||||||
if (_renderer->beginFrame(_swapChain)) {
|
if (_renderer->beginFrame(_swapChain)) {
|
||||||
_renderer->render(_view);
|
_renderer->render(_view);
|
||||||
_renderer->endFrame();
|
_renderer->endFrame();
|
||||||
} else {
|
}
|
||||||
// std::cout << "Skipping frame" << std::endl;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//void FilamentViewer::updateAnimation(AnimationBuffer animation, std::function<void(int)> moo) {
|
|
||||||
|
void FilamentViewer::updateViewportAndCameraProjection(int width, int height, float contentScaleFactor) {
|
||||||
|
if (!_view || !_mainCamera) {
|
||||||
|
Log("Skipping camera update, no view or camrea");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint32_t _width = width * contentScaleFactor;
|
||||||
|
const uint32_t _height = height * contentScaleFactor;
|
||||||
|
_view->setViewport({0, 0, _width, _height});
|
||||||
|
|
||||||
|
const double aspect = (double)width / height;
|
||||||
|
_mainCamera->setLensProjection(_cameraFocalLength, aspect, kNearPlane, kFarPlane);
|
||||||
|
Log("Set viewport to %d %d", _width, _height);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//void FilamentViewer::updateAnimation(AnimationBuffer animation, std::function<void(int)> moo) {
|
||||||
// if(morphAnimationBuffer.frameIndex >= animation.numFrames) {
|
// if(morphAnimationBuffer.frameIndex >= animation.numFrames) {
|
||||||
// this.animation = null;
|
// this.animation = null;
|
||||||
// return;
|
// return;
|
||||||
@@ -518,80 +547,115 @@ void FilamentViewer::render() {
|
|||||||
// }
|
// }
|
||||||
//}
|
//}
|
||||||
|
|
||||||
void FilamentViewer::updateMorphAnimation() {
|
// void FilamentViewer::updateMorphAnimation() {
|
||||||
|
|
||||||
if(morphAnimationBuffer->frameIndex >= morphAnimationBuffer->numFrames) {
|
// if(morphAnimationBuffer->frameIndex >= morphAnimationBuffer->numFrames) {
|
||||||
morphAnimationBuffer = nullptr;
|
// morphAnimationBuffer = nullptr;
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
|
|
||||||
if(morphAnimationBuffer->frameIndex == -1) {
|
// if(morphAnimationBuffer->frameIndex == -1) {
|
||||||
morphAnimationBuffer->frameIndex++;
|
// morphAnimationBuffer->frameIndex++;
|
||||||
morphAnimationBuffer->startTime = std::chrono::high_resolution_clock::now();
|
// morphAnimationBuffer->startTime = std::chrono::high_resolution_clock::now();
|
||||||
applyWeights(morphAnimationBuffer->frameData, morphAnimationBuffer->numWeights);
|
// applyWeights(morphAnimationBuffer->frameData, morphAnimationBuffer->numWeights);
|
||||||
} else {
|
// } else {
|
||||||
std::chrono::duration<double, std::milli> dur = std::chrono::high_resolution_clock::now() - morphAnimationBuffer->startTime;
|
// std::chrono::duration<double, std::milli> dur = std::chrono::high_resolution_clock::now() - morphAnimationBuffer->startTime;
|
||||||
int frameIndex = dur.count() / morphAnimationBuffer->frameLength;
|
// int frameIndex = dur.count() / morphAnimationBuffer->frameLength;
|
||||||
if(frameIndex != morphAnimationBuffer->frameIndex) {
|
// if(frameIndex != morphAnimationBuffer->frameIndex) {
|
||||||
morphAnimationBuffer->frameIndex = frameIndex;
|
// morphAnimationBuffer->frameIndex = frameIndex;
|
||||||
applyWeights(morphAnimationBuffer->frameData + (morphAnimationBuffer->frameIndex * morphAnimationBuffer->numWeights), morphAnimationBuffer->numWeights);
|
// applyWeights(morphAnimationBuffer->frameData + (morphAnimationBuffer->frameIndex * morphAnimationBuffer->numWeights), morphAnimationBuffer->numWeights);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
}
|
// }
|
||||||
|
|
||||||
void FilamentViewer::updateEmbeddedAnimation() {
|
// void FilamentViewer::updateEmbeddedAnimation() {
|
||||||
duration<double> dur = duration_cast<duration<double>>(std::chrono::high_resolution_clock::now() - embeddedAnimationBuffer->lastTime);
|
// duration<double> dur = duration_cast<duration<double>>(std::chrono::high_resolution_clock::now() - embeddedAnimationBuffer->lastTime);
|
||||||
float startTime = 0;
|
// float startTime = 0;
|
||||||
if(!embeddedAnimationBuffer->hasStarted) {
|
// if(!embeddedAnimationBuffer->hasStarted) {
|
||||||
embeddedAnimationBuffer->hasStarted = true;
|
// embeddedAnimationBuffer->hasStarted = true;
|
||||||
embeddedAnimationBuffer->lastTime = std::chrono::high_resolution_clock::now();
|
// embeddedAnimationBuffer->lastTime = std::chrono::high_resolution_clock::now();
|
||||||
} else if(dur.count() >= embeddedAnimationBuffer->duration) {
|
// } else if(dur.count() >= embeddedAnimationBuffer->duration) {
|
||||||
embeddedAnimationBuffer = nullptr;
|
// embeddedAnimationBuffer = nullptr;
|
||||||
return;
|
// return;
|
||||||
} else {
|
// } else {
|
||||||
startTime = dur.count();
|
// startTime = dur.count();
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
|
||||||
_animator->applyAnimation(embeddedAnimationBuffer->animationIndex, startTime);
|
// _animator->applyAnimation(embeddedAnimationBuffer->animationIndex, startTime);
|
||||||
_animator->updateBoneMatrices();
|
// _animator->updateBoneMatrices();
|
||||||
|
|
||||||
}
|
// }
|
||||||
//
|
// //
|
||||||
//if(morphAnimationBuffer.frameIndex >= morphAnimationBuffer.numFrames) {
|
// //if(morphAnimationBuffer.frameIndex >= morphAnimationBuffer.numFrames) {
|
||||||
// this.morphAnimationBuffer = null;
|
// // this.morphAnimationBuffer = null;
|
||||||
// return;
|
// // return;
|
||||||
//}
|
// //}
|
||||||
//
|
// //
|
||||||
//if(morphAnimationBuffer.frameIndex == -1) {
|
// //if(morphAnimationBuffer.frameIndex == -1) {
|
||||||
// applyWeights(morphAnimationBuffer->frameData, morphAnimationBuffer->numWeights);
|
// // applyWeights(morphAnimationBuffer->frameData, morphAnimationBuffer->numWeights);
|
||||||
// morphAnimationBuffer->frameIndex++;
|
// // morphAnimationBuffer->frameIndex++;
|
||||||
// morphAnimationBuffer->lastTime = std::chrono::high_resolution_clock::now();
|
// // morphAnimationBuffer->lastTime = std::chrono::high_resolution_clock::now();
|
||||||
//} else {
|
// //} else {
|
||||||
// duration dur = std::chrono::high_resolution_clock::now() - morphAnimationBuffer->lastTime;
|
// // duration dur = std::chrono::high_resolution_clock::now() - morphAnimationBuffer->lastTime;
|
||||||
// float msElapsed = dur.count();
|
// // float msElapsed = dur.count();
|
||||||
// if(msElapsed > morphAnimationBuffer->frameLength) {
|
// // if(msElapsed > morphAnimationBuffer->frameLength) {
|
||||||
// frameIndex++;
|
// // frameIndex++;
|
||||||
// applyWeights(frameData + (frameIndex * numWeights), numWeights);
|
// // applyWeights(frameData + (frameIndex * numWeights), numWeights);
|
||||||
// morphAnimationBuffer->lastTime = std::chrono::high_resolution_clock::now();
|
// // morphAnimationBuffer->lastTime = std::chrono::high_resolution_clock::now();
|
||||||
// }
|
// // }
|
||||||
//}
|
// //}
|
||||||
|
// void FilamentViewer::playAnimation(int index) {
|
||||||
|
// embeddedAnimationBuffer = make_unique<EmbeddedAnimationBuffer>(index, _animator->getAnimationDuration(index));
|
||||||
|
// }
|
||||||
|
|
||||||
void FilamentViewer::updateViewportAndCameraProjection(int width, int height, float contentScaleFactor) {
|
// void FilamentViewer::animateWeights(float* data, int numWeights, int length, float frameRate) {
|
||||||
if (!_view || !_mainCamera || !manipulator) {
|
// morphAnimationBuffer = std::make_unique<MorphAnimationBuffer>(data, numWeights, length / numWeights, 1000 / frameRate );
|
||||||
return;
|
// }
|
||||||
}
|
|
||||||
|
|
||||||
manipulator->setViewport(width, height);
|
// if(shaderPath) {
|
||||||
|
// opaqueShaderResources = _loadResource(opaqueShaderPath);
|
||||||
|
// fadeShaderResources = _loadResource(fadeShaderPath);
|
||||||
|
// _materialProvider = createGPUMorphShaderLoader(
|
||||||
|
// opaqueShaderResources.data,
|
||||||
|
// opaqueShaderResources.size,
|
||||||
|
// fadeShaderResources.data,
|
||||||
|
// fadeShaderResources.size,
|
||||||
|
// _engine);
|
||||||
|
// } else {
|
||||||
|
// }
|
||||||
|
// void printWeights(float* weights, int numWeights) {
|
||||||
|
// for(int i =0; i < numWeights; i++) {
|
||||||
|
// // std::cout << weights[i];
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
const uint32_t _width = width * contentScaleFactor;
|
// void FilamentViewer::createMorpher(const char* meshName, int* primitives, int numPrimitives) {
|
||||||
const uint32_t _height = height * contentScaleFactor;
|
// // morphHelper = new gltfio::GPUMorphHelper((FFilamentAsset*)_asset, meshName, primitives, numPrimitives);
|
||||||
_view->setViewport({0, 0, _width, _height});
|
// // morphHelper = new gltfio::CPUMorpher(((FFilamentAsset)*_asset, (FFilamentInstance*)_asset));
|
||||||
|
// }
|
||||||
|
|
||||||
const double aspect = (double)width / height;
|
// void FilamentViewer::animateBones() {
|
||||||
_mainCamera->setLensProjection(_cameraFocalLength, aspect, kNearPlane, kFarPlane);
|
// }
|
||||||
}
|
// Entity entity = _asset->getFirstEntityByName("CC_Base_JawRoot");
|
||||||
|
// if(!entity) {
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// TransformManager& transformManager = _engine->getTransformManager();
|
||||||
|
|
||||||
}
|
// TransformManager::Instance node = transformManager.getInstance( entity);
|
||||||
|
|
||||||
|
// mat4f xform = transformManager.getTransform(node);
|
||||||
|
// float3 scale;
|
||||||
|
// quatf rotation;
|
||||||
|
// float3 translation;
|
||||||
|
// decomposeMatrix(xform, &translation, &rotation, &scale);
|
||||||
|
|
||||||
|
// // const quatf srcQuat { weights[0] * 0.9238,0,weights[0] * 0.3826, 0 };
|
||||||
|
// // float3 { scale[0] * (1.0f - weights[0]), scale[1] * (1.0f - weights[1]), scale[2] * (1.0f - weights[2]) }
|
||||||
|
// // xform = composeMatrix(translation + float3 { weights[0], weights[1], weights[2] }, rotation, scale );
|
||||||
|
// transformManager.setTransform(node, xform);
|
||||||
|
|
||||||
|
// }
|
||||||
@@ -30,7 +30,11 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
|
||||||
#include "GPUMorphHelper.h"
|
#include <android/asset_manager.h>
|
||||||
|
#include <android/asset_manager_jni.h>
|
||||||
|
#include <android/native_window_jni.h>
|
||||||
|
#include <android/log.h>
|
||||||
|
#include <android/native_activity.h>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace filament;
|
using namespace filament;
|
||||||
@@ -51,46 +55,22 @@ namespace polyvox {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct ResourceBuffer {
|
struct ResourceBuffer {
|
||||||
ResourceBuffer(const void* data, const uint32_t size) : data(data), size(size) {};
|
ResourceBuffer(const void* data, const uint32_t size, const uint32_t id) : data(data), size(size), id(id) {};
|
||||||
|
|
||||||
ResourceBuffer& operator=(ResourceBuffer other)
|
ResourceBuffer& operator=(ResourceBuffer other)
|
||||||
{
|
{
|
||||||
data = other.data;
|
data = other.data;
|
||||||
size = other.size;
|
size = other.size;
|
||||||
|
id = other.id;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
const void* data;
|
const void* data;
|
||||||
uint64_t size;
|
uint32_t size;
|
||||||
};
|
uint32_t id;
|
||||||
|
|
||||||
struct MorphAnimationBuffer {
|
|
||||||
|
|
||||||
MorphAnimationBuffer(float* frameData,
|
|
||||||
int numWeights,
|
|
||||||
int numFrames,
|
|
||||||
float frameLength) : frameData(frameData), numWeights(numWeights), numFrames(numFrames), frameLength(frameLength) {
|
|
||||||
}
|
|
||||||
|
|
||||||
int frameIndex = -1;
|
|
||||||
int numFrames;
|
|
||||||
float frameLength;
|
|
||||||
time_point_t startTime;
|
|
||||||
|
|
||||||
float* frameData;
|
|
||||||
int numWeights;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct EmbeddedAnimationBuffer {
|
|
||||||
|
|
||||||
EmbeddedAnimationBuffer(int animationIndex, float duration) : animationIndex(animationIndex), duration(duration) {}
|
|
||||||
bool hasStarted = false;
|
|
||||||
int animationIndex;
|
|
||||||
float duration = 0;
|
|
||||||
time_point_t lastTime;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
using LoadResource = std::function<ResourceBuffer(const char* uri)>;
|
using LoadResource = std::function<ResourceBuffer(const char* uri)>;
|
||||||
using FreeResource = std::function<void * (void *mem, size_t s, void *)>;
|
using FreeResource = std::function<void (ResourceBuffer)>;
|
||||||
|
|
||||||
class FilamentViewer {
|
class FilamentViewer {
|
||||||
public:
|
public:
|
||||||
@@ -98,31 +78,29 @@ namespace polyvox {
|
|||||||
~FilamentViewer();
|
~FilamentViewer();
|
||||||
void loadGlb(const char* const uri);
|
void loadGlb(const char* const uri);
|
||||||
void loadGltf(const char* const uri, const char* relativeResourcePath);
|
void loadGltf(const char* const uri, const char* relativeResourcePath);
|
||||||
void loadSkybox(const char* const skyboxUri, const char* const iblUri);
|
void loadSkybox(const char* const skyboxUri, const char* const iblUri, AAssetManager* am);
|
||||||
|
|
||||||
void updateViewportAndCameraProjection(int height, int width, float scaleFactor);
|
void updateViewportAndCameraProjection(int height, int width, float scaleFactor);
|
||||||
void render();
|
void render();
|
||||||
void createMorpher(const char* meshName, int* primitives, int numPrimitives);
|
// void createMorpher(const char* meshName, int* primitives, int numPrimitives);
|
||||||
void releaseSourceAssets();
|
void releaseSourceAssets();
|
||||||
StringList getTargetNames(const char* meshName);
|
StringList getTargetNames(const char* meshName);
|
||||||
Manipulator<float>* manipulator;
|
Manipulator<float>* manipulator;
|
||||||
void applyWeights(float* weights, int count);
|
void applyWeights(float* weights, int count);
|
||||||
void animateWeights(float* data, int numWeights, int length, float frameRate);
|
// void animateWeights(float* data, int numWeights, int length, float frameRate);
|
||||||
void animateBones();
|
// void animateBones();
|
||||||
void playAnimation(int index);
|
void playAnimation(int index);
|
||||||
|
void setCamera(const char* nodeName);
|
||||||
|
void destroySwapChain();
|
||||||
|
void createSwapChain(void* surface);
|
||||||
|
|
||||||
|
Renderer* getRenderer();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void loadResources(std::string relativeResourcePath);
|
void loadResources(std::string relativeResourcePath);
|
||||||
void transformToUnitCube();
|
void transformToUnitCube();
|
||||||
void cleanup();
|
void cleanup();
|
||||||
void updateMorphAnimation();
|
|
||||||
void updateEmbeddedAnimation();
|
|
||||||
void setCamera(const char* cameraName);
|
|
||||||
|
|
||||||
// animation flags;
|
|
||||||
bool isAnimating;
|
|
||||||
unique_ptr<MorphAnimationBuffer> morphAnimationBuffer;
|
|
||||||
unique_ptr<EmbeddedAnimationBuffer> embeddedAnimationBuffer;
|
|
||||||
|
|
||||||
void* _layer;
|
void* _layer;
|
||||||
|
|
||||||
@@ -138,12 +116,13 @@ namespace polyvox {
|
|||||||
Camera* _mainCamera;
|
Camera* _mainCamera;
|
||||||
Renderer* _renderer;
|
Renderer* _renderer;
|
||||||
|
|
||||||
SwapChain* _swapChain;
|
SwapChain* _swapChain = nullptr;
|
||||||
|
|
||||||
Animator* _animator;
|
Animator* _animator;
|
||||||
|
|
||||||
AssetLoader* _assetLoader;
|
AssetLoader* _assetLoader;
|
||||||
FilamentAsset* _asset = nullptr;
|
FilamentAsset* _asset = nullptr;
|
||||||
|
ResourceBuffer _assetBuffer;
|
||||||
NameComponentManager* _ncm;
|
NameComponentManager* _ncm;
|
||||||
|
|
||||||
Entity _sun;
|
Entity _sun;
|
||||||
@@ -161,9 +140,41 @@ namespace polyvox {
|
|||||||
|
|
||||||
float _cameraFocalLength = 0.0f;
|
float _cameraFocalLength = 0.0f;
|
||||||
|
|
||||||
GPUMorphHelper* morphHelper;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// void updateMorphAnimation();
|
||||||
|
// void updateEmbeddedAnimation();
|
||||||
|
|
||||||
|
// animation flags;
|
||||||
|
// bool isAnimating;
|
||||||
|
// unique_ptr<MorphAnimationBuffer> morphAnimationBuffer;
|
||||||
|
// unique_ptr<EmbeddedAnimationBuffer> embeddedAnimationBuffer;
|
||||||
|
|
||||||
|
// struct EmbeddedAnimationBuffer {
|
||||||
|
|
||||||
|
// EmbeddedAnimationBuffer(int animationIndex, float duration) : animationIndex(animationIndex), duration(duration) {}
|
||||||
|
// bool hasStarted = false;
|
||||||
|
// int animationIndex;
|
||||||
|
// float duration = 0;
|
||||||
|
// time_point_t lastTime;
|
||||||
|
// };
|
||||||
|
|
||||||
|
// struct MorphAnimationBuffer {
|
||||||
|
|
||||||
|
// MorphAnimationBuffer(float* frameData,
|
||||||
|
// int numWeights,
|
||||||
|
// int numFrames,
|
||||||
|
// float frameLength) : frameData(frameData), numWeights(numWeights), numFrames(numFrames), frameLength(frameLength) {
|
||||||
|
// }
|
||||||
|
|
||||||
|
// int frameIndex = -1;
|
||||||
|
// int numFrames;
|
||||||
|
// float frameLength;
|
||||||
|
// time_point_t startTime;
|
||||||
|
|
||||||
|
// float* frameData;
|
||||||
|
// int numWeights;
|
||||||
|
// };
|
||||||
@@ -4,7 +4,6 @@ import 'package:flutter/services.dart';
|
|||||||
|
|
||||||
abstract class FilamentController {
|
abstract class FilamentController {
|
||||||
void onFilamentViewCreated(int id);
|
void onFilamentViewCreated(int id);
|
||||||
|
|
||||||
Future loadSkybox(String skyboxPath, String lightingPath);
|
Future loadSkybox(String skyboxPath, String lightingPath);
|
||||||
Future loadGlb(String path);
|
Future loadGlb(String path);
|
||||||
Future loadGltf(String path, String relativeResourcePath);
|
Future loadGltf(String path, String relativeResourcePath);
|
||||||
@@ -43,23 +42,15 @@ class PolyvoxFilamentController extends FilamentController {
|
|||||||
_id = id;
|
_id = id;
|
||||||
_channel = MethodChannel("app.polyvox.filament/filament_view_$id");
|
_channel = MethodChannel("app.polyvox.filament/filament_view_$id");
|
||||||
_channel.setMethodCallHandler((call) async {
|
_channel.setMethodCallHandler((call) async {
|
||||||
await Future.delayed(const Duration(
|
if(call.method == "ready") {
|
||||||
seconds:
|
onFilamentViewCreatedHandler?.call(_id);
|
||||||
1)); // todo - need a better way to know when the GL context is actually ready
|
return Future.value(true);
|
||||||
await _initialize();
|
} else {
|
||||||
onFilamentViewCreatedHandler?.call(_id);
|
throw Exception("Unknown method channel invocation ${call.method}");
|
||||||
return Future.value(true);
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Future _initialize() async {
|
|
||||||
await _channel.invokeMethod("initialize", [
|
|
||||||
"packages/polyvox_filament/assets/lit_opaque.filamat",
|
|
||||||
"packages/polyvox_filament/assets/lit_fade.filamat"
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future loadSkybox(String skyboxPath, String lightingPath) async {
|
Future loadSkybox(String skyboxPath, String lightingPath) async {
|
||||||
await _channel.invokeMethod("loadSkybox", [skyboxPath, lightingPath]);
|
await _channel.invokeMethod("loadSkybox", [skyboxPath, lightingPath]);
|
||||||
|
|||||||
@@ -1,17 +0,0 @@
|
|||||||
// You have generated a new plugin project without
|
|
||||||
// specifying the `--platforms` flag. A plugin project supports no platforms is generated.
|
|
||||||
// To add platforms, run `flutter create -t plugin --platforms <platforms> .` under the same
|
|
||||||
// directory. You can also find a detailed instruction on how to add platforms in the `pubspec.yaml` at https://flutter.dev/docs/development/packages-and-plugins/developing-packages#plugin-platforms.
|
|
||||||
|
|
||||||
import 'dart:async';
|
|
||||||
|
|
||||||
import 'package:flutter/services.dart';
|
|
||||||
|
|
||||||
class PolyvoxFilament {
|
|
||||||
static const MethodChannel _channel = MethodChannel('polyvox_filament');
|
|
||||||
|
|
||||||
static Future<String?> get platformVersion async {
|
|
||||||
final String? version = await _channel.invokeMethod('getPlatformVersion');
|
|
||||||
return version;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -17,32 +17,14 @@ class FilamentView extends FilamentViewPlatform {
|
|||||||
) {
|
) {
|
||||||
switch (defaultTargetPlatform) {
|
switch (defaultTargetPlatform) {
|
||||||
case TargetPlatform.android:
|
case TargetPlatform.android:
|
||||||
return PlatformViewLink(
|
return AndroidView(
|
||||||
viewType: FILAMENT_VIEW_ID,
|
viewType: FILAMENT_VIEW_ID,
|
||||||
surfaceFactory:
|
gestureRecognizers: <Factory<OneSequenceGestureRecognizer>>{},
|
||||||
(BuildContext context, PlatformViewController controller) {
|
hitTestBehavior: PlatformViewHitTestBehavior.opaque,
|
||||||
return AndroidViewSurface(
|
onPlatformViewCreated: (id) {
|
||||||
controller: controller as AndroidViewController,
|
print("onplatformview created $id");
|
||||||
gestureRecognizers: const <
|
onFilamentViewCreated(id);
|
||||||
Factory<OneSequenceGestureRecognizer>>{},
|
});
|
||||||
hitTestBehavior: PlatformViewHitTestBehavior.opaque,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
onCreatePlatformView: (PlatformViewCreationParams params) {
|
|
||||||
return PlatformViewsService.initSurfaceAndroidView(
|
|
||||||
id: params.id,
|
|
||||||
viewType: FILAMENT_VIEW_ID,
|
|
||||||
layoutDirection: TextDirection.ltr,
|
|
||||||
creationParams: {},
|
|
||||||
creationParamsCodec: StandardMessageCodec(),
|
|
||||||
)
|
|
||||||
..addOnPlatformViewCreatedListener((int id) {
|
|
||||||
onFilamentViewCreated(id);
|
|
||||||
params.onPlatformViewCreated(id);
|
|
||||||
})
|
|
||||||
..create();
|
|
||||||
},
|
|
||||||
);
|
|
||||||
case TargetPlatform.iOS:
|
case TargetPlatform.iOS:
|
||||||
return UiKitView(
|
return UiKitView(
|
||||||
viewType: FILAMENT_VIEW_ID,
|
viewType: FILAMENT_VIEW_ID,
|
||||||
@@ -51,8 +33,7 @@ class FilamentView extends FilamentViewPlatform {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
case TargetPlatform.windows:
|
case TargetPlatform.windows:
|
||||||
return Text(
|
return Text("Flutter doesn't support platform view on Windows yet.");
|
||||||
"Flutter doesn't support platform view on Windows yet.");
|
|
||||||
default:
|
default:
|
||||||
return Text(
|
return Text(
|
||||||
'$defaultTargetPlatform is not yet implemented by Filament plugin.');
|
'$defaultTargetPlatform is not yet implemented by Filament plugin.');
|
||||||
|
|||||||
@@ -2,13 +2,13 @@ import 'package:flutter/widgets.dart';
|
|||||||
import 'package:polyvox_filament/view/filament_view.dart';
|
import 'package:polyvox_filament/view/filament_view.dart';
|
||||||
import 'package:plugin_platform_interface/plugin_platform_interface.dart';
|
import 'package:plugin_platform_interface/plugin_platform_interface.dart';
|
||||||
|
|
||||||
typedef void FilamentViewCreatedCallback(int id);
|
typedef FilamentViewCreatedCallback = void Function(int id);
|
||||||
|
|
||||||
abstract class FilamentViewPlatform extends PlatformInterface {
|
abstract class FilamentViewPlatform extends PlatformInterface {
|
||||||
FilamentViewPlatform() : super(token: _token);
|
FilamentViewPlatform() : super(token: _token);
|
||||||
|
|
||||||
static final Object _token = Object();
|
static final Object _token = Object();
|
||||||
static FilamentViewPlatform _instance = FilamentView();
|
static final FilamentViewPlatform _instance = FilamentView();
|
||||||
|
|
||||||
static FilamentViewPlatform get instance => _instance;
|
static FilamentViewPlatform get instance => _instance;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,8 @@
|
|||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:flutter/gestures.dart';
|
||||||
|
import 'package:flutter/rendering.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
|
import 'package:polyvox_filament/view/filament_view.dart';
|
||||||
|
|
||||||
import '../filament_controller.dart';
|
import '../filament_controller.dart';
|
||||||
import 'filament_view_platform.dart';
|
import 'filament_view_platform.dart';
|
||||||
|
|||||||
@@ -27,6 +27,9 @@ flutter:
|
|||||||
#- assets/lit_fade.filamat
|
#- assets/lit_fade.filamat
|
||||||
plugin:
|
plugin:
|
||||||
platforms:
|
platforms:
|
||||||
|
android:
|
||||||
|
pluginClass: PolyvoxFilamentPlugin
|
||||||
|
package: app.polyvox.filament
|
||||||
ios:
|
ios:
|
||||||
pluginClass: PolyvoxFilamentPlugin
|
pluginClass: PolyvoxFilamentPlugin
|
||||||
windows:
|
windows:
|
||||||
|
|||||||
Reference in New Issue
Block a user