rearrange source/header files for compatibility with CocoaPods Framework structure

This commit is contained in:
Nick Fisher
2022-10-04 09:23:53 +08:00
parent 204c75a603
commit dcd0a16bf9
41 changed files with 377 additions and 619 deletions

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 131 B

After

Width:  |  Height:  |  Size: 572 KiB

Binary file not shown.

View File

@@ -1 +0,0 @@
#import "PolyvoxFilamentApi.h"

View File

@@ -1,295 +0,0 @@
import Flutter
import UIKit
import OpenGLES.ES3
import GLKit
public class SwiftPolyvoxFilamentPlugin: NSObject, FlutterPlugin, FlutterTexture {
var registrar : FlutterPluginRegistrar
var textureId: Int64?
var registry: FlutterTextureRegistry
var width: Double = 0
var height: Double = 0
var context: EAGLContext?;
var targetPixelBuffer: CVPixelBuffer?;
var textureCache: CVOpenGLESTextureCache?;
var texture: CVOpenGLESTexture? = nil;
var frameBuffer: GLuint = 0;
var pixelBufferAttrs = [
kCVPixelBufferPixelFormatTypeKey: NSNumber(value: kCVPixelFormatType_32BGRA),
kCVPixelBufferOpenGLCompatibilityKey: kCFBooleanTrue,
kCVPixelBufferOpenGLESCompatibilityKey: kCFBooleanTrue,
kCVPixelBufferIOSurfacePropertiesKey: [:]
] as CFDictionary
var resources:NSMutableDictionary = [:]
var viewer:UnsafeMutableRawPointer? = nil
var displayLink:CADisplayLink? = nil
static var messenger : FlutterBinaryMessenger? = nil;
var loadResourcePtr: UnsafeMutableRawPointer? = nil
var freeResourcePtr: UnsafeMutableRawPointer? = nil
var resourcesPtr : UnsafeMutableRawPointer? = nil
var loadResource : @convention(c) (UnsafeRawPointer, UnsafeMutableRawPointer) -> ResourceBuffer = { uri, resourcesPtr in
print("Loading resource buffer")
let instance:SwiftPolyvoxFilamentPlugin = Unmanaged<SwiftPolyvoxFilamentPlugin>.fromOpaque(resourcesPtr).takeUnretainedValue()
let uriString = String(cString:uri.assumingMemoryBound(to: UInt8.self))
let key = instance.registrar.lookupKey(forAsset:uriString)
let path = Bundle.main.path(forResource: key, ofType:nil)
do {
let foo: String = path!
let data = try Data(contentsOf: URL(fileURLWithPath:foo))
let resId = instance.resources.count
let nsData = data as NSData
instance.resources[resId] = nsData
let rawPtr = nsData.bytes
return ResourceBuffer(data:rawPtr, size:UInt32(nsData.count), id:UInt32(resId))
} catch {
print("Error opening file: \(error)")
return ResourceBuffer()
}
return ResourceBuffer()
}
var freeResource : @convention(c) (UInt32,UnsafeMutableRawPointer) -> () = { rid, resourcesPtr in
let instance:SwiftPolyvoxFilamentPlugin = Unmanaged<SwiftPolyvoxFilamentPlugin>.fromOpaque(resourcesPtr).takeUnretainedValue()
instance.resources.removeObject(forKey:rid)
}
func createDisplayLink() {
displayLink = CADisplayLink(target: self,
selector: #selector(doRender))
displayLink!.add(to: .current, forMode: RunLoop.Mode.default)
}
@objc func doRender() {
if(viewer != nil) {
render(viewer)
self.registry.textureFrameAvailable(self.textureId!)
}
}
public func copyPixelBuffer() -> Unmanaged<CVPixelBuffer>? {
if(targetPixelBuffer == nil) {
print("empty")
return nil;
}
return Unmanaged.passRetained(targetPixelBuffer!);
}
public static func register(with registrar: FlutterPluginRegistrar) {
let _messenger = registrar.messenger();
messenger = _messenger;
let channel = FlutterMethodChannel(name: "app.polyvox.filament/event", binaryMessenger: _messenger)
let instance = SwiftPolyvoxFilamentPlugin(textureRegistry: registrar.textures(), registrar:registrar)
registrar.addMethodCallDelegate(instance, channel: channel)
}
init(textureRegistry: FlutterTextureRegistry, registrar:FlutterPluginRegistrar) {
self.registry = textureRegistry;
self.registrar = registrar
}
private func createPixelBuffer(width:Int, height:Int) {
if(targetPixelBuffer != nil) {
destroy_swap_chain(self.viewer)
}
if(CVPixelBufferCreate(kCFAllocatorDefault, Int(width), Int(height),
kCVPixelFormatType_32BGRA, pixelBufferAttrs, &targetPixelBuffer) != kCVReturnSuccess) {
print("Error allocating pixel buffer")
}
if(self.viewer != nil) {
create_swap_chain(self.viewer, unsafeBitCast(targetPixelBuffer!, to: UnsafeMutableRawPointer.self))
update_viewport_and_camera_projection(self.viewer!, Int32(width), Int32(height), 1.0);
}
print("Pixel buffer created")
}
private func initialize(width:Int32, height:Int32) {
createPixelBuffer(width:Int(width), height:Int(height))
self.textureId = self.registry.register(self)
loadResourcePtr = unsafeBitCast(loadResource, to: UnsafeMutableRawPointer.self)
freeResourcePtr = unsafeBitCast(freeResource, to: UnsafeMutableRawPointer.self)
viewer = filament_viewer_new_ios(
unsafeBitCast(targetPixelBuffer!, to: UnsafeMutableRawPointer.self),
loadResourcePtr!,
freeResourcePtr!,
Unmanaged.passUnretained(self).toOpaque()
)
update_viewport_and_camera_projection(self.viewer!, Int32(width), Int32(height), 1.0);
createDisplayLink()
}
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
let methodName = call.method;
switch methodName {
case "initialize":
let args = call.arguments as! Array<Int32>
initialize(width:args[0], height:args[1])
result(self.textureId);
case "setBackgroundImage":
let uri = call.arguments as! String
set_background_image(self.viewer!, uri)
render(self.viewer!)
self.registry.textureFrameAvailable(self.textureId!)
result("OK")
case "resize":
let args = call.arguments as! Array<Double>
let width = Int(args[0])
let height = Int(args[1])
createPixelBuffer(width: width, height:height)
result("OK")
case "loadSkybox":
load_skybox(self.viewer!, call.arguments as! String)
result("OK");
case "removeSkybox":
remove_skybox(self.viewer!)
result("OK");
case "loadGlb":
let assetPtr = load_glb(self.viewer, call.arguments as! String)
result(unsafeBitCast(assetPtr, to:Int64.self));
case "loadGltf":
let args = call.arguments as! Array<Any?>
result(load_gltf(self.viewer, args[0] as! String, args[1] as! String));
case "removeAsset":
let assetPtr = UnsafeMutableRawPointer.init(bitPattern: call.arguments as! Int)
remove_asset(viewer!, assetPtr)
result("OK")
case "clearAssets":
clear_assets(viewer!)
result("OK")
case "loadIbl":
load_ibl(self.viewer, call.arguments as! String)
result("OK");
case "removeIbl":
remove_ibl(self.viewer)
result("OK");
case "setCamera":
let args = call.arguments as! Array<Any?>
let assetPtr = UnsafeMutableRawPointer.init(bitPattern: args[0] as! Int)
set_camera(self.viewer, assetPtr, args[1] as! String)
result("OK");
case "playAnimation":
let args = call.arguments as! Array<Any?>
let assetPtr = UnsafeMutableRawPointer.init(bitPattern: args[0] as! Int)
let animationIndex = args[1] as! Int32;
let loop = args[2] as! Bool;
play_animation(assetPtr, animationIndex, loop)
result("OK");
case "stopAnimation":
let args = call.arguments as! Array<Any?>
let assetPtr = UnsafeMutableRawPointer.init(bitPattern: args[0] as! Int)
let animationIndex = args[1] as! Int32
stop_animation(assetPtr, animationIndex) // TODO
result("OK");
case "getTargetNames":
let args = call.arguments as! Array<Any?>
let assetPtr = UnsafeMutableRawPointer.init(bitPattern: args[0] as! Int)
let meshName = args[1] as! String
let numNames = get_target_name_count(assetPtr, meshName)
var names = [String]()
for i in 0...numNames - 1{
let outPtr = UnsafeMutablePointer<CChar>.allocate(capacity:256)
get_target_name(assetPtr, meshName, outPtr, i)
names.append(String(cString:outPtr))
}
result(names);
case "getAnimationNames":
let assetPtr = UnsafeMutableRawPointer.init(bitPattern: call.arguments as! Int)
let numNames = get_animation_count(assetPtr)
var names = [String]()
for i in 0...numNames - 1{
let outPtr = UnsafeMutablePointer<CChar>.allocate(capacity:256)
get_animation_name(assetPtr, outPtr, i)
names.append(String(cString:outPtr))
}
result(names);
case "applyWeights":
let args = call.arguments as! Array<Any?>
let assetPtr = UnsafeMutableRawPointer.init(bitPattern: args[0] as! Int)
let weights = args[1] as! Array<Double>
weights.map { Float($0) }.withUnsafeBufferPointer {
apply_weights(assetPtr, UnsafeMutablePointer<Float>.init(mutating:$0.baseAddress), Int32(weights.count))
}
result("OK")
case "zoom":
let args = call.arguments as! Array<Any?>
let assetPtr = UnsafeMutableRawPointer.init(bitPattern: args[0] as! Int)
let factor = args[1] as! Double
scroll(assetPtr, 0,0, Float(factor))
result("OK")
case "animateWeights":
let args = call.arguments as! Array<Any?>
let assetPtr = UnsafeMutableRawPointer.init(bitPattern: args[0] as! Int)
let frameData = args[1] as! Array<Double>
let numWeights = args[2] as! Int
let numFrames = args[3] as! Int
let frameLenInMs = args[4] as! Double
frameData.map { Float($0)}.withUnsafeBufferPointer {
animate_weights(assetPtr, UnsafeMutablePointer<Float>.init(mutating:$0.baseAddress), Int32(numWeights), Int32(numFrames), Float(frameLenInMs))
}
result("OK")
case "panStart":
let args = call.arguments as! Array<Any>
grab_begin(self.viewer, args[0] as! Int32, args[1] as! Int32, true)
result("OK")
case "panUpdate":
let args = call.arguments as! Array<Any>
grab_update(self.viewer, args[0] as! Int32, args[1] as! Int32)
result("OK")
case "panEnd":
grab_end(self.viewer)
result("OK")
case "rotateStart":
let args = call.arguments as! Array<Any>
grab_begin(self.viewer, args[0] as! Int32, args[1] as! Int32, false)
result("OK")
case "rotateUpdate":
let args = call.arguments as! Array<Any>
grab_update(self.viewer, args[0] as! Int32, args[1] as! Int32)
result("OK")
case "rotateEnd":
grab_end(self.viewer)
result("OK")
case "setPosition":
let args = call.arguments as! Array<Any>
let assetPtr = UnsafeMutableRawPointer.init(bitPattern: args[0] as! Int)
let x = Float(args[1] as! Double)
set_position(assetPtr, x, Float(args[2] as! Double), Float(args[3] as! Double))
result("OK")
case "setRotation":
let args = call.arguments as! Array<Any>
let assetPtr = UnsafeMutableRawPointer.init(bitPattern: args[0] as! Int)
set_rotation(assetPtr, Float(args[1] as! Double), Float(args[2] as! Double), Float(args[3] as! Double), Float(args[4] as! Double))
result("OK")
default:
result(FlutterMethodNotImplemented)
}
}
}

