From 73c039b41382b1dc467f98ddded44f5028fc157d Mon Sep 17 00:00:00 2001 From: Nick Fisher Date: Thu, 15 Feb 2024 13:45:09 +0800 Subject: [PATCH] differentiate between setPosition/queuePositionUpdate (+rotate), use EntityId in collision callback, fix collisions + add skiing effect --- ios/include/AssetManager.hpp | 8 +- ios/include/FlutterFilamentApi.h | 10 +- ios/include/components/StandardComponents.h | 77 +++++++++------ ios/src/AssetManager.cpp | 98 ++++++++++++++++--- ios/src/FlutterFilamentApi.cpp | 28 ++++-- lib/entities/entity_transform_controller.dart | 75 ++++++++------ lib/filament_controller.dart | 54 ++++++---- lib/filament_controller_ffi.dart | 59 +++++++++-- 8 files changed, 292 insertions(+), 117 deletions(-) diff --git a/ios/include/AssetManager.hpp b/ios/include/AssetManager.hpp index 94c2a357..b2ba8e67 100644 --- a/ios/include/AssetManager.hpp +++ b/ios/include/AssetManager.hpp @@ -39,8 +39,10 @@ namespace polyvox 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, bool relative); - void setRotation(EntityId e, float rads, float x, float y, float z, float w, bool relative); + void setPosition(EntityId e, float x, float y, float z); + void setRotation(EntityId e, float rads, float x, float y, float z, float w); + void queuePositionUpdate(EntityId e, float x, float y, float z, bool relative); + void queueRotationUpdate(EntityId e, float rads, float x, float y, float z, float w, bool relative); const utils::Entity *getCameraEntities(EntityId e); size_t getCameraEntityCount(EntityId e); const utils::Entity *getLightEntities(EntityId e) const noexcept; @@ -101,7 +103,7 @@ namespace polyvox const char *entityName); int getEntityCount(EntityId entity, bool renderableOnly); const char* getEntityNameAt(EntityId entity, int index, bool renderableOnly); - void addCollisionComponent(EntityId entity); + void addCollisionComponent(EntityId entity, void (*onCollisionCallback)(EntityId entityId)); private: AssetLoader *_assetLoader = nullptr; diff --git a/ios/include/FlutterFilamentApi.h b/ios/include/FlutterFilamentApi.h index 8022c231..2cffc313 100644 --- a/ios/include/FlutterFilamentApi.h +++ b/ios/include/FlutterFilamentApi.h @@ -146,8 +146,10 @@ extern "C" FLUTTER_PLUGIN_EXPORT void clear_assets(const void *const viewer); FLUTTER_PLUGIN_EXPORT bool set_material_color(void *assetManager, EntityId asset, const char *meshName, int materialIndex, const float r, const float g, const float b, const float a); FLUTTER_PLUGIN_EXPORT void transform_to_unit_cube(void *assetManager, EntityId asset); - FLUTTER_PLUGIN_EXPORT void set_position(void *assetManager, EntityId asset, float x, float y, float z, bool relative); - FLUTTER_PLUGIN_EXPORT void set_rotation(void *assetManager, EntityId asset, float rads, float x, float y, float z, float w, bool relative); + FLUTTER_PLUGIN_EXPORT void queue_position_update(void *assetManager, EntityId asset, float x, float y, float z, bool relative); + FLUTTER_PLUGIN_EXPORT void queue_rotation_update(void *assetManager, EntityId asset, float rads, float x, float y, float z, float w, bool relative); + FLUTTER_PLUGIN_EXPORT void set_position(void *assetManager, EntityId asset, float x, float y, float z); + FLUTTER_PLUGIN_EXPORT void set_rotation(void *assetManager, EntityId asset, float rads, float x, float y, float z, float w); FLUTTER_PLUGIN_EXPORT void set_scale(void *assetManager, EntityId asset, float scale); // Camera methods @@ -176,14 +178,14 @@ extern "C" FLUTTER_PLUGIN_EXPORT void set_post_processing(void *const viewer, bool enabled); FLUTTER_PLUGIN_EXPORT void pick(void *const viewer, int x, int y, EntityId *entityId); FLUTTER_PLUGIN_EXPORT const char *get_name_for_entity(void *const assetManager, const EntityId entityId); - FLUTTER_PLUGIN_EXPORT const EntityId find_child_entity_by_name(void *const assetManager, const EntityId parent, const char* name); + FLUTTER_PLUGIN_EXPORT EntityId find_child_entity_by_name(void *const assetManager, const EntityId parent, const char* name); FLUTTER_PLUGIN_EXPORT int get_entity_count(void *const assetManager, const EntityId target, bool renderableOnly); FLUTTER_PLUGIN_EXPORT const char* get_entity_name_at(void *const assetManager, const EntityId target, int index, bool renderableOnly); FLUTTER_PLUGIN_EXPORT void set_recording(void *const viewer, bool recording); FLUTTER_PLUGIN_EXPORT void set_recording_output_directory(void *const viewer, const char* outputDirectory); FLUTTER_PLUGIN_EXPORT void ios_dummy(); FLUTTER_PLUGIN_EXPORT void flutter_filament_free(void *ptr); - FLUTTER_PLUGIN_EXPORT void add_collision_component(void *const assetManager, EntityId entityId); + FLUTTER_PLUGIN_EXPORT void add_collision_component(void *const assetManager, EntityId entityId, void (*callback)(const EntityId entityId)); FLUTTER_PLUGIN_EXPORT EntityId create_geometry(void *const viewer, float* vertices, int numVertices, uint16_t* indices, int numIndices, const char* materialPath); #ifdef __cplusplus diff --git a/ios/include/components/StandardComponents.h b/ios/include/components/StandardComponents.h index bd5e3f20..30498ca0 100644 --- a/ios/include/components/StandardComponents.h +++ b/ios/include/components/StandardComponents.h @@ -7,54 +7,71 @@ #include "filament/TransformManager.h" #include "gltfio/FilamentAsset.h" #include "gltfio/FilamentInstance.h" +#include "Log.hpp" namespace polyvox { -class FloatComponentManager : public utils::SingleInstanceComponentManager { - - static constexpr size_t DIRECTION = 0; - static constexpr size_t POSITION = 1; - static constexpr size_t MAX = 2; - static constexpr size_t SPEED = 2; - - // void update() { - // const auto* entities = getEntities(); - // for(int i = 0; i < getComponentCount(); i++) { - // // const auto instance = getInstance(); - // // elementAt - // // const auto component = get - // // const auto entity = entities[i]; - - // } - // } -}; - -class CollisionComponentManager : public utils::SingleInstanceComponentManager { - - static constexpr size_t INSTANCE = 0; +typedef void(*CollisionCallback)(int32_t entityId) ; +class CollisionComponentManager : public utils::SingleInstanceComponentManager { const filament::TransformManager& _transformManager; public: CollisionComponentManager(const filament::TransformManager& transformManager) : _transformManager(transformManager) {} - bool collides(filament::Aabb sourceBox) { + std::vector collides(filament::Aabb sourceBox, filament::math::float3 direction) { auto sourceCorners = sourceBox.getCorners(); - const auto& entities = getEntities(); + std::vector collision_axes; for(auto it = begin(); it < end(); it++) { - auto entity = entities[it]; - - auto targetInstance = elementAt(it); + auto entity = getEntity(it); auto targetXformInstance = _transformManager.getInstance(entity); auto targetXform = _transformManager.getWorldTransform(targetXformInstance); - auto targetBox = targetInstance->getBoundingBox().transform(targetXform); + auto targetBox = elementAt<0>(it).transform(targetXform); + + // iterate over every vertex in the source AABB for(int i = 0; i < 8; i++) { + // if the vertex has insersected with the target AABB if(targetBox.contains(sourceCorners.vertices[i]) < 0) { - return true; + + auto intersecting = sourceCorners.vertices[i]; + auto min = targetBox.min; + auto max = targetBox.max; + + float xmin = min.x - intersecting.x; + float ymin = min.y - intersecting.y; + float zmin = min.z - intersecting.z; + float xmax = intersecting.x - max.x; + float ymax = intersecting.y - max.y; + float zmax = intersecting.z - max.z; + + auto maxD = std::max(xmin,std::max(ymin,std::max(zmin,std::max(xmax,std::max(ymax,zmax))))); + filament::math::float3 axis; + if(maxD == xmin) { + axis = {-1.0f,0.0f, 0.0f}; + } else if(maxD == ymin) { + axis = {0.0f,-1.0f, 0.0f}; + } else if(maxD == zmin) { + axis = {0.0f,0.0f, -1.0f}; + } else if(maxD == xmax) { + axis = {1.0f,0.0f, 0.0f}; + } else if(maxD == ymax) { + axis = {0.0f,1.0f, 0.0f}; + } else { + axis = { 0.0f, 0.0f, 1.0f}; + } + collision_axes.push_back(axis); + break; + } + } + if(collision_axes.size() > 0) { + auto callback = elementAt<1>(it); + if(callback) { + callback(utils::Entity::smuggle(entity)); } } } - return false; + + return collision_axes; } }; diff --git a/ios/src/AssetManager.cpp b/ios/src/AssetManager.cpp index 7a1692dc..58d6ddc8 100644 --- a/ios/src/AssetManager.cpp +++ b/ios/src/AssetManager.cpp @@ -172,9 +172,7 @@ namespace polyvox sceneAsset.initialJointTransforms.push_back(jointTransform); } - utils::Entity e = EntityManager::get().create(); - - EntityId eid = Entity::smuggle(e); + EntityId eid = Entity::smuggle(asset->getRoot()); _entityIdLookup.emplace(eid, _assets.size()); _assets.push_back(sceneAsset); @@ -254,8 +252,7 @@ namespace polyvox sceneAsset.initialJointTransforms.push_back(jointTransform); } - utils::Entity e = EntityManager::get().create(); - EntityId eid = Entity::smuggle(e); + EntityId eid = Entity::smuggle(asset->getRoot()); _entityIdLookup.emplace(eid, _assets.size()); _assets.push_back(sceneAsset); @@ -351,7 +348,6 @@ namespace polyvox asset.fadeGltfAnimationIndex = -1; continue; } - asset.asset->getInstance()->getAnimator()->applyAnimation(animationStatus.index, elapsedInSecs); if (asset.fadeGltfAnimationIndex != -1 && elapsedInSecs < asset.fadeDuration) @@ -361,9 +357,11 @@ namespace polyvox auto alpha = elapsedInSecs / asset.fadeDuration; asset.asset->getInstance()->getAnimator()->applyCrossFade(asset.fadeGltfAnimationIndex, fadeFromTime, alpha); } - asset.asset->getInstance()->getAnimator()->updateBoneMatrices(); } + asset.asset->getInstance()->getAnimator()->updateBoneMatrices(); + + for (int i = (int)asset.morphAnimations.size() - 1; i >= 0; i--) { auto animationStatus = asset.morphAnimations[i]; @@ -1165,17 +1163,20 @@ namespace polyvox tm.setTransform(tm.getInstance(inst->getRoot()), transform); } - void AssetManager::addCollisionComponent(EntityId entityId) { + void AssetManager::addCollisionComponent(EntityId entityId, void(*onCollisionCallback)(EntityId entityId)) { std::lock_guard lock(_mutex); const auto &pos = _entityIdLookup.find(entityId); if (pos == _entityIdLookup.end()) { Log("ERROR: asset not found for entity."); return; - } + } auto &asset = _assets[pos->second]; + asset.asset->getAssetInstances(); auto collisionInstance = _collisionComponentManager->addComponent(asset.asset->getRoot()); - _collisionComponentManager->elementAt<0>(collisionInstance) = asset.asset->getInstance(); + _collisionComponentManager->elementAt<0>(collisionInstance) = asset.asset->getInstance()->getBoundingBox(); + _collisionComponentManager->elementAt<1>(collisionInstance) = onCollisionCallback; + } void AssetManager::updateTransforms() { @@ -1211,20 +1212,37 @@ namespace polyvox rotation = newRotation; } + math::float3 relativeTranslation; + if(newTranslationRelative) { math::mat3f rotationMatrix(rotation); - math::float3 relativeTranslation = rotationMatrix * newTranslation; + relativeTranslation = rotationMatrix * newTranslation; translation += relativeTranslation; } else { + relativeTranslation = newTranslation - translation; translation = newTranslation; } transform = composeMatrix(translation, rotation, scale); auto bb = asset.asset->getBoundingBox(); auto transformedBB = bb.transform(transform); - if(!_collisionComponentManager->collides(transformedBB)) { - tm.setTransform(transformInstance, transform); + + auto collisions = _collisionComponentManager->collides(transformedBB, relativeTranslation); + + Log("%d collisions", collisions.size()); + if(collisions.size() == 1) { + auto globalAxis = collisions[0]; + globalAxis *= norm(relativeTranslation); + auto newRelativeTranslation = relativeTranslation + globalAxis; + // Log("Collision axis global : %f %f %f relativeTranslation %f %f %f relativeTranslation (after subtracting global collision vector) %f %f %f", globalAxis.x, globalAxis.y, globalAxis.z, relativeTranslation.x, relativeTranslation.y, relativeTranslation.z, newRelativeTranslation.x, newRelativeTranslation.y, newRelativeTranslation.z); + translation -= relativeTranslation; + translation += newRelativeTranslation; + transform = composeMatrix(translation, rotation, scale); + } else if(collisions.size() > 1) { + translation -= relativeTranslation; + transform = composeMatrix(translation, rotation, scale); } + tm.setTransform(transformInstance, transform); } _transformUpdates.clear(); } @@ -1243,9 +1261,59 @@ namespace polyvox _transformUpdates[entity] = curr; } - void AssetManager::setPosition(EntityId entity, float x, float y, float z, bool relative) + void AssetManager::setPosition(EntityId entityId, float x, float y, float z) { std::lock_guard lock(_mutex); + + auto entity = Entity::import(entityId); + if(entity.isNull()) { + Log("Failed to find entity under ID %d", entityId); + return; + } + auto &tm = _engine->getTransformManager(); + + auto transformInstance = tm.getInstance(entity); + auto transform = tm.getTransform(transformInstance); + math::float3 translation; + math::quatf rotation; + math::float3 scale; + + decomposeMatrix(transform, &translation, &rotation, &scale); + translation = math::float3(x,y,z); + auto newTransform = composeMatrix(translation, rotation, scale); + tm.setTransform(transformInstance, newTransform); + } + + void AssetManager::setRotation(EntityId entityId, float rads, float x, float y, float z, float w) + { + std::lock_guard lock(_mutex); + + auto entity = Entity::import(entityId); + if(entity.isNull()) { + Log("Failed to find entity under ID %d", entityId); + return; + } + auto &tm = _engine->getTransformManager(); + + auto transformInstance = tm.getInstance(entity); + auto transform = tm.getTransform(transformInstance); + math::float3 translation; + math::quatf rotation; + math::float3 scale; + + decomposeMatrix(transform, &translation, &rotation, &scale); + rotation = math::quatf(w,x,y,z); + auto newTransform = composeMatrix(translation, rotation, scale); + tm.setTransform(transformInstance, newTransform); + } + + void AssetManager::queuePositionUpdate(EntityId entity, float x, float y, float z, bool relative) + { + std::lock_guard lock(_mutex); + + if(!relative) { + + } const auto &pos = _transformUpdates.find(entity); if (pos == _transformUpdates.end()) { @@ -1262,7 +1330,7 @@ namespace polyvox _transformUpdates[entity] = curr; } - void AssetManager::setRotation(EntityId entity, float rads, float x, float y, float z, float w, bool relative) + void AssetManager::queueRotationUpdate(EntityId entity, float rads, float x, float y, float z, float w, bool relative) { std::lock_guard lock(_mutex); const auto &pos = _transformUpdates.find(entity); diff --git a/ios/src/FlutterFilamentApi.cpp b/ios/src/FlutterFilamentApi.cpp index a57e8f30..08777999 100644 --- a/ios/src/FlutterFilamentApi.cpp +++ b/ios/src/FlutterFilamentApi.cpp @@ -470,14 +470,14 @@ extern "C" ((AssetManager *)assetManager)->transformToUnitCube(asset); } - FLUTTER_PLUGIN_EXPORT void set_position(void *assetManager, EntityId asset, float x, float y, float z, bool relative) + FLUTTER_PLUGIN_EXPORT void set_position(void *assetManager, EntityId asset, float x, float y, float z) { - ((AssetManager *)assetManager)->setPosition(asset, x, y, z, relative); + ((AssetManager *)assetManager)->setPosition(asset, x, y, z); } - FLUTTER_PLUGIN_EXPORT void set_rotation(void *assetManager, EntityId asset, float rads, float x, float y, float z, float w, bool relative) + FLUTTER_PLUGIN_EXPORT void set_rotation(void *assetManager, EntityId asset, float rads, float x, float y, float z, float w) { - ((AssetManager *)assetManager)->setRotation(asset, rads, x, y, z, w, relative); + ((AssetManager *)assetManager)->setRotation(asset, rads, x, y, z, w); } FLUTTER_PLUGIN_EXPORT void set_scale(void *assetManager, EntityId asset, float scale) @@ -485,6 +485,16 @@ extern "C" ((AssetManager *)assetManager)->setScale(asset, scale); } + FLUTTER_PLUGIN_EXPORT void queue_position_update(void *assetManager, EntityId asset, float x, float y, float z, bool relative) + { + ((AssetManager *)assetManager)->queuePositionUpdate(asset, x, y, z, relative); + } + + FLUTTER_PLUGIN_EXPORT void queue_rotation_update(void *assetManager, EntityId asset, float rads, float x, float y, float z, float w, bool relative) + { + ((AssetManager *)assetManager)->queueRotationUpdate(asset, rads, x, y, z, w, relative); + } + FLUTTER_PLUGIN_EXPORT void stop_animation(void *assetManager, EntityId asset, int index) { ((AssetManager *)assetManager)->stopAnimation(asset, index); @@ -537,13 +547,17 @@ extern "C" free(ptr); } - FLUTTER_PLUGIN_EXPORT void add_collision_component(void *const assetManager, EntityId entityId) { - ((AssetManager*)assetManager)->addCollisionComponent(entityId); + FLUTTER_PLUGIN_EXPORT void add_collision_component(void *const assetManager, EntityId entityId, void (*onCollisionCallback)(const EntityId entityId)) { + ((AssetManager*)assetManager)->addCollisionComponent(entityId, onCollisionCallback); } FLUTTER_PLUGIN_EXPORT EntityId create_geometry(void *const viewer, float* vertices, int numVertices, uint16_t* indices, int numIndices, const char* materialPath) { return ((FilamentViewer*)viewer)->createGeometry(vertices, (size_t)numVertices, indices, numIndices, materialPath); } - + + FLUTTER_PLUGIN_EXPORT EntityId find_child_entity_by_name(void *const assetManager, const EntityId parent, const char* name) { + auto entity = ((AssetManager*)assetManager)->findChildEntityByName(parent, name); + return Entity::smuggle(entity); + } } diff --git a/lib/entities/entity_transform_controller.dart b/lib/entities/entity_transform_controller.dart index e9224a80..071bb2be 100644 --- a/lib/entities/entity_transform_controller.dart +++ b/lib/entities/entity_transform_controller.dart @@ -1,6 +1,7 @@ import 'dart:async'; import 'dart:math'; +import 'package:flutter/services.dart'; import 'package:flutter_filament/filament_controller.dart'; import 'package:vector_math/vector_math_64.dart' as v; @@ -79,7 +80,7 @@ class EntityTransformController { double rads = 0.0; if (_rotY != 0) { - rads = _rotY! * pi / 1000; + rads = _rotY * pi / 1000; var rotY = v.Quaternion.axisAngle(v.Vector3(0, 1, 0), rads).normalized(); _rotation = rotY; updateRotation = true; @@ -87,12 +88,13 @@ class EntityTransformController { } if (updateTranslation) { - await controller.setPosition( + await controller.queuePositionUpdate( _entity, _position.x, _position.y, _position.z, relative: true); } if (updateRotation) { - await controller.setRotationQuat(_entity, _rotation, relative: true); + await controller.queueRotationUpdateQuat(_entity, _rotation, + relative: true); } } @@ -105,43 +107,45 @@ class EntityTransformController { } bool _playingForwardAnimation = false; + bool _playingBackwardAnimation = false; void forwardPressed() async { _forward = true; - if (forwardAnimationIndex != null) { - if (!_playingForwardAnimation) { - await controller.playAnimation(_entity, forwardAnimationIndex!, - loop: true); - _playingForwardAnimation = true; - } + if (forwardAnimationIndex != null && !_playingForwardAnimation) { + await controller.playAnimation(_entity, forwardAnimationIndex!, + loop: true, replaceActive: false); + _playingForwardAnimation = true; } } - Timer? _forwardTimer; - Timer? _backwardsTimer; - Timer? _strafeLeftTimer; - Timer? _strafeRightTimer; - void forwardReleased() async { - _forwardTimer?.cancel(); - _forwardTimer = Timer(Duration(milliseconds: 50), () async { - _forward = false; + _forward = false; + await Future.delayed(Duration(milliseconds: 50)); + if (!_forward) { _playingForwardAnimation = false; if (forwardAnimationIndex != null) { await controller.stopAnimation(_entity, forwardAnimationIndex!); } - }); + } } - void backPressed() { + void backPressed() async { _back = true; + if (forwardAnimationIndex != null) { + if (!_playingBackwardAnimation) { + await controller.playAnimation(_entity, forwardAnimationIndex!, + loop: true, replaceActive: false, reverse: true); + _playingBackwardAnimation = true; + } + } } void backReleased() async { - _backwardsTimer?.cancel(); - _backwardsTimer = Timer(Duration(milliseconds: 50), () { - _back = false; - }); + _back = false; + if (forwardAnimationIndex != null) { + await controller.stopAnimation(_entity, forwardAnimationIndex!); + } + _playingBackwardAnimation = false; } void strafeLeftPressed() { @@ -149,10 +153,7 @@ class EntityTransformController { } void strafeLeftReleased() async { - _strafeLeftTimer?.cancel(); - _strafeLeftTimer = Timer(Duration(milliseconds: 50), () { - _strafeLeft = false; - }); + _strafeLeft = false; } void strafeRightPressed() { @@ -160,9 +161,21 @@ class EntityTransformController { } void strafeRightReleased() async { - _strafeRightTimer?.cancel(); - _strafeRightTimer = Timer(Duration(milliseconds: 50), () { - _strafeRight = false; - }); + _strafeRight = false; } + + void Function()? _mouse1DownCallback; + void onMouse1Down(void Function() callback) { + _mouse1DownCallback = callback; + } + + void mouse1Down() async { + _mouse1DownCallback?.call(); + } + + void mouse1Up() async {} + + void mouse2Up() async {} + + void mouse2Down() async {} } diff --git a/lib/filament_controller.dart b/lib/filament_controller.dart index 006c1058..b4478bd9 100644 --- a/lib/filament_controller.dart +++ b/lib/filament_controller.dart @@ -449,9 +449,41 @@ abstract class FilamentController { Future transformToUnitCube(FilamentEntity entity); /// - /// Sets the world space position for [entity] to the given coordinates. + /// Directly sets the world space position for [entity] to the given coordinates, skipping all collision detection. /// - Future setPosition(FilamentEntity entity, double x, double y, double z, + Future setPosition(FilamentEntity entity, double x, double y, double z); + + /// + /// Directly sets the scale for [entity], skipping all collision detection. + /// + Future setScale(FilamentEntity entity, double scale); + + /// + /// Directly sets the rotation for [entity] to [rads] around the axis {x,y,z}, skipping all collision detection. + /// + Future setRotation( + FilamentEntity entity, double rads, double x, double y, double z); + + /// + /// Queues an update to the worldspace position for [entity] to {x,y,z}. + /// The actual update will occur on the next frame, and will be subject to collision detection. + /// + Future queuePositionUpdate( + FilamentEntity entity, double x, double y, double z, + {bool relative = false}); + + /// + /// Queues an update to the worldspace rotation for [entity]. + /// The actual update will occur on the next frame, and will be subject to collision detection. + /// + Future queueRotationUpdate( + FilamentEntity entity, double rads, double x, double y, double z, + {bool relative = false}); + + /// + /// Same as [queueRotationUpdate]. + /// + Future queueRotationUpdateQuat(FilamentEntity entity, Quaternion quat, {bool relative = false}); /// @@ -459,23 +491,10 @@ abstract class FilamentController { /// Future setPostProcessing(bool enabled); - /// - /// Sets the scale for the given entity. - /// - Future setScale(FilamentEntity entity, double scale); - - /// - /// Sets the rotation for [entity] to [rads] around the axis {x,y,z}. - /// - Future setRotation( - FilamentEntity entity, double rads, double x, double y, double z, - {bool relative = false}); - /// /// Sets the rotation for [entity] to the specified quaternion. /// - Future setRotationQuat(FilamentEntity entity, Quaternion rotation, - {bool relative = false}); + Future setRotationQuat(FilamentEntity entity, Quaternion rotation); /// /// Reveal the node [meshName] under [entity]. Only applicable if [hide] had previously been called; this is a no-op otherwise. @@ -544,7 +563,8 @@ abstract class FilamentController { /// At the moment, this is only relevant when controlling a different entity's transform. /// If there is a collision between the controlled entity and [collidableEntity], the transform will not be updated. /// - Future addCollisionComponent(FilamentEntity collidableEntity); + Future addCollisionComponent(FilamentEntity collidableEntity, + {void Function(int entityId)? callback}); /// /// Creates a (renderable) entity with the specified geometry and adds to the scene. diff --git a/lib/filament_controller_ffi.dart b/lib/filament_controller_ffi.dart index ba50ae3d..df9089bd 100644 --- a/lib/filament_controller_ffi.dart +++ b/lib/filament_controller_ffi.dart @@ -13,6 +13,7 @@ import 'package:flutter_filament/filament_controller.dart'; import 'package:flutter_filament/animations/animation_data.dart'; import 'package:flutter_filament/generated_bindings.dart'; import 'package:flutter_filament/hardware/hardware_keyboard_listener.dart'; +import 'package:flutter_filament/hardware/hardware_keyboard_poll.dart'; import 'package:flutter_filament/rendering_surface.dart'; import 'package:vector_math/vector_math_64.dart'; @@ -1051,13 +1052,33 @@ class FilamentControllerFFI extends FilamentController { } @override - Future setPosition(FilamentEntity entity, double x, double y, double z, - {bool relative = false}) async { + Future setPosition( + FilamentEntity entity, double x, double y, double z) async { if (_viewer == null) { throw Exception("No viewer available, ignoring"); } - set_position(_assetManager!, entity, x, y, z, relative); + set_position(_assetManager!, entity, x, y, z); + } + + @override + Future setRotation( + FilamentEntity entity, double rads, double x, double y, double z) async { + if (_viewer == null) { + throw Exception("No viewer available, ignoring"); + } + var quat = Quaternion.axisAngle(Vector3(x, y, z), rads); + await setRotationQuat(entity, quat); + } + + @override + Future setRotationQuat(FilamentEntity entity, Quaternion rotation, + {bool relative = false}) async { + if (_viewer == null) { + throw Exception("No viewer available, ignoring"); + } + set_rotation(_assetManager!, entity, rotation.radians, rotation.x, + rotation.y, rotation.z, rotation.w); } @override @@ -1069,23 +1090,33 @@ class FilamentControllerFFI extends FilamentController { } @override - Future setRotation( + Future queuePositionUpdate( + FilamentEntity entity, double x, double y, double z, + {bool relative = false}) async { + if (_viewer == null) { + throw Exception("No viewer available, ignoring"); + } + + queue_position_update(_assetManager!, entity, x, y, z, relative); + } + + @override + Future queueRotationUpdate( FilamentEntity entity, double rads, double x, double y, double z, {bool relative = false}) async { if (_viewer == null) { throw Exception("No viewer available, ignoring"); } var quat = Quaternion.axisAngle(Vector3(x, y, z), rads); - await setRotationQuat(entity, quat, relative: relative); + await queueRotationUpdateQuat(entity, quat, relative: relative); } - @override - Future setRotationQuat(FilamentEntity entity, Quaternion rotation, + Future queueRotationUpdateQuat(FilamentEntity entity, Quaternion rotation, {bool relative = false}) async { if (_viewer == null) { throw Exception("No viewer available, ignoring"); } - set_rotation(_assetManager!, entity, rotation.radians, rotation.x, + queue_rotation_update(_assetManager!, entity, rotation.radians, rotation.x, rotation.y, rotation.z, rotation.w, relative); } @@ -1359,12 +1390,20 @@ class FilamentControllerFFI extends FilamentController { } @override - Future addCollisionComponent(FilamentEntity entity) async { + Future addCollisionComponent(FilamentEntity entity, + {void Function(int entityId)? callback}) async { if (_assetManager == null) { throw Exception("AssetManager must be non-null"); } + // ignore: sdk_version_since - add_collision_component(_assetManager!, entity); + if (callback != null) { + var ptr = + NativeCallable.listener(callback); + add_collision_component(_assetManager!, entity, ptr.nativeFunction); + } else { + add_collision_component(_assetManager!, entity, nullptr); + } } @override