Skip to content

Commit ce7c00d

Browse files
committed
This doesn't currently fix the bugs still in the engine, but it's a checkin so I can work on other things in the tutorial and come back to this.
Integrate mikktspace tangent generation, enhance robust tangent handling for poles, unify shader refraction logic, improve transmission Fresnel, and implement thread-safe rigid body management.
1 parent 277a817 commit ce7c00d

24 files changed

+3323
-1306
lines changed

attachments/simple_engine/CMakeLists.txt

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,6 @@ target_sources(VulkanCppModule
4444
)
4545

4646

47-
# Add the vulkan.cppm file directly as a source file
48-
target_sources(VulkanCppModule
49-
PRIVATE
50-
"${Vulkan_INCLUDE_DIR}/vulkan/vulkan.cppm"
51-
)
5247

5348
# Platform-specific settings
5449
if(ANDROID)
@@ -119,6 +114,7 @@ set(SOURCES
119114
pipeline.cpp
120115
descriptor_manager.cpp
121116
renderdoc_debug_system.cpp
117+
mikktspace.c
122118
)
123119

124120
# Create executable

attachments/simple_engine/audio_system.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <mutex>
1313
#include <utility>
1414
#include <unordered_map>
15+
#include <algorithm>
1516

1617
// OpenAL headers
1718
#ifdef __APPLE__

attachments/simple_engine/audio_system.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <queue>
1212
#include <vulkan/vulkan_raii.hpp>
1313
#include <vulkan/vk_platform.h>
14+
#include <stdexcept>
1415

1516
/**
1617
* @brief Class representing an audio source.
@@ -148,6 +149,13 @@ class AudioSystem {
148149
*/
149150
AudioSystem() = default;
150151

152+
// Constructor-based initialization to replace separate Initialize() calls
153+
AudioSystem(Engine* engine, Renderer* renderer) {
154+
if (!Initialize(engine, renderer)) {
155+
throw std::runtime_error("AudioSystem: initialization failed");
156+
}
157+
}
158+
151159
/**
152160
* @brief Flush audio output: clears pending processing and device buffers so playback restarts cleanly.
153161
*/

attachments/simple_engine/engine.cpp

Lines changed: 31 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,7 @@
1313
// @see en/Building_a_Simple_Engine/Engine_Architecture/02_architectural_patterns.adoc
1414