View File

@@ -2,7 +2,6 @@
#define _POLYVOX_FILAMENT_API_H
#include "ResourceBuffer.hpp"
#include "LightManager.hpp"
typedef struct ResourceBuffer ResourceBuffer;
@@ -31,11 +30,10 @@ void scroll_begin(void* viewer);
void scroll_update(void* viewer, float x, float y , float z);
void scroll_end(void* viewer);
void grab_begin(void* viewer, int x, int y, bool pan);
void grab_update(void* viewer, int x, int y);
void grab_begin(void* viewer, float x, float y, bool pan);
void grab_update(void* viewer, float x, float y);
void grab_end(void* viewer);
void apply_weights(void* asset, float* const weights, int count);
void animate_weights(void* asset, float* data, int numWeights, int numFrames, float frameRate);
@@ -61,11 +59,10 @@ void set_texture(void* asset);
void transform_to_unit_cube(void* asset);
void set_position(void* asset, float x, float y, float z);
void set_rotation(void* asset, float rads, float x, float y, float z);
void set_scale(void* asset, float scale);
void set_camera_position(void* viewer, float x, float y, float z);
void set_camera_rotation(void* viewer, float rads, float x, float y, float z);
void set_camera_focal_length(void* viewer, float focalLength);
void set_camera_focus_distance(void* viewer, float focusDistance);

