9.22 routine backup

This commit is contained in:
Isuru Samarathunga
2025-09-22 15:19:25 +05:30
parent 6a6debb0db
commit 28ca737c21
25 changed files with 585 additions and 140 deletions

View File

@ -14,56 +14,174 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
#include <IAEngine/IAEngine.hpp>
#include <IAEngine/Physics/Physics.hpp>
#include <IAEngine/Nodes/Node.hpp>
#include <box2d/box2d.h>
#include <map>
namespace ia::iae
{
Vector<BoxCollider2DComponent *> g_colliders;
struct Body
{
struct Collider
{
b2ShapeId ShapeId{};
BoxCollider2DComponent *ColliderComponent{};
};
b2BodyId BodyId{.world0 = 0xFFFF};
PhysicsBody2DComponent *BodyComponent;
Vector<Collider> Colliders;
};
b2WorldId g_worldId{};
Vector<Body> g_bodies;
std::map<Handle, BoxCollider2DComponent*> g_shapeColliders;
INLINE Handle ShapeIdToHandle(IN b2ShapeId id)
{
return *reinterpret_cast<Handle*>(&id.index1);
}
VOID Physics::Initialize()
{
auto worldDef = b2DefaultWorldDef();
worldDef.gravity = b2Vec2{0.0f, 1000.0f};
g_worldId = b2CreateWorld(&worldDef);
}
VOID Physics::Terminate()
{
}
INLINE BOOL IsIntersectingH(IN CONST glm::vec4 &shape, IN FLOAT32 x)
{
return (x >= shape.x) && (x <= shape.z);
}
INLINE BOOL IsIntersectingV(IN CONST glm::vec4 &shape, IN FLOAT32 y)
{
return (y >= shape.y) && (y <= shape.w);
b2DestroyWorld(g_worldId);
}
VOID Physics::Update()
{
for (SIZE_T i = 0; i < g_colliders.size(); i++)
CONSTEXPR FLOAT32 TIME_STEP = 1.0f / 60.0f;
CONSTEXPR INT32 SUB_STEP_COUNT = 4;
b2World_Step(g_worldId, TIME_STEP, SUB_STEP_COUNT);
// Process contact events
const auto contactEvents = b2World_GetContactEvents(g_worldId);
for(INT32 i = 0; i < contactEvents.beginCount; i++)
{
for (SIZE_T j = i + 1; j < g_colliders.size(); j++)
const auto& shapeA = g_shapeColliders[ShapeIdToHandle(contactEvents.beginEvents[i].shapeIdA)];
const auto& shapeB = g_shapeColliders[ShapeIdToHandle(contactEvents.beginEvents[i].shapeIdB)];
shapeA->OnCollisionEnter(shapeB->GetNode());
shapeB->OnCollisionEnter(shapeA->GetNode());
}
for(INT32 i = 0; i < contactEvents.endCount; i++)
{
const auto& shapeA = g_shapeColliders[ShapeIdToHandle(contactEvents.endEvents[i].shapeIdA)];
const auto& shapeB = g_shapeColliders[ShapeIdToHandle(contactEvents.endEvents[i].shapeIdB)];
shapeA->OnCollisionExit(shapeB->GetNode());
shapeB->OnCollisionExit(shapeA->GetNode());
}
// Process sensor events
const auto sensorEvents = b2World_GetSensorEvents(g_worldId);
for(INT32 i = 0; i < sensorEvents.beginCount; i++)
{
const auto& shapeA = g_shapeColliders[ShapeIdToHandle(sensorEvents.beginEvents[i].sensorShapeId)];
const auto& shapeB = g_shapeColliders[ShapeIdToHandle(sensorEvents.beginEvents[i].visitorShapeId)];
shapeA->OnCollisionEnter(shapeB->GetNode());
shapeB->OnCollisionEnter(shapeA->GetNode());
}
for(INT32 i = 0; i < sensorEvents.endCount; i++)
{
const auto& shapeA = g_shapeColliders[ShapeIdToHandle(sensorEvents.endEvents[i].sensorShapeId)];
const auto& shapeB = g_shapeColliders[ShapeIdToHandle(sensorEvents.endEvents[i].visitorShapeId)];
shapeA->OnCollisionExit(shapeB->GetNode());
shapeB->OnCollisionExit(shapeA->GetNode());
}
}
VOID Physics::Bake()
{
for (auto &b : g_bodies)
{
const auto pos = b.BodyComponent->GetNode()->GetPosition();
auto bodyDef = b2DefaultBodyDef();
if (b.BodyComponent->IsDynamic())
bodyDef.type = b2_dynamicBody;
bodyDef.position = b2Vec2{pos.x, pos.y};
if (b.BodyId.world0 != 0xFFFF)
b2DestroyBody(b.BodyId);
b.BodyId = b2CreateBody(g_worldId, &bodyDef);
for (auto &c : b.Colliders)
{
const auto boxA = g_colliders[i]->AbsoluteShape();
const auto boxB = g_colliders[j]->AbsoluteShape();
const auto nodeA = g_colliders[i]->GetNode();
if(IsIntersectingH(boxB, boxA.z) && (IsIntersectingV(boxB, boxA.y) || IsIntersectingV(boxB, boxA.w)))
nodeA->SetLocalPosition(nodeA->GetLocalPosition() + glm::vec2(-boxA.z + boxB.x, 0));
else if(IsIntersectingH(boxB, boxA.x) && (IsIntersectingV(boxB, boxA.y) || IsIntersectingV(boxB, boxA.w)))
nodeA->SetLocalPosition(nodeA->GetLocalPosition() + glm::vec2(-boxA.x + boxB.z, 0));
else if(IsIntersectingV(boxB, boxA.w) && (IsIntersectingH(boxB, boxA.x) || IsIntersectingH(boxB, boxA.z)))
nodeA->SetLocalPosition(nodeA->GetLocalPosition() + glm::vec2(0, -boxA.w + boxB.y));
else if(IsIntersectingV(boxB, boxA.y) && (IsIntersectingH(boxB, boxA.x) || IsIntersectingH(boxB, boxA.z)))
nodeA->SetLocalPosition(nodeA->GetLocalPosition() + glm::vec2(0, -boxA.y + boxB.w));
const auto rect = c.ColliderComponent->Rect();
const auto halfW = rect.z/2.0f;
const auto halfH = rect.w/2.0f;
const auto box = b2MakeOffsetBox(halfW, halfH, {rect.x, rect.y - halfH/2.0f}, b2MakeRot(0));
auto boxShapeDef = b2DefaultShapeDef();
boxShapeDef.density = 1.0f;
boxShapeDef.isSensor = c.ColliderComponent->IsTrigger();
boxShapeDef.enableContactEvents = c.ColliderComponent->CollisionsEnabled();
boxShapeDef.enableSensorEvents = boxShapeDef.enableContactEvents;
c.ShapeId = b2CreatePolygonShape(b.BodyId, &boxShapeDef, &box);
g_shapeColliders[ShapeIdToHandle(c.ShapeId)] = c.ColliderComponent;
}
}
}
VOID Physics::AddCollider(IN BoxCollider2DComponent *collider)
Handle Physics::AddBody(IN PhysicsBody2DComponent *body)
{
g_colliders.pushBack(collider);
g_bodies.pushBack(Body{
.BodyComponent = body,
});
return g_bodies.size() - 1;
}
Handle Physics::AddColliderToBody(IN Handle bodyHandle, IN BoxCollider2DComponent *collider)
{
auto &b = g_bodies[bodyHandle];
b.Colliders.pushBack(Body::Collider{
.ColliderComponent = collider,
});
return b.Colliders.size() - 1;
}
FLOAT32 Physics::GetBodyRotation(IN Handle handle)
{
const auto &b = g_bodies[handle];
return acosf(b2Body_GetRotation(b.BodyId).c);
}
glm::vec2 Physics::GetBodyPosition(IN Handle handle)
{
const auto &b = g_bodies[handle];
const auto v = b2Body_GetPosition(b.BodyId);
return {v.x, v.y};
}
VOID Physics::ApplyBodyForce(IN Handle handle, IN glm::vec2 force)
{
const auto &b = g_bodies[handle];
b2Body_ApplyForce(b.BodyId, {force.x, force.y}, b2Body_GetLocalCenterOfMass(b.BodyId), true);
}
VOID Physics::SetBodyVelocity(IN Handle handle, IN glm::vec2 v)
{
const auto &b = g_bodies[handle];
b2Body_SetLinearVelocity(b.BodyId, {v.x, v.y});
}
VOID Physics::SetBodyVelocityX(IN Handle handle, IN FLOAT32 v)
{
const auto &b = g_bodies[handle];
b2Body_SetLinearVelocity(b.BodyId, {v, b2Body_GetLinearVelocity(b.BodyId).y});
}
VOID Physics::SetBodyVelocityY(IN Handle handle, IN FLOAT32 v)
{
const auto &b = g_bodies[handle];
b2Body_SetLinearVelocity(b.BodyId, {b2Body_GetLinearVelocity(b.BodyId).x, v});
}
} // namespace ia::iae