#pragma once #include #include "utils/globals.hpp" #include "utils/light.hpp" namespace Nimbin { class Camera; class GlRenderer; enum class ObjectType : uint8_t { Text, Prop, }; enum class PhysicsMode : uint8_t { AiHover, Carried, Dynamic, Hover, Projectile, Static, }; struct CollisionShape { Vec3 half_extents{0.5, 0.5, 0.5}; }; struct RigidBody { Vec3 vel {}; Vec3 force{}; double friction {0.8}; double hover_height{0.0}; double hover_phase {0.0}; double mass {1.0}; double restitution {0.3}; bool hover_disturbed{false}; PhysicsMode mode {PhysicsMode::Hover}; RigidBody(PhysicsMode m = PhysicsMode::Hover, double mass_ = 1.0, double restitution_ = 0.3, double friction_ = 0.8 ) : friction(friction_), mass(mass_), restitution(restitution_), mode(m) {} void apply_Force(const Vec3& f) { force.x += f.x; force.y += f.y; force.z += f.z; } void apply_KickImpulse(const Vec3& impulse) { if ( mode == PhysicsMode::Hover || mode == PhysicsMode::AiHover) { mode = PhysicsMode::Dynamic; vel = impulse; } else if (mode == PhysicsMode::Dynamic) { vel += impulse; } } void integrate(double dt) { if (mode != PhysicsMode::Dynamic) return; vel.x += (force.x / mass) * dt; vel.y += (force.y / mass) * dt; vel.z += (force.z / mass) * dt; force = {}; } }; struct GameObject { CollisionShape shape; RigidBody body; ObjectType type{ObjectType::Text}; Vec3 pos {}; float yaw {0.0f}; bool carriable {true}; bool interactable {true}; bool solid {true}; GameObject() {} GameObject(Vec3 p, ObjectType t, CollisionShape sh, RigidBody b, bool c = true, bool i = true, bool s = true) : shape(sh), body(b), type(t), pos(p), carriable(c), interactable(i), solid(s) {} virtual ~GameObject() = default; virtual void draw (GlRenderer&, const Camera&, const Light&) const = 0; Vec3 aabb_Min () const { const double c = SDL_fabs(SDL_cosf(yaw)); const double s = SDL_fabs(SDL_sinf(yaw)); const double ex = shape.half_extents.x * c + shape.half_extents.z * s; const double ez = shape.half_extents.x * s + shape.half_extents.z * c; return { pos.x - ex, pos.y - shape.half_extents.y, pos.z - ez }; } Vec3 aabb_Max () const { const double c = SDL_fabs(SDL_cosf(yaw)); const double s = SDL_fabs(SDL_sinf(yaw)); const double ex = shape.half_extents.x * c + shape.half_extents.z * s; const double ez = shape.half_extents.x * s + shape.half_extents.z * c; return { pos.x + ex, pos.y + shape.half_extents.y, pos.z + ez }; } }; } // namespace Nimbin