View File

@@ -1,3 +1,3 @@
void* filament_viewer_new_ios(void* texture, void* loadResource, void* freeResource, void* resources);
void create_swap_chain(void* viewer, void* texture);

View File

@@ -2,6 +2,7 @@
#include <functional>
#include <memory>
#include <chrono>
#include "ResourceBuffer.hpp"

View File

@@ -0,0 +1,10 @@
#ifndef SwiftPolyvoxFilamentPlugin_Bridging_Header_h
#define SwiftPolyvoxFilamentPlugin_Bridging_Header_h
void* filament_viewer_new_ios(void* texture, void* loadResource, void* freeResource, void* resources);
#import "PolyvoxFilamentIOSApi.h"
#import "PolyvoxFilamentApi.h"
#endif

View File

@@ -13,39 +13,36 @@ A new flutter plugin project.
s.license = { :file => '../LICENSE' }
s.author = { 'Your Company' => 'email@example.com' }
s.source = { :path => '.' }
s.source_files = 'Classes/**/*', 'src/ResourceBuffer.hpp', 'src/FilamentViewer.cpp', 'src/SceneAsset.cpp', 'src/SceneAssetLoader.cpp', 'src/StreamBufferAdapter.cpp', 'src/image/imagematerial.c', 'src/image/imagematerials_ios.c'
#s.header_dir = "include"
#s.header_mappings_dir = "include"
s.source_files = 'src/*', 'src/ios/*', 'src/shaders/*.c', 'src/shaders/*.h', 'include/filament/*', 'include/*', 'include/material/*.h', 'include/material/*.c'
s.public_header_files = 'include/SwiftPolyvoxFilamentPlugin-Bridging-Header.h', 'include/PolyvoxFilamentIOSApi.h', 'include/PolyvoxFilamentApi.h', 'include/ResourceBuffer.hpp' #, 'include/filament/*'
# s.header_mappings_dir = 'include'
s.dependency 'Flutter'
s.platform = :ios, '12.1'
s.static_framework = true
s.vendored_libraries = "lib/*.a"
s.library = "c++"
s.user_target_xcconfig = {
'DEFINES_MODULE' => 'YES',
'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386',
"CLANG_CXX_LANGUAGE_STANDARD" => "c++17",
'OTHER_CXXFLAGS' => '"--std=c++17" "-fmodules" "-fcxx-modules" "$(inherited)"',
'USER_HEADER_SEARCH_PATHS' => '"${PODS_ROOT}/../.symlinks/plugins/polyvox_filament/ios/include" "${PODS_ROOT}/../.symlinks/plugins/polyvox_filament/ios/src" "${PODS_ROOT}/../.symlinks/plugins/polyvox_filament/ios/src/image "$(inherited)"',
'USER_HEADER_SEARCH_PATHS' => '"${PODS_ROOT}/../.symlinks/plugins/polyvox_filament/ios/include" "${PODS_ROOT}/../.symlinks/plugins/polyvox_filament/ios/src" "${PODS_ROOT}/../.symlinks/plugins/polyvox_filament/ios/src/image" "${PODS_ROOT}/../.symlinks/plugins/polyvox_filament/ios/src/shaders" "$(inherited)"',
'ALWAYS_SEARCH_USER_PATHS' => 'YES',
"OTHER_LDFLAGS" => '-lfilament -lbackend -lfilameshio -lviewer -lfilamat -lgeometry -lutils -lfilabridge -lgltfio_core -lfilament-iblprefilter -limage -lcamutils -lgltfio_core -lfilaflat -ldracodec -libl -lktxreader -limageio -lpng -lpng16 -ltinyexr -lz -lstb -luberzlib -lsmol-v -luberarchive -lzstd',
'LIBRARY_SEARCH_PATHS' => '"${PODS_ROOT}/../.symlinks/plugins/polyvox_filament/ios/lib" "$(inherited)"',
}
# Flutter.framework does not contain a i386 slice.
s.pod_target_xcconfig = {
'DEFINES_MODULE' => 'YES',
'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386',
"CLANG_CXX_LANGUAGE_STANDARD" => "c++17",
'OTHER_CXXFLAGS' => '"--std=c++17" "-fmodules" "-fcxx-modules" "$(inherited)"',
'USER_HEADER_SEARCH_PATHS' => '"${PODS_ROOT}/../.symlinks/plugins/polyvox_filament/ios/include" "${PODS_ROOT}/../.symlinks/plugins/polyvox_filament/ios/src" "${PODS_ROOT}/../.symlinks/plugins/polyvox_filament/ios/src/image "$(inherited)"',
'USER_HEADER_SEARCH_PATHS' => '"${PODS_ROOT}/../.symlinks/plugins/polyvox_filament/ios/include" "${PODS_ROOT}/../.symlinks/plugins/polyvox_filament/ios/src" "${PODS_ROOT}/../.symlinks/plugins/polyvox_filament/ios/src/image" "${PODS_ROOT}/../.symlinks/plugins/polyvox_filament/ios/src/shaders" "$(inherited)"',
'ALWAYS_SEARCH_USER_PATHS' => 'YES',
"OTHER_LDFLAGS" => '-lfilament -lbackend -lfilameshio -lviewer -lfilamat -lgeometry -lutils -lfilabridge -lgltfio_core -lfilament-iblprefilter -limage -lcamutils -lgltfio_core -lfilaflat -ldracodec -libl -lktxreader -limageio -lpng -lpng16 -ltinyexr -lz -lstb -luberzlib -lsmol-v -luberarchive -lzstd',
'LIBRARY_SEARCH_PATHS' => '"${PODS_ROOT}/../.symlinks/plugins/polyvox_filament/ios/lib" "$(inherited)"',
}
s.swift_version = '5.0'
end

