Skip to content

Commit 0ef0316

Browse files
committed
Working through some of the PR comments. Concentrating on the text of the tutorial section first as only 90 total comments there, 200+ in the attachments and there's still bugs in the game engine itself. Holding back game code changes until it's bug free.
1 parent 03d05cf commit 0ef0316

File tree

6 files changed

+61
-49
lines changed

6 files changed

+61
-49
lines changed

en/Building_a_Simple_Engine/Camera_Transformations/02_math_foundations.adoc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ In our camera system, vectors serve several critical purposes:
2929
* *Scalar Multiplication*: Used for scaling movements and directions
3030
- Example: Slowing down camera movement by multiplying velocity by a factor < 1
3131

32-
* *Dot Product*: Calculates the cosine of the angle between vectors (when normalized)
32+
* *Dot Product*: Calculates the cosine of the angle between normalized vectors.
3333
- Applications: Determining if objects are facing the camera, calculating lighting intensity
3434

3535
==== The Right-Hand Rule
@@ -524,7 +524,7 @@ struct Sphere {
524524
525525
bool rayIntersectsSphere(const Ray& ray, const Sphere& sphere, float& t) {
526526
// Vector from ray origin to sphere center
527-
glm::vec3 oc = ray.origin - sphere.center;
527+
glm::vec3 oc = sphere.center - ray.origin;
528528
529529
// Quadratic equation coefficients
530530
float a = glm::dot(ray.direction, ray.direction); // Always 1 if direction is normalized
@@ -710,7 +710,7 @@ For complex scenes with many objects, raycasting can become computationally expe
710710

711711
* *Ray Batching*: Process multiple rays together to take advantage of SIMD instructions
712712

713-
* *Early Termination*: Stop testing once you've found the closest intersection (if that's all you need)
713+
* *Early Termination*: Stop testing once you've found any intersection (if that's all you need)
714714

715715
=== Projection in 3D Graphics
716716

en/Building_a_Simple_Engine/Camera_Transformations/03_camera_implementation.adoc

Lines changed: 32 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ Now that we understand the mathematical foundations, let's implement a flexible
1111
There are several types of cameras commonly used in 3D applications:
1212

1313
* *First-Person Camera*: Simulates viewing the world through the eyes of a character.
14-
* *Third-Person Camera*: Follows a character from behind or another fixed position.
14+
* *Third-Person Camera*: Follows a character from behind or another fixed relative position.
1515
* *Orbit Camera*: Rotates around a fixed point, useful for object inspection.
1616
* *Free Camera*: Allows unrestricted movement in all directions.
1717