1515
Engine::Engine()
16-
: resourceManager(std::make_unique<ResourceManager>()),
17-
modelLoader(std::make_unique<ModelLoader>()),
18-
audioSystem(std::make_unique<AudioSystem>()),
19-
physicsSystem(std::make_unique<PhysicsSystem>()),
20-
imguiSystem(std::make_unique<ImGuiSystem>()) {
16+
: resourceManager(std::make_unique<ResourceManager>()) {
2117
}
2218

2319
Engine::~Engine() {
@@ -64,37 +60,25 @@ bool Engine::Initialize(const std::string& appName, int width, int height, bool
6460
return false;
6561
}
6662

67-
// Initialize model loader
68-
if (!modelLoader->Initialize(renderer.get())) {
69-
return false;
70-
}
71-
72-
// Connect model loader to renderer for light extraction
73-
renderer->SetModelLoader(modelLoader.get());
74-
75-
// Initialize audio system
76-
if (!audioSystem->Initialize(this, renderer.get())) {
77-
return false;
78-
}
79-
80-
// Initialize a physics system
81-
physicsSystem->SetRenderer(renderer.get());
63+
try {
64+
// Model loader via constructor; also wire into renderer
65+
modelLoader = std::make_unique<ModelLoader>(renderer.get());
66+
renderer->SetModelLoader(modelLoader.get());
8267

83-
// Enable GPU acceleration for physics calculations to drastically speed up computations
84-
physicsSystem->SetGPUAccelerationEnabled(true);
68+
// Audio system via constructor
69+
audioSystem = std::make_unique<AudioSystem>(this, renderer.get());
8570

86-
if (!physicsSystem->Initialize()) {
87-
return false;
88-
}
71+
// Physics system via constructor (GPU enabled)
72+
physicsSystem = std::make_unique<PhysicsSystem>(renderer.get(), true);
8973

90-
// Initialize ImGui system
91-
if (!imguiSystem->Initialize(renderer.get(), width, height)) {
74+
// ImGui via constructor, then connect audio system
75+
imguiSystem = std::make_unique<ImGuiSystem>(renderer.get(), width, height);
76+
imguiSystem->SetAudioSystem(audioSystem.get());
77+
} catch (const std::exception& e) {
78+
std::cerr << "Subsystem initialization failed: " << e.what() << std::endl;
9279
return false;
9380
}
9481

95-
// Connect ImGui system to an audio system for UI controls
96-
imguiSystem->SetAudioSystem(audioSystem.get());
97-
9882
// Generate ball material properties once at load time
9983
GenerateBallMaterial();
10084

@@ -132,9 +116,15 @@ void Engine::Run() {
132116
// Update window title with FPS and frame time every second
133117
if (fpsUpdateTimer >= 1.0f) {
134118
uint64_t framesSinceLastUpdate = frameCount - lastFPSUpdateFrame;
135-
currentFPS = framesSinceLastUpdate / fpsUpdateTimer;
136-
// Average frame time in milliseconds over the last interval
137-
double avgMs = (fpsUpdateTimer / static_cast<double>(framesSinceLastUpdate)) * 1000.0;
119+
double avgMs = 0.0;
120+
if (framesSinceLastUpdate > 0 && fpsUpdateTimer > 0.0f) {
121+
currentFPS = static_cast<float>(static_cast<double>(framesSinceLastUpdate) / static_cast<double>(fpsUpdateTimer));
122+
avgMs = (fpsUpdateTimer / static_cast<double>(framesSinceLastUpdate)) * 1000.0;
123+
} else {
124+
// Avoid divide-by-zero; keep previous FPS and estimate avgMs from last delta
125+
currentFPS = std::max(currentFPS, 1.0f);
126+
avgMs = static_cast<double>(deltaTimeMs.count());
127+
}
138128

139129
// Update window title with frame count, FPS, and frame time
140130
std::string title = "Simple Engine - Frame: " + std::to_string(frameCount) +
@@ -402,15 +392,19 @@ void Engine::Update(TimeDelta deltaTime) {
402392
UpdateCameraControls(deltaTime);
403393
}
404394

405-
// Update all entities
395+
// Update all entities (guard against null unique_ptrs)
406396
for (auto& entity : entities) {
407-
if (entity->IsActive()) {
408-
entity->Update(deltaTime);
409-
}
397+
if (!entity) { continue; }
398+
if (!entity->IsActive()) { continue; }
399+
entity->Update(deltaTime);
410400
}
411401
}
412402

413403
void Engine::Render() {
404+
// Ensure renderer is ready
405+
if (!renderer || !renderer->IsInitialized()) {
406+
return;
407+
}
414408

415409
// Check if we have an active camera
416410
if (!activeCamera) {

attachments/simple_engine/imgui_system.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ void ImGuiSystem::NewFrame() {
218218
}
219219

220220
// Exposure slider
221-
static float exposure = 3.0f; // Higher default for emissive lighting
221+
static float exposure = 1.2f; // Default tuned to avoid washout
222222
if (ImGui::SliderFloat("Exposure", &exposure, 0.1f, 10.0f, "%.2f")) {
223223
// Update exposure in renderer
224224
if (renderer) {
@@ -228,7 +228,7 @@ void ImGuiSystem::NewFrame() {
228228
}
229229
ImGui::SameLine();
230230
if (ImGui::Button("Reset##Exposure")) {
231-
exposure = 3.0f; // Reset to higher value for emissive lighting
231+
exposure = 1.2f; // Reset to a sane default to avoid washout
232232
if (renderer) {
233233
renderer->SetExposure(exposure);
234234
}

attachments/simple_engine/imgui_system.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <memory>
66
#include <vulkan/vulkan_raii.hpp>
77
#include <vulkan/vk_platform.h>
8+
#include <stdexcept>
89

910
// Forward declarations
1011
class Renderer;
@@ -25,6 +26,13 @@ class ImGuiSystem {
2526
*/
2627
ImGuiSystem();
2728

29+
// Constructor-based initialization to replace separate Initialize() calls
30+
ImGuiSystem(Renderer* renderer, uint32_t width, uint32_t height) {
31+
if (!Initialize(renderer, width, height)) {
32+
throw std::runtime_error("ImGuiSystem: initialization failed");
33+
}
34+
}
35+
2836
/**
2937
* @brief Destructor for proper cleanup.
3038
*/

attachments/simple_engine/mesh_component.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,23 @@ void MeshComponent::CreateSphere(float radius, const glm::vec3& color, int segme
3636
static_cast<float>(lat) / static_cast<float>(segments)
3737
};
3838

39-
// Calculate tangent (derivative with respect to longitude)
39+
// Calculate tangent (derivative with respect to longitude). Handle poles robustly.
4040
glm::vec3 tangent = {
4141
-sinTheta * sinPhi,
4242
0.0f,
4343
sinTheta * cosPhi
4444
};
45-
tangent = glm::normalize(tangent);
45+
float len2 = glm::dot(tangent, tangent);
46+
if (len2 < 1e-12f) {
47+
// At poles sinTheta ~ 0 -> fallback tangent orthogonal to normal
48+
glm::vec3 t = glm::cross(normal, glm::vec3(0.0f, 0.0f, 1.0f));
49+
if (glm::length(t) < 1e-12f) {
50+
t = glm::cross(normal, glm::vec3(1.0f, 0.0f, 0.0f));
51+
}
52+
tangent = glm::normalize(t);
53+
} else {
54+
tangent = glm::normalize(tangent);
55+
}
4656

4757
vertices.push_back({
4858
position,

0 commit comments

Comments
 (0)