View File

@@ -69,7 +69,8 @@
#include "Log.hpp"
#include "SceneResources.hpp"
#if TARGET_OS_IPHONE
#include "image/imagematerials_ios.h"
#include "material/imagematerials_ios.h"
#include "material/unlitopaque.h"
#else
#include "image/imagematerial.h"
#include "shaders/unlitopaque.h"
@@ -98,7 +99,7 @@ namespace polyvox {
public:
UnlitMaterialProvider(Engine* engine) {
_m = Material::Builder()
.package(UNLITOPAQUE_UNLIT_OPAQUE_DATA, UNLITOPAQUE_UNLIT_OPAQUE_SIZE)
.package( UNLITOPAQUE_UNLIT_OPAQUE_DATA, UNLITOPAQUE_UNLIT_OPAQUE_SIZE)
.build(*engine);
_ms[0] = _m;
}

View File

@@ -1,91 +0,0 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <jni.h>
#include <filament/Engine.h>
#include <filament/Texture.h>
#include <imageio/HDRDecoder.h>
#include <utils/Log.h>
#include <sstream>
#include "common/NioUtils.h"
using namespace filament;
using namespace image;
using namespace utils;
using PixelBufferDescriptor = Texture::PixelBufferDescriptor;
jlong nCreateHDRTexture(JNIEnv* env, jclass,
jlong nativeEngine, jobject javaBuffer, jint remaining, jint internalFormat) {
slog.e << "Creating HDR texture." << io::endl;
Engine* engine = (Engine*) nativeEngine;
AutoBuffer buffer(env, javaBuffer, remaining);
Texture::InternalFormat textureFormat = (Texture::InternalFormat) internalFormat;
auto dataPtr = (char const*) buffer.getData();
const size_t byteCount = buffer.getSize();
// This creates a copy but it's the easest way to create a memory stream.
std::string ins(dataPtr, byteCount);
std::istringstream in(ins);
LinearImage* image = new LinearImage(ImageDecoder::decode(in, "memory.hdr"));
// This can happen if a decoding error occurs.
if (image->getChannels() != 3) {
delete image;
return 0;
}
Texture* texture = Texture::Builder()
.width(image->getWidth())
.height(image->getHeight())
.levels(0xff)
.sampler(Texture::Sampler::SAMPLER_2D)
.format(textureFormat)
.build(*engine);
if (texture == nullptr) {
slog.e << "Unable to create Filament Texture from HDR image." << io::endl;
delete image;
return 0;
}
PixelBufferDescriptor::Callback freeCallback = [](void* buf, size_t, void* userdata) {
delete (LinearImage*) userdata;
};
PixelBufferDescriptor pbd(
(void const* ) image->getPixelRef(),
image->getWidth() * image->getHeight() * 3 * sizeof(float),
PixelBufferDescriptor::PixelDataFormat::RGB,
PixelBufferDescriptor::PixelDataType::FLOAT,
freeCallback,
image);
// Note that the setImage call could fail (e.g. due to an invalid combination of internal format
// and PixelDataFormat) but there is no way of detecting such a failure.
texture->setImage(*engine, 0, std::move(pbd));
texture->generateMipmaps(*engine);
return (jlong) texture;
}

View File

@@ -1,160 +0,0 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <jni.h>
#include <filament/Engine.h>
#include <filament/IndirectLight.h>
#include <filament/Skybox.h>
#include <image/KtxUtility.h>
#include <android/asset_manager.h>
#include <android/asset_manager_jni.h>
#include "common/NioUtils.h"
#include <android/log.h>
using namespace filament;
using namespace filament::math;
using namespace image;
jlong nCreateHDRTexture(JNIEnv* env, jclass,
jlong nativeEngine, jobject javaBuffer, jint remaining, jint internalFormat);
static jlong nCreateKTXTexture(JNIEnv* env, jclass,
jlong nativeEngine, jobject javaBuffer, jint remaining, jboolean srgb) {
Engine* engine = (Engine*) nativeEngine;
AutoBuffer buffer(env, javaBuffer, remaining);
KtxBundle* bundle = new KtxBundle((const uint8_t*) buffer.getData(), buffer.getSize());
return (jlong) ktx::createTexture(engine, *bundle, srgb, [](void* userdata) {
KtxBundle* bundle = (KtxBundle*) userdata;
delete bundle;
}, bundle);
}
static jlong nCreateIndirectLight(JNIEnv* env, jclass,
jlong nativeEngine, jobject javaBuffer, jint remaining, jboolean srgb) {
Engine* engine = (Engine*) nativeEngine;
AutoBuffer buffer(env, javaBuffer, remaining);
KtxBundle* bundle = new KtxBundle((const uint8_t*) buffer.getData(), buffer.getSize());
Texture* cubemap = ktx::createTexture(engine, *bundle, srgb, [](void* userdata) {
KtxBundle* bundle = (KtxBundle*) userdata;
delete bundle;
}, bundle);
float3 harmonics[9];
bundle->getSphericalHarmonics(harmonics);
IndirectLight* indirectLight = IndirectLight::Builder()
.reflections(cubemap)
.irradiance(3, harmonics)
.intensity(30000)
.build(*engine);
return (jlong) indirectLight;
}
static jlong nCreateSkybox(JNIEnv* env, jclass,
jlong nativeEngine, jobject javaBuffer, jint remaining, jboolean srgb, jobject assetManager, jstring outpath) {
AAssetManager *mgr = AAssetManager_fromJava(env, assetManager);
AAsset *asset = AAssetManager_open(mgr, "envs/default_env/default_env_skybox.ktx", AASSET_MODE_BUFFER);
if(asset == nullptr) {
__android_log_print(ANDROID_LOG_VERBOSE, "filament_api", "Couldn't open asset");
return 0;
}
off_t length = AAsset_getLength(asset);
const void * buffer = AAsset_getBuffer(asset);
jboolean isCopy = (jboolean)false;
const char* out_cstr = env->GetStringUTFChars(outpath, &isCopy);
__android_log_print(ANDROID_LOG_VERBOSE, "filament_api", "Opening outfile %s for writing", out_cstr);
FILE* outfile = fopen(out_cstr, "w");
fwrite(buffer, 1, length, outfile);
fclose(outfile);
__android_log_print(ANDROID_LOG_VERBOSE, "filament_api", "Closed outfile %s", out_cstr);
Engine* engine = (Engine*) nativeEngine;
// __android_log_print(ANDROID_LOG_VERBOSE, "UTILS", "CREATing autobuffer");
// AutoBuffer buffer(env, javaBuffer, remaining);
// __android_log_print(ANDROID_LOG_VERBOSE, "UTILS", "CREATied autobuffer");
KtxBundle* bundle = new KtxBundle((const uint8_t*) buffer, length);
// KtxBundle* bundle = new KtxBundle((const uint8_t*) buffer.getData(), buffer.getSize());
__android_log_print(ANDROID_LOG_VERBOSE, "UTILS", "CREATED BUNDLE FROM API");
Texture* cubemap = ktx::createTexture(engine, *bundle, srgb, [](void* userdata) {
KtxBundle* bundle = (KtxBundle*) userdata;
delete bundle;
}, bundle);
__android_log_print(ANDROID_LOG_VERBOSE, "UTILS", "CREATED TEXTURE");
return (jlong) Skybox::Builder().environment(cubemap).showSun(true).build(*engine);
}
static jboolean nGetSphericalHarmonics(JNIEnv* env, jclass, jobject javaBuffer, jint remaining,
jfloatArray outSphericalHarmonics_) {
AutoBuffer buffer(env, javaBuffer, remaining);
KtxBundle bundle((const uint8_t*) buffer.getData(), buffer.getSize());
jfloat* outSphericalHarmonics = env->GetFloatArrayElements(outSphericalHarmonics_, nullptr);
const auto success = bundle.getSphericalHarmonics(
reinterpret_cast<filament::math::float3*>(outSphericalHarmonics)
);
env->ReleaseFloatArrayElements(outSphericalHarmonics_, outSphericalHarmonics, JNI_ABORT);
return success ? JNI_TRUE : JNI_FALSE;
}
JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void*) {
JNIEnv* env;
if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
return -1;
}
int rc;
// KTXLoader
jclass ktxloaderClass = env->FindClass("app/polyvox/filament/KTXLoader2");
if (ktxloaderClass == nullptr) return JNI_ERR;
static const JNINativeMethod ktxMethods[] = {
{(char*)"nCreateKTXTexture", (char*)"(JLjava/nio/Buffer;IZ)J", reinterpret_cast<void*>(nCreateKTXTexture)},
{(char*)"nCreateIndirectLight", (char*)"(JLjava/nio/Buffer;IZ)J", reinterpret_cast<void*>(nCreateIndirectLight)},
{(char*)"nCreateSkybox", (char*)"(JLjava/nio/Buffer;IZLandroid/content/res/AssetManager;Ljava/lang/String;)J", reinterpret_cast<void*>(nCreateSkybox)},
{(char*)"nGetSphericalHarmonics", (char*)"(Ljava/nio/Buffer;I[F)Z", reinterpret_cast<void*>(nGetSphericalHarmonics)},
};
rc = env->RegisterNatives(ktxloaderClass, ktxMethods, sizeof(ktxMethods) / sizeof(JNINativeMethod));
if (rc != JNI_OK) return rc;
// HDRLoader
jclass hdrloaderClass = env->FindClass("com/google/android/filament/utils/HDRLoader");
if (hdrloaderClass == nullptr) return JNI_ERR;
static const JNINativeMethod hdrMethods[] = {
{(char*)"nCreateHDRTexture", (char*)"(JLjava/nio/Buffer;II)J", reinterpret_cast<void*>(nCreateHDRTexture)},
};
rc = env->RegisterNatives(hdrloaderClass, hdrMethods, sizeof(hdrMethods) / sizeof(JNINativeMethod));
if (rc != JNI_OK) return rc;
return JNI_VERSION_1_6;
}