@@ -27,7 +27,7 @@ class Camera {
2727
private:
2828
// Camera position and orientation
2929
glm::vec3 position;
30-
glm::vec3 front;
30+
glm::vec3 forward;
3131
glm::vec3 up;
3232
glm::vec3 right;
3333
glm::vec3 worldUp;
@@ -40,6 +40,9 @@ private:
4040
float movementSpeed;
4141
float mouseSensitivity;
4242
float zoom;
43+
float aspectRatio;
44+
float nearPlane;
45+
float farPlane;
4346
4447
// Update camera vectors based on Euler angles
4548
void updateCameraVectors();
@@ -57,16 +60,16 @@ public:
5760
glm::mat4 getViewMatrix() const;
5861
5962
// Get projection matrix
60-
glm::mat4 getProjectionMatrix(float aspectRatio, float nearPlane = 0.1f, float farPlane = 100.0f) const;
63+
glm::mat4 getProjectionMatrix() const;
6164
62-
// Process keyboard input for camera movement
63-
void processKeyboard(CameraMovement direction, float deltaTime);
65+
// Process camera movement (translation)
66+
void move(CameraMovement direction, float deltaTime);
6467
65-
// Process mouse movement for camera rotation
66-
void processMouseMovement(float xOffset, float yOffset, bool constrainPitch = true);
68+
// Process camera rotation
69+
void rotate(float xOffset, float yOffset, bool constrainPitch = true);
6770
68-
// Process mouse scroll for zoom
69-
void processMouseScroll(float yOffset);
71+
// Process zoom
72+
void zoom(float delta);
7073
7174
// Getters for camera properties
7275
glm::vec3 getPosition() const { return position; }
@@ -98,18 +101,26 @@ And implement the movement logic:
98101
void Camera::processKeyboard(CameraMovement direction, float deltaTime) {
99102
float velocity = movementSpeed * deltaTime;
100103
101-
if (direction == CameraMovement::FORWARD)
102-
position += front * velocity;
103-
if (direction == CameraMovement::BACKWARD)
104-
position -= front * velocity;
105-
if (direction == CameraMovement::LEFT)
106-
position -= right * velocity;
107-
if (direction == CameraMovement::RIGHT)
108-
position += right * velocity;
109-
if (direction == CameraMovement::UP)
110-
position += up * velocity;
111-
if (direction == CameraMovement::DOWN)
112-
position -= up * velocity;
104+
switch (direction) {
105+
case CameraMovement::FORWARD:
106+
position += front * velocity;
107+
break;
108+
case CameraMovement::BACKWARD:
109+
position -= front * velocity;
110+
break;
111+
case CameraMovement::LEFT:
112+
position -= right * velocity;
113+
break;
114+
case CameraMovement::RIGHT:
115+
position += right * velocity;
116+
break;
117+
case CameraMovement::UP:
118+
position += up * velocity;
119+
break;
120+
case CameraMovement::DOWN:
121+
position -= up * velocity;
122+
break;
123+
}
113124
}
114125
----
115126

en/Building_a_Simple_Engine/Camera_Transformations/05_vulkan_integration.adoc

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -69,15 +69,13 @@ std::array<UboBuffer, maxConcurrentFrames> uniformBuffers;
6969
7070
void createUniformBuffers() {
7171
vk::DeviceSize bufferSize = sizeof(UniformBufferObject);
72-
72+
// Create the buffer
73+
vk::BufferCreateInfo bufferInfo{
74+
.size = bufferSize,
75+
.usage = vk::BufferUsageFlagBits::eUniformBuffer,
76+
.sharingMode = vk::SharingMode::eExclusive
77+
};
7378
for (size_t i = 0; i < maxConcurrentFrames; i++) {
74-
// Create the buffer
75-
vk::BufferCreateInfo bufferInfo{
76-
.size = bufferSize,
77-
.usage = vk::BufferUsageFlagBits::eUniformBuffer,
78-
.sharingMode = vk::SharingMode::eExclusive
79-
};
80-
8179
uniformBuffers[i].buffer = vk::raii::Buffer(device, bufferInfo);
8280
8381
// Allocate and bind memory

en/Building_a_Simple_Engine/Engine_Architecture/01_introduction.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ This chapter builds directly on the foundation established in the main Vulkan tu
3535

3636
Beyond Vulkan knowledge, you'll benefit from familiarity with object-oriented programming principles, as modern engine architecture relies heavily on encapsulation, inheritance, and polymorphism to manage complexity. Experience with common design patterns like Observer, Factory, and Singleton will help you recognize when and why we apply these patterns in our engine design.
3737

38-
Modern C++ features play a crucial role in our implementation approach. Smart pointers help us manage resource lifetimes safely, templates enable flexible, reusable components, and other C++11/14/17 features allow us to write more expressive and maintainable code. If you're not comfortable with these concepts, consider reviewing them before proceeding.
38+
Modern C:pp: features play a crucial role in our implementation approach. Smart pointers help us manage resource lifetimes safely, templates enable flexible, reusable components, and other C:pp:11/14/17 features allow us to write more expressive and maintainable code. If you're not comfortable with these concepts, consider reviewing them before proceeding.
3939

4040
You should also be familiar with the following chapters from the main tutorial:
4141

en/Building_a_Simple_Engine/Engine_Architecture/03_component_systems.adoc

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -102,13 +102,6 @@ public:
102102
T* AddComponent(Args&&... args) {
103103
static_assert(std::is_base_of<Component, T>::value, "T must derive from Component");
104104
105-
// Check if component of this type already exists
106-
for (auto& component : components) {
107-
if (dynamic_cast<T*>(component.get())) {
108-
return dynamic_cast<T*>(component.get());
109-
}
110-
}
111-
112105
// Create new component
113106
auto component = std::make_unique<T>(std::forward<Args>(args)...);
114107
T* componentPtr = component.get();

en/Building_a_Simple_Engine/Engine_Architecture/04_resource_management.adoc

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -95,14 +95,19 @@ public:
9595
bool IsLoaded() const { return loaded; }
9696
9797
// Virtual interface for resource-specific loading and unloading behavior
98-
virtual bool Load() {
99-
loaded = true;
100-
return true;
98+
bool Load() {
99+
loaded = doLoad();
100+
return loaded;
101101
}
102102
103-
virtual void Unload() {
103+
void Unload() {
104+
doUnload();
104105
loaded = false;
105106
}
107+
108+
protected:
109+
virtual bool doLoad() = 0;
110+
virtual bool doUnload() = 0;
106111
};
107112
----
108113

@@ -124,9 +129,14 @@ private:
124129
std::unordered_map<std::type_index,
125130
std::unordered_map<std::string, std::shared_ptr<Resource>>> resources;
126131
127-
// Reference counting system for automatic resource lifecycle management
128-
// Maps resource IDs to their current usage count for garbage collection
129-
std::unordered_map<std::string, int> refCounts;
132+
// Two-level reference counting system for automatic resource lifecycle management
133+
// First level maps resource type, second level maps resource IDs to their data
134+
struct ResourceData {
135+
std::shared_ptr<Resource> resource; // The actual resource
136+
int refCount; // Reference count for this resource
137+
};
138+
std::unordered_map<std::type_index,
139+
std::unordered_map<std::string, ResourceData>> refCounts;
130140
----
131141

132142
The storage architecture uses a sophisticated two-level mapping system that solves several critical problems in resource management. The outer map keyed by `std::type_index` ensures complete type separation, preventing name collisions between different resource types. For example, you could have both a texture named "stone" and a sound effect named "stone" without conflicts, as they're stored in separate type-specific containers.
@@ -201,8 +211,8 @@ After that, we provide the interface for safely accessing cached resources with
201211
template<typename T>
202212
bool HasResource(const std::string& resourceId) {
203213
// Efficient existence check without resource access overhead
204-
auto& typeResources = resources[std::type_index(typeid(T))];
205-
return typeResources.find(resourceId) != typeResources.end();
214+
auto resourceIt = resources.find(std::type_index(typeid(T)));
215+
return resourceIt != resources.end();
206216
}
207217
----
208218

0 commit comments

Comments
 (0)