diff --git a/README.md b/README.md index 014e45ed..6d4eab77 100644 --- a/README.md +++ b/README.md @@ -174,10 +174,10 @@ var entity = await _filamentController.loadGlb("file:///tmp/bob.glb"); The return type `FilamentEntity` is simply an integer handle that be used to manipulate the entity in the scene. For example, to remove the asset: ``` -await _filamentController.removeAsset(entity); +await _filamentController.removeEntity(entity); entity = null; ``` -> Removing an entity from the scene will invalidate the corresponding `FilamentEntity` handle, so ensure you don't retain any references to it after calling `removeAsset` or `clearAssets`. Removing one `FilamentEntity` does not invalidate/change any other `FilamentEntity` handles; you can continue to safely manipulate these via the `FilamentController`. +> Removing an entity from the scene will invalidate the corresponding `FilamentEntity` handle, so ensure you don't retain any references to it after calling `removeEntity` or `clearEntities`. Removing one `FilamentEntity` does not invalidate/change any other `FilamentEntity` handles; you can continue to safely manipulate these via the `FilamentController`. ### Lighting diff --git a/example/lib/main.dart b/example/lib/main.dart index 79231291..e0ebac9e 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -148,7 +148,7 @@ class ExampleWidgetState extends State { color: _controlled == entity ? Colors.green : Colors.black)), IconButton( onPressed: () async { - await _filamentController!.removeAsset(entity); + await _filamentController!.removeEntity(entity); assets.remove(entity); setState(() {}); }, diff --git a/example/lib/menus/asset_submenu.dart b/example/lib/menus/asset_submenu.dart index d0a452eb..7aa1d052 100644 --- a/example/lib/menus/asset_submenu.dart +++ b/example/lib/menus/asset_submenu.dart @@ -216,7 +216,8 @@ class _AssetSubmenuState extends State { ExampleWidgetState.animations = await widget.controller .getAnimationNames(ExampleWidgetState.assets.last); } else { - await widget.controller.removeAsset(ExampleWidgetState.buster!); + await widget.controller + .removeEntity(ExampleWidgetState.buster!); ExampleWidgetState.buster = null; } }, @@ -232,7 +233,7 @@ class _AssetSubmenuState extends State { force: true); } else { await widget.controller - .removeAsset(ExampleWidgetState.flightHelmet!); + .removeEntity(ExampleWidgetState.flightHelmet!); ExampleWidgetState.flightHelmet = null; } }, @@ -281,7 +282,7 @@ class _AssetSubmenuState extends State { child: const Text("Request permissions (tests inactive->resume)")), MenuItemButton( onPressed: () async { - await widget.controller.clearAssets(); + await widget.controller.clearEntities(); ExampleWidgetState.flightHelmet = null; ExampleWidgetState.buster = null; ExampleWidgetState.assets.clear(); diff --git a/ios/include/FilamentViewer.hpp b/ios/include/FilamentViewer.hpp index e7db6721..297bd176 100644 --- a/ios/include/FilamentViewer.hpp +++ b/ios/include/FilamentViewer.hpp @@ -70,8 +70,8 @@ namespace polyvox void rotateIbl(const math::mat3f & matrix); - void removeAsset(EntityId asset); - void clearAssets(); + void removeEntity(EntityId asset); + void clearEntities(); void updateViewportAndCameraProjection(int height, int width, float scaleFactor); void render( diff --git a/ios/include/FlutterFilamentApi.h b/ios/include/FlutterFilamentApi.h index 69805668..170f79d8 100644 --- a/ios/include/FlutterFilamentApi.h +++ b/ios/include/FlutterFilamentApi.h @@ -142,8 +142,8 @@ extern "C" FLUTTER_PLUGIN_EXPORT float get_animation_duration(void *assetManager, EntityId asset, int index); FLUTTER_PLUGIN_EXPORT void get_morph_target_name(void *assetManager, EntityId asset, const char *meshName, char *const outPtr, int index); FLUTTER_PLUGIN_EXPORT int get_morph_target_name_count(void *assetManager, EntityId asset, const char *meshName); - FLUTTER_PLUGIN_EXPORT void remove_asset(const void *const viewer, EntityId asset); - FLUTTER_PLUGIN_EXPORT void clear_assets(const void *const viewer); + FLUTTER_PLUGIN_EXPORT void remove_entity(const void *const viewer, EntityId asset); + FLUTTER_PLUGIN_EXPORT void clear_entities(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 queue_position_update(void *assetManager, EntityId asset, float x, float y, float z, bool relative); diff --git a/ios/include/FlutterFilamentFFIApi.h b/ios/include/FlutterFilamentFFIApi.h index 50122c15..006db42a 100644 --- a/ios/include/FlutterFilamentFFIApi.h +++ b/ios/include/FlutterFilamentFFIApi.h @@ -40,8 +40,8 @@ FLUTTER_PLUGIN_EXPORT void remove_light_ffi(void* const viewer, EntityId entityI FLUTTER_PLUGIN_EXPORT void clear_lights_ffi(void* const viewer); FLUTTER_PLUGIN_EXPORT EntityId load_glb_ffi(void* const assetManager, const char *assetPath, bool unlit); FLUTTER_PLUGIN_EXPORT EntityId load_gltf_ffi(void* const assetManager, const char *assetPath, const char *relativePath); -FLUTTER_PLUGIN_EXPORT void remove_asset_ffi(void* const viewer, EntityId asset); -FLUTTER_PLUGIN_EXPORT void clear_assets_ffi(void* const viewer); +FLUTTER_PLUGIN_EXPORT void remove_entity_ffi(void* const viewer, EntityId asset); +FLUTTER_PLUGIN_EXPORT void clear_entities_ffi(void* const viewer); FLUTTER_PLUGIN_EXPORT bool set_camera_ffi(void* const viewer, EntityId asset, const char *nodeName); FLUTTER_PLUGIN_EXPORT void apply_weights_ffi( void* const assetManager, diff --git a/ios/include/filament/viewer/ViewerGui.h b/ios/include/filament/viewer/ViewerGui.h index 0130e28c..3c9d1bc1 100644 --- a/ios/include/filament/viewer/ViewerGui.h +++ b/ios/include/filament/viewer/ViewerGui.h @@ -103,7 +103,7 @@ public: * * This removes all the asset entities from the Scene, but does not destroy them. */ - void removeAsset(); + void removeEntity(); /** * Sets or changes the current scene's IBL to allow the UI manipulate it. diff --git a/ios/src/AssetManager.cpp b/ios/src/AssetManager.cpp index a5a33b09..616c00e0 100644 --- a/ios/src/AssetManager.cpp +++ b/ios/src/AssetManager.cpp @@ -234,6 +234,9 @@ namespace polyvox inst->getAnimator()->updateBoneMatrices(); inst->recomputeBoundingBoxes(); + auto box = inst->getBoundingBox(); + auto verts = box.extent(); + Log("AABB extent for %s is %f %f %f", uri, verts.x, verts.y, verts.z); asset->releaseSourceData(); diff --git a/ios/src/FilamentViewer.cpp b/ios/src/FilamentViewer.cpp index 5bfa55b4..baded416 100644 --- a/ios/src/FilamentViewer.cpp +++ b/ios/src/FilamentViewer.cpp @@ -639,7 +639,7 @@ namespace polyvox FilamentViewer::~FilamentViewer() { - clearAssets(); + clearEntities(); delete _assetManager; for (auto it : _lights) @@ -725,7 +725,7 @@ namespace polyvox _engine->flushAndWait(); } - void FilamentViewer::clearAssets() + void FilamentViewer::clearEntities() { Log("Clearing all assets"); if (_mainCamera) @@ -738,7 +738,7 @@ namespace polyvox Log("Cleared all assets"); } - void FilamentViewer::removeAsset(EntityId asset) + void FilamentViewer::removeEntity(EntityId asset) { Log("Removing asset from scene"); diff --git a/ios/src/FlutterFilamentApi.cpp b/ios/src/FlutterFilamentApi.cpp index f6ca02a0..11c947d4 100644 --- a/ios/src/FlutterFilamentApi.cpp +++ b/ios/src/FlutterFilamentApi.cpp @@ -450,14 +450,14 @@ extern "C" strcpy(outPtr, name.c_str()); } - FLUTTER_PLUGIN_EXPORT void remove_asset(const void *const viewer, EntityId asset) + FLUTTER_PLUGIN_EXPORT void remove_entity(const void *const viewer, EntityId asset) { - ((FilamentViewer *)viewer)->removeAsset(asset); + ((FilamentViewer *)viewer)->removeEntity(asset); } - FLUTTER_PLUGIN_EXPORT void clear_assets(const void *const viewer) + FLUTTER_PLUGIN_EXPORT void clear_entities(const void *const viewer) { - ((FilamentViewer *)viewer)->clearAssets(); + ((FilamentViewer *)viewer)->clearEntities(); } 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) diff --git a/ios/src/FlutterFilamentFFIApi.cpp b/ios/src/FlutterFilamentFFIApi.cpp index fc66da88..bae93f73 100644 --- a/ios/src/FlutterFilamentFFIApi.cpp +++ b/ios/src/FlutterFilamentFFIApi.cpp @@ -366,14 +366,14 @@ FLUTTER_PLUGIN_EXPORT void clear_lights_ffi(void *const viewer) { fut.wait(); } -FLUTTER_PLUGIN_EXPORT void remove_asset_ffi(void *const viewer, +FLUTTER_PLUGIN_EXPORT void remove_entity_ffi(void *const viewer, EntityId asset) { - std::packaged_task lambda([&] { remove_asset(viewer, asset); }); + std::packaged_task lambda([&] { remove_entity(viewer, asset); }); auto fut = _rl->add_task(lambda); fut.wait(); } -FLUTTER_PLUGIN_EXPORT void clear_assets_ffi(void *const viewer) { - std::packaged_task lambda([&] { clear_assets(viewer); }); +FLUTTER_PLUGIN_EXPORT void clear_entities_ffi(void *const viewer) { + std::packaged_task lambda([&] { clear_entities(viewer); }); auto fut = _rl->add_task(lambda); fut.wait(); } diff --git a/ios/src/Untitled-1.cpp b/ios/src/Untitled-1.cpp new file mode 100644 index 00000000..09599183 --- /dev/null +++ b/ios/src/Untitled-1.cpp @@ -0,0 +1,54 @@ +// we know there's been a collision, but we want to adjust the direction vector to continue movement in the non-colliding direction + + // first, we need to find the AABB plane that we have collided with + + auto vertices = targetBox.getCorners().vertices; + + // each entry here is a plane from the target bounding box + // (we drop the fourth vertex because it's mathematically not necessary to define the plane) + std::vector> planes = { + { + vertices[0],vertices[2],vertices[4] // bottom + }, + { + vertices[1],vertices[3],vertices[5] // top + }, + { + vertices[0],vertices[1],vertices[4] // back + }, + { + vertices[0],vertices[1],vertices[2] // left + }, + { + vertices[4],vertices[5],vertices[6] // right + }, + { + vertices[2],vertices[3],vertices[6] //front + }, + }; + + // now, iterate over each plane and project the intersecting source vertex onto it + // the smallest value will be the closest plane + auto sourceVertex = sourceCorners.vertices[i]; + int planeIndex = -1; + int minDist = 999999.0f; + filament::math::float3 projection; + for(int j = 0; j < 6; j++) { + // translate the plane so the intersecting source vertex is at the origin + auto plane = std::vector{ planes[j][0] - sourceVertex, planes[j][1] - sourceVertex, planes[j][2] - sourceVertex }; + + // cross product of the two known co-planar vectors to find the normal + auto normal = normalize(cross(plane[1] - plane[0], plane[2] - plane[1])); + + // project the normal onto the original (untranslated) plane vector + auto dist = dot(planes[j][0], normal) / norm(planes[j][0]); + Log("Dist : %f", dist); + if(dist < minDist) { + minDist = dist; + planeIndex = j; + } + } + Log("Collision with plane index %d", planeIndex); + auto sourceNormal = normalize(cross(planes[planeIndex][1] - planes[planeIndex][0], planes[planeIndex][2] - planes[planeIndex][1])); + + projection = direction - (sourceNormal * dot(sourceNormal, direction)); \ No newline at end of file diff --git a/lib/filament_controller.dart b/lib/filament_controller.dart index 2130429f..8fc36574 100644 --- a/lib/filament_controller.dart +++ b/lib/filament_controller.dart @@ -35,7 +35,7 @@ abstract class FilamentController { Stream get onLoad; /// - /// A Stream containing every FilamentEntity removed from the scene (i.e. via [removeAsset], [clearAssets], [removeLight] or [clearLights]). + /// A Stream containing every FilamentEntity removed from the scene (i.e. via [removeEntity], [clearEntities], [removeLight] or [clearLights]). Stream get onUnload; @@ -294,13 +294,13 @@ abstract class FilamentController { /// Removes/destroys the specified entity from the scene. /// [entity] will no longer be a valid handle after this method is called; ensure you immediately discard all references once this method is complete. /// - Future removeAsset(FilamentEntity entity); + Future removeEntity(FilamentEntity entity); /// /// Removes/destroys all renderable entities from the scene (including cameras). /// All [FilamentEntity] handles will no longer be valid after this method is called; ensure you immediately discard all references to all entities once this method is complete. /// - Future clearAssets(); + Future clearEntities(); /// /// Called by `FilamentGestureDetector`. You probably don't want to call this yourself. diff --git a/lib/filament_controller_ffi.dart b/lib/filament_controller_ffi.dart index df4bdb7b..8aa75715 100644 --- a/lib/filament_controller_ffi.dart +++ b/lib/filament_controller_ffi.dart @@ -817,21 +817,21 @@ class FilamentControllerFFI extends FilamentController { } @override - Future removeAsset(FilamentEntity entity) async { + Future removeEntity(FilamentEntity entity) async { if (_viewer == null) { throw Exception("No viewer available, ignoring"); } _entities.remove(entity); - remove_asset_ffi(_viewer!, entity); + remove_entity_ffi(_viewer!, entity); _onUnloadController.add(entity); } @override - Future clearAssets() async { + Future clearEntities() async { if (_viewer == null) { throw Exception("No viewer available, ignoring"); } - clear_assets_ffi(_viewer!); + clear_entities_ffi(_viewer!); for (final entity in _entities) { _onUnloadController.add(entity); diff --git a/lib/generated_bindings.dart b/lib/generated_bindings.dart index b922d027..fbd56ae0 100644 --- a/lib/generated_bindings.dart +++ b/lib/generated_bindings.dart @@ -499,15 +499,15 @@ external int get_morph_target_name_count( ); @ffi.Native, EntityId)>( - symbol: 'remove_asset', assetId: 'flutter_filament_plugin') -external void remove_asset( + symbol: 'remove_entity', assetId: 'flutter_filament_plugin') +external void remove_entity( ffi.Pointer viewer, int asset, ); @ffi.Native)>( - symbol: 'clear_assets', assetId: 'flutter_filament_plugin') -external void clear_assets( + symbol: 'clear_entities', assetId: 'flutter_filament_plugin') +external void clear_entities( ffi.Pointer viewer, ); @@ -852,14 +852,15 @@ external void flutter_filament_free( ffi.Void Function( ffi.Pointer, EntityId, - ffi.Pointer< - ffi.NativeFunction>)>( + ffi.Pointer>, + ffi.Bool)>( symbol: 'add_collision_component', assetId: 'flutter_filament_plugin') external void add_collision_component( ffi.Pointer assetManager, int entityId, ffi.Pointer> callback, + bool affectsCollidingTransform, ); @ffi.Native< @@ -875,6 +876,14 @@ external int create_geometry( ffi.Pointer materialPath, ); +@ffi.Native, EntityId, EntityId)>( + symbol: 'set_parent', assetId: 'flutter_filament_plugin') +external void set_parent( + ffi.Pointer assetManager, + int child, + int parent, +); + @ffi.Native< ffi.Pointer Function( ffi.Pointer, @@ -1114,15 +1123,15 @@ external int load_gltf_ffi( ); @ffi.Native, EntityId)>( - symbol: 'remove_asset_ffi', assetId: 'flutter_filament_plugin') -external void remove_asset_ffi( + symbol: 'remove_entity_ffi', assetId: 'flutter_filament_plugin') +external void remove_entity_ffi( ffi.Pointer viewer, int asset, ); @ffi.Native)>( - symbol: 'clear_assets_ffi', assetId: 'flutter_filament_plugin') -external void clear_assets_ffi( + symbol: 'clear_entities_ffi', assetId: 'flutter_filament_plugin') +external void clear_entities_ffi( ffi.Pointer viewer, );