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
|
#include <foundation/PxBounds3.h>
#include "Mesh.h"
#include <algorithm>
#include <iostream>
// -------------------------------------------------------------------
struct SimpleVertexRef {
int vert, normal, texCoord;
int indexNr, subMeshNr;
bool operator < (const SimpleVertexRef &r) const {
if (vert < r.vert) return true;
if (vert > r.vert) return false;
if (normal < r.normal) return true;
if (normal > r.normal) return false;
return texCoord < r.texCoord;
}
bool operator == (const SimpleVertexRef &r) const {
return vert == r.vert && normal == r.normal && texCoord == r.texCoord;
}
void parse(char *s, int indexNr) {
int nr[3] = {0,0,0};
char *p = s;
for (int i = 0; i < 3; i++) {
while (*p != 0 && *p != '/') p++;
bool end = (*p == 0);
*p = 0;
sscanf_s(s, "%i", &nr[i]);
if (end) break;
p++; s = p;
}
vert = nr[0]-1; texCoord = nr[1]-1; normal = nr[2]-1;
this->indexNr = indexNr;
}
};
#define OBJ_STR_LEN 256
// -------------------------------------------------------------------
bool Mesh::loadFromObjFile(const std::string &filename)
{
const int maxVertsPerFace = 8;
char s[OBJ_STR_LEN], ps[maxVertsPerFace][OBJ_STR_LEN], sub[OBJ_STR_LEN];
int matNr = -1;
PxVec3 p;
float u,v;
shdfnd::Array<SimpleVertexRef> refs;
SimpleVertexRef ref[maxVertsPerFace];
shdfnd::Array<PxVec3> vertices;
shdfnd::Array<PxVec3> normals;
shdfnd::Array<float> texCoords;
int numIndices = 0;
mSubMeshes.resize(1);
mNames.resize(1);
mSubMeshes[0].init();
mNames[0] = "";
mSubMeshes[0].firstIndex = 0;
FILE *f;
if (fopen_s(&f, filename.c_str(), "r") != 0) {
std::cerr << "Could not load OBJ file: " << filename << std::endl;
return false;
}
// first a vertex ref is generated for each v/n/t combination
while (!feof(f)) {
if (fgets(s, OBJ_STR_LEN, f) == NULL) break;
if (strncmp(s, "usemtl", 6) == 0 || strncmp(s, "g ", 2) == 0) { // new group
bool isGroup = strncmp(s, "g ", 2) == 0;
if (isGroup)
strcpy(sub, &s[2]);
else
strcpy(sub, &s[6]);
int numSubs = mSubMeshes.size();
if (mSubMeshes[numSubs-1].numIndices > 0) {
mSubMeshes.resize(numSubs+1);
mNames.resize(numSubs+1);
mSubMeshes[numSubs].init();
mNames[numSubs] = "";
mSubMeshes[numSubs].firstIndex = mIndices.size();
}
int subNr = mSubMeshes.size() - 1;
if (mNames[subNr] == "" || isGroup)
mNames[subNr] = std::string(sub);
}
else if (strncmp(s, "v ", 2) == 0) { // vertex
sscanf_s(s, "v %f %f %f", &p.x, &p.y, &p.z);
vertices.pushBack(p);
}
else if (strncmp(s, "vn ", 3) == 0) { // normal
sscanf_s(s, "vn %f %f %f", &p.x, &p.y, &p.z);
normals.pushBack(p);
}
else if (strncmp(s, "vt ", 3) == 0) { // texture coords
sscanf_s(s, "vt %f %f", &u, &v);
texCoords.pushBack(u);
texCoords.pushBack(v);
}
else if (strncmp(s, "f ", 2) == 0) { // face, tri or quad
int nr;
nr = sscanf_s(s, "f %s %s %s %s %s %s",
ps[0], OBJ_STR_LEN, ps[1], OBJ_STR_LEN, ps[2], OBJ_STR_LEN, ps[3], OBJ_STR_LEN,
ps[4], OBJ_STR_LEN, ps[5], OBJ_STR_LEN, ps[6], OBJ_STR_LEN, ps[7], OBJ_STR_LEN);
if (nr >= 3) {
for (int i = 0; i < nr; i++)
ref[i].parse(ps[i], 0);
for (int i = 1; i < nr-1; i++) {
ref[0].indexNr = numIndices++; refs.pushBack(ref[0]); mIndices.pushBack(0);
ref[i].indexNr = numIndices++; refs.pushBack(ref[i]); mIndices.pushBack(0);
ref[i+1].indexNr = numIndices++; refs.pushBack(ref[i+1]); mIndices.pushBack(0);
mSubMeshes[mSubMeshes.size()-1].numIndices += 3;
}
}
}
}
fclose(f);
// now we merge multiple v/n/t triplets
std::sort(refs.begin(), refs.end());
int i = 0;
PxVec3 defNormal(1.0f, 0.0f, 0.0f);
bool normalsOK = true;
bool mTextured = true;
int numTexCoords = texCoords.size();
int baseVertNr = 0;
while (i < (int)refs.size()) {
int vertNr = mVertices.size();
SimpleVertexRef &r = refs[i];
mVertices.pushBack(vertices[r.vert]);
if (r.normal >= 0) mNormals.pushBack(normals[r.normal]);
else { mNormals.pushBack(defNormal); normalsOK = false; }
if (r.texCoord >= 0 && r.texCoord < numTexCoords) {
//mTexCoords.pushBack(texCoords[2*r.texCoord]);
//mTexCoords.pushBack(texCoords[2*r.texCoord+1]);
mTexCoords.pushBack(PxVec2(texCoords[2*r.texCoord],texCoords[2*r.texCoord+1]));
}
else {
//mTexCoords.pushBack(0.0f);
//mTexCoords.pushBack(0.0f);
mTexCoords.pushBack(PxVec2(0.0f,0.0f));
}
mIndices[r.indexNr] = vertNr;
i++;
while (i < (int)refs.size() && r == refs[i]) {
mIndices[refs[i].indexNr] = vertNr;
i++;
}
}
if (!normalsOK)
updateNormals();
return true;
}
|