-
Notifications
You must be signed in to change notification settings - Fork 0
/
PointCloud.cpp
253 lines (199 loc) · 6.94 KB
/
PointCloud.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
#include "PointCloud.h"
PointCloud::PointCloud(std::string objFilename, GLfloat pointSize)
: pointSize(pointSize)
{
/*
* Section 2: Currently, all the points are hard coded below.
* Modify this to read points from an obj file.
*/
std::ifstream objFile(objFilename,std::ios::in); // The obj file we are reading.
// Check whether the file can be opened.
if (objFile.is_open())
{
std::string line; // A line in the file.
// Read lines from the file.
while (std::getline(objFile, line))
{
// Turn the line into a string stream for processing.
std::stringstream ss;
ss << line;
// Read the first word of the line.
std::string label;
ss >> label;
// If the line is about vertex (starting with a "v").
if (label == "v")
{
// Read the later three float numbers and use them as the
// coordinates.
glm::vec3 point;
ss >> point.x >> point.y >> point.z;
// Process the point. For example, you can save it to a.
points.push_back(point);
}
//load normals
if (label == "vn") {
glm::vec3 normal;
ss >> normal.x >> normal.y >> normal.z;
normals.push_back(normal);
}
//load face indices
if (label == "f") {
std::vector<unsigned int> vect;
// store indices into the vertex list
// adjust 1-based indices to 0-based indices
unsigned int first;
ss >> first;
ss.ignore(256, ' ');
vect.push_back(first-1);
unsigned int second;
ss >> second;
ss.ignore(256, ' ');
vect.push_back(second-1);
unsigned int third;
ss >> third;
ss.ignore(256, ' ');
vect.push_back(third-1);
faceIndices.push_back(glm::ivec3(vect[0], vect[1], vect[2]));
}
}
}
else
{
std::cerr << "Can't open the file " << objFilename << std::endl;
}
objFile.close();
/*
* Section 4, you will need to normalize the object to fit in the
* screen.
*/
//Centering the model
//traverse the vertices of the model
for(int i= 0;i< points.size(); i++) {
// Find minimum and maximum coordinates along each dimension
if(points[i].x > xMax) {
xMax = points[i].x;
}
if(points[i].y > yMax) {
yMax = points[i].y;
}
if(points[i].z > zMax) {
zMax = points[i].z;
}
if(points[i].x < xMin) {
xMin = points[i].x;
}
if(points[i].y < yMin) {
yMin = points[i].y;
}
if(points[i].z < zMin) {
zMin = points[i].z;
}
}
//determine the center point of the model
GLfloat centerX = (GLfloat)((xMin+xMax)/2);
GLfloat centerY = (GLfloat)((yMin+yMax)/2);
GLfloat centerZ = (GLfloat)((zMin+zMax)/2);
modelCenter = glm::vec3(centerX, centerY, centerZ);
//shift all model coordinates by subtracting the coordinates of the center point
for(int i=0; i< points.size(); i++) {
GLfloat xCoor = points[i].x - modelCenter.x;
GLfloat yCoor = points[i].y - modelCenter.y;
GLfloat zCoor = points[i].z - modelCenter.z;
points[i] = glm::vec3(xCoor,yCoor,zCoor);
}
// Scaling the model
//calculate the maximum distance any point is from the center
for(int i=0; i< points.size(); i++) {
GLfloat d = sqrt( pow(points[i].x,2) +
pow(points[i].y,2) +
pow(points[i].z,2));
if(d > maxDistance) {
maxDistance = d;
}
}
GLfloat scale = 10.5/maxDistance;
// Set the model matrix to an identity matrix.
model = glm::mat4(1);
// Set the color.
color = glm::vec3(1, 1, 1);
model = glm::scale(glm::vec3(scale,scale,scale)) * model;
// Generate a vertex array (VAO) and 2 vertex buffer objects (VBO).
glGenVertexArrays(1, &vao);
glGenBuffers(2, vbos);
glGenBuffers(1, &ebo);
// Bind to the VAO.
glBindVertexArray(vao);
// Bind to the first VBO. We will use it to store the points.
glBindBuffer(GL_ARRAY_BUFFER, vbos[0]);
// Pass in the data.
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec3) * points.size(),
points.data(), GL_DYNAMIC_DRAW);
// Enable vertex attribute 0.
// We will be able to access points through it.
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), 0);
// Bind to the second VBO. We will use it to store the normals.
glBindBuffer(GL_ARRAY_BUFFER, vbos[1]);
// Pass in the data.
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec3) * normals.size(),
normals.data(), GL_DYNAMIC_DRAW);
// Enable vertex attribute 0.
// We will be able to access points through it.
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), 0);
//Bind to the ebo
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(glm::ivec3) * faceIndices.size(),
faceIndices.data(), GL_DYNAMIC_DRAW);
// Unbind from the VBO.
glBindBuffer(GL_ARRAY_BUFFER, 0);
// Unbind from the VAO.
glBindVertexArray(0);
}
PointCloud::~PointCloud()
{
// Delete the VBO and the VAO.
glDeleteBuffers(1, &ebo);
glDeleteBuffers(2, vbos);
glDeleteVertexArrays(1, &vao);
}
void PointCloud::draw()
{
// Bind to the VAO.
glBindVertexArray(vao);
// Set point size.
glPointSize(pointSize);
// Draw points
glDrawElements(GL_LINES, 3*faceIndices.size(), GL_UNSIGNED_INT, 0);
// Unbind from the VAO.
glBindVertexArray(0);
}
void PointCloud::update()
{
}
void PointCloud::updatePointSize(GLfloat size)
{
/*
* Section 3: Implement this function to adjust the point size.
*/
pointSize += size;
glPointSize(pointSize);
}
void PointCloud::rotate(float angle, glm::vec3 axis)
{
// Update the transformation matrix by multiplying a rotation matrix
model = glm::rotate(angle, axis)*model;
}
void PointCloud::scale(float factor)
{
model = glm::scale(glm::vec3(factor, factor, factor)) * model;
}
void PointCloud::translate(glm::vec3 direction)
{
model = glm::translate(direction) * model;
}
float PointCloud::getSphereRadius()
{
float r = (xMax - xMin) / 2.0f;
return r;
}