diff --git a/Engine/Rendering/mesh.c b/Engine/Rendering/mesh.c index 36177a0..1502f4b 100644 --- a/Engine/Rendering/mesh.c +++ b/Engine/Rendering/mesh.c @@ -1,5 +1,7 @@ #include "mesh.h" #include +#include +#include #include #ifndef MATH_ASM_AVAILABLE #include "../ASM/math_c_fallback.h" @@ -108,3 +110,99 @@ Mesh* mesh_create_sphere(ID3D11Device* dev, float r, int seg) { free(v); free(idx); return m; } + +// OBJ 加载器 +Mesh* mesh_load_obj(ID3D11Device* dev, const char* path) { + FILE* f = fopen(path, "r"); + if (!f) return NULL; + + // 先统计顶点和面数 + int max_v = 4096, max_f = 8192; + float* verts = (float*)malloc(max_v * 3 * sizeof(float)); + float* uvs = (float*)malloc(max_v * 2 * sizeof(float)); + int vert_count = 0, uv_count = 0; + int* face_idx = (int*)malloc(max_f * 3 * sizeof(int)); + int face_count = 0; + + char line[256]; + while (fgets(line, sizeof(line), f)) { + if (line[0] == 'v' && line[1] == ' ') { + float x, y, z; + if (sscanf(line + 2, "%f %f %f", &x, &y, &z) == 3 && vert_count < max_v) { + verts[vert_count * 3] = x; + verts[vert_count * 3 + 1] = y; + verts[vert_count * 3 + 2] = z; + vert_count++; + } + } else if (line[0] == 'v' && line[1] == 't') { + float u, v; + if (sscanf(line + 3, "%f %f", &u, &v) == 2 && uv_count < max_v) { + uvs[uv_count * 2] = u; + uvs[uv_count * 2 + 1] = v; + uv_count++; + } + } else if (line[0] == 'f' && line[1] == ' ') { + // 解析面: f v/vt v/vt v/vt 或 f v v v + int v0, v1, v2; + char* p = line + 2; + v0 = atoi(p) - 1; while (*p && *p != ' ') p++; p++; + v1 = atoi(p) - 1; while (*p && *p != ' ') p++; p++; + v2 = atoi(p) - 1; + if (v0 >= 0 && v1 >= 0 && v2 >= 0 && face_count < max_f) { + face_idx[face_count * 3] = v0; + face_idx[face_count * 3 + 1] = v1; + face_idx[face_count * 3 + 2] = v2; + face_count++; + } + } + } + fclose(f); + + if (vert_count == 0 || face_count == 0) { + free(verts); free(uvs); free(face_idx); + return NULL; + } + + // 构建去重顶点 (简单方案: 每个面一个顶点) + int out_vcount = face_count * 3; + Vertex* out_verts = (Vertex*)calloc(out_vcount, sizeof(Vertex)); + uint32_t* out_idx = (uint32_t*)malloc(face_count * 3 * sizeof(uint32_t)); + + for (int i = 0; i < face_count; i++) { + for (int j = 0; j < 3; j++) { + int vi = face_idx[i * 3 + j]; + int oi = i * 3 + j; + if (vi < vert_count) { + out_verts[oi].pos[0] = verts[vi * 3]; + out_verts[oi].pos[1] = verts[vi * 3 + 1]; + out_verts[oi].pos[2] = verts[vi * 3 + 2]; + } + out_verts[oi].color[0] = out_verts[oi].color[1] = out_verts[oi].color[2] = 1.0f; + out_verts[oi].color[3] = 1.0f; + out_idx[oi] = oi; + } + } + + // 简单法线计算 (面法线) + for (int i = 0; i < face_count; i++) { + float* p0 = out_verts[i * 3].pos; + float* p1 = out_verts[i * 3 + 1].pos; + float* p2 = out_verts[i * 3 + 2].pos; + float e1[3] = {p1[0] - p0[0], p1[1] - p0[1], p1[2] - p0[2]}; + float e2[3] = {p2[0] - p0[0], p2[1] - p0[1], p2[2] - p0[2]}; + float nx = e1[1]*e2[2] - e1[2]*e2[1]; + float ny = e1[2]*e2[0] - e1[0]*e2[2]; + float nz = e1[0]*e2[1] - e1[1]*e2[0]; + float nl = sqrtf(nx*nx + ny*ny + nz*nz); + if (nl > 0.0001f) { nx /= nl; ny /= nl; nz /= nl; } + for (int j = 0; j < 3; j++) { + out_verts[i * 3 + j].norm[0] = nx; + out_verts[i * 3 + j].norm[1] = ny; + out_verts[i * 3 + j].norm[2] = nz; + } + } + + Mesh* m = create_mesh(dev, out_verts, out_vcount, out_idx, face_count * 3, sizeof(Vertex)); + free(out_verts); free(out_idx); free(verts); free(uvs); free(face_idx); + return m; +} diff --git a/Engine/Rendering/mesh.h b/Engine/Rendering/mesh.h index 202ddef..1dfc41a 100644 --- a/Engine/Rendering/mesh.h +++ b/Engine/Rendering/mesh.h @@ -20,5 +20,6 @@ typedef struct { Mesh* mesh_create_cube(ID3D11Device* dev); Mesh* mesh_create_plane(ID3D11Device* dev, float size); Mesh* mesh_create_sphere(ID3D11Device* dev, float r, int seg); +Mesh* mesh_load_obj(ID3D11Device* dev, const char* path); void mesh_destroy(Mesh* m); void mesh_draw(Mesh* m, ID3D11DeviceContext* ctx);