#include "AudioDevice.hpp" #include "Color.hpp" #include "Keyboard.hpp" #include "Matrix.hpp" #include "Mesh.hpp" #include "Model.hpp" #include "RadiansDegrees.hpp" #include "Vector3.hpp" #include "raylib.h" #include #include #include #include #include #include #define SKYBOX_IMPLEMENTATION #include "skybox.hpp" void DrawBoundedModel(raylib::Model &model, auto transformer) { // store the original transform to apply a different transform to the // model without affecting the next time we draw raylib::Matrix oldTransform = model.GetTransform(); // apply the transform that we get from whatever the transformer callback // gives us raylib::Matrix transform = transformer(model.GetTransform()); // apply the transform that we got from the transformer to the model model.SetTransform(transform); // draw the model, passing the origin and default scale as arguments since // the transform is already applied to the model model.Draw({ 0, 0, 0 }, 1.0f, raylib::Color::White()); // get the bounding box of the model after applying the transform auto box = model.GetTransformedBoundingBox(); // draw the bounding box of the model using raylib's built in function DrawBoundingBox(box, raylib::Color::White()); // restore the model's transform to its original state so that the next time we // draw the model, it doesn't have the previous transform applied to it model.SetTransform(oldTransform); } class Component { public: struct Entity *entity; virtual void Setup() = 0; virtual void Update(float dt) = 0; virtual void Cleanup() = 0; }; struct Entity { std::vector> components; template T> T &AddComponent() { std::shared_ptr out = components.emplace_back(std::make_shared()); out->entity = this; return (T &)*out; } template T> std::optional> GetComponent() const { for (auto &c : components) { T *cast = dynamic_cast(c.get()); if (cast) { return *cast; } } return { }; } }; struct TransformComponent : public Component { raylib::Vector3 position = { 0, 0, 0 }; raylib::Quaternion rotation = raylib::Quaternion::Identity(); void Setup() override { } void Update(float dt) override { } void Cleanup() override { } }; struct DrawModelComponent : public Component { raylib::Model *model; void Setup() override { } void Update(float dt) override { DrawBoundedModel(*model, [this](raylib::Transform old) { auto t = entity->GetComponent(); if (t) { return old .Translate(t->get().position) .Rotate(t->get().rotation); } return old; }); } void Cleanup() override { } }; template struct Delegate { }; template struct Delegate { std::vector> functions; void connect(const std::function &func) { functions.push_back(func); } void operator+=(const std::function &func) { connect(func); } void operator()(int arg) { static_assert( std::is_same_v, "EC HW: Delegate only supports void return type"); for (const auto &func : functions) { f(std::forward(arg)...); } } }; raylib::Degree angle_normalize(raylib::Degree angle) { float decimal = float(angle) - int(angle); int normalized = (int(angle) % 360 + 360) % 360; return raylib::Degree(normalized + decimal); } int main() { raylib::Window window(800, 600, "CS381 - Assignment 5"); window.SetState(FLAG_WINDOW_RESIZABLE); raylib::AudioDevice audio; raylib::Model penguin("models/penguin.glb"); raylib::Transform penguinTransform = raylib::Transform::Identity() .Scale(40, 40, 40); penguin.SetTransform(penguinTransform); raylib::Camera3D camera( { 0, 400, -40 }, { 0, -0.25f, 1 }, { 0, 1, 0 }, 45.0f); raylib::Model ground = raylib::Mesh::Plane(10000, 10000, 50, 50, 25); raylib::Texture snowTexture("textures/snow.jpg"); ground.GetMaterials()[0].maps[MATERIAL_MAP_DIFFUSE].texture = snowTexture; cs381::SkyBox skybox("textures/skybox.png"); std::vector entities; Entity &e = entities.emplace_back(); e.AddComponent(); e.AddComponent(); e.GetComponent()->get().model = &penguin; window.SetTargetFPS(60); // save cpu cycles while (!window.ShouldClose()) { window.BeginDrawing(); window.ClearBackground(raylib::Color::Gray()); float dt = window.GetFrameTime(); camera.BeginMode(); skybox.Draw(); ground.Draw({ 0, 0, 0 }, 1.0f, raylib::Color::White()); for (const Entity &e : entities) { for (const std::shared_ptr &c : e.components) { c->Update(dt); } } camera.EndMode(); window.EndDrawing(); } return 0; }