View File

@@ -1,54 +0,0 @@
material {
name : Image,
parameters : [
{
type : sampler2d,
name : image
},
{
type : mat4,
name : transform,
precision : high
},
{
type : float3,
name : backgroundColor
},
{
type : int,
name : showImage
}
],
variables : [
imageUV
],
vertexDomain : device,
depthWrite : false,
shadingModel : unlit,
variantFilter : [ skinning, shadowReceiver, vsm ],
culling: none
}
vertex {
void materialVertex(inout MaterialVertexInputs material) {
material.imageUV.st = getPosition().st * 0.5 + 0.5;
}
}
fragment {
void material(inout MaterialInputs material) {
prepareMaterial(material);
vec4 bg = vec4(materialParams.backgroundColor, 1.0);
highp vec2 uv = (materialParams.transform * vec4(saturate(variable_imageUV.st), 1.0, 1.0)).st;
if (materialParams.showImage == 0 || uv.s > 1.0 || uv.s < 0.0 || uv.t < 0.0 || uv.t > 1.0) {
material.baseColor = bg;
} else {
uv.t = 1.0 - uv.t;
vec4 color = max(texture(materialParams_image, uv.st), 0.0);
color.rgb *= color.a;
// Manual, pre-multiplied srcOver with opaque destination optimization
material.baseColor.rgb = color.rgb + bg.rgb * (1.0 - color.a);
}
}
}

