-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathPrimitiveSphere.cpp
More file actions
175 lines (139 loc) · 5.12 KB
/
Copy pathPrimitiveSphere.cpp
File metadata and controls
175 lines (139 loc) · 5.12 KB
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
#include "PrimitiveSphere.h"
#include <glm/detail/type_float.hpp>
PrimitiveSphere::PrimitiveSphere(GLuint lats, GLuint longs, glm::vec4 rgba)
{
this->indexBufferObj = 0;
this->numLats = lats;
this->numLongs = longs;
this->vertexCount = 2 + ((numLats - 1) * numLongs);
this->overall_colour = rgba;
}
void PrimitiveSphere::makeObject()
{
this->vertexCount = 2 + ((numLats - 1) * numLongs);
this->vertex_positions.assign(vertexCount, { 0,0,0 });
this->texture_coords.assign(vertexCount, { 0,0 });
// Generate vertices.
constructSphereVertices(this->vertex_positions, this->texture_coords, this->numLats, this->numLongs);
// Generate vertex colours.
constructSphereVertColours(this->vertex_colours, overall_colour, vertex_positions.size() );
// Copy vertex position to vertex normals list.
this->vertex_normals.assign(this->vertex_positions.begin(), this->vertex_positions.end());
Object3D::makeObject(); // Call parent function
/* Calculate the number of indices in our index array and allocate memory for it */
const GLuint indexCount = ((numLongs * 2) + 2) * (numLats - 1) + ((numLongs + 2) * 2);
this->indices = std::vector<GLuint>(indexCount, 0);
GLuint index = 0; // Current index
#pragma omp parallel
{
// Define indices for the first triangle fan for one pole
#pragma omp for
for (auto i = 0; i < numLongs + 1; i++)
{
this->indices[index++] = i;
}
// Join last triangle in the triangle fan
this->indices[index++] = 1;
GLuint start = 1; // Start index for each latitude row
#pragma omp for
for (auto j = 0; j < numLats - 2; j++)
{
#pragma omp for
for (auto i = 0; i < numLongs; i++)
{
this->indices[index++] = start + i;
this->indices[index++] = start + i + numLongs;
}
#pragma omp single
{
this->indices[index++] = start; // close the triangle strip loop by going back to the first vertex in the loop
this->indices[index++] = start + numLongs; // close the triangle strip loop by going back to the first vertex in the loop
start += numLongs;
}
}
// Define indices for the last triangle fan for the south pole region
#pragma omp for
for (auto i = vertexCount - 1; i > (vertexCount - numLongs - 2); i--)
{
this->indices[index++] = i;
}
}
// Error check for index calculation
if (index < (indexCount - 2))
{
this->indices[index] = vertexCount - 2; // Tie up last triangle in fan
}
else
{
assert(false);
std::cout << "Error in sphere definition, index overrun" << std::endl;
}
// Generate a buffer for the indices
glGenBuffers(1, &this->indexBufferObj);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->indexBufferObj);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexCount * sizeof(GLuint), &this->indices[0], GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
void PrimitiveSphere::drawObject(bool clockwise)
{
Object3D::drawObject(clockwise); // Call parent function
/* Bind the indexed vertex buffer */
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->indexBufferObj);
/* Draw the north pole regions as a triangle fan*/
glDrawElements(GL_TRIANGLE_FAN, this->numLongs + 2, GL_UNSIGNED_INT, nullptr);
/* Calculate offsets into the indexed array. Note that we multiply offsets by 4
because it is a memory offset, the indices are type GLuint which is 4-bytes */
GLuint lat_offset_jump = (numLongs * 2) + 2;
GLuint lat_offset_start = numLongs + 2;
GLuint lat_offset_current = lat_offset_start * 4;
/* Draw the triangle strips of latitudes */
for (GLuint i = 0; i < numLats - 2; i++)
{
glDrawElements(GL_TRIANGLE_STRIP, numLongs * 2 + 2, GL_UNSIGNED_INT, (GLvoid*)lat_offset_current);
lat_offset_current += (lat_offset_jump * 4);
}
/* Draw the south pole as a triangle fan */
glDrawElements(GL_TRIANGLE_FAN, numLongs + 2, GL_UNSIGNED_INT, (char*)(lat_offset_current));
}
void constructSphereVertices(std::vector<glm::vec3>& vert_pos, std::vector<glm::vec2>& texCoords, GLuint lats, GLuint longs)
{
#pragma omp parallel
{
GLfloat DEG_TO_RADIANS = 3.141592f / 180.f;
GLuint vnum = 0;
GLfloat x, y, z, lat_radians, lon_radians;
// Create north-pole vertex
vert_pos[vnum] = glm::vec3(0, 0, 1);
texCoords[vnum] = glm::vec2(0.5, 0);
vnum++;
GLfloat latstep = 180.0f / lats;
GLfloat longstep = 360.0f / (longs - 1);
/* Define vertices along latitude lines */
#pragma omp for
for (GLfloat lat = 90.f - latstep; lat > -90.f; lat -= latstep)
{
lat_radians = lat * DEG_TO_RADIANS;
#pragma omp for
for (GLfloat lon = -180.f; lon <= (180.0f + longstep / 10.0f); lon += longstep)
{
lon_radians = lon * DEG_TO_RADIANS;
x = cos(lat_radians) * cos(lon_radians);
y = cos(lat_radians) * sin(lon_radians);
z = sin(lat_radians);
vert_pos[vnum] = glm::vec3(x, y, z);
float u = (lon + 180.0f) / 360.0f;
float v = (lat + 90.0f) / 180.0f;
texCoords[vnum] = { u,v };
vnum++;
}
// Create south pole vertex
vert_pos[vnum] = { 0, 0, -1 };
texCoords[vnum] = { 0.5, 0.f };
}
}
}
void constructSphereVertColours(std::vector<glm::vec4>& vert_colours, const glm::vec4 rgba, GLuint vert_count)
{
/* Define colours as the x,y,z components of the sphere vertices */
vert_colours = std::vector<glm::vec4>(vert_count, rgba);
}