diff --git a/ios/include/AssetManager.hpp b/ios/include/AssetManager.hpp index b2ba8e67..56d0c1c9 100644 --- a/ios/include/AssetManager.hpp +++ b/ios/include/AssetManager.hpp @@ -103,7 +103,9 @@ 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 (*onCollisionCallback)(EntityId entityId)); + void addCollisionComponent(EntityId entity, void (*onCollisionCallback)(EntityId entityId), bool affectsCollidingTransform); + void removeCollisionComponent(EntityId entityId); + void setParent(EntityId child, EntityId parent); private: AssetLoader *_assetLoader = nullptr; diff --git a/ios/include/FlutterFilamentApi.h b/ios/include/FlutterFilamentApi.h index 2cffc313..69805668 100644 --- a/ios/include/FlutterFilamentApi.h +++ b/ios/include/FlutterFilamentApi.h @@ -185,8 +185,9 @@ extern "C" 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, void (*callback)(const EntityId entityId)); + FLUTTER_PLUGIN_EXPORT void add_collision_component(void *const assetManager, EntityId entityId, void (*callback)(const EntityId entityId), bool affectsCollidingTransform); FLUTTER_PLUGIN_EXPORT EntityId create_geometry(void *const viewer, float* vertices, int numVertices, uint16_t* indices, int numIndices, const char* materialPath); + FLUTTER_PLUGIN_EXPORT void set_parent(void *const assetManager, EntityId child, EntityId parent); #ifdef __cplusplus } diff --git a/ios/include/components/StandardComponents.h b/ios/include/components/StandardComponents.h index 30498ca0..cf16261e 100644 --- a/ios/include/components/StandardComponents.h +++ b/ios/include/components/StandardComponents.h @@ -13,57 +13,63 @@ namespace polyvox { typedef void(*CollisionCallback)(int32_t entityId) ; -class CollisionComponentManager : public utils::SingleInstanceComponentManager { +class CollisionComponentManager : public utils::SingleInstanceComponentManager { const filament::TransformManager& _transformManager; public: CollisionComponentManager(const filament::TransformManager& transformManager) : _transformManager(transformManager) {} - std::vector collides(filament::Aabb sourceBox, filament::math::float3 direction) { + std::vector collides(filament::Aabb sourceBox) { auto sourceCorners = sourceBox.getCorners(); - std::vector collision_axes; + std::vector collisionAxes; for(auto it = begin(); it < end(); it++) { auto entity = getEntity(it); auto targetXformInstance = _transformManager.getInstance(entity); auto targetXform = _transformManager.getWorldTransform(targetXformInstance); auto targetBox = elementAt<0>(it).transform(targetXform); + bool collided = false; + // 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) { + + collided = true; + auto affectsCollidingTransform = elementAt<2>(it); + if(affectsCollidingTransform) { + auto intersecting = sourceCorners.vertices[i]; + auto min = targetBox.min; + auto max = targetBox.max; - 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; - 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}; + 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}; + } + collisionAxes.push_back(axis); } - collision_axes.push_back(axis); break; } } - if(collision_axes.size() > 0) { + if(collided) { auto callback = elementAt<1>(it); if(callback) { callback(utils::Entity::smuggle(entity)); @@ -71,7 +77,7 @@ class CollisionComponentManager : public utils::SingleInstanceComponentManagergetRoot()), transform); } - void AssetManager::addCollisionComponent(EntityId entityId, void(*onCollisionCallback)(EntityId entityId)) { + void AssetManager::setParent(EntityId childEntityId, EntityId parentEntityId) { + auto& tm = _engine->getTransformManager(); + const auto child = Entity::import(childEntityId); + const auto parent = Entity::import(parentEntityId); + + const auto& parentInstance = tm.getInstance(parent); + const auto& childInstance = tm.getInstance(child); + tm.setParent(childInstance, parentInstance); + + + } + + void AssetManager::addCollisionComponent(EntityId entityId, void(*onCollisionCallback)(EntityId entityId), bool affectsCollidingTransform) { std::lock_guard lock(_mutex); const auto &pos = _entityIdLookup.find(entityId); if (pos == _entityIdLookup.end()) @@ -1176,6 +1188,7 @@ namespace polyvox auto collisionInstance = _collisionComponentManager->addComponent(asset.asset->getRoot()); _collisionComponentManager->elementAt<0>(collisionInstance) = asset.asset->getInstance()->getBoundingBox(); _collisionComponentManager->elementAt<1>(collisionInstance) = onCollisionCallback; + _collisionComponentManager->elementAt<2>(collisionInstance) = affectsCollidingTransform; } @@ -1227,18 +1240,16 @@ namespace polyvox auto bb = asset.asset->getBoundingBox(); auto transformedBB = bb.transform(transform); - auto collisions = _collisionComponentManager->collides(transformedBB, relativeTranslation); + auto collisionAxes = _collisionComponentManager->collides(transformedBB); - Log("%d collisions", collisions.size()); - if(collisions.size() == 1) { - auto globalAxis = collisions[0]; + if(collisionAxes.size() == 1) { + auto globalAxis = collisionAxes[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) { + } else if(collisionAxes.size() > 1) { translation -= relativeTranslation; transform = composeMatrix(translation, rotation, scale); } diff --git a/ios/src/FlutterFilamentApi.cpp b/ios/src/FlutterFilamentApi.cpp index 08777999..f6ca02a0 100644 --- a/ios/src/FlutterFilamentApi.cpp +++ b/ios/src/FlutterFilamentApi.cpp @@ -547,8 +547,8 @@ extern "C" free(ptr); } - 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 void add_collision_component(void *const assetManager, EntityId entityId, void (*onCollisionCallback)(const EntityId entityId), bool affectsCollidingTransform) { + ((AssetManager*)assetManager)->addCollisionComponent(entityId, onCollisionCallback, affectsCollidingTransform); } FLUTTER_PLUGIN_EXPORT EntityId create_geometry(void *const viewer, float* vertices, int numVertices, uint16_t* indices, int numIndices, const char* materialPath) { @@ -560,4 +560,8 @@ extern "C" return Entity::smuggle(entity); } + FLUTTER_PLUGIN_EXPORT void set_parent(void *const assetManager, EntityId child, EntityId parent) { + ((AssetManager*)assetManager)->setParent(child, parent); + } + } diff --git a/lib/filament_controller.dart b/lib/filament_controller.dart index b4478bd9..2130429f 100644 --- a/lib/filament_controller.dart +++ b/lib/filament_controller.dart @@ -564,11 +564,17 @@ abstract class FilamentController { /// If there is a collision between the controlled entity and [collidableEntity], the transform will not be updated. /// Future addCollisionComponent(FilamentEntity collidableEntity, - {void Function(int entityId)? callback}); + {void Function(int entityId)? callback, + bool affectsCollingTransform = false}); /// /// Creates a (renderable) entity with the specified geometry and adds to the scene. /// Future createGeometry( List vertices, List indices, String? materialPath); + + /// + /// Sets the parent transform of [child] to the transform of [parent]. + /// + Future setParent(FilamentEntity child, FilamentEntity parent); } diff --git a/lib/filament_controller_ffi.dart b/lib/filament_controller_ffi.dart index df9089bd..df4bdb7b 100644 --- a/lib/filament_controller_ffi.dart +++ b/lib/filament_controller_ffi.dart @@ -13,7 +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'; @@ -1391,7 +1391,8 @@ class FilamentControllerFFI extends FilamentController { @override Future addCollisionComponent(FilamentEntity entity, - {void Function(int entityId)? callback}) async { + {void Function(int entityId)? callback, + bool affectsCollingTransform = false}) async { if (_assetManager == null) { throw Exception("AssetManager must be non-null"); } @@ -1400,9 +1401,11 @@ class FilamentControllerFFI extends FilamentController { if (callback != null) { var ptr = NativeCallable.listener(callback); - add_collision_component(_assetManager!, entity, ptr.nativeFunction); + add_collision_component( + _assetManager!, entity, ptr.nativeFunction, affectsCollingTransform); } else { - add_collision_component(_assetManager!, entity, nullptr); + add_collision_component( + _assetManager!, entity, nullptr, affectsCollingTransform); } } @@ -1440,4 +1443,12 @@ class FilamentControllerFFI extends FilamentController { return entity; } + + @override + Future setParent(FilamentEntity child, FilamentEntity parent) async { + if (_assetManager == null) { + throw Exception("Asset manager must be non-null"); + } + set_parent(_assetManager!, child, parent); + } }