/
mesh.cpp
410 lines (342 loc) · 9.08 KB
/
mesh.cpp
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
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
#include "mesh.h"
#if defined (_MSC_VER) && (_MSC_VER >= 1020)
#pragma warning(disable:4710) // function not inlined
#pragma warning(disable:4702) // unreachable code
#pragma warning(disable:4514) // unreferenced inline function has been removed
#endif
#include <assert.h>
#include <float.h>
#include <iostream>
Mesh::Mesh(char* filename)
{
_numVerts = _numTriangles = 0;
if (!loadFromFile(filename))
{
// we failed to load mesh from the file
_numVerts = _numTriangles = 0;
_vlist.clear();
_plist.clear();
}
}
Mesh::Mesh(const Mesh& m)
{
_numVerts = m._numVerts;
_numTriangles = m._numTriangles;
_vlist = m._vlist; // NOTE: triangles are still pointing to original mesh
_plist = m._plist;
// NOTE: should reset tris in _vlist, _plist
}
Mesh& Mesh::operator=(const Mesh& m)
{
if (this == &m) return *this; // don't assign to self
_numVerts = m._numVerts;
_numTriangles = m._numTriangles;
_vlist = m._vlist; // NOTE: triangles are still pointing to original mesh
_plist = m._plist;
// NOTE: should reset tris in _vlist, _plist
return *this;
}
Mesh::~Mesh()
{
_numVerts = _numTriangles = 0;
_vlist.erase(_vlist.begin(), _vlist.end());
_plist.erase(_plist.begin(), _plist.end());
}
// Helper function for reading PLY mesh file,读入顶点数
bool Mesh::readNumPlyVerts(FILE *&inFile, int& nVerts)
{
// Read # of verts
bool bElementFound = false;
/* Get number of vertices in mesh*/
for(;;)
{
char tempStr[1024];
fscanf(inFile, "%s", tempStr);
if (feof(inFile))
{
MessageBox(NULL, "Reached End of File and string \"element vertex\" not found!\n",
NULL, MB_ICONEXCLAMATION);
return false;
}
/* change tempStr to lower case */
ChangeStrToLower(tempStr);
if (bElementFound && !strncmp(tempStr, "vertex", 6))
{
break;
}
if (!strncmp(tempStr, "element", 7))
{
bElementFound = true;
continue;
}
}
fscanf(inFile, "%d", &nVerts);
if (feof(inFile))
{
MessageBox(NULL, "Reached End of File before \"element face\" found!\n",
NULL, MB_ICONEXCLAMATION);
return false;
}
return true;
}
// Helper function for reading PLY mesh file,读入三角形个数
bool Mesh::readNumPlyTris(FILE *&inFile, int& nTris)
{
bool bElementFound = false;
/* Get number of faces in mesh*/
for(;;)
{
char tempStr[1024];
fscanf(inFile, "%s", tempStr);
if (feof(inFile))
{
MessageBox(NULL, "Reached End of File and string \"element face\" not found!\n",
NULL, MB_ICONEXCLAMATION);
return false;
}
/* change tempStr to lower case */
ChangeStrToLower(tempStr);
if (bElementFound && !strncmp(tempStr, "face", 4))
{
break;
}
if (!strncmp(tempStr, "element", 7))
{
bElementFound = true;
continue;
}
}
fscanf(inFile, "%d", &nTris);
if (feof(inFile))
{
MessageBox(NULL, TEXT("Reached End of File before list of vertices found!\n"),
NULL, MB_ICONEXCLAMATION);
return false;
}
return true;
}
// Helper function for reading PLY mesh file,读入字符ply
bool Mesh::readPlyHeader(FILE *&inFile)
{
char tempStr[1024];
// Read "ply" string
do
{
fscanf(inFile, "%s", tempStr);
if (feof(inFile))
{
MessageBox(NULL, "Reached End of File and the string \"ply\" NOT FOUND!!\n",
NULL, MB_ICONEXCLAMATION);
return false;
}
ChangeStrToLower(tempStr); // change tempStr to lower case
} while (strncmp(tempStr, "ply", 3));
// Read # of verts
if (!readNumPlyVerts(inFile, _numVerts))
{
return false;
}
// Read # of triangles
if (!readNumPlyTris(inFile, _numTriangles))
{
return false;
}
// get end_header,读取文件结束标志
do
{
fscanf(inFile, "%s", tempStr);
if (feof(inFile))
{
MessageBox(NULL, TEXT("Reached End of File and string \"end_header\" not found!\n"),
NULL, MB_ICONEXCLAMATION);
return false;
}
/* change tempStr to lower case */
ChangeStrToLower(tempStr);
} while (strncmp(tempStr, "end_header", 10));
////////// end of header
return true;
}
// Helper function for reading PLY mesh file//读入顶点值并加入顶点链表
bool Mesh::readPlyVerts(FILE *&inFile)
{
int i;
// read vertices
for ( i = 0; i < _numVerts; i++)
{
char tempStr[1024];
#pragma warning(disable:4244) /* disable double -> float warning */
fscanf(inFile, "%s", tempStr);
float x = atof(tempStr);
fscanf(inFile, "%s", tempStr);
float y = atof(tempStr);
fscanf(inFile, "%s", tempStr);
float z = atof(tempStr);
#pragma warning(default:4244) /* double -> float */
vertex v(x, y, z);//定义vertex类对象并调用构造函数vertex(float x,float y,float z)进行初始化
v.setIndex(i);//调用对象v的setIndex函数
_vlist.push_back(v); // push_back puts a *copy* of the element at the end of the list
if (feof(inFile))
{
MessageBox(NULL,"Reached End of File before all vertices found!\n",
NULL, MB_ICONEXCLAMATION);
return false;
}
// read until end of line
while (fgetc(inFile) != '\n');
}
return true;
}
// Helper function for reading PLY mesh file
bool Mesh::readPlyTris(FILE *&inFile)
{
int i;
// read triangles
for (i = 0; i < _numTriangles; i++)
{
int v1, v2, v3;
int nVerts;
fscanf(inFile, "%d", &nVerts);
if (3 != nVerts)
{
MessageBox(NULL, "Error: Ply file contains polygons which are not triangles!\n",
NULL, MB_ICONEXCLAMATION);
return false;
}
fscanf(inFile, "%d", &v1); // get value for vertex A
fscanf(inFile, "%d", &v2); // get value for vertex B
fscanf(inFile, "%d", &v3); // get value for vertex C
// make sure verts in correct range
assert(v1 < _numVerts && v2 < _numVerts && v3 < _numVerts);
triangle t(this, v1, v2, v3);//创建triangle类对象t并调用构造函数triangle(mesh *mp,int v1,int v2,int v3)
t.setIndex(i);
_plist.push_back(t); // push_back puts a *copy* of the element at the end of the list
// update each vertex w/ its neighbors (vertrices & triangles)
_vlist[v1].addTriNeighbor(i);
_vlist[v1].addVertNeighbor(v2);
_vlist[v1].addVertNeighbor(v3);
_vlist[v2].addTriNeighbor(i);
_vlist[v2].addVertNeighbor(v1);
_vlist[v2].addVertNeighbor(v3);
_vlist[v3].addTriNeighbor(i);
_vlist[v3].addVertNeighbor(v1);
_vlist[v3].addVertNeighbor(v2);
if (feof(inFile))
{
MessageBox(NULL, "Reached End of File before all faces found!\n",
NULL, MB_ICONEXCLAMATION);
return false;
}
// read until end of line
while (fgetc(inFile) != '\n');
}
return true;
}
// Load mesh from PLY file
bool Mesh::loadFromFile(char* filename)
{
FILE* inFile = fopen(filename, "rt");
if (inFile == NULL)
{
char pszError[_MAX_FNAME + 1];
sprintf(pszError, "%s does not exist!\n", filename);
MessageBox(NULL, pszError, NULL, MB_ICONEXCLAMATION);
return FALSE;
}
// read header to PLY file
if (!readPlyHeader(inFile))
{
return false;
}
// read vertex data from PLY file
if (!readPlyVerts(inFile))
{
return false;
}
// read triangle data from PLY file
if (!readPlyTris(inFile))
{
return false;
}
fclose(inFile); // close the file
calcVertNormals();
return true;
}
// Recalculate the normal for one vertex
void Mesh::calcOneVertNormal(unsigned vert)
{
vertex& v = getVertex(vert);
const set<int>& triset = v.getTriNeighbors();
set<int>::const_iterator iter;
Vec3 vec;
for (iter = triset.begin(); iter != triset.end(); ++iter)
{
// get the triangles for each vertex & add up the normals.
vec += getTri(*iter).getNormalVec3();
}
vec.normalize(); // normalize the vertex
v.setVertNomal(vec);
}
// Calculate the vertex normals after loading the mesh.
void Mesh::calcVertNormals()
{
// Iterate through the vertices
for (unsigned i = 0; i < _vlist.size(); ++i)
{
calcOneVertNormal(i);
}
}
// Used for debugging
void Mesh::dump()
{
std::cout << "*** Mesh Dump ***" << std::endl;
std::cout << "# of vertices: " << _numVerts << std::endl;
std::cout << "# of triangles: " << _numTriangles << std::endl;
for (unsigned i = 0; i < _vlist.size(); ++i)
{
std::cout << "\tVertex " << i << ": " << _vlist[i] << std::endl;
}
std::cout << std::endl;
for (unsigned i = 0; i < _plist.size(); ++i)
{
std::cout << "\tTriangle " << i << ": " << _plist[i] << std::endl;
}
std::cout << "*** End of Mesh Dump ***" << std::endl;
std::cout << std::endl;
}
// Get min, max values of all verts
void Mesh::setMinMax(float min[3], float max[3])
{
max[0] = max[1] = max[2] = -FLT_MAX;
min[0] = min[1] = min[2] = FLT_MAX;
for (unsigned int i = 0; i < _vlist.size(); ++i)
{
const float* pVert = _vlist[i].getArrayVerts();
if (pVert[0] < min[0]) min[0] = pVert[0];
if (pVert[1] < min[1]) min[1] = pVert[1];
if (pVert[2] < min[2]) min[2] = pVert[2];
if (pVert[0] > max[0]) max[0] = pVert[0];
if (pVert[1] > max[1]) max[1] = pVert[1];
if (pVert[2] > max[2]) max[2] = pVert[2];
}
}
// Center mesh around origin.
// Fit mesh in box from (-1, -1, -1) to (1, 1, 1)
void Mesh::Normalize()
{
float min[3], max[3], Scale;
setMinMax(min, max);
Vec3 minv(min);
Vec3 maxv(max);
Vec3 dimv = maxv - minv;
if (dimv.x >= dimv.y && dimv.x >= dimv.z) Scale = 2.0f/dimv.x;
else if (dimv.y >= dimv.x && dimv.y >= dimv.z) Scale = 2.0f/dimv.y;
else Scale = 2.0f/dimv.z;
Vec3 transv = minv + maxv;
transv *= 0.5f;
for (unsigned int i = 0; i < _vlist.size(); ++i)
{
_vlist[i].getXYZ() -= transv;
_vlist[i].getXYZ() *= Scale;
}
}