add testCollisions method for manual collision checking

This commit is contained in:
Nick Fisher
2024-02-18 21:48:03 +08:00
parent 6c37368aea
commit a10fe6584d
9 changed files with 40 additions and 160 deletions

View File

@@ -1042,7 +1042,6 @@ namespace polyvox
_sceneManager->updateTransforms();
_sceneManager->updateAnimations();
_sceneManager->checkNonTransformableCollisions();
_cumulativeAnimationUpdateTime += tmr.elapsed();

View File

@@ -566,15 +566,6 @@ extern "C"
((SceneManager*)sceneManager)->addCollisionComponent(entityId, onCollisionCallback, affectsCollidingTransform);
}
FLUTTER_PLUGIN_EXPORT void mark_nontransformable_collidable(void *const sceneManager, EntityId entityId) {
((SceneManager*)sceneManager)->markNonTransformableCollidable(entityId);
}
FLUTTER_PLUGIN_EXPORT void unmark_nontransformable_collidable(void *const sceneManager, EntityId entityId) {
((SceneManager*)sceneManager)->unmarkNonTransformableCollidable(entityId);
}
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);
}
@@ -588,4 +579,8 @@ extern "C"
((SceneManager*)sceneManager)->setParent(child, parent);
}
FLUTTER_PLUGIN_EXPORT void test_collisions(void *const sceneManager, EntityId entity) {
((SceneManager*)sceneManager)->testCollisions(entity);
}
}

View File

@@ -1237,67 +1237,24 @@ namespace polyvox
_collisionComponentManager->elementAt<0>(collisionInstance) = asset.asset->getInstance()->getBoundingBox();
_collisionComponentManager->elementAt<1>(collisionInstance) = onCollisionCallback;
_collisionComponentManager->elementAt<2>(collisionInstance) = affectsTransform;
}
void SceneManager::markNonTransformableCollidable(EntityId entityId) {
// Log("Marking entity %d as non-transforming collidable", entityId);
std::lock_guard lock(_mutex);
for(auto& existing : _nonTransformableCollidableEntities) {
if(existing == entityId) {
Log("Collision already exists");
return;
}
void SceneManager::testCollisions(EntityId entityId) {
const auto &pos = _entityIdLookup.find(entityId);
if (pos == _entityIdLookup.end())
{
Log("ERROR: asset not found for entity.");
return;
}
_nonTransformableCollidableEntities.push_back(entityId);
Log("Mark complete.");
}
void SceneManager::unmarkNonTransformableCollidable(EntityId entityId) {
// Log("Removing non-transformable collidable from entity %d", entityId);
auto &asset = _assets[pos->second];
std::lock_guard lock(_mutex);
auto begin = _nonTransformableCollidableEntities.begin();
auto end = _nonTransformableCollidableEntities.end();
auto removed = std::remove_if(begin, end, [=](EntityId id) { return id == entityId; });
_nonTransformableCollidableEntities.erase(removed);
}
void SceneManager::checkNonTransformableCollisions() {
// Log("checkNonTransformableCollisions %d ", _nonTransformableCollidableEntities.size());
std::lock_guard lock(_mutex);
const auto& tm = _engine->getTransformManager();
for(const auto& entityId : _nonTransformableCollidableEntities) {
const auto &pos = _entityIdLookup.find(entityId);
if (pos == _entityIdLookup.end())
{
Log("ERROR: asset not found for entity.");
continue;
}
auto &asset = _assets[pos->second];
auto root = asset.asset->getRoot();
auto rootId = Entity::smuggle(root);
auto transformInstance = tm.getInstance(root);
if(!transformInstance.isValid()) {
Log("Invalid transform, skipping.");
continue;
}
auto parent = tm.getParent(transformInstance);
if(!parent.isNull()) {
transformInstance = tm.getInstance(parent);
}
auto transform = tm.getTransform(transformInstance);
auto worldTransform = tm.getWorldTransform(transformInstance);
Log("Entity id %d, Local Transform : %f %f %f World transform %f %f %f", rootId, transform[3][0],transform[3][1],transform[3][2], worldTransform[0], worldTransform[1], worldTransform[2]);
auto boundingBox = asset.asset->getInstance()->getBoundingBox();
auto worldBoundingBox = boundingBox.transform(worldTransform);
Log("Checking bounding box at center %f %f %f (world transformed centger %f %f %f)", boundingBox.center().x,boundingBox.center().y, boundingBox.center().z, worldBoundingBox.center().x, worldBoundingBox.center().y, worldBoundingBox.center().z);
_collisionComponentManager->collides(entityId, worldBoundingBox);
}
auto transformInstance = tm.getInstance(asset.asset->getRoot());
auto worldTransform = tm.getWorldTransform(transformInstance);
auto aabb = asset.asset->getInstance()->getBoundingBox();
aabb = aabb.transform(worldTransform);
_collisionComponentManager->collides(entityId, aabb);
}
@@ -1305,6 +1262,7 @@ namespace polyvox
std::lock_guard lock(_mutex);
auto &tm = _engine->getTransformManager();
for ( const auto &[entityId, transformUpdate]: _transformUpdates ) {
const auto &pos = _entityIdLookup.find(entityId);
if (pos == _entityIdLookup.end())

View File

@@ -1,54 +0,0 @@
// 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<std::vector<filament::math::float3>> 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<filament::math::float3>{ 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));