File: | tests/ctkgears.c |
Warning: | line 924, column 5 Value stored to 'previous_frame_time' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* The rendering code in here is taken from es2gears, which has the |
2 | * following copyright notice: |
3 | * |
4 | * Copyright (C) 1999-2001 Brian Paul All Rights Reserved. |
5 | * |
6 | * Permission is hereby granted, free of charge, to any person obtaining a |
7 | * copy of this software and associated documentation files (the "Software"), |
8 | * to deal in the Software without restriction, including without limitation |
9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
10 | * and/or sell copies of the Software, and to permit persons to whom the |
11 | * Software is furnished to do so, subject to the following conditions: |
12 | * |
13 | * The above copyright notice and this permission notice shall be included |
14 | * in all copies or substantial portions of the Software. |
15 | * |
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
17 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
19 | * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN |
20 | * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
21 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
22 | * |
23 | * Ported to GLES2. |
24 | * Kristian Høgsberg <krh@bitplanet.net> |
25 | * May 3, 2010 |
26 | * |
27 | * Improve GLES2 port: |
28 | * * Refactor gear drawing. |
29 | * * Use correct normals for surfaces. |
30 | * * Improve shader. |
31 | * * Use perspective projection transformation. |
32 | * * Add FPS count. |
33 | * * Add comments. |
34 | * Alexandros Frantzis <alexandros.frantzis@linaro.org> |
35 | * Jul 13, 2010 |
36 | */ |
37 | |
38 | #include "config.h" |
39 | |
40 | #include <math.h> |
41 | #include <stdlib.h> |
42 | #include <string.h> |
43 | #include <epoxy/gl.h> |
44 | |
45 | #include "ctkgears.h" |
46 | |
47 | #define STRIPS_PER_TOOTH7 7 |
48 | #define VERTICES_PER_TOOTH34 34 |
49 | #define GEAR_VERTEX_STRIDE6 6 |
50 | |
51 | #ifndef HAVE_SINCOS1 |
52 | static void |
53 | sincos (double x, double *_sin, double *_cos) |
54 | { |
55 | *_sin = sin (x); |
56 | *_cos = cos (x); |
57 | } |
58 | #endif |
59 | |
60 | /** |
61 | * Struct describing the vertices in triangle strip |
62 | */ |
63 | struct vertex_strip { |
64 | /** The first vertex in the strip */ |
65 | GLint first; |
66 | /** The number of consecutive vertices in the strip after the first */ |
67 | GLint count; |
68 | }; |
69 | |
70 | /* Each vertex consist of GEAR_VERTEX_STRIDE GLfloat attributes */ |
71 | typedef GLfloat GearVertex[GEAR_VERTEX_STRIDE6]; |
72 | |
73 | /** |
74 | * Struct representing a gear. |
75 | */ |
76 | struct gear { |
77 | /** The array of vertices comprising the gear */ |
78 | GearVertex *vertices; |
79 | /** The number of vertices comprising the gear */ |
80 | int nvertices; |
81 | /** The array of triangle strips comprising the gear */ |
82 | struct vertex_strip *strips; |
83 | /** The number of triangle strips comprising the gear */ |
84 | int nstrips; |
85 | }; |
86 | |
87 | typedef struct { |
88 | /* The view rotation [x, y, z] */ |
89 | GLfloat view_rot[CTK_GEARS_N_AXIS]; |
90 | |
91 | /* The Vertex Array Object */ |
92 | GLuint vao; |
93 | |
94 | /* The shader program */ |
95 | GLuint program; |
96 | |
97 | /* The gears */ |
98 | struct gear *gear1; |
99 | struct gear *gear2; |
100 | struct gear *gear3; |
101 | |
102 | /** The Vertex Buffer Object holding the vertices in the graphics card */ |
103 | GLuint gear_vbo[3]; |
104 | |
105 | /** The location of the shader uniforms */ |
106 | GLuint ModelViewProjectionMatrix_location; |
107 | GLuint NormalMatrix_location; |
108 | GLuint LightSourcePosition_location; |
109 | GLuint MaterialColor_location; |
110 | |
111 | /* The current gear rotation angle */ |
112 | GLfloat angle; |
113 | |
114 | /* The projection matrix */ |
115 | GLfloat ProjectionMatrix[16]; |
116 | |
117 | /* The direction of the directional light for the scene */ |
118 | GLfloat LightSourcePosition[4]; |
119 | |
120 | gint64 first_frame_time; |
121 | guint tick; |
122 | CtkLabel *fps_label; |
123 | } CtkGearsPrivate; |
124 | |
125 | G_DEFINE_TYPE_WITH_PRIVATE (CtkGears, ctk_gears, CTK_TYPE_GL_AREA)static void ctk_gears_init (CtkGears *self); static void ctk_gears_class_init (CtkGearsClass *klass); static GType ctk_gears_get_type_once (void); static gpointer ctk_gears_parent_class = ((void*)0); static gint CtkGears_private_offset; static void ctk_gears_class_intern_init (gpointer klass) { ctk_gears_parent_class = g_type_class_peek_parent (klass); if (CtkGears_private_offset != 0) g_type_class_adjust_private_offset (klass, &CtkGears_private_offset); ctk_gears_class_init ( (CtkGearsClass*) klass); } __attribute__ ((__unused__)) static inline gpointer ctk_gears_get_instance_private (CtkGears *self ) { return (((gpointer) ((guint8*) (self) + (glong) (CtkGears_private_offset )))); } GType ctk_gears_get_type (void) { static GType static_g_define_type_id = 0; if ((__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id ) == sizeof (gpointer), "Expression evaluates to false"); (void ) (0 ? (gpointer) * (&static_g_define_type_id) : ((void*) 0)); (!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id ) == sizeof (gpointer), "Expression evaluates to false"); __typeof__ (*(&static_g_define_type_id)) gapg_temp_newval; __typeof__ ((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id ); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5) ; gapg_temp_newval; })) && g_once_init_enter_pointer ( &static_g_define_type_id)); })) ) { GType g_define_type_id = ctk_gears_get_type_once (); (__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id) == sizeof (gpointer) , "Expression evaluates to false"); 0 ? (void) (*(&static_g_define_type_id ) = (g_define_type_id)) : (void) 0; g_once_init_leave_pointer ((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id )); })) ; } return static_g_define_type_id; } __attribute__ ( (__noinline__)) static GType ctk_gears_get_type_once (void) { GType g_define_type_id = g_type_register_static_simple ((ctk_gl_area_get_type ()), g_intern_static_string ("CtkGears"), sizeof (CtkGearsClass ), (GClassInitFunc)(void (*)(void)) ctk_gears_class_intern_init , sizeof (CtkGears), (GInstanceInitFunc)(void (*)(void)) ctk_gears_init , (GTypeFlags) 0); { {{ CtkGears_private_offset = g_type_add_instance_private (g_define_type_id, sizeof (CtkGearsPrivate)); };} } return g_define_type_id ; } |
126 | |
127 | static gboolean ctk_gears_render (CtkGLArea *area, |
128 | CdkGLContext *context); |
129 | static void ctk_gears_reshape (CtkGLArea *area, |
130 | int width, |
131 | int height); |
132 | static void ctk_gears_realize (CtkWidget *widget); |
133 | static void ctk_gears_unrealize (CtkWidget *widget); |
134 | static gboolean ctk_gears_tick (CtkWidget *widget, |
135 | CdkFrameClock *frame_clock, |
136 | gpointer user_data); |
137 | |
138 | static void destroy_gear (struct gear *g); |
139 | |
140 | CtkWidget * |
141 | ctk_gears_new (void) |
142 | { |
143 | return g_object_new (ctk_gears_get_type (), |
144 | "has-depth-buffer", TRUE(!(0)), |
145 | NULL((void*)0)); |
146 | } |
147 | |
148 | static void |
149 | ctk_gears_init (CtkGears *gears) |
150 | { |
151 | CtkGearsPrivate *priv = ctk_gears_get_instance_private (gears); |
152 | |
153 | priv->view_rot[CTK_GEARS_X_AXIS] = 20.0; |
154 | priv->view_rot[CTK_GEARS_Y_AXIS] = 30.0; |
155 | priv->view_rot[CTK_GEARS_Z_AXIS] = 20.0; |
156 | |
157 | priv->LightSourcePosition[0] = 5.0; |
158 | priv->LightSourcePosition[1] = 5.0; |
159 | priv->LightSourcePosition[2] = 10.0; |
160 | priv->LightSourcePosition[3] = 1.0; |
161 | |
162 | priv->tick = ctk_widget_add_tick_callback (CTK_WIDGET (gears)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((gears)), ((ctk_widget_get_type ())))))), ctk_gears_tick, gears, NULL((void*)0)); |
163 | } |
164 | |
165 | static void |
166 | ctk_gears_finalize (GObject *obj) |
167 | { |
168 | CtkGears *gears = CTK_GEARS (obj)((((CtkGears*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((obj)), ((ctk_gears_get_type ())))))); |
169 | CtkGearsPrivate *priv = ctk_gears_get_instance_private (gears); |
170 | |
171 | ctk_widget_remove_tick_callback (CTK_WIDGET (gears)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((gears)), ((ctk_widget_get_type ())))))), priv->tick); |
172 | |
173 | g_clear_object (&priv->fps_label)do { _Static_assert (sizeof *((&priv->fps_label)) == sizeof (gpointer), "Expression evaluates to false"); __typeof__ ((( &priv->fps_label))) _pp = ((&priv->fps_label)); __typeof__ (*((&priv->fps_label))) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_object_unref) (_ptr); } while (0); |
174 | |
175 | g_clear_pointer (&priv->gear1, destroy_gear)do { _Static_assert (sizeof *(&priv->gear1) == sizeof ( gpointer), "Expression evaluates to false"); __typeof__ ((& priv->gear1)) _pp = (&priv->gear1); __typeof__ (*(& priv->gear1)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (destroy_gear ) (_ptr); } while (0); |
176 | g_clear_pointer (&priv->gear2, destroy_gear)do { _Static_assert (sizeof *(&priv->gear2) == sizeof ( gpointer), "Expression evaluates to false"); __typeof__ ((& priv->gear2)) _pp = (&priv->gear2); __typeof__ (*(& priv->gear2)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (destroy_gear ) (_ptr); } while (0); |
177 | g_clear_pointer (&priv->gear3, destroy_gear)do { _Static_assert (sizeof *(&priv->gear3) == sizeof ( gpointer), "Expression evaluates to false"); __typeof__ ((& priv->gear3)) _pp = (&priv->gear3); __typeof__ (*(& priv->gear3)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (destroy_gear ) (_ptr); } while (0); |
178 | |
179 | G_OBJECT_CLASS (ctk_gears_parent_class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass *) ((ctk_gears_parent_class)), (((GType) ((20) << (2))) )))))->finalize (obj); |
180 | } |
181 | |
182 | static void |
183 | ctk_gears_class_init (CtkGearsClass *klass) |
184 | { |
185 | CTK_GL_AREA_CLASS (klass)((((CtkGLAreaClass*) (void *) g_type_check_class_cast ((GTypeClass *) ((klass)), ((ctk_gl_area_get_type ()))))))->render = ctk_gears_render; |
186 | CTK_GL_AREA_CLASS (klass)((((CtkGLAreaClass*) (void *) g_type_check_class_cast ((GTypeClass *) ((klass)), ((ctk_gl_area_get_type ()))))))->resize = ctk_gears_reshape; |
187 | |
188 | CTK_WIDGET_CLASS (klass)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass *) ((klass)), ((ctk_widget_get_type ()))))))->realize = ctk_gears_realize; |
189 | CTK_WIDGET_CLASS (klass)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass *) ((klass)), ((ctk_widget_get_type ()))))))->unrealize = ctk_gears_unrealize; |
190 | |
191 | G_OBJECT_CLASS (klass)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass *) ((klass)), (((GType) ((20) << (2))))))))->finalize = ctk_gears_finalize; |
192 | } |
193 | |
194 | /* |
195 | * Fills a gear vertex. |
196 | * |
197 | * @param v the vertex to fill |
198 | * @param x the x coordinate |
199 | * @param y the y coordinate |
200 | * @param z the z coortinate |
201 | * @param n pointer to the normal table |
202 | * |
203 | * @return the operation error code |
204 | */ |
205 | static GearVertex * |
206 | vert (GearVertex *v, |
207 | GLfloat x, |
208 | GLfloat y, |
209 | GLfloat z, |
210 | GLfloat n[3]) |
211 | { |
212 | v[0][0] = x; |
213 | v[0][1] = y; |
214 | v[0][2] = z; |
215 | v[0][3] = n[0]; |
216 | v[0][4] = n[1]; |
217 | v[0][5] = n[2]; |
218 | |
219 | return v + 1; |
220 | } |
221 | |
222 | static void |
223 | destroy_gear (struct gear *g) |
224 | { |
225 | g_free (g->strips); |
226 | g_free (g); |
227 | } |
228 | |
229 | /** |
230 | * Create a gear wheel. |
231 | * |
232 | * @param inner_radius radius of hole at center |
233 | * @param outer_radius radius at center of teeth |
234 | * @param width width of gear |
235 | * @param teeth number of teeth |
236 | * @param tooth_depth depth of tooth |
237 | * |
238 | * @return pointer to the constructed struct gear |
239 | */ |
240 | static struct gear * |
241 | create_gear (GLfloat inner_radius, |
242 | GLfloat outer_radius, |
243 | GLfloat width, |
244 | GLint teeth, |
245 | GLfloat tooth_depth) |
246 | { |
247 | GLfloat r0, r1, r2; |
248 | GLfloat da; |
249 | GearVertex *v; |
250 | struct gear *gear; |
251 | double s[5], c[5]; |
252 | GLfloat normal[3]; |
253 | int cur_strip = 0; |
254 | int i; |
255 | |
256 | /* Allocate memory for the gear */ |
257 | gear = g_malloc (sizeof *gear); |
258 | |
259 | /* Calculate the radii used in the gear */ |
260 | r0 = inner_radius; |
261 | r1 = outer_radius - tooth_depth / 2.0; |
262 | r2 = outer_radius + tooth_depth / 2.0; |
263 | |
264 | da = 2.0 * M_PI3.14159265358979323846 / teeth / 4.0; |
265 | |
266 | /* Allocate memory for the triangle strip information */ |
267 | gear->nstrips = STRIPS_PER_TOOTH7 * teeth; |
268 | gear->strips = g_malloc0_n (gear->nstrips, sizeof (*gear->strips)); |
269 | |
270 | /* Allocate memory for the vertices */ |
271 | gear->vertices = g_malloc0_n (VERTICES_PER_TOOTH34 * teeth, sizeof(*gear->vertices)); |
272 | v = gear->vertices; |
273 | |
274 | for (i = 0; i < teeth; i++) { |
275 | /* A set of macros for making the creation of the gears easier */ |
276 | #define GEAR_POINT(p, r, da)do { p.x = (r) * c[(da)]; p.y = (r) * s[(da)]; } while(0) do { p.x = (r) * c[(da)]; p.y = (r) * s[(da)]; } while(0) |
277 | #define SET_NORMAL(x, y, z)do { normal[0] = (x); normal[1] = (y); normal[2] = (z); } while (0) do { \ |
278 | normal[0] = (x); normal[1] = (y); normal[2] = (z); \ |
279 | } while(0) |
280 | |
281 | #define GEAR_VERT(v, point, sign)vert((v), p[(point)].x, p[(point)].y, (sign) * width * 0.5, normal ) vert((v), p[(point)].x, p[(point)].y, (sign) * width * 0.5, normal) |
282 | |
283 | #define START_STRIPdo { gear->strips[cur_strip].first = v - gear->vertices ; } while(0); do { \ |
284 | gear->strips[cur_strip].first = v - gear->vertices; \ |
285 | } while(0); |
286 | |
287 | #define END_STRIPdo { int _tmp = (v - gear->vertices); gear->strips[cur_strip ].count = _tmp - gear->strips[cur_strip].first; cur_strip++ ; } while (0) do { \ |
288 | int _tmp = (v - gear->vertices); \ |
289 | gear->strips[cur_strip].count = _tmp - gear->strips[cur_strip].first; \ |
290 | cur_strip++; \ |
291 | } while (0) |
292 | |
293 | #define QUAD_WITH_NORMAL(p1, p2)do { do { normal[0] = ((p[(p1)].y - p[(p2)].y)); normal[1] = ( -(p[(p1)].x - p[(p2)].x)); normal[2] = (0); } while(0); v = vert ((v), p[((p1))].x, p[((p1))].y, (-1) * width * 0.5, normal); v = vert((v), p[((p1))].x, p[((p1))].y, (1) * width * 0.5, normal ); v = vert((v), p[((p2))].x, p[((p2))].y, (-1) * width * 0.5 , normal); v = vert((v), p[((p2))].x, p[((p2))].y, (1) * width * 0.5, normal); } while(0) do { \ |
294 | SET_NORMAL((p[(p1)].y - p[(p2)].y), -(p[(p1)].x - p[(p2)].x), 0)do { normal[0] = ((p[(p1)].y - p[(p2)].y)); normal[1] = (-(p[ (p1)].x - p[(p2)].x)); normal[2] = (0); } while(0); \ |
295 | v = GEAR_VERT(v, (p1), -1)vert((v), p[((p1))].x, p[((p1))].y, (-1) * width * 0.5, normal ); \ |
296 | v = GEAR_VERT(v, (p1), 1)vert((v), p[((p1))].x, p[((p1))].y, (1) * width * 0.5, normal ); \ |
297 | v = GEAR_VERT(v, (p2), -1)vert((v), p[((p2))].x, p[((p2))].y, (-1) * width * 0.5, normal ); \ |
298 | v = GEAR_VERT(v, (p2), 1)vert((v), p[((p2))].x, p[((p2))].y, (1) * width * 0.5, normal ); \ |
299 | } while(0) |
300 | struct point { |
301 | GLfloat x; |
302 | GLfloat y; |
303 | }; |
304 | |
305 | /* Create the 7 points (only x,y coords) used to draw a tooth */ |
306 | struct point p[7]; |
307 | |
308 | /* Calculate needed sin/cos for varius angles */ |
309 | sincos(i * 2.0 * G_PI3.1415926535897932384626433832795028841971693993751 / teeth + da * 0, &s[0], &c[0]); |
310 | sincos(i * 2.0 * M_PI3.14159265358979323846 / teeth + da * 1, &s[1], &c[1]); |
311 | sincos(i * 2.0 * M_PI3.14159265358979323846 / teeth + da * 2, &s[2], &c[2]); |
312 | sincos(i * 2.0 * M_PI3.14159265358979323846 / teeth + da * 3, &s[3], &c[3]); |
313 | sincos(i * 2.0 * M_PI3.14159265358979323846 / teeth + da * 4, &s[4], &c[4]); |
314 | |
315 | GEAR_POINT(p[0], r2, 1)do { p[0].x = (r2) * c[(1)]; p[0].y = (r2) * s[(1)]; } while( 0); |
316 | GEAR_POINT(p[1], r2, 2)do { p[1].x = (r2) * c[(2)]; p[1].y = (r2) * s[(2)]; } while( 0); |
317 | GEAR_POINT(p[2], r1, 0)do { p[2].x = (r1) * c[(0)]; p[2].y = (r1) * s[(0)]; } while( 0); |
318 | GEAR_POINT(p[3], r1, 3)do { p[3].x = (r1) * c[(3)]; p[3].y = (r1) * s[(3)]; } while( 0); |
319 | GEAR_POINT(p[4], r0, 0)do { p[4].x = (r0) * c[(0)]; p[4].y = (r0) * s[(0)]; } while( 0); |
320 | GEAR_POINT(p[5], r1, 4)do { p[5].x = (r1) * c[(4)]; p[5].y = (r1) * s[(4)]; } while( 0); |
321 | GEAR_POINT(p[6], r0, 4)do { p[6].x = (r0) * c[(4)]; p[6].y = (r0) * s[(4)]; } while( 0); |
322 | |
323 | /* Front face */ |
324 | START_STRIPdo { gear->strips[cur_strip].first = v - gear->vertices ; } while(0);; |
325 | SET_NORMAL(0, 0, 1.0)do { normal[0] = (0); normal[1] = (0); normal[2] = (1.0); } while (0); |
326 | v = GEAR_VERT(v, 0, +1)vert((v), p[(0)].x, p[(0)].y, (+1) * width * 0.5, normal); |
327 | v = GEAR_VERT(v, 1, +1)vert((v), p[(1)].x, p[(1)].y, (+1) * width * 0.5, normal); |
328 | v = GEAR_VERT(v, 2, +1)vert((v), p[(2)].x, p[(2)].y, (+1) * width * 0.5, normal); |
329 | v = GEAR_VERT(v, 3, +1)vert((v), p[(3)].x, p[(3)].y, (+1) * width * 0.5, normal); |
330 | v = GEAR_VERT(v, 4, +1)vert((v), p[(4)].x, p[(4)].y, (+1) * width * 0.5, normal); |
331 | v = GEAR_VERT(v, 5, +1)vert((v), p[(5)].x, p[(5)].y, (+1) * width * 0.5, normal); |
332 | v = GEAR_VERT(v, 6, +1)vert((v), p[(6)].x, p[(6)].y, (+1) * width * 0.5, normal); |
333 | END_STRIPdo { int _tmp = (v - gear->vertices); gear->strips[cur_strip ].count = _tmp - gear->strips[cur_strip].first; cur_strip++ ; } while (0); |
334 | |
335 | /* Inner face */ |
336 | START_STRIPdo { gear->strips[cur_strip].first = v - gear->vertices ; } while(0);; |
337 | QUAD_WITH_NORMAL(4, 6)do { do { normal[0] = ((p[(4)].y - p[(6)].y)); normal[1] = (- (p[(4)].x - p[(6)].x)); normal[2] = (0); } while(0); v = vert ((v), p[((4))].x, p[((4))].y, (-1) * width * 0.5, normal); v = vert((v), p[((4))].x, p[((4))].y, (1) * width * 0.5, normal) ; v = vert((v), p[((6))].x, p[((6))].y, (-1) * width * 0.5, normal ); v = vert((v), p[((6))].x, p[((6))].y, (1) * width * 0.5, normal ); } while(0); |
338 | END_STRIPdo { int _tmp = (v - gear->vertices); gear->strips[cur_strip ].count = _tmp - gear->strips[cur_strip].first; cur_strip++ ; } while (0); |
339 | |
340 | /* Back face */ |
341 | START_STRIPdo { gear->strips[cur_strip].first = v - gear->vertices ; } while(0);; |
342 | SET_NORMAL(0, 0, -1.0)do { normal[0] = (0); normal[1] = (0); normal[2] = (-1.0); } while (0); |
343 | v = GEAR_VERT(v, 6, -1)vert((v), p[(6)].x, p[(6)].y, (-1) * width * 0.5, normal); |
344 | v = GEAR_VERT(v, 5, -1)vert((v), p[(5)].x, p[(5)].y, (-1) * width * 0.5, normal); |
345 | v = GEAR_VERT(v, 4, -1)vert((v), p[(4)].x, p[(4)].y, (-1) * width * 0.5, normal); |
346 | v = GEAR_VERT(v, 3, -1)vert((v), p[(3)].x, p[(3)].y, (-1) * width * 0.5, normal); |
347 | v = GEAR_VERT(v, 2, -1)vert((v), p[(2)].x, p[(2)].y, (-1) * width * 0.5, normal); |
348 | v = GEAR_VERT(v, 1, -1)vert((v), p[(1)].x, p[(1)].y, (-1) * width * 0.5, normal); |
349 | v = GEAR_VERT(v, 0, -1)vert((v), p[(0)].x, p[(0)].y, (-1) * width * 0.5, normal); |
350 | END_STRIPdo { int _tmp = (v - gear->vertices); gear->strips[cur_strip ].count = _tmp - gear->strips[cur_strip].first; cur_strip++ ; } while (0); |
351 | |
352 | /* Outer face */ |
353 | START_STRIPdo { gear->strips[cur_strip].first = v - gear->vertices ; } while(0);; |
354 | QUAD_WITH_NORMAL(0, 2)do { do { normal[0] = ((p[(0)].y - p[(2)].y)); normal[1] = (- (p[(0)].x - p[(2)].x)); normal[2] = (0); } while(0); v = vert ((v), p[((0))].x, p[((0))].y, (-1) * width * 0.5, normal); v = vert((v), p[((0))].x, p[((0))].y, (1) * width * 0.5, normal) ; v = vert((v), p[((2))].x, p[((2))].y, (-1) * width * 0.5, normal ); v = vert((v), p[((2))].x, p[((2))].y, (1) * width * 0.5, normal ); } while(0); |
355 | END_STRIPdo { int _tmp = (v - gear->vertices); gear->strips[cur_strip ].count = _tmp - gear->strips[cur_strip].first; cur_strip++ ; } while (0); |
356 | |
357 | START_STRIPdo { gear->strips[cur_strip].first = v - gear->vertices ; } while(0);; |
358 | QUAD_WITH_NORMAL(1, 0)do { do { normal[0] = ((p[(1)].y - p[(0)].y)); normal[1] = (- (p[(1)].x - p[(0)].x)); normal[2] = (0); } while(0); v = vert ((v), p[((1))].x, p[((1))].y, (-1) * width * 0.5, normal); v = vert((v), p[((1))].x, p[((1))].y, (1) * width * 0.5, normal) ; v = vert((v), p[((0))].x, p[((0))].y, (-1) * width * 0.5, normal ); v = vert((v), p[((0))].x, p[((0))].y, (1) * width * 0.5, normal ); } while(0); |
359 | END_STRIPdo { int _tmp = (v - gear->vertices); gear->strips[cur_strip ].count = _tmp - gear->strips[cur_strip].first; cur_strip++ ; } while (0); |
360 | |
361 | START_STRIPdo { gear->strips[cur_strip].first = v - gear->vertices ; } while(0);; |
362 | QUAD_WITH_NORMAL(3, 1)do { do { normal[0] = ((p[(3)].y - p[(1)].y)); normal[1] = (- (p[(3)].x - p[(1)].x)); normal[2] = (0); } while(0); v = vert ((v), p[((3))].x, p[((3))].y, (-1) * width * 0.5, normal); v = vert((v), p[((3))].x, p[((3))].y, (1) * width * 0.5, normal) ; v = vert((v), p[((1))].x, p[((1))].y, (-1) * width * 0.5, normal ); v = vert((v), p[((1))].x, p[((1))].y, (1) * width * 0.5, normal ); } while(0); |
363 | END_STRIPdo { int _tmp = (v - gear->vertices); gear->strips[cur_strip ].count = _tmp - gear->strips[cur_strip].first; cur_strip++ ; } while (0); |
364 | |
365 | START_STRIPdo { gear->strips[cur_strip].first = v - gear->vertices ; } while(0);; |
366 | QUAD_WITH_NORMAL(5, 3)do { do { normal[0] = ((p[(5)].y - p[(3)].y)); normal[1] = (- (p[(5)].x - p[(3)].x)); normal[2] = (0); } while(0); v = vert ((v), p[((5))].x, p[((5))].y, (-1) * width * 0.5, normal); v = vert((v), p[((5))].x, p[((5))].y, (1) * width * 0.5, normal) ; v = vert((v), p[((3))].x, p[((3))].y, (-1) * width * 0.5, normal ); v = vert((v), p[((3))].x, p[((3))].y, (1) * width * 0.5, normal ); } while(0); |
367 | END_STRIPdo { int _tmp = (v - gear->vertices); gear->strips[cur_strip ].count = _tmp - gear->strips[cur_strip].first; cur_strip++ ; } while (0); |
368 | } |
369 | |
370 | gear->nvertices = (v - gear->vertices); |
371 | |
372 | return gear; |
373 | } |
374 | |
375 | /** |
376 | * Multiplies two 4x4 matrices. |
377 | * |
378 | * The result is stored in matrix m. |
379 | * |
380 | * @param m the first matrix to multiply |
381 | * @param n the second matrix to multiply |
382 | */ |
383 | static void |
384 | multiply (GLfloat *m, const GLfloat *n) |
385 | { |
386 | GLfloat tmp[16]; |
387 | int i, j; |
388 | |
389 | for (i = 0; i < 16; i++) { |
390 | const GLfloat *row, *column; |
391 | div_t d; |
392 | |
393 | tmp[i] = 0; |
394 | d = div(i, 4); |
395 | row = n + d.quot * 4; |
396 | column = m + d.rem; |
397 | for (j = 0; j < 4; j++) |
398 | tmp[i] += row[j] * column[j * 4]; |
399 | } |
400 | memcpy(m, &tmp, sizeof tmp); |
401 | } |
402 | |
403 | /** |
404 | * Rotates a 4x4 matrix. |
405 | * |
406 | * @param[in,out] m the matrix to rotate |
407 | * @param angle the angle to rotate |
408 | * @param x the x component of the direction to rotate to |
409 | * @param y the y component of the direction to rotate to |
410 | * @param z the z component of the direction to rotate to |
411 | */ |
412 | static void |
413 | rotate(GLfloat *m, GLfloat angle, GLfloat x, GLfloat y, GLfloat z) |
414 | { |
415 | double s = sin (angle); |
416 | double c = cos (angle); |
417 | |
418 | GLfloat r[16] = { |
419 | x * x * (1 - c) + c, y * x * (1 - c) + z * s, x * z * (1 - c) - y * s, 0, |
420 | x * y * (1 - c) - z * s, y * y * (1 - c) + c, y * z * (1 - c) + x * s, 0, |
421 | x * z * (1 - c) + y * s, y * z * (1 - c) - x * s, z * z * (1 - c) + c, 0, |
422 | 0, 0, 0, 1 |
423 | }; |
424 | |
425 | multiply(m, r); |
426 | } |
427 | |
428 | /** |
429 | * Translates a 4x4 matrix. |
430 | * |
431 | * @param[in,out] m the matrix to translate |
432 | * @param x the x component of the direction to translate to |
433 | * @param y the y component of the direction to translate to |
434 | * @param z the z component of the direction to translate to |
435 | */ |
436 | static void |
437 | translate(GLfloat *m, GLfloat x, GLfloat y, GLfloat z) |
438 | { |
439 | GLfloat t[16] = { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, x, y, z, 1 }; |
440 | |
441 | multiply(m, t); |
442 | } |
443 | |
444 | /** |
445 | * Creates an identity 4x4 matrix. |
446 | * |
447 | * @param m the matrix make an identity matrix |
448 | */ |
449 | static void |
450 | identity(GLfloat *m) |
451 | { |
452 | GLfloat t[16] = { |
453 | 1.0, 0.0, 0.0, 0.0, |
454 | 0.0, 1.0, 0.0, 0.0, |
455 | 0.0, 0.0, 1.0, 0.0, |
456 | 0.0, 0.0, 0.0, 1.0, |
457 | }; |
458 | |
459 | memcpy(m, t, sizeof(t)); |
460 | } |
461 | |
462 | /** |
463 | * Transposes a 4x4 matrix. |
464 | * |
465 | * @param m the matrix to transpose |
466 | */ |
467 | static void |
468 | transpose(GLfloat *m) |
469 | { |
470 | GLfloat t[16] = { |
471 | m[0], m[4], m[8], m[12], |
472 | m[1], m[5], m[9], m[13], |
473 | m[2], m[6], m[10], m[14], |
474 | m[3], m[7], m[11], m[15]}; |
475 | |
476 | memcpy(m, t, sizeof(t)); |
477 | } |
478 | |
479 | /** |
480 | * Inverts a 4x4 matrix. |
481 | * |
482 | * This function can currently handle only pure translation-rotation matrices. |
483 | * Read http://www.gamedev.net/community/forums/topic.asp?topic_id=425118 |
484 | * for an explanation. |
485 | */ |
486 | static void |
487 | invert(GLfloat *m) |
488 | { |
489 | GLfloat t[16]; |
490 | identity(t); |
491 | |
492 | // Extract and invert the translation part 't'. The inverse of a |
493 | // translation matrix can be calculated by negating the translation |
494 | // coordinates. |
495 | t[12] = -m[12]; t[13] = -m[13]; t[14] = -m[14]; |
496 | |
497 | // Invert the rotation part 'r'. The inverse of a rotation matrix is |
498 | // equal to its transpose. |
499 | m[12] = m[13] = m[14] = 0; |
500 | transpose(m); |
501 | |
502 | // inv(m) = inv(r) * inv(t) |
503 | multiply(m, t); |
504 | } |
505 | |
506 | /** |
507 | * Calculate a perspective projection transformation. |
508 | * |
509 | * @param m the matrix to save the transformation in |
510 | * @param fovy the field of view in the y direction |
511 | * @param aspect the view aspect ratio |
512 | * @param zNear the near clipping plane |
513 | * @param zFar the far clipping plane |
514 | */ |
515 | void perspective(GLfloat *m, GLfloat fovy, GLfloat aspect, GLfloat zNear, GLfloat zFar) |
516 | { |
517 | GLfloat tmp[16]; |
518 | double sine, cosine, cotangent, deltaZ; |
519 | GLfloat radians = fovy / 2 * M_PI3.14159265358979323846 / 180; |
520 | identity(tmp); |
521 | |
522 | deltaZ = zFar - zNear; |
523 | sincos(radians, &sine, &cosine); |
524 | |
525 | if ((deltaZ == 0) || (sine == 0) || (aspect == 0)) |
526 | return; |
527 | |
528 | cotangent = cosine / sine; |
529 | |
530 | tmp[0] = cotangent / aspect; |
531 | tmp[5] = cotangent; |
532 | tmp[10] = -(zFar + zNear) / deltaZ; |
533 | tmp[11] = -1; |
534 | tmp[14] = -2 * zNear * zFar / deltaZ; |
535 | tmp[15] = 0; |
536 | |
537 | memcpy(m, tmp, sizeof(tmp)); |
538 | } |
539 | |
540 | /** |
541 | * Draws a gear. |
542 | * |
543 | * @param gear the gear to draw |
544 | * @param transform the current transformation matrix |
545 | * @param x the x position to draw the gear at |
546 | * @param y the y position to draw the gear at |
547 | * @param angle the rotation angle of the gear |
548 | * @param color the color of the gear |
549 | */ |
550 | static void |
551 | draw_gear(CtkGears *self, |
552 | struct gear *gear, |
553 | GLuint gear_vbo, |
554 | GLfloat *transform, |
555 | GLfloat x, |
556 | GLfloat y, |
557 | GLfloat angle, |
558 | const GLfloat color[4]) |
559 | { |
560 | CtkGearsPrivate *priv = ctk_gears_get_instance_private (self); |
561 | GLfloat model_view[16]; |
562 | GLfloat normal_matrix[16]; |
563 | GLfloat model_view_projection[16]; |
564 | int n; |
565 | |
566 | /* Translate and rotate the gear */ |
567 | memcpy(model_view, transform, sizeof (model_view)); |
568 | translate(model_view, x, y, 0); |
569 | rotate(model_view, 2 * G_PI3.1415926535897932384626433832795028841971693993751 * angle / 360.0, 0, 0, 1); |
570 | |
571 | /* Create and set the ModelViewProjectionMatrix */ |
572 | memcpy(model_view_projection, priv->ProjectionMatrix, sizeof(model_view_projection)); |
573 | multiply(model_view_projection, model_view); |
574 | |
575 | glUniformMatrix4fvepoxy_glUniformMatrix4fv(priv->ModelViewProjectionMatrix_location, 1, GL_FALSE0, |
576 | model_view_projection); |
577 | |
578 | /* |
579 | * Create and set the NormalMatrix. It's the inverse transpose of the |
580 | * ModelView matrix. |
581 | */ |
582 | memcpy(normal_matrix, model_view, sizeof (normal_matrix)); |
583 | invert(normal_matrix); |
584 | transpose(normal_matrix); |
585 | glUniformMatrix4fvepoxy_glUniformMatrix4fv(priv->NormalMatrix_location, 1, GL_FALSE0, normal_matrix); |
586 | |
587 | /* Set the gear color */ |
588 | glUniform4fvepoxy_glUniform4fv(priv->MaterialColor_location, 1, color); |
589 | |
590 | /* Set the vertex buffer object to use */ |
591 | glBindBufferepoxy_glBindBuffer(GL_ARRAY_BUFFER0x8892, gear_vbo); |
592 | |
593 | /* Set up the position of the attributes in the vertex buffer object */ |
594 | glVertexAttribPointerepoxy_glVertexAttribPointer(0, 3, GL_FLOAT0x1406, GL_FALSE0, 6 * sizeof(GLfloat), NULL((void*)0)); |
595 | glVertexAttribPointerepoxy_glVertexAttribPointer(1, 3, GL_FLOAT0x1406, GL_FALSE0, 6 * sizeof(GLfloat), (GLfloat *) 0 + 3); |
596 | |
597 | /* Enable the attributes */ |
598 | glEnableVertexAttribArrayepoxy_glEnableVertexAttribArray(0); |
599 | glEnableVertexAttribArrayepoxy_glEnableVertexAttribArray(1); |
600 | |
601 | /* Draw the triangle strips that comprise the gear */ |
602 | for (n = 0; n < gear->nstrips; n++) { |
603 | glDrawArraysepoxy_glDrawArrays(GL_TRIANGLE_STRIP0x0005, gear->strips[n].first, gear->strips[n].count); |
604 | } |
605 | |
606 | /* Disable the attributes */ |
607 | glDisableVertexAttribArrayepoxy_glDisableVertexAttribArray(1); |
608 | glDisableVertexAttribArrayepoxy_glDisableVertexAttribArray(0); |
609 | } |
610 | |
611 | /* new window size or exposure */ |
612 | static void |
613 | ctk_gears_reshape (CtkGLArea *area, int width, int height) |
614 | { |
615 | CtkGearsPrivate *priv = ctk_gears_get_instance_private ((CtkGears *) area); |
616 | |
617 | /* Update the projection matrix */ |
618 | perspective (priv->ProjectionMatrix, 60.0, width / (float)height, 1.0, 1024.0); |
619 | |
620 | /* Set the viewport */ |
621 | glViewportepoxy_glViewport (0, 0, (GLint) width, (GLint) height); |
622 | } |
623 | |
624 | static gboolean |
625 | ctk_gears_render (CtkGLArea *area, |
626 | CdkGLContext *context G_GNUC_UNUSED__attribute__ ((__unused__))) |
627 | { |
628 | static const GLfloat red[4] = { 0.8, 0.1, 0.0, 1.0 }; |
629 | static const GLfloat green[4] = { 0.0, 0.8, 0.2, 1.0 }; |
630 | static const GLfloat blue[4] = { 0.2, 0.2, 1.0, 1.0 }; |
631 | |
632 | CtkGears *self = CTK_GEARS (area)((((CtkGears*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((area)), ((ctk_gears_get_type ())))))); |
633 | CtkGearsPrivate *priv = ctk_gears_get_instance_private (self); |
634 | GLfloat transform[16]; |
635 | |
636 | identity (transform); |
637 | |
638 | glClearColorepoxy_glClearColor (0.0, 0.0, 0.0, 0.0); |
639 | glClearepoxy_glClear (GL_COLOR_BUFFER_BIT0x00004000 | GL_DEPTH_BUFFER_BIT0x00000100); |
640 | |
641 | /* Translate and rotate the view */ |
642 | translate (transform, 0, 0, -20); |
643 | rotate (transform, 2 * G_PI3.1415926535897932384626433832795028841971693993751 * priv->view_rot[0] / 360.0, 1, 0, 0); |
644 | rotate (transform, 2 * G_PI3.1415926535897932384626433832795028841971693993751 * priv->view_rot[1] / 360.0, 0, 1, 0); |
645 | rotate (transform, 2 * G_PI3.1415926535897932384626433832795028841971693993751 * priv->view_rot[2] / 360.0, 0, 0, 1); |
646 | |
647 | /* Draw the gears */ |
648 | draw_gear (self, priv->gear1, priv->gear_vbo[0], transform, -3.0, -2.0, priv->angle, red); |
649 | draw_gear (self, priv->gear2, priv->gear_vbo[1], transform, 3.1, -2.0, -2 * priv->angle - 9.0, green); |
650 | draw_gear (self, priv->gear3, priv->gear_vbo[2], transform, -3.1, 4.2, -2 * priv->angle - 25.0, blue); |
651 | |
652 | return TRUE(!(0)); |
653 | } |
654 | |
655 | static const char vertex_shader_gl[] = |
656 | "#version 330\n" |
657 | "\n" |
658 | "in vec3 position;\n" |
659 | "in vec3 normal;\n" |
660 | "\n" |
661 | "uniform mat4 ModelViewProjectionMatrix;\n" |
662 | "uniform mat4 NormalMatrix;\n" |
663 | "uniform vec4 LightSourcePosition;\n" |
664 | "uniform vec4 MaterialColor;\n" |
665 | "\n" |
666 | "smooth out vec4 Color;\n" |
667 | "\n" |
668 | "void main(void)\n" |
669 | "{\n" |
670 | " // Transform the normal to eye coordinates\n" |
671 | " vec3 N = normalize(vec3(NormalMatrix * vec4(normal, 1.0)));\n" |
672 | "\n" |
673 | " // The LightSourcePosition is actually its direction for directional light\n" |
674 | " vec3 L = normalize(LightSourcePosition.xyz);\n" |
675 | "\n" |
676 | " // Multiply the diffuse value by the vertex color (which is fixed in this case)\n" |
677 | " // to get the actual color that we will use to draw this vertex with\n" |
678 | " float diffuse = max(dot(N, L), 0.0);\n" |
679 | " Color = diffuse * MaterialColor;\n" |
680 | "\n" |
681 | " // Transform the position to clip coordinates\n" |
682 | " gl_Position = ModelViewProjectionMatrix * vec4(position, 1.0);\n" |
683 | "}"; |
684 | |
685 | static const char fragment_shader_gl[] = |
686 | "#version 330\n" |
687 | "\n" |
688 | "smooth in vec4 Color;\n" |
689 | "\n" |
690 | "out vec4 vertexColor;\n" |
691 | "\n" |
692 | "void main(void)\n" |
693 | "{\n" |
694 | " vertexColor = Color;\n" |
695 | "}"; |
696 | |
697 | static const char vertex_shader_gles[] = |
698 | "attribute vec3 position;\n" |
699 | "attribute vec3 normal;\n" |
700 | "\n" |
701 | "uniform mat4 ModelViewProjectionMatrix;\n" |
702 | "uniform mat4 NormalMatrix;\n" |
703 | "uniform vec4 LightSourcePosition;\n" |
704 | "uniform vec4 MaterialColor;\n" |
705 | "\n" |
706 | "varying vec4 Color;\n" |
707 | "\n" |
708 | "void main(void)\n" |
709 | "{\n" |
710 | " // Transform the normal to eye coordinates\n" |
711 | " vec3 N = normalize(vec3(NormalMatrix * vec4(normal, 1.0)));\n" |
712 | "\n" |
713 | " // The LightSourcePosition is actually its direction for directional light\n" |
714 | " vec3 L = normalize(LightSourcePosition.xyz);\n" |
715 | "\n" |
716 | " // Multiply the diffuse value by the vertex color (which is fixed in this case)\n" |
717 | " // to get the actual color that we will use to draw this vertex with\n" |
718 | " float diffuse = max(dot(N, L), 0.0);\n" |
719 | " Color = diffuse * MaterialColor;\n" |
720 | "\n" |
721 | " // Transform the position to clip coordinates\n" |
722 | " gl_Position = ModelViewProjectionMatrix * vec4(position, 1.0);\n" |
723 | "}"; |
724 | |
725 | static const char fragment_shader_gles[] = |
726 | "precision mediump float;\n" |
727 | "varying vec4 Color;\n" |
728 | "\n" |
729 | "void main(void)\n" |
730 | "{\n" |
731 | " gl_FragColor = Color;\n" |
732 | "}"; |
733 | |
734 | static void |
735 | ctk_gears_realize (CtkWidget *widget) |
736 | { |
737 | CtkGLArea *glarea = CTK_GL_AREA (widget)((((CtkGLArea*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((widget)), ((ctk_gl_area_get_type ())))))); |
738 | CtkGears *gears = CTK_GEARS (widget)((((CtkGears*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((widget)), ((ctk_gears_get_type ())))))); |
739 | CtkGearsPrivate *priv = ctk_gears_get_instance_private (gears); |
740 | CdkGLContext *context; |
741 | GLuint vao, v, f, program; |
742 | const char *p; |
743 | char msg[512]; |
744 | |
745 | CTK_WIDGET_CLASS (ctk_gears_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass *) ((ctk_gears_parent_class)), ((ctk_widget_get_type ()))))))->realize (widget); |
746 | |
747 | ctk_gl_area_make_current (glarea); |
748 | if (ctk_gl_area_get_error (glarea) != NULL((void*)0)) |
749 | return; |
750 | |
751 | context = ctk_gl_area_get_context (glarea); |
752 | |
753 | glEnableepoxy_glEnable (GL_CULL_FACE0x0B44); |
754 | glEnableepoxy_glEnable (GL_DEPTH_TEST0x0B71); |
755 | |
756 | /* Create the VAO */ |
757 | glGenVertexArraysepoxy_glGenVertexArrays (1, &vao); |
758 | glBindVertexArrayepoxy_glBindVertexArray (vao); |
759 | priv->vao = vao; |
760 | |
761 | /* Compile the vertex shader */ |
762 | if (cdk_gl_context_get_use_es (context)) |
763 | p = vertex_shader_gles; |
764 | else |
765 | p = vertex_shader_gl; |
766 | v = glCreateShaderepoxy_glCreateShader(GL_VERTEX_SHADER0x8B31); |
767 | glShaderSourceepoxy_glShaderSource(v, 1, &p, NULL((void*)0)); |
768 | glCompileShaderepoxy_glCompileShader(v); |
769 | glGetShaderInfoLogepoxy_glGetShaderInfoLog(v, sizeof msg, NULL((void*)0), msg); |
770 | g_print ("vertex shader info: %s\n", msg); |
771 | |
772 | /* Compile the fragment shader */ |
773 | if (cdk_gl_context_get_use_es (context)) |
774 | p = fragment_shader_gles; |
775 | else |
776 | p = fragment_shader_gl; |
777 | f = glCreateShaderepoxy_glCreateShader(GL_FRAGMENT_SHADER0x8B30); |
778 | glShaderSourceepoxy_glShaderSource(f, 1, &p, NULL((void*)0)); |
779 | glCompileShaderepoxy_glCompileShader(f); |
780 | glGetShaderInfoLogepoxy_glGetShaderInfoLog(f, sizeof msg, NULL((void*)0), msg); |
781 | g_print ("fragment shader info: %s\n", msg); |
782 | |
783 | /* Create and link the shader program */ |
784 | program = glCreateProgramepoxy_glCreateProgram(); |
785 | glAttachShaderepoxy_glAttachShader(program, v); |
786 | glAttachShaderepoxy_glAttachShader(program, f); |
787 | glBindAttribLocationepoxy_glBindAttribLocation(program, 0, "position"); |
788 | glBindAttribLocationepoxy_glBindAttribLocation(program, 1, "normal"); |
789 | |
790 | glLinkProgramepoxy_glLinkProgram(program); |
791 | glGetProgramInfoLogepoxy_glGetProgramInfoLog(program, sizeof msg, NULL((void*)0), msg); |
792 | g_print ("program info: %s\n", msg); |
793 | glDeleteShaderepoxy_glDeleteShader (v); |
794 | glDeleteShaderepoxy_glDeleteShader (f); |
795 | |
796 | /* Enable the shaders */ |
797 | glUseProgramepoxy_glUseProgram(program); |
798 | priv->program = program; |
799 | |
800 | /* Get the locations of the uniforms so we can access them */ |
801 | priv->ModelViewProjectionMatrix_location = glGetUniformLocationepoxy_glGetUniformLocation(program, "ModelViewProjectionMatrix"); |
802 | priv->NormalMatrix_location = glGetUniformLocationepoxy_glGetUniformLocation(program, "NormalMatrix"); |
803 | priv->LightSourcePosition_location = glGetUniformLocationepoxy_glGetUniformLocation(program, "LightSourcePosition"); |
804 | priv->MaterialColor_location = glGetUniformLocationepoxy_glGetUniformLocation(program, "MaterialColor"); |
805 | |
806 | /* Set the LightSourcePosition uniform which is constant throught the program */ |
807 | glUniform4fvepoxy_glUniform4fv(priv->LightSourcePosition_location, 1, priv->LightSourcePosition); |
808 | |
809 | /* make the gears */ |
810 | priv->gear1 = create_gear(1.0, 4.0, 1.0, 20, 0.7); |
811 | |
812 | /* Store the vertices in a vertex buffer object (VBO) */ |
813 | glGenBuffersepoxy_glGenBuffers (1, &(priv->gear_vbo[0])); |
814 | glBindBufferepoxy_glBindBuffer (GL_ARRAY_BUFFER0x8892, priv->gear_vbo[0]); |
815 | glBufferDataepoxy_glBufferData (GL_ARRAY_BUFFER0x8892, |
816 | priv->gear1->nvertices * sizeof(GearVertex), |
817 | priv->gear1->vertices, |
818 | GL_STATIC_DRAW0x88E4); |
819 | |
820 | priv->gear2 = create_gear(0.5, 2.0, 2.0, 10, 0.7); |
821 | glGenBuffersepoxy_glGenBuffers (1, &(priv->gear_vbo[1])); |
822 | glBindBufferepoxy_glBindBuffer (GL_ARRAY_BUFFER0x8892, priv->gear_vbo[1]); |
823 | glBufferDataepoxy_glBufferData (GL_ARRAY_BUFFER0x8892, |
824 | priv->gear2->nvertices * sizeof(GearVertex), |
825 | priv->gear2->vertices, |
826 | GL_STATIC_DRAW0x88E4); |
827 | |
828 | priv->gear3 = create_gear(1.3, 2.0, 0.5, 10, 0.7); |
829 | glGenBuffersepoxy_glGenBuffers (1, &(priv->gear_vbo[2])); |
830 | glBindBufferepoxy_glBindBuffer (GL_ARRAY_BUFFER0x8892, priv->gear_vbo[2]); |
831 | glBufferDataepoxy_glBufferData (GL_ARRAY_BUFFER0x8892, |
832 | priv->gear3->nvertices * sizeof(GearVertex), |
833 | priv->gear3->vertices, |
834 | GL_STATIC_DRAW0x88E4); |
835 | } |
836 | |
837 | static void |
838 | ctk_gears_unrealize (CtkWidget *widget) |
839 | { |
840 | CtkGLArea *glarea = CTK_GL_AREA (widget)((((CtkGLArea*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((widget)), ((ctk_gl_area_get_type ())))))); |
841 | CtkGearsPrivate *priv = ctk_gears_get_instance_private ((CtkGears *) widget); |
842 | |
843 | ctk_gl_area_make_current (glarea); |
844 | if (ctk_gl_area_get_error (glarea) != NULL((void*)0)) |
845 | return; |
846 | |
847 | /* Release the resources associated with OpenGL */ |
848 | if (priv->gear_vbo[0] != 0) |
849 | glDeleteBuffersepoxy_glDeleteBuffers (1, &(priv->gear_vbo[0])); |
850 | |
851 | if (priv->gear_vbo[1] != 0) |
852 | glDeleteBuffersepoxy_glDeleteBuffers (1, &(priv->gear_vbo[1])); |
853 | |
854 | if (priv->gear_vbo[2] != 0) |
855 | glDeleteBuffersepoxy_glDeleteBuffers (1, &(priv->gear_vbo[2])); |
856 | |
857 | if (priv->vao != 0) |
858 | glDeleteVertexArraysepoxy_glDeleteVertexArrays (1, &priv->vao); |
859 | |
860 | if (priv->program != 0) |
861 | glDeleteProgramepoxy_glDeleteProgram (priv->program); |
862 | |
863 | priv->ModelViewProjectionMatrix_location = 0; |
864 | priv->NormalMatrix_location = 0; |
865 | priv->LightSourcePosition_location = 0; |
866 | priv->MaterialColor_location = 0; |
867 | |
868 | CTK_WIDGET_CLASS (ctk_gears_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass *) ((ctk_gears_parent_class)), ((ctk_widget_get_type ()))))))->unrealize (widget); |
869 | } |
870 | |
871 | static gboolean |
872 | ctk_gears_tick (CtkWidget *widget, |
873 | CdkFrameClock *frame_clock, |
874 | gpointer user_data G_GNUC_UNUSED__attribute__ ((__unused__))) |
875 | { |
876 | CtkGears *gears = CTK_GEARS (widget)((((CtkGears*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((widget)), ((ctk_gears_get_type ())))))); |
877 | CtkGearsPrivate *priv = ctk_gears_get_instance_private (gears); |
878 | CdkFrameTimings *timings, *previous_timings; |
879 | gint64 previous_frame_time = 0; |
880 | gint64 frame_time; |
881 | gint64 history_start, history_len; |
882 | gint64 frame; |
883 | |
884 | frame = cdk_frame_clock_get_frame_counter (frame_clock); |
885 | frame_time = cdk_frame_clock_get_frame_time (frame_clock); |
886 | |
887 | if (priv->first_frame_time == 0) |
888 | { |
889 | /* No need for changes on first frame */ |
890 | priv->first_frame_time = frame_time; |
891 | if (priv->fps_label) |
892 | ctk_label_set_label (priv->fps_label, "FPS: ---"); |
893 | return G_SOURCE_CONTINUE(!(0)); |
894 | } |
895 | |
896 | /* glxgears advances 70 degrees per second, so do the same */ |
897 | |
898 | priv->angle = fmod ((frame_time - priv->first_frame_time) / (double)G_USEC_PER_SEC1000000 * 70.0, 360.0); |
899 | |
900 | ctk_widget_queue_draw (widget); |
901 | |
902 | history_start = cdk_frame_clock_get_history_start (frame_clock); |
903 | |
904 | if (priv->fps_label && frame % 60 == 0) |
905 | { |
906 | history_len = frame - history_start; |
907 | if (history_len > 0) |
908 | { |
909 | char *s; |
910 | |
911 | previous_timings = cdk_frame_clock_get_timings (frame_clock, frame - history_len); |
912 | previous_frame_time = cdk_frame_timings_get_frame_time (previous_timings); |
913 | |
914 | s = g_strdup_printf ("FPS: %-4.1f", (G_USEC_PER_SEC1000000 * history_len) / (double)(frame_time - previous_frame_time)); |
915 | ctk_label_set_label (priv->fps_label, s); |
916 | g_free (s); |
917 | } |
918 | } |
919 | |
920 | timings = cdk_frame_clock_get_current_timings (frame_clock); |
921 | previous_timings = cdk_frame_clock_get_timings (frame_clock, |
922 | cdk_frame_timings_get_frame_counter (timings) - 1); |
923 | if (previous_timings != NULL((void*)0)) |
924 | previous_frame_time = cdk_frame_timings_get_frame_time (previous_timings); |
Value stored to 'previous_frame_time' is never read | |
925 | |
926 | return G_SOURCE_CONTINUE(!(0)); |
927 | } |
928 | |
929 | void |
930 | ctk_gears_set_axis (CtkGears *gears, int axis, double value) |
931 | { |
932 | CtkGearsPrivate *priv = ctk_gears_get_instance_private (gears); |
933 | |
934 | if (axis < 0 || axis >= CTK_GEARS_N_AXIS) |
935 | return; |
936 | |
937 | priv->view_rot[axis] = value; |
938 | |
939 | ctk_widget_queue_draw (CTK_WIDGET (gears)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((gears)), ((ctk_widget_get_type ()))))))); |
940 | } |
941 | |
942 | double |
943 | ctk_gears_get_axis (CtkGears *gears, int axis) |
944 | { |
945 | CtkGearsPrivate *priv = ctk_gears_get_instance_private (gears); |
946 | |
947 | if (axis < 0 || axis >= CTK_GEARS_N_AXIS) |
948 | return 0.0; |
949 | |
950 | return priv->view_rot[axis]; |
951 | } |
952 | |
953 | void |
954 | ctk_gears_set_fps_label (CtkGears *gears, CtkLabel *label) |
955 | { |
956 | CtkGearsPrivate *priv = ctk_gears_get_instance_private (gears); |
957 | |
958 | if (label) |
959 | g_object_ref (label)((__typeof__ (label)) (g_object_ref) (label)); |
960 | |
961 | g_clear_object (&priv->fps_label)do { _Static_assert (sizeof *((&priv->fps_label)) == sizeof (gpointer), "Expression evaluates to false"); __typeof__ ((( &priv->fps_label))) _pp = ((&priv->fps_label)); __typeof__ (*((&priv->fps_label))) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_object_unref) (_ptr); } while (0); |
962 | |
963 | priv->fps_label = label; |
964 | } |