2
* Copyright (C) 1998 Janne L�f <jlof@mail.student.oulu.fi>
4
* This library is free software; you can redistribute it and/or
5
* modify it under the terms of the GNU Library General Public
6
* License as published by the Free Software Foundation; either
7
* version 2 of the License, or (at your option) any later version.
9
* This library is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
* Library General Public License for more details.
14
* You should have received a copy of the GNU Library General Public
15
* License along with this library; if not, write to the Free
16
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22
#include <gtkgl/gtkglarea.h>
27
#include "trackball.h"
31
#define VIEW_ASPECT 1.3
33
char help_text[] = "Usage: viewlw [OPTION]... [FILE]...\n"
34
"View LightWave 3D objects.\n"
37
" --help display help\n"
40
" Mouse button 1 + drag spin (virtual trackball)\n"
41
" Mouse button 2 + drag zoom\n"
42
" Mouse button 3 popup menu\n"
48
/* information needed to display lightwave mesh */
50
gint do_init; /* true if initgl not yet called */
51
lwObject *lwobject; /* lightwave object mesh */
52
float beginx,beginy; /* position of mouse */
53
float quat[4]; /* orientation of object */
54
float zoom; /* field of view in degrees */
59
void select_lwobject(void);
60
gint show_lwobject(char *lwobject_name);
67
GLfloat light0_pos[4] = { -50.0, 50.0, 0.0, 0.0 };
68
GLfloat light0_color[4] = { .6, .6, .6, 1.0 }; /* white light */
69
GLfloat light1_pos[4] = { 50.0, 50.0, 0.0, 0.0 };
70
GLfloat light1_color[4] = { .4, .4, 1, 1.0 }; /* cold blue light */
72
/* remove back faces */
73
glDisable(GL_CULL_FACE);
74
glEnable(GL_DEPTH_TEST);
78
glShadeModel(GL_SMOOTH);
79
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
80
glHint(GL_POLYGON_SMOOTH_HINT, GL_FASTEST);
83
glLightfv(GL_LIGHT0, GL_POSITION, light0_pos);
84
glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_color);
85
glLightfv(GL_LIGHT1, GL_POSITION, light1_pos);
86
glLightfv(GL_LIGHT1, GL_DIFFUSE, light1_color);
89
glEnable(GL_LIGHTING);
91
glColorMaterial(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE);
92
glEnable(GL_COLOR_MATERIAL);
95
gint glarea_expose(GtkWidget *widget, GdkEventExpose *event)
99
GtkGLArea *glarea = GTK_GL_AREA(widget);
100
mesh_info *info = (mesh_info*)gtk_object_get_data(GTK_OBJECT(widget), "mesh_info");
102
/* draw only last expose */
103
if (event->count > 0) {
107
/* OpenGL calls can be done only if make_current returns true */
108
if (gtk_gl_area_make_current(glarea)) {
109
/* basic initialization */
110
if (info->do_init == TRUE) {
112
info->do_init = FALSE;
116
glMatrixMode(GL_PROJECTION);
118
gluPerspective(info->zoom, VIEW_ASPECT, 1,100);
119
glMatrixMode(GL_MODELVIEW);
122
glClearColor(.3,.4,.6,1);
123
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
126
glTranslatef(0,0,-30);
127
build_rotmatrix(m,info->quat);
128
glMultMatrixf(&m[0][0]);
130
lw_object_show(info->lwobject);
132
/* swap backbuffer to front */
133
gtk_gl_area_swapbuffers(glarea);
139
gint glarea_configure(GtkWidget *widget, GdkEventConfigure *event)
141
/* OpenGL calls can be done only if make_current returns true */
142
if (gtk_gl_area_make_current(GTK_GL_AREA(widget))) {
143
glViewport(0,0, widget->allocation.width, widget->allocation.height);
148
gint glarea_destroy(GtkWidget *widget)
150
/* delete mesh info */
151
mesh_info *info = (mesh_info*)gtk_object_get_data(GTK_OBJECT(widget),"mesh_info");
153
lw_object_free(info->lwobject);
159
gint glarea_button_press(GtkWidget *widget, GdkEventButton *event)
161
mesh_info *info = (mesh_info*)gtk_object_get_data(GTK_OBJECT(widget), "mesh_info");
162
if (event->button == 1) {
163
/* beginning of drag, reset mouse position */
164
info->beginx = event->x;
165
info->beginy = event->y;
171
gint glarea_motion_notify(GtkWidget *widget, GdkEventMotion *event)
175
GdkModifierType state;
176
mesh_info *info = (mesh_info*)gtk_object_get_data(GTK_OBJECT(widget), "mesh_info");
178
if (event->is_hint) {
181
gdk_window_get_pointer(event->window, &x, &y, &state);
186
state = event->state;
191
area.width = widget->allocation.width;
192
area.height = widget->allocation.height;
194
if (state & GDK_BUTTON1_MASK) {
195
/* drag in progress, simulate trackball */
198
(2.0*info->beginx - area.width) / area.width,
199
( area.height - 2.0*info->beginy) / area.height,
200
( 2.0*x - area.width) / area.width,
201
( area.height - 2.0*y) / area.height);
202
add_quats(spin_quat, info->quat, info->quat);
203
/* orientation has changed, redraw mesh */
204
gtk_widget_draw(widget, &area);
207
if (state & GDK_BUTTON2_MASK) {
209
info->zoom += ((y - info->beginy) / area.height) * 40;
210
if (info->zoom < 5) info->zoom = 5;
211
if (info->zoom > 120) info->zoom = 120;
212
/* zoom has changed, redraw mesh */
213
gtk_widget_draw(widget, &area);
225
gint popup_menu_handler(GtkWidget *widget, GdkEventButton *event)
227
if (event->button == 3) {
228
gtk_menu_popup(GTK_MENU(widget), NULL, NULL, NULL, NULL,
229
event->button, event->time);
234
void popup_menu_detacher(GtkWidget *attach_widget,GtkMenu *menu)
237
void create_popup_menu(GtkWidget *widget)
239
GtkWidget *menu = gtk_menu_new();
240
GtkWidget *open_item = gtk_menu_item_new_with_label("Open");
241
GtkWidget *quit_item = gtk_menu_item_new_with_label("Quit");
242
GtkWidget *quit_all_item = gtk_menu_item_new_with_label("Quit All");
244
gtk_menu_append(GTK_MENU(menu), open_item);
245
gtk_menu_append(GTK_MENU(menu), quit_item);
246
gtk_menu_append(GTK_MENU(menu), quit_all_item);
248
gtk_widget_show(open_item);
249
gtk_widget_show(quit_item);
250
gtk_widget_show(quit_all_item);
252
gtk_menu_attach_to_widget(GTK_MENU(menu),GTK_WIDGET(widget),popup_menu_detacher);
253
gtk_signal_connect_object(GTK_OBJECT(widget), "destroy",
254
GTK_SIGNAL_FUNC(gtk_menu_detach), GTK_OBJECT(menu));
256
gtk_signal_connect_object(GTK_OBJECT(widget), "button_press_event",
257
GTK_SIGNAL_FUNC(popup_menu_handler), GTK_OBJECT(menu));
260
gtk_signal_connect(GTK_OBJECT(open_item), "activate",
261
GTK_SIGNAL_FUNC(select_lwobject), NULL);
263
gtk_signal_connect_object(GTK_OBJECT(quit_item), "activate",
264
GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(widget));
266
gtk_signal_connect(GTK_OBJECT(quit_all_item), "activate",
267
GTK_SIGNAL_FUNC(gtk_main_quit), NULL);
272
gint window_count = 0; /* number of windows on screen */
273
gint window_destroy(GtkWidget *widget)
275
/* if this was last window quit */
276
if (--window_count == 0)
283
gint show_lwobject(char *lwobject_name)
285
GtkWidget *window, *glarea;
289
/* read lightwave object */
290
if (!lw_is_lwobject(lwobject_name)) {
291
g_print("%s is not a LightWave 3D object\n", lwobject_name);
294
lwobject = lw_object_read(lwobject_name);
295
if (lwobject == NULL) {
296
g_print("Can't read LightWave 3D object %s\n", lwobject_name);
299
lw_object_scale(lwobject, 10.0 / lw_object_radius(lwobject));
302
/* create new OpenGL widget */
303
glarea = gtk_gl_area_new_vargs(NULL, /* no sharing */
310
GDK_GL_NONE); /* last argument must be GDK_GL_NONE */
311
if (glarea == NULL) {
312
lw_object_free(lwobject);
313
g_print("Can't create GtkGLArea widget\n");
316
/* set up events and signals for OpenGL widget */
317
gtk_widget_set_events(glarea,
319
GDK_BUTTON_PRESS_MASK|
320
GDK_BUTTON_RELEASE_MASK|
321
GDK_POINTER_MOTION_MASK|
322
GDK_POINTER_MOTION_HINT_MASK);
323
gtk_signal_connect (GTK_OBJECT(glarea), "expose_event",
324
GTK_SIGNAL_FUNC(glarea_expose), NULL);
325
gtk_signal_connect (GTK_OBJECT(glarea), "motion_notify_event",
326
GTK_SIGNAL_FUNC(glarea_motion_notify), NULL);
327
gtk_signal_connect (GTK_OBJECT(glarea), "button_press_event",
328
GTK_SIGNAL_FUNC(glarea_button_press), NULL);
329
gtk_signal_connect (GTK_OBJECT(glarea), "configure_event",
330
GTK_SIGNAL_FUNC(glarea_configure), NULL);
331
gtk_signal_connect (GTK_OBJECT(glarea), "destroy",
332
GTK_SIGNAL_FUNC (glarea_destroy), NULL);
334
gtk_widget_set_usize(glarea, 200,200/VIEW_ASPECT); /* minimum size */
336
/* set up mesh info */
337
info = (mesh_info*)g_malloc(sizeof(mesh_info));
338
info->do_init = TRUE;
339
info->lwobject = lwobject;
343
trackball(info->quat , 0.0, 0.0, 0.0, 0.0);
344
gtk_object_set_data(GTK_OBJECT(glarea), "mesh_info", info);
347
/* create new top level window */
348
window = gtk_window_new( GTK_WINDOW_TOPLEVEL);
349
gtk_window_set_title(GTK_WINDOW(window), lwobject_name);
350
gtk_container_set_border_width(GTK_CONTAINER(window), 10);
351
create_popup_menu(window); /* add popup menu to window */
352
gtk_signal_connect (GTK_OBJECT(window), "destroy",
353
GTK_SIGNAL_FUNC(window_destroy), NULL);
356
/* destroy this window when exiting from gtk_main() */
357
gtk_quit_add_destroy(1, GTK_OBJECT(window));
360
/* put glarea into window and show it all */
361
gtk_container_add(GTK_CONTAINER(window), glarea);
363
gtk_widget_show(glarea);
364
gtk_widget_show(window);
371
gint filew_ok(GtkWidget *widget, GtkWidget *filew)
373
if (show_lwobject(gtk_file_selection_get_filename(GTK_FILE_SELECTION(filew))) == TRUE)
374
gtk_widget_destroy(filew);
378
void select_lwobject()
380
GtkWidget *filew = gtk_file_selection_new("Select LightWave 3D object");
382
gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION (filew)->ok_button), "clicked",
383
GTK_SIGNAL_FUNC(filew_ok), filew);
385
gtk_signal_connect_object(GTK_OBJECT(GTK_FILE_SELECTION(filew)->cancel_button), "clicked",
386
GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(filew));
388
gtk_signal_connect (GTK_OBJECT(filew), "destroy",
389
GTK_SIGNAL_FUNC(window_destroy), NULL);
392
gtk_widget_show(filew);
399
int main (int argc, char **argv)
402
gtk_init( &argc, &argv );
404
/* Check if OpenGL (GLX extension) is supported. */
405
if (gdk_gl_query() == FALSE) {
406
g_print("OpenGL not supported\n");
411
if (argc >= 2 && strcmp(argv[1],"--help")==0) {
412
g_print("%s", help_text);
417
/* no filenames, show filerequester */
420
/* show requested files */
422
for (i=1; i<argc; i++)
423
show_lwobject(argv[i]);
426
if (window_count > 0)