#include "mesh.h" #include #include #include #include #ifndef MATH_ASM_AVAILABLE #include "../ASM/math_c_fallback.h" #endif #define POS(n,x,y,z,nx,ny,nz,u,v,r,g,b,a) {x,y,z, nx,ny,nz, u,v, r,g,b,a} static Mesh* create_mesh(ID3D11Device* dev, const void* verts, uint32_t vc, const uint32_t* idx, uint32_t ic, uint32_t stride) { Mesh* m = (Mesh*)calloc(1, sizeof(Mesh)); m->stride = stride; m->vcount = vc; m->icount = ic; D3D11_BUFFER_DESC bd = {0}; D3D11_SUBRESOURCE_DATA sd = {0}; bd.ByteWidth = stride * vc; bd.Usage = D3D11_USAGE_DEFAULT; bd.BindFlags = D3D11_BIND_VERTEX_BUFFER; sd.pSysMem = verts; dev->lpVtbl->CreateBuffer(dev, &bd, &sd, &m->vb); if (idx && ic > 0) { bd.ByteWidth = sizeof(uint32_t) * ic; bd.BindFlags = D3D11_BIND_INDEX_BUFFER; sd.pSysMem = idx; dev->lpVtbl->CreateBuffer(dev, &bd, &sd, &m->ib); } return m; } void mesh_destroy(Mesh* m) { if (!m) return; if (m->ib) m->ib->lpVtbl->Release(m->ib); if (m->vb) m->vb->lpVtbl->Release(m->vb); free(m); } void mesh_draw(Mesh* m, ID3D11DeviceContext* ctx) { UINT stride = m->stride, offset = 0; ctx->lpVtbl->IASetVertexBuffers(ctx, 0, 1, &m->vb, &stride, &offset); if (m->ib) { ctx->lpVtbl->IASetIndexBuffer(ctx, m->ib, DXGI_FORMAT_R32_UINT, 0); ctx->lpVtbl->DrawIndexed(ctx, m->icount, 0, 0); } else { ctx->lpVtbl->Draw(ctx, m->vcount, 0); } } Mesh* mesh_create_cube(ID3D11Device* dev) { typedef struct { float p[3], n[3], uv[2], c[4]; } V; V v[24] = { POS(0,-.5f,-.5f,-.5f, 0,0,-1, 0,1, 1,1,1,1), POS(1, .5f,-.5f,-.5f, 0,0,-1, 1,1, 1,1,1,1), POS(2, .5f, .5f,-.5f, 0,0,-1, 1,0, 1,1,1,1), POS(3,-.5f, .5f,-.5f, 0,0,-1, 0,0, 1,1,1,1), POS(4, .5f,-.5f, .5f, 0,0, 1, 0,1, 1,1,1,1), POS(5,-.5f,-.5f, .5f, 0,0, 1, 1,1, 1,1,1,1), POS(6,-.5f, .5f, .5f, 0,0, 1, 1,0, 1,1,1,1), POS(7, .5f, .5f, .5f, 0,0, 1, 0,0, 1,1,1,1), POS(8,-.5f, .5f,-.5f, 0,1, 0, 0,1, 1,1,1,1), POS(9, .5f, .5f,-.5f, 0,1, 0, 1,1, 1,1,1,1), POS(10,.5f, .5f, .5f, 0,1, 0, 1,0, 1,1,1,1), POS(11,-.5f, .5f, .5f, 0,1, 0, 0,0, 1,1,1,1), POS(12,-.5f,-.5f, .5f, 0,-1,0, 0,1, 1,1,1,1), POS(13,.5f,-.5f, .5f, 0,-1,0, 1,1, 1,1,1,1), POS(14,.5f,-.5f,-.5f, 0,-1,0, 1,0, 1,1,1,1), POS(15,-.5f,-.5f,-.5f, 0,-1,0, 0,0, 1,1,1,1), POS(16,.5f,-.5f,-.5f, 1,0, 0, 0,1, 1,1,1,1), POS(17,.5f,-.5f, .5f, 1,0, 0, 1,1, 1,1,1,1), POS(18,.5f, .5f, .5f, 1,0, 0, 1,0, 1,1,1,1), POS(19,.5f, .5f,-.5f, 1,0, 0, 0,0, 1,1,1,1), POS(20,-.5f,-.5f, .5f, -1,0,0, 0,1, 1,1,1,1), POS(21,-.5f,-.5f,-.5f, -1,0,0, 1,1, 1,1,1,1), POS(22,-.5f, .5f,-.5f, -1,0,0, 1,0, 1,1,1,1), POS(23,-.5f, .5f, .5f, -1,0,0, 0,0, 1,1,1,1), }; uint32_t idx[36]; for (int i = 0; i < 6; i++) { int b = i*4; idx[i*6]=b; idx[i*6+1]=b+1; idx[i*6+2]=b+2; idx[i*6+3]=b; idx[i*6+4]=b+2; idx[i*6+5]=b+3; } return create_mesh(dev, v, 24, idx, 36, sizeof(V)); } Mesh* mesh_create_plane(ID3D11Device* dev, float size) { typedef struct { float p[3], n[3], uv[2], c[4]; } V; float h = size * 0.5f; V v[4] = { {{-h,0,h},{0,1,0},{0,1},{1,1,1,1}}, {{ h,0,h},{0,1,0},{1,1},{1,1,1,1}}, {{ h,0,-h},{0,1,0},{1,0},{1,1,1,1}}, {{-h,0,-h},{0,1,0},{0,0},{1,1,1,1}}, }; uint32_t idx[6] = {0,1,2,0,2,3}; return create_mesh(dev, v, 4, idx, 6, sizeof(V)); } Mesh* mesh_create_sphere(ID3D11Device* dev, float r, int seg) { typedef struct { float p[3], n[3], uv[2], c[4]; } V; int vc = (seg+1)*(seg+1); V* v = (V*)malloc(vc * sizeof(V)); int vi = 0; for (int lat = 0; lat <= seg; lat++) { float theta = 3.14159265f * lat / seg; float st = sinf(theta), ct = cosf(theta); for (int lon = 0; lon <= seg; lon++) { float phi = 2.0f * 3.14159265f * lon / seg; float sp = sinf(phi), cp = cosf(phi); float nx = cp*st, ny = ct, nz = sp*st; v[vi].p[0] = nx*r; v[vi].p[1] = ny*r; v[vi].p[2] = nz*r; v[vi].n[0] = nx; v[vi].n[1] = ny; v[vi].n[2] = nz; v[vi].uv[0] = (float)lon/seg; v[vi].uv[1] = (float)lat/seg; v[vi].c[0]=1; v[vi].c[1]=1; v[vi].c[2]=1; v[vi].c[3]=1; vi++; } } int ic = seg*seg*6; uint32_t* idx = (uint32_t*)malloc(ic * sizeof(uint32_t)); int ii = 0; for (int lat = 0; lat < seg; lat++) { for (int lon = 0; lon < seg; lon++) { uint32_t f = lat*(seg+1)+lon, s = f+seg+1; idx[ii++]=f; idx[ii++]=s; idx[ii++]=f+1; idx[ii++]=s; idx[ii++]=s+1; idx[ii++]=f+1; } } Mesh* m = create_mesh(dev, v, vc, idx, ic, sizeof(V)); 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; }