读取3DMax的.obj文件,并优化顶点数据

数据结构

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;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值