add flag for affectsCollidingTransform, add setParent method for transforms

This commit is contained in:
Nick Fisher
2024-02-15 14:50:14 +08:00
parent 023900bb99
commit 935b876ce9
7 changed files with 87 additions and 46 deletions

View File

@@ -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;

View File

@@ -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
}

View File

@@ -13,57 +13,63 @@ namespace polyvox
{
typedef void(*CollisionCallback)(int32_t entityId) ;
class CollisionComponentManager : public utils::SingleInstanceComponentManager<filament::Aabb, CollisionCallback> {
class CollisionComponentManager : public utils::SingleInstanceComponentManager<filament::Aabb, CollisionCallback, bool> {
const filament::TransformManager& _transformManager;
public:
CollisionComponentManager(const filament::TransformManager& transformManager) : _transformManager(transformManager) {}
std::vector<filament::math::float3> collides(filament::Aabb sourceBox, filament::math::float3 direction) {
std::vector<filament::math::float3> collides(filament::Aabb sourceBox) {
auto sourceCorners = sourceBox.getCorners();
std::vector<filament::math::float3> collision_axes;
std::vector<filament::math::float3> 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::SingleInstanceComponentManager<f
}
}
return collision_axes;
return collisionAxes;
}
};

View File

@@ -1163,7 +1163,19 @@ namespace polyvox
tm.setTransform(tm.getInstance(inst->getRoot()), 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);
}

View File

@@ -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);
}
}

View File

@@ -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<double> vertices, List<int> indices, String? materialPath);
///
/// Sets the parent transform of [child] to the transform of [parent].
///
Future setParent(FilamentEntity child, FilamentEntity parent);
}

View File

@@ -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<Void Function(Int32 entityId)>.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);
}
}