-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathstlModel.cpp
131 lines (105 loc) · 4.52 KB
/
stlModel.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
#include "stlModel.h"
#include <iostream>
#include "stl_reader/stl_reader.h"
#ifndef _USE_MATH_DEFINES
#define _USE_MATH_DEFINES
#endif
#include <math.h>
#include <assert.h>
using namespace FileLoader;
namespace {
template<typename val_T, uint32_t num_T>
static val_T dot( const std::array<val_T, num_T>& v1, const std::array<val_T, num_T>& v2 ) {
val_T result = val_T( 0 );
for (uint32_t i = 0; i < num_T; i++) {
result += v1[i] * v2[i];
}
return result;
}
}
void StlModel::clear() {
mCoords.clear();
mNormals.clear();
mIndices.clear();
mSolids.clear();
mCenterAndRadius = std::array<float, 4>{ 0.0f, 0.0f, 0.0f, 0.0f };
mWasRadiusCalculated = false;
}
eRetVal StlModel::load(const std::string& url)
{
std::vector<float> faceNormals;
try {
stl_reader::ReadStlFile(url.c_str(), mCoords, faceNormals, mIndices, mSolids);
}
catch (std::exception& e) {
std::cout << e.what() << std::endl;
}
mCenterAndRadius = std::array<float, 4>{ 0.0f, 0.0f, 0.0f, 0.0f };
mWasRadiusCalculated = false;
assert( faceNormals.size() % 3 == 0 && "assume there is always a coord-triple xyz in each face normal" );
// distribute face normals to vertices, assume triangles only
mNormals.resize( faceNormals.size() * 3 );
std::fill( mNormals.begin(), mNormals.end(), 0.0f );
for (size_t faceIdx = 0, lastIdx = mIndices.size() / 3; faceIdx < lastIdx; faceIdx++) {
const uint32_t v0_idx = mIndices[faceIdx * 3 + 0];
const uint32_t v1_idx = mIndices[faceIdx * 3 + 1];
const uint32_t v2_idx = mIndices[faceIdx * 3 + 2];
const float faceNormal_x = faceNormals[ faceIdx * 3 + 0 ];
const float faceNormal_y = faceNormals[ faceIdx * 3 + 1 ];
const float faceNormal_z = faceNormals[ faceIdx * 3 + 2 ];
mNormals[v0_idx * 3 + 0] = 0.5f * ( mNormals[v0_idx * 3 + 0] + faceNormal_x );
mNormals[v0_idx * 3 + 1] = 0.5f * ( mNormals[v0_idx * 3 + 1] + faceNormal_y );
mNormals[v0_idx * 3 + 2] = 0.5f * ( mNormals[v0_idx * 3 + 2] + faceNormal_z );
mNormals[v1_idx * 3 + 0] = 0.5f * ( mNormals[v1_idx * 3 + 0] + faceNormal_x );
mNormals[v1_idx * 3 + 1] = 0.5f * ( mNormals[v1_idx * 3 + 1] + faceNormal_y );
mNormals[v1_idx * 3 + 2] = 0.5f * ( mNormals[v1_idx * 3 + 2] + faceNormal_z );
mNormals[v2_idx * 3 + 0] = 0.5f * ( mNormals[v2_idx * 3 + 0] + faceNormal_x );
mNormals[v2_idx * 3 + 1] = 0.5f * ( mNormals[v2_idx * 3 + 1] + faceNormal_y );
mNormals[v2_idx * 3 + 2] = 0.5f * ( mNormals[v2_idx * 3 + 2] + faceNormal_z );
}
getBoundingSphere(mCenterAndRadius);
return eRetVal::OK;//();
}
eRetVal StlModel::save(const std::string& url, const std::string& comment)
{
return eRetVal::ERROR; //("StlModel::save() is not implemented yet");
}
const void StlModel::getBoundingSphere(std::array<float, 4>& centerAndRadius) const
{
if (mWasRadiusCalculated) {
centerAndRadius = mCenterAndRadius;
return;
}
const size_t numTris = mIndices.size() / 3;
for (size_t itri = 0; itri < numTris; ++itri) {
//std::cout << "coordinates of triangle " << itri << ": ";
for (size_t icorner = 0; icorner < 3; ++icorner) {
const float* const c = &mCoords[3 * mIndices[3 * itri + icorner]];
//std::cout << "(" << c[0] << ", " << c[1] << ", " << c[2] << ") ";
mCenterAndRadius[0] += c[0];
mCenterAndRadius[1] += c[1];
mCenterAndRadius[2] += c[2];
}
}
const float fNumCoords = static_cast<float>(mIndices.size());
mCenterAndRadius[0] /= fNumCoords;
mCenterAndRadius[1] /= fNumCoords;
mCenterAndRadius[2] /= fNumCoords;
const std::array<float, 3> sphereCenter{ mCenterAndRadius[0], mCenterAndRadius[1], mCenterAndRadius[2] };
float maxLen = 0.0f;
for (size_t itri = 0; itri < numTris; ++itri) {
for (size_t icorner = 0; icorner < 3; ++icorner) {
const float *const c = &mCoords[3 * mIndices[3 * itri + icorner]];
std::array<float, uint32_t{3u}> coord{ c[0], c[1], c[2] };
std::array<float, uint32_t{3u}> vecToCenter{
coord[0] - sphereCenter[0],
coord[1] - sphereCenter[1],
coord[2] - sphereCenter[2],
};
maxLen = std::max( maxLen, dot<float, uint32_t{3u}>( vecToCenter, vecToCenter ) );
}
}
mCenterAndRadius[3] = sqrtf(maxLen);
mWasRadiusCalculated = true;
centerAndRadius = mCenterAndRadius;
}