[ Opengl ] (solution) Obj File 임포트 구현
문제
기존 msh 파일만 읽어 오는 임포트 코드를 OBJ 파일을 읽어올 수 있게 코드 수정 시도
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# cube.obj
mtllib cube.mtl
o cube
v -0.500000 -0.500000 0.500000
v 0.500000 -0.500000 0.500000
v -0.500000 0.500000 0.500000
v 0.500000 0.500000 0.500000
v -0.500000 0.500000 -0.500000
v 0.500000 0.500000 -0.500000
v -0.500000 -0.500000 -0.500000
v 0.500000 -0.500000 -0.500000
vt 0.000000 0.000000
vt 1.000000 0.000000
vt 0.000000 1.000000
vt 1.000000 1.000000
vn 0.000000 0.000000 1.000000
vn 0.000000 1.000000 0.000000
vn 0.000000 0.000000 -1.000000
vn 0.000000 -1.000000 0.000000
vn 1.000000 0.000000 0.000000
vn -1.000000 0.000000 0.000000
g cube
usemtl cube
s 1
f 1/1/1 2/2/1 3/3/1
f 3/3/1 2/2/1 4/4/1
s 2
f 3/1/2 4/2/2 5/3/2
f 5/3/2 4/2/2 6/4/2
s 3
f 5/4/3 6/3/3 7/2/3
f 7/2/3 6/3/3 8/1/3
s 4
f 7/1/4 8/2/4 1/3/4
f 1/3/4 8/2/4 2/4/4
s 5
f 2/1/5 8/2/5 4/3/5
f 4/3/5 8/2/5 6/4/5
s 6
f 7/1/6 1/2/6 5/3/6
f 5/3/6 1/2/6 3/4/6
obj 파일 파싱을 통한 임포트 수도 코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
void Object::readOBJFile(char* pFileName)
{
//읽을 목적의 파일 선언
ifstream readFile(pFileName);
//파일이 열렸는지 확인
if (readFile.is_open())
{
//파일 끝까지 읽었는지 확인
while (!readFile.eof())
{
readFile.getline(text, 256);
line.push_back(text);
}
//한줄씩 읽어오기
for (int i = 0; i < line.size(); i++)
{
if(문장이 'v'라면)
{
첫 번째 수->m_vertex[vertexNum][0];
두 번째 수->m_vertex[vertexNum][1];
세 번째 수->m_vertex[vertexNum][2];
vertexNum++;
}
else if(문장이 'vt'라면)
{
첫 번째 수->m_texture[textureNum][0];
두 번째 수->m_texture[textureNum][1];
세 번째 수->m_texture[textureNum][2];
textureNum++;
}
else if(문장이 'vn'라면)
{
첫 번째 수->m_vertexNormal[normalNum][0];
두 번째 수->m_vertexNormal[normalNum][1];
세 번째 수->m_vertexNormal[normalNum][2];
normalNum++;
}
else if(문장이 'f'라면)
{
if('/'포함)
{
첫 번째 수->m_face[faceNum][0];
두 번째 수->m_face_texture[faceNum][0];
세 번째 수->m_face_normal[faceNum][0];
첫 번째 수->m_face[faceNum][1];
두 번째 수->m_face_texture[faceNum][1];
세 번째 수->m_face_normal[faceNum][1];
첫 번째 수->m_face[faceNum][2];
두 번째 수->m_face_texture[faceNum][2];
세 번째 수->m_face_normal[faceNum][2];
faceNum++;
}
else
{
첫 번째 수->m_face[faceNum][0];
두 번째 수->m_face[faceNum][1];
세 번째 수->m_face[faceNum][2];
faceNum++;
}
}
}
}
readFile.close();
}
그러나 OBJ File Loader의 face 중 4개 이상의 vertex들을 가진 face의 경우 임포트 에러 발생, 구체 등의 물체는 하나의 face가 3개 이상을 가진 경우가 많으므로 코드 수정
해결
하나의 face를 여러 삼각형으로 나눈다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
void Object::readOBJFile(char* pFileName)
{
//ifstream readFile("dodecahedron.txt");
ifstream readFile(pFileName);
int faceVertex[20];
int UV;
int nomal;
char text[256];
vector<string>line;
if (readFile.is_open())
{
while (!readFile.eof())
{
readFile.getline(text, 256);
line.push_back(text);
}
for (int i = 0; i < line.size(); i++)
{
if (line[i][0] == 'v' && line[i][1] == ' ')
{
sscanf_s(line[i].c_str(), "v %f %f %f", &m_vertex[m_nNumVertex][0], &m_vertex[m_nNumVertex][1], &m_vertex[m_nNumVertex][2]);
m_nNumVertex++;
}
else if (line[i][0] == 'v' && line[i][1] == 't')
{
sscanf_s(line[i].c_str(), "vt %f %f", &m_uv[m_nNumTexture][0], &m_uv[m_nNumTexture][1]);
m_nNumTexture++;
haveUV = true;
}
else if (line[i][0] == 'v' && line[i][1] == 'n')
{
sscanf_s(line[i].c_str(), "vn %f %f %f", &m_vertexNormal[m_nNumNormal][0], &m_vertexNormal[m_nNumNormal][1], &m_vertexNormal[m_nNumNormal][2]);
m_nNumNormal++;
haveNormal = true;
}
else if (i < line.size() && line[i][0] == 'f')
{
int j = 0, numVertex = 0;
for (; j < line[i].size(); j++)
{
if (line[i][j] == ' ')
{
numVertex++;
}
}
if (line[i][j - 1] == ' ')
{
numVertex--;
}
m_face[m_nNumFace].m_nNumVertex = numVertex;
int faceVerNum = 0, faceVerNorNum = 0, faceUVNum = 0;
if (line[i][1] == ' ' && haveUV && haveNormal)
{
for (int j = 1; j < line[i].size(); j++)
{
if (line[i][j] == ' ') {
sscanf_s(&line[i][j + 1], "%d/%d/%d", &faceVertex[faceVerNum], &m_uv, &m_faceNormal);
faceVerNum++;
}
}
for (int j = 0; j < m_face[m_nNumFace].m_nNumVertex; j++)
{
m_face[m_nNumFace].m_vertex[j] = faceVertex[j];
}
}
else if (line[i][1] == ' ' && !haveUV && haveNormal)
{
for (int j = 1; j < line[i].size(); j++)
{
if (line[i][j] == ' ')
{
sscanf_s(&line[i][j + 1], "%d//%d", &faceVertex[faceVerNum], &m_faceNormal);
faceVerNum++;
}
}
for (int j = 0; j < m_face[m_nNumFace].m_nNumVertex; j++)
{
m_face[m_nNumFace].m_vertex[j] = faceVertex[j];
}
}
else
{
for (int j = 1; j < line[i].size(); j++)
{
if (line[i][j] == ' ')
{
sscanf_s(&line[i][j + 1], "%d", &faceVertex[faceVerNum]);
faceVerNum++;
}
}
for (int j = 0; j < m_face[m_nNumFace].m_nNumVertex; j++)
{
m_face[m_nNumFace].m_vertex[j] = faceVertex[j];
}
}
m_nNumFace++;
}
}
}
readFile.close();
}
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.