]> Pileus Git - grits/blob - examples/sorting/sort.c
Debugging and code formatting
[grits] / examples / sorting / sort.c
1 #include <gtk/gtk.h>
2 #include <gtk/gtkgl.h>
3 #include <gdk/gdkkeysyms.h>
4 #include <GL/gl.h>
5 #include <GL/glu.h>
6 #include <stdlib.h>
7
8 typedef struct {
9         gfloat xyz[3];
10         gfloat color[4];
11 } __attribute__ ((packed)) vert_t;
12
13 static int sort_cmp(const void *a, const void *b)
14 {
15         vert_t *a_verts = (vert_t*)(((gfloat*)a)+2);
16         vert_t *b_verts = (vert_t*)(((gfloat*)b)+2);
17         gfloat a_sum = a_verts[0].xyz[2] + a_verts[1].xyz[2] + a_verts[2].xyz[2];
18         gfloat b_sum = b_verts[0].xyz[2] + b_verts[1].xyz[2] + b_verts[2].xyz[2];
19         return a_sum == b_sum ? 0 :
20                a_sum <  b_sum ? 1 : -1;
21 }
22
23 static gfloat *sort_start()
24 {
25         int size = 1000000;
26         gfloat *data = g_new0(gfloat, size);
27         glFeedbackBuffer(size, GL_3D_COLOR, data);
28         glRenderMode(GL_FEEDBACK);
29         g_print("1st = %f\n", data[0]);
30         return data;
31 }
32
33 static void sort_end(gfloat *data)
34 {
35         int vertsize = sizeof(vert_t)/sizeof(gfloat);
36         int nvals = glRenderMode(GL_RENDER);
37
38         /* Set up screen coords */
39         gint view[4];
40         glGetIntegerv(GL_VIEWPORT, view);
41
42         glMatrixMode(GL_PROJECTION);
43         glLoadIdentity();
44         glOrtho(view[0],view[2], view[1],view[3], -10,10);
45
46         glMatrixMode(GL_MODELVIEW);
47         glLoadIdentity();
48         glDisable(GL_LIGHTING);
49
50         /* Sort the vertexes (this only works with all-triangles */
51         int trisize = 2*sizeof(gfloat) + 3*sizeof(vert_t);
52         int ntris   = nvals*sizeof(gfloat) / trisize;
53         g_print("%d, %d, %d\n", sizeof(gfloat), trisize, ntris);
54         qsort(data, ntris, trisize, sort_cmp);
55
56         /* Draw the data */
57         for (int i = 0; i < nvals;) {
58                 gfloat token = data[i++];
59                 if (token == GL_POLYGON_TOKEN) {
60                         gfloat n = data[i++];
61                         vert_t *verts = (vert_t*)&data[i];
62                         i += n*vertsize;
63                         //g_print("GL_POLYGON_TOKEN: %f\n", n);
64
65                         /* Draw triangle */
66                         glBegin(GL_TRIANGLES);
67                         for (int j = 0; j < n; j++) {
68                                 //g_print("\t%f, %f, %f\n",
69                                 //      verts[j].xyz[0],
70                                 //      verts[j].xyz[1],
71                                 //      verts[j].xyz[2]);
72                                 glColor4fv(verts[j].color);
73                                 glVertex3fv(verts[j].xyz);
74                         }
75                         glEnd();
76
77                         /* Draw line */
78                         glColor4f(1,1,1,1);
79                         glBegin(GL_LINE_LOOP);
80                         for (int j = 0; j < n; j++)
81                                 glVertex3fv(verts[j].xyz);
82                         glEnd();
83                 } else {
84                         g_error("Unknown token: %f\n", token);
85                 }
86         }
87         g_free(data);
88 }
89
90 static gboolean on_expose(GtkWidget *drawing, GdkEventExpose *event, gpointer _)
91 {
92         //glClearColor(0.5, 0.5, 1.0, 1.0);
93         glClearColor(0.0, 0.0, 0.0, 0.0);
94         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
95
96         glEnable(GL_BLEND);
97
98         /* Blend, but broken sorting */
99         //glEnable(GL_DEPTH_TEST);
100         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
101
102         /* No sorting, just add */
103         //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
104         //glBlendFunc(GL_ONE, GL_ONE);
105
106         /* Lighting */
107         float light_ambient[]  = {0.1f, 0.1f, 0.0f, 1.0f};
108         float light_diffuse[]  = {0.9f, 0.9f, 0.9f, 1.0f};
109         float light_position[] = {-30.0f, 50.0f, 40.0f, 1.0f};
110         glLightfv(GL_LIGHT0, GL_AMBIENT,  light_ambient);
111         glLightfv(GL_LIGHT0, GL_DIFFUSE,  light_diffuse);
112         glLightfv(GL_LIGHT0, GL_POSITION, light_position);
113         glEnable(GL_COLOR_MATERIAL);
114         glEnable(GL_LIGHTING);
115         glEnable(GL_LIGHT0);
116
117         /* Set up projection */
118         glMatrixMode(GL_PROJECTION);
119         glLoadIdentity();
120         glOrtho(1,-1, -0.7,0.7, -10,10);
121
122         /* Draw teapots */
123         glMatrixMode(GL_MODELVIEW);
124
125         gfloat *data = sort_start();
126         glLoadIdentity();
127         glTranslatef(0.05, 0.05, -2);
128         glRotatef(30, 1, -1, -0.2);
129         glColor4f(1.0, 0.2, 0.2, 0.6);
130         gdk_gl_draw_teapot(TRUE, 0.5);
131
132         glLoadIdentity();
133         glTranslatef(-0.2, -0.05, -2);
134         glRotatef(30, 1, -1, -0.2);
135         glColor4f(0.2, 0.2, 1.0, 0.6);
136         gdk_gl_draw_teapot(TRUE, 0.5);
137         sort_end(data);
138
139         /* Flush */
140         GdkGLDrawable *gldrawable = gdk_gl_drawable_get_current();
141         if (gdk_gl_drawable_is_double_buffered(gldrawable))
142                 gdk_gl_drawable_swap_buffers(gldrawable);
143         else
144                 glFlush();
145         return FALSE;
146 }
147
148 static gboolean on_configure(GtkWidget *drawing, GdkEventConfigure *event, gpointer _)
149 {
150         glViewport(0, 0,
151                 drawing->allocation.width,
152                 drawing->allocation.height);
153         return FALSE;
154 }
155
156 static gboolean on_key_press(GtkWidget *widget, GdkEventKey *event, gpointer _)
157 {
158         if (event->keyval == GDK_q)
159                 gtk_main_quit();
160         return FALSE;
161 }
162
163 int main(int argc, char **argv)
164 {
165         gtk_init(&argc, &argv);
166
167         GtkWidget   *window   = gtk_window_new(GTK_WINDOW_TOPLEVEL);
168         GtkWidget   *drawing  = gtk_drawing_area_new();
169         GdkGLConfig *glconfig = gdk_gl_config_new_by_mode((GdkGLConfigMode)(
170                         GDK_GL_MODE_RGBA   | GDK_GL_MODE_DEPTH |
171                         GDK_GL_MODE_DOUBLE | GDK_GL_MODE_ALPHA));
172         g_signal_connect(window,  "destroy",         G_CALLBACK(gtk_main_quit), NULL);
173         g_signal_connect(window,  "key-press-event", G_CALLBACK(on_key_press),  NULL);
174         g_signal_connect(drawing, "expose-event",    G_CALLBACK(on_expose),     NULL);
175         g_signal_connect(drawing, "configure-event", G_CALLBACK(on_configure),  NULL);
176         gtk_widget_set_gl_capability(drawing, glconfig, NULL, TRUE, GDK_GL_RGBA_TYPE);
177         gtk_container_add(GTK_CONTAINER(window), drawing);
178         gtk_widget_show_all(window);
179
180         /* OpenGL setup */
181         GdkGLContext  *glcontext  = gtk_widget_get_gl_context(GTK_WIDGET(drawing));
182         GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable(GTK_WIDGET(drawing));
183         gdk_gl_drawable_gl_begin(gldrawable, glcontext);
184
185         gtk_main();
186
187         gdk_gl_drawable_gl_end(gldrawable);
188 }