Update gitattributes
[opengl.git] / shapes.hpp
1 #include <array>
2 #include <vector>
3 #include <cmath>
4 #define GLM_FORCE_PURE
5 #include <glm/glm.hpp>
6
7 using namespace std;
8
9 constexpr array<glm::vec3, 6> quadToTriangles(const array<glm::vec3, 4> quads) {
10         return {
11                 quads[0],
12                 quads[1],
13                 quads[2],
14                 quads[2],
15                 quads[3],
16                 quads[0]
17         };
18 }
19
20 constexpr array<glm::vec3, 6> plane() {
21         return quadToTriangles({
22                 glm::vec3(1, 1, 0),
23                 glm::vec3(-1, 1, 0),
24                 glm::vec3(-1, -1, 0),
25                 glm::vec3(1, -1, 0)
26         });
27 }
28
29 inline vector<glm::vec3> cube() {
30         int i = 0;
31         vector<glm::vec3> vertices(36);
32         
33         const array<glm::vec3, 4> front = {
34                 glm::vec3(1, -1, -1),
35                 glm::vec3(-1, -1, -1),
36                 glm::vec3(-1, 1, -1),
37                 glm::vec3(1, 1, -1)
38         };
39         
40         for (auto v: quadToTriangles(front))
41                 vertices[i++] = v;
42
43         const array<glm::vec3, 4> back = {
44                 glm::vec3(1, 1, 1),
45                 glm::vec3(-1, 1, 1),
46                 glm::vec3(-1, -1, 1),
47                 glm::vec3(1, -1, 1)
48         };
49         for (auto v: quadToTriangles(back))
50                 vertices[i++] = v;
51
52
53         const array<glm::vec3, 4> top = {
54                 glm::vec3(1, 1, -1),
55                 glm::vec3(-1, 1, -1),
56                 glm::vec3(-1, 1, 1),
57                 glm::vec3(1, 1, 1)
58         };
59         for (auto v: quadToTriangles(top))
60                 vertices[i++] = v;
61
62         const array<glm::vec3, 4> bottom = {
63                 glm::vec3(1, -1, 1),
64                 glm::vec3(-1, -1, 1),
65                 glm::vec3(-1, -1, -1),
66                 glm::vec3(1, -1, -1)
67         };
68         for (auto v: quadToTriangles(bottom))
69                 vertices[i++] = v;
70
71         const array<glm::vec3, 4> left = {
72                 glm::vec3(-1, 1, 1),
73                 glm::vec3(-1, 1, -1),
74                 glm::vec3(-1, -1, -1),
75                 glm::vec3(-1, -1, 1)
76         };
77         for (auto v: quadToTriangles(left))
78                 vertices[i++] = v;
79
80         const array<glm::vec3, 4> right = {
81                 glm::vec3(1, 1, -1),
82                 glm::vec3(1, 1, 1),
83                 glm::vec3(1, -1, 1),
84                 glm::vec3(1, -1, -1)
85         };
86         for (auto v: quadToTriangles(right))
87                 vertices[i++] = v;
88
89         return vertices;
90 }
91
92 constexpr array<glm::vec3, 36> cubeArray() {
93         int i = 0;
94         array<glm::vec3, 36> vertices;
95         
96         const array<glm::vec3, 4> front = {
97                 glm::vec3(1, -1, -1),
98                 glm::vec3(-1, -1, -1),
99                 glm::vec3(-1, 1, -1),
100                 glm::vec3(1, 1, -1)
101         };
102         
103         for (auto v: quadToTriangles(front))
104                 vertices[i++] = v;
105
106         const array<glm::vec3, 4> back = {
107                 glm::vec3(1, 1, 1),
108                 glm::vec3(-1, 1, 1),
109                 glm::vec3(-1, -1, 1),
110                 glm::vec3(1, -1, 1)
111         };
112         for (auto v: quadToTriangles(back))
113                 vertices[i++] = v;
114
115
116         const array<glm::vec3, 4> top = {
117                 glm::vec3(1, 1, -1),
118                 glm::vec3(-1, 1, -1),
119                 glm::vec3(-1, 1, 1),
120                 glm::vec3(1, 1, 1)
121         };
122         for (auto v: quadToTriangles(top))
123                 vertices[i++] = v;
124
125         const array<glm::vec3, 4> bottom = {
126                 glm::vec3(1, -1, 1),
127                 glm::vec3(-1, -1, 1),
128                 glm::vec3(-1, -1, -1),
129                 glm::vec3(1, -1, -1)
130         };
131         for (auto v: quadToTriangles(bottom))
132                 vertices[i++] = v;
133
134         const array<glm::vec3, 4> left = {
135                 glm::vec3(-1, 1, 1),
136                 glm::vec3(-1, 1, -1),
137                 glm::vec3(-1, -1, -1),
138                 glm::vec3(-1, -1, 1)
139         };
140         for (auto v: quadToTriangles(left))
141                 vertices[i++] = v;
142
143         const array<glm::vec3, 4> right = {
144                 glm::vec3(1, 1, -1),
145                 glm::vec3(1, 1, 1),
146                 glm::vec3(1, -1, 1),
147                 glm::vec3(1, -1, -1)
148         };
149         for (auto v: quadToTriangles(right))
150                 vertices[i++] = v;
151
152         return vertices;
153 }
154
155 constexpr glm::vec3 pyramid[18] = {
156         glm::vec3(0.0f, 1.0f, 0.0f),
157         glm::vec3(1.0f, -1.0f, -1.0f),
158         glm::vec3(-1.0f, -1.0f, -1.0f),
159
160         glm::vec3(0.0f, 1.0f, 0.0f),
161         glm::vec3(-1.0f, -1.0f, 1.0f),
162         glm::vec3(1.0f, -1.0f, 1.0f),
163
164         glm::vec3(0.0f, 1.0f, 0.0f),
165         glm::vec3(-1.0f, -1.0f, -1.0f),
166         glm::vec3(-1.0f, -1.0f, 1.0f),
167
168         glm::vec3(0.0f, 1.0f, 0.0f),
169         glm::vec3(1.0f, -1.0f, 1.0f),
170         glm::vec3(1.0f, -1.0f, -1.0f),
171
172         glm::vec3(1, -1, 1),
173         glm::vec3(-1, -1, 1),
174         glm::vec3(-1, -1, -1),
175         glm::vec3(-1, -1, -1),
176         glm::vec3(1, -1, -1),
177         glm::vec3(1, -1, 1)
178 };
179
180 // taken from http://www.songho.ca/opengl/gl_sphere.html
181 #define SECTOR_COUNT 16
182 #define STACK_COUNT 16
183 inline std::vector<glm::vec3> sphere(float radius = 1) {
184         float sectorStep = 2 * M_PI / SECTOR_COUNT;
185         float stackStep = M_PI / STACK_COUNT;
186
187         std::vector<glm::vec3> vertices;
188
189         for(int i = 0; i <= STACK_COUNT; i++) {
190                 float stackAngle = M_PI / 2 - i * stackStep;        // starting from pi/2 to -pi/2
191                 float xy = radius * cosf(stackAngle);             // r * cos(u)
192                 float z = radius * sinf(stackAngle);              // r * sin(u)
193
194                 // add (sectorCount+1) vertices per stack
195                 // the first and last vertices have same position and normal, but different tex coords
196                 for(int j = 0; j <= SECTOR_COUNT; j++)
197                 {
198                         float sectorAngle = j * sectorStep;           // starting from 0 to 2pi
199
200                         // vertex position (x, y, z)
201                         float x = xy * cosf(sectorAngle);             // r * cos(u) * cos(v)
202                         float y = xy * sinf(sectorAngle);             // r * cos(u) * sin(v)
203                         vertices.push_back({x, y, z});
204
205                         // normalized vertex normal (nx, ny, nz)
206                         /* nx = x * lengthInv; */
207                         /* ny = y * lengthInv; */
208                         /* nz = z * lengthInv; */
209                         /* normals.push_back(nx); */
210                         /* normals.push_back(ny); */
211                         /* normals.push_back(nz); */
212
213                 }
214         }
215         return vertices;
216 }
217
218 inline std::vector<unsigned int> sphereIndices() {
219         // generate CCW index list of sphere triangles
220         vector<unsigned int> indices;
221         int k1, k2;
222         for(int i = 0; i < STACK_COUNT; ++i)
223         {
224                 k1 = i * (SECTOR_COUNT + 1);     // beginning of current stack
225                 k2 = k1 + SECTOR_COUNT + 1;      // beginning of next stack
226
227                 for(int j = 0; j < SECTOR_COUNT; ++j, ++k1, ++k2)
228                 {
229                         // 2 triangles per sector excluding first and last stacks
230                         // k1 => k2 => k1+1
231                         if(i != 0)
232                         {
233                                 indices.push_back(k1);
234                                 indices.push_back(k2);
235                                 indices.push_back(k1 + 1);
236                         }
237
238                         // k1+1 => k2 => k2+1
239                         if(i != (STACK_COUNT-1))
240                         {
241                                 indices.push_back(k1 + 1);
242                                 indices.push_back(k2);
243                                 indices.push_back(k2 + 1);
244                         }
245                 }
246         } 
247         return indices;
248 }