我对以下代码有疑问。它应该是一个简单的.obj
加载器,将数据存储在三个不同的数组中。数组被传递到函数中,但它们没有被修改。每次我使用该函数时,该行*out_vertices[index] = gl_vector3_make(0.0, 0.0, 0.0);
也会抛出一个EXC_BAD_ACCESS
,即使我预先分配了传入的数组并删除了函数本身中的所有相关分配代码。
对象IO.h
#ifndef ObjectIO_h
#define ObjectIO_h
union _vector2 {
struct {float x, y;};
struct {float s, t;};
float v[2];
};
typedef union _vector2 gl_vector2;
extern inline gl_vector2 gl_vector2_make(float x, float y);
union _vector3 {
struct {float x, y, z;};
struct {float s, t, p;};
struct {float r, g, b;};
float v[3];
};
typedef union _vector3 gl_vector3;
extern inline gl_vector3 gl_vector3_make(float x, float y, float z);
union _vector4 {
struct {float x, y, z, w;};
struct {float s, t, p, q;};
struct {float r, g, b, a;};
float v[4];
};
typedef union _vector4 gl_vector4;
extern inline gl_vector4 gl_vector4_make(float x, float y, float z, float w);
extern inline int loadOBJ(const char *path, gl_vector3 **out_vertices, gl_vector2 **out_uvs, gl_vector3 **out_normals);
#endif
对象IO.c:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ObjectIO.h"
extern inline gl_vector2 gl_vector2_make(float x, float y) {
gl_vector2 vector;
vector.x = x;
vector.y = y;
return vector;
}
extern inline gl_vector3 gl_vector3_make(float x, float y, float z) {
gl_vector3 vector;
vector.x = x;
vector.y = y;
vector.z = z;
return vector;
}
extern inline gl_vector4 gl_vector4_make(float x, float y, float z, float w) {
gl_vector4 vector;
vector.x = x;
vector.y = y;
vector.z = z;
vector.w = w;
return vector;
}
extern inline char** splitstring(char *inputstring, char *separator, size_t *lines) {
char **res = NULL;
char * p = strtok(inputstring, separator);
int n_spaces = 0, i;
while (p) {
n_spaces ++;
res = realloc(res, sizeof(char*) * n_spaces);
if (res == NULL)
exit (-1); /* memory allocation failed */
res[n_spaces - 1] = p;
p = strtok (NULL, separator);
}
res = realloc (res, sizeof (char*) * (n_spaces + 1));
res[n_spaces] = '\0';
/* print the result */
for (i = 0; i < (n_spaces); i ++) printf ("res[%d] = %s\n", i, res[i]);
/* free the memory allocated */
*lines = (n_spaces - 1);
free(res);
return res;
}
extern inline int loadOBJ(const char *path, gl_vector3 **out_vertices, gl_vector2 **out_uvs, gl_vector3 **out_normals) {
printf("Loading OBJ file %s...\n", path);
long filesize;
char *file_c;
char *linesep;
char **filecontents;
size_t filecontentsize, result, lines, index, faces;
float *normals = malloc(sizeof(float) * 3);
float *uvs = malloc(sizeof(float) * 2);
float *vertices = malloc(sizeof(float) * 3);
FILE* file = fopen(path, "r");
if (file == NULL) {
printf("File %s cannot be opened.\n", path);
fclose(file);
return 0;
}
fseek(file, 0, SEEK_END);
filesize = ftell(file);
fseek(file, 0, SEEK_SET);
filecontentsize = sizeof(char) * filesize;
file_c = malloc(filecontentsize);
result = fread(file_c, 1, filesize, file);
linesep = malloc(sizeof(char) * 2);
linesep[0] = '\n';
lines = 0;
index = 0;
faces = 0;
filecontents = splitstring(file_c, linesep, &lines);
fseek(file, 0, SEEK_SET);
while (index < lines) {
if (filecontents[index][0] == 'v') {
if (filecontents[index][1] == 'n') {
normals = realloc(normals, (sizeof(float) * 3));
fscanf(file, "vn %f %f %f\n", &normals[(index * 3) + 0], &normals[(index * 3) + 1], &normals[(index * 3) + 2]);
}
else {
if (filecontents[index][1] == 't') {
uvs = realloc(uvs, (sizeof(float) * 2));
fscanf(file, "vt %f %f\n", &uvs[(index * 3) + 0], &uvs[(index * 3) + 1]);
}
else {
vertices = realloc(vertices, (sizeof(float) * 3));
fscanf(file, "v %f %f %f\n", &vertices[(index * 3) + 0], &vertices[(index * 3) + 1], &vertices[(index * 3) + 2]);
}
}
}
if (filecontents[index][0] == 'f') {
faces ++;
}
index ++;
}
*out_vertices = malloc(sizeof(gl_vector3) * faces * 3);
*out_uvs = malloc(sizeof(gl_vector2) * faces * 2);
*out_normals = malloc(sizeof(gl_vector3) * faces * 3);
index = 0;
while (index <= lines) {
*out_normals[index] = gl_vector3_make(0.0, 0.0, 0.0);
*out_uvs[index] = gl_vector2_make(0.0, 0.0);
*out_vertices[index] = gl_vector3_make(0.0, 0.0, 0.0);
printf("%lu\n", index);
index ++;
}
fclose(file);
return 1;
}
该函数在这里调用:
gl_vector3 *normals;
gl_vector2 *uvs;
gl_vector3 *vertices;
loadOBJ("/Users/justin/Downloads/OpenGL-tutorial_v0010_21/tutorial16_shadowmaps/room.obj", &vertices, &uvs, &normals);
printf("%f, %f, %f\n", vertices[0].x, vertices[0].y, vertices[0].z);