summaryrefslogtreecommitdiff
path: root/src/tests/test_mesh.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/tests/test_mesh.cc')
-rw-r--r--src/tests/test_mesh.cc336
1 files changed, 210 insertions, 126 deletions
diff --git a/src/tests/test_mesh.cc b/src/tests/test_mesh.cc
index 7f898c4..0865f80 100644
--- a/src/tests/test_mesh.cc
+++ b/src/tests/test_mesh.cc
@@ -8,9 +8,8 @@
#include "gpu/effects/shaders.h"
#include "gpu/texture_manager.h"
#include "platform/platform.h"
-#include "util/asset_manager_utils.h"
-#include <webgpu.h>
#include "procedural/generator.h"
+#include "util/asset_manager_utils.h"
#include <algorithm>
#include <cmath>
#include <cstdio>
@@ -18,6 +17,7 @@
#include <fstream>
#include <map>
#include <vector>
+#include <webgpu.h>
// Global State
static Renderer3D g_renderer;
@@ -41,18 +41,20 @@ void on_adapter_request_ended(WGPURequestAdapterStatus status,
if (status == WGPURequestAdapterStatus_Success) {
*(WGPUAdapter*)userdata = adapter;
} else {
- fprintf(stderr, "Failed to request adapter.\n"); // Avoid WGPUStringView::s issues
+ fprintf(stderr,
+ "Failed to request adapter.\n"); // Avoid WGPUStringView::s issues
}
}
-void on_device_request_ended(WGPURequestDeviceStatus status,
- WGPUDevice device, WGPUStringView message,
- void* userdata, void* user2) {
+void on_device_request_ended(WGPURequestDeviceStatus status, WGPUDevice device,
+ WGPUStringView message, void* userdata,
+ void* user2) {
(void)user2;
if (status == WGPURequestDeviceStatus_Success) {
*(WGPUDevice*)userdata = device;
} else {
- fprintf(stderr, "Failed to request device.\n"); // Avoid WGPUStringView::s issues
+ fprintf(stderr,
+ "Failed to request device.\n"); // Avoid WGPUStringView::s issues
}
}
@@ -80,7 +82,7 @@ void init_wgpu(WGPUInstance instance, PlatformState* platform_state) {
adapter_callback_info.userdata1 = &g_adapter; // Corrected to userdata1
wgpuInstanceRequestAdapter(instance, &adapter_opts, adapter_callback_info);
-
+
// Busy-wait for adapter
while (!g_adapter) {
platform_wgpu_wait_any(instance);
@@ -92,7 +94,7 @@ void init_wgpu(WGPUInstance instance, PlatformState* platform_state) {
device_callback_info.mode = WGPUCallbackMode_WaitAnyOnly;
device_callback_info.callback = on_device_request_ended;
device_callback_info.userdata1 = &g_device; // Corrected to userdata1
-
+
wgpuAdapterRequestDevice(g_adapter, &device_desc, device_callback_info);
// Busy-wait for device
@@ -122,136 +124,196 @@ void init_wgpu(WGPUInstance instance, PlatformState* platform_state) {
struct Vec3 {
float x, y, z;
- Vec3 operator+(const Vec3& o) const { return {x + o.x, y + o.y, z + o.z}; }
- Vec3& operator+=(const Vec3& o) { x+=o.x; y+=o.y; z+=o.z; return *this; }
- Vec3 operator-(const Vec3& o) const { return {x - o.x, y - o.y, z - o.z}; }
- Vec3 operator*(float s) const { return {x * s, y * s, z * s}; }
+ Vec3 operator+(const Vec3& o) const {
+ return {x + o.x, y + o.y, z + o.z};
+ }
+ Vec3& operator+=(const Vec3& o) {
+ x += o.x;
+ y += o.y;
+ z += o.z;
+ return *this;
+ }
+ Vec3 operator-(const Vec3& o) const {
+ return {x - o.x, y - o.y, z - o.z};
+ }
+ Vec3 operator*(float s) const {
+ return {x * s, y * s, z * s};
+ }
static Vec3 cross(const Vec3& a, const Vec3& b) {
- return {a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x};
+ return {a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z,
+ a.x * b.y - a.y * b.x};
}
Vec3 normalize() const {
float len = std::sqrt(x * x + y * y + z * z);
- if (len > 1e-6f) return {x / len, y / len, z / len};
+ if (len > 1e-6f)
+ return {x / len, y / len, z / len};
return {0, 0, 0};
}
};
bool load_obj_and_create_buffers(const char* path, Object3D& out_obj) {
- std::ifstream obj_file(path);
- if (!obj_file.is_open()) {
- fprintf(stderr, "Error: Could not open mesh file: %s\n", path);
- return false;
- }
+ std::ifstream obj_file(path);
+ if (!obj_file.is_open()) {
+ fprintf(stderr, "Error: Could not open mesh file: %s\n", path);
+ return false;
+ }
- std::vector<float> v_pos, v_norm, v_uv;
- struct RawFace { int v[3], vt[3], vn[3]; };
- std::vector<RawFace> raw_faces;
- std::vector<MeshVertex> final_vertices;
- std::vector<uint32_t> final_indices;
- std::map<std::string, uint32_t> vertex_map;
+ std::vector<float> v_pos, v_norm, v_uv;
+ struct RawFace {
+ int v[3], vt[3], vn[3];
+ };
+ std::vector<RawFace> raw_faces;
+ std::vector<MeshVertex> final_vertices;
+ std::vector<uint32_t> final_indices;
+ std::map<std::string, uint32_t> vertex_map;
- std::string obj_line;
- while (std::getline(obj_file, obj_line)) {
- if (obj_line.compare(0, 2, "v ") == 0) {
- float x, y, z;
- sscanf(obj_line.c_str(), "v %f %f %f", &x, &y, &z);
- v_pos.insert(v_pos.end(), {x, y, z});
- } else if (obj_line.compare(0, 3, "vn ") == 0) {
- float x, y, z;
- sscanf(obj_line.c_str(), "vn %f %f %f", &x, &y, &z);
- v_norm.insert(v_norm.end(), {x, y, z});
- } else if (obj_line.compare(0, 3, "vt ") == 0) {
- float u, v;
- sscanf(obj_line.c_str(), "vt %f %f", &u, &v);
- v_uv.insert(v_uv.end(), {u, v});
- } else if (obj_line.compare(0, 2, "f ") == 0) {
- char s1[64], s2[64], s3[64];
- if (sscanf(obj_line.c_str(), "f %s %s %s", s1, s2, s3) == 3) {
- std::string parts[3] = {s1, s2, s3};
- RawFace face = {};
- for (int i = 0; i < 3; ++i) {
- // Handle v//vn format
- if (parts[i].find("//") != std::string::npos) {
- sscanf(parts[i].c_str(), "%d//%d", &face.v[i], &face.vn[i]);
- face.vt[i] = 0;
- } else {
- int res = sscanf(parts[i].c_str(), "%d/%d/%d", &face.v[i], &face.vt[i], &face.vn[i]);
- if (res == 2) face.vn[i] = 0;
- else if (res == 1) { face.vt[i] = 0; face.vn[i] = 0; }
- }
- }
- raw_faces.push_back(face);
+ std::string obj_line;
+ while (std::getline(obj_file, obj_line)) {
+ if (obj_line.compare(0, 2, "v ") == 0) {
+ float x, y, z;
+ sscanf(obj_line.c_str(), "v %f %f %f", &x, &y, &z);
+ v_pos.insert(v_pos.end(), {x, y, z});
+ } else if (obj_line.compare(0, 3, "vn ") == 0) {
+ float x, y, z;
+ sscanf(obj_line.c_str(), "vn %f %f %f", &x, &y, &z);
+ v_norm.insert(v_norm.end(), {x, y, z});
+ } else if (obj_line.compare(0, 3, "vt ") == 0) {
+ float u, v;
+ sscanf(obj_line.c_str(), "vt %f %f", &u, &v);
+ v_uv.insert(v_uv.end(), {u, v});
+ } else if (obj_line.compare(0, 2, "f ") == 0) {
+ char s1[64], s2[64], s3[64];
+ if (sscanf(obj_line.c_str(), "f %s %s %s", s1, s2, s3) == 3) {
+ std::string parts[3] = {s1, s2, s3};
+ RawFace face = {};
+ for (int i = 0; i < 3; ++i) {
+ // Handle v//vn format
+ if (parts[i].find("//") != std::string::npos) {
+ sscanf(parts[i].c_str(), "%d//%d", &face.v[i], &face.vn[i]);
+ face.vt[i] = 0;
+ } else {
+ int res = sscanf(parts[i].c_str(), "%d/%d/%d", &face.v[i],
+ &face.vt[i], &face.vn[i]);
+ if (res == 2)
+ face.vn[i] = 0;
+ else if (res == 1) {
+ face.vt[i] = 0;
+ face.vn[i] = 0;
}
+ }
}
+ raw_faces.push_back(face);
+ }
}
+ }
- if (v_norm.empty() && !v_pos.empty()) {
- std::vector<Vec3> temp_normals(v_pos.size() / 3, {0,0,0});
- for(auto& face : raw_faces) {
- int i0=face.v[0]-1, i1=face.v[1]-1, i2=face.v[2]-1;
- Vec3 p0={v_pos[i0*3],v_pos[i0*3+1],v_pos[i0*3+2]};
- Vec3 p1={v_pos[i1*3],v_pos[i1*3+1],v_pos[i1*3+2]};
- Vec3 p2={v_pos[i2*3],v_pos[i2*3+1],v_pos[i2*3+2]};
- Vec3 n = Vec3::cross(p1-p0, p2-p0).normalize();
- temp_normals[i0] += n; temp_normals[i1] += n; temp_normals[i2] += n;
+ if (v_norm.empty() && !v_pos.empty()) {
+ std::vector<Vec3> temp_normals(v_pos.size() / 3, {0, 0, 0});
+ for (auto& face : raw_faces) {
+ int i0 = face.v[0] - 1, i1 = face.v[1] - 1, i2 = face.v[2] - 1;
+ Vec3 p0 = {v_pos[i0 * 3], v_pos[i0 * 3 + 1], v_pos[i0 * 3 + 2]};
+ Vec3 p1 = {v_pos[i1 * 3], v_pos[i1 * 3 + 1], v_pos[i1 * 3 + 2]};
+ Vec3 p2 = {v_pos[i2 * 3], v_pos[i2 * 3 + 1], v_pos[i2 * 3 + 2]};
+ Vec3 n = Vec3::cross(p1 - p0, p2 - p0).normalize();
+ temp_normals[i0] += n;
+ temp_normals[i1] += n;
+ temp_normals[i2] += n;
+ }
+ for (const auto& n : temp_normals) {
+ Vec3 norm = n.normalize();
+ v_norm.insert(v_norm.end(), {norm.x, norm.y, norm.z});
+ }
+ for (auto& face : raw_faces) {
+ face.vn[0] = face.v[0];
+ face.vn[1] = face.v[1];
+ face.vn[2] = face.v[2];
+ }
+ }
+
+ for (const auto& face : raw_faces) {
+ for (int i = 0; i < 3; ++i) {
+ char key_buf[128];
+ snprintf(key_buf, sizeof(key_buf), "%d/%d/%d", face.v[i], face.vt[i],
+ face.vn[i]);
+ std::string key = key_buf;
+ if (vertex_map.find(key) == vertex_map.end()) {
+ vertex_map[key] = (uint32_t)final_vertices.size();
+ MeshVertex v = {};
+ if (face.v[i] > 0) {
+ v.p[0] = v_pos[(face.v[i] - 1) * 3];
+ v.p[1] = v_pos[(face.v[i] - 1) * 3 + 1];
+ v.p[2] = v_pos[(face.v[i] - 1) * 3 + 2];
}
- for(const auto& n : temp_normals) {
- Vec3 norm = n.normalize();
- v_norm.insert(v_norm.end(), {norm.x, norm.y, norm.z});
+ if (face.vn[i] > 0) {
+ v.n[0] = v_norm[(face.vn[i] - 1) * 3];
+ v.n[1] = v_norm[(face.vn[i] - 1) * 3 + 1];
+ v.n[2] = v_norm[(face.vn[i] - 1) * 3 + 2];
}
- for(auto& face : raw_faces) {
- face.vn[0]=face.v[0]; face.vn[1]=face.v[1]; face.vn[2]=face.v[2];
+ if (face.vt[i] > 0) {
+ v.u[0] = v_uv[(face.vt[i] - 1) * 2];
+ v.u[1] = v_uv[(face.vt[i] - 1) * 2 + 1];
}
+ final_vertices.push_back(v);
+ }
+ final_indices.push_back(vertex_map[key]);
}
+ }
- for (const auto& face : raw_faces) {
- for (int i=0; i<3; ++i) {
- char key_buf[128];
- snprintf(key_buf, sizeof(key_buf), "%d/%d/%d", face.v[i], face.vt[i], face.vn[i]);
- std::string key = key_buf;
- if (vertex_map.find(key) == vertex_map.end()) {
- vertex_map[key] = (uint32_t)final_vertices.size();
- MeshVertex v = {};
- if(face.v[i]>0) { v.p[0]=v_pos[(face.v[i]-1)*3]; v.p[1]=v_pos[(face.v[i]-1)*3+1]; v.p[2]=v_pos[(face.v[i]-1)*3+2]; }
- if(face.vn[i]>0) { v.n[0]=v_norm[(face.vn[i]-1)*3]; v.n[1]=v_norm[(face.vn[i]-1)*3+1]; v.n[2]=v_norm[(face.vn[i]-1)*3+2]; }
- if(face.vt[i]>0) { v.u[0]=v_uv[(face.vt[i]-1)*2]; v.u[1]=v_uv[(face.vt[i]-1)*2+1]; }
- final_vertices.push_back(v);
- }
- final_indices.push_back(vertex_map[key]);
- }
- }
+ if (final_vertices.empty())
+ return false;
- if (final_vertices.empty()) return false;
+ // Calculate AABB and center the mesh
+ float min_x = 1e10f, min_y = 1e10f, min_z = 1e10f;
+ float max_x = -1e10f, max_y = -1e10f, max_z = -1e10f;
+ for (const auto& v : final_vertices) {
+ min_x = std::min(min_x, v.p[0]);
+ min_y = std::min(min_y, v.p[1]);
+ min_z = std::min(min_z, v.p[2]);
+ max_x = std::max(max_x, v.p[0]);
+ max_y = std::max(max_y, v.p[1]);
+ max_z = std::max(max_z, v.p[2]);
+ }
+ float cx = (min_x + max_x) * 0.5f;
+ float cy = (min_y + max_y) * 0.5f;
+ float cz = (min_z + max_z) * 0.5f;
+ for (auto& v : final_vertices) {
+ v.p[0] -= cx;
+ v.p[1] -= cy;
+ v.p[2] -= cz;
+ }
+ out_obj.local_extent = vec3((max_x - min_x) * 0.5f, (max_y - min_y) * 0.5f,
+ (max_z - min_z) * 0.5f);
- // Calculate AABB and center the mesh
- float min_x = 1e10f, min_y = 1e10f, min_z = 1e10f;
- float max_x = -1e10f, max_y = -1e10f, max_z = -1e10f;
- for (const auto& v : final_vertices) {
- min_x = std::min(min_x, v.p[0]); min_y = std::min(min_y, v.p[1]); min_z = std::min(min_z, v.p[2]);
- max_x = std::max(max_x, v.p[0]); max_y = std::max(max_y, v.p[1]); max_z = std::max(max_z, v.p[2]);
- }
- float cx = (min_x + max_x) * 0.5f;
- float cy = (min_y + max_y) * 0.5f;
- float cz = (min_z + max_z) * 0.5f;
- for (auto& v : final_vertices) {
- v.p[0] -= cx; v.p[1] -= cy; v.p[2] -= cz;
- }
- out_obj.local_extent = vec3((max_x - min_x) * 0.5f, (max_y - min_y) * 0.5f, (max_z - min_z) * 0.5f);
-
- g_mesh_gpu_data.num_indices = final_indices.size();
- g_mesh_gpu_data.vertex_buffer = gpu_create_buffer(g_device, final_vertices.size() * sizeof(MeshVertex), WGPUBufferUsage_Vertex | WGPUBufferUsage_CopyDst, final_vertices.data()).buffer;
- g_mesh_gpu_data.index_buffer = gpu_create_buffer(g_device, final_indices.size() * sizeof(uint32_t), WGPUBufferUsage_Index | WGPUBufferUsage_CopyDst, final_indices.data()).buffer;
-
- out_obj.type = ObjectType::MESH;
- out_obj.user_data = new std::vector<MeshVertex>(final_vertices);
+ g_mesh_gpu_data.num_indices = final_indices.size();
+ g_mesh_gpu_data.vertex_buffer =
+ gpu_create_buffer(g_device, final_vertices.size() * sizeof(MeshVertex),
+ WGPUBufferUsage_Vertex | WGPUBufferUsage_CopyDst,
+ final_vertices.data())
+ .buffer;
+ g_mesh_gpu_data.index_buffer =
+ gpu_create_buffer(g_device, final_indices.size() * sizeof(uint32_t),
+ WGPUBufferUsage_Index | WGPUBufferUsage_CopyDst,
+ final_indices.data())
+ .buffer;
- // This test doesn't use the asset system, so we override the renderer's internal cache lookup
- // by manually setting the buffers on the renderer object. This is a HACK for this specific tool.
- g_renderer.override_mesh_buffers(&g_mesh_gpu_data);
+ struct MeshData {
+ std::vector<MeshVertex> vertices;
+ std::vector<uint32_t> indices;
+ };
+ MeshData* mesh_data = new MeshData();
+ mesh_data->vertices = final_vertices;
+ mesh_data->indices = final_indices;
- return true;
-}
+ out_obj.type = ObjectType::MESH;
+ out_obj.user_data = mesh_data;
+ // This test doesn't use the asset system, so we override the renderer's
+ // internal cache lookup by manually setting the buffers on the renderer
+ // object. This is a HACK for this specific tool.
+ g_renderer.override_mesh_buffers(&g_mesh_gpu_data);
+
+ return true;
+}
int main(int argc, char** argv) {
if (argc < 2) {
@@ -262,7 +324,7 @@ int main(int argc, char** argv) {
bool debug_mode = (argc > 2 && strcmp(argv[2], "--debug") == 0);
printf("Loading mesh: %s\n", obj_path);
-
+
PlatformState platform_state = platform_init(false, 1280, 720);
WGPUInstance instance = wgpuCreateInstance(nullptr);
@@ -279,7 +341,8 @@ int main(int argc, char** argv) {
g_textures.init(g_device, g_queue);
ProceduralTextureDef noise_def;
- noise_def.width=256; noise_def.height=256;
+ noise_def.width = 256;
+ noise_def.height = 256;
noise_def.gen_func = procedural::gen_noise;
noise_def.params = {1234.0f, 16.0f};
g_textures.create_procedural_texture("noise", noise_def);
@@ -294,13 +357,13 @@ int main(int argc, char** argv) {
Object3D mesh_obj;
if (!load_obj_and_create_buffers(obj_path, mesh_obj)) {
- printf("Failed to load or process OBJ file.\n");
- return 1;
+ printf("Failed to load or process OBJ file.\n");
+ return 1;
}
mesh_obj.color = vec4(1.0f, 0.7f, 0.2f, 1.0f);
mesh_obj.position = {0, 1.5, 0}; // Elevate a bit more
g_scene.add_object(mesh_obj);
-
+
g_camera.position = vec3(0, 3, 5);
g_camera.target = vec3(0, 1.5, 0);
@@ -309,32 +372,53 @@ int main(int argc, char** argv) {
float time = (float)platform_state.time;
g_camera.aspect_ratio = platform_state.aspect_ratio;
-
+
g_scene.objects[1].rotation = quat::from_axis({0.5f, 1.0f, 0.0f}, time);
#if !defined(STRIP_ALL)
if (debug_mode) {
- auto* vertices = (std::vector<MeshVertex>*)g_scene.objects[1].user_data;
- g_renderer.GetVisualDebug().add_mesh_normals(g_scene.objects[1].get_model_matrix(), (uint32_t)vertices->size(), vertices->data());
+ struct MeshData {
+ std::vector<MeshVertex> vertices;
+ std::vector<uint32_t> indices;
+ };
+ auto* data = (MeshData*)g_scene.objects[1].user_data;
+ VisualDebug& dbg = g_renderer.GetVisualDebug();
+ dbg.add_mesh_normals(g_scene.objects[1].get_model_matrix(),
+ (uint32_t)data->vertices.size(),
+ data->vertices.data());
+ dbg.add_mesh_wireframe(g_scene.objects[1].get_model_matrix(),
+ (uint32_t)data->vertices.size(),
+ data->vertices.data(),
+ (uint32_t)data->indices.size(),
+ data->indices.data(), vec3(0.0f, 1.0f, 1.0f));
}
#endif /* !defined(STRIP_ALL) */
WGPUSurfaceTexture surface_tex;
wgpuSurfaceGetCurrentTexture(g_surface, &surface_tex);
- if (surface_tex.status == WGPUSurfaceGetCurrentTextureStatus_SuccessOptimal) { // WGPUSurfaceGetCurrentTextureStatus_Success is 0
- WGPUTextureView view = wgpuTextureCreateView(surface_tex.texture, nullptr);
+ if (surface_tex.status ==
+ WGPUSurfaceGetCurrentTextureStatus_SuccessOptimal) { // WGPUSurfaceGetCurrentTextureStatus_Success
+ // is 0
+ WGPUTextureView view =
+ wgpuTextureCreateView(surface_tex.texture, nullptr);
g_renderer.render(g_scene, g_camera, time, view);
wgpuTextureViewRelease(view);
wgpuSurfacePresent(g_surface);
}
- wgpuTextureRelease(surface_tex.texture); // Release here, after present, outside the if block
+ wgpuTextureRelease(
+ surface_tex
+ .texture); // Release here, after present, outside the if block
}
#if !defined(STRIP_ALL)
Renderer3D::SetDebugEnabled(false); // Reset debug mode
#endif
- delete (std::vector<MeshVertex>*)g_scene.objects[1].user_data;
+ struct MeshData {
+ std::vector<MeshVertex> vertices;
+ std::vector<uint32_t> indices;
+ };
+ delete (MeshData*)g_scene.objects[1].user_data;
wgpuBufferRelease(g_mesh_gpu_data.vertex_buffer);
wgpuBufferRelease(g_mesh_gpu_data.index_buffer);