diff --git a/android/CMakeLists.txt b/android/CMakeLists.txt index 1befecea..37ba3728 100644 --- a/android/CMakeLists.txt +++ b/android/CMakeLists.txt @@ -13,7 +13,7 @@ add_library( ../ios/src/ktxreader/Ktx1Reader.cpp src/main/cpp/StbProvider.cpp src/main/cpp/JobSystem.cpp - ../ios/src/SceneAssetLoader.cpp + ../ios/src/AssetManager.cpp ../ios/src/FilamentViewer.cpp ../ios/src/PolyvoxFilamentApi.cpp ../ios/src/StreamBufferAdapter.cpp diff --git a/example/lib/main.dart b/example/lib/main.dart index 3b3dc19b..fd6a35e5 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -19,12 +19,12 @@ class MyApp extends StatefulWidget { State createState() => _MyAppState(); } -class _MyAppState extends State { - final FilamentController _filamentController = PolyvoxFilamentController(); +class _MyAppState extends State with SingleTickerProviderStateMixin { + late FilamentController _filamentController; - FilamentAsset? _cube; - FilamentAsset? _flightHelmet; - FilamentLight? _light; + FilamentEntity? _cube; + FilamentEntity? _flightHelmet; + FilamentEntity? _light; final weights = List.filled(255, 0.0); List _targetNames = []; @@ -37,6 +37,7 @@ class _MyAppState extends State { @override void initState() { super.initState(); + _filamentController = FilamentController(this); } void onClick(int index) async { @@ -45,7 +46,7 @@ class _MyAppState extends State { await _filamentController.initialize(); break; case -2: - await _filamentController.render(); + _filamentController.render(); break; case -4: setState(() { @@ -61,55 +62,48 @@ class _MyAppState extends State { break; case 0: - await _filamentController.setBackgroundImage('assets/background.ktx'); + _filamentController.setBackgroundImage('assets/background.ktx'); break; case 1: - await _filamentController + _filamentController .loadSkybox('assets/default_env/default_env_skybox.ktx'); break; case -3: - await _filamentController - .loadIbl('assets/default_env/default_env_ibl.ktx'); + _filamentController.loadIbl('assets/default_env/default_env_ibl.ktx'); break; case 2: - await _filamentController.removeSkybox(); + _filamentController.removeSkybox(); break; case 3: - _cube = await _filamentController.loadGlb('assets/cube.glb'); - - _animationNames = await _filamentController.getAnimationNames(_cube!); + _cube = _filamentController.loadGlb('assets/cube.glb'); + _animationNames = _filamentController.getAnimationNames(_cube!); break; case 4: if (_cube != null) { - await _filamentController.removeAsset(_cube!); + _filamentController.removeAsset(_cube!); } - _cube = - await _filamentController.loadGltf('assets/cube.gltf', 'assets'); - print(await _filamentController.getAnimationNames(_cube!)); + _cube = _filamentController.loadGltf('assets/cube.gltf', 'assets'); break; case 5: - if (_flightHelmet == null) { - _flightHelmet = await _filamentController.loadGltf( - 'assets/FlightHelmet/FlightHelmet.gltf', 'assets/FlightHelmet'); - } + _flightHelmet ??= _filamentController.loadGltf( + 'assets/FlightHelmet/FlightHelmet.gltf', 'assets/FlightHelmet'); break; case 6: - await _filamentController.removeAsset(_cube!); + _filamentController.removeAsset(_cube!); break; case 7: - await _filamentController.setMorphTargetWeights( - _cube!, List.filled(8, 1.0)); + _filamentController.setMorphTargetWeights(_cube!, List.filled(8, 1.0)); break; case 8: - await _filamentController.setMorphTargetWeights( - _cube!, List.filled(8, 0)); + _filamentController.setMorphTargetWeights(_cube!, List.filled(8, 0)); break; case 9: - _filamentController.playAnimations( - _cube!, List.generate(_animationNames.length, (i) => i), - loop: _loop); + for (int i = 0; i < _animationNames.length; i++) { + _filamentController.playAnimation(_cube!, i, loop: _loop); + } + break; case 10: _filamentController.stopAnimation(_cube!, 0); @@ -145,39 +139,38 @@ class _MyAppState extends State { // _filamentController.setAnimation(_cube!, animation); break; case 16: - _targetNames = - await _filamentController.getMorphTargetNames(_cube!, "Cube"); + _targetNames = _filamentController.getMorphTargetNames(_cube!, "Cube"); setState(() {}); break; case 17: - _animationNames = await _filamentController.getAnimationNames(_cube!); + _animationNames = _filamentController.getAnimationNames(_cube!); setState(() {}); break; case 18: - await _filamentController.panStart(1, 1); - await _filamentController.panUpdate(1, 2); - await _filamentController.panEnd(); + _filamentController.panStart(1, 1); + _filamentController.panUpdate(1, 2); + _filamentController.panEnd(); break; case 19: - await _filamentController.panStart(1, 1); - await _filamentController.panUpdate(0, 0); - await _filamentController.panEnd(); + _filamentController.panStart(1, 1); + _filamentController.panUpdate(0, 0); + _filamentController.panEnd(); break; case 20: - await _filamentController.clearAssets(); + _filamentController.clearAssets(); break; case 21: - await _filamentController.setTexture(_cube!, "assets/background.png"); + _filamentController.setTexture(_cube!, "assets/background.png"); break; case 22: - await _filamentController.transformToUnitCube(_cube!); + _filamentController.transformToUnitCube(_cube!); break; case 23: - await _filamentController.setPosition(_cube!, 1.0, 1.0, -1.0); + _filamentController.setPosition(_cube!, 1.0, 1.0, -1.0); break; case 24: - await _filamentController.setRotation(_cube!, pi / 2, 0.0, 1.0, 0.0); + _filamentController.setRotation(_cube!, pi / 2, 0.0, 1.0, 0.0); break; case 25: setState(() { @@ -185,35 +178,34 @@ class _MyAppState extends State { }); break; case 26: - await _filamentController.setCameraPosition(0, 0, 3); - await _filamentController.setCameraRotation(0, 0, 1, 0); + _filamentController.setCameraPosition(0, 0, 3); + _filamentController.setCameraRotation(0, 0, 1, 0); break; case 27: _framerate = _framerate == 60 ? 30 : 60; - await _filamentController.setFrameRate(_framerate); + _filamentController.setFrameRate(_framerate); break; case 28: - await _filamentController.setBackgroundImagePosition(25, 25); + _filamentController.setBackgroundImagePosition(25, 25); break; case 29: - _light = await _filamentController.addLight( + _light = _filamentController.addLight( 1, 6500, 15000000, 0, 1, 0, 0, -1, 0, true); - _light = await _filamentController.addLight( + _light = _filamentController.addLight( 2, 6500, 15000000, 0, 0, 1, 0, 0, -1, true); break; case 30: if (_light != null) { - await _filamentController.removeLight(_light!); + _filamentController.removeLight(_light!); } break; case 31: - await _filamentController.clearLights(); + _filamentController.clearLights(); break; case 32: - await _filamentController - .setCameraModelMatrix(List.filled(16, 1.0)); + _filamentController.setCameraModelMatrix(List.filled(16, 1.0)); - // await _filamentController.setBoneTransform( + // _filamentController.setBoneTransform( // _cube!, // "Bone.001", // "Cube.001", diff --git a/example/linux/CMakeLists.txt b/example/linux/CMakeLists.txt index b0ff3c37..437b0609 100644 --- a/example/linux/CMakeLists.txt +++ b/example/linux/CMakeLists.txt @@ -41,7 +41,7 @@ endif() # of modifying this function. function(APPLY_STANDARD_SETTINGS TARGET) target_compile_features(${TARGET} PUBLIC cxx_std_14) - target_compile_options(${TARGET} PRIVATE -Wall -Werror -Wno-unused-function) + target_compile_options(${TARGET} PRIVATE -Wall -Werror -Wno-unused-function -Wno-unused-variable) target_compile_options(${TARGET} PRIVATE "$<$>:-O3>") target_compile_definitions(${TARGET} PRIVATE "$<$>:NDEBUG>") endfunction() diff --git a/ios/include/AssetManager.hpp b/ios/include/AssetManager.hpp new file mode 100644 index 00000000..80610260 --- /dev/null +++ b/ios/include/AssetManager.hpp @@ -0,0 +1,95 @@ +#pragma once + +#include + +#include +#include +#include + +#include "ResourceManagement.hpp" +#include "SceneAsset.hpp" +#include "ResourceBuffer.hpp" + +typedef int32_t EntityId; + +namespace polyvox { + using namespace filament; + using namespace filament::gltfio; + + class AssetManager { + public: + AssetManager(LoadResource loadResource, + FreeResource freeResource, + NameComponentManager *ncm, + Engine *engine, + Scene *scene); + ~AssetManager(); + EntityId loadGltf(const char* uri, const char* relativeResourcePath); + EntityId loadGlb(const char* uri, bool unlit); + FilamentAsset* getAssetByEntityId(EntityId entityId); + void remove(EntityId entity); + void destroyAll(); + unique_ptr> getAnimationNames(EntityId entity); + unique_ptr> getMorphTargetNames(EntityId entity, const char *meshName); + void transformToUnitCube(EntityId e); + inline void updateTransform(EntityId e); + void setScale(EntityId e, float scale); + void setPosition(EntityId e, float x, float y, float z); + void setRotation(EntityId e, float rads, float x, float y, float z); + const utils::Entity *getCameraEntities(EntityId e); + size_t getCameraEntityCount(EntityId e); + const utils::Entity* getLightEntities(EntityId e) const noexcept; + size_t getLightEntityCount(EntityId e) const noexcept; + void updateAnimations(); + + bool setBoneAnimationBuffer( + EntityId entity, + int length, + const char** const boneNames, + const char** const meshNames, + const float* const frameData, + int numFrames, + float frameLengthInMs); + bool setMorphAnimationBuffer( + EntityId entity, + const char* entityName, + const float* const morphData, + int numMorphWeights, + int numFrames, + float frameLengthInMs); + void playAnimation(EntityId e, int index, bool loop, bool reverse); + void stopAnimation(EntityId e, int index); + void setMorphTargetWeights(const char* const entityName, float *weights, int count); + void loadTexture(EntityId entity, const char* resourcePath, int renderableIndex); + void setAnimationFrame(EntityId entity, int animationIndex, int animationFrame); + + private: + LoadResource _loadResource; + FreeResource _freeResource; + AssetLoader* _assetLoader = nullptr; + ResourceLoader* _resourceLoader = nullptr; + NameComponentManager* _ncm = nullptr; + Engine* _engine; + Scene* _scene; + MaterialProvider* _unlitProvider = nullptr; + MaterialProvider* _ubershaderProvider = nullptr; + gltfio::ResourceLoader* _gltfResourceLoader = nullptr; + gltfio::TextureProvider* _stbDecoder = nullptr; + tsl::robin_map _assets; + + void setBoneTransform( + FilamentInstance* instance, + vector animations, + int frameNumber + ); + + utils::Entity findEntityByName( + SceneAsset asset, + const char* entityName + ); + + inline void updateTransform(SceneAsset asset); + + + }; +} diff --git a/ios/include/FilamentViewer.hpp b/ios/include/FilamentViewer.hpp index 4fdf018f..8cba25e7 100644 --- a/ios/include/FilamentViewer.hpp +++ b/ios/include/FilamentViewer.hpp @@ -31,17 +31,16 @@ #include #include -#include "SceneAssetLoader.hpp" -#include "SceneAsset.hpp" +#include "AssetManager.hpp" #include "ResourceManagement.hpp" using namespace std; using namespace filament; using namespace filament::math; using namespace gltfio; -using namespace utils; using namespace camutils; +typedef int32_t EntityId; namespace polyvox { class FilamentViewer { @@ -56,9 +55,7 @@ namespace polyvox { void loadIbl(const char* const iblUri, float intensity); void removeIbl(); - SceneAsset* loadGlb(const char* const uri, bool unlit); - SceneAsset* loadGltf(const char* const uri, const char* relativeResourcePath); - void removeAsset(SceneAsset* asset); + void removeAsset(EntityId asset); // removes all add assets from the current scene void clearAssets(); @@ -66,8 +63,7 @@ namespace polyvox { void render(uint64_t frameTimeInNanos); void setFrameInterval(float interval); - bool setFirstCamera(SceneAsset* asset); - bool setCamera(SceneAsset* asset, const char* nodeName); + bool setCamera(EntityId asset, const char* nodeName); void createSwapChain(void* surface, uint32_t width, uint32_t height); void destroySwapChain(); @@ -95,9 +91,13 @@ namespace polyvox { void scrollEnd(); int32_t addLight(LightManager::Type t, float colour, float intensity, float posX, float posY, float posZ, float dirX, float dirY, float dirZ, bool shadows); - void removeLight(int32_t entityId); + void removeLight(EntityId entityId); void clearLights(); + AssetManager* const getAssetManager() { + return (AssetManager* const) _assetManager; + } + private: void createImageRenderable(); void loadResources(std::string relativeResourcePath); @@ -124,24 +124,18 @@ namespace polyvox { SwapChain* _swapChain = nullptr; - vector _assets; - - SceneAssetLoader* _ubershaderAssetLoader; - SceneAssetLoader* _unlitAssetLoader; - NameComponentManager* _ncm; + AssetManager* _assetManager = nullptr; + + NameComponentManager* _ncm = nullptr; + std::mutex mtx; // mutex to ensure thread safety when removing assets - vector _lights; + vector _lights; Texture* _skyboxTexture = nullptr; Skybox* _skybox = nullptr; Texture* _iblTexture = nullptr; IndirectLight* _indirectLight = nullptr; - MaterialProvider* _ubershaderProvider = nullptr; - MaterialProvider* _unlitProvider = nullptr; - - gltfio::ResourceLoader* _resourceLoader = nullptr; - gltfio::TextureProvider* _stbDecoder = nullptr; bool _recomputeAabb = false; bool _actualSize = false; @@ -156,7 +150,7 @@ namespace polyvox { uint32_t _imageWidth = 0; mat4f _imageScale; Texture* _imageTexture = nullptr; - Entity* _imageEntity = nullptr; + utils::Entity* _imageEntity = nullptr; VertexBuffer* _imageVb = nullptr; IndexBuffer* _imageIb = nullptr; Material* _imageMaterial = nullptr; diff --git a/ios/include/PolyvoxFilamentApi.h b/ios/include/PolyvoxFilamentApi.h index 644166be..8d653a06 100644 --- a/ios/include/PolyvoxFilamentApi.h +++ b/ios/include/PolyvoxFilamentApi.h @@ -7,111 +7,104 @@ typedef struct ResourceBuffer ResourceBuffer; -/// -/// Frame data for animating multiples bones for multiple meshes. -/// [data] +typedef int32_t EntityId; + +/// +/// struct to facilitate passing bone animation frame data between Dart/native. /// -struct BoneAnimation { - const char* const* const boneNames; - const char* const* const meshNames; - const float* const data; - size_t numBones; - size_t numMeshTargets; -}; +void* create_filament_viewer(void *context, ResourceBuffer (*loadResource)(const char *), void (*freeResource)(uint32_t)); +void delete_filament_viewer(void *viewer); +void* get_asset_manager(void* viewer); +void create_render_target(void *viewer, uint32_t textureId, uint32_t width, uint32_t height); +void clear_background_image(void *viewer); +void set_background_image(void *viewer, const char *path); +void set_background_image_position(void *viewer, float x, float y, bool clamp); +void set_background_color(void *viewer, const float r, const float g, const float b, const float a); +void load_skybox(void *viewer, const char *skyboxPath); +void load_ibl(void *viewer, const char *iblPath, float intensity); +void remove_skybox(void *viewer); +void remove_ibl(void *viewer); +EntityId add_light(void *viewer, uint8_t type, float colour, float intensity, float posX, float posY, float posZ, float dirX, float dirY, float dirZ, bool shadows); +void remove_light(void *viewer, EntityId entityId); +void clear_lights(void *viewer); +EntityId load_glb(void *assetManager, const char *assetPath, bool unlit); +EntityId load_gltf(void *assetManager, const char *assetPath, const char *relativePath); +bool set_camera(void *viewer, EntityId asset, const char *nodeName); +void render(void *viewer, uint64_t frameTimeInNanos); +void create_swap_chain(void *viewer, void *surface, uint32_t width, uint32_t height); +void destroy_swap_chain(void *viewer); +void set_frame_interval(void *viewer, float interval); +void* get_renderer(void *viewer); +void update_viewport_and_camera_projection(void *viewer, int width, int height, float scaleFactor); +void scroll_begin(void *viewer); +void scroll_update(void *viewer, float x, float y, float z); +void scroll_end(void *viewer); -typedef struct BoneAnimation BoneAnimation; +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* filament_viewer_new(void* context, ResourceBuffer (*loadResource)(const char*), void (*freeResource)(uint32_t)); -void filament_viewer_delete(void* viewer); -void create_render_target(void* viewer, uint32_t textureId, uint32_t width, uint32_t height); -void clear_background_image(void* viewer); -void set_background_image(void* viewer, const char* path); -void set_background_image_position(void* viewer, float x, float y, bool clamp); -void set_background_color(void* viewer, const float r, const float g, const float b, const float a); - -void load_skybox(void* viewer, const char* skyboxPath); -void load_ibl(void* viewer, const char* iblPath, float intensity); -void remove_skybox(void* viewer); -void remove_ibl(void* viewer); -int32_t add_light(void* viewer, uint8_t type, float colour, float intensity, float posX, float posY, float posZ, float dirX, float dirY, float dirZ, bool shadows); -void remove_light(void* viewer, int32_t entityId); -void clear_lights(void* viewer); -void* load_glb(void* viewer, const char* assetPath, bool unlit); -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, uint64_t frameTimeInNanos); -void create_swap_chain(void* viewer, void* surface, uint32_t width, uint32_t height); -void destroy_swap_chain(void* viewer); -void set_frame_interval(void* viewer, float interval); -void* get_renderer(void* viewer); -void update_viewport_and_camera_projection(void* viewer, int width, int height, float scaleFactor); - -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, 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, const char* const entityName, float* const weights, int count); - -void set_animation( - void* asset, - const char* const entityName, - const float* const morphData, - int numMorphWeights, - const BoneAnimation* const boneAnimations, - int numBoneAnimations, - int numFrames, - float frameLengthInMs +void apply_weights( + void* assetManager, + EntityId asset, + const char *const entityName, + float *const weights, + int count ); +void set_morph_animation( + void* assetManager, + EntityId asset, + const char *const entityName, + const float *const morphData, + int numMorphWeights, + int numFrames, + float frameLengthInMs); + + void set_bone_animation( + void* assetManager, + EntityId asset, + int length, + const char** const boneNames, + const char** const meshNames, + const float* const frameData, + int numFrames, + float frameLengthInMs); + // void set_bone_transform( -// void* asset, -// const char* boneName, +// EntityId asset, +// const char* boneName, // const char* entityName, -// float transX, -// float transY, -// float transZ, +// float transX, +// float transY, +// float transZ, // float quatX, // float quatY, // float quatZ, // float quatW // ); - -void play_animation(void* asset, int index, bool loop, bool reverse); -void set_animation_frame(void* asset, int animationIndex, int animationFrame); -void stop_animation(void* asset, int index); -int get_animation_count(void* asset); - -void get_animation_name(void* asset, char* const outPtr, int index); +void play_animation(void* assetManager, EntityId asset, int index, bool loop, bool reverse); +void set_animation_frame(void* assetManager, EntityId asset, int animationIndex, int animationFrame); +void stop_animation(void* assetManager, EntityId asset, int index); +int get_animation_count(void* assetManager, EntityId asset); +void get_animation_name(void* assetManager, EntityId asset, char *const outPtr, int index); +void get_morph_target_name(void* assetManager, EntityId asset, const char *meshName, char *const outPtr, int index); +int get_morph_target_name_count(void* assetManager, EntityId asset, const char *meshName); +void remove_asset(void *viewer, EntityId asset); +void clear_assets(void *viewer); +void load_texture(void* assetManager, EntityId asset, const char *assetPath, int renderableIndex); +void set_texture(void* assetManager, EntityId asset); +void transform_to_unit_cube(void* assetManager, EntityId asset); +void set_position(void* assetManager, EntityId asset, float x, float y, float z); +void set_rotation(void* assetManager, EntityId asset, float rads, float x, float y, float z); +void set_scale(void* assetManager, EntityId asset, float scale); +void set_camera_exposure(void *viewer, float aperture, float shutterSpeed, float sensitivity); +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_model_matrix(void *viewer, const float *const matrix); +void set_camera_focal_length(void *viewer, float focalLength); +void set_camera_focus_distance(void *viewer, float focusDistance); -void get_morph_target_name(void* asset, const char* meshName, char* const outPtr, int index ); - -int get_morph_target_name_count(void* asset, const char* meshName); - -void remove_asset(void* viewer, void* asset); - -void clear_assets(void* viewer); - -void load_texture(void* asset, const char* assetPath, int renderableIndex); -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_exposure(void* viewer, float aperture, float shutterSpeed, float sensitivity); -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_model_matrix(void* viewer, const float* const matrix); -void set_camera_focal_length(void* viewer, float focalLength); -void set_camera_focus_distance(void* viewer, float focusDistance); - #endif diff --git a/ios/include/PolyvoxFilamentIOSApi.h b/ios/include/PolyvoxFilamentIOSApi.h index 5da32c15..367a2df2 100644 --- a/ios/include/PolyvoxFilamentIOSApi.h +++ b/ios/include/PolyvoxFilamentIOSApi.h @@ -1,2 +1,2 @@ -void* filament_viewer_new_ios(void* texture, void* loadResource, void* freeResource, void* resources); +void* create_filament_viewer_ios(void* texture, void* loadResource, void* freeResource, void* resources); diff --git a/ios/include/ResourceManagement.hpp b/ios/include/ResourceManagement.hpp index 51fe7f2d..2087d7d2 100644 --- a/ios/include/ResourceManagement.hpp +++ b/ios/include/ResourceManagement.hpp @@ -15,7 +15,7 @@ namespace polyvox { // // Typedef for a function that loads a resource into a ResourceBuffer from an asset URI. // - using LoadResource = function; + using LoadResource = function; // // Typedef for a function that frees an ID associated with a ResourceBuffer. diff --git a/ios/include/SceneAsset.hpp b/ios/include/SceneAsset.hpp index 92e79b19..fcbb1307 100644 --- a/ios/include/SceneAsset.hpp +++ b/ios/include/SceneAsset.hpp @@ -11,14 +11,12 @@ #include #include +#include #include -#include #include - #include #include "ResourceManagement.hpp" -#include "SceneAssetAnimation.hpp" extern "C" { #include "PolyvoxFilamentApi.h" @@ -30,121 +28,88 @@ namespace polyvox { using namespace utils; using namespace std; - class SceneAsset { - friend class SceneAssetLoader; - public: - SceneAsset(FilamentAsset* asset, Engine* engine, NameComponentManager* ncm, LoadResource loadResource, FreeResource freeResource); - ~SceneAsset(); - - unique_ptr> getMorphTargetNames(const char* meshName); - unique_ptr> getAnimationNames(); - - /// - /// - /// - void loadTexture(const char* resourcePath, int renderableIndex); - void setTexture(); - - /// - /// Update the bone/morph target animations to reflect the current frame (if applicable). - /// - void updateAnimations(); - - /// - /// Immediately stop the animation at the specified index. Noop if no animation is playing. - /// - void stopAnimation(int index); - - /// - /// Play the embedded animation (i.e. animation node embedded in the GLTF asset) under the specified index. If [loop] is true, the animation will repeat indefinitely. - /// - void playAnimation(int index, bool loop, bool reverse); - - void setAnimationFrame(int animationIndex, int animationFrame); - - /// - /// Set the weights for all [count] morph targets in this asset's entity named [inst] to [weights]. - /// See [setAnimation] if you want to do the same across a number of frames (and extended to bone transforms). - /// - void setMorphTargetWeights(const char* const entityName, float* weights, int count); - - /// - /// Animates the asset's morph targets/bone transforms according to the frame weights/transforms specified in [morphData]/[boneData]. - /// The duration of each "frame" is specified by [frameLengthInMs] (i.e. this is not the framerate of the renderer). - /// [morphData] is a contiguous chunk of floats whose length will be (numMorphWeights * numFrames). - /// [boneData] is a contiguous chunk of floats whose length will be (numBones * 7 * numFrames) (where 7 is 3 floats for translation, 4 for quat rotation). - /// [morphData] and [boneData] will both be copied, so remember to free these after calling this function. - /// - void setAnimation( - const char* entityName, - const float* const morphData, - int numMorphWeights, - const BoneAnimation* const targets, - int numBoneAnimations, - int numFrames, - float frameLengthInMs - ); - - size_t getBoneIndex(const char* name); - - Entity getNode(const char* name); - - void transformToUnitCube(); - - void setScale(float scale); - - void setPosition(float x, float y, float z); - - void setRotation(float rads, float x, float y, float z); - - const utils::Entity* getCameraEntities(); - - size_t getCameraEntityCount(); - - const Entity* getLightEntities() const noexcept; - - size_t getLightEntityCount() const noexcept; - - - private: - - FilamentAsset* _asset = nullptr; - Engine* _engine = nullptr; - NameComponentManager* _ncm; - - void setBoneTransform( - uint8_t skinIndex, - const vector& boneIndices, - const vector& targets, - const vector data, - int frameNumber - ); - - void updateRuntimeAnimation(); - - void updateEmbeddedAnimations(); - - Animator* _animator; - - // animation flags; - unique_ptr _runtimeAnimationBuffer; - vector _embeddedAnimationStatus; - - LoadResource _loadResource; - FreeResource _freeResource; - - // a slot to preload textures - filament::Texture* _texture = nullptr; - - // initialized to identity - math::mat4f _position; - - // initialized to identity - math::mat4f _rotation; - - float _scale = 1; - - void updateTransform(); + typedef std::chrono::time_point time_point_t; + struct AnimationStatus { + time_point_t mStart = time_point_t::max(); + bool mLoop = false; + bool mReverse = false; + float mDuration = 0; + int mFrameNumber = -1; }; + + // + // Use this to manually construct a buffer of frame data for morph animations. + // + struct MorphAnimationBuffer { + utils::EntityInstance* mInstance = nullptr; + int mNumFrames = -1; + float mFrameLengthInMs = 0; + vector mFrameData; + int mNumMorphWeights = 0; + }; + + /// + /// Frame data for the bones/meshes specified by [mBoneIndices] and [mMeshTargets]. + /// This is mainly used as a wrapper for animation data being transferred from the Dart to the native side. + /// + struct BoneAnimationData { + size_t skinIndex = 0; + uint8_t mBoneIndex; + utils::Entity mMeshTarget; + vector mFrameData; + }; + + // + // Use this to manually construct a buffer of frame data for bone animations. + // + struct BoneAnimationBuffer { + int mNumFrames = -1; + float mFrameLengthInMs = 0; + vector mAnimations; + }; + + struct SceneAsset { + + FilamentAsset* mAsset = nullptr; + Animator* mAnimator = nullptr; + + // animation flags; + bool mAnimating = false; + + // fixed-sized vector containing the status of the morph, bone and GLTF animations. + // entries 0 and 1 are the morph/bone animations. + // subsequent entries are the GLTF animations. + vector mAnimations; + + MorphAnimationBuffer mMorphAnimationBuffer; + BoneAnimationBuffer mBoneAnimationBuffer; + + // a slot to preload textures + filament::Texture* mTexture = nullptr; + + // initialized to identity + math::mat4f mPosition; + + // initialized to identity + math::mat4f mRotation; + + float mScale = 1; + + SceneAsset( + FilamentAsset* asset + ) : mAsset(asset) { + + mAnimator = mAsset->getInstance()->getAnimator(); + + mAnimations.resize(2 + mAnimator->getAnimationCount()); + + for(int i=2; i < mAnimations.size(); i++) { + mAnimations[i].mDuration = mAnimator->getAnimationDuration(i-2); + } + } + }; + } + + \ No newline at end of file diff --git a/ios/include/SceneAssetAnimation.hpp b/ios/include/SceneAssetAnimation.hpp deleted file mode 100644 index 901f06fc..00000000 --- a/ios/include/SceneAssetAnimation.hpp +++ /dev/null @@ -1,118 +0,0 @@ -#ifndef SCENE_ASSET_ANIMATION_H_ -#define SCENE_ASSET_ANIMATION_H_ - -#include "utils/Entity.h" -#include - -namespace polyvox { - - using namespace std; - - using Instance = utils::EntityInstance; - - typedef std::chrono::time_point time_point_t; - - // - // Holds the current state of a GLTF animation. - // Whenever a SceneAsset is created, an instance of GLTFAnimation will be created for every embedded animation. - // On each frame loop, we check if [play] is true, and if so, advance the animation to the correct frame based on [startedAt]. - // The [GLTFAnimation] will persist for the lifetime of the SceneAsset. - // - struct GLTFAnimation { - GLTFAnimation(bool loop, bool reverse) : loop(loop), reverse(reverse) {} - - // - // A flag that is checked each frame to determine whether or not the animation should play. - // - bool play = false; - - // - // If [play] is true, this flag will be checked when the animation is complete. If true, the animation will restart. - // - bool loop = false; - - // - // If true, the animation will be played in reverse. - // - bool reverse = false; - - // - // If [play] is true, this flag will be set to true when the animation is started. - // - bool started = false; - - // - // The index of the animation in the GLTF asset. - // - int animationIndex = -1; - - // - // The time point at which this animation was last started. - // This is used to calculate the "animation time offset" that is passed to the Animator. - // - time_point_t startedAt; - - }; - - /// - /// Holds a single set of frame data that may be used to animate multiple bones/meshes. - /// - struct BoneTransformTarget { - - size_t skinIndex = 0; - unique_ptr> mBoneIndices; - unique_ptr> mMeshTargets; - unique_ptr> mBoneData; - - BoneTransformTarget( - unique_ptr>& boneIndices, - unique_ptr>& meshTargets, - unique_ptr>& boneData) : mBoneIndices(move(boneIndices)), mMeshTargets(move(meshTargets)), mBoneData(move(boneData)) {} - - }; - - // - // An animation created by manually passing frame data for morph weights/bone transforms. - // - struct RuntimeAnimation { - - Instance mInstance; - - int frameNumber = -1; - int mNumFrames = -1; - float mFrameLengthInMs = 0; - time_point_t startTime; - - - float* mMorphFrameData = nullptr; - int mNumMorphWeights = 0; - - unique_ptr> mTargets; - - RuntimeAnimation(Instance instance, - const float* const morphData, - int numMorphWeights, - unique_ptr>& targets, - int numFrames, - float frameLengthInMs) : - mInstance(instance), - mNumFrames(numFrames), - mFrameLengthInMs(frameLengthInMs), - mNumMorphWeights(numMorphWeights), - mTargets(move(targets)) { - - if(numMorphWeights > 0) { - size_t morphSize = numMorphWeights * mNumFrames * sizeof(float); - mMorphFrameData = (float*)malloc(morphSize); - memcpy(mMorphFrameData, morphData, morphSize); - } - } - - ~RuntimeAnimation() { - delete(mMorphFrameData); - } - }; - -} - -#endif diff --git a/ios/include/SceneAssetLoader.hpp b/ios/include/SceneAssetLoader.hpp deleted file mode 100644 index dbb0dfa3..00000000 --- a/ios/include/SceneAssetLoader.hpp +++ /dev/null @@ -1,47 +0,0 @@ -#pragma once - -#include - -#include -#include -#include - -#include "ResourceManagement.hpp" -#include "SceneAsset.hpp" -#include "ResourceBuffer.hpp" - -namespace polyvox { - using namespace filament; - using namespace filament::gltfio; - using namespace utils; - - class SceneAssetLoader { - public: - SceneAssetLoader( - LoadResource loadResource, - FreeResource freeResource, - MaterialProvider* materialProvider, - EntityManager* entityManager, - ResourceLoader* resourceLoader, - NameComponentManager* ncm, - Engine* engine, - Scene* scene); - ~SceneAssetLoader(); - SceneAsset* fromGltf(const char* uri, const char* relativeResourcePath); - SceneAsset* fromGlb(const char* uri); - void remove(SceneAsset* asset); - void destroyAll(); - - private: - LoadResource _loadResource; - FreeResource _freeResource; - AssetLoader* _assetLoader; - ResourceLoader* _resourceLoader; - NameComponentManager* _ncm; - Engine* _engine; - Scene* _scene; - - vector _assets; - - }; -} diff --git a/ios/include/TimeIt.hpp b/ios/include/TimeIt.hpp new file mode 100644 index 00000000..33ad998a --- /dev/null +++ b/ios/include/TimeIt.hpp @@ -0,0 +1,32 @@ +#ifndef TIMEIT_H_ +#define TIMEIT_H_ + +#pragma once + +#if __cplusplus <= 199711L + #include +#else + #include +#endif + +class Timer +{ + public: + + Timer() { reset(); } + void reset(); + double elapsed(); + + private: + +#if __cplusplus <= 199711L + timespec beg_, end_; +#else + typedef std::chrono::high_resolution_clock clock_; + typedef std::chrono::duration > second_; + std::chrono::time_point beg_; +#endif + +}; + +#endif // TIMEIT_H_ diff --git a/ios/include/material/FileMaterialProvider.hpp b/ios/include/material/FileMaterialProvider.hpp index 885e1650..f4a41c2e 100644 --- a/ios/include/material/FileMaterialProvider.hpp +++ b/ios/include/material/FileMaterialProvider.hpp @@ -4,6 +4,10 @@ #include #include #include +#include +#include +#include +#include namespace polyvox { class FileMaterialProvider : public MaterialProvider { @@ -36,9 +40,8 @@ namespace polyvox { return hasTexture ? int(uvmap->at(srcIndex)) - 1 : -1; }; - Log("CREATING MATERIAL INSTANCE"); auto instance = _m->createInstance(); - mat3f identity; + math::mat3f identity; instance->setParameter("baseColorUvMatrix", identity); instance->setParameter("normalUvMatrix", identity); diff --git a/ios/include/material/UnlitMaterialProvider.hpp b/ios/include/material/UnlitMaterialProvider.hpp index d0477b2c..c2d7d4fe 100644 --- a/ios/include/material/UnlitMaterialProvider.hpp +++ b/ios/include/material/UnlitMaterialProvider.hpp @@ -1,5 +1,8 @@ #ifndef UNLIT_MATERIAL_PROVIDER #define UNLIT_MATERIAL_PROVIDER + +#include "material/unlit_opaque.h" + namespace polyvox { class UnlitMaterialProvider : public MaterialProvider { diff --git a/ios/src/AssetManager.cpp b/ios/src/AssetManager.cpp new file mode 100644 index 00000000..2bd4cf7c --- /dev/null +++ b/ios/src/AssetManager.cpp @@ -0,0 +1,777 @@ +#include "AssetManager.hpp" +#include "Log.hpp" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include "StreamBufferAdapter.hpp" +#include "SceneAsset.hpp" +#include "Log.hpp" +#include "ResourceManagement.hpp" +#include "material/UnlitMaterialProvider.hpp" +#include "material/FileMaterialProvider.hpp" +#include "gltfio/materials/uberarchive.h" + +extern "C" { + #include "material/image.h" + #include "material/unlit_opaque.h" +} + +namespace polyvox { + +using namespace std; +using namespace std::chrono; +using namespace image; +using namespace utils; +using namespace filament; +using namespace filament::gltfio; + +AssetManager::AssetManager(LoadResource loadResource, + FreeResource freeResource, + NameComponentManager *ncm, + Engine *engine, + Scene *scene) + : _loadResource(loadResource), + _freeResource(freeResource), + _ncm(ncm), + _engine(engine), + _scene(scene) { + + _stbDecoder = createStbProvider(_engine); + + _gltfResourceLoader = new ResourceLoader({.engine = _engine, + .normalizeSkinningWeights = true }); + _ubershaderProvider = gltfio::createUbershaderProvider( + _engine, UBERARCHIVE_DEFAULT_DATA, UBERARCHIVE_DEFAULT_SIZE); + EntityManager &em = EntityManager::get(); + _assetLoader = AssetLoader::create({_engine, _ubershaderProvider, _ncm, &em }); + _unlitProvider = new UnlitMaterialProvider(_engine); + + _gltfResourceLoader->addTextureProvider("image/png", _stbDecoder); + _gltfResourceLoader->addTextureProvider("image/jpeg", _stbDecoder); + } + +AssetManager::~AssetManager() { + _gltfResourceLoader->asyncCancelLoad(); + _ubershaderProvider->destroyMaterials(); + _unlitProvider->destroyMaterials(); + destroyAll(); + AssetLoader::destroy(&_assetLoader); + +} + +EntityId AssetManager::loadGltf(const char *uri, + const char *relativeResourcePath) { + ResourceBuffer rbuf = _loadResource(uri); + + // Parse the glTF file and create Filament entities. + FilamentAsset *asset = + _assetLoader->createAsset((uint8_t *)rbuf.data, rbuf.size); + + if (!asset) { + Log("Unable to parse asset"); + return 0; + } + + const char *const *const resourceUris = asset->getResourceUris(); + const size_t resourceUriCount = asset->getResourceUriCount(); + + for (size_t i = 0; i < resourceUriCount; i++) { + string uri = + string(relativeResourcePath) + string("/") + string(resourceUris[i]); + ResourceBuffer buf = _loadResource(uri.c_str()); + + // using FunctionCallback = std::function; auto cb = [&] (void * ptr, unsigned int len, void * misc) { + // }; + // FunctionCallback fcb = cb; + + ResourceLoader::BufferDescriptor b(buf.data, buf.size); + _gltfResourceLoader->addResourceData(resourceUris[i], std::move(b)); + _freeResource(buf.id); + } + + _gltfResourceLoader->loadResources(asset); + const utils::Entity *entities = asset->getEntities(); + RenderableManager &rm = _engine->getRenderableManager(); + for (int i = 0; i < asset->getEntityCount(); i++) { + auto inst = rm.getInstance(entities[i]); + rm.setCulling(inst, false); + } + + FilamentInstance* inst = asset->getInstance(); + inst->getAnimator()->updateBoneMatrices(); + inst->recomputeBoundingBoxes(); + + _scene->addEntities(asset->getEntities(), asset->getEntityCount()); + + asset->releaseSourceData(); + + Log("Load complete for GLTF at URI %s", uri); + SceneAsset sceneAsset(asset); + utils::Entity e = EntityManager::get().create(); + + EntityId eid = Entity::smuggle(e); + + _assets.emplace(eid, sceneAsset); + + return eid; +} + +EntityId AssetManager::loadGlb(const char *uri, bool unlit) { + + Log("Loading GLB at URI %s", uri); + _loadResource("BLORTY"); + Log("blorty"); + + ResourceBuffer rbuf = _loadResource(uri); + + FilamentAsset *asset = _assetLoader->createAsset( + (const uint8_t *)rbuf.data, rbuf.size); + + if (!asset) { + Log("Unknown error loading GLB asset."); + return 0; + } + + int entityCount = asset->getEntityCount(); + + _scene->addEntities(asset->getEntities(), entityCount); + + _gltfResourceLoader->loadResources(asset); + + // const Entity *entities = asset->getEntities(); + + // RenderableManager &rm = _engine->getRenderableManager(); + + // MaterialKey config; + // auto mi_new = _materialProvider->createMaterialInstance(&config, nullptr); + + // for (int i = 0; i < asset->getEntityCount(); i++) { + // auto entityInstance = rm.getInstance(entities[i]); + // auto mi = rm.getMaterialInstanceAt(entityInstance, 0); + // // auto m = mi->getMaterial(); + // // auto shading = m->getShading(); + // // Log("Shading %d", shading); + // } + + auto lights = asset->getLightEntities(); + _scene->addEntities(lights, asset->getLightEntityCount()); + + FilamentInstance* inst = asset->getInstance(); + + inst->getAnimator()->updateBoneMatrices(); + + inst->recomputeBoundingBoxes(); + + asset->releaseSourceData(); + + _freeResource(rbuf.id); + + SceneAsset sceneAsset(asset); + + utils::Entity e = EntityManager::get().create(); + EntityId eid = Entity::smuggle(e); + + _assets.emplace(eid, sceneAsset); + + return eid; +} + +void AssetManager::destroyAll() { + for (auto kp : _assets) { + auto asset = kp.second; + _scene->removeEntities(asset.mAsset->getEntities(), + asset.mAsset->getEntityCount()); + + _scene->removeEntities(asset.mAsset->getLightEntities(), + asset.mAsset->getLightEntityCount()); + + _gltfResourceLoader->evictResourceData(); + _assetLoader->destroyAsset(asset.mAsset); + } + _assets.clear(); +} + +FilamentAsset* AssetManager::getAssetByEntityId(EntityId entityId) { + const auto& pos = _assets.find(entityId); + if(pos == _assets.end()) { + return nullptr; + } + return pos->second.mAsset; +} + + +void AssetManager::updateAnimations() { + auto now = high_resolution_clock::now(); + + RenderableManager &rm = _engine->getRenderableManager(); + + for (auto kp : _assets) { + auto asset = kp.second; + if(asset.mAnimating) { + + asset.mAnimating = false; + + // morph animation + AnimationStatus morphAnimation = asset.mAnimations[0]; + auto elapsed = (now - morphAnimation.mStart).count(); + + int lengthInFrames = static_cast(morphAnimation.mDuration / asset.mMorphAnimationBuffer.mFrameLengthInMs); + + if(elapsed >= morphAnimation.mDuration) { + if(morphAnimation.mLoop) { + morphAnimation.mStart = now; + if(morphAnimation.mReverse) { + morphAnimation.mFrameNumber = lengthInFrames; + } + asset.mAnimating = true; + } else { + morphAnimation.mStart = time_point_t::max(); + } + } else { + asset.mAnimating = true; + } + + int frameNumber = static_cast(elapsed / asset.mMorphAnimationBuffer.mFrameLengthInMs); + if(frameNumber < lengthInFrames) { + if(morphAnimation.mReverse) { + frameNumber = lengthInFrames - frameNumber; + } + rm.setMorphWeights( + *(asset.mMorphAnimationBuffer.mInstance), + asset.mMorphAnimationBuffer.mFrameData.data() + (morphAnimation.mFrameNumber * asset.mMorphAnimationBuffer.mNumMorphWeights), + asset.mMorphAnimationBuffer.mNumMorphWeights); + } + + // bone animation + AnimationStatus boneAnimation = asset.mAnimations[1]; + elapsed = (now - boneAnimation.mStart).count(); + + lengthInFrames = static_cast(boneAnimation.mDuration / asset.mBoneAnimationBuffer.mFrameLengthInMs); + + if(elapsed >= boneAnimation.mDuration) { + if(boneAnimation.mLoop) { + boneAnimation.mStart = now; + if(boneAnimation.mReverse) { + boneAnimation.mFrameNumber = lengthInFrames; + } + asset.mAnimating = true; + } else { + boneAnimation.mStart = time_point_t::max(); + } + } else { + asset.mAnimating = true; + } + + frameNumber = static_cast(elapsed / asset.mBoneAnimationBuffer.mFrameLengthInMs); + if(frameNumber < lengthInFrames) { + if(boneAnimation.mReverse) { + frameNumber = lengthInFrames - frameNumber; + } + boneAnimation.mFrameNumber = frameNumber; + setBoneTransform( + asset.mAsset->getInstance(), + asset.mBoneAnimationBuffer.mAnimations, + frameNumber + ); + } + + // GLTF animations + + Animator* animator = asset.mAnimator; + + for(int j = 2; j < asset.mAnimations.size(); j++) { + + AnimationStatus anim = asset.mAnimations[j]; + + elapsed = (now - anim.mStart).count(); + + if(elapsed < anim.mDuration) { + if(anim.mLoop) { + animator->applyAnimation(j-2, anim.mDuration - elapsed); + } else { + animator->applyAnimation(j-2, elapsed); + } + asset.mAnimating = true; + } else if(anim.mLoop) { + animator->applyAnimation(j-2, float(elapsed) ); //% anim.mDuration + asset.mAnimating = true; + } else if(elapsed - anim.mDuration < 0.3) { + // cross-fade + animator->applyCrossFade(j-2, anim.mDuration - 0.05, elapsed / 0.3); + asset.mAnimating = true; + } else { + // stop + anim.mStart = time_point_t::max(); + } + } + asset.mAnimator->updateBoneMatrices(); + } + } +} + +void AssetManager::remove(EntityId entityId) { + const auto& pos = _assets.find(entityId); + if(pos == _assets.end()) { + Log("Couldn't find asset under specified entity id."); + return; + } + auto sceneAsset = pos->second; + + _scene->removeEntities(sceneAsset.mAsset->getEntities(), + sceneAsset.mAsset->getEntityCount()); + + _scene->removeEntities(sceneAsset.mAsset->getLightEntities(), + sceneAsset.mAsset->getLightEntityCount()); + + _assetLoader->destroyAsset(sceneAsset.mAsset); + + if(sceneAsset.mTexture) { + _engine->destroy(sceneAsset.mTexture); + } + EntityManager& em = EntityManager::get(); + em.destroy(Entity::import(entityId)); + _assets.erase(entityId); +} + +void AssetManager::setMorphTargetWeights(const char* const entityName, float *weights, int count) { + // TODO +} + +utils::Entity AssetManager::findEntityByName(SceneAsset asset, const char* entityName) { + utils::Entity entity; + for (size_t i = 0, c = asset.mAsset->getEntityCount(); i != c; ++i) { + auto entity = asset.mAsset->getEntities()[i]; + auto name = _ncm->getName(_ncm->getInstance(entity)); + + if(strcmp(entityName,name)==0) { + return entity; + } + } + return entity; +} + + +bool AssetManager::setMorphAnimationBuffer( + EntityId entityId, + const char* entityName, + const float* const morphData, + int numMorphWeights, + int numFrames, + float frameLengthInMs) { + + const auto& pos = _assets.find(entityId); + if(pos == _assets.end()) { + Log("ERROR: asset not found for entity."); + return false; + } + auto asset = pos->second; + + auto entity = findEntityByName(asset, entityName); + if(!entity) { + Log("Warning: failed to find entity %s", entityName); + return false; + } + RenderableManager &rm = _engine->getRenderableManager(); + auto inst = rm.getInstance(entity); + + asset.mMorphAnimationBuffer.mInstance = &inst; + asset.mMorphAnimationBuffer.mNumFrames = numFrames; + asset.mMorphAnimationBuffer.mFrameLengthInMs = frameLengthInMs; + asset.mMorphAnimationBuffer.mFrameData.clear(); + asset.mMorphAnimationBuffer.mFrameData.insert( + asset.mMorphAnimationBuffer.mFrameData.begin(), + morphData, + morphData + (numFrames * numMorphWeights) + ); + + asset.mMorphAnimationBuffer.mNumMorphWeights = numMorphWeights; + return true; +} + +bool AssetManager::setBoneAnimationBuffer( + EntityId entity, + int length, + const char** const boneNames, + const char** const meshNames, + const float* const frameData, + int numFrames, + float frameLengthInMs) { + + const auto& pos = _assets.find(entity); + if(pos == _assets.end()) { + Log("ERROR: asset not found for entity."); + return false; + } + auto asset = pos->second; + + auto filamentInstance = asset.mAsset->getInstance(); + + size_t skinCount = filamentInstance->getSkinCount(); + + if(skinCount > 1) { + Log("WARNING - skin count > 1 not currently implemented. This will probably not work"); + } + + int skinIndex = 0; + const utils::Entity* joints = filamentInstance->getJointsAt(skinIndex); + size_t numJoints = filamentInstance->getJointCountAt(skinIndex); + vector boneIndices; + for(int i = 0; i < length; i++) { + for(int j = 0; j < numJoints; j++) { + const char* jointName = _ncm->getName(_ncm->getInstance(joints[j])); + if(strcmp(jointName, boneNames[i]) == 0) { + boneIndices.push_back(j); + break; + } + } + } + + if(boneIndices.size() != length) { + Log("Failed to find one or more bone indices"); + return false; + } + + asset.mBoneAnimationBuffer.mAnimations.clear(); + + for(int i = 0; i < length; i++) { + BoneAnimationData boneAnimationData; + boneAnimationData.mBoneIndex = boneIndices[i]; + + auto entity = findEntityByName(asset, meshNames[i]); + + if(!entity) { + Log("Mesh target %s for bone animation could not be found", meshNames[i]); + return false; + } + + boneAnimationData.mMeshTarget = entity; + + boneAnimationData.mFrameData.insert( + boneAnimationData.mFrameData.begin(), + frameData[i * numFrames * 7 * sizeof(float)], // 7 == x, y, z, w + three euler angles + frameData[(i+1) * numFrames * 7 * sizeof(float)] + ); + + asset.mBoneAnimationBuffer.mAnimations.push_back(boneAnimationData); + } + return true; +} + +void AssetManager::setBoneTransform( + FilamentInstance* filamentInstance, + vector animations, + int frameNumber) { + + RenderableManager &rm = _engine->getRenderableManager(); + + TransformManager &transformManager = _engine->getTransformManager(); + + auto frameDataOffset = frameNumber * 7; + + int skinIndex = 0; + + for(auto& animation : animations) { + + math::mat4f inverseGlobalTransform = inverse( + transformManager.getWorldTransform( + transformManager.getInstance(animation.mMeshTarget) + ) + ); + + utils::Entity joint = filamentInstance->getJointsAt(skinIndex)[animation.mBoneIndex]; + + math::mat4f localTransform(math::quatf{ + animation.mFrameData[frameDataOffset+6], + animation.mFrameData[frameDataOffset+3], + animation.mFrameData[frameDataOffset+4], + animation.mFrameData[frameDataOffset+5] + }); + + const math::mat4f& inverseBindMatrix = filamentInstance->getInverseBindMatricesAt(animation.skinIndex)[animation.mBoneIndex]; + auto jointInstance = transformManager.getInstance(joint); + math::mat4f globalJointTransform = transformManager.getWorldTransform(jointInstance); + + math::mat4f boneTransform = inverseGlobalTransform * globalJointTransform * localTransform * inverseBindMatrix; + auto renderable = rm.getInstance(animation.mMeshTarget); + rm.setBones( + renderable, + &boneTransform, + 1, + animation.mBoneIndex + ); + } +} + +void AssetManager::playAnimation(EntityId e, int index, bool loop, bool reverse) { + const auto& pos = _assets.find(e); + if(pos == _assets.end()) { + Log("ERROR: asset not found for entity."); + return; + } + auto asset = pos->second; + + asset.mAnimations[index+2].mStart = high_resolution_clock::now(); + asset.mAnimations[index+2].mLoop = loop; + asset.mAnimations[index+2].mReverse = reverse; +} + +void AssetManager::stopAnimation(EntityId entityId, int index) { + const auto& pos = _assets.find(entityId); + if(pos == _assets.end()) { + Log("ERROR: asset not found for entity."); + return; + } + auto asset = pos->second; + asset.mAnimations[index+2].mStart = time_point_t::max(); +} + +void AssetManager::loadTexture(EntityId entity, const char* resourcePath, int renderableIndex) { + + const auto& pos = _assets.find(entity); + if(pos == _assets.end()) { + Log("ERROR: asset not found for entity."); + return; + } + auto asset = pos->second; + + Log("Loading texture at %s for renderableIndex %d", resourcePath, renderableIndex); + + string rp(resourcePath); + + if(asset.mTexture) { + _engine->destroy(asset.mTexture); + asset.mTexture = nullptr; + } + + ResourceBuffer imageResource = _loadResource(rp.c_str()); + + StreamBufferAdapter sb((char *)imageResource.data, (char *)imageResource.data + imageResource.size); + + istream *inputStream = new std::istream(&sb); + + LinearImage *image = new LinearImage(ImageDecoder::decode( + *inputStream, rp.c_str(), ImageDecoder::ColorSpace::SRGB)); + + if (!image->isValid()) { + Log("Invalid image : %s", rp.c_str()); + delete inputStream; + _freeResource(imageResource.id); + return; + } + + uint32_t channels = image->getChannels(); + uint32_t w = image->getWidth(); + uint32_t h = image->getHeight(); + asset.mTexture = Texture::Builder() + .width(w) + .height(h) + .levels(0xff) + .format(channels == 3 ? Texture::InternalFormat::RGB16F + : Texture::InternalFormat::RGBA16F) + .sampler(Texture::Sampler::SAMPLER_2D) + .build(*_engine); + + Texture::PixelBufferDescriptor::Callback freeCallback = [](void *buf, size_t, + void *data) { + delete reinterpret_cast(data); + }; + + Texture::PixelBufferDescriptor buffer( + image->getPixelRef(), size_t(w * h * channels * sizeof(float)), + channels == 3 ? Texture::Format::RGB : Texture::Format::RGBA, + Texture::Type::FLOAT, freeCallback); + + asset.mTexture->setImage(*_engine, 0, std::move(buffer)); + MaterialInstance* const* inst = asset.mAsset->getInstance()->getMaterialInstances(); + size_t mic = asset.mAsset->getInstance()->getMaterialInstanceCount(); + Log("Material instance count : %d", mic); + + auto sampler = TextureSampler(); + inst[0]->setParameter("baseColorIndex",0); + inst[0]->setParameter("baseColorMap",asset.mTexture,sampler); + delete inputStream; + + _freeResource(imageResource.id); + +} + + +void AssetManager::setAnimationFrame(EntityId entity, int animationIndex, int animationFrame) { + const auto& pos = _assets.find(entity); + if(pos == _assets.end()) { + Log("ERROR: asset not found for entity."); + return; + } + auto asset = pos->second; + auto offset = 60 * animationFrame * 1000; // TODO - don't hardcore 60fps framerate + asset.mAnimator->applyAnimation(animationIndex, offset); + asset.mAnimator->updateBoneMatrices(); +} + +unique_ptr> AssetManager::getAnimationNames(EntityId entity) { + + const auto& pos = _assets.find(entity); + + unique_ptr> names = make_unique>(); + + if(pos == _assets.end()) { + Log("ERROR: asset not found for entity id."); + return names; + } + auto asset = pos->second; + + size_t count = asset.mAnimator->getAnimationCount(); + + + for (size_t i = 0; i < count; i++) { + names->push_back(asset.mAnimator->getAnimationName(i)); + } + + return names; +} + +unique_ptr> AssetManager::getMorphTargetNames(EntityId entity, const char *meshName) { + + unique_ptr> names = make_unique>(); + + const auto& pos = _assets.find(entity); + if(pos == _assets.end()) { + Log("ERROR: asset not found for entity."); + return names; + } + auto asset = pos->second; + + const utils::Entity *entities = asset.mAsset->getEntities(); + + for (int i = 0; i < asset.mAsset->getEntityCount(); i++) { + utils::Entity e = entities[i]; + auto inst = _ncm->getInstance(e); + const char *name = _ncm->getName(inst); + + if (strcmp(name, meshName) == 0) { + size_t count = asset.mAsset->getMorphTargetCountAt(e); + for (int j = 0; j < count; j++) { + const char *morphName = asset.mAsset->getMorphTargetNameAt(e, j); + names->push_back(morphName); + } + break; + } + } + return names; +} + +void AssetManager::transformToUnitCube(EntityId entity) { + const auto& pos = _assets.find(entity); + if(pos == _assets.end()) { + Log("ERROR: asset not found for entity."); + return; + } + auto asset = pos->second; + + Log("Transforming asset to unit cube."); + auto &tm = _engine->getTransformManager(); + FilamentInstance* inst = asset.mAsset->getInstance(); + auto aabb = inst->getBoundingBox(); + auto center = aabb.center(); + auto halfExtent = aabb.extent(); + auto maxExtent = max(halfExtent) * 2; + auto scaleFactor = 2.0f / maxExtent; + auto transform = + math::mat4f::scaling(scaleFactor) * math::mat4f::translation(-center); + tm.setTransform(tm.getInstance(inst->getRoot()), transform); +} + +void AssetManager::updateTransform(SceneAsset asset) { + auto &tm = _engine->getTransformManager(); + auto transform = + asset.mPosition * asset.mRotation * math::mat4f::scaling(asset.mScale); + tm.setTransform(tm.getInstance(asset.mAsset->getRoot()), transform); +} + +void AssetManager::setScale(EntityId entity, float scale) { + const auto& pos = _assets.find(entity); + if(pos == _assets.end()) { + Log("ERROR: asset not found for entity."); + return; + } + auto asset = pos->second; + asset.mScale = scale; + updateTransform(asset); +} + +void AssetManager::setPosition(EntityId entity, float x, float y, float z) { + const auto& pos = _assets.find(entity); + if(pos == _assets.end()) { + Log("ERROR: asset not found for entity."); + return; + } + auto asset = pos->second; + asset.mPosition = math::mat4f::translation(math::float3(x,y,z)); + updateTransform(asset); +} + +void AssetManager::setRotation(EntityId entity, float rads, float x, float y, float z) { + const auto& pos = _assets.find(entity); + if(pos == _assets.end()) { + Log("ERROR: asset not found for entity."); + return; + } + auto asset = pos->second; + asset.mRotation = math::mat4f::rotation(rads, math::float3(x,y,z)); + updateTransform(asset); +} + +const utils::Entity *AssetManager::getCameraEntities(EntityId entity) { + const auto& pos = _assets.find(entity); + if(pos == _assets.end()) { + Log("ERROR: asset not found for entity."); + return nullptr; + } + auto asset = pos->second; + return asset.mAsset->getCameraEntities(); +} + +size_t AssetManager::getCameraEntityCount(EntityId entity) { + const auto& pos = _assets.find(entity); + if(pos == _assets.end()) { + Log("ERROR: asset not found for entity."); + return 0; + } + auto asset = pos->second; + return asset.mAsset->getCameraEntityCount(); +} + +const utils::Entity* AssetManager::getLightEntities(EntityId entity) const noexcept { + const auto& pos = _assets.find(entity); + if(pos == _assets.end()) { + Log("ERROR: asset not found for entity."); + return nullptr; + } + auto asset = pos->second; + return asset.mAsset->getLightEntities(); +} + +size_t AssetManager::getLightEntityCount(EntityId entity) const noexcept { + const auto& pos = _assets.find(entity); + if(pos == _assets.end()) { + Log("ERROR: asset not found for entity."); + return 0; + } + auto asset = pos->second; + return asset.mAsset->getLightEntityCount(); +} + + +} // namespace polyvox diff --git a/ios/src/FilamentViewer.cpp b/ios/src/FilamentViewer.cpp index 3b08af7a..feade990 100644 --- a/ios/src/FilamentViewer.cpp +++ b/ios/src/FilamentViewer.cpp @@ -70,17 +70,11 @@ #include #include "Log.hpp" -#include "ResourceManagement.hpp" - -extern "C" { - #include "material/image.h" - #include "material/unlit_opaque.h" -} #include "FilamentViewer.hpp" #include "StreamBufferAdapter.hpp" -#include "material/UnlitMaterialProvider.hpp" -#include "material/FileMaterialProvider.hpp" +#include "material/image.h" +#include "TimeIt.hpp" using namespace filament; using namespace filament::math; @@ -116,15 +110,13 @@ static const uint16_t sFullScreenTriangleIndices[3] = {0, 1, 2}; FilamentViewer::FilamentViewer(void* context, LoadResource loadResource, FreeResource freeResource) : _loadResource(loadResource), _freeResource(freeResource) { - Log("Creating FilamentViewer"); + #if TARGET_OS_IPHONE _engine = Engine::create(Engine::Backend::METAL); #else _engine = Engine::create(Engine::Backend::OPENGL, nullptr, context, nullptr); #endif - Log("Engine created"); - _renderer = _engine->createRenderer(); float fr = 60.0f; @@ -138,7 +130,7 @@ FilamentViewer::FilamentViewer(void* context, LoadResource loadResource, Log("Scene created"); - Entity camera = EntityManager::get().create(); + utils::Entity camera = EntityManager::get().create(); _mainCamera = _engine->createCamera(camera); @@ -191,38 +183,17 @@ FilamentViewer::FilamentViewer(void* context, LoadResource loadResource, // Log("Loaded resource of size %d", materialRb.size); // _materialProvider = new FileMaterialProvider(_engine, (void*) materialRb.data, (size_t)materialRb.size); - _unlitProvider = new UnlitMaterialProvider(_engine); - _ubershaderProvider = gltfio::createUbershaderProvider( - _engine, UBERARCHIVE_DEFAULT_DATA, UBERARCHIVE_DEFAULT_SIZE); - EntityManager &em = EntityManager::get(); + _ncm = new NameComponentManager(em); + + _assetManager = new AssetManager( + _loadResource, + _freeResource, + _ncm, + _engine, + _scene); - _resourceLoader = new ResourceLoader({.engine = _engine, - .normalizeSkinningWeights = true }); - _stbDecoder = createStbProvider(_engine); - _resourceLoader->addTextureProvider("image/png", _stbDecoder); - _resourceLoader->addTextureProvider("image/jpeg", _stbDecoder); - _ubershaderAssetLoader = new SceneAssetLoader(_loadResource, - _freeResource, - _ubershaderProvider, - &em, - _resourceLoader, - _ncm, - _engine, - _scene); - - _unlitAssetLoader = new SceneAssetLoader(_loadResource, - _freeResource, - _unlitProvider, - &em, - _resourceLoader, - - _ncm, - _engine, - _scene); - - _imageTexture = Texture::Builder() .width(1) .height(1) @@ -261,7 +232,7 @@ FilamentViewer::FilamentViewer(void* context, LoadResource loadResource, _imageIb->setBuffer(*_engine, {sFullScreenTriangleIndices, sizeof(sFullScreenTriangleIndices)}); - Entity imageEntity = em.create(); + utils::Entity imageEntity = em.create(); RenderableManager::Builder(1) .boundingBox({{}, {1.0f, 1.0f, 1.0f}}) .material(0, _imageMaterial->getDefaultInstance()) @@ -432,7 +403,6 @@ void FilamentViewer::clearBackgroundImage() { } } - void FilamentViewer::setBackgroundImage(const char *resourcePath) { string resourcePathString(resourcePath); @@ -535,11 +505,7 @@ void FilamentViewer::setBackgroundImagePosition(float x, float y, bool clamp=fal FilamentViewer::~FilamentViewer() { clearAssets(); - delete _ubershaderAssetLoader; - delete _unlitAssetLoader; - _resourceLoader->asyncCancelLoad(); - _ubershaderProvider->destroyMaterials(); - _unlitProvider->destroyMaterials(); + delete _assetManager; for(auto it : _lights) { _engine->destroy(it); @@ -616,36 +582,6 @@ void FilamentViewer::destroySwapChain() { } } -SceneAsset *FilamentViewer::loadGlb(const char *const uri, bool unlit) { - SceneAsset *asset; - if(unlit) { - asset = _unlitAssetLoader->fromGlb(uri); - } else { - asset = _ubershaderAssetLoader->fromGlb(uri); - } - if (!asset) { - Log("Unknown error loading asset."); - } else { - _assets.push_back(asset); - Log("GLB loaded, asset at index %d", _assets.size() - 1); - } - - return asset; -} - -SceneAsset *FilamentViewer::loadGltf(const char *const uri, - const char *const relativeResourcePath) { - Log("Loading GLTF at URI %s with relativeResourcePath %s", uri, - relativeResourcePath); - SceneAsset *asset = _ubershaderAssetLoader->fromGltf(uri, relativeResourcePath); - if (!asset) { - Log("Unknown error loading asset."); - } else { - _assets.push_back(asset); - } - return asset; -} - void FilamentViewer::clearAssets() { Log("Clearing all assets"); if(_mainCamera) { @@ -657,21 +593,18 @@ void FilamentViewer::clearAssets() { _manipulator = nullptr; } - _ubershaderAssetLoader->destroyAll(); - _unlitAssetLoader->destroyAll(); - - _assets.clear(); + _assetManager->destroyAll(); + Log("Cleared all assets"); } -void FilamentViewer::removeAsset(SceneAsset *asset) { +void FilamentViewer::removeAsset(EntityId asset) { Log("Removing asset from scene"); mtx.lock(); // todo - what if we are using a camera from this asset? _view->setCamera(_mainCamera); - _ubershaderAssetLoader->remove(asset); - _unlitAssetLoader->remove(asset); + _assetManager->remove(asset); mtx.unlock(); } @@ -704,65 +637,58 @@ void FilamentViewer::setCameraFocusDistance(float focusDistance) { } /// -/// Sets the active camera to the first GLTF camera node found in the hierarchy. -/// Useful when your asset only has one camera. -/// -bool FilamentViewer::setFirstCamera(SceneAsset *asset) { - size_t count = asset->getCameraEntityCount(); - if (count == 0) { - Log("Failed, no cameras found in current asset."); - return false; - } - const utils::Entity *cameras = asset->getCameraEntities(); - Log("%zu cameras found in asset", count); - auto inst = _ncm->getInstance(cameras[0]); - const char *name = _ncm->getName(inst); - return setCamera(asset, name); -} - -/// -/// Sets the active camera to the GLTF camera node specified by [name]. +/// Sets the active camera to the GLTF camera node specified by [name] (or if null, the first camera found under that node). /// N.B. Blender will generally export a three-node hierarchy - /// Camera1->Camera_Orientation->Camera2. The correct name will be the Camera_Orientation. /// -bool FilamentViewer::setCamera(SceneAsset *asset, const char *cameraName) { - Log("Attempting to set camera to %s.", cameraName); +bool FilamentViewer::setCamera(EntityId entityId, const char *cameraName) { + + auto asset = _assetManager->getAssetByEntityId(entityId); + if(!asset) { + Log("Failed to find asset attached to specified entity id."); + } size_t count = asset->getCameraEntityCount(); if (count == 0) { Log("Failed, no cameras found in current asset."); return false; } - const utils::Entity *cameras = asset->getCameraEntities(); - Log("%zu cameras found in asset", count); - for (int i = 0; i < count; i++) { + const utils::Entity* cameras = asset->getCameraEntities(); - auto inst = _ncm->getInstance(cameras[i]); - const char *name = _ncm->getName(inst); - Log("Camera %d : %s", i, name); - if (strcmp(name, cameraName) == 0) { + const utils::Entity target; - Camera *camera = _engine->getCameraComponent(cameras[i]); - _view->setCamera(camera); + int i = -1; - const Viewport &vp = _view->getViewport(); - const double aspect = (double)vp.width / vp.height; - - const float aperture = camera->getAperture(); - const float shutterSpeed = camera->getShutterSpeed(); - const float sens = camera->getSensitivity(); - - // camera->setExposure(1.0f); - - Log("Camera focal length : %f aspect %f aperture %f shutter %f sensitivity %f", camera->getFocalLength(), - aspect, aperture, shutterSpeed, sens); - camera->setScaling({1.0 / aspect, 1.0}); - Log("Successfully set camera."); - return true; + if(!cameraName) { + i = 0; + } else { + for (int j = 0; j < count; j++) { + auto inst = _ncm->getInstance(cameras[j]); + const char *name = _ncm->getName(inst); + if (strcmp(name, cameraName) == 0) { + i = j; + break; + } + } + if(i == -1) { + Log("Unable to locate camera under name %s ", cameraName); + return false; } } - Log("Unable to locate camera under name %s ", cameraName); - return false; + + Camera *camera = _engine->getCameraComponent(target); + _view->setCamera(camera); + + const Viewport &vp = _view->getViewport(); + const double aspect = (double)vp.width / vp.height; + + // const float aperture = camera->getAperture(); + // const float shutterSpeed = camera->getShutterSpeed(); + // const float sens = camera->getSensitivity(); + // camera->setExposure(1.0f); + + camera->setScaling({1.0 / aspect, 1.0}); + return true; } void FilamentViewer::loadSkybox(const char *const skyboxPath) { @@ -792,9 +718,6 @@ void FilamentViewer::loadSkybox(const char *const skyboxPath) { _scene->setSkybox(_skybox); _freeResource(skyboxBuffer.id); - - - } } @@ -856,6 +779,9 @@ void FilamentViewer::loadIbl(const char *const iblPath, float intensity) { } } +double _elapsed = 0; +int _frameCount = 0; + void FilamentViewer::render(uint64_t frameTimeInNanos) { if (!_view || !_mainCamera || !_swapChain) { @@ -863,10 +789,19 @@ void FilamentViewer::render(uint64_t frameTimeInNanos) { return; } - for (auto &asset : _assets) { - asset->updateAnimations(); + if(_frameCount == 60) { + Log("1 sec average for asset animation update %f", _elapsed); + _elapsed = 0; + _frameCount = 0; } + Timer tmr; + + _assetManager->updateAnimations(); + + _elapsed += tmr.elapsed(); + _frameCount++; + if(_manipulator) { math::float3 eye, target, upward; Camera& cam =_view->getCamera(); diff --git a/ios/src/PolyvoxFilamentApi.cpp b/ios/src/PolyvoxFilamentApi.cpp index 103556c9..11f827e3 100644 --- a/ios/src/PolyvoxFilamentApi.cpp +++ b/ios/src/PolyvoxFilamentApi.cpp @@ -6,180 +6,210 @@ using namespace polyvox; +#define FLUTTER_PLUGIN_EXPORT __attribute__((visibility("default"))) + extern "C" { #include "PolyvoxFilamentApi.h" - void* filament_viewer_new(void* context, ResourceBuffer (*loadResource)(char const*), void (*freeResource)(unsigned int)) { + FLUTTER_PLUGIN_EXPORT void* create_filament_viewer(void* context, ResourceBuffer (*loadResource)(char const*), void (*freeResource)(unsigned int)) { FilamentViewer* v = new FilamentViewer(context, loadResource, freeResource); return (void*)v; } - void create_render_target(void* viewer, uint32_t textureId, uint32_t width, uint32_t height) { + FLUTTER_PLUGIN_EXPORT void create_render_target(void* viewer, uint32_t textureId, uint32_t width, uint32_t height) { ((FilamentViewer*)viewer)->createRenderTarget(textureId, width, height); } - void filament_viewer_delete(void* viewer) { + FLUTTER_PLUGIN_EXPORT void delete_filament_viewer(void* viewer) { delete((FilamentViewer*)viewer); } - void set_background_color(void* viewer, const float r, const float g, const float b, const float a) { + FLUTTER_PLUGIN_EXPORT void set_background_color(void* viewer, const float r, const float g, const float b, const float a) { ((FilamentViewer*)viewer)->setBackgroundColor(r, g, b, a); } - void clear_background_image(void* viewer) { + FLUTTER_PLUGIN_EXPORT void clear_background_image(void* viewer) { ((FilamentViewer*)viewer)->clearBackgroundImage(); } - void set_background_image(void* viewer, const char* path) { + FLUTTER_PLUGIN_EXPORT void set_background_image(void* viewer, const char* path) { ((FilamentViewer*)viewer)->setBackgroundImage(path); } - void set_background_image_position(void* viewer, float x, float y, bool clamp) { + FLUTTER_PLUGIN_EXPORT void set_background_image_position(void* viewer, float x, float y, bool clamp) { ((FilamentViewer*)viewer)->setBackgroundImagePosition(x, y, clamp); } - void load_skybox(void* viewer, const char* skyboxPath) { + FLUTTER_PLUGIN_EXPORT void load_skybox(void* viewer, const char* skyboxPath) { ((FilamentViewer*)viewer)->loadSkybox(skyboxPath); } - void load_ibl(void* viewer, const char* iblPath, float intensity) { + FLUTTER_PLUGIN_EXPORT void load_ibl(void* viewer, const char* iblPath, float intensity) { ((FilamentViewer*)viewer)->loadIbl(iblPath, intensity); } - void remove_skybox(void* viewer) { + FLUTTER_PLUGIN_EXPORT void remove_skybox(void* viewer) { ((FilamentViewer*)viewer)->removeSkybox(); } - void remove_ibl(void* viewer) { + FLUTTER_PLUGIN_EXPORT void remove_ibl(void* viewer) { ((FilamentViewer*)viewer)->removeIbl(); } - int32_t add_light(void* viewer, uint8_t type, float colour, float intensity, float posX, float posY, float posZ, float dirX, float dirY, float dirZ, bool shadows) { + FLUTTER_PLUGIN_EXPORT int32_t add_light(void* viewer, uint8_t type, float colour, float intensity, float posX, float posY, float posZ, float dirX, float dirY, float dirZ, bool shadows) { return ((FilamentViewer*)viewer)->addLight((LightManager::Type)type, colour, intensity, posX, posY, posZ, dirX, dirY, dirZ, shadows); } - void remove_light(void* viewer, int32_t entityId) { + FLUTTER_PLUGIN_EXPORT void remove_light(void* viewer, int32_t entityId) { ((FilamentViewer*)viewer)->removeLight(entityId); } - void clear_lights(void* viewer) { + FLUTTER_PLUGIN_EXPORT void clear_lights(void* viewer) { ((FilamentViewer*)viewer)->clearLights(); } - void* load_glb(void* viewer, const char* assetPath, bool unlit) { - return ((FilamentViewer*)viewer)->loadGlb(assetPath, unlit); + FLUTTER_PLUGIN_EXPORT EntityId load_glb(void* assetManager, const char* assetPath, bool unlit) { + return ((AssetManager*)assetManager)->loadGlb(assetPath, unlit); } - void* load_gltf(void* viewer, const char* assetPath, const char* relativePath) { - return ((FilamentViewer*)viewer)->loadGltf(assetPath, relativePath); + FLUTTER_PLUGIN_EXPORT EntityId load_gltf(void* assetManager, const char* assetPath, const char* relativePath) { + return ((AssetManager*)assetManager)->loadGltf(assetPath, relativePath); } - bool set_camera(void* viewer, void* asset, const char* nodeName) { - return ((FilamentViewer*)viewer)->setCamera((SceneAsset*)asset, nodeName); + FLUTTER_PLUGIN_EXPORT bool set_camera(void* viewer, EntityId asset, const char* nodeName) { + return ((FilamentViewer*)viewer)->setCamera(asset, nodeName); } - void set_camera_exposure(void* viewer, float aperture, float shutterSpeed, float sensitivity) { + FLUTTER_PLUGIN_EXPORT void set_camera_exposure(void* viewer, float aperture, float shutterSpeed, float sensitivity) { ((FilamentViewer*)viewer)->setCameraExposure(aperture, shutterSpeed, sensitivity); } - void set_camera_position(void* viewer, float x, float y, float z) { + FLUTTER_PLUGIN_EXPORT void set_camera_position(void* viewer, float x, float y, float z) { ((FilamentViewer*)viewer)->setCameraPosition(x, y, z); } - void set_camera_rotation(void* viewer, float rads, float x, float y, float z) { + FLUTTER_PLUGIN_EXPORT void set_camera_rotation(void* viewer, float rads, float x, float y, float z) { ((FilamentViewer*)viewer)->setCameraRotation(rads, x, y, z); } - void set_camera_model_matrix(void* viewer, const float* const matrix) { + FLUTTER_PLUGIN_EXPORT void set_camera_model_matrix(void* viewer, const float* const matrix) { ((FilamentViewer*)viewer)->setCameraModelMatrix(matrix); } - void set_camera_focal_length(void* viewer, float focalLength) { + FLUTTER_PLUGIN_EXPORT void set_camera_focal_length(void* viewer, float focalLength) { ((FilamentViewer*)viewer)->setCameraFocalLength(focalLength); } - void render( + FLUTTER_PLUGIN_EXPORT void render( void* viewer, uint64_t frameTimeInNanos ) { ((FilamentViewer*)viewer)->render(frameTimeInNanos); } - void set_frame_interval( + FLUTTER_PLUGIN_EXPORT void set_frame_interval( void* viewer, float frameInterval ) { ((FilamentViewer*)viewer)->setFrameInterval(frameInterval); } - void destroy_swap_chain(void* viewer) { + FLUTTER_PLUGIN_EXPORT void destroy_swap_chain(void* viewer) { ((FilamentViewer*)viewer)->destroySwapChain(); } - void create_swap_chain(void* viewer, void* surface=nullptr, uint32_t width=0, uint32_t height=0) { + FLUTTER_PLUGIN_EXPORT void create_swap_chain(void* viewer, void* surface=nullptr, uint32_t width=0, uint32_t height=0) { ((FilamentViewer*)viewer)->createSwapChain(surface, width, height); } - void* get_renderer(void* viewer) { + FLUTTER_PLUGIN_EXPORT void* get_renderer(void* viewer) { return ((FilamentViewer*)viewer)->getRenderer(); } - void update_viewport_and_camera_projection(void* viewer, int width, int height, float scaleFactor) { + FLUTTER_PLUGIN_EXPORT void update_viewport_and_camera_projection(void* viewer, int width, int height, float scaleFactor) { return ((FilamentViewer*)viewer)->updateViewportAndCameraProjection(width, height, scaleFactor); } - void scroll_update(void* viewer, float x, float y, float delta) { + FLUTTER_PLUGIN_EXPORT void scroll_update(void* viewer, float x, float y, float delta) { ((FilamentViewer*)viewer)->scrollUpdate(x, y, delta); } - void scroll_begin(void* viewer) { + FLUTTER_PLUGIN_EXPORT void scroll_begin(void* viewer) { ((FilamentViewer*)viewer)->scrollBegin(); } - void scroll_end(void* viewer) { + FLUTTER_PLUGIN_EXPORT void scroll_end(void* viewer) { ((FilamentViewer*)viewer)->scrollEnd(); } - void grab_begin(void* viewer, float x, float y, bool pan) { + FLUTTER_PLUGIN_EXPORT void grab_begin(void* viewer, float x, float y, bool pan) { ((FilamentViewer*)viewer)->grabBegin(x, y, pan); } - void grab_update(void* viewer, float x, float y) { + FLUTTER_PLUGIN_EXPORT void grab_update(void* viewer, float x, float y) { ((FilamentViewer*)viewer)->grabUpdate(x, y); } - void grab_end(void* viewer) { + FLUTTER_PLUGIN_EXPORT void grab_end(void* viewer) { ((FilamentViewer*)viewer)->grabEnd(); } - void apply_weights(void* asset, const char* const entityName, float* const weights, int count) { - ((SceneAsset*)asset)->setMorphTargetWeights(entityName, weights, count); + FLUTTER_PLUGIN_EXPORT void* get_asset_manager(void* viewer) { + return (void*)((FilamentViewer*)viewer)->getAssetManager(); } - void set_animation( - void* asset, + FLUTTER_PLUGIN_EXPORT void apply_weights( + void* assetManager, + EntityId asset, + const char* const entityName, + float* const weights, + int count) { + // ((AssetManager*)assetManager)->setMorphTargetWeights(asset, entityName, weights, count); + } + + FLUTTER_PLUGIN_EXPORT void set_morph_animation( + void* assetManager, + EntityId asset, const char* const entityName, const float* const morphData, int numMorphWeights, - const BoneAnimation* const boneAnimations, - int numBoneAnimations, int numFrames, float frameLengthInMs) { - ((SceneAsset*)asset)->setAnimation( + ((AssetManager*)assetManager)->setMorphAnimationBuffer( + asset, entityName, morphData, numMorphWeights, - boneAnimations, - numBoneAnimations, + numFrames, + frameLengthInMs + ); + } + + FLUTTER_PLUGIN_EXPORT void set_bone_animation( + void* assetManager, + EntityId asset, + int length, + const char** const boneNames, + const char** const meshNames, + const float* const frameData, + int numFrames, + float frameLengthInMs) { + ((AssetManager*)assetManager)->setBoneAnimationBuffer( + asset, + length, + boneNames, + meshNames, + frameData, numFrames, frameLengthInMs ); } + // void set_bone_transform( -// void* asset, +// EntityId asset, // const char* boneName, // const char* entityName, // float transX, @@ -190,7 +220,7 @@ extern "C" { // float quatZ, // float quatW // ) { -// ((SceneAsset*)asset)->setBoneTransform( +// ((AssetManager*)assetManager)->setBoneTransform( // boneName, // entityName, // transX, @@ -206,70 +236,86 @@ extern "C" { // } - void play_animation(void* asset, int index, bool loop, bool reverse) { - ((SceneAsset*)asset)->playAnimation(index, loop, reverse); + FLUTTER_PLUGIN_EXPORT void play_animation( + void* assetManager, + EntityId asset, + int index, + bool loop, + bool reverse) { + ((AssetManager*)assetManager)->playAnimation(asset, index, loop, reverse); } - void set_animation_frame(void* asset, int animationIndex, int animationFrame) { - ((SceneAsset*)asset)->setAnimationFrame(animationIndex, animationFrame); + FLUTTER_PLUGIN_EXPORT void set_animation_frame( + void* assetManager, + EntityId asset, + int animationIndex, + int animationFrame) { + // ((AssetManager*)assetManager)->setAnimationFrame(asset, animationIndex, animationFrame); } - int get_animation_count(void* asset) { - auto names = ((SceneAsset*)asset)->getAnimationNames(); + FLUTTER_PLUGIN_EXPORT int get_animation_count( + void* assetManager, + EntityId asset) { + auto names = ((AssetManager*)assetManager)->getAnimationNames(asset); return names->size(); } - void get_animation_name(void* asset, char* const outPtr, int index) { - auto names = ((SceneAsset*)asset)->getAnimationNames(); + FLUTTER_PLUGIN_EXPORT void get_animation_name( + void* assetManager, + EntityId asset, + char* const outPtr, + int index + ) { + auto names = ((AssetManager*)assetManager)->getAnimationNames(asset); string name = names->at(index); strcpy(outPtr, name.c_str()); } - int get_morph_target_name_count(void* asset, const char* meshName) { - unique_ptr> names = ((SceneAsset*)asset)->getMorphTargetNames(meshName); + FLUTTER_PLUGIN_EXPORT int get_morph_target_name_count(void* assetManager, EntityId asset, const char* meshName) { + unique_ptr> names = ((AssetManager*)assetManager)->getMorphTargetNames(asset, meshName); return names->size(); } - void get_morph_target_name(void* asset, const char* meshName, char* const outPtr, int index ) { - unique_ptr> names = ((SceneAsset*)asset)->getMorphTargetNames(meshName); + FLUTTER_PLUGIN_EXPORT void get_morph_target_name(void* assetManager, EntityId asset, const char* meshName, char* const outPtr, int index ) { + unique_ptr> names = ((AssetManager*)assetManager)->getMorphTargetNames(asset, meshName); string name = names->at(index); strcpy(outPtr, name.c_str()); } - void remove_asset(void* viewer, void* asset) { - ((FilamentViewer*)viewer)->removeAsset((SceneAsset*)asset); + FLUTTER_PLUGIN_EXPORT void remove_asset(void* viewer, EntityId asset) { + ((FilamentViewer*)viewer)->removeAsset(asset); } - void clear_assets(void* viewer) { + FLUTTER_PLUGIN_EXPORT void clear_assets(void* viewer) { ((FilamentViewer*)viewer)->clearAssets(); } - void load_texture(void* asset, const char* assetPath, int renderableIndex) { - ((SceneAsset*)asset)->loadTexture(assetPath, renderableIndex); + FLUTTER_PLUGIN_EXPORT void load_texture(void* assetManager, EntityId asset, const char* assetPath, int renderableIndex) { + // ((AssetManager*)assetManager)->loadTexture(assetPath, renderableIndex); } - void set_texture(void* asset) { - ((SceneAsset*)asset)->setTexture(); + FLUTTER_PLUGIN_EXPORT void set_texture(void* assetManager, EntityId asset) { + // ((AssetManager*)assetManager)->setTexture(); } - void transform_to_unit_cube(void* asset) { - ((SceneAsset*)asset)->transformToUnitCube(); + FLUTTER_PLUGIN_EXPORT void transform_to_unit_cube(void* assetManager, EntityId asset) { + ((AssetManager*)assetManager)->transformToUnitCube(asset); } - void set_position(void* asset, float x, float y, float z) { - ((SceneAsset*)asset)->setPosition(x, y, z); + FLUTTER_PLUGIN_EXPORT void set_position(void* assetManager, EntityId asset, float x, float y, float z) { + ((AssetManager*)assetManager)->setPosition(asset, x, y, z); } - void set_rotation(void* asset, float rads, float x, float y, float z) { - ((SceneAsset*)asset)->setRotation(rads, x, y, z); + FLUTTER_PLUGIN_EXPORT void set_rotation(void* assetManager, EntityId asset, float rads, float x, float y, float z) { + ((AssetManager*)assetManager)->setRotation(asset, rads, x, y, z); } - void set_scale(void* asset, float scale) { - ((SceneAsset*)asset)->setScale(scale); - } + FLUTTER_PLUGIN_EXPORT void set_scale(void* assetManager, EntityId asset, float scale) { + ((AssetManager*)assetManager)->setScale(asset, scale); + } - void stop_animation(void* asset, int index) { - ((SceneAsset*)asset)->stopAnimation(index); + FLUTTER_PLUGIN_EXPORT void stop_animation(void* assetManager, EntityId asset, int index) { + ((AssetManager*)assetManager)->stopAnimation(asset, index); } } diff --git a/ios/src/SceneAsset.cpp b/ios/src/SceneAsset.cpp deleted file mode 100644 index 4aa551d8..00000000 --- a/ios/src/SceneAsset.cpp +++ /dev/null @@ -1,517 +0,0 @@ -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include - -#include "StreamBufferAdapter.hpp" -#include "SceneAsset.hpp" -#include "Log.hpp" -#include "ResourceManagement.hpp" -#include "SceneAssetAnimation.hpp" - -using namespace std::chrono; - -namespace polyvox { - -using namespace std; -using namespace filament; -using namespace filament::gltfio; -using namespace image; -using namespace utils; - -SceneAsset::SceneAsset(FilamentAsset *asset, Engine *engine, - NameComponentManager *ncm, LoadResource loadResource, FreeResource freeResource) - : _asset(asset), _engine(engine), _ncm(ncm), _loadResource(loadResource), _freeResource(freeResource) { - _animator = _asset->getInstance()->getAnimator(); - for (int i = 0; i < _animator->getAnimationCount(); i++) { - _embeddedAnimationStatus.push_back( - GLTFAnimation(false,false)); - } - Log("Created animation buffers for %d", _embeddedAnimationStatus.size()); -} - -SceneAsset::~SceneAsset() { - // most other destructor work is deferred to SceneAssetLoader so we don't need to do anything here - if(_texture) { - _engine->destroy(_texture); - _texture = nullptr; - } -} - -void SceneAsset::setMorphTargetWeights(const char* const entityName, float *weights, int count) { - // TODO -} - -void SceneAsset::setAnimation( - const char* entityName, - const float* const morphData, - int numMorphWeights, - const BoneAnimation* const boneAnimations, - int numBoneAnimations, - int numFrames, - float frameLengthInMs) { - - auto filamentInstance = _asset->getInstance(); - - size_t skinCount = filamentInstance->getSkinCount(); - - if(skinCount > 1) { - Log("WARNING - skin count > 1 not currently implemented. This will probably not work"); - } - - auto transforms = make_unique>(); - - auto numFloats = numFrames * 7; - - for(int i = 0; i < numBoneAnimations; i++) { - - auto boneIndices = make_unique>(); - boneIndices->resize(boneAnimations[i].numBones); - for(int j = 0; j < boneAnimations[i].numBones; j++) { - boneIndices->at(j) = getBoneIndex(boneAnimations[i].boneNames[j]); - } - - auto meshTargets = make_unique>(); - for(int j = 0; j < _asset->getEntityCount(); j++) { - for(int k = 0; k < boneAnimations[i].numMeshTargets;k++) { - auto meshName = boneAnimations[i].meshNames[k]; - auto entity = _asset->getEntities()[j]; - auto nameInstance = _ncm->getInstance(entity); - if(strcmp(meshName,_ncm->getName(nameInstance))==0) { - meshTargets->push_back(entity); - } - } - } - - auto frameData = make_unique>( - boneAnimations[i].data, - boneAnimations[i].data + (numFloats * sizeof(float)) - ); - - transforms->push_back(BoneTransformTarget( - boneIndices, - meshTargets, - frameData - )); - } - - RenderableManager &rm = _engine->getRenderableManager(); - Instance inst; - for (size_t i = 0, c = _asset->getEntityCount(); i != c; ++i) { - auto entity = _asset->getEntities()[i]; - auto name = _ncm->getName(_ncm->getInstance(entity)); - - if(strcmp(entityName,name)==0) { - inst = rm.getInstance(_asset->getEntities()[i]); - } - } - - if(!inst) { - Log("Warning: failed to find Renderable instance for entity %s", entityName); - } else { - - _runtimeAnimationBuffer = std::make_unique( - inst, - morphData, - numMorphWeights, - transforms, - numFrames, - frameLengthInMs - ); - } -} - -void SceneAsset::updateAnimations() { - updateRuntimeAnimation(); - updateEmbeddedAnimations(); -} - -void SceneAsset::updateRuntimeAnimation() { - - if (!_runtimeAnimationBuffer) { - return; - } - - if (_runtimeAnimationBuffer->frameNumber == -1) { - _runtimeAnimationBuffer->startTime = high_resolution_clock::now(); - } - - duration dur = - high_resolution_clock::now() - _runtimeAnimationBuffer->startTime; - int frameNumber = - static_cast(dur.count() / _runtimeAnimationBuffer->mFrameLengthInMs); - - // if the animation has finished, return early - if (frameNumber >= _runtimeAnimationBuffer->mNumFrames) { - _runtimeAnimationBuffer = nullptr; - return; - } - - RenderableManager &rm = _engine->getRenderableManager(); - if (frameNumber > _runtimeAnimationBuffer->frameNumber) { - _runtimeAnimationBuffer->frameNumber = frameNumber; - if(_runtimeAnimationBuffer->mMorphFrameData) { - auto morphFramePtrOffset = frameNumber * _runtimeAnimationBuffer->mNumMorphWeights; - rm.setMorphWeights( - _runtimeAnimationBuffer->mInstance, - _runtimeAnimationBuffer->mMorphFrameData + morphFramePtrOffset, - _runtimeAnimationBuffer->mNumMorphWeights); - } - - if(_runtimeAnimationBuffer->mTargets->size() > 0) { - for(auto& target : *(_runtimeAnimationBuffer->mTargets)) { - - setBoneTransform( - target.skinIndex, - *(target.mBoneIndices), - *(target.mMeshTargets), - *(target.mBoneData), - frameNumber - ); - } - } - } -} - -size_t SceneAsset::getBoneIndex(const char* name) { - - auto filamentInstance = _asset->getInstance(); - - int skinIndex = 0; - const utils::Entity* joints = filamentInstance->getJointsAt(skinIndex); - size_t numJoints = filamentInstance->getJointCountAt(skinIndex); - - int boneIndex = -1; - for(int i =0; i < numJoints; i++) { - const char* jointName = _ncm->getName(_ncm->getInstance(joints[i])); - if(strcmp(jointName, name) == 0) { - boneIndex = i; - break; - } - } - if(boneIndex == -1) { - Log("Failed to find bone index %d for bone %s", name); - } - return boneIndex; -} - -void SceneAsset::setBoneTransform( - uint8_t skinIndex, - const vector& boneIndices, - const vector& targets, - const vector data, - int frameNumber) { - - auto filamentInstance = _asset->getInstance(); - - RenderableManager &rm = _engine->getRenderableManager(); - TransformManager &transformManager = _engine->getTransformManager(); - - auto frameDataOffset = frameNumber * 7; - - for(auto& target : targets) { - - auto renderable = rm.getInstance(target); - - math::mat4f inverseGlobalTransform = inverse( - transformManager.getWorldTransform( - transformManager.getInstance(target) - ) - ); - - for(auto boneIndex : boneIndices) { - - utils::Entity joint = filamentInstance->getJointsAt(skinIndex)[boneIndex]; - - math::mat4f localTransform(math::quatf{ - data[frameDataOffset+6], - data[frameDataOffset+3], - data[frameDataOffset+4], - data[frameDataOffset+5] - }); - - const math::mat4f& inverseBindMatrix = filamentInstance->getInverseBindMatricesAt(skinIndex)[boneIndex]; - auto jointInstance = transformManager.getInstance(joint); - math::mat4f globalJointTransform = transformManager.getWorldTransform(jointInstance); - - math::mat4f boneTransform = inverseGlobalTransform * globalJointTransform * localTransform * inverseBindMatrix; - - rm.setBones( - renderable, - &boneTransform, - 1, boneIndex); - } - } -} - -void SceneAsset::playAnimation(int index, bool loop, bool reverse) { - if (index > _animator->getAnimationCount() - 1) { - Log("Asset does not contain an animation at index %d", index); - } else { - const char* name = _animator->getAnimationName(index); - Log("Playing animation %d : %s", index, name); - if (_embeddedAnimationStatus[index].started) { - Log("Animation already playing, call stop first."); - } else { - Log("Starting animation at index %d with loop : %d and reverse %d ", index, loop, reverse); - _embeddedAnimationStatus[index].play = true; - _embeddedAnimationStatus[index].loop = loop; - _embeddedAnimationStatus[index].reverse = reverse; - } - } -} - -void SceneAsset::stopAnimation(int index) { - Log("Stopping animation %d", index); - // TODO - does this need to be threadsafe? - _embeddedAnimationStatus[index].play = false; - _embeddedAnimationStatus[index].started = false; -} - -void SceneAsset::loadTexture(const char* resourcePath, int renderableIndex) { - - Log("Loading texture at %s for renderableIndex %d", resourcePath, renderableIndex); - - string rp(resourcePath); - - if(_texture) { - _engine->destroy(_texture); - _texture = nullptr; - } - - ResourceBuffer imageResource = _loadResource(rp.c_str()); - - StreamBufferAdapter sb((char *)imageResource.data, (char *)imageResource.data + imageResource.size); - - istream *inputStream = new std::istream(&sb); - - LinearImage *image = new LinearImage(ImageDecoder::decode( - *inputStream, rp.c_str(), ImageDecoder::ColorSpace::SRGB)); - - if (!image->isValid()) { - Log("Invalid image : %s", rp.c_str()); - return; - } - - uint32_t channels = image->getChannels(); - uint32_t w = image->getWidth(); - uint32_t h = image->getHeight(); - _texture = Texture::Builder() - .width(w) - .height(h) - .levels(0xff) - .format(channels == 3 ? Texture::InternalFormat::RGB16F - : Texture::InternalFormat::RGBA16F) - .sampler(Texture::Sampler::SAMPLER_2D) - .build(*_engine); - - Texture::PixelBufferDescriptor::Callback freeCallback = [](void *buf, size_t, - void *data) { - delete reinterpret_cast(data); - }; - - Texture::PixelBufferDescriptor buffer( - image->getPixelRef(), size_t(w * h * channels * sizeof(float)), - channels == 3 ? Texture::Format::RGB : Texture::Format::RGBA, - Texture::Type::FLOAT, freeCallback); - - _texture->setImage(*_engine, 0, std::move(buffer)); - setTexture(); - delete inputStream; - - _freeResource(imageResource.id); - -} - -void SceneAsset::setTexture() { - - MaterialInstance* const* inst = _asset->getInstance()->getMaterialInstances(); - size_t mic = _asset->getInstance()->getMaterialInstanceCount(); - Log("Material instance count : %d", mic); - - auto sampler = TextureSampler(); - inst[0]->setParameter("baseColorIndex",0); - inst[0]->setParameter("baseColorMap",_texture,sampler); - -} - -void SceneAsset::setAnimationFrame(int animationIndex, int animationFrame) { - auto offset = 60 * animationFrame * 1000; // TODO - don't hardcore 60fps framerate - _animator->applyAnimation(animationIndex, offset); - _animator->updateBoneMatrices(); -} - -void SceneAsset::updateEmbeddedAnimations() { - auto now = high_resolution_clock::now(); - - bool needsUpdate = false; - for (int animationIndex = 0; animationIndex < _embeddedAnimationStatus.size(); animationIndex++) { - auto &status = _embeddedAnimationStatus[animationIndex]; - if (status.play == false) { - continue; - } - needsUpdate = true; - - float animationLength = _animator->getAnimationDuration(animationIndex); - - duration elapsed = - duration_cast>(now - status.startedAt); - float animationTimeOffset = 0; - bool finished = false; - bool fading = false; - - // if the animation hasn't started yet, start the animation at time zero - if (!status.started) { - status.started = true; - status.startedAt = now; - - // if the animation has finished - } else if (elapsed.count() >= animationLength) { - // if we aren't looping, just mark the animation as finished - if(!status.loop) { - finished = true; - // otherwise, cross-fade between the end of the animation and the start frame over 1 second - } else { - // if 1 second has elapsed, - if(elapsed.count() >= animationLength + 0.3) { - // reset the start time to zero - status.startedAt = now; - // otherwise, apply the first frame of the animation, then cross-fade with the last frame over 1 second - } else { - fading = true; - } - } - } else { - animationTimeOffset = elapsed.count(); - } - - if (finished) { - Log("Animation %d finished", animationIndex); - status.play = false; - status.started = false; - } else { - if(status.reverse) { - animationTimeOffset = _animator->getAnimationDuration(animationIndex) - animationTimeOffset; - } - _animator->applyAnimation(animationIndex, animationTimeOffset); - if(fading) { - // Log("Fading at %0f offset %f", elapsed.count() - animationLength, animationTimeOffset); - _animator->applyCrossFade(animationIndex, animationLength - 0.05, (elapsed.count() - animationLength) / 0.3); - } - } - } - if(needsUpdate) { - _animator->updateBoneMatrices(); - } - needsUpdate = false; -} - -unique_ptr> SceneAsset::getAnimationNames() { - size_t count = _animator->getAnimationCount(); - - unique_ptr> names = make_unique>(); - - for (size_t i = 0; i < count; i++) { - names->push_back(_animator->getAnimationName(i)); - } - - return names; -} - -unique_ptr> SceneAsset::getMorphTargetNames(const char *meshName) { - if (!_asset) { - Log("No asset, ignoring call."); - return nullptr; - } -// Log("Retrieving morph target names for mesh %s", meshName); - unique_ptr> names = make_unique>(); - const Entity *entities = _asset->getEntities(); - - for (int i = 0; i < _asset->getEntityCount(); i++) { - Entity e = entities[i]; - auto inst = _ncm->getInstance(e); - const char *name = _ncm->getName(inst); - - if (strcmp(name, meshName) == 0) { - size_t count = _asset->getMorphTargetCountAt(e); - for (int j = 0; j < count; j++) { - const char *morphName = _asset->getMorphTargetNameAt(e, j); - names->push_back(morphName); - } - break; - } - } - return names; -} - -void SceneAsset::transformToUnitCube() { - if (!_asset) { - Log("No asset, cannot transform."); - return; - } - Log("Transforming asset to unit cube."); - auto &tm = _engine->getTransformManager(); - FilamentInstance* inst = _asset->getInstance(); - auto aabb = inst->getBoundingBox(); - auto center = aabb.center(); - auto halfExtent = aabb.extent(); - auto maxExtent = max(halfExtent) * 2; - auto scaleFactor = 2.0f / maxExtent; - auto transform = - math::mat4f::scaling(scaleFactor) * math::mat4f::translation(-center); - tm.setTransform(tm.getInstance(inst->getRoot()), transform); -} - -void SceneAsset::updateTransform() { - auto &tm = _engine->getTransformManager(); - auto transform = - _position * _rotation * math::mat4f::scaling(_scale); - tm.setTransform(tm.getInstance(_asset->getRoot()), transform); -} - -void SceneAsset::setScale(float scale) { - _scale = scale; - updateTransform(); -} - -void SceneAsset::setPosition(float x, float y, float z) { - Log("Setting position to %f %f %f", x, y, z); - _position = math::mat4f::translation(math::float3(x,y,z)); - updateTransform(); -} - -void SceneAsset::setRotation(float rads, float x, float y, float z) { - Log("Rotating %f radians around axis %f %f %f", rads, x, y, z); - _rotation = math::mat4f::rotation(rads, math::float3(x,y,z)); - updateTransform(); -} - -const utils::Entity *SceneAsset::getCameraEntities() { - return _asset->getCameraEntities(); -} - -size_t SceneAsset::getCameraEntityCount() { - return _asset->getCameraEntityCount(); -} - -const Entity* SceneAsset::getLightEntities() const noexcept { - return _asset->getLightEntities(); -} - -size_t SceneAsset::getLightEntityCount() const noexcept { - return _asset->getLightEntityCount(); -} - - -} // namespace polyvox diff --git a/ios/src/SceneAssetLoader.cpp b/ios/src/SceneAssetLoader.cpp deleted file mode 100644 index 01bc0550..00000000 --- a/ios/src/SceneAssetLoader.cpp +++ /dev/null @@ -1,196 +0,0 @@ -#include "SceneAssetLoader.hpp" -#include "Log.hpp" - -#include - -namespace polyvox { - -using namespace filament; -using namespace filament::gltfio; - -SceneAssetLoader::SceneAssetLoader(LoadResource loadResource, - FreeResource freeResource, - MaterialProvider* materialProvider, - EntityManager* entityManager, - ResourceLoader *resourceLoader, - NameComponentManager *ncm, - Engine *engine, - Scene *scene) - : _loadResource(loadResource), _freeResource(freeResource), _resourceLoader(resourceLoader), _ncm(ncm), - _engine(engine), _scene(scene) { - _assetLoader = AssetLoader::create({_engine, materialProvider, _ncm, entityManager}); - } - -SceneAssetLoader::~SceneAssetLoader() { - destroyAll(); - AssetLoader::destroy(&_assetLoader); -} - -SceneAsset *SceneAssetLoader::fromGltf(const char *uri, - const char *relativeResourcePath) { - ResourceBuffer rbuf = _loadResource(uri); - - // Parse the glTF file and create Filament entities. - Log("Creating asset from JSON"); - FilamentAsset *asset = - _assetLoader->createAsset((uint8_t *)rbuf.data, rbuf.size); - Log("Created asset from JSON"); - - if (!asset) { - Log("Unable to parse asset"); - return nullptr; - } - Log("Loading relative resources"); - - const char *const *const resourceUris = asset->getResourceUris(); - const size_t resourceUriCount = asset->getResourceUriCount(); - - Log("Loading %d resources for asset", resourceUriCount); - - for (size_t i = 0; i < resourceUriCount; i++) { - string uri = - string(relativeResourcePath) + string("/") + string(resourceUris[i]); - Log("Creating resource buffer for resource at %s", uri.c_str()); - ResourceBuffer buf = _loadResource(uri.c_str()); - - // using FunctionCallback = std::function; auto cb = [&] (void * ptr, unsigned int len, void * misc) { - // }; - // FunctionCallback fcb = cb; - - ResourceLoader::BufferDescriptor b(buf.data, buf.size); - _resourceLoader->addResourceData(resourceUris[i], std::move(b)); - _freeResource(buf.id); - } - - _resourceLoader->loadResources(asset); - const Entity *entities = asset->getEntities(); - RenderableManager &rm = _engine->getRenderableManager(); - for (int i = 0; i < asset->getEntityCount(); i++) { - Entity e = entities[i]; - auto inst = rm.getInstance(e); - rm.setCulling(inst, false); - } - - FilamentInstance* inst = asset->getInstance(); - inst->getAnimator()->updateBoneMatrices(); - - inst->recomputeBoundingBoxes(); - - _scene->addEntities(asset->getEntities(), asset->getEntityCount()); - - Log("Loaded relative resources"); - asset->releaseSourceData(); - - Log("Load complete for GLTF at URI %s", uri); - return new SceneAsset(asset, _engine, _ncm, _loadResource,_freeResource); -} - -SceneAsset *SceneAssetLoader::fromGlb(const char *uri) { - Log("Loading GLB at URI %s", uri); - - ResourceBuffer rbuf = _loadResource(uri); - - FilamentAsset *asset = _assetLoader->createAsset( - (const uint8_t *)rbuf.data, rbuf.size); - - - if (!asset) { - Log("Unknown error loading GLB asset."); - return nullptr; - } - - int entityCount = asset->getEntityCount(); - - _scene->addEntities(asset->getEntities(), entityCount); - - Log("Added %d entities to scene", entityCount); - - _resourceLoader->loadResources(asset); - - Log("Resources loaded."); - - // const Entity *entities = asset->getEntities(); - - // RenderableManager &rm = _engine->getRenderableManager(); - - // MaterialKey config; - // auto mi_new = _materialProvider->createMaterialInstance(&config, nullptr); - - // for (int i = 0; i < asset->getEntityCount(); i++) { - // auto entityInstance = rm.getInstance(entities[i]); - // auto mi = rm.getMaterialInstanceAt(entityInstance, 0); - // // auto m = mi->getMaterial(); - // // auto shading = m->getShading(); - // // Log("Shading %d", shading); - // } - - auto lights = asset->getLightEntities(); - _scene->addEntities(lights, asset->getLightEntityCount()); - - Log("Added %d lights to scene from asset", asset->getLightEntityCount()); - - FilamentInstance* inst = asset->getInstance(); - - - inst->getAnimator()->updateBoneMatrices(); - - inst->recomputeBoundingBoxes(); - - asset->releaseSourceData(); - Log("Source data released."); - - _freeResource(rbuf.id); - - Log("Successfully loaded GLB."); - SceneAsset* sceneAsset = new SceneAsset(asset, _engine, _ncm, _loadResource, _freeResource); - _assets.push_back(sceneAsset); - - - - - return sceneAsset; -} - -void SceneAssetLoader::destroyAll() { - for (auto asset : _assets) { - _scene->removeEntities(asset->_asset->getEntities(), - asset->_asset->getEntityCount()); - - _scene->removeEntities(asset->getLightEntities(), - asset->getLightEntityCount()); - - _resourceLoader->evictResourceData(); - _assetLoader->destroyAsset(asset->_asset); - delete asset; - } - _assets.clear(); -} - -void SceneAssetLoader::remove(SceneAsset *asset) { - bool erased = false; - for (auto it = _assets.begin(); it != _assets.end();++it) { - if (*it == asset) { - _assets.erase(it); - erased = true; - break; - } - } - if (!erased) { - Log("Error removing asset from scene : not found"); - return; - } - - Log("Removing asset and all associated entities/lights."); - - _scene->removeEntities(asset->_asset->getEntities(), - asset->_asset->getEntityCount()); - - _scene->removeEntities(asset->getLightEntities(), - asset->getLightEntityCount()); - - _resourceLoader->evictResourceData(); - _assetLoader->destroyAsset(asset->_asset); - delete asset; -} -} // namespace polyvox diff --git a/ios/src/TimeIt.cpp b/ios/src/TimeIt.cpp new file mode 100644 index 00000000..1ebc81f4 --- /dev/null +++ b/ios/src/TimeIt.cpp @@ -0,0 +1,30 @@ +#include "TimeIt.hpp" + +#if __cplusplus <= 199711L + +void Timer::reset() +{ + clock_gettime(CLOCK_REALTIME, &beg_); +} + +double Timer::elapsed() +{ + clock_gettime(CLOCK_REALTIME, &end_); + return end_.tv_sec - beg_.tv_sec + + (end_.tv_nsec - beg_.tv_nsec) / 1000000000.; +} + +#else + +void Timer::reset() +{ + beg_ = clock_::now(); +} + +double Timer::elapsed() +{ + return std::chrono::duration_cast + (clock_::now() - beg_).count(); +} + +#endif \ No newline at end of file diff --git a/ios/src/ios/PolyvoxFilamentIOSApi.cpp b/ios/src/ios/PolyvoxFilamentIOSApi.cpp index b3ab7a0f..dcb1c47b 100644 --- a/ios/src/ios/PolyvoxFilamentIOSApi.cpp +++ b/ios/src/ios/PolyvoxFilamentIOSApi.cpp @@ -11,7 +11,7 @@ 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) { + void* create_filament_viewer_ios(void* pb, void* loadResource, void* freeResource, void* resources) { FreeResource _freeResource = [=](uint32_t rid) { reinterpret_cast(freeResource)(rid, resources); diff --git a/lib/animations/animation_builder.dart b/lib/animations/animation_builder.dart index cabb5158..1cb48b0b 100644 --- a/lib/animations/animation_builder.dart +++ b/lib/animations/animation_builder.dart @@ -1,9 +1,11 @@ -import 'animations.dart'; +import 'package:polyvox_filament/animations/animations.dart'; +import 'package:tuple/tuple.dart'; + import 'package:flutter/foundation.dart'; import 'package:vector_math/vector_math.dart'; class AnimationBuilder { - BoneAnimation? boneAnimation; + DartBoneAnimation? dartBoneAnimation; double _frameLengthInMs = 0; double _duration = 0; int _numMorphWeights = 0; @@ -13,9 +15,10 @@ class AnimationBuilder { double? _interpMorphStartValue; double? _interpMorphEndValue; - List? _boneAnimations = null; + List? _dartBoneAnimations = null; - Animation build(String meshName, List morphNames) { + Tuple2> build( + String meshName, List morphNames) { if (_numMorphWeights == 0 || _duration == 0 || _frameLengthInMs == 0) throw Exception(); @@ -39,8 +42,8 @@ class AnimationBuilder { var morphAnimation = MorphAnimation(meshName, morphData, morphNames, _frameLengthInMs); - return Animation( - morphAnimation: morphAnimation, boneAnimations: _boneAnimations); + return Tuple2>( + morphAnimation, _dartBoneAnimations!); } AnimationBuilder setFramerate(int framerate) { @@ -107,16 +110,18 @@ class AnimationBuilder { } } - var boneFrameData = BoneTransformFrameData(translations, quats); + throw Exception(); - _boneAnimations ??= []; + // var boneFrameData = BoneTransformFrameData(translations, quats); - var frameData = List>.generate( - numFrames, (index) => boneFrameData.getFrameData(index).toList()); + // _DartBoneAnimations ??= []; - var animData = Float32List.fromList(frameData.expand((x) => x).toList()); + // var frameData = List>.generate( + // numFrames, (index) => boneFrameData.getFrameData(index).toList()); - _boneAnimations!.add(BoneAnimation([boneName], [meshName], animData)); + // var animData = Float32List.fromList(frameData.expand((x) => x).toList()); + + // _DartBoneAnimations!.add(DartDartBoneAnimation([boneName], [meshName], animData)); return this; } diff --git a/lib/animations/animations.dart b/lib/animations/animations.dart index 9b7351e5..e9976b01 100644 --- a/lib/animations/animations.dart +++ b/lib/animations/animations.dart @@ -2,16 +2,13 @@ import 'dart:typed_data'; import 'package:vector_math/vector_math.dart'; -class BoneAnimation { - final List boneNames; - final List meshNames; +class DartBoneAnimation { + final String boneName; + final String meshName; final Float32List frameData; - - BoneAnimation(this.boneNames, this.meshNames, this.frameData); - - List toList() { - return [boneNames, meshNames, frameData]; - } + double frameLengthInMs; + DartBoneAnimation( + this.boneName, this.meshName, this.frameData, this.frameLengthInMs); } // @@ -24,25 +21,18 @@ class MorphAnimation { final String meshName; final List morphNames; - late final Float32List morphData; + final Float32List data; MorphAnimation( - this.meshName, this.morphData, this.morphNames, this.frameLengthInMs); + this.meshName, this.data, this.morphNames, this.frameLengthInMs); int get numMorphWeights => morphNames.length; - int get numFrames => morphData.length ~/ numMorphWeights; + int get numFrames => data.length ~/ numMorphWeights; final double frameLengthInMs; } -class Animation { - final MorphAnimation? morphAnimation; - final List? boneAnimations; - - Animation({this.morphAnimation, this.boneAnimations}); -} - class BoneTransformFrameData { final List translations; final List quaternions; @@ -67,18 +57,3 @@ class BoneTransformFrameData { yield quaternions[frame].w; } } - -// Animation.from( -// {required this.meshName, -// required List> morphData, -// required this.numMorphWeights, -// this.boneAnimations, -// required this.numFrames, -// required this.frameLengthInMs}) { -// if (morphData.length != numFrames) { -// throw Exception("Mismatched animation data with frame length"); -// } -// } - -// not directly used, the list of morph targets animated by this [Animation], and may be a subset of the actual morph targets in the asset (and may also be ordered differently). -// // When passed to a [FilamentController], these will be re-mapped appropriately (and any morph targets not provided will be set to zero at each frame). \ No newline at end of file diff --git a/lib/filament_controller.dart b/lib/filament_controller.dart index 122b5f30..04c2455e 100644 --- a/lib/filament_controller.dart +++ b/lib/filament_controller.dart @@ -1,115 +1,27 @@ import 'dart:async'; -import 'dart:typed_data'; -import 'dart:ui'; +import 'dart:ffi'; +import 'dart:io'; +import 'dart:ui' as ui; + +import 'package:ffi/ffi.dart'; +import 'package:flutter/animation.dart'; +import 'package:flutter/scheduler.dart'; import 'package:flutter/services.dart'; +import 'package:polyvox_filament/generated_bindings.dart'; -import 'animations/animation_builder.dart'; import 'animations/animations.dart'; -// this is confusing - "FilamentAsset" actually defines a pointer to a SceneAsset, whereas FilamentLight is an Entity ID. -// should make this consistent -typedef FilamentAsset = int; -typedef FilamentLight = int; -const FilamentAsset FILAMENT_ASSET_ERROR = 0; +typedef AssetManager = Pointer; +typedef FilamentViewer = Pointer; +typedef FilamentEntity = int; +const FilamentEntity FILAMENT_ASSET_ERROR = 0; -abstract class FilamentController { - Size get size; - late Stream textureId; - Future get initialized; - Stream get onInitializationRequested; - Future initialize(); - Future createTextureViewer(int width, int height); - Future setFrameRate(int framerate); - Future setRendering(bool render); - Future render(); - void setPixelRatio(double ratio); - Future resize(int width, int height, {double contentScaleFactor = 1}); - Future setBackgroundColor(Color color); - Future clearBackgroundImage(); - Future setBackgroundImage(String path); - Future setBackgroundImagePosition(double x, double y, {bool clamp = false}); - Future loadSkybox(String skyboxPath); - Future removeSkybox(); - Future loadIbl(String path, {double intensity = 30000}); - Future removeIbl(); - - // copied from LightManager.h - // enum class Type : uint8_t { - // SUN, //!< Directional light that also draws a sun's disk in the sky. - // DIRECTIONAL, //!< Directional light, emits light in a given direction. - // POINT, //!< Point light, emits light from a position, in all directions. - // FOCUSED_SPOT, //!< Physically correct spot light. - // SPOT, //!< Spot light with coupling of outer cone and illumination disabled. - // }; - Future addLight( - int type, - double colour, - double intensity, - double posX, - double posY, - double posZ, - double dirX, - double dirY, - double dirZ, - bool castShadows); - Future removeLight(FilamentLight light); - Future clearLights(); - Future loadGlb(String path, {bool unlit = false}); - Future loadGltf(String path, String relativeResourcePath); - Future zoomBegin(); - Future zoomUpdate(double z); - Future zoomEnd(); - Future panStart(double x, double y); - Future panUpdate(double x, double y); - Future panEnd(); - Future rotateStart(double x, double y); - Future rotateUpdate(double x, double y); - Future rotateEnd(); - Future setMorphTargetWeights(FilamentAsset asset, List weights); - Future> getMorphTargetNames( - FilamentAsset asset, String meshName); - Future> getAnimationNames(FilamentAsset asset); - Future removeAsset(FilamentAsset asset); - Future clearAssets(); - Future setAnimationFrame( - FilamentAsset asset, int animationIndex, int animationFrame); - Future playAnimation(FilamentAsset asset, int index, - {bool loop = false, bool reverse = false}); - Future playAnimations(FilamentAsset asset, List indices, - {bool loop = false, bool reverse = false}); - Future stopAnimation(FilamentAsset asset, int index); - Future setCamera(FilamentAsset asset, String name); - Future setTexture(FilamentAsset asset, String assetPath, - {int renderableIndex = 0}); - Future transformToUnitCube(FilamentAsset asset); - Future setPosition(FilamentAsset asset, double x, double y, double z); - Future setRotation( - FilamentAsset asset, double rads, double x, double y, double z); - // Future setBoneTransform(FilamentAsset asset, String boneName, String meshName, - // BoneTransform transform); - Future setScale(FilamentAsset asset, double scale); - Future setCameraExposure( - double aperture, double shutterSpeed, double sensitivity); - Future setCameraFocalLength(double focalLength); - Future setCameraFocusDistance(double focusDistance); - Future setCameraPosition(double x, double y, double z); - Future setCameraRotation(double rads, double x, double y, double z); - Future setCameraModelMatrix(List matrix); - - /// - /// Animates morph target weights/bone transforms (where each frame requires a duration of [frameLengthInMs]. - /// [morphWeights] is a list of doubles in frame-major format. - /// Each frame is [numWeights] in length, and each entry is the weight to be applied to the morph target located at that index in the mesh primitive at that frame. - /// - Future setAnimation(FilamentAsset asset, Animation animation); -} - -class PolyvoxFilamentController extends FilamentController { +class FilamentController { late MethodChannel _channel = MethodChannel("app.polyvox.filament/event"); double _pixelRatio = 1.0; - Size size = Size(0, 0); + ui.Size size = ui.Size.zero; int? _textureId; final _textureIdController = StreamController.broadcast(); @@ -121,15 +33,27 @@ class PolyvoxFilamentController extends FilamentController { final _initialized = Completer(); Future get initialized => _initialized.future; - PolyvoxFilamentController() { + late NativeLibrary _nativeLibrary; + + late FilamentViewer _viewer; + late AssetManager _assetManager; + + final TickerProvider _tickerProvider; + Ticker? _ticker; + bool _rendering = false; + + FilamentController(this._tickerProvider) { _channel.setMethodCallHandler((call) async { - print("Received Filament method channel call : ${call.method}"); throw Exception("Unknown method channel invocation ${call.method}"); }); _textureIdController.onListen = () { _textureIdController.add(_textureId); }; + + _nativeLibrary = NativeLibrary(Platform.isAndroid || Platform.isLinux + ? DynamicLibrary.open("libpolyvox_filament_plugin.so") + : DynamicLibrary.process()); } Future initialize() async { @@ -138,89 +62,126 @@ class PolyvoxFilamentController extends FilamentController { } Future setRendering(bool render) async { - await _channel.invokeMethod("setRendering", render); + _rendering = render; } - Future render() async { - await _channel.invokeMethod("render"); + void render() { + _nativeLibrary.render(_viewer, 0); + _channel.invokeMethod("onFrameAvailable"); } Future setFrameRate(int framerate) async { - await _channel.invokeMethod("setFrameInterval", 1 / framerate); + _nativeLibrary.set_frame_interval(_viewer, 1 / framerate); } void setPixelRatio(double ratio) { - print("Set pixel ratio to $ratio"); _pixelRatio = ratio; } Future createTextureViewer(int width, int height) async { - size = Size(width * _pixelRatio, height * _pixelRatio); - print("Creating texture of size $size"); + size = ui.Size(width * _pixelRatio, height * _pixelRatio); _textureId = - await _channel.invokeMethod("initialize", [size.width, size.height]); + await _channel.invokeMethod("createTexture", [size.width, size.height]); _textureIdController.add(_textureId); + + var glContext = + Pointer.fromAddress(await _channel.invokeMethod("getContext")); + + final loadResource = Pointer< + NativeFunction)>>.fromAddress( + await _channel.invokeMethod("getLoadResourceFn")); + + print("got $loadResource loadResource"); + var freeResource = + Pointer>.fromAddress( + await _channel.invokeMethod("getFreeResourceFn")); + + _viewer = _nativeLibrary.create_filament_viewer( + glContext, loadResource, freeResource); + + // don't pass a surface to the SwapChain as we are effectively creating a headless SwapChain that will render into a RenderTarget associated with a texture + _nativeLibrary.create_swap_chain( + _viewer, nullptr, size.width.toInt(), size.height.toInt()); + + var glTextureId = await _channel.invokeMethod("getGlTextureId"); + + _nativeLibrary.create_render_target( + _viewer, glTextureId, size.width.toInt(), size.height.toInt()); + _nativeLibrary.update_viewport_and_camera_projection( + _viewer, size.width.toInt(), size.height.toInt(), 1.0); + _initialized.complete(true); + _assetManager = _nativeLibrary.get_asset_manager(_viewer); + print("got asset maanger $_assetManager"); + + _ticker = _tickerProvider.createTicker((elapsed) { + if (_rendering) { + render(); + } + }); + _ticker!.start(); } Future resize(int width, int height, {double contentScaleFactor = 1.0}) async { - size = Size(width * _pixelRatio, height * _pixelRatio); + size = ui.Size(width * _pixelRatio, height * _pixelRatio); _textureId = await _channel.invokeMethod("resize", [width * _pixelRatio, height * _pixelRatio, contentScaleFactor]); - print("Resized to $size with texutre Id $textureId"); + _textureIdController.add(_textureId); } - @override - Future clearBackgroundImage() async { - await _channel.invokeMethod("clearBackgroundImage"); + void clearBackgroundImage() async { + _nativeLibrary.clear_background_image(_viewer); } - @override - Future setBackgroundImage(String path) async { - await _channel.invokeMethod("setBackgroundImage", path); + void setBackgroundImage(String path) async { + _nativeLibrary.set_background_image( + _viewer, path.toNativeUtf8().cast()); } - @override - Future setBackgroundColor(Color color) async { - await _channel.invokeMethod("setBackgroundColor", [ - color.red.toDouble() / 255.0, - color.green.toDouble() / 255.0, - color.blue.toDouble() / 255.0, - color.alpha.toDouble() / 255.0 - ]); + void setBackgroundColor(Color color) async { + _nativeLibrary.set_background_color( + _viewer, + color.red.toDouble() / 255.0, + color.green.toDouble() / 255.0, + color.blue.toDouble() / 255.0, + color.alpha.toDouble() / 255.0); } - @override - Future setBackgroundImagePosition(double x, double y, + void setBackgroundImagePosition(double x, double y, {bool clamp = false}) async { - await _channel.invokeMethod("setBackgroundImagePosition", [x, y, clamp]); + _nativeLibrary.set_background_image_position(_viewer, x, y, clamp ? 1 : 0); } - @override - Future loadSkybox(String skyboxPath) async { - await _channel.invokeMethod("loadSkybox", skyboxPath); + void loadSkybox(String skyboxPath) async { + _nativeLibrary.load_skybox(_viewer, skyboxPath.toNativeUtf8().cast()); } - @override - Future loadIbl(String lightingPath, {double intensity = 30000}) async { - await _channel.invokeMethod("loadIbl", [lightingPath, intensity]); + void loadIbl(String lightingPath, {double intensity = 30000}) async { + _nativeLibrary.load_ibl( + _viewer, lightingPath.toNativeUtf8().cast(), intensity); } - @override - Future removeSkybox() async { - await _channel.invokeMethod("removeSkybox"); + void removeSkybox() async { + _nativeLibrary.remove_skybox(_viewer); } - @override - Future removeIbl() async { - await _channel.invokeMethod("removeIbl"); + void removeIbl() async { + _nativeLibrary.remove_ibl(_viewer); } - @override - Future addLight( + // copied from LightManager.h + // enum class Type : uint8_t { + // SUN, //!< Directional light that also draws a sun's disk in the sky. + // DIRECTIONAL, //!< Directional light, emits light in a given direction. + // POINT, //!< Point light, emits light from a position, in all directions. + // FOCUSED_SPOT, //!< Physically correct spot light. + // SPOT, //!< Spot light with coupling of outer cone and illumination disabled. + // }; + + FilamentEntity addLight( int type, double colour, double intensity, @@ -230,221 +191,241 @@ class PolyvoxFilamentController extends FilamentController { double dirX, double dirY, double dirZ, - bool castShadows) async { - var entityId = await _channel.invokeMethod("addLight", [ - type, - colour, - intensity, - posX, - posY, - posZ, - dirX, - dirY, - dirZ, - castShadows - ]); - return entityId as FilamentLight; + bool castShadows) { + return _nativeLibrary.add_light(_viewer, type, colour, intensity, posX, + posY, posZ, dirX, dirY, dirZ, castShadows ? 1 : 0); } - @override - Future removeLight(FilamentLight light) { - return _channel.invokeMethod("removeLight", light); + void removeLight(FilamentEntity light) async { + _nativeLibrary.remove_light(_viewer, light); } - @override - Future clearLights() { - return _channel.invokeMethod("clearLights"); + void clearLights() async { + _nativeLibrary.clear_lights(_viewer); } - Future loadGlb(String path, {bool unlit = false}) async { - print("Loading GLB at $path "); - var asset = await _channel.invokeMethod("loadGlb", [path, unlit]); + FilamentEntity loadGlb(String path, {bool unlit = false}) { + var asset = _nativeLibrary.load_glb( + _assetManager, path.toNativeUtf8().cast(), unlit ? 1 : 0); if (asset == FILAMENT_ASSET_ERROR) { throw Exception("An error occurred loading the asset at $path"); } - return asset as FilamentAsset; + return asset; } - Future loadGltf( - String path, String relativeResourcePath) async { - print( - "Loading GLTF at $path with relative resource path $relativeResourcePath"); - var asset = - await _channel.invokeMethod("loadGltf", [path, relativeResourcePath]); - return asset as FilamentAsset; + FilamentEntity loadGltf(String path, String relativeResourcePath) { + return _nativeLibrary.load_gltf( + _assetManager, + path.toNativeUtf8().cast(), + relativeResourcePath.toNativeUtf8().cast()); } - Future panStart(double x, double y) async { - await _channel.invokeMethod("panStart", [x * _pixelRatio, y * _pixelRatio]); + void panStart(double x, double y) async { + _nativeLibrary.grab_begin(_viewer, x * _pixelRatio, y * _pixelRatio, 1); } - Future panUpdate(double x, double y) async { - await _channel - .invokeMethod("panUpdate", [x * _pixelRatio, y * _pixelRatio]); + void panUpdate(double x, double y) async { + _nativeLibrary.grab_update(_viewer, x * _pixelRatio, y * _pixelRatio); } - Future panEnd() async { - await _channel.invokeMethod("panEnd"); + void panEnd() async { + _nativeLibrary.grab_end(_viewer); } - Future rotateStart(double x, double y) async { - await _channel - .invokeMethod("rotateStart", [x * _pixelRatio, y * _pixelRatio]); + void rotateStart(double x, double y) async { + _nativeLibrary.grab_begin(_viewer, x * _pixelRatio, y * _pixelRatio, 0); } - Future rotateUpdate(double x, double y) async { - await _channel - .invokeMethod("rotateUpdate", [x * _pixelRatio, y * _pixelRatio]); + void rotateUpdate(double x, double y) async { + _nativeLibrary.grab_update(_viewer, x * _pixelRatio, y * _pixelRatio); } - Future rotateEnd() async { - await _channel.invokeMethod("rotateEnd"); + void rotateEnd() async { + _nativeLibrary.grab_end(_viewer); } - Future setMorphTargetWeights( - FilamentAsset asset, List weights) async { - await _channel.invokeMethod( - "setMorphTargetWeights", [asset, Float32List.fromList(weights)]); + void setMorphTargetWeights(FilamentEntity asset, List weights) { + throw Exception("TODO"); + // _nativeLibrary.set_morph_target_weights(_assetManager, asset, Float32List.fromList(weights)); } - Future> getMorphTargetNames( - FilamentAsset asset, String meshName) async { - var result = - (await _channel.invokeMethod("getMorphTargetNames", [asset, meshName])) - .cast(); - return result; + List getMorphTargetNames(FilamentEntity asset, String meshName) { + var meshNamePtr = meshName.toNativeUtf8().cast(); + var count = _nativeLibrary.get_morph_target_name_count( + _assetManager, asset, meshNamePtr); + var names = []; + for (int i = 0; i < count; i++) { + var outPtr = calloc(255); + _nativeLibrary.get_morph_target_name( + _assetManager, asset, meshNamePtr, outPtr, i); + names.add(outPtr.cast().toDartString()); + } + return names; } - Future> getAnimationNames(FilamentAsset asset) async { - var result = (await _channel.invokeMethod("getAnimationNames", asset)) - .cast(); - return result; + List getAnimationNames(FilamentEntity asset) { + var count = _nativeLibrary.get_animation_count(_assetManager, asset); + var names = []; + for (int i = 0; i < count; i++) { + var outPtr = calloc(255); + _nativeLibrary.get_animation_name(_assetManager, asset, outPtr, i); + names.add(outPtr.cast().toDartString()); + } + return names; } - Future setAnimation(FilamentAsset asset, Animation animation) async { - await _channel.invokeMethod("setAnimation", [ - asset, - animation.morphAnimation!.meshName, - animation.morphAnimation!.morphData, - animation.morphAnimation!.numMorphWeights, - animation.boneAnimations?.map((a) => a.toList()).toList() ?? [], - animation.morphAnimation!.numFrames, - animation.morphAnimation!.frameLengthInMs - ]); + /// + /// Animates morph target weights/bone transforms (where each frame requires a duration of [frameLengthInMs]. + /// [morphWeights] is a list of doubles in frame-major format. + /// Each frame is [numWeights] in length, and each entry is the weight to be applied to the morph target located at that index in the mesh primitive at that frame. + /// + void setMorphAnimation(FilamentEntity asset, MorphAnimation animation) async { + var data = calloc(animation.data.length); + for (int i = 0; i < animation.data.length; i++) { + data.elementAt(i).value = animation.data[i]; + } + _nativeLibrary.set_morph_animation( + _assetManager, + asset, + animation.meshName.toNativeUtf8().cast(), + data, + animation.numMorphWeights, + animation.numFrames, + animation.frameLengthInMs); + calloc.free(data); } - Future removeAsset(FilamentAsset asset) async { - print("Removing asset : $asset"); - await _channel.invokeMethod("removeAsset", asset); + /// + /// Animates morph target weights/bone transforms (where each frame requires a duration of [frameLengthInMs]. + /// [morphWeights] is a list of doubles in frame-major format. + /// Each frame is [numWeights] in length, and each entry is the weight to be applied to the morph target located at that index in the mesh primitive at that frame. + /// + void setBoneAnimation( + FilamentEntity asset, List animations) async { + var data = + calloc(animations.length * animations.first.frameData.length); + int offset = 0; + var numFrames = animations.first.frameData.length; + var meshNames = calloc>(animations.length); + var boneNames = calloc>(animations.length); + int animIdx = 0; + for (var animation in animations) { + if (animation.frameData.length != numFrames) { + throw Exception( + "All bone animations must share the same animation frame data length."); + } + for (int i = 0; i < animation.frameData.length; i++) { + data.elementAt(offset).value = animation.frameData[i]; + offset += 1; + } + meshNames.elementAt(animIdx).value = + animation.meshName.toNativeUtf8().cast(); + boneNames.elementAt(animIdx).value = + animation.boneName.toNativeUtf8().cast(); + } + + _nativeLibrary.set_bone_animation( + _assetManager, + asset, + animations.length, + boneNames, + meshNames, + data, + numFrames, + animations.first.frameLengthInMs); + calloc.free(data); } - Future clearAssets() async { - await _channel.invokeMethod("clearAssets"); + void removeAsset(FilamentEntity asset) async { + _nativeLibrary.remove_asset(_viewer, asset); } - Future zoomBegin() async { - await _channel.invokeMethod("zoomBegin"); + void clearAssets() async { + _nativeLibrary.clear_assets(_viewer); } - Future zoomUpdate(double z) async { - await _channel.invokeMethod("zoomUpdate", [0.0, 0.0, z]); + void zoomBegin() async { + _nativeLibrary.scroll_begin(_viewer); } - Future zoomEnd() async { - await _channel.invokeMethod("zoomEnd"); + void zoomUpdate(double z) async { + _nativeLibrary.scroll_update(_viewer, 0.0, 0.0, z); } - Future playAnimation(FilamentAsset asset, int index, + void zoomEnd() async { + _nativeLibrary.scroll_end(_viewer); + } + + void playAnimation(FilamentEntity asset, int index, {bool loop = false, bool reverse = false}) async { - await _channel.invokeMethod("playAnimation", [asset, index, loop, reverse]); + _nativeLibrary.play_animation( + _assetManager, asset, index, loop ? 1 : 0, reverse ? 1 : 0); } - Future setAnimationFrame( - FilamentAsset asset, int index, int animationFrame) async { - await _channel - .invokeMethod("setAnimationFrame", [asset, index, animationFrame]); + void setAnimationFrame( + FilamentEntity asset, int index, int animationFrame) async { + _nativeLibrary.set_animation_frame( + _assetManager, asset, index, animationFrame); } - Future playAnimations(FilamentAsset asset, List indices, - {bool loop = false, bool reverse = false}) async { - return Future.wait(indices.map((index) { - return _channel - .invokeMethod("playAnimation", [asset, index, loop, reverse]); - })); + void stopAnimation(FilamentEntity asset, int animationIndex) async { + _nativeLibrary.stop_animation(_assetManager, asset, animationIndex); } - Future stopAnimation(FilamentAsset asset, int animationIndex) async { - await _channel.invokeMethod("stopAnimation", [asset, animationIndex]); + void setCamera(FilamentEntity asset, String name) async { + _nativeLibrary.set_camera(_viewer, asset, name.toNativeUtf8().cast()); } - Future setCamera(FilamentAsset asset, String name) async { - await _channel.invokeMethod("setCamera", [asset, name]); + void setCameraFocalLength(double focalLength) async { + _nativeLibrary.set_camera_focal_length(_viewer, focalLength); } - Future setCameraFocalLength(double focalLength) async { - await _channel.invokeMethod("setCameraFocalLength", focalLength); + void setCameraFocusDistance(double focusDistance) async { + _nativeLibrary.set_camera_focus_distance(_viewer, focusDistance); } - Future setCameraFocusDistance(double focusDistance) async { - await _channel.invokeMethod("setCameraFocusDistance", focusDistance); + void setCameraPosition(double x, double y, double z) async { + _nativeLibrary.set_camera_position(_viewer, x, y, z); } - Future setCameraPosition(double x, double y, double z) async { - await _channel.invokeMethod("setCameraPosition", [x, y, z]); - } - - Future setCameraExposure( + void setCameraExposure( double aperture, double shutterSpeed, double sensitivity) async { - await _channel.invokeMethod( - "setCameraExposure", [aperture, shutterSpeed, sensitivity]); + _nativeLibrary.set_camera_exposure( + _viewer, aperture, shutterSpeed, sensitivity); } - Future setCameraRotation(double rads, double x, double y, double z) async { - await _channel.invokeMethod("setCameraRotation", [rads, x, y, z]); + void setCameraRotation(double rads, double x, double y, double z) async { + _nativeLibrary.set_camera_rotation(_viewer, rads, x, y, z); } - Future setCameraModelMatrix(List matrix) async { + void setCameraModelMatrix(List matrix) async { assert(matrix.length == 16); - await _channel.invokeMethod( - "setCameraModelMatrix", Float32List.fromList(matrix)); + var ptr = calloc(16); + for (int i = 0; i < 16; i++) { + ptr.elementAt(i).value = matrix[i]; + } + _nativeLibrary.set_camera_model_matrix(_viewer, ptr); } - Future setTexture(FilamentAsset asset, String assetPath, + void setTexture(FilamentEntity asset, String assetPath, {int renderableIndex = 0}) async { - await _channel - .invokeMethod("setTexture", [asset, assetPath, renderableIndex]); + _nativeLibrary.set_texture(_assetManager, asset); } - Future transformToUnitCube(FilamentAsset asset) async { - await _channel.invokeMethod("transformToUnitCube", asset); + void transformToUnitCube(FilamentEntity asset) async { + _nativeLibrary.transform_to_unit_cube(_assetManager, asset); } - Future setPosition(FilamentAsset asset, double x, double y, double z) async { - await _channel.invokeMethod("setPosition", [asset, x, y, z]); + void setPosition(FilamentEntity asset, double x, double y, double z) async { + _nativeLibrary.set_position(_assetManager, asset, x, y, z); } - // Future setBoneTransform(FilamentAsset asset, String boneName, String meshName, - // BoneTransform transform) async { - // await _channel.invokeMethod("setBoneTransform", [ - // asset, - // boneName, - // meshName, - // transform.translations[0].x, - // transform.translations[0].y, - // transform.translations[0].z, - // transform.quaternions[0].x, - // transform.quaternions[0].y, - // transform.quaternions[0].z, - // transform.quaternions[0].w - // ]); - // } - - Future setScale(FilamentAsset asset, double scale) async { - await _channel.invokeMethod("setScale", [asset, scale]); + void setScale(FilamentEntity asset, double scale) async { + _nativeLibrary.set_scale(_assetManager, asset, scale); } - Future setRotation( - FilamentAsset asset, double rads, double x, double y, double z) async { - await _channel.invokeMethod("setRotation", [asset, rads, x, y, z]); + void setRotation( + FilamentEntity asset, double rads, double x, double y, double z) async { + _nativeLibrary.set_rotation(_assetManager, asset, rads, x, y, z); } } diff --git a/lib/filament_gesture_detector.dart b/lib/filament_gesture_detector.dart index 2567f2e1..1ff45ae0 100644 --- a/lib/filament_gesture_detector.dart +++ b/lib/filament_gesture_detector.dart @@ -41,9 +41,9 @@ class _FilamentGestureDetectorState extends State { // to avoid duplicating code for pan/rotate (panStart, panUpdate, panEnd, rotateStart, rotateUpdate etc) // we have only a single function for start/update/end. // when the gesture type is changed, these properties are updated to point to the correct function. - late Future Function(double x, double y) _functionStart; - late Future Function(double x, double y) _functionUpdate; - late Future Function() _functionEnd; + late Function(double x, double y) _functionStart; + late Function(double x, double y) _functionUpdate; + late Function() _functionEnd; double _lastScale = 0; @@ -104,8 +104,8 @@ class _FilamentGestureDetectorState extends State { : (d) async { _scaling = true; if (d.pointerCount == 2) { - await widget.controller.zoomEnd(); - await widget.controller.zoomBegin(); + widget.controller.zoomEnd(); + widget.controller.zoomBegin(); } }, onScaleEnd: !widget.enableControls @@ -114,7 +114,7 @@ class _FilamentGestureDetectorState extends State { _scaling = false; if (d.pointerCount == 2) { _lastScale = 0; - await widget.controller.zoomEnd(); + widget.controller.zoomEnd(); } }, onScaleUpdate: !widget.enableControls @@ -122,7 +122,7 @@ class _FilamentGestureDetectorState extends State { : (d) async { if (d.pointerCount == 2) { if (_lastScale != 0) { - await widget.controller.zoomUpdate(Platform.isIOS + widget.controller.zoomUpdate(Platform.isIOS ? 1000 * (_lastScale - d.scale) : 100 * (_lastScale - d.scale)); } @@ -138,8 +138,8 @@ class _FilamentGestureDetectorState extends State { // scroll-wheel zoom on desktop if (pointerSignal is PointerScrollEvent) { _scrollTimer?.cancel(); - await widget.controller.zoomBegin(); - await widget.controller.zoomUpdate( + widget.controller.zoomBegin(); + widget.controller.zoomUpdate( pointerSignal.scrollDelta.dy > 0 ? 10 : -10); _scrollTimer = Timer(Duration(milliseconds: 100), () { @@ -154,10 +154,10 @@ class _FilamentGestureDetectorState extends State { ? null : (d) async { if (d.buttons == kTertiaryButton || _rotating) { - await widget.controller.rotateStart( + widget.controller.rotateStart( d.localPosition.dx, d.localPosition.dy); } else { - await _functionStart( + _functionStart( d.localPosition.dx, d.localPosition.dy); } }, @@ -165,10 +165,10 @@ class _FilamentGestureDetectorState extends State { ? null : (d) async { if (d.buttons == kTertiaryButton || _rotating) { - await widget.controller.rotateUpdate( + widget.controller.rotateUpdate( d.localPosition.dx, d.localPosition.dy); } else { - await _functionUpdate( + _functionUpdate( d.localPosition.dx, d.localPosition.dy); } }, @@ -176,9 +176,9 @@ class _FilamentGestureDetectorState extends State { ? null : (d) async { if (d.buttons == kTertiaryButton || _rotating) { - await widget.controller.rotateEnd(); + widget.controller.rotateEnd(); } else { - await _functionEnd(); + _functionEnd(); } }, child: widget.child))), diff --git a/lib/generated_bindings.dart b/lib/generated_bindings.dart new file mode 100644 index 00000000..c1e8ce0f --- /dev/null +++ b/lib/generated_bindings.dart @@ -0,0 +1,1343 @@ +// AUTO GENERATED FILE, DO NOT EDIT. +// +// Generated by `package:ffigen`. +// ignore_for_file: type=lint +import 'dart:ffi' as ffi; + +class NativeLibrary { + /// Holds the symbol lookup function. + final ffi.Pointer Function(String symbolName) + _lookup; + + /// The symbols are looked up in [dynamicLibrary]. + NativeLibrary(ffi.DynamicLibrary dynamicLibrary) + : _lookup = dynamicLibrary.lookup; + + /// The symbols are looked up with [lookup]. + NativeLibrary.fromLookup( + ffi.Pointer Function(String symbolName) + lookup) + : _lookup = lookup; + + /// struct to facilitate passing bone animation frame data between Dart/native. + ffi.Pointer create_filament_viewer( + ffi.Pointer context, + ffi.Pointer< + ffi.NativeFunction)>> + loadResource, + ffi.Pointer> freeResource, + ) { + return _create_filament_viewer( + context, + loadResource, + freeResource, + ); + } + + late final _create_filament_viewerPtr = _lookup< + ffi.NativeFunction< + ffi.Pointer Function( + ffi.Pointer, + ffi.Pointer< + ffi.NativeFunction< + ResourceBuffer Function(ffi.Pointer)>>, + ffi.Pointer< + ffi.NativeFunction>)>>( + 'create_filament_viewer'); + late final _create_filament_viewer = _create_filament_viewerPtr.asFunction< + ffi.Pointer Function( + ffi.Pointer, + ffi.Pointer< + ffi.NativeFunction< + ResourceBuffer Function(ffi.Pointer)>>, + ffi.Pointer>)>(); + + void delete_filament_viewer( + ffi.Pointer viewer, + ) { + return _delete_filament_viewer( + viewer, + ); + } + + late final _delete_filament_viewerPtr = + _lookup)>>( + 'delete_filament_viewer'); + late final _delete_filament_viewer = _delete_filament_viewerPtr + .asFunction)>(); + + ffi.Pointer get_asset_manager( + ffi.Pointer viewer, + ) { + return _get_asset_manager( + viewer, + ); + } + + late final _get_asset_managerPtr = _lookup< + ffi.NativeFunction< + ffi.Pointer Function( + ffi.Pointer)>>('get_asset_manager'); + late final _get_asset_manager = _get_asset_managerPtr + .asFunction Function(ffi.Pointer)>(); + + void create_render_target( + ffi.Pointer viewer, + int textureId, + int width, + int height, + ) { + return _create_render_target( + viewer, + textureId, + width, + height, + ); + } + + late final _create_render_targetPtr = _lookup< + ffi.NativeFunction< + ffi.Void Function(ffi.Pointer, ffi.Uint32, ffi.Uint32, + ffi.Uint32)>>('create_render_target'); + late final _create_render_target = _create_render_targetPtr + .asFunction, int, int, int)>(); + + void clear_background_image( + ffi.Pointer viewer, + ) { + return _clear_background_image( + viewer, + ); + } + + late final _clear_background_imagePtr = + _lookup)>>( + 'clear_background_image'); + late final _clear_background_image = _clear_background_imagePtr + .asFunction)>(); + + void set_background_image( + ffi.Pointer viewer, + ffi.Pointer path, + ) { + return _set_background_image( + viewer, + path, + ); + } + + late final _set_background_imagePtr = _lookup< + ffi.NativeFunction< + ffi.Void Function(ffi.Pointer, + ffi.Pointer)>>('set_background_image'); + late final _set_background_image = _set_background_imagePtr.asFunction< + void Function(ffi.Pointer, ffi.Pointer)>(); + + void set_background_image_position( + ffi.Pointer viewer, + double x, + double y, + int clamp, + ) { + return _set_background_image_position( + viewer, + x, + y, + clamp, + ); + } + + late final _set_background_image_positionPtr = _lookup< + ffi.NativeFunction< + ffi.Void Function(ffi.Pointer, ffi.Float, ffi.Float, + ffi.Int)>>('set_background_image_position'); + late final _set_background_image_position = _set_background_image_positionPtr + .asFunction, double, double, int)>(); + + void set_background_color( + ffi.Pointer viewer, + double r, + double g, + double b, + double a, + ) { + return _set_background_color( + viewer, + r, + g, + b, + a, + ); + } + + late final _set_background_colorPtr = _lookup< + ffi.NativeFunction< + ffi.Void Function(ffi.Pointer, ffi.Float, ffi.Float, + ffi.Float, ffi.Float)>>('set_background_color'); + late final _set_background_color = _set_background_colorPtr.asFunction< + void Function(ffi.Pointer, double, double, double, double)>(); + + void load_skybox( + ffi.Pointer viewer, + ffi.Pointer skyboxPath, + ) { + return _load_skybox( + viewer, + skyboxPath, + ); + } + + late final _load_skyboxPtr = _lookup< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer, ffi.Pointer)>>('load_skybox'); + late final _load_skybox = _load_skyboxPtr.asFunction< + void Function(ffi.Pointer, ffi.Pointer)>(); + + void load_ibl( + ffi.Pointer viewer, + ffi.Pointer iblPath, + double intensity, + ) { + return _load_ibl( + viewer, + iblPath, + intensity, + ); + } + + late final _load_iblPtr = _lookup< + ffi.NativeFunction< + ffi.Void Function(ffi.Pointer, ffi.Pointer, + ffi.Float)>>('load_ibl'); + late final _load_ibl = _load_iblPtr.asFunction< + void Function(ffi.Pointer, ffi.Pointer, double)>(); + + void remove_skybox( + ffi.Pointer viewer, + ) { + return _remove_skybox( + viewer, + ); + } + + late final _remove_skyboxPtr = + _lookup)>>( + 'remove_skybox'); + late final _remove_skybox = + _remove_skyboxPtr.asFunction)>(); + + void remove_ibl( + ffi.Pointer viewer, + ) { + return _remove_ibl( + viewer, + ); + } + + late final _remove_iblPtr = + _lookup)>>( + 'remove_ibl'); + late final _remove_ibl = + _remove_iblPtr.asFunction)>(); + + int add_light( + ffi.Pointer viewer, + int type, + double colour, + double intensity, + double posX, + double posY, + double posZ, + double dirX, + double dirY, + double dirZ, + int shadows, + ) { + return _add_light( + viewer, + type, + colour, + intensity, + posX, + posY, + posZ, + dirX, + dirY, + dirZ, + shadows, + ); + } + + late final _add_lightPtr = _lookup< + ffi.NativeFunction< + EntityId Function( + ffi.Pointer, + ffi.Uint8, + ffi.Float, + ffi.Float, + ffi.Float, + ffi.Float, + ffi.Float, + ffi.Float, + ffi.Float, + ffi.Float, + ffi.Int)>>('add_light'); + late final _add_light = _add_lightPtr.asFunction< + int Function(ffi.Pointer, int, double, double, double, double, + double, double, double, double, int)>(); + + void remove_light( + ffi.Pointer viewer, + int entityId, + ) { + return _remove_light( + viewer, + entityId, + ); + } + + late final _remove_lightPtr = _lookup< + ffi.NativeFunction< + ffi.Void Function(ffi.Pointer, EntityId)>>('remove_light'); + late final _remove_light = + _remove_lightPtr.asFunction, int)>(); + + void clear_lights( + ffi.Pointer viewer, + ) { + return _clear_lights( + viewer, + ); + } + + late final _clear_lightsPtr = + _lookup)>>( + 'clear_lights'); + late final _clear_lights = + _clear_lightsPtr.asFunction)>(); + + int load_glb( + ffi.Pointer assetManager, + ffi.Pointer assetPath, + int unlit, + ) { + return _load_glb( + assetManager, + assetPath, + unlit, + ); + } + + late final _load_glbPtr = _lookup< + ffi.NativeFunction< + EntityId Function(ffi.Pointer, ffi.Pointer, + ffi.Int)>>('load_glb'); + late final _load_glb = _load_glbPtr.asFunction< + int Function(ffi.Pointer, ffi.Pointer, int)>(); + + int load_gltf( + ffi.Pointer assetManager, + ffi.Pointer assetPath, + ffi.Pointer relativePath, + ) { + return _load_gltf( + assetManager, + assetPath, + relativePath, + ); + } + + late final _load_gltfPtr = _lookup< + ffi.NativeFunction< + EntityId Function(ffi.Pointer, ffi.Pointer, + ffi.Pointer)>>('load_gltf'); + late final _load_gltf = _load_gltfPtr.asFunction< + int Function(ffi.Pointer, ffi.Pointer, + ffi.Pointer)>(); + + int set_camera( + ffi.Pointer viewer, + int asset, + ffi.Pointer nodeName, + ) { + return _set_camera( + viewer, + asset, + nodeName, + ); + } + + late final _set_cameraPtr = _lookup< + ffi.NativeFunction< + ffi.Int Function(ffi.Pointer, EntityId, + ffi.Pointer)>>('set_camera'); + late final _set_camera = _set_cameraPtr.asFunction< + int Function(ffi.Pointer, int, ffi.Pointer)>(); + + void render( + ffi.Pointer viewer, + int frameTimeInNanos, + ) { + return _render( + viewer, + frameTimeInNanos, + ); + } + + late final _renderPtr = _lookup< + ffi.NativeFunction< + ffi.Void Function(ffi.Pointer, ffi.Uint64)>>('render'); + late final _render = + _renderPtr.asFunction, int)>(); + + void create_swap_chain( + ffi.Pointer viewer, + ffi.Pointer surface, + int width, + int height, + ) { + return _create_swap_chain( + viewer, + surface, + width, + height, + ); + } + + late final _create_swap_chainPtr = _lookup< + ffi.NativeFunction< + ffi.Void Function(ffi.Pointer, ffi.Pointer, + ffi.Uint32, ffi.Uint32)>>('create_swap_chain'); + late final _create_swap_chain = _create_swap_chainPtr.asFunction< + void Function(ffi.Pointer, ffi.Pointer, int, int)>(); + + void destroy_swap_chain( + ffi.Pointer viewer, + ) { + return _destroy_swap_chain( + viewer, + ); + } + + late final _destroy_swap_chainPtr = + _lookup)>>( + 'destroy_swap_chain'); + late final _destroy_swap_chain = + _destroy_swap_chainPtr.asFunction)>(); + + void set_frame_interval( + ffi.Pointer viewer, + double interval, + ) { + return _set_frame_interval( + viewer, + interval, + ); + } + + late final _set_frame_intervalPtr = _lookup< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer, ffi.Float)>>('set_frame_interval'); + late final _set_frame_interval = _set_frame_intervalPtr + .asFunction, double)>(); + + ffi.Pointer get_renderer( + ffi.Pointer viewer, + ) { + return _get_renderer( + viewer, + ); + } + + late final _get_rendererPtr = _lookup< + ffi.NativeFunction< + ffi.Pointer Function( + ffi.Pointer)>>('get_renderer'); + late final _get_renderer = _get_rendererPtr + .asFunction Function(ffi.Pointer)>(); + + void update_viewport_and_camera_projection( + ffi.Pointer viewer, + int width, + int height, + double scaleFactor, + ) { + return _update_viewport_and_camera_projection( + viewer, + width, + height, + scaleFactor, + ); + } + + late final _update_viewport_and_camera_projectionPtr = _lookup< + ffi.NativeFunction< + ffi.Void Function(ffi.Pointer, ffi.Int, ffi.Int, + ffi.Float)>>('update_viewport_and_camera_projection'); + late final _update_viewport_and_camera_projection = + _update_viewport_and_camera_projectionPtr + .asFunction, int, int, double)>(); + + void scroll_begin( + ffi.Pointer viewer, + ) { + return _scroll_begin( + viewer, + ); + } + + late final _scroll_beginPtr = + _lookup)>>( + 'scroll_begin'); + late final _scroll_begin = + _scroll_beginPtr.asFunction)>(); + + void scroll_update( + ffi.Pointer viewer, + double x, + double y, + double z, + ) { + return _scroll_update( + viewer, + x, + y, + z, + ); + } + + late final _scroll_updatePtr = _lookup< + ffi.NativeFunction< + ffi.Void Function(ffi.Pointer, ffi.Float, ffi.Float, + ffi.Float)>>('scroll_update'); + late final _scroll_update = _scroll_updatePtr.asFunction< + void Function(ffi.Pointer, double, double, double)>(); + + void scroll_end( + ffi.Pointer viewer, + ) { + return _scroll_end( + viewer, + ); + } + + late final _scroll_endPtr = + _lookup)>>( + 'scroll_end'); + late final _scroll_end = + _scroll_endPtr.asFunction)>(); + + void grab_begin( + ffi.Pointer viewer, + double x, + double y, + int pan, + ) { + return _grab_begin( + viewer, + x, + y, + pan, + ); + } + + late final _grab_beginPtr = _lookup< + ffi.NativeFunction< + ffi.Void Function(ffi.Pointer, ffi.Float, ffi.Float, + ffi.Int)>>('grab_begin'); + late final _grab_begin = _grab_beginPtr + .asFunction, double, double, int)>(); + + void grab_update( + ffi.Pointer viewer, + double x, + double y, + ) { + return _grab_update( + viewer, + x, + y, + ); + } + + late final _grab_updatePtr = _lookup< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer, ffi.Float, ffi.Float)>>('grab_update'); + late final _grab_update = _grab_updatePtr + .asFunction, double, double)>(); + + void grab_end( + ffi.Pointer viewer, + ) { + return _grab_end( + viewer, + ); + } + + late final _grab_endPtr = + _lookup)>>( + 'grab_end'); + late final _grab_end = + _grab_endPtr.asFunction)>(); + + void apply_weights( + ffi.Pointer assetManager, + int asset, + ffi.Pointer entityName, + ffi.Pointer weights, + int count, + ) { + return _apply_weights( + assetManager, + asset, + entityName, + weights, + count, + ); + } + + late final _apply_weightsPtr = _lookup< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer, + EntityId, + ffi.Pointer, + ffi.Pointer, + ffi.Int)>>('apply_weights'); + late final _apply_weights = _apply_weightsPtr.asFunction< + void Function(ffi.Pointer, int, ffi.Pointer, + ffi.Pointer, int)>(); + + void set_morph_animation( + ffi.Pointer assetManager, + int asset, + ffi.Pointer entityName, + ffi.Pointer morphData, + int numMorphWeights, + int numFrames, + double frameLengthInMs, + ) { + return _set_morph_animation( + assetManager, + asset, + entityName, + morphData, + numMorphWeights, + numFrames, + frameLengthInMs, + ); + } + + late final _set_morph_animationPtr = _lookup< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer, + EntityId, + ffi.Pointer, + ffi.Pointer, + ffi.Int, + ffi.Int, + ffi.Float)>>('set_morph_animation'); + late final _set_morph_animation = _set_morph_animationPtr.asFunction< + void Function(ffi.Pointer, int, ffi.Pointer, + ffi.Pointer, int, int, double)>(); + + void set_bone_animation( + ffi.Pointer assetManager, + int asset, + int length, + ffi.Pointer> boneNames, + ffi.Pointer> meshNames, + ffi.Pointer frameData, + int numFrames, + double frameLengthInMs, + ) { + return _set_bone_animation( + assetManager, + asset, + length, + boneNames, + meshNames, + frameData, + numFrames, + frameLengthInMs, + ); + } + + late final _set_bone_animationPtr = _lookup< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer, + EntityId, + ffi.Int, + ffi.Pointer>, + ffi.Pointer>, + ffi.Pointer, + ffi.Int, + ffi.Float)>>('set_bone_animation'); + late final _set_bone_animation = _set_bone_animationPtr.asFunction< + void Function( + ffi.Pointer, + int, + int, + ffi.Pointer>, + ffi.Pointer>, + ffi.Pointer, + int, + double)>(); + + void play_animation( + ffi.Pointer assetManager, + int asset, + int index, + int loop, + int reverse, + ) { + return _play_animation( + assetManager, + asset, + index, + loop, + reverse, + ); + } + + late final _play_animationPtr = _lookup< + ffi.NativeFunction< + ffi.Void Function(ffi.Pointer, EntityId, ffi.Int, ffi.Int, + ffi.Int)>>('play_animation'); + late final _play_animation = _play_animationPtr + .asFunction, int, int, int, int)>(); + + void set_animation_frame( + ffi.Pointer assetManager, + int asset, + int animationIndex, + int animationFrame, + ) { + return _set_animation_frame( + assetManager, + asset, + animationIndex, + animationFrame, + ); + } + + late final _set_animation_framePtr = _lookup< + ffi.NativeFunction< + ffi.Void Function(ffi.Pointer, EntityId, ffi.Int, + ffi.Int)>>('set_animation_frame'); + late final _set_animation_frame = _set_animation_framePtr + .asFunction, int, int, int)>(); + + void stop_animation( + ffi.Pointer assetManager, + int asset, + int index, + ) { + return _stop_animation( + assetManager, + asset, + index, + ); + } + + late final _stop_animationPtr = _lookup< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer, EntityId, ffi.Int)>>('stop_animation'); + late final _stop_animation = _stop_animationPtr + .asFunction, int, int)>(); + + int get_animation_count( + ffi.Pointer assetManager, + int asset, + ) { + return _get_animation_count( + assetManager, + asset, + ); + } + + late final _get_animation_countPtr = _lookup< + ffi.NativeFunction< + ffi.Int Function( + ffi.Pointer, EntityId)>>('get_animation_count'); + late final _get_animation_count = _get_animation_countPtr + .asFunction, int)>(); + + void get_animation_name( + ffi.Pointer assetManager, + int asset, + ffi.Pointer outPtr, + int index, + ) { + return _get_animation_name( + assetManager, + asset, + outPtr, + index, + ); + } + + late final _get_animation_namePtr = _lookup< + ffi.NativeFunction< + ffi.Void Function(ffi.Pointer, EntityId, + ffi.Pointer, ffi.Int)>>('get_animation_name'); + late final _get_animation_name = _get_animation_namePtr.asFunction< + void Function(ffi.Pointer, int, ffi.Pointer, int)>(); + + void get_morph_target_name( + ffi.Pointer assetManager, + int asset, + ffi.Pointer meshName, + ffi.Pointer outPtr, + int index, + ) { + return _get_morph_target_name( + assetManager, + asset, + meshName, + outPtr, + index, + ); + } + + late final _get_morph_target_namePtr = _lookup< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer, + EntityId, + ffi.Pointer, + ffi.Pointer, + ffi.Int)>>('get_morph_target_name'); + late final _get_morph_target_name = _get_morph_target_namePtr.asFunction< + void Function(ffi.Pointer, int, ffi.Pointer, + ffi.Pointer, int)>(); + + int get_morph_target_name_count( + ffi.Pointer assetManager, + int asset, + ffi.Pointer meshName, + ) { + return _get_morph_target_name_count( + assetManager, + asset, + meshName, + ); + } + + late final _get_morph_target_name_countPtr = _lookup< + ffi.NativeFunction< + ffi.Int Function(ffi.Pointer, EntityId, + ffi.Pointer)>>('get_morph_target_name_count'); + late final _get_morph_target_name_count = + _get_morph_target_name_countPtr.asFunction< + int Function(ffi.Pointer, int, ffi.Pointer)>(); + + void remove_asset( + ffi.Pointer viewer, + int asset, + ) { + return _remove_asset( + viewer, + asset, + ); + } + + late final _remove_assetPtr = _lookup< + ffi.NativeFunction< + ffi.Void Function(ffi.Pointer, EntityId)>>('remove_asset'); + late final _remove_asset = + _remove_assetPtr.asFunction, int)>(); + + void clear_assets( + ffi.Pointer viewer, + ) { + return _clear_assets( + viewer, + ); + } + + late final _clear_assetsPtr = + _lookup)>>( + 'clear_assets'); + late final _clear_assets = + _clear_assetsPtr.asFunction)>(); + + void load_texture( + ffi.Pointer assetManager, + int asset, + ffi.Pointer assetPath, + int renderableIndex, + ) { + return _load_texture( + assetManager, + asset, + assetPath, + renderableIndex, + ); + } + + late final _load_texturePtr = _lookup< + ffi.NativeFunction< + ffi.Void Function(ffi.Pointer, EntityId, + ffi.Pointer, ffi.Int)>>('load_texture'); + late final _load_texture = _load_texturePtr.asFunction< + void Function(ffi.Pointer, int, ffi.Pointer, int)>(); + + void set_texture( + ffi.Pointer assetManager, + int asset, + ) { + return _set_texture( + assetManager, + asset, + ); + } + + late final _set_texturePtr = _lookup< + ffi.NativeFunction< + ffi.Void Function(ffi.Pointer, EntityId)>>('set_texture'); + late final _set_texture = + _set_texturePtr.asFunction, int)>(); + + void transform_to_unit_cube( + ffi.Pointer assetManager, + int asset, + ) { + return _transform_to_unit_cube( + assetManager, + asset, + ); + } + + late final _transform_to_unit_cubePtr = _lookup< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer, EntityId)>>('transform_to_unit_cube'); + late final _transform_to_unit_cube = _transform_to_unit_cubePtr + .asFunction, int)>(); + + void set_position( + ffi.Pointer assetManager, + int asset, + double x, + double y, + double z, + ) { + return _set_position( + assetManager, + asset, + x, + y, + z, + ); + } + + late final _set_positionPtr = _lookup< + ffi.NativeFunction< + ffi.Void Function(ffi.Pointer, EntityId, ffi.Float, + ffi.Float, ffi.Float)>>('set_position'); + late final _set_position = _set_positionPtr.asFunction< + void Function(ffi.Pointer, int, double, double, double)>(); + + void set_rotation( + ffi.Pointer assetManager, + int asset, + double rads, + double x, + double y, + double z, + ) { + return _set_rotation( + assetManager, + asset, + rads, + x, + y, + z, + ); + } + + late final _set_rotationPtr = _lookup< + ffi.NativeFunction< + ffi.Void Function(ffi.Pointer, EntityId, ffi.Float, + ffi.Float, ffi.Float, ffi.Float)>>('set_rotation'); + late final _set_rotation = _set_rotationPtr.asFunction< + void Function( + ffi.Pointer, int, double, double, double, double)>(); + + void set_scale( + ffi.Pointer assetManager, + int asset, + double scale, + ) { + return _set_scale( + assetManager, + asset, + scale, + ); + } + + late final _set_scalePtr = _lookup< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer, EntityId, ffi.Float)>>('set_scale'); + late final _set_scale = _set_scalePtr + .asFunction, int, double)>(); + + void set_camera_exposure( + ffi.Pointer viewer, + double aperture, + double shutterSpeed, + double sensitivity, + ) { + return _set_camera_exposure( + viewer, + aperture, + shutterSpeed, + sensitivity, + ); + } + + late final _set_camera_exposurePtr = _lookup< + ffi.NativeFunction< + ffi.Void Function(ffi.Pointer, ffi.Float, ffi.Float, + ffi.Float)>>('set_camera_exposure'); + late final _set_camera_exposure = _set_camera_exposurePtr.asFunction< + void Function(ffi.Pointer, double, double, double)>(); + + void set_camera_position( + ffi.Pointer viewer, + double x, + double y, + double z, + ) { + return _set_camera_position( + viewer, + x, + y, + z, + ); + } + + late final _set_camera_positionPtr = _lookup< + ffi.NativeFunction< + ffi.Void Function(ffi.Pointer, ffi.Float, ffi.Float, + ffi.Float)>>('set_camera_position'); + late final _set_camera_position = _set_camera_positionPtr.asFunction< + void Function(ffi.Pointer, double, double, double)>(); + + void set_camera_rotation( + ffi.Pointer viewer, + double rads, + double x, + double y, + double z, + ) { + return _set_camera_rotation( + viewer, + rads, + x, + y, + z, + ); + } + + late final _set_camera_rotationPtr = _lookup< + ffi.NativeFunction< + ffi.Void Function(ffi.Pointer, ffi.Float, ffi.Float, + ffi.Float, ffi.Float)>>('set_camera_rotation'); + late final _set_camera_rotation = _set_camera_rotationPtr.asFunction< + void Function(ffi.Pointer, double, double, double, double)>(); + + void set_camera_model_matrix( + ffi.Pointer viewer, + ffi.Pointer matrix, + ) { + return _set_camera_model_matrix( + viewer, + matrix, + ); + } + + late final _set_camera_model_matrixPtr = _lookup< + ffi.NativeFunction< + ffi.Void Function(ffi.Pointer, + ffi.Pointer)>>('set_camera_model_matrix'); + late final _set_camera_model_matrix = _set_camera_model_matrixPtr.asFunction< + void Function(ffi.Pointer, ffi.Pointer)>(); + + void set_camera_focal_length( + ffi.Pointer viewer, + double focalLength, + ) { + return _set_camera_focal_length( + viewer, + focalLength, + ); + } + + late final _set_camera_focal_lengthPtr = _lookup< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer, ffi.Float)>>('set_camera_focal_length'); + late final _set_camera_focal_length = _set_camera_focal_lengthPtr + .asFunction, double)>(); + + void set_camera_focus_distance( + ffi.Pointer viewer, + double focusDistance, + ) { + return _set_camera_focus_distance( + viewer, + focusDistance, + ); + } + + late final _set_camera_focus_distancePtr = _lookup< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer, ffi.Float)>>('set_camera_focus_distance'); + late final _set_camera_focus_distance = _set_camera_focus_distancePtr + .asFunction, double)>(); +} + +class __fsid_t extends ffi.Struct { + @ffi.Array.multi([2]) + external ffi.Array __val; +} + +class ResourceBuffer extends ffi.Struct { + external ffi.Pointer data; + + @ffi.Uint32() + external int size; + + @ffi.Uint32() + external int id; +} + +typedef EntityId = ffi.Int32; + +const int _STDINT_H = 1; + +const int _FEATURES_H = 1; + +const int _DEFAULT_SOURCE = 1; + +const int __GLIBC_USE_ISOC2X = 1; + +const int __USE_ISOC11 = 1; + +const int __USE_ISOC99 = 1; + +const int __USE_ISOC95 = 1; + +const int _POSIX_SOURCE = 1; + +const int _POSIX_C_SOURCE = 200809; + +const int __USE_POSIX = 1; + +const int __USE_POSIX2 = 1; + +const int __USE_POSIX199309 = 1; + +const int __USE_POSIX199506 = 1; + +const int __USE_XOPEN2K = 1; + +const int __USE_XOPEN2K8 = 1; + +const int _ATFILE_SOURCE = 1; + +const int __USE_MISC = 1; + +const int __USE_ATFILE = 1; + +const int __USE_FORTIFY_LEVEL = 0; + +const int __GLIBC_USE_DEPRECATED_GETS = 0; + +const int __GLIBC_USE_DEPRECATED_SCANF = 0; + +const int _STDC_PREDEF_H = 1; + +const int __STDC_IEC_559__ = 1; + +const int __STDC_IEC_559_COMPLEX__ = 1; + +const int __STDC_ISO_10646__ = 201706; + +const int __GNU_LIBRARY__ = 6; + +const int __GLIBC__ = 2; + +const int __GLIBC_MINOR__ = 33; + +const int _SYS_CDEFS_H = 1; + +const int __THROW = 1; + +const int __THROWNL = 1; + +const int __glibc_c99_flexarr_available = 1; + +const int __WORDSIZE = 64; + +const int __WORDSIZE_TIME64_COMPAT32 = 1; + +const int __SYSCALL_WORDSIZE = 64; + +const int __LDOUBLE_REDIRECTS_TO_FLOAT128_ABI = 0; + +const int __HAVE_GENERIC_SELECTION = 0; + +const int __GLIBC_USE_LIB_EXT2 = 1; + +const int __GLIBC_USE_IEC_60559_BFP_EXT = 1; + +const int __GLIBC_USE_IEC_60559_BFP_EXT_C2X = 1; + +const int __GLIBC_USE_IEC_60559_FUNCS_EXT = 1; + +const int __GLIBC_USE_IEC_60559_FUNCS_EXT_C2X = 1; + +const int __GLIBC_USE_IEC_60559_TYPES_EXT = 1; + +const int _BITS_TYPES_H = 1; + +const int __TIMESIZE = 64; + +const int _BITS_TYPESIZES_H = 1; + +const int __OFF_T_MATCHES_OFF64_T = 1; + +const int __INO_T_MATCHES_INO64_T = 1; + +const int __RLIM_T_MATCHES_RLIM64_T = 1; + +const int __STATFS_MATCHES_STATFS64 = 1; + +const int __KERNEL_OLD_TIMEVAL_MATCHES_TIMEVAL64 = 1; + +const int __FD_SETSIZE = 1024; + +const int _BITS_TIME64_H = 1; + +const int _BITS_WCHAR_H = 1; + +const int __WCHAR_MAX = 2147483647; + +const int __WCHAR_MIN = -2147483648; + +const int _BITS_STDINT_INTN_H = 1; + +const int _BITS_STDINT_UINTN_H = 1; + +const int INT8_MIN = -128; + +const int INT16_MIN = -32768; + +const int INT32_MIN = -2147483648; + +const int INT64_MIN = -9223372036854775808; + +const int INT8_MAX = 127; + +const int INT16_MAX = 32767; + +const int INT32_MAX = 2147483647; + +const int INT64_MAX = 9223372036854775807; + +const int UINT8_MAX = 255; + +const int UINT16_MAX = 65535; + +const int UINT32_MAX = 4294967295; + +const int UINT64_MAX = -1; + +const int INT_LEAST8_MIN = -128; + +const int INT_LEAST16_MIN = -32768; + +const int INT_LEAST32_MIN = -2147483648; + +const int INT_LEAST64_MIN = -9223372036854775808; + +const int INT_LEAST8_MAX = 127; + +const int INT_LEAST16_MAX = 32767; + +const int INT_LEAST32_MAX = 2147483647; + +const int INT_LEAST64_MAX = 9223372036854775807; + +const int UINT_LEAST8_MAX = 255; + +const int UINT_LEAST16_MAX = 65535; + +const int UINT_LEAST32_MAX = 4294967295; + +const int UINT_LEAST64_MAX = -1; + +const int INT_FAST8_MIN = -128; + +const int INT_FAST16_MIN = -9223372036854775808; + +const int INT_FAST32_MIN = -9223372036854775808; + +const int INT_FAST64_MIN = -9223372036854775808; + +const int INT_FAST8_MAX = 127; + +const int INT_FAST16_MAX = 9223372036854775807; + +const int INT_FAST32_MAX = 9223372036854775807; + +const int INT_FAST64_MAX = 9223372036854775807; + +const int UINT_FAST8_MAX = 255; + +const int UINT_FAST16_MAX = -1; + +const int UINT_FAST32_MAX = -1; + +const int UINT_FAST64_MAX = -1; + +const int INTPTR_MIN = -9223372036854775808; + +const int INTPTR_MAX = 9223372036854775807; + +const int UINTPTR_MAX = -1; + +const int INTMAX_MIN = -9223372036854775808; + +const int INTMAX_MAX = 9223372036854775807; + +const int UINTMAX_MAX = -1; + +const int PTRDIFF_MIN = -9223372036854775808; + +const int PTRDIFF_MAX = 9223372036854775807; + +const int SIG_ATOMIC_MIN = -2147483648; + +const int SIG_ATOMIC_MAX = 2147483647; + +const int SIZE_MAX = -1; + +const int WCHAR_MIN = -2147483648; + +const int WCHAR_MAX = 2147483647; + +const int WINT_MIN = 0; + +const int WINT_MAX = 4294967295; diff --git a/linux/CMakeLists.txt b/linux/CMakeLists.txt index d5c7dd19..a222614d 100644 --- a/linux/CMakeLists.txt +++ b/linux/CMakeLists.txt @@ -29,11 +29,11 @@ add_library(${PLUGIN_NAME} SHARED "polyvox_filament_plugin.cc" "filament_texture.cc" "filament_pb_texture.cc" - "${CMAKE_CURRENT_SOURCE_DIR}/../ios/src/SceneAssetLoader.cpp" - "${CMAKE_CURRENT_SOURCE_DIR}/../ios/src/SceneAsset.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/../ios/src/AssetManager.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/../ios/src/FilamentViewer.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/../ios/src/PolyvoxFilamentApi.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/../ios/src/StreamBufferAdapter.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/../ios/src/TimeIt.cpp" ) # Apply a standard set of build settings that are configured in the diff --git a/linux/include/polyvox_filament/resource_loader.hpp b/linux/include/polyvox_filament/resource_loader.hpp index c05c2c5e..806f0d49 100644 --- a/linux/include/polyvox_filament/resource_loader.hpp +++ b/linux/include/polyvox_filament/resource_loader.hpp @@ -19,6 +19,8 @@ static uint32_t _i = 0; ResourceBuffer loadResource(const char* name) { + std::cout << "LOADING RESOURCE" << std::endl; + char cwd[PATH_MAX]; if (getcwd(cwd, sizeof(cwd)) != NULL) { std::cout << "Current working dir: " << cwd << std::endl; diff --git a/linux/polyvox_filament_plugin.cc b/linux/polyvox_filament_plugin.cc index 204bc38b..b087c86c 100644 --- a/linux/polyvox_filament_plugin.cc +++ b/linux/polyvox_filament_plugin.cc @@ -40,7 +40,7 @@ struct _PolyvoxFilamentPlugin { FlTextureRegistrar* texture_registrar; FlView* fl_view; FlTexture* texture; - void* _viewer; + void* viewer; double width; double height; @@ -52,26 +52,22 @@ struct _PolyvoxFilamentPlugin { G_DEFINE_TYPE(PolyvoxFilamentPlugin, polyvox_filament_plugin, g_object_get_type()) +// unused, left here for posterity in case we want to restore static gboolean on_frame_tick(GtkWidget* widget, GdkFrameClock* frame_clock, gpointer self) { PolyvoxFilamentPlugin* plugin = (PolyvoxFilamentPlugin*)self; if(plugin->_rendering) { - render(plugin->_viewer, 0); + render(plugin->viewer, 0); fl_texture_registrar_mark_texture_frame_available(plugin->texture_registrar, plugin->texture); } return TRUE; } - -static FlMethodResponse* _initialize(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { - - if(self->_viewer) { - Log("Deleting existing viewer"); - filament_viewer_delete(self->_viewer); +static FlMethodResponse* _create_texture(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { + if(self->texture) { + Log("Error - create_texture called when texture exists."); } - auto context = glXGetCurrentContext(); - FlValue* args = fl_method_call_get_args(method_call); const double width = fl_value_get_float(fl_value_get_list_value(args, 0)); @@ -83,21 +79,6 @@ static FlMethodResponse* _initialize(PolyvoxFilamentPlugin* self, FlMethodCall* auto texture = create_filament_texture(uint32_t(width), uint32_t(height), self->texture_registrar); //auto texture = create_filament_pb_texture(uint32_t(width), uint32_t(height), self->texture_registrar); self->texture = texture; - - self->_viewer = filament_viewer_new( - (void*)context, - loadResource, - freeResource - ); - - GtkWidget *w = gtk_widget_get_toplevel (GTK_WIDGET(self->fl_view)); - gtk_widget_add_tick_callback(w, on_frame_tick, self,NULL); - - // don't pass a surface to the SwapChain as we are effectively creating a headless SwapChain that will render into a RenderTarget associated with a texture - create_swap_chain(self->_viewer, nullptr, width, height); - create_render_target(self->_viewer, ((FilamentTextureGL*)texture)->texture_id,width,height); - - update_viewport_and_camera_projection(self->_viewer, width, height, 1.0f); g_autoptr(FlValue) result = fl_value_new_int(reinterpret_cast(texture)); @@ -105,451 +86,6 @@ static FlMethodResponse* _initialize(PolyvoxFilamentPlugin* self, FlMethodCall* return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); } -static FlMethodResponse* _loadSkybox(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { - FlValue* args = fl_method_call_get_args(method_call); - - const gchar* path = fl_value_get_string(args); - - load_skybox(self->_viewer, path); - - g_autoptr(FlValue) result = fl_value_new_string("OK"); - return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); -} - -static FlMethodResponse* _remove_ibl(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { - remove_ibl(self->_viewer); - g_autoptr(FlValue) result = fl_value_new_string("OK"); - return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); -} - -static FlMethodResponse* _loadIbl(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { - FlValue* args = fl_method_call_get_args(method_call); - - auto path = fl_value_get_string(fl_value_get_list_value(args, 0)); - auto intensity = fl_value_get_float(fl_value_get_list_value(args, 1)); - - load_ibl(self->_viewer, path, intensity); - - g_autoptr(FlValue) result = fl_value_new_string("OK"); - return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); -} - -static FlMethodResponse* _removeSkybox(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { - std::cout << "Removing skybox" << std::endl; - remove_skybox(self->_viewer); - g_autoptr(FlValue) result = fl_value_new_string("OK"); - return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); -} - -static FlMethodResponse* _set_background_image(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { - - FlValue* args = fl_method_call_get_args(method_call); - - const gchar* path = fl_value_get_string(args); - - set_background_image(self->_viewer, path); - - g_autoptr(FlValue) result = fl_value_new_string("OK"); - return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); -} - -static FlMethodResponse* _set_background_color(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { - - const float* color = fl_value_get_float32_list(fl_method_call_get_args(method_call)); - set_background_color(self->_viewer, color[0], color[1], color[2], color[2]); - - g_autoptr(FlValue) result = fl_value_new_string("OK"); - return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); -} - -static FlMethodResponse* _add_light(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { - - FlValue* args = fl_method_call_get_args(method_call); - - auto type = (uint8_t)fl_value_get_int(fl_value_get_list_value(args, 0)); - auto color = (float)fl_value_get_float(fl_value_get_list_value(args, 1)); - auto intensity = float(fl_value_get_float(fl_value_get_list_value(args, 2))); - auto posX = (float)fl_value_get_float(fl_value_get_list_value(args, 3)); - auto posY = (float)fl_value_get_float(fl_value_get_list_value(args, 4)); - auto posZ = (float)fl_value_get_float(fl_value_get_list_value(args, 5)); - auto dirX = (float)fl_value_get_float(fl_value_get_list_value(args, 6)); - auto dirY = (float)fl_value_get_float(fl_value_get_list_value(args, 7)); - auto dirZ = (float)fl_value_get_float(fl_value_get_list_value(args, 8)); - auto shadows = fl_value_get_bool(fl_value_get_list_value(args, 9)); - - auto entityId = add_light(self->_viewer, type, color, intensity, posX, posY, posZ, dirX, dirY, dirZ, shadows); - g_autoptr(FlValue) result = fl_value_new_int(entityId); - return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); - -} - -static FlMethodResponse* _load_glb(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { - FlValue* args = fl_method_call_get_args(method_call); - auto path = fl_value_get_string(fl_value_get_list_value(args, 0)); - auto unlit = fl_value_get_bool(fl_value_get_list_value(args, 1)); - auto entityId = load_glb(self->_viewer, path, unlit); - g_autoptr(FlValue) result = fl_value_new_int((int64_t)entityId); - return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); -} - -static FlMethodResponse* _get_animation_names(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { - - FlValue* args = fl_method_call_get_args(method_call); - auto assetPtr = (void*)fl_value_get_int(args); - g_autoptr(FlValue) result = fl_value_new_list(); - - auto numNames = get_animation_count(assetPtr); - - for(int i = 0; i < numNames; i++) { - gchar out[255]; - get_animation_name(assetPtr, out, i); - fl_value_append_take (result, fl_value_new_string (out)); - } - - return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); -} - -static FlMethodResponse* _remove_asset(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { - FlValue* args = fl_method_call_get_args(method_call); - auto assetPtr = (void*)fl_value_get_int(args); - remove_asset(self->_viewer, assetPtr); - g_autoptr(FlValue) result = fl_value_new_string("OK"); - return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); -} - -static FlMethodResponse* _transform_to_unit_cube(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { - FlValue* args = fl_method_call_get_args(method_call); - auto assetPtr = (void*)fl_value_get_int(args); - transform_to_unit_cube(assetPtr); - g_autoptr(FlValue) result = fl_value_new_string("OK"); - return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); -} - -static FlMethodResponse* _rotate_start(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { - FlValue* args = fl_method_call_get_args(method_call); - - auto x = (float)fl_value_get_float(fl_value_get_list_value(args, 0)); - auto y = (float)fl_value_get_float(fl_value_get_list_value(args, 1)); - - grab_begin(self->_viewer, x,y, false); - - g_autoptr(FlValue) result = fl_value_new_string("OK"); - return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); -} - -static FlMethodResponse* _rotate_end(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { - grab_end(self->_viewer); - g_autoptr(FlValue) result = fl_value_new_string("OK"); - return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); -} - -static FlMethodResponse* _rotate_update(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { - FlValue* args = fl_method_call_get_args(method_call); - auto x = (float)fl_value_get_float(fl_value_get_list_value(args, 0)); - auto y = (float)fl_value_get_float(fl_value_get_list_value(args, 1)); - - grab_update(self->_viewer, x,y); - - g_autoptr(FlValue) result = fl_value_new_string("OK"); - return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); -} - -static FlMethodResponse* _pan_start(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { - - FlValue* args = fl_method_call_get_args(method_call); - - auto x = (float)fl_value_get_float(fl_value_get_list_value(args, 0)); - auto y = (float)fl_value_get_float(fl_value_get_list_value(args, 1)); - - grab_begin(self->_viewer, x,y, true); - g_autoptr(FlValue) result = fl_value_new_string("OK"); - return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); -} - -static FlMethodResponse* _pan_update(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { - FlValue* args = fl_method_call_get_args(method_call); - auto x = (float)fl_value_get_float(fl_value_get_list_value(args, 0)); - auto y = (float)fl_value_get_float(fl_value_get_list_value(args, 1)); - - grab_update(self->_viewer, x,y); - g_autoptr(FlValue) result = fl_value_new_string("OK"); - return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); -} - -static FlMethodResponse* _pan_end(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { - grab_end(self->_viewer); - g_autoptr(FlValue) result = fl_value_new_string("OK"); - return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); -} - -static FlMethodResponse* _set_position(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { - FlValue* args = fl_method_call_get_args(method_call); - auto assetPtr = (void*)fl_value_get_int(fl_value_get_list_value(args, 0)); - - set_position( - assetPtr, - (float)fl_value_get_float(fl_value_get_list_value(args, 1)), // x - (float)fl_value_get_float(fl_value_get_list_value(args, 2)), // y - (float)fl_value_get_float(fl_value_get_list_value(args, 3)) // z - ); - g_autoptr(FlValue) result = fl_value_new_string("OK"); - return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); -} - -static FlMethodResponse* _set_rotation(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { - FlValue* args = fl_method_call_get_args(method_call); - auto assetPtr = (void*)fl_value_get_int(fl_value_get_list_value(args, 0)); - - set_rotation( - assetPtr, - (float)fl_value_get_float(fl_value_get_list_value(args, 1)), // rads - (float)fl_value_get_float(fl_value_get_list_value(args, 2)), // x - (float)fl_value_get_float(fl_value_get_list_value(args, 3)), // y - (float)fl_value_get_float(fl_value_get_list_value(args, 4)) // z - ); - g_autoptr(FlValue) result = fl_value_new_string("OK"); - return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); -} - - - -// static FlMethodResponse* _set_bone_transform(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { -// FlValue* args = fl_method_call_get_args(method_call); -// auto assetPtr = (void*)fl_value_get_int(fl_value_get_list_value(args, 0)); -// auto boneName = fl_value_get_string(fl_value_get_list_value(args, 1)); -// auto meshName = fl_value_get_string(fl_value_get_list_value(args, 2)); - -// set_bone_transform( -// assetPtr, -// boneName, -// meshName, -// (float)fl_value_get_float(fl_value_get_list_value(args, 3)), // transX -// (float)fl_value_get_float(fl_value_get_list_value(args, 4)), // transY -// (float)fl_value_get_float(fl_value_get_list_value(args, 5)), // transZ -// (float)fl_value_get_float(fl_value_get_list_value(args, 6)), // quatX -// (float)fl_value_get_float(fl_value_get_list_value(args, 7)), // quatY -// (float)fl_value_get_float(fl_value_get_list_value(args, 8)), // quatZ -// (float)fl_value_get_float(fl_value_get_list_value(args, 9)) // quatW -// ); -// g_autoptr(FlValue) result = fl_value_new_string("OK"); -// return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); -// } - -static FlMethodResponse* _set_camera(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { - FlValue* args = fl_method_call_get_args(method_call); - auto assetPtr = (void*)fl_value_get_int(fl_value_get_list_value(args, 0)); - auto cameraName = fl_value_get_string(fl_value_get_list_value(args, 1)) ; - - set_camera(self->_viewer, (void*)assetPtr, cameraName); - g_autoptr(FlValue) result = fl_value_new_string("OK"); - return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); -} - -static FlMethodResponse* _set_camera_model_matrix(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { - FlValue* args = fl_method_call_get_args(method_call); - set_camera_model_matrix(self->_viewer, fl_value_get_float32_list(args)); - g_autoptr(FlValue) result = fl_value_new_string("OK"); - return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); -} - -static FlMethodResponse* _set_camera_exposure(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { - FlValue* args = fl_method_call_get_args(method_call); - auto aperture = (float)fl_value_get_float(fl_value_get_list_value(args, 0)); - auto shutter_speed = (float)fl_value_get_float(fl_value_get_list_value(args, 1)); - auto sensitivity = (float)fl_value_get_float(fl_value_get_list_value(args, 2)); - set_camera_exposure(self->_viewer, aperture, shutter_speed, sensitivity); - g_autoptr(FlValue) result = fl_value_new_string("OK"); - return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); -} - -static FlMethodResponse* _set_camera_position(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { - FlValue* args = fl_method_call_get_args(method_call); - auto x = (float)fl_value_get_float(fl_value_get_list_value(args, 0)); - auto y = (float)fl_value_get_float(fl_value_get_list_value(args, 1)); - auto z = (float)fl_value_get_float(fl_value_get_list_value(args, 2)); - set_camera_position(self->_viewer, x,y, z); - g_autoptr(FlValue) result = fl_value_new_string("OK"); - return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); -} - -static FlMethodResponse* _set_camera_rotation(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { - FlValue* args = fl_method_call_get_args(method_call); - auto rads = (float)fl_value_get_float(fl_value_get_list_value(args,0 )); - auto x = (float)fl_value_get_float(fl_value_get_list_value(args, 1)); - auto y = (float)fl_value_get_float(fl_value_get_list_value(args, 2)); - auto z = (float)fl_value_get_float(fl_value_get_list_value(args, 3)); - - set_camera_rotation(self->_viewer, rads, x,y, z); - g_autoptr(FlValue) result = fl_value_new_string("OK"); - return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); -} - -static FlMethodResponse* _set_rendering(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { - FlValue* args = fl_method_call_get_args(method_call); - self->_rendering = (bool)fl_value_get_bool(args); - g_autoptr(FlValue) result = fl_value_new_string("OK"); - return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); -} - -static FlMethodResponse* _set_frame_interval(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { - FlValue* args = fl_method_call_get_args(method_call); - auto val = (float) fl_value_get_float(args); - set_frame_interval(self->_viewer, val); - g_autoptr(FlValue) result = fl_value_new_string("OK"); - return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); -} - -static FlMethodResponse* _zoom_begin(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { - scroll_begin(self->_viewer); - g_autoptr(FlValue) result = fl_value_new_string("OK"); - return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); -} - -static FlMethodResponse* _zoom_end(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { - scroll_end(self->_viewer); - g_autoptr(FlValue) result = fl_value_new_string("OK"); - return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); -} - -static FlMethodResponse* _zoom_update(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { - FlValue* args = fl_method_call_get_args(method_call); - auto x = (float)fl_value_get_float(fl_value_get_list_value(args, 0)); - auto y = (float)fl_value_get_float(fl_value_get_list_value(args, 1)); - auto z = (float)fl_value_get_float(fl_value_get_list_value(args, 2)); - - scroll_update(self->_viewer, x,y, z); - g_autoptr(FlValue) result = fl_value_new_string("OK"); - return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); -} - -static FlMethodResponse* _play_animation(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { - FlValue* args = fl_method_call_get_args(method_call); - auto assetPtr = (void*)fl_value_get_int(fl_value_get_list_value(args, 0)); - auto animationId = (int)fl_value_get_int(fl_value_get_list_value(args, 1)); - auto loop = (bool)fl_value_get_bool(fl_value_get_list_value(args, 2)); - auto reverse = (bool)fl_value_get_bool(fl_value_get_list_value(args, 3)); - play_animation(assetPtr, animationId, loop, reverse); - g_autoptr(FlValue) result = fl_value_new_string("OK"); - return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); -} - - -static FlMethodResponse* _stop_animation(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { - FlValue* args = fl_method_call_get_args(method_call); - auto assetPtr = (void*)fl_value_get_int(fl_value_get_list_value(args, 0)); - auto animationId = (int)fl_value_get_int(fl_value_get_list_value(args, 1)); - stop_animation(assetPtr, animationId); - g_autoptr(FlValue) result = fl_value_new_string("OK"); - return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); -} - -static FlMethodResponse* _apply_weights(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { - FlValue* args = fl_method_call_get_args(method_call); - auto assetPtr = (void*)fl_value_get_int(fl_value_get_list_value(args, 0)); - auto entityName = fl_value_get_string(fl_value_get_list_value(args, 1)); - auto weightsValue = fl_value_get_list_value(args, 2); - float* const weights = (float* const) fl_value_get_float32_list(weightsValue); - size_t len = fl_value_get_length(weightsValue); - apply_weights(assetPtr, entityName, weights, (int)len); - g_autoptr(FlValue) result = fl_value_new_string("OK"); - return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); -} - -static FlMethodResponse* _set_animation(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { - FlValue* args = fl_method_call_get_args(method_call); - auto assetPtr = (void*)fl_value_get_int(fl_value_get_list_value(args, 0)); - - const char* entityName = fl_value_get_string(fl_value_get_list_value(args, 1)); - - float* const morphData = (float* const) fl_value_get_float32_list(fl_value_get_list_value(args, 2)); - - int64_t numMorphWeights = fl_value_get_int(fl_value_get_list_value(args, 3)); - - FlValue* flBoneAnimations = fl_value_get_list_value(args, 4); - - size_t numBoneAnimations = fl_value_get_length(flBoneAnimations); - - vector boneAnimations; - - for(int i = 0; i < numBoneAnimations; i++) { - - FlValue* flBoneAnimation = fl_value_get_list_value(flBoneAnimations, i); - - FlValue* flBoneNames = fl_value_get_list_value(flBoneAnimation, 0); - FlValue* flMeshNames = fl_value_get_list_value(flBoneAnimation, 1); - float* const frameData = (float* const) fl_value_get_float32_list(fl_value_get_list_value(flBoneAnimation, 2)); - - Log("Framedata %f", frameData); - - vector boneNames; - boneNames.resize(fl_value_get_length(flBoneNames)); - - for(int i=0; i < boneNames.size(); i++) { - boneNames[i] = fl_value_get_string(fl_value_get_list_value(flBoneNames, i)) ; - } - - vector meshNames; - meshNames.resize(fl_value_get_length(flMeshNames)); - for(int i=0; i < meshNames.size(); i++) { - meshNames[i] = fl_value_get_string(fl_value_get_list_value(flMeshNames, i)); - } - - const char** boneNamesPtr = (const char**)malloc(boneNames.size() * sizeof(char*)); - memcpy((void*)boneNamesPtr, (void*)boneNames.data(), boneNames.size() * sizeof(char*)); - auto meshNamesPtr = (const char**)malloc(meshNames.size() * sizeof(char*)); - memcpy((void*)meshNamesPtr, (void*)meshNames.data(), meshNames.size() * sizeof(char*)); - - BoneAnimation animation { - .boneNames = boneNamesPtr, - .meshNames = meshNamesPtr, - .data = frameData, - .numBones = boneNames.size(), - .numMeshTargets = meshNames.size() - }; - - boneAnimations.push_back(animation); - - } - - int64_t numFrames = fl_value_get_int(fl_value_get_list_value(args, 5)); - - float frameLengthInMs = fl_value_get_float(fl_value_get_list_value(args, 6)); - - auto boneAnimationsPointer = boneAnimations.data(); - auto boneAnimationsSize = boneAnimations.size(); - - set_animation( - assetPtr, - entityName, - morphData, - numMorphWeights, - boneAnimationsPointer, - boneAnimationsSize, - numFrames, - frameLengthInMs); - - g_autoptr(FlValue) result = fl_value_new_string("OK"); - return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); -} - -static FlMethodResponse* _get_morph_target_names(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { - FlValue* args = fl_method_call_get_args(method_call); - auto assetPtr = (void*)fl_value_get_int(fl_value_get_list_value(args, 0)); - auto meshName = fl_value_get_string(fl_value_get_list_value(args, 1)); - g_autoptr(FlValue) result = fl_value_new_list(); - - auto numNames = get_morph_target_name_count(assetPtr, meshName); - - std::cout << numNames << " morph targets found in mesh " << meshName << std::endl; - - for(int i = 0; i < numNames; i++) { - gchar out[255]; - get_morph_target_name(assetPtr, meshName, out, i); - fl_value_append_take (result, fl_value_new_string (out)); - } - - return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); -} // TODO - defer the destruction of the old texture until this call has returned // otherwise the front-end may render using the destroyed texture ID for a single frame (hopefully no more) @@ -563,16 +99,16 @@ static FlMethodResponse* _resize(PolyvoxFilamentPlugin* self, FlMethodCall* meth self->_rendering = false; self->_resizing = true; - destroy_swap_chain(self->_viewer); + destroy_swap_chain(self->viewer); destroy_filament_texture(self->texture, self->texture_registrar); self->texture = create_filament_texture(uint32_t(width), uint32_t(height), self->texture_registrar); - create_swap_chain(self->_viewer, nullptr, width, height); - create_render_target(self->_viewer, ((FilamentTextureGL*)self->texture)->texture_id,width,height); + create_swap_chain(self->viewer, nullptr, width, height); + create_render_target(self->viewer, ((FilamentTextureGL*)self->texture)->texture_id,width,height); - update_viewport_and_camera_projection(self->_viewer, width, height, 1.0f); + update_viewport_and_camera_projection(self->viewer, width, height, 1.0f); std::cout << "Created new texture " << self->texture << std::endl; @@ -596,92 +132,32 @@ static void polyvox_filament_plugin_handle_method_call( const gchar* method = fl_method_call_get_name(method_call); - if(strcmp(method, "initialize") == 0) { - response = _initialize(self, method_call); - } else if(strcmp(method, "loadSkybox") == 0) { - response = _loadSkybox(self, method_call); - } else if(strcmp(method, "loadIbl") == 0) { - response = _loadIbl(self, method_call); - } else if(strcmp(method, "removeIbl") ==0) { - response = _remove_ibl(self, method_call); - } else if(strcmp(method, "removeSkybox") == 0) { - response = _removeSkybox(self, method_call); - } else if(strcmp(method, "resize") == 0) { - response = _resize(self, method_call); - } else if(strcmp(method, "render") == 0) { - render(self->_viewer, 0); - g_autoptr(FlValue) result = fl_value_new_string("OK"); - response = FL_METHOD_RESPONSE(fl_method_success_response_new(result)); - } else if(strcmp(method, "setBackgroundColor") == 0) { - response = _set_background_color(self, method_call); - } else if(strcmp(method, "setBackgroundImage") == 0) { - response = _set_background_image(self, method_call); - } else if(strcmp(method, "addLight") == 0) { - response = _add_light(self, method_call); - } else if(strcmp(method, "loadGlb") == 0) { - response = _load_glb(self, method_call); - } else if(strcmp(method, "getAnimationNames") == 0) { - response = _get_animation_names(self, method_call); - } else if(strcmp(method, "clearAssets") == 0) { - clear_assets(self->_viewer); - g_autoptr(FlValue) result = fl_value_new_string("OK"); - response = FL_METHOD_RESPONSE(fl_method_success_response_new(result)); - } else if(strcmp(method, "removeAsset") == 0) { - response = _remove_asset(self, method_call); - } else if(strcmp(method, "transformToUnitCube") == 0) { - response = _transform_to_unit_cube(self, method_call); - } else if(strcmp(method, "clearLights") == 0) { - clear_lights(self->_viewer); - g_autoptr(FlValue) result = fl_value_new_string("OK"); - response = FL_METHOD_RESPONSE(fl_method_success_response_new(result)); - } else if(strcmp(method, "panStart") == 0) { - response = _pan_start(self, method_call); - } else if(strcmp(method, "panEnd") == 0) { - response = _pan_end(self, method_call); - } else if(strcmp(method, "panUpdate") == 0) { - response = _pan_update(self, method_call); - } else if(strcmp(method, "rotateStart") == 0) { - response = _rotate_start(self, method_call); - } else if(strcmp(method, "rotateEnd") == 0) { - response = _rotate_end(self, method_call); - } else if(strcmp(method, "rotateUpdate") == 0) { - response = _rotate_update(self, method_call); - } else if(strcmp(method, "setRotation") == 0) { - response = _set_rotation(self, method_call); - } else if(strcmp(method, "setCamera") == 0) { - response = _set_camera(self, method_call); - } else if(strcmp(method, "setCameraModelMatrix") == 0) { - response = _set_camera_model_matrix(self, method_call); - } else if(strcmp(method, "setCameraExposure") == 0) { - response = _set_camera_exposure(self, method_call); - } else if(strcmp(method, "setCameraPosition") == 0) { - response = _set_camera_position(self, method_call); - } else if(strcmp(method, "setCameraRotation") == 0) { - response = _set_camera_rotation(self, method_call); - } else if(strcmp(method, "setRendering") == 0) { - response = _set_rendering(self, method_call); - } else if(strcmp(method, "setFrameInterval") == 0) { - response = _set_frame_interval(self, method_call); - } else if(strcmp(method, "zoomBegin") == 0) { - response = _zoom_begin(self, method_call); - } else if(strcmp(method, "zoomEnd") == 0) { - response = _zoom_end(self, method_call); - } else if(strcmp(method, "zoomUpdate") == 0) { - response = _zoom_update(self, method_call); - } else if(strcmp(method, "playAnimation") == 0) { - response = _play_animation(self, method_call); - } else if(strcmp(method, "stopAnimation") == 0) { - response = _stop_animation(self, method_call); - } else if(strcmp(method, "setMorphTargetWeights") == 0) { - response = _apply_weights(self, method_call); - } else if(strcmp(method, "setAnimation") == 0) { - response = _set_animation(self, method_call); - } else if(strcmp(method, "getMorphTargetNames") == 0) { - response = _get_morph_target_names(self, method_call); - } else if(strcmp(method, "setPosition") == 0) { - response = _set_position(self, method_call); - } else if(strcmp(method, "setBoneTransform") == 0) { - // response = _set_bone_transform(self, method_call); + if(strcmp(method, "createTexture") == 0) { + response = _create_texture(self, method_call); + } else if(strcmp(method, "getContext") == 0) { + g_autoptr(FlValue) result = + fl_value_new_int(reinterpret_cast(glXGetCurrentContext())); + response = FL_METHOD_RESPONSE(fl_method_success_response_new(result)); + } else if(strcmp(method, "getGlTextureId") == 0) { + g_autoptr(FlValue) result = + fl_value_new_int(reinterpret_cast(((FilamentTextureGL*)self->texture)->texture_id)); + response = FL_METHOD_RESPONSE(fl_method_success_response_new(result)); + } else if(strcmp(method, "getLoadResourceFn") == 0) { + g_autoptr(FlValue) result = + fl_value_new_int(reinterpret_cast(loadResource)); + response = FL_METHOD_RESPONSE(fl_method_success_response_new(result)); + } else if(strcmp(method, "getFreeResourceFn") == 0) { + g_autoptr(FlValue) result = + fl_value_new_int(reinterpret_cast(&freeResource)); + response = FL_METHOD_RESPONSE(fl_method_success_response_new(result)); + } else if(strcmp(method, "getRenderCallback") == 0) { + GtkWidget *w = gtk_widget_get_toplevel (GTK_WIDGET(self->fl_view)); + gtk_widget_add_tick_callback(w, on_frame_tick, self,NULL); + response = FL_METHOD_RESPONSE(fl_method_success_response_new(fl_value_new_string("OK"))); + } else if(strcmp(method, "onFrameAvailable") == 0) { + fl_texture_registrar_mark_texture_frame_available(self->texture_registrar, + self->texture); + response = FL_METHOD_RESPONSE(fl_method_success_response_new(fl_value_new_string("OK"))); } else { response = FL_METHOD_RESPONSE(fl_method_not_implemented_response_new()); } @@ -726,3 +202,537 @@ void polyvox_filament_plugin_register_with_registrar(FlPluginRegistrar* registra g_object_unref(plugin); } + + + + + + +// static FlMethodResponse* _loadSkybox(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { +// FlValue* args = fl_method_call_get_args(method_call); + +// const gchar* path = fl_value_get_string(args); + +// load_skybox(self->viewer, path); + +// g_autoptr(FlValue) result = fl_value_new_string("OK"); +// return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +// } + +// static FlMethodResponse* _remove_ibl(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { +// remove_ibl(self->viewer); +// g_autoptr(FlValue) result = fl_value_new_string("OK"); +// return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +// } + +// static FlMethodResponse* _loadIbl(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { +// FlValue* args = fl_method_call_get_args(method_call); + +// auto path = fl_value_get_string(fl_value_get_list_value(args, 0)); +// auto intensity = fl_value_get_float(fl_value_get_list_value(args, 1)); + +// load_ibl(self->viewer, path, intensity); + +// g_autoptr(FlValue) result = fl_value_new_string("OK"); +// return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +// } + +// static FlMethodResponse* _removeSkybox(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { +// std::cout << "Removing skybox" << std::endl; +// remove_skybox(self->viewer); +// g_autoptr(FlValue) result = fl_value_new_string("OK"); +// return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +// } + +// static FlMethodResponse* _set_background_image(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { + +// FlValue* args = fl_method_call_get_args(method_call); + +// const gchar* path = fl_value_get_string(args); + +// set_background_image(self->viewer, path); + +// g_autoptr(FlValue) result = fl_value_new_string("OK"); +// return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +// } + +// static FlMethodResponse* _set_background_color(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { + +// const float* color = fl_value_get_float32_list(fl_method_call_get_args(method_call)); +// set_background_color(self->viewer, color[0], color[1], color[2], color[2]); + +// g_autoptr(FlValue) result = fl_value_new_string("OK"); +// return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +// } + +// static FlMethodResponse* _add_light(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { + +// FlValue* args = fl_method_call_get_args(method_call); + +// auto type = (uint8_t)fl_value_get_int(fl_value_get_list_value(args, 0)); +// auto color = (float)fl_value_get_float(fl_value_get_list_value(args, 1)); +// auto intensity = float(fl_value_get_float(fl_value_get_list_value(args, 2))); +// auto posX = (float)fl_value_get_float(fl_value_get_list_value(args, 3)); +// auto posY = (float)fl_value_get_float(fl_value_get_list_value(args, 4)); +// auto posZ = (float)fl_value_get_float(fl_value_get_list_value(args, 5)); +// auto dirX = (float)fl_value_get_float(fl_value_get_list_value(args, 6)); +// auto dirY = (float)fl_value_get_float(fl_value_get_list_value(args, 7)); +// auto dirZ = (float)fl_value_get_float(fl_value_get_list_value(args, 8)); +// auto shadows = fl_value_get_bool(fl_value_get_list_value(args, 9)); + +// auto entityId = add_light(self->viewer, type, color, intensity, posX, posY, posZ, dirX, dirY, dirZ, shadows); +// g_autoptr(FlValue) result = fl_value_new_int(entityId); +// return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); + +// } + +// static FlMethodResponse* _load_glb(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { +// FlValue* args = fl_method_call_get_args(method_call); +// auto path = fl_value_get_string(fl_value_get_list_value(args, 0)); +// auto unlit = fl_value_get_bool(fl_value_get_list_value(args, 1)); +// auto entityId = load_glb(self->viewer, path, unlit); +// g_autoptr(FlValue) result = fl_value_new_int((int64_t)entityId); +// return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +// } + +// static FlMethodResponse* _get_animation_names(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { + +// FlValue* args = fl_method_call_get_args(method_call); +// auto assetPtr = (void*)fl_value_get_int(args); +// g_autoptr(FlValue) result = fl_value_new_list(); + +// auto numNames = get_animation_count(assetPtr); + +// for(int i = 0; i < numNames; i++) { +// gchar out[255]; +// get_animation_name(assetPtr, out, i); +// fl_value_append_take (result, fl_value_new_string (out)); +// } + +// return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +// } + +// static FlMethodResponse* _remove_asset(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { +// FlValue* args = fl_method_call_get_args(method_call); +// auto assetPtr = (void*)fl_value_get_int(args); +// remove_asset(self->viewer, assetPtr); +// g_autoptr(FlValue) result = fl_value_new_string("OK"); +// return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +// } + +// static FlMethodResponse* _transform_to_unit_cube(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { +// FlValue* args = fl_method_call_get_args(method_call); +// auto assetPtr = (void*)fl_value_get_int(args); +// transform_to_unit_cube(assetPtr); +// g_autoptr(FlValue) result = fl_value_new_string("OK"); +// return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +// } + +// static FlMethodResponse* _rotate_start(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { +// FlValue* args = fl_method_call_get_args(method_call); + +// auto x = (float)fl_value_get_float(fl_value_get_list_value(args, 0)); +// auto y = (float)fl_value_get_float(fl_value_get_list_value(args, 1)); + +// grab_begin(self->viewer, x,y, false); + +// g_autoptr(FlValue) result = fl_value_new_string("OK"); +// return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +// } + +// static FlMethodResponse* _rotate_end(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { +// grab_end(self->viewer); +// g_autoptr(FlValue) result = fl_value_new_string("OK"); +// return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +// } + +// static FlMethodResponse* _rotate_update(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { +// FlValue* args = fl_method_call_get_args(method_call); +// auto x = (float)fl_value_get_float(fl_value_get_list_value(args, 0)); +// auto y = (float)fl_value_get_float(fl_value_get_list_value(args, 1)); + +// grab_update(self->viewer, x,y); + +// g_autoptr(FlValue) result = fl_value_new_string("OK"); +// return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +// } + +// static FlMethodResponse* _pan_start(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { + +// FlValue* args = fl_method_call_get_args(method_call); + +// auto x = (float)fl_value_get_float(fl_value_get_list_value(args, 0)); +// auto y = (float)fl_value_get_float(fl_value_get_list_value(args, 1)); + +// grab_begin(self->viewer, x,y, true); +// g_autoptr(FlValue) result = fl_value_new_string("OK"); +// return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +// } + +// static FlMethodResponse* _pan_update(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { +// FlValue* args = fl_method_call_get_args(method_call); +// auto x = (float)fl_value_get_float(fl_value_get_list_value(args, 0)); +// auto y = (float)fl_value_get_float(fl_value_get_list_value(args, 1)); + +// grab_update(self->viewer, x,y); +// g_autoptr(FlValue) result = fl_value_new_string("OK"); +// return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +// } + +// static FlMethodResponse* _pan_end(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { +// grab_end(self->viewer); +// g_autoptr(FlValue) result = fl_value_new_string("OK"); +// return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +// } + +// static FlMethodResponse* _set_position(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { +// FlValue* args = fl_method_call_get_args(method_call); +// auto assetPtr = (void*)fl_value_get_int(fl_value_get_list_value(args, 0)); + +// set_position( +// assetPtr, +// (float)fl_value_get_float(fl_value_get_list_value(args, 1)), // x +// (float)fl_value_get_float(fl_value_get_list_value(args, 2)), // y +// (float)fl_value_get_float(fl_value_get_list_value(args, 3)) // z +// ); +// g_autoptr(FlValue) result = fl_value_new_string("OK"); +// return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +// } + +// static FlMethodResponse* _set_rotation(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { +// FlValue* args = fl_method_call_get_args(method_call); +// auto assetPtr = (void*)fl_value_get_int(fl_value_get_list_value(args, 0)); + +// set_rotation( +// assetPtr, +// (float)fl_value_get_float(fl_value_get_list_value(args, 1)), // rads +// (float)fl_value_get_float(fl_value_get_list_value(args, 2)), // x +// (float)fl_value_get_float(fl_value_get_list_value(args, 3)), // y +// (float)fl_value_get_float(fl_value_get_list_value(args, 4)) // z +// ); +// g_autoptr(FlValue) result = fl_value_new_string("OK"); +// return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +// } + + + +// static FlMethodResponse* _set_bone_transform(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { +// FlValue* args = fl_method_call_get_args(method_call); +// auto assetPtr = (void*)fl_value_get_int(fl_value_get_list_value(args, 0)); +// auto boneName = fl_value_get_string(fl_value_get_list_value(args, 1)); +// auto meshName = fl_value_get_string(fl_value_get_list_value(args, 2)); + +// set_bone_transform( +// assetPtr, +// boneName, +// meshName, +// (float)fl_value_get_float(fl_value_get_list_value(args, 3)), // transX +// (float)fl_value_get_float(fl_value_get_list_value(args, 4)), // transY +// (float)fl_value_get_float(fl_value_get_list_value(args, 5)), // transZ +// (float)fl_value_get_float(fl_value_get_list_value(args, 6)), // quatX +// (float)fl_value_get_float(fl_value_get_list_value(args, 7)), // quatY +// (float)fl_value_get_float(fl_value_get_list_value(args, 8)), // quatZ +// (float)fl_value_get_float(fl_value_get_list_value(args, 9)) // quatW +// ); +// g_autoptr(FlValue) result = fl_value_new_string("OK"); +// return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +// } + +// static FlMethodResponse* _set_camera(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { +// FlValue* args = fl_method_call_get_args(method_call); +// auto assetPtr = (void*)fl_value_get_int(fl_value_get_list_value(args, 0)); +// auto cameraName = fl_value_get_string(fl_value_get_list_value(args, 1)) ; + +// set_camera(self->viewer, (void*)assetPtr, cameraName); +// g_autoptr(FlValue) result = fl_value_new_string("OK"); +// return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +// } + +// static FlMethodResponse* _set_camera_model_matrix(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { +// FlValue* args = fl_method_call_get_args(method_call); +// set_camera_model_matrix(self->viewer, fl_value_get_float32_list(args)); +// g_autoptr(FlValue) result = fl_value_new_string("OK"); +// return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +// } + +// static FlMethodResponse* _set_camera_exposure(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { +// FlValue* args = fl_method_call_get_args(method_call); +// auto aperture = (float)fl_value_get_float(fl_value_get_list_value(args, 0)); +// auto shutter_speed = (float)fl_value_get_float(fl_value_get_list_value(args, 1)); +// auto sensitivity = (float)fl_value_get_float(fl_value_get_list_value(args, 2)); +// set_camera_exposure(self->viewer, aperture, shutter_speed, sensitivity); +// g_autoptr(FlValue) result = fl_value_new_string("OK"); +// return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +// } + +// static FlMethodResponse* _set_camera_position(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { +// FlValue* args = fl_method_call_get_args(method_call); +// auto x = (float)fl_value_get_float(fl_value_get_list_value(args, 0)); +// auto y = (float)fl_value_get_float(fl_value_get_list_value(args, 1)); +// auto z = (float)fl_value_get_float(fl_value_get_list_value(args, 2)); +// set_camera_position(self->viewer, x,y, z); +// g_autoptr(FlValue) result = fl_value_new_string("OK"); +// return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +// } + +// static FlMethodResponse* _set_camera_rotation(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { +// FlValue* args = fl_method_call_get_args(method_call); +// auto rads = (float)fl_value_get_float(fl_value_get_list_value(args,0 )); +// auto x = (float)fl_value_get_float(fl_value_get_list_value(args, 1)); +// auto y = (float)fl_value_get_float(fl_value_get_list_value(args, 2)); +// auto z = (float)fl_value_get_float(fl_value_get_list_value(args, 3)); + +// set_camera_rotation(self->viewer, rads, x,y, z); +// g_autoptr(FlValue) result = fl_value_new_string("OK"); +// return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +// } + +// static FlMethodResponse* _set_rendering(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { +// FlValue* args = fl_method_call_get_args(method_call); +// self->_rendering = (bool)fl_value_get_bool(args); +// g_autoptr(FlValue) result = fl_value_new_string("OK"); +// return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +// } + +// static FlMethodResponse* _set_frame_interval(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { +// FlValue* args = fl_method_call_get_args(method_call); +// auto val = (float) fl_value_get_float(args); +// set_frame_interval(self->viewer, val); +// g_autoptr(FlValue) result = fl_value_new_string("OK"); +// return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +// } + +// static FlMethodResponse* _zoom_begin(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { +// scroll_begin(self->viewer); +// g_autoptr(FlValue) result = fl_value_new_string("OK"); +// return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +// } + +// static FlMethodResponse* _zoom_end(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { +// scroll_end(self->viewer); +// g_autoptr(FlValue) result = fl_value_new_string("OK"); +// return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +// } + +// static FlMethodResponse* _zoom_update(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { +// FlValue* args = fl_method_call_get_args(method_call); +// auto x = (float)fl_value_get_float(fl_value_get_list_value(args, 0)); +// auto y = (float)fl_value_get_float(fl_value_get_list_value(args, 1)); +// auto z = (float)fl_value_get_float(fl_value_get_list_value(args, 2)); + +// scroll_update(self->viewer, x,y, z); +// g_autoptr(FlValue) result = fl_value_new_string("OK"); +// return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +// } + +// static FlMethodResponse* _play_animation(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { +// FlValue* args = fl_method_call_get_args(method_call); +// auto assetPtr = (void*)fl_value_get_int(fl_value_get_list_value(args, 0)); +// auto animationId = (int)fl_value_get_int(fl_value_get_list_value(args, 1)); +// auto loop = (bool)fl_value_get_bool(fl_value_get_list_value(args, 2)); +// auto reverse = (bool)fl_value_get_bool(fl_value_get_list_value(args, 3)); +// play_animation(assetPtr, animationId, loop, reverse); +// g_autoptr(FlValue) result = fl_value_new_string("OK"); +// return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +// } + + +// static FlMethodResponse* _stop_animation(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { +// FlValue* args = fl_method_call_get_args(method_call); +// auto assetPtr = (void*)fl_value_get_int(fl_value_get_list_value(args, 0)); +// auto animationId = (int)fl_value_get_int(fl_value_get_list_value(args, 1)); +// stop_animation(assetPtr, animationId); +// g_autoptr(FlValue) result = fl_value_new_string("OK"); +// return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +// } + +// static FlMethodResponse* _apply_weights(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { +// FlValue* args = fl_method_call_get_args(method_call); +// auto assetPtr = (void*)fl_value_get_int(fl_value_get_list_value(args, 0)); +// auto entityName = fl_value_get_string(fl_value_get_list_value(args, 1)); +// auto weightsValue = fl_value_get_list_value(args, 2); +// float* const weights = (float* const) fl_value_get_float32_list(weightsValue); +// size_t len = fl_value_get_length(weightsValue); +// apply_weights(assetPtr, entityName, weights, (int)len); +// g_autoptr(FlValue) result = fl_value_new_string("OK"); +// return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +// } + +// static FlMethodResponse* _set_animation(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { +// FlValue* args = fl_method_call_get_args(method_call); +// auto assetPtr = (void*)fl_value_get_int(fl_value_get_list_value(args, 0)); + +// const char* entityName = fl_value_get_string(fl_value_get_list_value(args, 1)); + +// float* const morphData = (float* const) fl_value_get_float32_list(fl_value_get_list_value(args, 2)); + +// int64_t numMorphWeights = fl_value_get_int(fl_value_get_list_value(args, 3)); + +// FlValue* flBoneAnimations = fl_value_get_list_value(args, 4); + +// size_t numBoneAnimations = fl_value_get_length(flBoneAnimations); + +// vector boneAnimations; + +// for(int i = 0; i < numBoneAnimations; i++) { + +// FlValue* flBoneAnimation = fl_value_get_list_value(flBoneAnimations, i); + +// FlValue* flBoneNames = fl_value_get_list_value(flBoneAnimation, 0); +// FlValue* flMeshNames = fl_value_get_list_value(flBoneAnimation, 1); +// float* const frameData = (float* const) fl_value_get_float32_list(fl_value_get_list_value(flBoneAnimation, 2)); + +// Log("Framedata %f", frameData); + +// vector boneNames; +// boneNames.resize(fl_value_get_length(flBoneNames)); + +// for(int i=0; i < boneNames.size(); i++) { +// boneNames[i] = fl_value_get_string(fl_value_get_list_value(flBoneNames, i)) ; +// } + +// vector meshNames; +// meshNames.resize(fl_value_get_length(flMeshNames)); +// for(int i=0; i < meshNames.size(); i++) { +// meshNames[i] = fl_value_get_string(fl_value_get_list_value(flMeshNames, i)); +// } + +// const char** boneNamesPtr = (const char**)malloc(boneNames.size() * sizeof(char*)); +// memcpy((void*)boneNamesPtr, (void*)boneNames.data(), boneNames.size() * sizeof(char*)); +// auto meshNamesPtr = (const char**)malloc(meshNames.size() * sizeof(char*)); +// memcpy((void*)meshNamesPtr, (void*)meshNames.data(), meshNames.size() * sizeof(char*)); + +// BoneAnimation animation { +// .boneNames = boneNamesPtr, +// .meshNames = meshNamesPtr, +// .data = frameData, +// .numBones = boneNames.size(), +// .numMeshTargets = meshNames.size() +// }; + +// boneAnimations.push_back(animation); + +// } + +// int64_t numFrames = fl_value_get_int(fl_value_get_list_value(args, 5)); + +// float frameLengthInMs = fl_value_get_float(fl_value_get_list_value(args, 6)); + +// auto boneAnimationsPointer = boneAnimations.data(); +// auto boneAnimationsSize = boneAnimations.size(); + +// set_animation( +// assetPtr, +// entityName, +// morphData, +// numMorphWeights, +// boneAnimationsPointer, +// boneAnimationsSize, +// numFrames, +// frameLengthInMs); + +// g_autoptr(FlValue) result = fl_value_new_string("OK"); +// return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +// } + +// static FlMethodResponse* _get_morph_target_names(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { +// FlValue* args = fl_method_call_get_args(method_call); +// auto assetPtr = (void*)fl_value_get_int(fl_value_get_list_value(args, 0)); +// auto meshName = fl_value_get_string(fl_value_get_list_value(args, 1)); +// g_autoptr(FlValue) result = fl_value_new_list(); + +// auto numNames = get_morph_target_name_count(assetPtr, meshName); + +// std::cout << numNames << " morph targets found in mesh " << meshName << std::endl; + +// for(int i = 0; i < numNames; i++) { +// gchar out[255]; +// get_morph_target_name(assetPtr, meshName, out, i); +// fl_value_append_take (result, fl_value_new_string (out)); +// } + +// return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +// } + + // } else if(strcmp(method, "loadSkybox") == 0) { + // response = _loadSkybox(self, method_call); + // } else if(strcmp(method, "loadIbl") == 0) { + // response = _loadIbl(self, method_call); + // } else if(strcmp(method, "removeIbl") ==0) { + // response = _remove_ibl(self, method_call); + // } else if(strcmp(method, "removeSkybox") == 0) { + // response = _removeSkybox(self, method_call); + + // } else if(strcmp(method, "render") == 0) { + // render(self->viewer, 0); + // g_autoptr(FlValue) result = fl_value_new_string("OK"); + // response = FL_METHOD_RESPONSE(fl_method_success_response_new(result)); + // } else if(strcmp(method, "setBackgroundColor") == 0) { + // response = _set_background_color(self, method_call); + // } else if(strcmp(method, "setBackgroundImage") == 0) { + // response = _set_background_image(self, method_call); + // } else if(strcmp(method, "addLight") == 0) { + // response = _add_light(self, method_call); + // } else if(strcmp(method, "loadGlb") == 0) { + // response = _load_glb(self, method_call); + // } else if(strcmp(method, "getAnimationNames") == 0) { + // response = _get_animation_names(self, method_call); + // } else if(strcmp(method, "clearAssets") == 0) { + // clear_assets(self->viewer); + // g_autoptr(FlValue) result = fl_value_new_string("OK"); + // response = FL_METHOD_RESPONSE(fl_method_success_response_new(result)); + // } else if(strcmp(method, "removeAsset") == 0) { + // response = _remove_asset(self, method_call); + // } else if(strcmp(method, "transformToUnitCube") == 0) { + // response = _transform_to_unit_cube(self, method_call); + // } else if(strcmp(method, "clearLights") == 0) { + // clear_lights(self->viewer); + // g_autoptr(FlValue) result = fl_value_new_string("OK"); + // response = FL_METHOD_RESPONSE(fl_method_success_response_new(result)); + // } else if(strcmp(method, "panStart") == 0) { + // response = _pan_start(self, method_call); + // } else if(strcmp(method, "panEnd") == 0) { + // response = _pan_end(self, method_call); + // } else if(strcmp(method, "panUpdate") == 0) { + // response = _pan_update(self, method_call); + // } else if(strcmp(method, "rotateStart") == 0) { + // response = _rotate_start(self, method_call); + // } else if(strcmp(method, "rotateEnd") == 0) { + // response = _rotate_end(self, method_call); + // } else if(strcmp(method, "rotateUpdate") == 0) { + // response = _rotate_update(self, method_call); + // } else if(strcmp(method, "setRotation") == 0) { + // response = _set_rotation(self, method_call); + // } else if(strcmp(method, "setCamera") == 0) { + // response = _set_camera(self, method_call); + // } else if(strcmp(method, "setCameraModelMatrix") == 0) { + // response = _set_camera_model_matrix(self, method_call); + // } else if(strcmp(method, "setCameraExposure") == 0) { + // response = _set_camera_exposure(self, method_call); + // } else if(strcmp(method, "setCameraPosition") == 0) { + // response = _set_camera_position(self, method_call); + // } else if(strcmp(method, "setCameraRotation") == 0) { + // response = _set_camera_rotation(self, method_call); + + // } else if(strcmp(method, "setFrameInterval") == 0) { + // response = _set_frame_interval(self, method_call); + // } else if(strcmp(method, "zoomBegin") == 0) { + // response = _zoom_begin(self, method_call); + // } else if(strcmp(method, "zoomEnd") == 0) { + // response = _zoom_end(self, method_call); + // } else if(strcmp(method, "zoomUpdate") == 0) { + // response = _zoom_update(self, method_call); + // } else if(strcmp(method, "playAnimation") == 0) { + // response = _play_animation(self, method_call); + // } else if(strcmp(method, "stopAnimation") == 0) { + // response = _stop_animation(self, method_call); + // } else if(strcmp(method, "setMorphTargetWeights") == 0) { + // response = _apply_weights(self, method_call); + // } else if(strcmp(method, "setAnimation") == 0) { + // response = _set_animation(self, method_call); + // } else if(strcmp(method, "getMorphTargetNames") == 0) { + // response = _get_morph_target_names(self, method_call); + // } else if(strcmp(method, "setPosition") == 0) { + // response = _set_position(self, method_call); + // } else if(strcmp(method, "setBoneTransform") == 0) { + // // response = _set_bone_transform(self, method_call); \ No newline at end of file diff --git a/pubspec.yaml b/pubspec.yaml index b3a96e6e..ba0188b7 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -12,12 +12,20 @@ dependencies: sdk: flutter vector_math: ^2.1.2 plugin_platform_interface: ^2.0.0 + ffi: + tuple: dev_dependencies: flutter_test: sdk: flutter flutter_lints: ^1.0.0 + ffigen: +ffigen: + output: 'lib/generated_bindings.dart' + headers: + entry-points: + - 'ios/include/PolyvoxFilamentApi.h' flutter: plugin: