diff options
Diffstat (limited to 'src/extantz/gears.c')
-rw-r--r-- | src/extantz/gears.c | 354 |
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 | |||
9 | static 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 | */ | ||
30 | static 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 | |||
128 | void free_gear(Gear *gear) | ||
129 | { | ||
130 | free(gear->vertices); | ||
131 | free(gear); | ||
132 | gear = NULL; | ||
133 | } | ||
134 | |||
135 | static 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 | |||
154 | static 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 | |||
171 | static 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 | |||
178 | static 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 | |||
200 | void 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 | |||
226 | static 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 | |||
257 | static 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 | |||
293 | void 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 | ||