From c6e429bcba2f1cb121f642f1928099c56ba1f613 Mon Sep 17 00:00:00 2001 From: Nick Fisher Date: Fri, 19 Aug 2022 12:39:55 +0800 Subject: [PATCH] replace view with texture, move plugin to Swift implementation --- ios/Classes/FilamentMethodCallHandler.h | 20 -- ios/Classes/FilamentMethodCallHandler.mm | 170 ----------- ios/Classes/FilamentNativeViewFactory.h | 25 -- ios/Classes/FilamentNativeViewFactory.mm | 67 ----- ios/Classes/FilamentView.h | 32 -- ios/Classes/FilamentView.mm | 108 ------- ios/Classes/PolyvoxFilamentApi.cc | 147 +++++++++ ios/Classes/PolyvoxFilamentApi.h | 56 ++++ ios/Classes/PolyvoxFilamentIOSApi.cc | 32 ++ ios/Classes/PolyvoxFilamentIOSApi.h | 3 + ios/Classes/PolyvoxFilamentPlugin.m | 63 ++++ ios/Classes/PolyvoxFilamentPlugin.mm | 12 - ...iftPolyvoxFilamentPlugin-Bridging-Header.h | 1 + ios/Classes/SwiftPolyvoxFilamentPlugin.swift | 283 ++++++++++++++++++ ios/polyvox_filament.podspec | 27 +- ios/src/ResourceBuffer.hpp | 44 +++ ios/src/SceneAsset.cpp | 2 +- ios/src/SceneAssetLoader.cpp | 6 +- ios/src/SceneAssetLoader.hpp | 1 + ios/src/SceneResources.hpp | 50 +--- 20 files changed, 658 insertions(+), 491 deletions(-) delete mode 100644 ios/Classes/FilamentMethodCallHandler.h delete mode 100644 ios/Classes/FilamentMethodCallHandler.mm delete mode 100644 ios/Classes/FilamentNativeViewFactory.h delete mode 100644 ios/Classes/FilamentNativeViewFactory.mm delete mode 100644 ios/Classes/FilamentView.h delete mode 100644 ios/Classes/FilamentView.mm create mode 100644 ios/Classes/PolyvoxFilamentApi.cc create mode 100644 ios/Classes/PolyvoxFilamentApi.h create mode 100644 ios/Classes/PolyvoxFilamentIOSApi.cc create mode 100644 ios/Classes/PolyvoxFilamentIOSApi.h create mode 100644 ios/Classes/PolyvoxFilamentPlugin.m delete mode 100644 ios/Classes/PolyvoxFilamentPlugin.mm create mode 100644 ios/Classes/SwiftPolyvoxFilamentPlugin-Bridging-Header.h create mode 100644 ios/Classes/SwiftPolyvoxFilamentPlugin.swift create mode 100644 ios/src/ResourceBuffer.hpp diff --git a/ios/Classes/FilamentMethodCallHandler.h b/ios/Classes/FilamentMethodCallHandler.h deleted file mode 100644 index fb2f4cdb..00000000 --- a/ios/Classes/FilamentMethodCallHandler.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef FilamentMethodCallHandler_h -#define FilamentMethodCallHandler_h -#endif /* FilamentNativeViewFactory_h */ - -#import - -#include "FilamentViewer.hpp" - -using namespace polyvox; - -static const id VIEW_TYPE = @"app.polyvox.filament/filament_view"; - -@interface FilamentMethodCallHandler : FlutterMethodChannel -- (void)handleMethodCall:(FlutterMethodCall* _Nonnull)call result:( FlutterResult _Nonnull)result; -- (polyvox::FilamentViewer*) _viewer; -- (polyvox::ResourceBuffer)loadResource:(const char* const)path; -- (void)freeResource:(polyvox::ResourceBuffer)rb; -- (void)ready; -- (instancetype)initWithRegistrar:(NSObject*)registrar viewId:(int64_t)viewId viewer:(FilamentViewer*)viewer; -@end diff --git a/ios/Classes/FilamentMethodCallHandler.mm b/ios/Classes/FilamentMethodCallHandler.mm deleted file mode 100644 index b31d6c20..00000000 --- a/ios/Classes/FilamentMethodCallHandler.mm +++ /dev/null @@ -1,170 +0,0 @@ -#import "FilamentMethodCallHandler.h" -#import "FilamentNativeViewFactory.h" - -static int _resourceId = 0; - -using namespace polyvox; -using namespace std; - -@implementation FilamentMethodCallHandler { - FlutterMethodChannel* _channel; - FilamentViewer* _viewer; - - NSObject* _registrar; -} -- (instancetype)initWithRegistrar:(NSObject*)registrar - viewId:(int64_t)viewId - viewer:(FilamentViewer*)viewer - -{ - _registrar = registrar; - _viewer = viewer; - - NSString* channelName = [NSString stringWithFormat:@"%@_%d",VIEW_TYPE,viewId]; - _channel = [FlutterMethodChannel - methodChannelWithName:channelName - binaryMessenger:[registrar messenger]]; - [_channel setMethodCallHandler:^(FlutterMethodCall * _Nonnull call, FlutterResult _Nonnull result) { - [self handleMethodCall:call result:result]; - }]; - [self ready]; - return self; -} - -- (void)handleMethodCall:(FlutterMethodCall* _Nonnull)call result:(FlutterResult _Nonnull )result { - if(!_viewer) { - result([FlutterError errorWithCode:@"UNAVAILABLE" - message:@"View unavailable" - details:nil]); - return; - } - if([@"loadSkybox" isEqualToString:call.method]) { - _viewer->loadSkybox([call.arguments UTF8String]); - result(@"OK"); - } else if([@"removeSkybox" isEqualToString:call.method]) { - _viewer->removeSkybox(); - result(@"OK"); - } else if([@"loadIbl" isEqualToString:call.method]) { - _viewer->loadIbl([call.arguments UTF8String]); - result(@"OK"); - } else if([@"removeIbl" isEqualToString:call.method]) { - _viewer->removeIbl(); - result(@"OK"); - } else if([@"loadGlb" isEqualToString:call.method]) { - _viewer->loadGlb([call.arguments UTF8String]); - result(@"OK"); - } else if([@"loadGltf" isEqualToString:call.method]) { - _viewer->loadGltf([call.arguments[0] UTF8String], [call.arguments[1] UTF8String]); - result(@"OK"); - } else if([@"setCamera" isEqualToString:call.method]) { - _viewer->setCamera([call.arguments UTF8String]); - result(@"OK"); - } else if([@"panStart" isEqualToString:call.method]) { - _viewer->manipulator->grabBegin([call.arguments[0] intValue], [call.arguments[1] intValue], true); - result(@"OK"); - } else if([@"panUpdate" isEqualToString:call.method]) { - _viewer->manipulator->grabUpdate([call.arguments[0] intValue], [call.arguments[1] intValue]); - result(@"OK"); - } else if([@"panEnd" isEqualToString:call.method]) { - _viewer->manipulator->grabEnd(); - result(@"OK"); - } else if([@"rotateStart" isEqualToString:call.method]) { - _viewer->manipulator->grabBegin([call.arguments[0] intValue], [call.arguments[1] intValue], false); - result(@"OK"); - } else if([@"rotateUpdate" isEqualToString:call.method]) { - _viewer->manipulator->grabUpdate([call.arguments[0] intValue], [call.arguments[1] intValue]); - result(@"OK"); - } else if([@"rotateEnd" isEqualToString:call.method]) { - _viewer->manipulator->grabEnd(); - result(@"OK"); - } else if([@"animateWeights" isEqualToString:call.method]) { - NSArray* frameData = call.arguments[0]; - NSNumber* numWeights = call.arguments[1]; - NSNumber* numFrames = call.arguments[2]; - NSNumber* frameLenInMs = call.arguments[3]; - - float* framesArr = (float*)malloc([frameData count] *sizeof(float)); - for(int i =0 ; i < [frameData count]; i++) { - *(framesArr+i) = [[frameData objectAtIndex:i] floatValue]; - } - - _viewer->animateWeights((float*)framesArr, [numWeights intValue], [numFrames intValue], [frameLenInMs floatValue]); - result(@"OK"); - } else if([@"playAnimation" isEqualToString:call.method]) { - int animationIndex = [call.arguments[0] intValue]; - bool loop = call.arguments[1]; - _viewer->playAnimation(animationIndex, loop); - result(@"OK"); - } else if ([@"stopAnimation" isEqualToString:call.method]) { - _viewer->stopAnimation(); - result(@"OK"); - } else if([@"getTargetNames" isEqualToString:call.method]) { - NSMutableArray* names = [self getTargetNames:call.arguments]; - result(names); - } else if([@"getAnimationNames" isEqualToString:call.method]) { - NSMutableArray* names = [self getAnimationNames]; - result(names); - } else if([@"applyWeights" isEqualToString:call.method]) { - - NSArray* nWeights = call.arguments; - - int count = [nWeights count]; - float weights[count]; - for(int i=0; i < count; i++) { - weights[i] = [nWeights[i] floatValue]; - } - _viewer->applyWeights(weights, count); - result(@"OK"); - } else if([@"zoom" isEqualToString:call.method]) { - _viewer->manipulator->scroll(0.0f, 0.0f, [call.arguments floatValue]); - result(@"OK"); - } else { - result(FlutterMethodNotImplemented); - } -} - -- (ResourceBuffer)loadResource:(const char* const)path { - NSString* p = [NSString stringWithFormat:@"%s", path]; - NSString* key = [_registrar lookupKeyForAsset:p]; - NSString* nsPath = [[NSBundle mainBundle] pathForResource:key - ofType:nil]; - if (![[NSFileManager defaultManager] fileExistsAtPath:nsPath]) { - NSLog(@"Error: no file exists at %@", p); - exit(-1); - } - - NSData* buffer = [NSData dataWithContentsOfFile:nsPath]; - void* cpy = malloc([buffer length]); - memcpy(cpy, [buffer bytes], [buffer length]); // can we avoid this copy somehow? - _resourceId++; - ResourceBuffer rbuf(cpy, [buffer length], _resourceId); - return rbuf; -} - -- (void)freeResource:(ResourceBuffer)rb { - free((void*)rb.data); -} - -- (void)ready { - [_channel invokeMethod:@"ready" arguments:nil]; -} - -- (NSMutableArray*) getAnimationNames { - unique_ptr> list = _viewer->getAnimationNames(); - NSMutableArray* asArray = [NSMutableArray arrayWithCapacity:list->size()]; - for(int i = 0; i < list->size(); i++) { - asArray[i] = [NSString stringWithFormat:@"%s", list->at(i).c_str()]; - } - return asArray; -} - -- (NSMutableArray*) getTargetNames:(NSString*) meshName { - unique_ptr> list = _viewer->getTargetNames([meshName UTF8String]); - NSMutableArray* asArray = [NSMutableArray arrayWithCapacity:list->size()]; - for(int i = 0; i < list->size(); i++) { - asArray[i] = [NSString stringWithFormat:@"%s", list->at(i).c_str()]; - } - return asArray; -} - -@end diff --git a/ios/Classes/FilamentNativeViewFactory.h b/ios/Classes/FilamentNativeViewFactory.h deleted file mode 100644 index 3a2a9d27..00000000 --- a/ios/Classes/FilamentNativeViewFactory.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef FilamentNativeViewFactory_h -#define FilamentNativeViewFactory_h -#endif /* FilamentNativeViewFactory_h */ - -#import -#import "FilamentView.h" - -#include "FilamentViewer.hpp" - - -@interface FilamentNativeViewFactory : NSObject -- (instancetype)initWithRegistrar:(NSObject*)registrar; -@end - -@interface FilamentNativeView : NSObject - -- (instancetype)initWithFrame:(CGRect)frame - viewIdentifier:(int64_t)viewId - arguments:(id _Nullable)args - registrar:(NSObject*)registrar; - -- (UIView*)view; - -@end - diff --git a/ios/Classes/FilamentNativeViewFactory.mm b/ios/Classes/FilamentNativeViewFactory.mm deleted file mode 100644 index e0320e0e..00000000 --- a/ios/Classes/FilamentNativeViewFactory.mm +++ /dev/null @@ -1,67 +0,0 @@ -#import "FilamentNativeViewFactory.h" -#import "FilamentMethodCallHandler.h" - -using namespace polyvox; - -static const FilamentMethodCallHandler* _shandler; - -static ResourceBuffer loadResource(const char* name) { - return [_shandler loadResource:name]; -} - -static void* freeResource(ResourceBuffer rb) { - [_shandler freeResource:rb ]; - return nullptr; -} - -@implementation FilamentNativeViewFactory { - NSObject* _registrar; -} - -- (instancetype)initWithRegistrar:(NSObject*)registrar { - self = [super init]; - if (self) { - _registrar = registrar; - } - return self; -} - -- (NSObject*)createWithFrame:(CGRect)frame - viewIdentifier:(int64_t)viewId - arguments:(id _Nullable)args { - return [[FilamentNativeView alloc] initWithFrame:frame - viewIdentifier:viewId - arguments:args - registrar:_registrar]; -} - -@end - -@implementation FilamentNativeView { - FilamentView* _view; - FilamentViewer* _viewer; - FilamentMethodCallHandler* _handler; - void* _layer; -} - -- (instancetype)initWithFrame:(CGRect)frame - viewIdentifier:(int64_t)viewId - arguments:(id _Nullable)args - registrar:(NSObject*)registrar { - if (self = [super init]) { - _view = [[FilamentView alloc] init]; - _layer = (__bridge_retained void*)[_view layer]; - _viewer = new FilamentViewer(_layer, loadResource, freeResource); - [_view setViewer:_viewer]; - _handler = [[FilamentMethodCallHandler alloc] initWithRegistrar:registrar viewId:viewId viewer:_viewer ]; - _shandler = _handler; - } - return self; -} - -- (UIView*)view { - return _view; -} - - -@end diff --git a/ios/Classes/FilamentView.h b/ios/Classes/FilamentView.h deleted file mode 100644 index a7d3509f..00000000 --- a/ios/Classes/FilamentView.h +++ /dev/null @@ -1,32 +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. - */ - -#import -#include "FilamentViewer.hpp" -NS_ASSUME_NONNULL_BEGIN - -/** - * FILModelView is simply a UIView with an OpenGL layer. - * - * - */ -@interface FilamentView : UIView -- (void)setViewer:(polyvox::FilamentViewer*)viewer; -- (void)startDisplayLink; -- (void)stopDisplayLink; -@end - -NS_ASSUME_NONNULL_END diff --git a/ios/Classes/FilamentView.mm b/ios/Classes/FilamentView.mm deleted file mode 100644 index 6650c8ed..00000000 --- a/ios/Classes/FilamentView.mm +++ /dev/null @@ -1,108 +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. - */ - -// These defines are set in the "Preprocessor Macros" build setting for each scheme. -#include "FilamentView.h" -#include "FilamentViewer.hpp" -#import - -using namespace std; -using namespace polyvox; - -@interface FilamentView () -- (void)initCommon; -- (void)setViewer:(FilamentViewer*)viewer; -@end - -@implementation FilamentView { - FilamentViewer* _viewer; - CADisplayLink* _displayLink; -} - -- (void)setViewer:(FilamentViewer*)viewer { - _viewer = viewer; -} - -- (instancetype)initWithFrame:(CGRect)frame { - if (self = [super initWithFrame:frame]) { - [self initCommon]; - } - return self; -} - -- (instancetype)initWithCoder:(NSCoder*)coder { - if (self = [super initWithCoder:coder]) { - [self initCommon]; - } - return self; -} - -- (void)initCommon { - [self initializeGLLayer]; -} - -- (void)initializeGLLayer { - CAEAGLLayer* glLayer = (CAEAGLLayer*)self.layer; - glLayer.opaque = YES; -} - -+ (Class)layerClass { - return [CAEAGLLayer class]; -} - -- (void)layoutSubviews { - [super layoutSubviews]; - NSLog(@"layout subview"); - - if(_viewer) { - _viewer->updateViewportAndCameraProjection(self.bounds.size.width, self.bounds.size.height, self.contentScaleFactor); - } - [self startDisplayLink]; -} - -- (void)setContentScaleFactor:(CGFloat)contentScaleFactor { - [super setContentScaleFactor:contentScaleFactor]; - if(_viewer) { - _viewer->updateViewportAndCameraProjection(self.bounds.size.width, self.bounds.size.height, self.contentScaleFactor); - } -} - -- (void)drawRect:(CGRect)rect { - NSLog(@"Drawing rect"); - [super drawRect:rect]; -} - -- (void)startDisplayLink { - NSLog(@"Starting display link"); - - [self stopDisplayLink]; - - // Call our render method 60 times a second. - _displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(render)]; - _displayLink.preferredFramesPerSecond = 60; - [_displayLink addToRunLoop:NSRunLoop.currentRunLoop forMode:NSDefaultRunLoopMode]; -} - -- (void)stopDisplayLink { - [_displayLink invalidate]; - _displayLink = nil; -} - -- (void)render { - _viewer->render(); -} - -@end diff --git a/ios/Classes/PolyvoxFilamentApi.cc b/ios/Classes/PolyvoxFilamentApi.cc new file mode 100644 index 00000000..568226d4 --- /dev/null +++ b/ios/Classes/PolyvoxFilamentApi.cc @@ -0,0 +1,147 @@ +#ifndef _POLYVOX_FILAMENT_API_H +#define _POLYVOX_FILAMENT_API_H + +#include "ResourceBuffer.hpp" +#include "FilamentViewer.hpp" + +using namespace polyvox; + +extern "C" { +// ResourceBuffer create_resource_buffer(const void* data, const uint32_t size, const uint32_t id) { +// return ResourceBuffer {data, size, id }; +// } + + void* filament_viewer_new(void* texture, ResourceBuffer (*loadResource)(const char*), void (*freeResource)(uint32_t)) { + return nullptr; + } + + void set_background_image(void* viewer, const char* path) { + ((FilamentViewer*)viewer)->setBackgroundImage(path); + } + + void load_skybox(void* viewer, const char* skyboxPath) { + ((FilamentViewer*)viewer)->loadSkybox(skyboxPath); + } + + void load_ibl(void* viewer, const char* iblPath) { + ((FilamentViewer*)viewer)->loadIbl(iblPath); + } + + void remove_skybox(void* viewer) { + ((FilamentViewer*)viewer)->removeSkybox(); + } + + + void remove_ibl(void* viewer) { + ((FilamentViewer*)viewer)->removeIbl(); + } + + void* load_glb(void* viewer, const char* assetPath) { + return ((FilamentViewer*)viewer)->loadGlb(assetPath); + } + + void* load_gltf(void* viewer, const char* assetPath, const char* relativePath) { + return ((FilamentViewer*)viewer)->loadGltf(assetPath, relativePath); + } + + bool set_camera(void* viewer, void* asset, const char* nodeName) { + return ((FilamentViewer*)viewer)->setCamera((SceneAsset*)asset, nodeName); + } + + void render( + void* viewer + ) { + ((FilamentViewer*)viewer)->render(); + } + + void destroy_swap_chain(void* viewer) { + ((FilamentViewer*)viewer)->destroySwapChain(); + } + + 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) { + ((FilamentViewer*)viewer)->manipulator->grabBegin(x, y, pan); + + } + + void grab_update(void* viewer, int x, int y) { + ((FilamentViewer*)viewer)->manipulator->grabUpdate(x, y); + } + + void grab_end(void* viewer) { + ((FilamentViewer*)viewer)->manipulator->grabEnd(); + } + + void apply_weights(void* asset, float* const weights, int count) { + ((SceneAsset*)asset)->applyWeights(weights, count); + } + + void animate_weights(void* asset, float* data, int numWeights, int numFrames, float frameRate) { + ((SceneAsset*)asset)->animateWeights((float*)data, numWeights, numFrames, frameRate); + } + + void play_animation(void* asset, int index, bool loop) { + ((SceneAsset*)asset)->playAnimation(index, loop); + } + + int get_animation_count(void* asset) { + auto names = ((SceneAsset*)asset)->getAnimationNames(); + return names->size(); + } + + void get_animation_name(void* asset, char* const outPtr, int index) { + auto names = ((SceneAsset*)asset)->getAnimationNames(); + string name = names->at(index); + strcpy(outPtr, name.c_str()); + } + + int get_target_name_count(void* asset, const char* meshName) { + unique_ptr> names = ((SceneAsset*)asset)->getTargetNames(meshName); + return names->size(); + } + + void get_target_name(void* asset, const char* meshName, char* const outPtr, int index ) { + unique_ptr> names = ((SceneAsset*)asset)->getTargetNames(meshName); + string name = names->at(index); + strcpy(outPtr, name.c_str()); + } + + void remove_asset(void* viewer, void* asset) { + ((FilamentViewer*)viewer)->removeAsset((SceneAsset*)asset); + } + + void clear_assets(void* viewer) { + ((FilamentViewer*)viewer)->clearAssets(); + } + + void set_texture(void* asset, const char* assetPath, int renderableIndex) { + ((SceneAsset*)asset)->setTexture(assetPath, renderableIndex); + } + + void transform_to_unit_cube(void* asset) { + ((SceneAsset*)asset)->transformToUnitCube(); + } + + // void set_position(void* asset, float x, float y, float z) { + // ((SceneAsset*)asset)->setPosition(x, y, z); + // } + + // void set_rotation(void* asset, float rads, float x, float y, float z) { + // ((SceneAsset*)asset)->setRotation(rads, x, y, z); + // } + +} + +#endif diff --git a/ios/Classes/PolyvoxFilamentApi.h b/ios/Classes/PolyvoxFilamentApi.h new file mode 100644 index 00000000..061eda38 --- /dev/null +++ b/ios/Classes/PolyvoxFilamentApi.h @@ -0,0 +1,56 @@ +#ifndef _POLYVOX_FILAMENT_API_H +#define _POLYVOX_FILAMENT_API_H + +#include "ResourceBuffer.hpp" + +typedef struct ResourceBuffer ResourceBuffer; + +//ResourceBuffer create_resource_buffer(const void* data, const uint32_t size, const uint32_t id); +void* filament_viewer_new(void* texture, void* loadResource, void* freeResource); +void set_background_image(void* viewer, const char* path); +void load_skybox(void* viewer, const char* skyboxPath); +void load_ibl(void* viewer, const char* iblPath); +void remove_skybox(void* viewer); +void remove_ibl(void* viewer); +void* load_glb(void* viewer, const char* assetPath); +void* load_gltf(void* viewer, const char* assetPath, const char* relativePath); +bool set_camera(void* viewer, void* asset, const char* nodeName); +void render(void* viewer); +void destroy_swap_chain(void* viewer); +void* get_renderer(void* viewer); +void update_viewport_and_camera_projection(void* viewer, int width, int height, float scaleFactor); + +void scroll(void* viewer, float x, float y , float z); + +void grab_begin(void* viewer, int x, int y, bool pan); +void grab_update(void* viewer, int x, int 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); + +void play_animation(void* asset, int index, bool loop); + +int get_animation_count(void* asset); + +void get_animation_name(void* asset, char* const outPtr, int index); + +void get_target_name(void* asset, const char* meshName, char* const outPtr, int index ); + +int get_target_name_count(void* asset, const char* meshName); + +void remove_asset(void* viewer, void* asset); + +void clear_assets(void* viewer); + +void set_texture(void* asset, const char* assetPath, int renderableIndex); + +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); + +#endif diff --git a/ios/Classes/PolyvoxFilamentIOSApi.cc b/ios/Classes/PolyvoxFilamentIOSApi.cc new file mode 100644 index 00000000..849f0fdf --- /dev/null +++ b/ios/Classes/PolyvoxFilamentIOSApi.cc @@ -0,0 +1,32 @@ +#include "PolyvoxFilamentApi.h" +#include "FilamentViewer.hpp" +#include "ResourceBuffer.hpp" +#include "SceneResources.hpp" +#include + +using namespace polyvox; +using namespace std; + +extern "C" { + using RawLoadType = ResourceBuffer(const char*, void* resource); + using RawFreeType = void(uint32_t, void*); + + void* filament_viewer_new_ios(void* pb, void* loadResource, void* freeResource, void* resources) { + + FreeResource _freeResource = [=](uint32_t rid) { + reinterpret_cast(freeResource)(rid, resources); + }; + + function _loadResource = [=](const char* uri){ + auto cast = reinterpret_cast(loadResource); + return cast(uri, resources); + }; + + auto viewer = new FilamentViewer(pb,_loadResource, _freeResource); + + return (void*)viewer; + } + void create_swap_chain(void* viewer, void* texture) { + ((FilamentViewer*)viewer)->createSwapChain(texture); + } +} diff --git a/ios/Classes/PolyvoxFilamentIOSApi.h b/ios/Classes/PolyvoxFilamentIOSApi.h new file mode 100644 index 00000000..0b97842c --- /dev/null +++ b/ios/Classes/PolyvoxFilamentIOSApi.h @@ -0,0 +1,3 @@ +void* filament_viewer_new_ios(void* texture, void* loadResource, void* freeResource, void* resources); + +void create_swap_chain(void* viewer, void* texture); diff --git a/ios/Classes/PolyvoxFilamentPlugin.m b/ios/Classes/PolyvoxFilamentPlugin.m new file mode 100644 index 00000000..14f8ef46 --- /dev/null +++ b/ios/Classes/PolyvoxFilamentPlugin.m @@ -0,0 +1,63 @@ +#import "PolyvoxFilamentPlugin.h" +#if __has_include() +#import +#else +// Support project import fallback if the generated compatibility header +// is not copied when this plugin is created as a library. +// https://forums.swift.org/t/swift-static-libraries-dont-copy-generated-objective-c-header/19816 +#import "polyvox_filament-Swift.h" +#endif + +@implementation PolyvoxFilamentPlugin ++ (void)registerWithRegistrar:(NSObject*)registrar { + [SwiftPolyvoxFilamentPlugin registerWithRegistrar:registrar]; +} +@end + +// - (ResourceBuffer)loadResource:(const char* const)path { +// NSString* p = [NSString stringWithFormat:@"%s", path]; +// NSString* key = [_registrar lookupKeyForAsset:p]; +// NSString* nsPath = [[NSBundle mainBundle] pathForResource:key +// ofType:nil]; +// if (![[NSFileManager defaultManager] fileExistsAtPath:nsPath]) { +// NSLog(@"Error: no file exists at %@", p); +// exit(-1); +// } + +// NSData* buffer = [NSData dataWithContentsOfFile:nsPath]; +// void* cpy = malloc([buffer length]); +// memcpy(cpy, [buffer bytes], [buffer length]); // can we avoid this copy somehow? +// _resourceId++; +// ResourceBuffer rbuf(cpy, [buffer length], _resourceId); +// return rbuf; +// } + +// - (void)freeResource:(ResourceBuffer)rb { +// free((void*)rb.data); +// } + +// - (void)ready { +// [_channel invokeMethod:@"ready" arguments:nil]; +// } + +// - (NSMutableArray*) getAnimationNames { +// unique_ptr> list = _viewer->getAnimationNames(); +// NSMutableArray* asArray = [NSMutableArray arrayWithCapacity:list->size()]; +// for(int i = 0; i < list->size(); i++) { +// asArray[i] = [NSString stringWithFormat:@"%s", list->at(i).c_str()]; +// } +// return asArray; +// } + +// - (NSMutableArray*) getTargetNames:(NSString*) meshName { +// unique_ptr> list = _viewer->getTargetNames([meshName UTF8String]); +// NSMutableArray* asArray = [NSMutableArray arrayWithCapacity:list->size()]; +// for(int i = 0; i < list->size(); i++) { +// asArray[i] = [NSString stringWithFormat:@"%s", list->at(i).c_str()]; +// } +// return asArray; +// } + +// @end + +// @end diff --git a/ios/Classes/PolyvoxFilamentPlugin.mm b/ios/Classes/PolyvoxFilamentPlugin.mm deleted file mode 100644 index daa00fa0..00000000 --- a/ios/Classes/PolyvoxFilamentPlugin.mm +++ /dev/null @@ -1,12 +0,0 @@ -#import "PolyvoxFilamentPlugin.h" -#import "FilamentNativeViewFactory.h" - -FilamentNativeViewFactory* factory; - -@implementation PolyvoxFilamentPlugin -+ (void)registerWithRegistrar:(NSObject*)registrar { - factory = - [[FilamentNativeViewFactory alloc] initWithRegistrar:registrar]; - [registrar registerViewFactory:factory withId:@"app.polyvox.filament/filament_view"]; -} -@end diff --git a/ios/Classes/SwiftPolyvoxFilamentPlugin-Bridging-Header.h b/ios/Classes/SwiftPolyvoxFilamentPlugin-Bridging-Header.h new file mode 100644 index 00000000..ce9a1d8f --- /dev/null +++ b/ios/Classes/SwiftPolyvoxFilamentPlugin-Bridging-Header.h @@ -0,0 +1 @@ +#import "PolyvoxFilamentApi.h" \ No newline at end of file diff --git a/ios/Classes/SwiftPolyvoxFilamentPlugin.swift b/ios/Classes/SwiftPolyvoxFilamentPlugin.swift new file mode 100644 index 00000000..7838cf00 --- /dev/null +++ b/ios/Classes/SwiftPolyvoxFilamentPlugin.swift @@ -0,0 +1,283 @@ +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.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.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? { + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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.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.allocate(capacity:256) + get_animation_name(assetPtr, outPtr, i) + names.append(String(cString:outPtr)) + } + result(names); + case "applyWeights": + let args = call.arguments as! Array + let assetPtr = UnsafeMutableRawPointer.init(bitPattern: args[0] as! Int) + let weights = args[1] as! Array + weights.map { Float($0) }.withUnsafeBufferPointer { + apply_weights(assetPtr, UnsafeMutablePointer.init(mutating:$0.baseAddress), Int32(weights.count)) + + } + result("OK") + case "zoom": + let args = call.arguments as! Array + 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 + let assetPtr = UnsafeMutableRawPointer.init(bitPattern: args[0] as! Int) + let frameData = args[1] as! Array + 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.init(mutating:$0.baseAddress), Int32(numWeights), Int32(numFrames), Float(frameLenInMs)) + } + result("OK") + default: + result(FlutterMethodNotImplemented) + } + } +} + + + +// } else if([@"panStart" isEqualToString:call.method]) { +// _viewer->manipulator->grabBegin([call.arguments[0] intValue], [call.arguments[1] intValue], true); +// result(@"OK"); +// } else if([@"panUpdate" isEqualToString:call.method]) { +// _viewer->manipulator->grabUpdate([call.arguments[0] intValue], [call.arguments[1] intValue]); +// result(@"OK"); +// } else if([@"panEnd" isEqualToString:call.method]) { +// _viewer->manipulator->grabEnd(); +// result(@"OK"); +// } else if([@"rotateStart" isEqualToString:call.method]) { +// _viewer->manipulator->grabBegin([call.arguments[0] intValue], [call.arguments[1] intValue], false); +// result(@"OK"); +// } else if([@"rotateUpdate" isEqualToString:call.method]) { +// _viewer->manipulator->grabUpdate([call.arguments[0] intValue], [call.arguments[1] intValue]); +// result(@"OK"); +// } else if([@"rotateEnd" isEqualToString:call.method]) { +// _viewer->manipulator->grabEnd(); +// result(@"OK"); +// } else diff --git a/ios/polyvox_filament.podspec b/ios/polyvox_filament.podspec index 1e95beb8..2a55e30a 100644 --- a/ios/polyvox_filament.podspec +++ b/ios/polyvox_filament.podspec @@ -13,7 +13,7 @@ A new flutter plugin project. s.license = { :file => '../LICENSE' } s.author = { 'Your Company' => 'email@example.com' } s.source = { :path => '.' } - s.source_files = 'Classes/**/*', 'src/*.*', 'src/morph/*.*', 'src/morph/UbershaderLoader.cpp' #, "include/**/*" + 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.dependency 'Flutter' @@ -23,26 +23,27 @@ A new flutter plugin project. 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)"', + '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.user_target_xcconfig = { - # 'CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES' => 'YES', - # 'ALWAYS_SEARCH_USER_PATHS' => 'YES', - # '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/morph" "$(inherited)"', - # 'OTHER_CXXFLAGS' => '"--std=c++17" "-fmodules" "-fcxx-modules" "$(inherited)"', - # "CLANG_CXX_LANGUAGE_STANDARD" => "c++17", - # #"CLANG_CXX_LIBRARY" => "libc++" - # "OTHER_LDFLAGS" => '-lfilament -lbackend -lfilameshio -lviewer -lfilamat -lgeometry -lutils -lfilabridge -lgltfio_resources_lite -lgltfio_core -lfilament-iblprefilter -limage -lcamutils -lgltfio_resources -lfilaflat -ldracodec -libl', - # 'LIBRARY_SEARCH_PATHS' => '"${PODS_ROOT}/../.symlinks/plugins/polyvox_filament/ios/lib" "$(inherited)"', - # } 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/morph" "$(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)"', 'ALWAYS_SEARCH_USER_PATHS' => 'YES', - "OTHER_LDFLAGS" => '-lfilament -lbackend -lfilameshio -lviewer -lfilamat -lgeometry -lutils -lfilabridge -lgltfio_resources_lite -lgltfio_core -lfilament-iblprefilter -limage -lcamutils -lgltfio_resources -lfilaflat -ldracodec -libl', + "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)"', } diff --git a/ios/src/ResourceBuffer.hpp b/ios/src/ResourceBuffer.hpp new file mode 100644 index 00000000..fa7a2705 --- /dev/null +++ b/ios/src/ResourceBuffer.hpp @@ -0,0 +1,44 @@ +#ifndef RESOURCE_BUFFER_H +#define RESOURCE_BUFFER_H + +#include +#if defined(__cplusplus) +extern "C" { +#endif + // + // Pairs a memory buffer with an ID that can be used to unload the backing asset if needed. + // Use this when you want to load an asset from a resource that requires more than just `free` on the underlying buffer. + // e.g. + // ``` + // uint64_t id = get_next_resource_id(); + // AAsset *asset = AAssetManager_open(am, name, AASSET_MODE_BUFFER); + // off_t length = AAsset_getLength(asset); + // const void * buffer = AAsset_getBuffer(asset); + // uint8_t *buf = new uint8_t[length ]; + // memcpy(buf,buffer, length); + // ResourceBuffer rb(buf, length, id); + // ... + // ... + // (elsewhere) + // AAsset* asset = get_asset_from_id(rb.id); + // AAsset_close(asset); + // free_asset_id(rb.id); + // + struct ResourceBuffer { + #if defined(__cplusplus) + ResourceBuffer(const void* data, const uint32_t size, const uint32_t id) : data(data), size(size), id(id) {}; + ResourceBuffer& operator=(ResourceBuffer other) { + data = other.data; + size = other.size; + id = other.id; + return *this; + } + #endif + const void* data; + uint32_t size; + uint32_t id; + }; +#if defined(__cplusplus) +} +#endif +#endif diff --git a/ios/src/SceneAsset.cpp b/ios/src/SceneAsset.cpp index eb2a32a4..0ac1701a 100644 --- a/ios/src/SceneAsset.cpp +++ b/ios/src/SceneAsset.cpp @@ -139,7 +139,7 @@ void SceneAsset::setTexture(const char* resourcePath, int renderableIndex) { delete inputStream; - _freeResource(imageResource); + _freeResource(imageResource.id); uint32_t channels = image->getChannels(); uint32_t w = image->getWidth(); diff --git a/ios/src/SceneAssetLoader.cpp b/ios/src/SceneAssetLoader.cpp index 005940c7..e597d84a 100644 --- a/ios/src/SceneAssetLoader.cpp +++ b/ios/src/SceneAssetLoader.cpp @@ -52,7 +52,7 @@ SceneAsset *SceneAssetLoader::fromGltf(const char *uri, ResourceLoader::BufferDescriptor b(buf.data, buf.size); _resourceLoader->addResourceData(resourceUris[i], std::move(b)); - _freeResource(buf); + _freeResource(buf.id); } _resourceLoader->loadResources(asset); @@ -115,7 +115,7 @@ SceneAsset *SceneAssetLoader::fromGlb(const char *uri) { asset->releaseSourceData(); Log("Source data released."); - _freeResource(rbuf); + _freeResource(rbuf.id); Log("Successfully loaded GLB."); return new SceneAsset(asset, _engine, _ncm, _loadResource, _freeResource); @@ -128,4 +128,4 @@ void SceneAssetLoader::remove(SceneAsset *asset) { _assetLoader->destroyAsset(asset->_asset); delete asset; } -} // namespace polyvox \ No newline at end of file +} // namespace polyvox diff --git a/ios/src/SceneAssetLoader.hpp b/ios/src/SceneAssetLoader.hpp index 44b33c9c..2b62e3dc 100644 --- a/ios/src/SceneAssetLoader.hpp +++ b/ios/src/SceneAssetLoader.hpp @@ -8,6 +8,7 @@ #include "SceneResources.hpp" #include "SceneAsset.hpp" +#include "ResourceBuffer.hpp" namespace polyvox { using namespace filament; diff --git a/ios/src/SceneResources.hpp b/ios/src/SceneResources.hpp index b2a2ec48..8ea1a95b 100644 --- a/ios/src/SceneResources.hpp +++ b/ios/src/SceneResources.hpp @@ -1,52 +1,21 @@ #pragma once #include +#include + +#include "ResourceBuffer.hpp" namespace polyvox { - - // - // Pairs a memory buffer with an ID that can be used to unload the backing asset if needed. - // Use this when you want to load an asset from a resource that requires more than just `free` on the underlying buffer. - // e.g. - // ``` - // uint64_t id = get_next_resource_id(); - // AAsset *asset = AAssetManager_open(am, name, AASSET_MODE_BUFFER); - // off_t length = AAsset_getLength(asset); - // const void * buffer = AAsset_getBuffer(asset); - // uint8_t *buf = new uint8_t[length ]; - // memcpy(buf,buffer, length); - // ResourceBuffer rb(buf, length, id); - // ... - // ... - // (elsewhere) - // AAsset* asset = get_asset_from_id(rb.id); - // AAsset_close(asset); - // free_asset_id(rb.id); - // - struct ResourceBuffer { - ResourceBuffer(const void* data, const uint32_t size, const uint32_t id) : data(data), size(size), id(id) {}; - - ResourceBuffer& operator=(ResourceBuffer other) - { - data = other.data; - size = other.size; - id = other.id; - return *this; - } - const void* data; - uint32_t size; - uint32_t id; - }; - + using namespace std; // - // Typedef for any function that loads a resource into a ResourceBuffer from an asset URI. + // Typedef for a function that loads a resource into a ResourceBuffer from an asset URI. // - using LoadResource = std::function; + using LoadResource = function; // - // Typedef for any function that frees a ResourceBuffer. + // Typedef for a function that frees an ID associated with a ResourceBuffer. // - using FreeResource = std::function; + using FreeResource = function; typedef std::chrono::time_point time_point_t; @@ -110,4 +79,5 @@ namespace polyvox { float* frameData; int numWeights; }; -} \ No newline at end of file +} +