aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src/extantz/gears.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/extantz/gears.c')
-rw-r--r--src/extantz/gears.c354
1 files changed, 354 insertions, 0 deletions
diff --git a/src/extantz/gears.c b/src/extantz/gears.c
new file mode 100644
index 0000000..68f817e
--- /dev/null
+++ b/src/extantz/gears.c
@@ -0,0 +1,354 @@
1#include "extantz.h"
2
3
4
5#if DO_GEARS
6//--------------------------------//
7// Gear Stuff.
8
9static GLfloat *vert(GLfloat *p, GLfloat x, GLfloat y, GLfloat z, GLfloat *n)
10{
11 p[0] = x;
12 p[1] = y;
13 p[2] = z;
14 p[3] = n[0];
15 p[4] = n[1];
16 p[5] = n[2];
17
18 return p + 6;
19}
20
21/* Draw a gear wheel. You'll probably want to call this function when
22 * building a display list since we do a lot of trig here.
23 *
24 * Input: inner_radius - radius of hole at center
25 * outer_radius - radius at center of teeth
26 * width - width of gear
27 * teeth - number of teeth
28 * tooth_depth - depth of tooth
29 */
30static Gear *make_gear(GLData *gld, GLfloat inner_radius, GLfloat outer_radius, GLfloat width, GLint teeth, GLfloat tooth_depth)
31{
32 GLint i;
33 GLfloat r0, r1, r2;
34 GLfloat da;
35 GLfloat *v;
36 Gear *gear;
37 double s[5], c[5];
38 GLfloat normal[3];
39 const int tris_per_tooth = 20;
40 Evas_GL_API *gl = gld->glApi;
41
42 gear = (Gear*)malloc(sizeof(Gear));
43 if (gear == NULL)
44 return NULL;
45
46 r0 = inner_radius;
47 r1 = outer_radius - tooth_depth / 2.0;
48 r2 = outer_radius + tooth_depth / 2.0;
49
50 da = 2.0 * M_PI / teeth / 4.0;
51
52 gear->vertices = calloc(teeth * tris_per_tooth * 3 * 6, sizeof *gear->vertices);
53 s[4] = 0;
54 c[4] = 1;
55 v = gear->vertices;
56 for (i = 0; i < teeth; i++)
57 {
58 s[0] = s[4];
59 c[0] = c[4];
60 s[1] = sin(i * 2.0 * M_PI / teeth + da);
61 c[1] = cos(i * 2.0 * M_PI / teeth + da);
62 s[2] = sin(i * 2.0 * M_PI / teeth + da * 2);
63 c[2] = cos(i * 2.0 * M_PI / teeth + da * 2);
64 s[3] = sin(i * 2.0 * M_PI / teeth + da * 3);
65 c[3] = cos(i * 2.0 * M_PI / teeth + da * 3);
66 s[4] = sin(i * 2.0 * M_PI / teeth + da * 4);
67 c[4] = cos(i * 2.0 * M_PI / teeth + da * 4);
68
69 normal[0] = 0.0;
70 normal[1] = 0.0;
71 normal[2] = 1.0;
72
73 v = vert(v, r2 * c[1], r2 * s[1], width * 0.5, normal);
74
75 v = vert(v, r2 * c[1], r2 * s[1], width * 0.5, normal);
76 v = vert(v, r2 * c[2], r2 * s[2], width * 0.5, normal);
77 v = vert(v, r1 * c[0], r1 * s[0], width * 0.5, normal);
78 v = vert(v, r1 * c[3], r1 * s[3], width * 0.5, normal);
79 v = vert(v, r0 * c[0], r0 * s[0], width * 0.5, normal);
80 v = vert(v, r1 * c[4], r1 * s[4], width * 0.5, normal);
81 v = vert(v, r0 * c[4], r0 * s[4], width * 0.5, normal);
82
83 v = vert(v, r0 * c[4], r0 * s[4], width * 0.5, normal);
84 v = vert(v, r0 * c[0], r0 * s[0], width * 0.5, normal);
85 v = vert(v, r0 * c[4], r0 * s[4], -width * 0.5, normal);
86 v = vert(v, r0 * c[0], r0 * s[0], -width * 0.5, normal);
87
88 normal[0] = 0.0;
89 normal[1] = 0.0;
90 normal[2] = -1.0;
91
92 v = vert(v, r0 * c[4], r0 * s[4], -width * 0.5, normal);
93
94 v = vert(v, r0 * c[4], r0 * s[4], -width * 0.5, normal);
95 v = vert(v, r1 * c[4], r1 * s[4], -width * 0.5, normal);
96 v = vert(v, r0 * c[0], r0 * s[0], -width * 0.5, normal);
97 v = vert(v, r1 * c[3], r1 * s[3], -width * 0.5, normal);
98 v = vert(v, r1 * c[0], r1 * s[0], -width * 0.5, normal);
99 v = vert(v, r2 * c[2], r2 * s[2], -width * 0.5, normal);
100 v = vert(v, r2 * c[1], r2 * s[1], -width * 0.5, normal);
101
102 v = vert(v, r1 * c[0], r1 * s[0], width * 0.5, normal);
103
104 v = vert(v, r1 * c[0], r1 * s[0], width * 0.5, normal);
105 v = vert(v, r1 * c[0], r1 * s[0], -width * 0.5, normal);
106 v = vert(v, r2 * c[1], r2 * s[1], width * 0.5, normal);
107 v = vert(v, r2 * c[1], r2 * s[1], -width * 0.5, normal);
108 v = vert(v, r2 * c[2], r2 * s[2], width * 0.5, normal);
109 v = vert(v, r2 * c[2], r2 * s[2], -width * 0.5, normal);
110 v = vert(v, r1 * c[3], r1 * s[3], width * 0.5, normal);
111 v = vert(v, r1 * c[3], r1 * s[3], -width * 0.5, normal);
112 v = vert(v, r1 * c[4], r1 * s[4], width * 0.5, normal);
113 v = vert(v, r1 * c[4], r1 * s[4], -width * 0.5, normal);
114
115 v = vert(v, r1 * c[4], r1 * s[4], -width * 0.5, normal);
116 }
117
118 gear->count = (v - gear->vertices) / 6;
119
120 gl->glGenBuffers(1, &gear->vbo);
121 gl->glBindBuffer(GL_ARRAY_BUFFER, gear->vbo);
122 gl->glBufferData(GL_ARRAY_BUFFER, gear->count * 6 * 4, gear->vertices, GL_STATIC_DRAW);
123
124
125 return gear;
126}
127
128void free_gear(Gear *gear)
129{
130 free(gear->vertices);
131 free(gear);
132 gear = NULL;
133}
134
135static void multiply(GLfloat *m, const GLfloat *n)
136{
137 GLfloat tmp[16];
138 const GLfloat *row, *column;
139 div_t d;
140 int i, j;
141
142 for (i = 0; i < 16; i++)
143 {
144 tmp[i] = 0;
145 d = div(i, 4);
146 row = n + d.quot * 4;
147 column = m + d.rem;
148 for (j = 0; j < 4; j++)
149 tmp[i] += row[j] * column[j * 4];
150 }
151 memcpy(m, &tmp, sizeof tmp);
152}
153
154static void rotate(GLfloat *m, GLfloat angle, GLfloat x, GLfloat y, GLfloat z)
155{
156 double s, c;
157
158 s = sin(angle);
159 c = cos(angle);
160 GLfloat r[16] =
161 {
162 x * x * (1 - c) + c, y * x * (1 - c) + z * s, x * z * (1 - c) - y * s, 0,
163 x * y * (1 - c) - z * s, y * y * (1 - c) + c, y * z * (1 - c) + x * s, 0,
164 x * z * (1 - c) + y * s, y * z * (1 - c) - x * s, z * z * (1 - c) + c, 0,
165 0, 0, 0, 1
166 };
167
168 multiply(m, r);
169}
170
171static void translate(GLfloat *m, GLfloat x, GLfloat y, GLfloat z)
172{
173 GLfloat t[16] = { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, x, y, z, 1 };
174
175 multiply(m, t);
176}
177
178static void draw_gear(GLData *gld, Gear *gear, GLfloat *m, GLfloat x, GLfloat y, GLfloat angle, const GLfloat *color)
179{
180 Evas_GL_API *gl = gld->glApi;
181 GLfloat tmp[16];
182
183 memcpy(tmp, m, sizeof tmp);
184 translate(tmp, x, y, 0);
185 rotate(tmp, 2 * M_PI * angle / 360.0, 0, 0, 1);
186 gl->glUniformMatrix4fv(gld->proj_location, 1, GL_FALSE, tmp);
187 gl->glUniform3fv(gld->light_location, 1, gld->light);
188 gl->glUniform4fv(gld->color_location, 1, color);
189
190 gl->glBindBuffer(GL_ARRAY_BUFFER, gear->vbo);
191
192 gl->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), NULL);
193 gl->glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLfloat *) 0 + 3);
194 gl->glEnableVertexAttribArray(0);
195 gl->glEnableVertexAttribArray(1);
196 gl->glDrawArrays(GL_TRIANGLE_STRIP, 0, gear->count);
197}
198
199
200void drawGears(GLData *gld)
201{
202 Evas_GL_API *gl = gld->glApi;
203 static const GLfloat red[4] = { 0.8, 0.1, 0.0, 1.0 };
204 static const GLfloat green[4] = { 0.0, 0.8, 0.2, 1.0 };
205 static const GLfloat blue[4] = { 0.2, 0.2, 1.0, 1.0 };
206 GLfloat m[16];
207
208 // Draw the gears.
209 if (!gld->useIrr)
210 {
211 gl->glClearColor(0.7, 0.0, 1.0, 1.0);
212 gl->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
213 }
214
215 memcpy(m, gld->proj, sizeof m);
216 rotate(m, 2 * M_PI * gld->view_rotx / 360.0, 1, 0, 0);
217 rotate(m, 2 * M_PI * gld->view_roty / 360.0, 0, 1, 0);
218 rotate(m, 2 * M_PI * gld->view_rotz / 360.0, 0, 0, 1);
219
220 draw_gear(gld, gld->gear1, m, -3.0, -2.0, gld->angle, red);
221 draw_gear(gld, gld->gear2, m, 3.1, -2.0, -2 * gld->angle - 9.0, green);
222 draw_gear(gld, gld->gear3, m, -3.1, 4.2, -2 * gld->angle - 25.0, blue);
223 gld->angle += 2.0;
224}
225
226static const char vertex_shader[] =
227 "uniform mat4 proj;\n"
228 "attribute vec4 position;\n"
229 "attribute vec4 normal;\n"
230 "varying vec3 rotated_normal;\n"
231 "varying vec3 rotated_position;\n"
232 "vec4 tmp;\n"
233 "void main()\n"
234 "{\n"
235 " gl_Position = proj * position;\n"
236 " rotated_position = gl_Position.xyz;\n"
237 " tmp = proj * normal;\n"
238 " rotated_normal = tmp.xyz;\n"
239 "}\n";
240
241 static const char fragment_shader[] =
242 "#ifdef GL_ES\n"
243 "precision mediump float;\n"
244 "#endif\n"
245 "uniform vec4 color;\n"
246 "uniform vec3 light;\n"
247 "varying vec3 rotated_normal;\n"
248 "varying vec3 rotated_position;\n"
249 "vec3 light_direction;\n"
250 "vec4 white = vec4(0.5, 0.5, 0.5, 1.0);\n"
251 "void main()\n"
252 "{\n"
253 " light_direction = normalize(light - rotated_position);\n"
254 " gl_FragColor = color + white * dot(light_direction, rotated_normal);\n"
255 "}\n";
256
257static GLuint load_shader(GLData *gld, GLenum type, const char *shader_src)
258{
259 Evas_GL_API *gl = gld->glApi;
260 GLuint shader;
261 GLint compiled = 0;
262
263 // Create the shader object
264 if (!(shader = gl->glCreateShader(type))) return 0;
265 gl->glShaderSource(shader, 1, &shader_src, NULL);
266 // Compile the shader
267 gl->glCompileShader(shader);
268 gl->glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
269
270 if (!compiled)
271 {
272 GLint len = 0;
273
274 gl->glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &len);
275 if (len > 1)
276 {
277 char *info = malloc(sizeof(char) * len);
278
279 if (info)
280 {
281 gl->glGetShaderInfoLog(shader, len, NULL, info);
282 printf("Error compiling shader:\n"
283 "%s\n", info);
284 free(info);
285 }
286 }
287 gl->glDeleteShader(shader);
288 return 0;
289 }
290 return shader;
291}
292
293void gears_init(GLData *gld)
294{
295 Evas_GL_API *gl = gld->glApi;
296 GLint linked = 0;
297
298// char msg[512];
299
300 gl->glEnable(GL_CULL_FACE);
301 gl->glEnable(GL_DEPTH_TEST);
302 gl->glEnable(GL_BLEND);
303
304 // Load the vertex/fragment shaders
305 gld->vtx_shader = load_shader(gld, GL_VERTEX_SHADER, vertex_shader);
306 gld->fgmt_shader = load_shader(gld, GL_FRAGMENT_SHADER, fragment_shader);
307
308 // Create the program object
309 if (!(gld->program = gl->glCreateProgram()))
310 return;
311
312 gl->glAttachShader(gld->program, gld->vtx_shader);
313 gl->glAttachShader(gld->program, gld->fgmt_shader);
314
315 // Bind shader attributes.
316 gl->glBindAttribLocation(gld->program, 0, "position");
317 gl->glBindAttribLocation(gld->program, 1, "normal");
318
319 // Link the program
320 gl->glLinkProgram(gld->program);
321 gld->glApi->glGetProgramiv(gld->program, GL_LINK_STATUS, &linked);
322
323 if (!linked)
324 {
325 GLint len = 0;
326
327 gld->glApi->glGetProgramiv(gld->program, GL_INFO_LOG_LENGTH, &len);
328 if (len > 1)
329 {
330 char *info = malloc(sizeof(char) * len);
331
332 if (info)
333 {
334 gld->glApi->glGetProgramInfoLog(gld->program, len, NULL, info);
335 printf("Error linking program:\n%s\n", info);
336 free(info);
337 }
338 }
339 gld->glApi->glDeleteProgram(gld->program);
340 }
341
342 gl->glUseProgram(gld->program);
343 gld->proj_location = gl->glGetUniformLocation(gld->program, "proj");
344 gld->light_location = gl->glGetUniformLocation(gld->program, "light");
345 gld->color_location = gl->glGetUniformLocation(gld->program, "color");
346
347 /* make the gears */
348 gld->gear1 = make_gear(gld, 1.0, 4.0, 1.0, 20, 0.7);
349 gld->gear2 = make_gear(gld, 0.5, 2.0, 2.0, 10, 0.7);
350 gld->gear3 = make_gear(gld, 1.3, 2.0, 0.5, 10, 0.7);
351
352 gld->gearsInited = EINA_TRUE;
353}
354#endif