gpt4 book ai didi

c++ - 如何将一个简单的 .obj 文件解析为三角形?

转载 作者:行者123 更新时间:2023-11-28 04:31:15 34 4
gpt4 key购买 nike

我正在尝试实现一个光线转换器,我从简单的 .obj 文件 (utah-teapot) 开始,目前我只为球体和三角形制作类,我基本上拥有交叉点的所有功能,生成查看光线等。都准备好了,但我似乎无法将 .obj 文件解析为三角形(每个三个 vector ),因此我可以在自定义 .obj 文件上进行光线转换,而不仅仅是球体。

这是我当前的 .obj 文件解析器(此处未包含完整的工作代码)

char lineHeader[512];
// read the first word of the line
int res = fscanf(file, "%s", lineHeader);
if (res == EOF)
break; // EOF

// else : parse lineHeader

if (strcmp(lineHeader, "v") == 0) {
glm::vec3 vertex;
fscanf(file, "%f %f %f\n", &vertex.x, &vertex.y, &vertex.z);
vertex.x *= scale;
vertex.y *= scale;
vertex.z *= scale;
temp_vertices.push_back(vertex);
}
else if (strcmp(lineHeader, "vt") == 0) {
glm::vec2 uv;
fscanf(file, "%f %f\n", &uv.x, &uv.y);
uv.y = -uv.y; // Invert V coordinate since we will only use DDS texture, which are inverted. Remove if you want to use TGA or BMP loaders.
temp_uvs.push_back(uv);
}
else if (strcmp(lineHeader, "vn") == 0) {
glm::vec3 normal;
fscanf(file, "%f %f %f\n", &normal.x, &normal.y, &normal.z);
temp_normals.push_back(normal);
}
else if (strcmp(lineHeader, "f") == 0) {
std::string vertex1, vertex2, vertex3;
unsigned int vertexIndex[3] = { 0 }, uvIndex[3] = { 0 }, normalIndex[3] = { 0 };
char stupidBuffer[1024];
fgets(stupidBuffer, 1024, file);
int matches = sscanf(stupidBuffer, "%d/%d/%d %d/%d/%d %d/%d/%d\n", &vertexIndex[0], &uvIndex[0], &normalIndex[0], &vertexIndex[1], &uvIndex[1], &normalIndex[1], &vertexIndex[2], &uvIndex[2], &normalIndex[2]);
if (matches != 9) {
vertexIndex[3] = { 0 }, uvIndex[3] = { 0 }, normalIndex[3] = { 0 };
matches = sscanf(stupidBuffer, "%d//%d %d//%d %d//%d\n", &vertexIndex[0], &normalIndex[0], &vertexIndex[1], &normalIndex[1], &vertexIndex[2], &normalIndex[2]);
if (matches != 6) {
vertexIndex[3] = { 0 }, uvIndex[3] = { 0 }, normalIndex[3] = { 0 };
matches = sscanf(stupidBuffer, "%d %d %d\n", &vertexIndex[0], &vertexIndex[1], &vertexIndex[2]);
if (matches != 3) {
printf("File can't be read \n");
fclose(file);
return false;
}
}
}
}

这是我的三角形类

class Triangle {
public:
Vector p0, p1, p2;
Vector color;
Vector normal(void);
};

我不知道如何将 .obj 文件中的信息解析为由三个 3d vector (点)组成的三角形。我不需要代码,我只需要了解如何(如果可能的话?)将所有信息解析为三角形。欢迎任何其他想法。从长远来看,我想制作一款简单的益智游戏,但我只是一步一个脚印。

最佳答案

您已完成 90%。在您的面部元素解析器中,使用每个面部顶点的已解析位置/法线/纹理坐标索引从 temp_* vector 中获取信息。如果一个面元素有三个顶点,你可以按原样发射一个三角形,否则对于 4 个以上的顶点,我通常假设生成的多边形是凸的和共面的,在这种情况下你可以 triangulate by pretending it's a triangle fan .

一起:

struct Vertex
{
glm::vec3 position;
glm::vec2 texcoord;
glm::vec3 normal;
};

struct VertRef
{
VertRef( int v, int vt, int vn ) : v(v), vt(vt), vn(vn) { }
int v, vt, vn;
};

std::vector< Vertex > LoadOBJ( std::istream& in )
{
std::vector< Vertex > verts;

std::vector< glm::vec4 > positions( 1, glm::vec4( 0, 0, 0, 0 ) );
std::vector< glm::vec3 > texcoords( 1, glm::vec3( 0, 0, 0 ) );
std::vector< glm::vec3 > normals( 1, glm::vec3( 0, 0, 0 ) );
std::string lineStr;
while( std::getline( in, lineStr ) )
{
std::istringstream lineSS( lineStr );
std::string lineType;
lineSS >> lineType;

// vertex
if( lineType == "v" )
{
float x = 0, y = 0, z = 0, w = 1;
lineSS >> x >> y >> z >> w;
positions.push_back( glm::vec4( x, y, z, w ) );
}

// texture
if( lineType == "vt" )
{
float u = 0, v = 0, w = 0;
lineSS >> u >> v >> w;
texcoords.push_back( glm::vec3( u, v, w ) );
}

// normal
if( lineType == "vn" )
{
float i = 0, j = 0, k = 0;
lineSS >> i >> j >> k;
normals.push_back( glm::normalize( glm::vec3( i, j, k ) ) );
}

// polygon
if( lineType == "f" )
{
std::vector< VertRef > refs;
std::string refStr;
while( lineSS >> refStr )
{
std::istringstream ref( refStr );
std::string vStr, vtStr, vnStr;
std::getline( ref, vStr, '/' );
std::getline( ref, vtStr, '/' );
std::getline( ref, vnStr, '/' );
int v = atoi( vStr.c_str() );
int vt = atoi( vtStr.c_str() );
int vn = atoi( vnStr.c_str() );
v = ( v >= 0 ? v : positions.size() + v );
vt = ( vt >= 0 ? vt : texcoords.size() + vt );
vn = ( vn >= 0 ? vn : normals.size() + vn );
refs.push_back( VertRef( v, vt, vn ) );
}

// triangulate, assuming n>3-gons are convex and coplanar
for( size_t i = 1; i+1 < refs.size(); ++i )
{
const VertRef* p[3] = { &refs[0], &refs[i], &refs[i+1] };

// http://www.opengl.org/wiki/Calculating_a_Surface_Normal
glm::vec3 U( positions[ p[1]->v ] - positions[ p[0]->v ] );
glm::vec3 V( positions[ p[2]->v ] - positions[ p[0]->v ] );
glm::vec3 faceNormal = glm::normalize( glm::cross( U, V ) );

for( size_t j = 0; j < 3; ++j )
{
Vertex vert;
vert.position = glm::vec3( positions[ p[j]->v ] );
vert.texcoord = glm::vec2( texcoords[ p[j]->vt ] );
vert.normal = ( p[j]->vn != 0 ? normals[ p[j]->vn ] : faceNormal );
verts.push_back( vert );
}
}
}
}

return verts;
}

参见 the full program here .

关于c++ - 如何将一个简单的 .obj 文件解析为三角形?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52824956/

34 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com