summaryrefslogtreecommitdiff
path: root/src/3d
diff options
context:
space:
mode:
Diffstat (limited to 'src/3d')
-rw-r--r--src/3d/object.h6
-rw-r--r--src/3d/physics.cc2
-rw-r--r--src/3d/renderer.cc63
-rw-r--r--src/3d/renderer.h11
-rw-r--r--src/3d/renderer_mesh.cc8
-rw-r--r--src/3d/scene_loader.cc196
-rw-r--r--src/3d/scene_loader.h9
-rw-r--r--src/3d/visual_debug.cc67
-rw-r--r--src/3d/visual_debug.h10
9 files changed, 222 insertions, 150 deletions
diff --git a/src/3d/object.h b/src/3d/object.h
index c2d9ba1..dcd96e3 100644
--- a/src/3d/object.h
+++ b/src/3d/object.h
@@ -4,8 +4,8 @@
#pragma once
-#include "util/mini_math.h"
#include "util/asset_manager_dcl.h"
+#include "util/mini_math.h"
enum class ObjectType {
CUBE,
@@ -41,12 +41,12 @@ class Object3D {
AssetId mesh_asset_id;
vec3 local_extent; // Half-extents for AABB (used by meshes for shadows)
- void* user_data; // For tool-specific data, not for general use
+ void* user_data; // For tool-specific data, not for general use
Object3D(ObjectType t = ObjectType::CUBE)
: position(0, 0, 0), rotation(0, 0, 0, 1), scale(1, 1, 1), type(t),
color(1, 1, 1, 1), velocity(0, 0, 0), mass(1.0f), restitution(0.5f),
- is_static(false), mesh_asset_id((AssetId)0), local_extent(1, 1, 1),
+ is_static(false), mesh_asset_id((AssetId)0), local_extent(1, 1, 1),
user_data(nullptr) {
}
diff --git a/src/3d/physics.cc b/src/3d/physics.cc
index 229eb40..2aa101d 100644
--- a/src/3d/physics.cc
+++ b/src/3d/physics.cc
@@ -54,7 +54,7 @@ float PhysicsSystem::sample_sdf(const Object3D& obj, vec3 world_p) {
float sx = vec3(model.m[0], model.m[1], model.m[2]).len();
float sy = vec3(model.m[4], model.m[5], model.m[6]).len();
float sz = vec3(model.m[8], model.m[9], model.m[10]).len();
-
+
float s = std::min(sx, std::min(sy, sz));
if (obj.type == ObjectType::PLANE) {
s = sy; // For plane with local normal (0,1,0), scale is sy
diff --git a/src/3d/renderer.cc b/src/3d/renderer.cc
index c37ea79..e08a0d0 100644
--- a/src/3d/renderer.cc
+++ b/src/3d/renderer.cc
@@ -117,10 +117,12 @@ void Renderer3D::create_default_resources() {
WGPUBufferUsage_Storage | WGPUBufferUsage_CopyDst,
nullptr)
.buffer;
- bvh_storage_buffer_ = gpu_create_buffer(
- device_, sizeof(BVHNode) * kMaxObjects * 2, // Capacity for a full tree
- WGPUBufferUsage_Storage | WGPUBufferUsage_CopyDst, nullptr)
- .buffer;
+ bvh_storage_buffer_ =
+ gpu_create_buffer(
+ device_,
+ sizeof(BVHNode) * kMaxObjects * 2, // Capacity for a full tree
+ WGPUBufferUsage_Storage | WGPUBufferUsage_CopyDst, nullptr)
+ .buffer;
}
void Renderer3D::set_noise_texture(WGPUTextureView noise_view) {
@@ -165,15 +167,30 @@ void Renderer3D::update_uniforms(const Scene& scene, const Camera& camera,
data.color = obj.color;
float type_id = 0.0f;
switch (obj.type) {
- case ObjectType::SPHERE: type_id = 1.0f; break;
- case ObjectType::BOX: type_id = 2.0f; break;
- case ObjectType::CUBE: type_id = 2.0f; break; // CUBE is same as BOX for shader
- case ObjectType::TORUS: type_id = 3.0f; break;
- case ObjectType::PLANE: type_id = 4.0f; break;
- case ObjectType::MESH: type_id = 5.0f; break;
- default: type_id = 0.0f; break;
+ case ObjectType::SPHERE:
+ type_id = 1.0f;
+ break;
+ case ObjectType::BOX:
+ type_id = 2.0f;
+ break;
+ case ObjectType::CUBE:
+ type_id = 2.0f;
+ break; // CUBE is same as BOX for shader
+ case ObjectType::TORUS:
+ type_id = 3.0f;
+ break;
+ case ObjectType::PLANE:
+ type_id = 4.0f;
+ break;
+ case ObjectType::MESH:
+ type_id = 5.0f;
+ break;
+ default:
+ type_id = 0.0f;
+ break;
}
- data.params = vec4(type_id, obj.local_extent.x, obj.local_extent.y, obj.local_extent.z);
+ data.params = vec4(type_id, obj.local_extent.x, obj.local_extent.y,
+ obj.local_extent.z);
obj_data.push_back(data);
if (obj_data.size() >= kMaxObjects)
break;
@@ -243,8 +260,7 @@ void Renderer3D::draw(WGPURenderPassEncoder pass, const Scene& scene,
{
WGPUBindGroupEntry e = {};
e.binding = 5;
- e.textureView =
- sky_texture_view_ ? sky_texture_view_ : noise_texture_view_;
+ e.textureView = sky_texture_view_ ? sky_texture_view_ : noise_texture_view_;
bg_entries.push_back(e);
}
@@ -284,13 +300,15 @@ void Renderer3D::draw(WGPURenderPassEncoder pass, const Scene& scene,
for (uint32_t i = 0; i < instance_count; ++i) {
const auto& obj = scene.objects[i];
if (obj.type == ObjectType::MESH) {
- const MeshGpuData* mesh = temp_mesh_override_ ? temp_mesh_override_ : get_or_create_mesh(obj.mesh_asset_id);
+ const MeshGpuData* mesh = temp_mesh_override_
+ ? temp_mesh_override_
+ : get_or_create_mesh(obj.mesh_asset_id);
if (mesh) {
- wgpuRenderPassEncoderSetVertexBuffer(pass, 0, mesh->vertex_buffer, 0,
- WGPU_WHOLE_SIZE);
- wgpuRenderPassEncoderSetIndexBuffer(
- pass, mesh->index_buffer, WGPUIndexFormat_Uint32, 0,
- WGPU_WHOLE_SIZE);
+ wgpuRenderPassEncoderSetVertexBuffer(pass, 0, mesh->vertex_buffer,
+ 0, WGPU_WHOLE_SIZE);
+ wgpuRenderPassEncoderSetIndexBuffer(pass, mesh->index_buffer,
+ WGPUIndexFormat_Uint32, 0,
+ WGPU_WHOLE_SIZE);
wgpuRenderPassEncoderDrawIndexed(pass, mesh->num_indices, 1, 0, 0,
i);
}
@@ -308,7 +326,10 @@ void Renderer3D::draw(WGPURenderPassEncoder pass, const Scene& scene,
} else if (obj.type == ObjectType::MESH) {
MeshAsset mesh = GetMeshAsset(obj.mesh_asset_id);
if (mesh.num_indices > 0) {
- visual_debug_.add_mesh_wireframe(obj.get_model_matrix(), mesh.num_vertices, mesh.vertices, mesh.num_indices, mesh.indices, vec3(0.0f, 1.0f, 1.0f)); // Cyan wireframe
+ visual_debug_.add_mesh_wireframe(
+ obj.get_model_matrix(), mesh.num_vertices, mesh.vertices,
+ mesh.num_indices, mesh.indices,
+ vec3(0.0f, 1.0f, 1.0f)); // Cyan wireframe
}
} else {
extent = vec3(1.0f, 1.0f, 1.0f);
diff --git a/src/3d/renderer.h b/src/3d/renderer.h
index 5c9fd38..02e01d5 100644
--- a/src/3d/renderer.h
+++ b/src/3d/renderer.h
@@ -4,9 +4,9 @@
#pragma once
+#include "3d/bvh.h"
#include "3d/camera.h"
#include "3d/scene.h"
-#include "3d/bvh.h"
#include "gpu/gpu.h"
#include <map>
#include <vector>
@@ -63,7 +63,9 @@ class Renderer3D {
void resize(int width, int height);
// Set whether to use BVH acceleration
- void SetBvhEnabled(bool enabled) { bvh_enabled_ = enabled; }
+ void SetBvhEnabled(bool enabled) {
+ bvh_enabled_ = enabled;
+ }
struct MeshGpuData {
WGPUBuffer vertex_buffer;
@@ -77,11 +79,12 @@ class Renderer3D {
}
#if !defined(STRIP_ALL)
- VisualDebug& GetVisualDebug() { return visual_debug_; }
+ VisualDebug& GetVisualDebug() {
+ return visual_debug_;
+ }
#endif
private:
-
void create_pipeline();
WGPURenderPipeline create_pipeline_impl(bool use_bvh);
void create_mesh_pipeline();
diff --git a/src/3d/renderer_mesh.cc b/src/3d/renderer_mesh.cc
index 0a098ef..7ef2b42 100644
--- a/src/3d/renderer_mesh.cc
+++ b/src/3d/renderer_mesh.cc
@@ -81,15 +81,17 @@ void Renderer3D::create_mesh_pipeline() {
WGPUPipelineLayout pipeline_layout =
wgpuDeviceCreatePipelineLayout(device_, &pl_desc);
- const char* shader_code_asset = (const char*)GetAsset(AssetId::ASSET_SHADER_MESH);
-
+ const char* shader_code_asset =
+ (const char*)GetAsset(AssetId::ASSET_SHADER_MESH);
+
ShaderComposer::CompositionMap composition_map;
if (bvh_enabled_) {
composition_map["render/scene_query_mode"] = "render/scene_query_bvh";
} else {
composition_map["render/scene_query_mode"] = "render/scene_query_linear";
}
- std::string shader_source = ShaderComposer::Get().Compose({}, shader_code_asset, composition_map);
+ std::string shader_source =
+ ShaderComposer::Get().Compose({}, shader_code_asset, composition_map);
#if defined(DEMO_CROSS_COMPILE_WIN32)
WGPUShaderModuleWGSLDescriptor wgsl_desc = {};
diff --git a/src/3d/scene_loader.cc b/src/3d/scene_loader.cc
index 69079ef..669fac8 100644
--- a/src/3d/scene_loader.cc
+++ b/src/3d/scene_loader.cc
@@ -1,108 +1,140 @@
#include "3d/scene_loader.h"
-#include "util/asset_manager.h"
#include "generated/assets.h"
+#include "util/asset_manager.h"
#include "util/mini_math.h"
-#include <cstring>
#include <cstdio>
+#include <cstring>
#include <vector>
bool SceneLoader::LoadScene(Scene& scene, const uint8_t* data, size_t size) {
- if (!data || size < 16) { // Header size check
- printf("SceneLoader: Data too small\n");
- return false;
- }
+ if (!data || size < 16) { // Header size check
+ printf("SceneLoader: Data too small\n");
+ return false;
+ }
- // Check Magic
- if (std::memcmp(data, "SCN1", 4) != 0) {
- printf("SceneLoader: Invalid magic (expected SCN1)\n");
- return false;
- }
-
- size_t offset = 4;
+ // Check Magic
+ if (std::memcmp(data, "SCN1", 4) != 0) {
+ printf("SceneLoader: Invalid magic (expected SCN1)\n");
+ return false;
+ }
- uint32_t num_objects = *reinterpret_cast<const uint32_t*>(data + offset); offset += 4;
- uint32_t num_cameras = *reinterpret_cast<const uint32_t*>(data + offset); offset += 4;
- uint32_t num_lights = *reinterpret_cast<const uint32_t*>(data + offset); offset += 4;
+ size_t offset = 4;
- // printf("SceneLoader: Loading %d objects, %d cameras, %d lights\n", num_objects, num_cameras, num_lights);
+ uint32_t num_objects = *reinterpret_cast<const uint32_t*>(data + offset);
+ offset += 4;
+ uint32_t num_cameras = *reinterpret_cast<const uint32_t*>(data + offset);
+ offset += 4;
+ uint32_t num_lights = *reinterpret_cast<const uint32_t*>(data + offset);
+ offset += 4;
- for (uint32_t i = 0; i < num_objects; ++i) {
- if (offset + 64 > size) return false; // Name check
-
- char name[65] = {0};
- std::memcpy(name, data + offset, 64); offset += 64;
+ // printf("SceneLoader: Loading %d objects, %d cameras, %d lights\n",
+ // num_objects, num_cameras, num_lights);
- if (offset + 4 > size) return false;
- uint32_t type_val = *reinterpret_cast<const uint32_t*>(data + offset); offset += 4;
- ObjectType type = (ObjectType)type_val;
+ for (uint32_t i = 0; i < num_objects; ++i) {
+ if (offset + 64 > size)
+ return false; // Name check
- if (offset + 12 + 16 + 12 + 16 > size) return false; // Transforms + Color
+ char name[65] = {0};
+ std::memcpy(name, data + offset, 64);
+ offset += 64;
- float px = *reinterpret_cast<const float*>(data + offset); offset += 4;
- float py = *reinterpret_cast<const float*>(data + offset); offset += 4;
- float pz = *reinterpret_cast<const float*>(data + offset); offset += 4;
- vec3 pos(px, py, pz);
+ if (offset + 4 > size)
+ return false;
+ uint32_t type_val = *reinterpret_cast<const uint32_t*>(data + offset);
+ offset += 4;
+ ObjectType type = (ObjectType)type_val;
- float rx = *reinterpret_cast<const float*>(data + offset); offset += 4;
- float ry = *reinterpret_cast<const float*>(data + offset); offset += 4;
- float rz = *reinterpret_cast<const float*>(data + offset); offset += 4;
- float rw = *reinterpret_cast<const float*>(data + offset); offset += 4;
- quat rot(rx, ry, rz, rw);
+ if (offset + 12 + 16 + 12 + 16 > size)
+ return false; // Transforms + Color
- float sx = *reinterpret_cast<const float*>(data + offset); offset += 4;
- float sy = *reinterpret_cast<const float*>(data + offset); offset += 4;
- float sz = *reinterpret_cast<const float*>(data + offset); offset += 4;
- vec3 scale(sx, sy, sz);
+ float px = *reinterpret_cast<const float*>(data + offset);
+ offset += 4;
+ float py = *reinterpret_cast<const float*>(data + offset);
+ offset += 4;
+ float pz = *reinterpret_cast<const float*>(data + offset);
+ offset += 4;
+ vec3 pos(px, py, pz);
- float cr = *reinterpret_cast<const float*>(data + offset); offset += 4;
- float cg = *reinterpret_cast<const float*>(data + offset); offset += 4;
- float cb = *reinterpret_cast<const float*>(data + offset); offset += 4;
- float ca = *reinterpret_cast<const float*>(data + offset); offset += 4;
- vec4 color(cr, cg, cb, ca);
+ float rx = *reinterpret_cast<const float*>(data + offset);
+ offset += 4;
+ float ry = *reinterpret_cast<const float*>(data + offset);
+ offset += 4;
+ float rz = *reinterpret_cast<const float*>(data + offset);
+ offset += 4;
+ float rw = *reinterpret_cast<const float*>(data + offset);
+ offset += 4;
+ quat rot(rx, ry, rz, rw);
- // Mesh Asset Name Length
- if (offset + 4 > size) return false;
- uint32_t name_len = *reinterpret_cast<const uint32_t*>(data + offset); offset += 4;
+ float sx = *reinterpret_cast<const float*>(data + offset);
+ offset += 4;
+ float sy = *reinterpret_cast<const float*>(data + offset);
+ offset += 4;
+ float sz = *reinterpret_cast<const float*>(data + offset);
+ offset += 4;
+ vec3 scale(sx, sy, sz);
- AssetId mesh_id = (AssetId)0; // Default or INVALID (if 0 is invalid)
+ float cr = *reinterpret_cast<const float*>(data + offset);
+ offset += 4;
+ float cg = *reinterpret_cast<const float*>(data + offset);
+ offset += 4;
+ float cb = *reinterpret_cast<const float*>(data + offset);
+ offset += 4;
+ float ca = *reinterpret_cast<const float*>(data + offset);
+ offset += 4;
+ vec4 color(cr, cg, cb, ca);
- if (name_len > 0) {
- if (offset + name_len > size) return false;
- char mesh_name[128] = {0};
- if (name_len < 128) {
- std::memcpy(mesh_name, data + offset, name_len);
- }
- offset += name_len;
-
- // Resolve Asset ID
- mesh_id = GetAssetIdByName(mesh_name);
- if (mesh_id == AssetId::ASSET_LAST_ID) {
- printf("SceneLoader: Warning: Mesh asset '%s' not found for object '%s'\n", mesh_name, name);
- }
- }
+ // Mesh Asset Name Length
+ if (offset + 4 > size)
+ return false;
+ uint32_t name_len = *reinterpret_cast<const uint32_t*>(data + offset);
+ offset += 4;
- // Physics properties
- if (offset + 4 + 4 + 4 > size) return false;
- float mass = *reinterpret_cast<const float*>(data + offset); offset += 4;
- float restitution = *reinterpret_cast<const float*>(data + offset); offset += 4;
- uint32_t is_static_u32 = *reinterpret_cast<const uint32_t*>(data + offset); offset += 4;
- bool is_static = (is_static_u32 != 0);
+ AssetId mesh_id = (AssetId)0; // Default or INVALID (if 0 is invalid)
- // Create Object3D
- Object3D obj(type);
- obj.position = pos;
- obj.rotation = rot;
- obj.scale = scale;
- obj.color = color;
- obj.mesh_asset_id = mesh_id;
- obj.mass = mass;
- obj.restitution = restitution;
- obj.is_static = is_static;
- // user_data is nullptr by default
+ if (name_len > 0) {
+ if (offset + name_len > size)
+ return false;
+ char mesh_name[128] = {0};
+ if (name_len < 128) {
+ std::memcpy(mesh_name, data + offset, name_len);
+ }
+ offset += name_len;
- // Add to scene
- scene.add_object(obj);
+ // Resolve Asset ID
+ mesh_id = GetAssetIdByName(mesh_name);
+ if (mesh_id == AssetId::ASSET_LAST_ID) {
+ printf(
+ "SceneLoader: Warning: Mesh asset '%s' not found for object '%s'\n",
+ mesh_name, name);
+ }
}
- return true;
+ // Physics properties
+ if (offset + 4 + 4 + 4 > size)
+ return false;
+ float mass = *reinterpret_cast<const float*>(data + offset);
+ offset += 4;
+ float restitution = *reinterpret_cast<const float*>(data + offset);
+ offset += 4;
+ uint32_t is_static_u32 = *reinterpret_cast<const uint32_t*>(data + offset);
+ offset += 4;
+ bool is_static = (is_static_u32 != 0);
+
+ // Create Object3D
+ Object3D obj(type);
+ obj.position = pos;
+ obj.rotation = rot;
+ obj.scale = scale;
+ obj.color = color;
+ obj.mesh_asset_id = mesh_id;
+ obj.mass = mass;
+ obj.restitution = restitution;
+ obj.is_static = is_static;
+ // user_data is nullptr by default
+
+ // Add to scene
+ scene.add_object(obj);
+ }
+
+ return true;
} \ No newline at end of file
diff --git a/src/3d/scene_loader.h b/src/3d/scene_loader.h
index 15f08c7..eabfb7a 100644
--- a/src/3d/scene_loader.h
+++ b/src/3d/scene_loader.h
@@ -1,14 +1,15 @@
#pragma once
#include "3d/scene.h"
-#include <cstdint>
#include <cstddef>
+#include <cstdint>
-// SceneLoader handles parsing of binary scene files (.bin) exported from Blender.
-// It populates a Scene object with objects, lights, and cameras.
+// SceneLoader handles parsing of binary scene files (.bin) exported from
+// Blender. It populates a Scene object with objects, lights, and cameras.
class SceneLoader {
public:
// Loads a scene from a binary buffer.
- // Returns true on success, false on failure (e.g., invalid magic, version mismatch).
+ // Returns true on success, false on failure (e.g., invalid magic, version
+ // mismatch).
static bool LoadScene(Scene& scene, const uint8_t* data, size_t size);
};
diff --git a/src/3d/visual_debug.cc b/src/3d/visual_debug.cc
index 78c751b..35ab60d 100644
--- a/src/3d/visual_debug.cc
+++ b/src/3d/visual_debug.cc
@@ -215,25 +215,28 @@ void VisualDebug::add_mesh_normals(const mat4& transform, uint32_t num_vertices,
vec4 p_world = transform * vec4(v.p[0], v.p[1], v.p[2], 1.0f);
vec3 n_object = vec3(v.n[0], v.n[1], v.n[2]);
- vec4 n_world_h = normal_matrix * vec4(n_object.x, n_object.y, n_object.z, 0.0f);
+ vec4 n_world_h =
+ normal_matrix * vec4(n_object.x, n_object.y, n_object.z, 0.0f);
vec3 n_world = n_world_h.xyz().normalize();
- lines_.push_back(
- {p_world.xyz(), p_world.xyz() + n_world * 0.1f, // 0.1 is the length
- {0.0f, 1.0f, 1.0f} // Cyan color
- });
+ lines_.push_back({
+ p_world.xyz(),
+ p_world.xyz() + n_world * 0.1f, // 0.1 is the length
+ {0.0f, 1.0f, 1.0f} // Cyan color
+ });
}
}
-void VisualDebug::add_mesh_wireframe(const mat4& transform, uint32_t num_vertices,
- const MeshVertex* vertices, uint32_t num_indices,
- const uint32_t* indices, const vec3& color) {
+void VisualDebug::add_mesh_wireframe(
+ const mat4& transform, uint32_t num_vertices, const MeshVertex* vertices,
+ uint32_t num_indices, const uint32_t* indices, const vec3& color) {
if (!vertices || !indices || num_indices == 0)
return;
for (uint32_t i = 0; i < num_indices; i += 3) {
- if (i + 2 >= num_indices) break;
-
+ if (i + 2 >= num_indices)
+ break;
+
uint32_t idx0 = indices[i];
uint32_t idx1 = indices[i + 1];
uint32_t idx2 = indices[i + 2];
@@ -241,9 +244,12 @@ void VisualDebug::add_mesh_wireframe(const mat4& transform, uint32_t num_vertice
if (idx0 >= num_vertices || idx1 >= num_vertices || idx2 >= num_vertices)
continue;
- vec4 p0_world = transform * vec4(vertices[idx0].p[0], vertices[idx0].p[1], vertices[idx0].p[2], 1.0f);
- vec4 p1_world = transform * vec4(vertices[idx1].p[0], vertices[idx1].p[1], vertices[idx1].p[2], 1.0f);
- vec4 p2_world = transform * vec4(vertices[idx2].p[0], vertices[idx2].p[1], vertices[idx2].p[2], 1.0f);
+ vec4 p0_world = transform * vec4(vertices[idx0].p[0], vertices[idx0].p[1],
+ vertices[idx0].p[2], 1.0f);
+ vec4 p1_world = transform * vec4(vertices[idx1].p[0], vertices[idx1].p[1],
+ vertices[idx1].p[2], 1.0f);
+ vec4 p2_world = transform * vec4(vertices[idx2].p[0], vertices[idx2].p[1],
+ vertices[idx2].p[2], 1.0f);
add_line(p0_world.xyz(), p1_world.xyz(), color);
add_line(p1_world.xyz(), p2_world.xyz(), color);
@@ -251,7 +257,8 @@ void VisualDebug::add_mesh_wireframe(const mat4& transform, uint32_t num_vertice
}
}
-void VisualDebug::add_line(const vec3& start, const vec3& end, const vec3& color) {
+void VisualDebug::add_line(const vec3& start, const vec3& end,
+ const vec3& color) {
lines_.push_back({start, end, color});
}
@@ -262,7 +269,8 @@ void VisualDebug::add_cross(const vec3& center, float size, const vec3& color) {
add_line(center - vec3(0, 0, s), center + vec3(0, 0, s), color);
}
-void VisualDebug::add_sphere(const vec3& center, float radius, const vec3& color) {
+void VisualDebug::add_sphere(const vec3& center, float radius,
+ const vec3& color) {
const int kSegments = 16;
const float kStep = 6.2831853f / kSegments;
@@ -272,14 +280,14 @@ void VisualDebug::add_sphere(const vec3& center, float radius, const vec3& color
float a2 = (i + 1) * kStep;
vec3 p1 = center;
vec3 p2 = center;
-
+
// axis mapping: 0=x, 1=y, 2=z
p1[axis1] += std::cos(a1) * radius;
p1[axis2] += std::sin(a1) * radius;
-
+
p2[axis1] += std::cos(a2) * radius;
p2[axis2] += std::sin(a2) * radius;
-
+
add_line(p1, p2, color);
}
};
@@ -289,30 +297,31 @@ void VisualDebug::add_sphere(const vec3& center, float radius, const vec3& color
draw_circle(1, 2); // YZ
}
-void VisualDebug::add_cone(const vec3& apex, const vec3& dir, float height, float radius, const vec3& color) {
+void VisualDebug::add_cone(const vec3& apex, const vec3& dir, float height,
+ float radius, const vec3& color) {
vec3 d = dir.normalize();
vec3 base_center = apex + d * height;
-
+
// Rotation to align (0, 1, 0) with d
quat q = quat::from_to(vec3(0, 1, 0), d);
-
+
const int kSegments = 16;
const float kStep = 6.2831853f / kSegments;
-
+
for (int i = 0; i < kSegments; ++i) {
float a1 = i * kStep;
float a2 = (i + 1) * kStep;
-
+
// Circle points in XZ plane (local space, y=0)
vec3 p1_local(std::cos(a1) * radius, 0, std::sin(a1) * radius);
vec3 p2_local(std::cos(a2) * radius, 0, std::sin(a2) * radius);
-
+
// Rotate and translate to base_center
vec3 p1 = base_center + q.rotate(p1_local);
vec3 p2 = base_center + q.rotate(p2_local);
-
+
add_line(p1, p2, color); // Base circle
-
+
// Connect to apex (draw every 4th segment to avoid clutter)
if (i % 4 == 0) {
add_line(apex, p1, color);
@@ -320,8 +329,10 @@ void VisualDebug::add_cone(const vec3& apex, const vec3& dir, float height, floa
}
}
-void VisualDebug::add_trajectory(const std::vector<vec3>& points, const vec3& color) {
- if (points.size() < 2) return;
+void VisualDebug::add_trajectory(const std::vector<vec3>& points,
+ const vec3& color) {
+ if (points.size() < 2)
+ return;
for (size_t i = 0; i < points.size() - 1; ++i) {
add_line(points[i], points[i + 1], color);
}
diff --git a/src/3d/visual_debug.h b/src/3d/visual_debug.h
index c8069e1..a60ec1c 100644
--- a/src/3d/visual_debug.h
+++ b/src/3d/visual_debug.h
@@ -6,10 +6,10 @@
#if !defined(STRIP_ALL)
+#include "3d/object.h"
#include "gpu/gpu.h"
-#include "util/mini_math.h"
#include "util/asset_manager_utils.h"
-#include "3d/object.h"
+#include "util/mini_math.h"
#include <vector>
struct DebugLine {
@@ -29,7 +29,8 @@ class VisualDebug {
void add_aabb(const vec3& min, const vec3& max, const vec3& color);
- void add_mesh_normals(const mat4& transform, uint32_t num_vertices, const MeshVertex* vertices);
+ void add_mesh_normals(const mat4& transform, uint32_t num_vertices,
+ const MeshVertex* vertices);
void add_mesh_wireframe(const mat4& transform, uint32_t num_vertices,
const MeshVertex* vertices, uint32_t num_indices,
const uint32_t* indices, const vec3& color);
@@ -37,7 +38,8 @@ class VisualDebug {
void add_line(const vec3& start, const vec3& end, const vec3& color);
void add_cross(const vec3& center, float size, const vec3& color);
void add_sphere(const vec3& center, float radius, const vec3& color);
- void add_cone(const vec3& apex, const vec3& dir, float height, float radius, const vec3& color);
+ void add_cone(const vec3& apex, const vec3& dir, float height, float radius,
+ const vec3& color);
void add_trajectory(const std::vector<vec3>& points, const vec3& color);
// Render all queued primitives and clear the queue