View File

@@ -0,0 +1,353 @@
import Flutter
import UIKit
import OpenGLES.ES3
import GLKit
public class SwiftPolyvoxFilamentPlugin: NSObject, FlutterPlugin, FlutterTexture {
var registrar : FlutterPluginRegistrar
var textureId: Int64?
var registry: FlutterTextureRegistry
var width: Double = 0
var height: Double = 0
var context: EAGLContext?;
var targetPixelBuffer: CVPixelBuffer?;
var textureCache: CVOpenGLESTextureCache?;
var texture: CVOpenGLESTexture? = nil;
var frameBuffer: GLuint = 0;
var pixelBufferAttrs = [
kCVPixelBufferPixelFormatTypeKey: NSNumber(value: kCVPixelFormatType_32BGRA),
kCVPixelBufferOpenGLCompatibilityKey: kCFBooleanTrue,
kCVPixelBufferOpenGLESCompatibilityKey: kCFBooleanTrue,
kCVPixelBufferIOSurfacePropertiesKey: [:]
] as CFDictionary
var resources:NSMutableDictionary = [:]
var viewer:UnsafeMutableRawPointer? = nil
var displayLink:CADisplayLink? = nil
static var messenger : FlutterBinaryMessenger? = nil;
var loadResourcePtr: UnsafeMutableRawPointer? = nil
var freeResourcePtr: UnsafeMutableRawPointer? = nil
var resourcesPtr : UnsafeMutableRawPointer? = nil
var _rendering = true
var loadResource : @convention(c) (UnsafeRawPointer, UnsafeMutableRawPointer) -> ResourceBuffer = { uri, resourcesPtr in
let instance:SwiftPolyvoxFilamentPlugin = Unmanaged<SwiftPolyvoxFilamentPlugin>.fromOpaque(resourcesPtr).takeUnretainedValue()
let uriString = String(cString:uri.assumingMemoryBound(to: UInt8.self))
let key = instance.registrar.lookupKey(forAsset:uriString)
let path = Bundle.main.path(forResource: key, ofType:nil)
do {
let foo: String = path!
let data = try Data(contentsOf: URL(fileURLWithPath:foo))
let resId = instance.resources.count
let nsData = data as NSData
instance.resources[resId] = nsData
let rawPtr = nsData.bytes
return ResourceBuffer(data:rawPtr, size:UInt32(nsData.count), id:UInt32(resId))
} catch {
print("Error opening file: \(error)")
return ResourceBuffer()
}
return ResourceBuffer()
}
var freeResource : @convention(c) (UInt32,UnsafeMutableRawPointer) -> () = { rid, resourcesPtr in
let instance:SwiftPolyvoxFilamentPlugin = Unmanaged<SwiftPolyvoxFilamentPlugin>.fromOpaque(resourcesPtr).takeUnretainedValue()
instance.resources.removeObject(forKey:rid)
}
func createDisplayLink() {
displayLink = CADisplayLink(target: self,
selector: #selector(doRender))
displayLink!.add(to: .current, forMode: RunLoop.Mode.default)
}
@objc func doRender() {
if(viewer != nil && _rendering) {
render(viewer, 0)
self.registry.textureFrameAvailable(self.textureId!)
}
}
public func copyPixelBuffer() -> Unmanaged<CVPixelBuffer>? {
if(targetPixelBuffer == nil) {
print("empty")
return nil;
}
return Unmanaged.passRetained(targetPixelBuffer!);
}
public static func register(with registrar: FlutterPluginRegistrar) {
let _messenger = registrar.messenger();
messenger = _messenger;
let channel = FlutterMethodChannel(name: "app.polyvox.filament/event", binaryMessenger: _messenger)
let instance = SwiftPolyvoxFilamentPlugin(textureRegistry: registrar.textures(), registrar:registrar)
registrar.addMethodCallDelegate(instance, channel: channel)
}
init(textureRegistry: FlutterTextureRegistry, registrar:FlutterPluginRegistrar) {
self.registry = textureRegistry;
self.registrar = registrar
}
private func createPixelBuffer(width:Int, height:Int) {
if(targetPixelBuffer != nil) {
destroy_swap_chain(self.viewer)
}
if(CVPixelBufferCreate(kCFAllocatorDefault, Int(width), Int(height),
kCVPixelFormatType_32BGRA, pixelBufferAttrs, &targetPixelBuffer) != kCVReturnSuccess) {
print("Error allocating pixel buffer")
}
if(self.viewer != nil) {
create_swap_chain(self.viewer, unsafeBitCast(targetPixelBuffer!, to: UnsafeMutableRawPointer.self))
update_viewport_and_camera_projection(self.viewer!, Int32(width), Int32(height), 1.0);
}
print("Pixel buffer created")
}
private func initialize(width:Int32, height:Int32) {
createPixelBuffer(width:Int(width), height:Int(height))
self.textureId = self.registry.register(self)
loadResourcePtr = unsafeBitCast(loadResource, to: UnsafeMutableRawPointer.self)
freeResourcePtr = unsafeBitCast(freeResource, to: UnsafeMutableRawPointer.self)
viewer = filament_viewer_new_ios(
unsafeBitCast(targetPixelBuffer!, to: UnsafeMutableRawPointer.self),
loadResourcePtr!,
freeResourcePtr!,
Unmanaged.passUnretained(self).toOpaque()
)
update_viewport_and_camera_projection(self.viewer!, Int32(width), Int32(height), 1.0);
createDisplayLink()
}
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
let methodName = call.method;
switch methodName {
case "initialize":
let args = call.arguments as! Array<Int32>
initialize(width:args[0], height:args[1])
result(self.textureId);
case "setBackgroundImage":
let uri = call.arguments as! String
set_background_image(self.viewer!, uri)
render(self.viewer!, 0)
self.registry.textureFrameAvailable(self.textureId!)
result("OK")
case "setBackgroundImagePosition":
let args = call.arguments as! Array<Any>
set_background_image_position(self.viewer, Float(args[0] as! Double), Float(args[1] as! Double), args[2] as! Bool)
result("OK");
case "resize":
let args = call.arguments as! Array<Double>
let width = Int(args[0])
let height = Int(args[1])
createPixelBuffer(width: width, height:height)
result("OK")
case "loadSkybox":
load_skybox(self.viewer!, call.arguments as! String)
result("OK");
case "removeSkybox":
remove_skybox(self.viewer!)
result("OK");
case "loadGlb":
let assetPtr = load_glb(self.viewer, call.arguments as! String)
result(unsafeBitCast(assetPtr, to:Int64.self));
case "loadGltf":
let args = call.arguments as! Array<Any?>
result(load_gltf(self.viewer, args[0] as! String, args[1] as! String));
case "removeAsset":
let assetPtr = UnsafeMutableRawPointer.init(bitPattern: call.arguments as! Int)
remove_asset(viewer!, assetPtr)
result("OK")
case "clearAssets":
clear_assets(viewer!)
result("OK")
case "loadIbl":
load_ibl(self.viewer, call.arguments as! String)
result("OK");
case "removeIbl":
remove_ibl(self.viewer)
result("OK");
case "setCamera":
let args = call.arguments as! Array<Any?>
let assetPtr = UnsafeMutableRawPointer.init(bitPattern: args[0] as! Int)
set_camera(self.viewer, assetPtr, args[1] as! String)
result("OK");
case "playAnimation":
let args = call.arguments as! Array<Any?>
let assetPtr = UnsafeMutableRawPointer.init(bitPattern: args[0] as! Int)
let animationIndex = args[1] as! Int32;
let loop = args[2] as! Bool;
let reverse = args[3] as! Bool;
play_animation(assetPtr, animationIndex, loop, reverse)
result("OK");
case "stopAnimation":
let args = call.arguments as! Array<Any?>
let assetPtr = UnsafeMutableRawPointer.init(bitPattern: args[0] as! Int)
let animationIndex = args[1] as! Int32
stop_animation(assetPtr, animationIndex) // TODO
result("OK");
case "getTargetNames":
let args = call.arguments as! Array<Any?>
let assetPtr = UnsafeMutableRawPointer.init(bitPattern: args[0] as! Int)
let meshName = args[1] as! String
let numNames = get_target_name_count(assetPtr, meshName)
var names = [String]()
for i in 0...numNames - 1{
let outPtr = UnsafeMutablePointer<CChar>.allocate(capacity:256)
get_target_name(assetPtr, meshName, outPtr, i)
names.append(String(cString:outPtr))
}
result(names);
case "getAnimationNames":
let assetPtr = UnsafeMutableRawPointer.init(bitPattern: call.arguments as! Int)
let numNames = get_animation_count(assetPtr)
var names = [String]()
for i in 0...numNames - 1{
let outPtr = UnsafeMutablePointer<CChar>.allocate(capacity:256)
get_animation_name(assetPtr, outPtr, i)
names.append(String(cString:outPtr))
}
result(names);
case "applyWeights":
let args = call.arguments as! Array<Any?>
let assetPtr = UnsafeMutableRawPointer.init(bitPattern: args[0] as! Int)
let weights = args[1] as! Array<Double>
weights.map { Float($0) }.withUnsafeBufferPointer {
apply_weights(assetPtr, UnsafeMutablePointer<Float>.init(mutating:$0.baseAddress), Int32(weights.count))
}
result("OK")
case "zoomBegin":
scroll_begin(self.viewer)
result("OK")
case "zoomUpdate":
let args = call.arguments as! Array<Any?>
scroll_update(self.viewer, Float(args[0] as! Double), Float(args[1] as! Double),Float(args[2] as! Double))
result("OK")
case "zoomEnd":
scroll_end(self.viewer)
result("OK")
case "animateWeights":
let args = call.arguments as! Array<Any?>
let assetPtr = UnsafeMutableRawPointer.init(bitPattern: args[0] as! Int)
let frameData = args[1] as! Array<Double>
let numWeights = args[2] as! Int
let numFrames = args[3] as! Int
let frameLenInMs = args[4] as! Double
frameData.map { Float($0)}.withUnsafeBufferPointer {
animate_weights(assetPtr, UnsafeMutablePointer<Float>.init(mutating:$0.baseAddress), Int32(numWeights), Int32(numFrames), Float(frameLenInMs))
}
result("OK")
case "panStart":
let args = call.arguments as! Array<Any>
grab_begin(self.viewer, Float(args[0] as! Double), Float(args[1] as! Double), true)
result("OK")
case "panUpdate":
let args = call.arguments as! Array<Any>
grab_update(self.viewer, Float(args[0] as! Double), Float(args[1] as! Double))
result("OK")
case "panEnd":
grab_end(self.viewer)
result("OK")
case "rotateStart":
let args = call.arguments as! Array<Any>
grab_begin(self.viewer, Float(args[0] as! Double), Float(args[1] as! Double), false)
result("OK")
case "rotateUpdate":
let args = call.arguments as! Array<Any>
grab_update(self.viewer, Float(args[0] as! Double), Float(args[1] as! Double))
result("OK")
case "rotateEnd":
grab_end(self.viewer)
result("OK")
case "setPosition":
let args = call.arguments as! Array<Any>
let assetPtr = UnsafeMutableRawPointer.init(bitPattern: args[0] as! Int)
let x = Float(args[1] as! Double)
set_position(assetPtr, x, Float(args[2] as! Double), Float(args[3] as! Double))
result("OK")
case "setRotation":
let args = call.arguments as! Array<Any>
let assetPtr = UnsafeMutableRawPointer.init(bitPattern: args[0] as! Int)
set_rotation(assetPtr, Float(args[1] as! Double), Float(args[2] as! Double), Float(args[3] as! Double), Float(args[4] as! Double))
result("OK")
case "setScale":
let args = call.arguments as! Array<Any>
let assetPtr = UnsafeMutableRawPointer.init(bitPattern: args[0] as! Int)
set_scale(assetPtr, Float(args[1] as! Double))
result("OK");
case "setCameraPosition":
let args = call.arguments as! Array<Any>
set_camera_position(self.viewer, Float(args[0] as! Double), Float(args[1] as! Double), Float(args[2] as! Double))
result("OK");
case "setCameraRotation":
let args = call.arguments as! Array<Any>
set_camera_rotation(self.viewer, Float(args[0] as! Double), Float(args[1] as! Double), Float(args[2] as! Double),Float(args[3] as! Double))
case "setCameraFocalLength":
set_camera_focal_length(self.viewer, Float(call.arguments as! Double))
result("OK");
case "setCameraFocusDistance":
// TODO
// set_camera_focus_distance(self.viewer, Float(call.arguments as! Double))
// result("OK");
break
case "setRendering":
_rendering = call.arguments as! Bool
result("OK")
case "render":
doRender()
result("OK")
case "addLight":
let args = call.arguments as! Array<Any>
let entity = add_light(
self.viewer,
args[0] as! UInt8,
Float(args[1] as! Double),
Float(args[2] as! Double),
Float(args[3] as! Double),
Float(args[4] as! Double),
Float(args[5] as! Double),
Float(args[6] as! Double),
Float(args[7] as! Double),
Float(args[8] as! Double),
args[9] as! Bool)
result(entity);
case "removeLight":
remove_light(self.viewer,call.arguments as! Int32)
result(true);
case "clearLights":
clear_lights(self.viewer);
result(true);
case "setTexture":
let args = call.arguments as! Array<Any>
let assetPtr = UnsafeMutableRawPointer.init(bitPattern: args[0] as! Int)
load_texture(assetPtr, args[1] as! String, args[2] as! Int32)
result("OK");
default:
result(FlutterMethodNotImplemented)
}
}
}