#if 0 #include "behavior.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include UF_BEHAVIOR_REGISTER_CPP(ext::SceneCollisionBehavior) #define this ((uf::Scene*) &self) void ext::SceneCollisionBehavior::initialize( uf::Object& self ) { uf::instantiator::bind( "RenderBehavior", *this ); } void ext::SceneCollisionBehavior::tick( uf::Object& self ) { #if 0 auto& metadata = this->getComponent(); if ( !metadata["system"]["physics"]["collision"].as() ) return; if ( this->hasComponent() ) { this->getComponent()->lock(); } bool threaded = !metadata["system"]["physics"]["single threaded"].as(); bool sort = metadata["system"]["physics"]["sort"].as(); bool useStrongest = metadata["system"]["physics"]["use"]["strongest"].as(); bool queued = metadata["system"]["physics"]["use"]["queue"].as(); bool updatePhysics = !metadata["system"]["physics"]["optimizations"]["entity-local update"].as(); bool ignoreStaticEntities = metadata["system"]["physics"]["optimizations"]["ignore static entities"].as(); bool ignoreDuplicateTests = metadata["system"]["physics"]["optimizations"]["ignore duplicate tests"].as(); bool useWorkers = metadata["system"]["physics"]["use"]["worker"].as(); std::vector> jobs; std::vector entities; { // update physics if ( updatePhysics ) { this->process([&]( uf::Entity* entity ) { if ( !entity->hasComponent() ) return; auto& metadata = entity->getComponent(); auto& transform = entity->getComponent>(); auto& physics = entity->getComponent(); if ( ext::json::isNull( metadata["system"]["physics"]["gravity"] ) ) { physics.linear.acceleration.x = metadata["system"]["physics"]["gravity"][0].as(); physics.linear.acceleration.y = metadata["system"]["physics"]["gravity"][1].as(); physics.linear.acceleration.z = metadata["system"]["physics"]["gravity"][2].as(); } if ( !metadata["system"]["physics"]["collision"].as() ) { physics.linear.acceleration.x = 0; physics.linear.acceleration.y = 0; physics.linear.acceleration.z = 0; } transform = uf::physics::update( transform, physics ); }); } this->process([&]( uf::Entity* entity ) { if ( !entity ) return; auto& metadata = entity->getComponent(); if ( !ext::json::isNull( metadata["system"]["physics"]["collision"] ) && !metadata["system"]["physics"]["collision"].as() ) return; if ( entity->hasComponent() ) entities.push_back((uf::Object*) entity); }); auto onCollision = []( pod::Collider::Manifold& manifold, size_t uidA, size_t uidB, bool queued ){ uf::Serializer payload; payload["normal"][0] = manifold.normal.x; payload["normal"][1] = manifold.normal.y; payload["normal"][2] = manifold.normal.z; payload["entity"] = uidB; payload["depth"] = -manifold.depth; auto& scene = uf::scene::getCurrentScene(); if ( queued ) scene.queueHook(uf::Object::formatHookName("world:Collision.%UID%",uidA), payload); else scene.callHook(uf::Object::formatHookName("world:Collision.%UID%",uidA), payload); payload["entity"] = uidA; payload["depth"] = manifold.depth; if ( queued ) scene.queueHook(uf::Object::formatHookName("world:Collision.%UID%",uidB), payload); else scene.callHook(uf::Object::formatHookName("world:Collision.%UID%",uidB), payload); }; auto testColliders = [&]( uf::Collider& colliderA, uf::Collider& colliderB, size_t uidA, size_t uidB, bool useStrongest ){ pod::Collider::Manifold strongest; auto manifolds = colliderA.intersects(colliderB); for ( auto manifold : manifolds ) { if ( manifold.colliding && manifold.depth > 0 ) { if ( !useStrongest ) onCollision(manifold, uidA, uidB, queued); else if ( strongest.depth < manifold.depth ) strongest = manifold; } } if ( useStrongest && strongest.colliding ) onCollision(strongest, uidA, uidB, queued); }; // collide with others if ( ignoreDuplicateTests ) { struct Pair { uf::Object* a = NULL; uf::Object* b = NULL; }; std::unordered_map queued; for ( auto* _a : entities ) { uf::Object& entityA = *_a; if ( ignoreStaticEntities && !entityA.hasComponent() ) continue; for ( auto* _b : entities ) { if ( _a == _b ) continue; uf::Object& entityB = *_b; std::string hash = std::to_string(std::min( entityA.getUid(), entityB.getUid() )) + ":" + std::to_string(std::max( entityA.getUid(), entityB.getUid() )); if ( queued.count(hash) > 0 ) continue; queued[hash] = { .a = _a, .b = _b, }; } } for ( auto& pair : queued ) { auto* entityA = pair.second.a; auto* entityB = pair.second.b; auto& colliderA = entityA->getComponent(); auto& colliderB = entityB->getComponent(); size_t uidA = entityA->getUid(); size_t uidB = entityB->getUid(); auto function = [&, uidA, uidB]() -> int { testColliders( colliderA, colliderB, uidA, uidB, useStrongest ); return 0; }; if ( threaded && useWorkers ) jobs.emplace_back(function); else function(); } } else { for ( auto* _a : entities ) { uf::Object& entityA = *_a; size_t uidA = entityA.getUid(); if ( ignoreStaticEntities && !entityA.hasComponent() ) continue; for ( auto* _b : entities ) { if ( _a == _b ) continue; uf::Object& entityB = *_b; auto& colliderA = entityA.getComponent(); auto& colliderB = entityB.getComponent(); size_t uidB = entityB.getUid(); auto function = [&, uidA, uidB]() -> int { testColliders( colliderA, colliderB, uidA, uidB, useStrongest ); return 0; }; if ( threaded && useWorkers ) jobs.emplace_back(function); else function(); } } } } if ( !jobs.empty() ) { if ( threaded ) uf::thread::batchWorkers( jobs ); else { for ( auto& fun : jobs ) fun(); } } if ( this->hasComponent() ) { this->getComponent()->lock(); } #endif /* pod::Thread& thread = uf::thread::has("Physics") ? uf::thread::get("Physics") : uf::thread::create( "Physics", true, false ); auto function = [&]() -> int { std::vector entities; // update physics if ( updatePhysics ) { this->process([&]( uf::Entity* entity ) { if ( !entity->hasComponent() ) return; auto& metadata = entity->getComponent(); auto& transform = entity->getComponent>(); auto& physics = entity->getComponent(); if ( ext::json::isNull( metadata["system"]["physics"]["gravity"] ) ) { physics.linear.acceleration.x = metadata["system"]["physics"]["gravity"][0].as(); physics.linear.acceleration.y = metadata["system"]["physics"]["gravity"][1].as(); physics.linear.acceleration.z = metadata["system"]["physics"]["gravity"][2].as(); } if ( !metadata["system"]["physics"]["collision"].as() ) { physics.linear.acceleration.x = 0; physics.linear.acceleration.y = 0; physics.linear.acceleration.z = 0; } transform = uf::physics::update( transform, physics ); }); } this->process([&]( uf::Entity* entity ) { if ( !entity ) return; auto& metadata = entity->getComponent(); if ( !ext::json::isNull( metadata["system"]["physics"]["collision"] ) && !metadata["system"]["physics"]["collision"].as() ) return; if ( entity->hasComponent() ) entities.push_back((uf::Object*) entity); }); auto onCollision = []( pod::Collider::Manifold& manifold, size_t uidA, size_t uidB, bool queued ){ uf::Serializer payload; payload["normal"][0] = manifold.normal.x; payload["normal"][1] = manifold.normal.y; payload["normal"][2] = manifold.normal.z; payload["entity"] = uidB; payload["depth"] = -manifold.depth; auto& scene = uf::scene::getCurrentScene(); if ( queued ) scene.queueHook(uf::Object::formatHookName("world:Collision.%UID%",uidA), payload); else scene.callHook(uf::Object::formatHookName("world:Collision.%UID%",uidA), payload); payload["entity"] = uidA; payload["depth"] = manifold.depth; if ( queued ) scene.queueHook(uf::Object::formatHookName("world:Collision.%UID%",uidB), payload); else scene.callHook(uf::Object::formatHookName("world:Collision.%UID%",uidB), payload); }; auto testColliders = [&]( uf::Collider& colliderA, uf::Collider& colliderB, size_t uidA, size_t uidB, bool useStrongest ){ pod::Collider::Manifold strongest; auto manifolds = colliderA.intersects(colliderB); for ( auto manifold : manifolds ) { if ( manifold.colliding && manifold.depth > 0 ) { if ( !useStrongest ) onCollision(manifold, uidA, uidB, queued); else if ( strongest.depth < manifold.depth ) strongest = manifold; } } if ( useStrongest && strongest.colliding ) onCollision(strongest, uidA, uidB, queued); }; // collide with others if ( ignoreDuplicateTests ) { struct Pair { uf::Object* a = NULL; uf::Object* b = NULL; }; std::unordered_map queued; for ( auto* _a : entities ) { uf::Object& entityA = *_a; if ( ignoreStaticEntities && !entityA.hasComponent() ) continue; for ( auto* _b : entities ) { if ( _a == _b ) continue; uf::Object& entityB = *_b; std::string hash = std::to_string(std::min( entityA.getUid(), entityB.getUid() )) + ":" + std::to_string(std::max( entityA.getUid(), entityB.getUid() )); if ( queued.count(hash) > 0 ) continue; queued[hash] = { .a = _a, .b = _b, }; } } for ( auto& pair : queued ) { auto* entityA = pair.second.a; auto* entityB = pair.second.b; auto& colliderA = entityA->getComponent(); auto& colliderB = entityB->getComponent(); auto function = [&]() -> int { testColliders( colliderA, colliderB, entityA->getUid(), entityB->getUid(), useStrongest ); return 0; }; if ( threaded && useWorkers ) uf::thread::add( uf::thread::fetchWorker(), function, true ); else function(); } } else { for ( auto* _a : entities ) { uf::Object& entityA = *_a; if ( ignoreStaticEntities && !entityA.hasComponent() ) continue; for ( auto* _b : entities ) { if ( _a == _b ) continue; uf::Object& entityB = *_b; auto& colliderA = entityA.getComponent(); auto& colliderB = entityB.getComponent(); auto function = [&]() -> int { testColliders( colliderA, colliderB, entityA.getUid(), entityB.getUid(), useStrongest ); return 0; }; if ( threaded && useWorkers ) uf::thread::add( uf::thread::fetchWorker(), function, true ); else function(); } } } mutex.unlock(); return 0; }; if ( threaded ) uf::thread::add( thread, function, true ); else function(); */ } void ext::SceneCollisionBehavior::render( uf::Object& self ){} void ext::SceneCollisionBehavior::destroy( uf::Object& self ){ /* { for ( int i = ext::bullet::dynamicsWorld->getNumCollisionObjects() - 1; i >= 0; i--) { btCollisionObject* obj = ext::bullet::dynamicsWorld->getCollisionObjectArray()[i]; btRigidBody* body = btRigidBody::upcast(obj); if (body && body->getMotionState()) { delete body->getMotionState(); } ext::bullet::dynamicsWorld->removeCollisionObject(obj); delete obj; } for ( size_t i = 0; i < ext::bullet::collisionShapes.size(); ++i ) { btCollisionShape* shape = ext::bullet::collisionShapes[i]; ext::bullet::collisionShapes[i] = NULL; delete shape; } delete ext::bullet::dynamicsWorld; delete ext::bullet::solver; delete ext::bullet::overlappingPairCache; delete ext::bullet::dispatcher; delete ext::bullet::collisionConfiguration; ext::bullet::collisionShapes.clear(); } */ #if 0 { auto& mutexPointer = this->getComponent(); delete mutexPointer; mutexPointer = NULL; } #endif } #undef this #endif