-
Notifications
You must be signed in to change notification settings - Fork 2
/
mesh.h
177 lines (153 loc) · 3.78 KB
/
mesh.h
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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
#ifndef __MESH_H__
#define __MESH_H__
#include <cassert>
#include <string>
#include <iostream>
#include <fstream>
#include <sstream>
#include <map>
typedef std::vector<mesh_vertex_t> mesh_vertex_vec_t;
typedef std::vector<interp_vertex_t> interp_vertex_vec_t;
typedef std::vector<uint16_t> index_vec_t;
struct mesh_t
{
mesh_vertex_vec_t m_mesh_vertex;
index_vec_t m_mesh_indices;
interp_vertex_vec_t m_vertex_post;
struct index_t
{
int iv, it, in; // index of vert / uv / normal
index_t() : iv(-1), it(-1), in(-1) {}
bool valid() const {
return iv >= 0 && it >= 0 && in >= 0;
}
friend bool operator<(const index_t& l, const index_t& r) {
assert(l.valid() && r.valid());
return (l.iv < r.iv) ? true : (
l.iv > r.iv ? false : (
l.it < r.it ? true : (
l.it > r.it ? false : l.in < r.in
)
)
);
}
};
struct triangle_t {
index_t a, b, c;
};
mesh_t()
{
}
int load(const std::string& mpath)
{
std::ifstream in;
in.open(mpath, std::ifstream::in);
if (in.fail()) {
printf("load model failed\n");
return -1;
}
auto slash_count = [](const std::string& instr, char flag) -> int {
int scnt = 0;
for (auto c : instr) {
scnt += (c == flag);
}
return scnt;
};
auto read_point = [](std::istringstream& s, index_t& p) {
char slash;
s >> p.iv >> slash >> p.it >> slash >> p.in;
// in wavefront obj all indices start at 1, not zero
--p.iv;
--p.it;
--p.in;
assert(p.valid());
};
std::vector<vector3_t> verts;
std::vector<triangle_t> faces; // index of vertex/uv/normal
std::vector<vector3_t> norms;
std::vector<texcoord_t> uvs;
std::string line;
while (!in.eof()) {
std::getline(in, line);
std::istringstream iss(line.c_str());
char trash;
if (!line.compare(0, 2, "v "))
{
iss >> trash;
vector3_t v;
iss >> v.x >> v.y >> v.z;
verts.push_back(v);
}
else if (!line.compare(0, 3, "vn "))
{
iss >> trash >> trash;
vector3_t n;
iss >> n.x >> n.y >> n.z;
norms.push_back(n);
}
else if (!line.compare(0, 3, "vt "))
{
iss >> trash >> trash;
texcoord_t tc;
iss >> tc.u >> tc.v;
uvs.push_back(tc);
}
else if (!line.compare(0, 2, "f "))
{
iss >> trash;
int scnt = slash_count(line, '/');
if (scnt != 6) {
std::cout << "parse obj(wavefront) failed!" << std::endl;
return -1;
}
triangle_t tri;
read_point(iss, tri.a);
read_point(iss, tri.b);
read_point(iss, tri.c);
faces.push_back(tri);
}
}
std::cout << "# v# " << verts.size() << " f# " << faces.size() << " vt# " << uvs.size() << " vn# " << norms.size() << std::endl;
int vidx = 0;
std::map<index_t, int> vmap;
for (auto& f : faces)
{
if (vmap.find(f.a) == vmap.end()) {
vmap[f.a] = vidx++;
}
if (vmap.find(f.b) == vmap.end()) {
vmap[f.b] = vidx++;
}
if (vmap.find(f.c) == vmap.end()) {
vmap[f.c] = vidx++;
}
}
m_mesh_vertex.resize(vmap.size());
m_mesh_indices.resize(faces.size() * 3);
m_vertex_post.resize(vmap.size());
for (auto& kv : vmap)
{
mesh_vertex_t& vtx = m_mesh_vertex[kv.second];
index_t idx = kv.first;
vtx.pos = verts[idx.iv] * 0.01f; // ue4 obj's unit is centimeter, convert to meter
vtx.uv = uvs[idx.it];
vtx.nor = norms[idx.in];
vector3_t c = vtx.pos;
c.normalize();
vtx.color = c;
std::swap(vtx.pos.y, vtx.pos.z); // obj file format is right-hand coordinate system
std::swap(vtx.nor.y, vtx.nor.z); // obj file format is right-hand coordinate system
}
for (size_t i = 0; i < faces.size(); ++i)
{
int ia = vmap[faces[i].a];
int ib = vmap[faces[i].b];
int ic = vmap[faces[i].c];
m_mesh_indices[i * 3 + 0] = ia;
m_mesh_indices[i * 3 + 1] = ib;
m_mesh_indices[i * 3 + 2] = ic;
}
return 0;
}
};
#endif //__MESH_H__