void spatial_properties_mixin<false, D>::set_logic_transform(const components::transform t) const { if (logic_transform() == t) { return; } const auto handle = *static_cast<const D*>(this); const auto owner = handle.get_owner_body(); bool is_only_fixtural = owner.alive() && owner != handle; ensure(!is_only_fixtural); if (handle.has<components::physics>()) { ensure(!handle.has<components::transform>()); const auto& phys = handle.get<components::physics>(); phys.set_transform(t); } else { handle.get<components::transform>() = t; if (handle.has<components::dynamic_tree_node>()) { handle.get<components::dynamic_tree_node>().update_proxy(); } } }
vec2 basic_spatial_properties_mixin<C, D>::get_effective_velocity() const { const auto handle = *static_cast<const D*>(this); const auto owner = handle.get_owner_body(); if (owner.alive()) { return owner.get<components::physics>().velocity(); } else if (handle.has<components::position_copying>()) { ensure(handle.has<components::transform>()); return (handle.get<components::transform>().pos - handle.get<components::position_copying>().get_previous_transform().pos) * static_cast<float>(handle.get_cosmos().get_fixed_delta().get_steps_per_second()); } return{}; }
bool basic_spatial_properties_mixin<C, D>::has_logic_transform() const { const auto handle = *static_cast<const D*>(this); const auto owner = handle.get_owner_body(); if (owner.alive() && owner != handle) { return true; } else if (handle.has<components::physics>()) { return true; } else if (handle.has<components::transform>()) { return true; } return false; }
components::transform basic_spatial_properties_mixin<C, D>::logic_transform() const { const auto handle = *static_cast<const D*>(this); const auto owner = handle.get_owner_body(); if (owner.alive() && owner != handle) { return components::fixtures::transform_around_body(handle, owner.logic_transform()); } else if (handle.has<components::physics>()) { ensure(!handle.has<components::transform>()); const auto& phys = handle.get<components::physics>(); return{ phys.get_position(), phys.get_angle() }; } else if (handle.has<components::wandering_pixels>()) { return handle.get<components::wandering_pixels>().reach.center(); } else { return handle.get<components::transform>(); } }
void physics_system::fixtures_construct(const const_entity_handle handle) { //ensure(!is_constructed_colliders(handle)); if (is_constructed_colliders(handle)) return; if (handle.has<components::fixtures>()) { const auto colliders = handle.get<components::fixtures>(); if (colliders.is_activated() && is_constructed_rigid_body(colliders.get_owner_body())) { const auto& colliders_data = colliders.get_data(); auto& cache = get_colliders_cache(handle); const auto owner_body_entity = colliders.get_owner_body(); ensure(owner_body_entity.alive()); auto& owner_cache = get_rigid_body_cache(owner_body_entity); const auto this_cache_id = handle.get_id().pool.indirection_index; const auto owner_cache_id = owner_body_entity.get_id().pool.indirection_index; owner_cache.correspondent_colliders_caches.push_back(this_cache_id); cache.correspondent_rigid_body_cache = owner_cache_id; for (size_t ci = 0; ci < colliders_data.colliders.size(); ++ci) { const auto& c = colliders_data.colliders[ci]; b2PolygonShape shape; b2FixtureDef fixdef; fixdef.density = c.density; fixdef.friction = c.friction; fixdef.isSensor = c.sensor; fixdef.filter = c.filter; fixdef.restitution = c.restitution; fixdef.shape = &shape; fixdef.userData = handle.get_id(); auto transformed_shape = c.shape; transformed_shape.offset_vertices(colliders.get_total_offset()); std::vector<b2Fixture*> partitioned_collider; for (const auto convex : transformed_shape.convex_polys) { std::vector<b2Vec2> b2verts(convex.vertices.begin(), convex.vertices.end()); for (auto& v : b2verts) v *= PIXELS_TO_METERSf; shape.Set(b2verts.data(), b2verts.size()); b2Fixture* const new_fix = owner_cache.body->CreateFixture(&fixdef); ensure(static_cast<short>(ci) < std::numeric_limits<short>::max()); new_fix->collider_index = static_cast<short>(ci); partitioned_collider.push_back(new_fix); } cache.fixtures_per_collider.push_back(partitioned_collider); } } } }
void physics_system::contact_listener::PreSolve(b2Contact* contact, const b2Manifold* oldManifold) { auto& sys = get_sys(); auto& cosmos = cosm; messages::collision_message msgs[2]; for (int i = 0; i < 2; ++i) { auto fix_a = contact->GetFixtureA(); auto fix_b = contact->GetFixtureB(); if (i == 1) std::swap(fix_a, fix_b); b2WorldManifold manifold; contact->GetWorldManifold(&manifold); auto body_a = fix_a->GetBody(); auto body_b = fix_b->GetBody(); auto& msg = msgs[i]; msg.type = messages::collision_message::event_type::PRE_SOLVE; auto subject = cosmos[fix_a->GetUserData()]; auto collider = cosmos[fix_b->GetUserData()]; msg.subject = subject; msg.collider = collider; auto& subject_fixtures = subject.get<components::fixtures>(); auto& collider_fixtures = collider.get<components::fixtures>(); if (subject_fixtures.is_friction_ground()) { // friction fields do not collide with their children if (are_connected_by_friction(collider, subject)) { contact->SetEnabled(false); return; } auto& collider_physics = collider_fixtures.get_owner_body().get<components::special_physics>(); for (auto it = collider_physics.owner_friction_grounds.begin(); it != collider_physics.owner_friction_grounds.end(); ++it) if ((*it).target == subject_fixtures.get_owner_body()) { contact->SetEnabled(false); return; } } const const_entity_handle subject_owner_body = subject.get_owner_body(); const const_entity_handle collider_owner_body = collider.get_owner_body(); auto* driver = subject_owner_body.find<components::driver>(); bool colliding_with_owning_car = driver && driver->owned_vehicle == collider_owner_body; if (colliding_with_owning_car) { contact->SetEnabled(false); return; } if (subject_fixtures.standard_collision_resolution_disabled() || collider_fixtures.standard_collision_resolution_disabled()) { contact->SetEnabled(false); } msg.subject_collider_and_convex_indices = sys.map_fixture_pointer_to_indices(fix_a, subject); msg.point = manifold.points[0]; msg.point *= METERS_TO_PIXELSf; msg.subject_impact_velocity = body_a->GetLinearVelocityFromWorldPoint(manifold.points[0]); msg.collider_impact_velocity = body_b->GetLinearVelocityFromWorldPoint(manifold.points[0]); } sys.accumulated_messages.push_back(msgs[0]); sys.accumulated_messages.push_back(msgs[1]); }