数据结构
struct vertex_t {
float p[3];
float n[3];
float t[2];
};
struct mesh_t {
vertex_t *vertices;
unsigned short *indices;
unsigned int vertexCnt, indexCnt;
mesh_t(unsigned int vertex_count, unsigned int index_cnt);
~mesh_t();
};
mesh_t::mesh_t(unsigned int vertex_count, unsigned int index_count)
:vertexCnt(vertex_count), indexCnt(index_count)
{
vertices = new vertex_t[vertex_count];
indices = new unsigned short[index_count];
}
mesh_t::~mesh_t()
{
delete[] vertices;
delete[] indices;
}
读取并优化
int RepeatCheck(float *position, float *normal, float *texCoord, int index,
float p0, float p1, float p2, float n0, float n1, float n2, float t0, float t1)
{
int repeatIndex = 0;
for (int i = 0; i < index; i++) {
if (fabs(p0 - position[i * 3 + 0]) < 0.0001f &&
fabs(p1 - position[i * 3 + 1]) < 0.0001f &&
fabs(p2 - position[i * 3 + 2]) < 0.0001f &&
fabs(n0 - normal[i * 3 + 0]) < 0.0001f &&
fabs(n1 - normal[i * 3 + 1]) < 0.0001f &&
fabs(n2 - normal[i * 3 + 2]) < 0.0001f &&
fabs(t0 - texCoord[i * 2 + 0]) < 0.0001f &&
fabs(t1 - texCoord[i * 2 + 1]) < 0.0001f)
{
repeatIndex = i + 1;
break;
}
}
return repeatIndex;
}
int loadSimpleObjFile(const char *filename, mesh_t **mesh)
{
FILE *file;
fopen_s(&file, filename, "rt");
if (!file) return 0;
char line[1024];
// 第一次遍历文件,统计数量
int np = 0, nn = 0, nt = 0, nf = 0;
while (!feof(file))
{
fgets(line, 1024, file);
if (line[0] == '#') continue;
if (line[0] == 'v')
{
if (line[1] == ' ') { np++; continue; }
if (line[1] == 'n') { nn++; continue; }
if (line[1] == 't') { nt++; continue; }
}
if (line[0] == 'f') { nf++; continue; }
}
float *position = new float[np * 3];
float *normal = new float[nn * 3];
float *texCoord = new float[nt * 2];
int *index_p = new int[nf * 3];
int *index_n = new int[nf * 3];
int *index_t = new int[nf * 3];
fseek(file, 0, SEEK_SET);
unsigned int cp = 0, cn = 0, ct = 0, cf = 0;
// 第二次遍历文件,存储数据
while (!feof(file))
{
fgets(line, 1024, file);
if (line[0] == '#') continue;
if (line[0] == 'v')
{
if (line[1] == ' ') { char *e1, *e2; position[cp + 0] = (float)strtod(line + 2, &e1); position[cp + 1] = (float)strtod(e1, &e2); position[cp + 2] = (float)strtod(e2, 0); cp += 3; continue; }
if (line[1] == 'n') { char *e1, *e2; normal[cn + 0] = (float)strtod(line + 3, &e1); normal[cn + 1] = (float)strtod(e1, &e2); normal[cn + 2] = (float)strtod(e2, 0); cn += 3; continue; }
if (line[1] == 't') { char *e1; texCoord[ct + 0] = (float)strtod(line + 3, &e1); texCoord[ct + 1] = (float)strtod(e1, 0); ct += 2; continue; }
}
if (line[0] == 'f')
{
char *e1, *e2, *e3 = line + 1;
for (int i = 0; i < 3; i++)
{
index_p[cf + i] = (int)strtoul(e3 + 1, &e1, 10) - 1; // obj文件面的索引从 1 开始,转换成数组的索引需要减 1
index_t[cf + i] = (int)strtoul(e1 + 1, &e2, 10) - 1;
index_n[cf + i] = (int)strtoul(e2 + 1, &e3, 10) - 1;
}
cf += 3;
continue;
}
}
fclose(file);
float *optimize_p = new float[nf*3*3];
float *optimize_n = new float[nf*3*3];
float *optimize_t = new float[nf*3*2];
int *indices = new int[nf * 3];
// 优化数据
int idx = 0, optimizeIdx = 0;
for (int i = 0; i < nf * 3; i++) {
int pi = index_p[i];
int ni = index_n[i];
int ti = index_t[i];
float p0 = position[pi * 3 + 0];
float p1 = position[pi * 3 + 1];
float p2 = position[pi * 3 + 2];
float n0 = normal[ni * 3 + 0];
float n1 = normal[ni * 3 + 1];
float n2 = normal[ni * 3 + 2];
float t0 = texCoord[ti * 2 + 0];
float t1 = texCoord[ti * 2 + 1];
int repeatIndex = RepeatCheck(optimize_p, optimize_n, optimize_t, idx, p0, p1, p2, n0, n1, n2, t0, t1);
if (0 == repeatIndex) {
optimize_p[optimizeIdx * 3 + 0] = p0;
optimize_p[optimizeIdx * 3 + 1] = p1;
optimize_p[optimizeIdx * 3 + 2] = p2;
optimize_n[optimizeIdx * 3 + 0] = n0;
optimize_n[optimizeIdx * 3 + 1] = n1;
optimize_n[optimizeIdx * 3 + 2] = n2;
optimize_t[optimizeIdx * 2 + 0] = t0;
optimize_t[optimizeIdx * 2 + 1] = t1;
indices[idx] = optimizeIdx;
optimizeIdx++;
}
else {
indices[idx] = repeatIndex - 1;
}
idx++;
}
delete[] position;
delete[] normal;
delete[] texCoord;
delete[] index_p;
delete[] index_n;
delete[] index_t;
// 填充mesh
*mesh = new mesh_t(optimizeIdx, idx);
for (int i = 0; i < idx; i++) {
(*mesh)->indices[i] = (unsigned short)indices[i];
}
for (int i = 0; i < optimizeIdx; i++) {
((*mesh)->vertices + i)->p[0] = optimize_p[i * 3 + 0];
((*mesh)->vertices + i)->p[1] = optimize_p[i * 3 + 1];
((*mesh)->vertices + i)->p[2] = optimize_p[i * 3 + 2];
((*mesh)->vertices + i)->n[0] = optimize_n[i * 3 + 0];
((*mesh)->vertices + i)->n[1] = optimize_n[i * 3 + 1];
((*mesh)->vertices + i)->n[2] = optimize_n[i * 3 + 2];
((*mesh)->vertices + i)->t[0] = optimize_t[i * 2 + 0];
((*mesh)->vertices + i)->t[1] = optimize_t[i * 2 + 1];
}
delete[] optimize_p;
delete[] optimize_n;
delete[] optimize_t;
delete[] indices;
return 1;
}