Wavefront .obj文件加载后输出随机值,代码错误定位求助
问题分析与修复方案
让我来帮你找出代码里的问题——你看到随机值的核心原因是指针传递错误和局部变量内存失效,另外还有一些容易忽略的细节问题,下面一步步拆解:
关键错误点
1. 局部数组的悬空指针问题
你在loadobj函数里定义了float verticesout[24];,这是一个栈上的局部数组。当函数执行完毕返回时,栈上的局部变量会被系统回收,内存变得无效。而你写的vertices = verticesout;只是修改了函数内部的vertices指针副本,完全没有影响到main函数里传入的vertices数组。后续main里访问这个数组时,读取的是未初始化的内存,自然就是随机值。
2. 指针参数的传递逻辑错误
C语言里参数传递是值传递,即使你传入的是数组名(会退化为指针),函数内部修改的也只是这个指针的副本,不会改变原数组的地址。你需要直接往传入的指针指向的内存空间里写入数据,而不是重新给指针赋值。
3. 其他细节问题
- 没有关闭打开的文件:
fopen后没有调用fclose(file),会导致文件资源泄漏。 fscanf格式字符串里的\n多余:fscanf会自动跳过空白字符(包括换行),加\n反而可能导致读取异常。- 缺少数组越界检查:如果模型的顶点数量超过24个float(8个顶点),会导致数组越界,引发未定义行为。
修正后的代码
修改后的obj.h
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<cglm/cglm.h> // 增加maxVertices参数,避免数组越界 int loadobj(const char* filename, float* vertices, float* normals, float* texturecoords, int maxVertices) { FILE* file = fopen(filename, "r"); char lineheader[128]; int res; int vertexCount = 0; vec3 vertex; if(file == NULL){ printf("Failed to open file!"); return 1; } while(1){ res = fscanf(file, "%s", lineheader); if(res == EOF){ break; } if(strcmp(lineheader, "v") == 0){ // 读取顶点数据,检查读取是否成功 if(fscanf(file, "%f %f %f", &vertex[0], &vertex[1], &vertex[2]) != 3) { printf("Error reading vertex data!\n"); fclose(file); return 1; } // 检查是否超出数组容量 if(vertexCount + 3 > maxVertices) { printf("Vertex buffer overflow! Increase buffer size.\n"); fclose(file); return 1; } // 直接写入传入的vertices数组 vertices[vertexCount] = vertex[0]; vertices[vertexCount + 1] = vertex[1]; vertices[vertexCount + 2] = vertex[2]; vertexCount += 3; } // 后续可以添加处理vn(法线)、vt(纹理坐标)、f(面)的逻辑 // 注意:当前代码仅读取原始顶点,未处理面索引,若模型用面存储,还需解析f指令重组顶点 } fclose(file); // 关闭文件,释放资源 return 0; }
修改后的main.c
#include<stdio.h> #include<stdlib.h> #include<cglm/cglm.h> #include"obj.h" int main(){ const int maxVertexElements = 24; // 对应8个顶点(每个顶点3个分量) float vertices[maxVertexElements]; float normals[24]; float texcoords[24]; int result = loadobj("model.obj", vertices, normals, texcoords, maxVertexElements); if(result != 0) { return 1; } // 格式化输出,每个顶点占一行,更易读 for(int i = 0; i < maxVertexElements; i++){ printf("%f ", vertices[i]); if((i + 1) % 3 == 0) { printf("\n"); } } printf("\n"); return 0; }
额外说明
当前修正后的代码仅读取了.obj文件里的原始顶点(v指令),如果你的模型是用**面索引(f指令)**存储的,还需要进一步解析f指令,根据索引把对应的顶点、法线、纹理坐标重新组织成渲染需要的连续顶点数据——这也是完整加载.obj文件的核心步骤,你可以后续补充这部分逻辑。
内容的提问来源于stack exchange,提问作者RadoslavL
相关产品推荐
相关产品推荐

