11#include " engine.h"
2+ #include " scene_loading.h"
23
34#include < chrono>
45#include < algorithm>
56#include < stdexcept>
7+ #include < iostream>
68
79// This implementation corresponds to the Engine_Architecture chapter in the tutorial:
810// @see en/Building_a_Simple_Engine/Engine_Architecture/02_architectural_patterns.adoc
@@ -38,13 +40,72 @@ bool Engine::Initialize(const std::string& appName, int width, int height, bool
3840
3941 // Set mouse callback
4042 platform->SetMouseCallback ([this ](float x, float y, uint32_t buttons) {
43+ // Handle camera rotation when left mouse button is pressed
44+ if (buttons & 1 ) { // Left mouse button (bit 0)
45+ if (!cameraControl.mouseLeftPressed ) {
46+ cameraControl.mouseLeftPressed = true ;
47+ cameraControl.firstMouse = true ;
48+ }
49+
50+ if (cameraControl.firstMouse ) {
51+ cameraControl.lastMouseX = x;
52+ cameraControl.lastMouseY = y;
53+ cameraControl.firstMouse = false ;
54+ }
55+
56+ float xOffset = x - cameraControl.lastMouseX ;
57+ float yOffset = cameraControl.lastMouseY - y; // Reversed since y-coordinates go from bottom to top
58+ cameraControl.lastMouseX = x;
59+ cameraControl.lastMouseY = y;
60+
61+ xOffset *= cameraControl.mouseSensitivity ;
62+ yOffset *= cameraControl.mouseSensitivity ;
63+
64+ cameraControl.yaw += xOffset;
65+ cameraControl.pitch += yOffset;
66+
67+ // Constrain pitch to avoid gimbal lock
68+ if (cameraControl.pitch > 89 .0f ) cameraControl.pitch = 89 .0f ;
69+ if (cameraControl.pitch < -89 .0f ) cameraControl.pitch = -89 .0f ;
70+ } else {
71+ cameraControl.mouseLeftPressed = false ;
72+ }
73+
4174 if (imguiSystem) {
4275 imguiSystem->HandleMouse (x, y, buttons);
4376 }
4477 });
4578
4679 // Set keyboard callback
4780 platform->SetKeyboardCallback ([this ](uint32_t key, bool pressed) {
81+ // Handle camera movement keys (WASD + Arrow keys)
82+ switch (key) {
83+ case GLFW_KEY_W:
84+ case GLFW_KEY_UP:
85+ cameraControl.moveForward = pressed;
86+ break ;
87+ case GLFW_KEY_S:
88+ case GLFW_KEY_DOWN:
89+ cameraControl.moveBackward = pressed;
90+ break ;
91+ case GLFW_KEY_A:
92+ case GLFW_KEY_LEFT:
93+ cameraControl.moveLeft = pressed;
94+ break ;
95+ case GLFW_KEY_D:
96+ case GLFW_KEY_RIGHT:
97+ cameraControl.moveRight = pressed;
98+ break ;
99+ case GLFW_KEY_Q:
100+ case GLFW_KEY_PAGE_UP:
101+ cameraControl.moveUp = pressed;
102+ break ;
103+ case GLFW_KEY_E:
104+ case GLFW_KEY_PAGE_DOWN:
105+ cameraControl.moveDown = pressed;
106+ break ;
107+ }
108+
48109 if (imguiSystem) {
49110 imguiSystem->HandleKeyboard (key, pressed);
50111 }
@@ -68,6 +129,9 @@ bool Engine::Initialize(const std::string& appName, int width, int height, bool
68129 return false ;
69130 }
70131
132+ // Connect model loader to renderer for light extraction
133+ renderer->SetModelLoader (modelLoader.get ());
134+
71135 // Initialize audio system
72136 if (!audioSystem->Initialize (renderer.get ())) {
73137 return false ;
@@ -246,6 +310,9 @@ ImGuiSystem* Engine::GetImGuiSystem() const {
246310}
247311
248312void Engine::Update (float deltaTime) {
313+ // Check for completed background loading and create entities if ready
314+ CheckAndCreateLoadedEntities ();
315+
249316 // Update physics system
250317 physicsSystem->Update (deltaTime);
251318
@@ -255,6 +322,11 @@ void Engine::Update(float deltaTime) {
255322 // Update ImGui system
256323 imguiSystem->NewFrame ();
257324
325+ // Update camera controls
326+ if (activeCamera) {
327+ UpdateCameraControls (deltaTime);
328+ }
329+
258330 // Update all entities
259331 for (auto & entity : entities) {
260332 if (entity->IsActive ()) {
@@ -325,6 +397,75 @@ void Engine::HandleResize(int width, int height) {
325397 }
326398}
327399
400+ void Engine::UpdateCameraControls (float deltaTime) {
401+ if (!activeCamera) return ;
402+
403+ // Get camera transform component
404+ TransformComponent* cameraTransform = activeCamera->GetOwner ()->GetComponent <TransformComponent>();
405+ if (!cameraTransform) return ;
406+
407+ // Calculate movement speed
408+ float velocity = cameraControl.cameraSpeed * deltaTime;
409+
410+ // Calculate camera direction vectors based on yaw and pitch
411+ glm::vec3 front;
412+ front.x = cos (glm::radians (cameraControl.yaw )) * cos (glm::radians (cameraControl.pitch ));
413+ front.y = sin (glm::radians (cameraControl.pitch ));
414+ front.z = sin (glm::radians (cameraControl.yaw )) * cos (glm::radians (cameraControl.pitch ));
415+ front = glm::normalize (front);
416+
417+ glm::vec3 up = glm::vec3 (0 .0f , 1 .0f , 0 .0f );
418+ glm::vec3 right = glm::normalize (glm::cross (front, up));
419+ up = glm::normalize (glm::cross (right, front));
420+
421+ // Get current camera position
422+ glm::vec3 position = cameraTransform->GetPosition ();
423+
424+ // Apply movement based on input
425+ if (cameraControl.moveForward ) {
426+ position += front * velocity;
427+ }
428+ if (cameraControl.moveBackward ) {
429+ position -= front * velocity;
430+ }
431+ if (cameraControl.moveLeft ) {
432+ position -= right * velocity;
433+ }
434+ if (cameraControl.moveRight ) {
435+ position += right * velocity;
436+ }
437+ if (cameraControl.moveUp ) {
438+ position += up * velocity;
439+ }
440+ if (cameraControl.moveDown ) {
441+ position -= up * velocity;
442+ }
443+
444+ // Update camera position
445+ cameraTransform->SetPosition (position);
446+
447+ // Update camera target based on direction
448+ glm::vec3 target = position + front;
449+ activeCamera->SetTarget (target);
450+ }
451+
452+ void Engine::CheckAndCreateLoadedEntities () {
453+ // Check if background loading is complete
454+ if (g_loadingState.loadingComplete && !g_loadingState.loadedMaterials .empty ()) {
455+ // Create entities from loaded materials on the main thread
456+ CreateEntitiesFromLoadedMaterials (this );
457+
458+ // Reset the loading complete flag
459+ g_loadingState.loadingComplete = false ;
460+ }
461+
462+ // Check for loading errors
463+ if (g_loadingState.loadingFailed ) {
464+ std::cerr << " Background loading failed: " << g_loadingState.errorMessage << std::endl;
465+ g_loadingState.loadingFailed = false ; // Reset the flag
466+ }
467+ }
468+
328469#if PLATFORM_ANDROID
329470// Android-specific implementation
330471bool Engine::InitializeAndroid (android_app* app, const std::string& appName, bool enableValidationLayers) {
@@ -371,6 +512,9 @@ bool Engine::InitializeAndroid(android_app* app, const std::string& appName, boo
371512 return false ;
372513 }
373514
515+ // Connect model loader to renderer for light extraction
516+ renderer->SetModelLoader (modelLoader.get ());
517+
374518 // Initialize audio system
375519 if (!audioSystem->Initialize (renderer.get ())) {
376520 return false ;
0 commit comments