Initial commit - some engine bugs stopping compiling

This commit is contained in:
Will
2026-03-29 15:52:42 +01:00
commit 3d573a200e
361 changed files with 332759 additions and 0 deletions

509
src/main.cpp Normal file
View File

@@ -0,0 +1,509 @@
#include "Engine.h"
#include "LevelEditor.cpp"
#include <iostream>
#include <random>
#include <deque>
#include <chrono>
// ---------------------------------------------
// SceneDemo: existing complex scene demo
// ---------------------------------------------
class SceneDemo : public Engine {
private:
float time_ = 0.0f;
std::vector<std::shared_ptr<GameObject>> rotating_cubes_;
std::vector<std::shared_ptr<GameObject>> floating_spheres_;
std::shared_ptr<GameObject> central_sphere_;
std::shared_ptr<GameObject> ground_plane_;
std::shared_ptr<GameObject> grid_;
std::mt19937 rng_;
std::uniform_real_distribution<float> color_dist_{0.3f, 1.0f};
public:
SceneDemo()
: Engine(1920, 1080, "Modern C++ Engine - Complex Scene Demo"),
rng_(std::random_device{}()) {}
bool OnInitialize() override {
std::cout << "Creating complex scene with primitives..." << std::endl;
auto grid_primitive = CreateGrid(25, 1.0f, glm::vec3(0.4f));
grid_ = CreateGameObject(grid_primitive, glm::vec3(0,0,0));
AddGameObject(grid_);
auto plane_primitive = CreatePlane(30.0f, 30.0f, glm::vec3(0.2f,0.2f,0.3f));
ground_plane_ = CreateGameObject(plane_primitive, glm::vec3(0,-0.01f,0));
AddGameObject(ground_plane_);
auto central_sphere_primitive = CreateSphere(64, glm::vec3(0.9f,0.3f,0.1f));
central_sphere_ = CreateGameObject(central_sphere_primitive, glm::vec3(0,3,0));
central_sphere_->SetScale(glm::vec3(2.0f));
AddGameObject(central_sphere_);
for (int i = 0; i < 8; ++i) {
glm::vec3 color{color_dist_(rng_), color_dist_(rng_), color_dist_(rng_)};
auto cube = CreateGameObject(CreateCube(color), glm::vec3(0.0f));
rotating_cubes_.push_back(cube);
AddGameObject(cube);
}
for (int i = 0; i < 15; ++i) {
glm::vec3 color{color_dist_(rng_), color_dist_(rng_), color_dist_(rng_)};
float x = (rng_() % 20) - 10.0f;
float z = (rng_() % 20) - 10.0f;
float y = 1.0f + (rng_() % 5);
auto sphere = CreateGameObject(CreateSphere(32, color),
glm::vec3(x,y,z));
sphere->SetScale(glm::vec3(0.5f + (rng_()%10)*0.1f));
floating_spheres_.push_back(sphere);
AddGameObject(sphere);
}
for (int i = 0; i < 5; ++i) {
glm::vec3 color{1.0f - i*0.15f, 0.2f + i*0.15f, 0.5f};
auto cube = CreateGameObject(CreateCube(color),
glm::vec3(-8, i*2.1f+1, 8));
cube->SetScale(glm::vec3(0.8f + i*0.1f));
AddGameObject(cube);
}
for (int i = 0; i < 10; ++i) {
float hue = i/10.0f;
glm::vec3 color{hue, 1.0f-hue, 0.5f};
auto sphere = CreateGameObject(CreateSphere(24, color),
glm::vec3(i*2-9,1,-10));
sphere->SetScale(glm::vec3(0.3f));
AddGameObject(sphere);
}
std::cout << "Scene created with " << game_objects_.size() << " objects!" << std::endl;
return true;
}
void OnUpdate(float dt) override {
time_ += dt;
if (central_sphere_)
central_sphere_->SetRotation(glm::vec3(0, time_*30, 0));
for (size_t i = 0; i < rotating_cubes_.size(); ++i) {
float angle = time_*60.0f + i*(360.0f/rotating_cubes_.size());
float radius=8.0f, height=2.0f+std::sin(time_*2.0f+i)*1.5f;
glm::vec3 pos{std::cos(glm::radians(angle))*radius,
height,
std::sin(glm::radians(angle))*radius};
rotating_cubes_[i]->SetPosition(pos);
rotating_cubes_[i]->SetRotation(glm::vec3(angle,angle*1.5f,0));
}
for (size_t i = 0; i < floating_spheres_.size(); ++i) {
auto sphere = floating_spheres_[i];
glm::vec3 p = sphere->GetPosition();
float bob = std::sin(time_*3.0f + i*0.5f)*0.3f;
sphere->SetPosition(glm::vec3(p.x, p.y+bob, p.z));
sphere->SetRotation(glm::vec3(0, time_*20.0f + i*30.0f, 0));
}
float camAng = time_*15.0f;
SetCameraOrbit(20.0f, camAng, 12.0f);
SetCameraTarget(glm::vec3(0,2,0));
static float status_timer=0.0f;
status_timer += dt;
if (status_timer >= 3.0f) {
std::cout<<"Scene running: "<<int(time_)<<"s | "
<<game_objects_.size()<<" objects | Cam angle: "
<<int(camAng)%360<<"°"<<std::endl;
status_timer=0.0f;
}
}
};
// ---------------------------------------------
// StressTest: incremental spawn until quit
// ---------------------------------------------
class StressTest : public Engine {
public:
StressTest() : Engine(1920, 1080, "Zoom Stresser") {}
bool OnInitialize() override {
last_report_ = std::chrono::high_resolution_clock::now();
// Add a ground plane for visual reference
auto plane = CreateGameObject(CreatePlane(50.0f, 50.0f, glm::vec3(0.2f, 0.3f, 0.5f)),
glm::vec3(0, -1, 0));
AddGameObject(plane);
return true;
}
void OnUpdate(float dt) override {
time_ += dt;
// Spawn new objects every second
if (game_objects_.size() < 10000) {
spawn_timer_ += dt;
if (spawn_timer_ >= 1.0f) {
spawn_timer_ = 0.0f;
AddRow();
}
}
// Animate existing objects
AnimateObjects();
// Orbit camera around the scene
float camera_angle = time_ * 20.0f; // 20 degrees per second
float radius = 30.0f + std::sin(time_ * 0.5f) * 10.0f; // Varying radius
float height = 15.0f + std::cos(time_ * 0.3f) * 5.0f; // Varying height
SetCameraOrbit(radius, camera_angle, height);
SetCameraTarget(glm::vec3(0, 5, 0));
// Report performance every 2 seconds
auto now = std::chrono::high_resolution_clock::now();
float elapsed = std::chrono::duration<float>(now - last_report_).count();
if (elapsed >= 2.0f) {
float fps = 1.0f/dt;
std::cout << "Objects: " << game_objects_.size()
<< " | FPS: " << fps
<< " | Cam angle: " << int(camera_angle) % 360 << "°" << std::endl;
last_report_ = now;
}
}
private:
void AddRow() {
int row = int(stress_objects_.size()) / columns_;
for (int i = 0; i < columns_; ++i) {
// Colorful gradient based on position
float hue = (i + row * columns_) / 100.0f;
glm::vec3 color{
0.5f + 0.5f * std::sin(hue * 6.28f),
0.5f + 0.5f * std::sin(hue * 6.28f + 2.09f),
0.5f + 0.5f * std::sin(hue * 6.28f + 4.19f)
};
glm::vec3 pos{
i * spacing_ - columns_ * spacing_ / 2.0f,
0.5f + row * spacing_,
-20.0f + row * 2.0f // Spread them out in depth too
};
// Alternate between cubes and spheres
std::shared_ptr<GameObject> obj;
if ((i + row) % 2 == 0) {
obj = CreateGameObject(CreateCube(color), pos);
} else {
obj = CreateGameObject(CreateSphere(16, color), pos);
}
obj->SetScale(glm::vec3(0.4f + (i % 5) * 0.1f)); // Varying sizes
stress_objects_.push_back(obj);
AddGameObject(obj);
}
}
void AnimateObjects() {
for (size_t i = 0; i < stress_objects_.size(); ++i) {
auto& obj = stress_objects_[i];
glm::vec3 pos = obj->GetPosition();
// Floating/bobbing motion
float bob_speed = 2.0f + (i % 10) * 0.2f;
float bob_height = 0.3f + (i % 7) * 0.1f;
float bob = std::sin(time_ * bob_speed + i * 0.1f) * bob_height;
obj->SetPosition(glm::vec3(pos.x, pos.y + bob, pos.z));
// Rotation animation
float rot_speed = 30.0f + (i % 13) * 10.0f;
glm::vec3 rotation{
time_ * rot_speed + i * 10.0f,
time_ * (rot_speed * 0.7f) + i * 15.0f,
time_ * (rot_speed * 0.4f) + i * 20.0f
};
obj->SetRotation(rotation);
}
}
float time_{0.0f};
float spawn_timer_{0.0f};
std::chrono::high_resolution_clock::time_point last_report_;
std::vector<std::shared_ptr<GameObject>> stress_objects_;
static constexpr int columns_{500}; // Reduced for better performance
static constexpr float spacing_{1.0f};
};
// ---------------------------------------------
// SpinningMonkey: Loads OBJ monkey and spins it
// ---------------------------------------------
class SpinningMonkey : public Engine {
private:
float time_ = 0.0f;
std::shared_ptr<GameObject> monkey_;
std::shared_ptr<GameObject> ground_plane_;
std::shared_ptr<GameObject> grid_;
// Animation parameters
float spin_speed_ = 45.0f; // degrees per second
float bob_height_ = 2.0f; // vertical bobbing range
float bob_speed_ = 1.5f; // bobbing frequency
float scale_pulse_ = 0.2f; // scale pulsing amount
public:
SpinningMonkey()
: Engine(1920, 1080, "Spinning Monkey Demo - OBJ Model Loader") {}
bool OnInitialize() override {
std::cout << "Loading Suzanne (Blender Monkey) model..." << std::endl;
// Create ground reference
auto grid_primitive = CreateGrid(15, 1.0f, glm::vec3(0.3f, 0.3f, 0.4f));
grid_ = CreateGameObject(grid_primitive, glm::vec3(0, 0, 0));
AddGameObject(grid_);
auto plane_primitive = CreatePlane(20.0f, 20.0f, glm::vec3(0.15f, 0.25f, 0.35f));
ground_plane_ = CreateGameObject(plane_primitive, glm::vec3(0, -0.01f, 0));
AddGameObject(ground_plane_);
// Try to load monkey model (with optional texture)
try {
// First try with texture
auto monkey_primitive = CreateOBJModel("monkey.obj", "monkey.jpg");
if (monkey_primitive) {
monkey_ = CreateGameObject(monkey_primitive, glm::vec3(0, 3, 0));
monkey_->SetScale(glm::vec3(2.0f));
AddGameObject(monkey_);
std::cout << "✓ Loaded monkey with texture!" << std::endl;
}
} catch (...) {
std::cout << "! Texture loading failed, trying without texture..." << std::endl;
try {
// Fallback: load without texture
auto monkey_primitive = CreateOBJModel("monkey.obj");
if (monkey_primitive) {
monkey_ = CreateGameObject(monkey_primitive, glm::vec3(0, 3, 0));
monkey_->SetScale(glm::vec3(2.0f));
AddGameObject(monkey_);
std::cout << "✓ Loaded monkey without texture!" << std::endl;
}
} catch (...) {
std::cout << "✗ Failed to load monkey.obj, using fallback cube..." << std::endl;
// Ultimate fallback: colored cube
auto fallback_primitive = CreateCube(glm::vec3(1.0f, 0.5f, 0.2f));
monkey_ = CreateGameObject(fallback_primitive, glm::vec3(0, 3, 0));
monkey_->SetScale(glm::vec3(2.0f));
AddGameObject(monkey_);
}
}
// Set initial camera position
SetCameraPosition(glm::vec3(8, 6, 8));
SetCameraTarget(glm::vec3(0, 3, 0));
std::cout << "Scene initialized with " << game_objects_.size() << " objects!" << std::endl;
std::cout << "Controls:" << std::endl;
std::cout << " - Camera orbits automatically" << std::endl;
std::cout << " - Monkey spins and bobs up and down" << std::endl;
std::cout << " - Scale pulses with time" << std::endl;
return true;
}
void OnUpdate(float dt) override {
time_ += dt;
float spin_y = time_ * spin_speed_;
if (monkey_) {
// Spinning animation
float spin_x = std::sin(time_ * 0.3f) * 15.0f; // Gentle x-axis wobble
float spin_z = std::cos(time_ * 0.7f) * 10.0f; // Gentle z-axis wobble
monkey_->SetRotation(glm::vec3(spin_x, spin_y, spin_z));
// Vertical bobbing
float base_height = 3.0f;
float bob_offset = std::sin(time_ * bob_speed_) * bob_height_;
monkey_->SetPosition(glm::vec3(0, base_height + bob_offset, 0));
// Scale pulsing
float base_scale = 2.0f;
float scale_offset = std::sin(time_ * 2.0f) * scale_pulse_;
float current_scale = base_scale + scale_offset;
monkey_->SetScale(glm::vec3(current_scale));
}
// Orbiting camera
float camera_angle = time_ * 25.0f; // 25 degrees per second
float camera_radius = 10.0f + std::sin(time_ * 0.8f) * 3.0f; // Varying distance
float camera_height = 6.0f + std::cos(time_ * 0.5f) * 2.0f; // Varying height
SetCameraOrbit(camera_radius, camera_angle, camera_height);
SetCameraTarget(glm::vec3(0, 3, 0)); // Always look at monkey
// Status updates every 5 seconds
static float status_timer = 0.0f;
status_timer += dt;
if (status_timer >= 5.0f) {
std::cout << "🐵 Monkey spinning: " << int(time_) << "s | "
<< "Rotation: " << int(spin_y) % 360 << "° | "
<< "Camera: " << int(camera_angle) % 360 << "°" << std::endl;
status_timer = 0.0f;
}
}
};
// ---------------------------------------------
// MonkeyGridDemo: 50 jiggling monkeys on grid
// ---------------------------------------------
class MonkeyGridDemo : public Engine {
private:
float time_ = 0.0f;
std::vector<std::shared_ptr<GameObject>> monkeys_;
std::shared_ptr<GameObject> ground_plane_;
std::shared_ptr<GameObject> grid_;
static constexpr int MONKEY_COUNT = 50;
static constexpr int GRID_COLS = 7;
static constexpr int GRID_ROWS = 8;
static constexpr float SPACING = 4.0f;
std::mt19937 rng_{ std::random_device{}() };
std::uniform_real_distribution<float> jiggle_dist_{ -0.1f, 0.1f };
public:
MonkeyGridDemo()
: Engine(1920, 1080, "Monkey Grid Demo") {}
bool OnInitialize() override {
std::cout << "Spawning " << MONKEY_COUNT << " miniature monkeys on grid..." << std::endl;
// Grid and plane for reference
auto grid_primitive = CreateGrid(15, 1.0f, glm::vec3(0.3f));
grid_ = CreateGameObject(grid_primitive, glm::vec3(0, 0, 0));
AddGameObject(grid_);
auto plane_primitive = CreatePlane(60.0f, 60.0f, glm::vec3(0.2f, 0.25f, 0.3f));
ground_plane_ = CreateGameObject(plane_primitive, glm::vec3(0, -0.01f, 0));
AddGameObject(ground_plane_);
// Load OBJ monkey primitive once
std::shared_ptr<Primitive> monkey_primitive;
try {
monkey_primitive = CreateOBJModel("monkey.obj", "monkey.jpg");
if (!monkey_primitive)
monkey_primitive = CreateOBJModel("monkey.obj");
} catch (...) {
monkey_primitive = CreateCube(glm::vec3(1.0f, 0.5f, 0.2f));
}
// Spawn monkeys on GRID_COLS×GRID_ROWS grid
int spawned = 0;
for (int r = 0; r < GRID_ROWS && spawned < MONKEY_COUNT; ++r) {
for (int c = 0; c < GRID_COLS && spawned < MONKEY_COUNT; ++c) {
float x = (c - (GRID_COLS - 1) * 0.5f) * SPACING;
float z = (r - (GRID_ROWS - 1) * 0.5f) * SPACING;
auto monkey = CreateGameObject(monkey_primitive, glm::vec3(x, 1.0f, z));
monkey->SetScale(glm::vec3(0.5f)); // shrink to half size
monkeys_.push_back(monkey);
AddGameObject(monkey);
++spawned;
}
}
// Setup camera
SetCameraOrbit(50.0f, 45.0f, 30.0f);
SetCameraTarget(glm::vec3(0, 1.0f, 0));
return true;
}
void OnUpdate(float dt) override {
time_ += dt;
// Jiggle and slight bob for each monkey
for (auto& monkey : monkeys_) {
glm::vec3 basePos = monkey->GetPosition();
float jigX = jiggle_dist_(rng_);
float jigZ = jiggle_dist_(rng_);
float bobY = std::sin(time_ * 3.0f + basePos.x + basePos.z) * 0.2f;
monkey->SetPosition(glm::vec3(
basePos.x + jigX,
1.0f + bobY,
basePos.z + jigZ
));
// Optional subtle rotation
float angle = std::sin(time_ * 2.0f + basePos.x - basePos.z) * 15.0f;
monkey->SetRotation(glm::vec3(0, angle, 0));
}
// Slow orbiting camera
float camAng = time_ * 10.0f;
SetCameraOrbit(50.0f, camAng, 30.0f);
SetCameraTarget(glm::vec3(0, 1.0f, 0));
}
};
// ---------------------------------------------
// main: choose demo, stress, or monkey by arg
// ---------------------------------------------
int main(int argc, char** argv) {
try {
std::string mode = (argc > 1) ? std::string(argv[1]) : "demo";
if (mode == "stress") {
std::cout << "Running Stress Test..." << std::endl;
StressTest demo;
demo.Run();
return 0;
}
else if (mode == "monkeygrid") {
std::cout << "Starting Monkey Grid Demo..." << std::endl;
MonkeyGridDemo demo;
demo.Run();
return 0;
}
else if (mode == "edit") {
std::cout << "Starting Zoom Level Editor ..." << std::endl;
LevelEditor edit;
edit.Run();
return 0;
}
else if (mode == "monkey") {
std::cout << "🐵 Starting Spinning Monkey Demo..." << std::endl;
std::cout << "====================================" << std::endl;
std::cout << "Place your monkey.obj in models/ folder" << std::endl;
std::cout << "Optionally add monkey.bmp in textures/ folder" << std::endl;
std::cout << "====================================" << std::endl;
SpinningMonkey demo;
demo.Run();
std::cout << "====================================" << std::endl;
std::cout << "Monkey demo completed successfully! 🐵" << std::endl;
return 0;
} else {
std::cout << "Starting Modern C++ Engine Scene Demo..." << std::endl;
std::cout << "=========================================" << std::endl;
SceneDemo demo;
demo.Run();
std::cout << "=========================================" << std::endl;
std::cout << "Demo completed successfully!" << std::endl;
return 0;
}
} catch (const std::exception& e) {
std::cerr << "Error: " << e.what() << std::endl;
return -1;
}
}