1 /*
2 * File: mat_preview.c
3 *
4 * Description: displays a preview of the material attributes passed to it
5 *
6 * This source code is part of kludge3d, and is released under the
7 * GNU General Public License.
8 *
9 *
10 */
11
12 /* Note: this file is based on:
13 * simple.c, written by Naofumi Yasufuku <naofumi@users.sourceforge.net>
14 * ...which is one of the example programs packaged with gtkglext.
15 * I grabbed the checkered-background interleaved array (backer_square) from
16 * me3d's gtk_gl_tex_preview.
17 *
18 * This widget is intended as a simple replacement for me3d's
19 * gtk_gl_tex_preview. The ultimate goal is to make it easier to port me3d's
20 * mat_edit to kludge3d.
21 *
22 * Note: Unlike me3d's gtk_gl_tex_preview, this widget is for output only.
23 * You can not *retrieve* the material attributes from the widget; you can
24 * only *set* the attributes.
25 */
26
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30
31 #include <gtk/gtk.h>
32 #include <gtk/gtkgl.h>
33 #ifdef G_OS_WIN32
34 #define WIN32_LEAN_AND_MEAN 1
35 #include <windows.h>
36 #endif
37 #include <GL/gl.h>
38 #include <GL/glu.h>
39
40 #include "mat_preview.h"
41 #include "material.h"
42
43 #ifdef MEMWATCH
44 #include "memwatch.h"
45 #endif
46
47
48 #define MAT_PREVIEW_SPHERE_DISPLIST 1
49 #define MAT_PREVIEW_DRAW_CHECKERED_BACKGROUND 1
50
51
52 static GLfloat backer_square[] = {
53 0.50, 0.50, 0.50, 1.0, 0.0, 0.0, -1.0, -100.0, 100.0, 0.0,
54 0.50, 0.50, 0.50, 1.0, 0.0, 0.0, -1.0, -100.0, 0.0, 0.0,
55 0.50, 0.50, 0.50, 1.0, 0.0, 0.0, -1.0, 0.0, 0.0, 0.0,
56 0.50, 0.50, 0.50, 1.0, 0.0, 0.0, -1.0, 0.0, 100.0, 0.0,
57 0.75, 0.75, 0.75, 1.0, 0.0, 0.0, -1.0, 0.0, 100.0, 0.0,
58 0.75, 0.75, 0.75, 1.0, 0.0, 0.0, -1.0, 0.0, 0.0, 0.0,
59 0.75, 0.75, 0.75, 1.0, 0.0, 0.0, -1.0, 100.0, 0.0, 0.0,
60 0.75, 0.75, 0.75, 1.0, 0.0, 0.0, -1.0, 100.0, 100.0, 0.0,
61 0.75, 0.75, 0.75, 1.0, 0.0, 0.0, -1.0, -100.0, 0.0, 0.0,
62 0.75, 0.75, 0.75, 1.0, 0.0, 0.0, -1.0, -100.0, -100.0, 0.0,
63 0.75, 0.75, 0.75, 1.0, 0.0, 0.0, -1.0, 0.0, -100.0, 0.0,
64 0.75, 0.75, 0.75, 1.0, 0.0, 0.0, -1.0, 0.0, 0.0, 0.0,
65 0.50, 0.50, 0.50, 1.0, 0.0, 0.0, -1.0, 0.0, 0.0, 0.0,
66 0.50, 0.50, 0.50, 1.0, 0.0, 0.0, -1.0, 0.0, -100.0, 0.0,
67 0.50, 0.50, 0.50, 1.0, 0.0, 0.0, -1.0, 100.0, -100.0, 0.0,
68 0.50, 0.50, 0.50, 1.0, 0.0, 0.0, -1.0, 100.0, 0.0, 0.0,
69 }; /* C4F_N3F_V3F with CCW polygons */
70
71
72
73 gboolean matpreview_free_attr(
74 GtkWidget *widget, gpointer data );
75
76
77 static void
matpreview_realize(GtkWidget * widget,gpointer data)78 matpreview_realize( GtkWidget *widget, gpointer data )
79 {
80 GdkGLContext *glcontext = gtk_widget_get_gl_context (widget);
81 GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable (widget);
82
83 GLUquadricObj *qobj;
84 static GLfloat light_diffuse[] = {1.0, 1.0, 1.0, 1.0};
85 static GLfloat light_position[] = {1.0, 1.0, 1.0, 0.0};
86 GLfloat aspect = 1.0;
87 int width, height;
88
89 /*** OpenGL BEGIN ***/
90 if (!gdk_gl_drawable_gl_begin (gldrawable, glcontext))
91 return;
92
93 width = widget->allocation.width;
94 height = widget->allocation.height;
95
96 qobj = gluNewQuadric ();
97 gluQuadricDrawStyle (qobj, GLU_FILL);
98 glNewList (MAT_PREVIEW_SPHERE_DISPLIST, GL_COMPILE);
99 gluSphere (qobj, 1.0, 20, 20);
100 glEndList ();
101
102 glLightfv (GL_LIGHT0, GL_DIFFUSE, light_diffuse);
103 glLightfv (GL_LIGHT0, GL_POSITION, light_position);
104 glEnable (GL_LIGHTING);
105 glEnable (GL_LIGHT0);
106
107 glEnable (GL_DEPTH_TEST);
108
109 glClearColor (0.50, 0.50, 0.50, 1.0);
110 glClearDepth (1.0);
111
112 glViewport (0, 0, width, height);
113 aspect = (GLfloat)width / (GLfloat)height;
114
115 glMatrixMode (GL_PROJECTION);
116 glLoadIdentity ();
117 gluPerspective (40.0, (GLdouble)aspect, 1.0, 10.0);
118
119 glMatrixMode (GL_MODELVIEW);
120 glLoadIdentity ();
121 gluLookAt( 0.0, 0.0, 3.0,
122 0.0, 0.0, 0.0,
123 0.0, 1.0, 0.0 );
124 glTranslatef (0.0, 0.0, -2.0);
125
126 gdk_gl_drawable_gl_end (gldrawable);
127 /*** OpenGL END ***/
128 }
129
130 static gboolean
matpreview_configure_event(GtkWidget * widget,GdkEventConfigure * event,gpointer data)131 matpreview_configure_event(
132 GtkWidget *widget, GdkEventConfigure *event, gpointer data )
133 {
134 GdkGLContext *glcontext = gtk_widget_get_gl_context (widget);
135 GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable (widget);
136
137 /*** OpenGL BEGIN ***/
138 if (!gdk_gl_drawable_gl_begin (gldrawable, glcontext))
139 return FALSE;
140
141 glViewport (0, 0,
142 widget->allocation.width, widget->allocation.height);
143
144 gdk_gl_drawable_gl_end (gldrawable);
145 /*** OpenGL END ***/
146
147 return TRUE;
148 }
149
150 static gboolean
matpreview_expose_event(GtkWidget * widget,GdkEventExpose * event,gpointer data)151 matpreview_expose_event(
152 GtkWidget *widget, GdkEventExpose *event, gpointer data )
153 {
154 GdkGLContext *glcontext = gtk_widget_get_gl_context (widget);
155 GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable (widget);
156 Material *mp_attr;
157
158 /*** OpenGL BEGIN ***/
159 if (!gdk_gl_drawable_gl_begin (gldrawable, glcontext))
160 return FALSE;
161
162 #if MAT_PREVIEW_DRAW_CHECKERED_BACKGROUND
163 glClear (GL_DEPTH_BUFFER_BIT);
164 glDisable(GL_LIGHTING);
165 glInterleavedArrays(GL_C4F_N3F_V3F, 0, backer_square);
166 glDrawArrays(GL_QUADS, 0, 16);
167 glEnable(GL_LIGHTING);
168 #else
169 glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
170 #endif
171
172 mp_attr = (Material *)
173 g_object_get_data( G_OBJECT( widget ), "user-data" );
174
175 glMaterialfv(GL_FRONT, GL_AMBIENT, mp_attr->ambient);
176 glMaterialfv(GL_FRONT, GL_DIFFUSE, mp_attr->diffuse);
177 glMaterialfv(GL_FRONT, GL_SPECULAR, mp_attr->specular);
178 glMaterialfv(GL_FRONT, GL_EMISSION, mp_attr->emission);
179 glMaterialf(GL_FRONT, GL_SHININESS, mp_attr->shininess);
180
181 glCallList ( MAT_PREVIEW_SPHERE_DISPLIST );
182
183 if (gdk_gl_drawable_is_double_buffered (gldrawable))
184 gdk_gl_drawable_swap_buffers (gldrawable);
185 else
186 glFlush ();
187
188 gdk_gl_drawable_gl_end (gldrawable);
189 /*** OpenGL END ***/
190
191 return TRUE;
192 }
193
194
mat_preview_new(void)195 GtkWidget *mat_preview_new( void )
196 {
197 GdkGLConfig *glconfig;
198 GtkWidget *drawing_area;
199 Material *mp_attr;
200
201 /*
202 * Configure OpenGL-capable visual.
203 */
204
205 /* Try double-buffered visual */
206 glconfig = gdk_gl_config_new_by_mode (
207 GDK_GL_MODE_RGB |
208 GDK_GL_MODE_DEPTH |
209 GDK_GL_MODE_DOUBLE);
210
211 if (glconfig == NULL) {
212 fprintf( stderr, "*** Cannot find the double-buffered visual.\n");
213 fprintf( stderr, "*** Trying single-buffered visual.\n");
214
215 /* Try single-buffered visual */
216 glconfig = gdk_gl_config_new_by_mode (
217 GDK_GL_MODE_RGB |
218 GDK_GL_MODE_DEPTH );
219 if (glconfig == NULL) {
220 fprintf( stderr, "*** No appropriate OpenGL-capable visual found.\n" );
221 return NULL;
222 }
223 }
224
225 /*
226 * Drawing area for drawing OpenGL scene.
227 */
228
229 drawing_area = gtk_drawing_area_new ();
230 gtk_widget_set_size_request (drawing_area, 200, 200);
231
232 /* Set OpenGL-capability to the widget. */
233 gtk_widget_set_gl_capability (drawing_area,
234 glconfig,
235 NULL,
236 TRUE,
237 GDK_GL_RGBA_TYPE);
238
239 mp_attr = material_new();
240
241 g_object_set_data( G_OBJECT( drawing_area ), "user-data", mp_attr );
242 g_signal_connect (G_OBJECT (drawing_area), "destroy",
243 G_CALLBACK (matpreview_free_attr), mp_attr );
244
245 g_signal_connect_after (G_OBJECT (drawing_area), "realize",
246 G_CALLBACK (matpreview_realize), NULL);
247 g_signal_connect (G_OBJECT (drawing_area), "configure_event",
248 G_CALLBACK (matpreview_configure_event), NULL);
249 g_signal_connect (G_OBJECT (drawing_area), "expose_event",
250 G_CALLBACK (matpreview_expose_event), NULL);
251
252 gtk_widget_show (drawing_area);
253
254 return drawing_area;
255 }
256
257
mat_preview_set_all(GtkWidget * widget,Material * material)258 void mat_preview_set_all( GtkWidget *widget, Material *material ) {
259 Material *mp_attr;
260
261 mp_attr = (Material *)
262 g_object_get_data( G_OBJECT( widget ), "user-data" );
263 if( mp_attr == NULL )
264 return;
265
266 material_copy( mp_attr, material );
267
268 gtk_widget_queue_draw( widget );
269 }
270
271
mat_preview_set_ambient(GtkWidget * widget,float * ambient)272 void mat_preview_set_ambient( GtkWidget *widget, float *ambient ) {
273 Material *mp_attr;
274
275 mp_attr = (Material *)
276 g_object_get_data( G_OBJECT( widget ), "user-data" );
277 if( mp_attr == NULL )
278 return;
279
280 mp_attr->ambient[0] = ambient[0];
281 mp_attr->ambient[1] = ambient[1];
282 mp_attr->ambient[2] = ambient[2];
283 mp_attr->ambient[3] = ambient[3];
284
285 gtk_widget_queue_draw( widget );
286 }
287
288
mat_preview_set_diffuse(GtkWidget * widget,float * diffuse)289 void mat_preview_set_diffuse( GtkWidget *widget, float *diffuse ) {
290 Material *mp_attr;
291
292 mp_attr = (Material *)
293 g_object_get_data( G_OBJECT( widget ), "user-data" );
294 if( mp_attr == NULL )
295 return;
296
297 mp_attr->diffuse[0] = diffuse[0];
298 mp_attr->diffuse[1] = diffuse[1];
299 mp_attr->diffuse[2] = diffuse[2];
300 mp_attr->diffuse[3] = diffuse[3];
301
302 gtk_widget_queue_draw( widget );
303 }
304
305
mat_preview_set_specular(GtkWidget * widget,float * specular)306 void mat_preview_set_specular( GtkWidget *widget, float *specular ) {
307 Material *mp_attr;
308
309 mp_attr = (Material *)
310 g_object_get_data( G_OBJECT( widget ), "user-data" );
311 if( mp_attr == NULL )
312 return;
313
314 mp_attr->specular[0] = specular[0];
315 mp_attr->specular[1] = specular[1];
316 mp_attr->specular[2] = specular[2];
317 mp_attr->specular[3] = specular[3];
318
319 gtk_widget_queue_draw( widget );
320 }
321
322
mat_preview_set_emission(GtkWidget * widget,float * emission)323 void mat_preview_set_emission( GtkWidget *widget, float *emission ) {
324 Material *mp_attr;
325
326 mp_attr = (Material *)
327 g_object_get_data( G_OBJECT( widget ), "user-data" );
328 if( mp_attr == NULL )
329 return;
330
331 mp_attr->emission[0] = emission[0];
332 mp_attr->emission[1] = emission[1];
333 mp_attr->emission[2] = emission[2];
334 mp_attr->emission[3] = emission[3];
335
336 gtk_widget_queue_draw( widget );
337 }
338
339
mat_preview_set_shininess(GtkWidget * widget,float shininess)340 void mat_preview_set_shininess( GtkWidget *widget, float shininess ) {
341 Material *mp_attr;
342
343 mp_attr = (Material *)
344 g_object_get_data( G_OBJECT( widget ), "user-data" );
345 if( mp_attr == NULL )
346 return;
347
348 mp_attr->shininess = shininess;
349
350 gtk_widget_queue_draw( widget );
351 }
352
353
matpreview_free_attr(GtkWidget * widget,gpointer data)354 gboolean matpreview_free_attr(
355 GtkWidget *widget, gpointer data )
356 {
357 free( data );
358 return FALSE;
359 }
360
361
362 /**************************************************************************
363
364 DEAD CODE
365
366 ***************************************************************************/
367
368 #if 0
369
370 static void
371 print_gl_config_attrib (GdkGLConfig *glconfig,
372 const gchar *attrib_str,
373 int attrib,
374 gboolean is_boolean)
375 {
376 int value;
377
378 g_print ("%s = ", attrib_str);
379 if (gdk_gl_config_get_attrib (glconfig, attrib, &value))
380 {
381 if (is_boolean)
382 g_print ("%s\n", value == TRUE ? "TRUE" : "FALSE");
383 else
384 g_print ("%d\n", value);
385 }
386 else
387 g_print ("*** Cannot get %s attribute value\n", attrib_str);
388 }
389
390 static void
391 examine_gl_config_attrib (GdkGLConfig *glconfig)
392 {
393 g_print ("\nOpenGL visual configurations :\n\n");
394
395 g_print ("gdk_gl_config_is_rgba (glconfig) = %s\n",
396 gdk_gl_config_is_rgba (glconfig) ? "TRUE" : "FALSE");
397 g_print ("gdk_gl_config_is_double_buffered (glconfig) = %s\n",
398 gdk_gl_config_is_double_buffered (glconfig) ? "TRUE" : "FALSE");
399 g_print ("gdk_gl_config_is_stereo (glconfig) = %s\n",
400 gdk_gl_config_is_stereo (glconfig) ? "TRUE" : "FALSE");
401 g_print ("gdk_gl_config_has_alpha (glconfig) = %s\n",
402 gdk_gl_config_has_alpha (glconfig) ? "TRUE" : "FALSE");
403 g_print ("gdk_gl_config_has_depth_buffer (glconfig) = %s\n",
404 gdk_gl_config_has_depth_buffer (glconfig) ? "TRUE" : "FALSE");
405 g_print ("gdk_gl_config_has_stencil_buffer (glconfig) = %s\n",
406 gdk_gl_config_has_stencil_buffer (glconfig) ? "TRUE" : "FALSE");
407 g_print ("gdk_gl_config_has_accum_buffer (glconfig) = %s\n",
408 gdk_gl_config_has_accum_buffer (glconfig) ? "TRUE" : "FALSE");
409
410 g_print ("\n");
411
412 print_gl_config_attrib (glconfig, "GDK_GL_USE_GL", GDK_GL_USE_GL, TRUE);
413 print_gl_config_attrib (glconfig, "GDK_GL_BUFFER_SIZE", GDK_GL_BUFFER_SIZE, FALSE);
414 print_gl_config_attrib (glconfig, "GDK_GL_LEVEL", GDK_GL_LEVEL, FALSE);
415 print_gl_config_attrib (glconfig, "GDK_GL_RGBA", GDK_GL_RGBA, TRUE);
416 print_gl_config_attrib (glconfig, "GDK_GL_DOUBLEBUFFER", GDK_GL_DOUBLEBUFFER, TRUE);
417 print_gl_config_attrib (glconfig, "GDK_GL_STEREO", GDK_GL_STEREO, TRUE);
418 print_gl_config_attrib (glconfig, "GDK_GL_AUX_BUFFERS", GDK_GL_AUX_BUFFERS, FALSE);
419 print_gl_config_attrib (glconfig, "GDK_GL_RED_SIZE", GDK_GL_RED_SIZE, FALSE);
420 print_gl_config_attrib (glconfig, "GDK_GL_GREEN_SIZE", GDK_GL_GREEN_SIZE, FALSE);
421 print_gl_config_attrib (glconfig, "GDK_GL_BLUE_SIZE", GDK_GL_BLUE_SIZE, FALSE);
422 print_gl_config_attrib (glconfig, "GDK_GL_ALPHA_SIZE", GDK_GL_ALPHA_SIZE, FALSE);
423 print_gl_config_attrib (glconfig, "GDK_GL_DEPTH_SIZE", GDK_GL_DEPTH_SIZE, FALSE);
424 print_gl_config_attrib (glconfig, "GDK_GL_STENCIL_SIZE", GDK_GL_STENCIL_SIZE, FALSE);
425 print_gl_config_attrib (glconfig, "GDK_GL_ACCUM_RED_SIZE", GDK_GL_ACCUM_RED_SIZE, FALSE);
426 print_gl_config_attrib (glconfig, "GDK_GL_ACCUM_GREEN_SIZE", GDK_GL_ACCUM_GREEN_SIZE, FALSE);
427 print_gl_config_attrib (glconfig, "GDK_GL_ACCUM_BLUE_SIZE", GDK_GL_ACCUM_BLUE_SIZE, FALSE);
428 print_gl_config_attrib (glconfig, "GDK_GL_ACCUM_ALPHA_SIZE", GDK_GL_ACCUM_ALPHA_SIZE, FALSE);
429
430 g_print ("\n");
431 }
432
433
434 #endif
435
436
437
438
439
440
441