From aae24d21a33faa2a23fccde24255365ca845c46f Mon Sep 17 00:00:00 2001 From: Robert Roebling Date: Sun, 10 Jan 1999 10:49:57 +0000 Subject: [PATCH] OpenGl works now under GTK git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@1360 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/gtk/app.h | 6 +- include/wx/gtk1/app.h | 6 +- src/gtk/app.cpp | 62 +-- src/gtk/win_gtk.c | 1 + src/gtk/window.cpp | 13 +- src/gtk1/app.cpp | 62 +-- src/gtk1/win_gtk.c | 1 + src/gtk1/window.cpp | 13 +- utils/glcanvas/Makefile | 1 - utils/glcanvas/docs/notes.txt | 2 +- utils/glcanvas/samples/cube/Makefile | 16 + utils/glcanvas/samples/cube/cube.cpp | 11 +- utils/glcanvas/samples/isosurf/Makefile | 16 + utils/glcanvas/samples/penguin/Makefile | 23 ++ utils/glcanvas/samples/penguin/lw.c | 426 +++++++++++++++++++++ utils/glcanvas/samples/penguin/lw.h | 62 +++ utils/glcanvas/samples/penguin/penguin.cpp | 236 ++++++++++++ utils/glcanvas/samples/penguin/penguin.h | 84 ++++ utils/glcanvas/samples/penguin/trackball.c | 324 ++++++++++++++++ utils/glcanvas/samples/penguin/trackball.h | 78 ++++ utils/glcanvas/src/Makefile | 1 - utils/glcanvas/src/Makefile.in | 67 ---- utils/glcanvas/src/glcanvas.cpp | 211 +++++++--- utils/glcanvas/src/glcanvas.h | 33 +- 24 files changed, 1532 insertions(+), 223 deletions(-) delete mode 100644 utils/glcanvas/Makefile create mode 100644 utils/glcanvas/samples/cube/Makefile create mode 100644 utils/glcanvas/samples/isosurf/Makefile create mode 100644 utils/glcanvas/samples/penguin/Makefile create mode 100644 utils/glcanvas/samples/penguin/lw.c create mode 100644 utils/glcanvas/samples/penguin/lw.h create mode 100644 utils/glcanvas/samples/penguin/penguin.cpp create mode 100644 utils/glcanvas/samples/penguin/penguin.h create mode 100644 utils/glcanvas/samples/penguin/trackball.c create mode 100644 utils/glcanvas/samples/penguin/trackball.h delete mode 100644 utils/glcanvas/src/Makefile delete mode 100644 utils/glcanvas/src/Makefile.in diff --git a/include/wx/gtk/app.h b/include/wx/gtk/app.h index 4884ccf091..07d586dcb8 100644 --- a/include/wx/gtk/app.h +++ b/include/wx/gtk/app.h @@ -31,9 +31,6 @@ class wxLog; extern wxApp *wxTheApp; -extern GdkVisual *wxVisualSetByExternal; -extern GdkColormap *wxColormapSetByExternal; - //----------------------------------------------------------------------------- // global functions //----------------------------------------------------------------------------- @@ -66,8 +63,7 @@ class wxApp: public wxEvtHandler /* this may have to be overwritten when special, non-default visuals have to be set. it is also platform dependent as only X knows about displays - and visuals. by standard, this routine looks at wxVisualSetByExternal - which might have been set in the wxModule code of the OpenGL canvas */ + and visuals. */ virtual bool InitVisual(); virtual bool OnInit(); diff --git a/include/wx/gtk1/app.h b/include/wx/gtk1/app.h index 4884ccf091..07d586dcb8 100644 --- a/include/wx/gtk1/app.h +++ b/include/wx/gtk1/app.h @@ -31,9 +31,6 @@ class wxLog; extern wxApp *wxTheApp; -extern GdkVisual *wxVisualSetByExternal; -extern GdkColormap *wxColormapSetByExternal; - //----------------------------------------------------------------------------- // global functions //----------------------------------------------------------------------------- @@ -66,8 +63,7 @@ class wxApp: public wxEvtHandler /* this may have to be overwritten when special, non-default visuals have to be set. it is also platform dependent as only X knows about displays - and visuals. by standard, this routine looks at wxVisualSetByExternal - which might have been set in the wxModule code of the OpenGL canvas */ + and visuals. */ virtual bool InitVisual(); virtual bool OnInit(); diff --git a/src/gtk/app.cpp b/src/gtk/app.cpp index dec83867a0..74560c6d6e 100644 --- a/src/gtk/app.cpp +++ b/src/gtk/app.cpp @@ -44,9 +44,6 @@ wxAppInitializerFunction wxApp::m_appInitFn = (wxAppInitializerFunction) NULL; extern wxList wxPendingDelete; extern wxResourceCache *wxTheResourceCache; -GdkVisual *wxVisualSetByExternal = (GdkVisual*) NULL; -GdkColormap *wxColormapSetByExternal = (GdkColormap*) NULL; - unsigned char g_palette[64*3] = { 0x0, 0x0, 0x0, @@ -174,45 +171,28 @@ wxApp::~wxApp(void) bool wxApp::InitVisual() { - if (wxVisualSetByExternal) - { - /* this happens in the wxModule code of the OpenGl canvas. - it chooses the best display for OpenGl and stores it - in wxDisplaySetByExternal. we then have to make it the - default for the system */ - - gtk_widget_set_default_visual( wxVisualSetByExternal ); - } - - if (wxColormapSetByExternal) - { - /* OpenGl also gives us a colormap */ - - gtk_widget_set_default_colormap( wxColormapSetByExternal ); - } - else - { - /* this initiates the standard palette as defined by GdkImlib - in the GNOME libraries. it ensures that all GNOME applications - use the same 64 colormap entries on 8-bit displays so you - can use several rather graphics-heavy applications at the - same time */ + return TRUE; + + /* this initiates the standard palette as defined by GdkImlib + in the GNOME libraries. it ensures that all GNOME applications + use the same 64 colormap entries on 8-bit displays so you + can use several rather graphics-heavy applications at the + same time */ - GdkColormap *cmap = gdk_colormap_new( gdk_visual_get_system(), TRUE ); + GdkColormap *cmap = gdk_colormap_new( gdk_visual_get_system(), TRUE ); - for (int i = 0; i < 64; i++) - { - GdkColor col; - col.red = g_palette[i*3 + 0] << 8; - col.green = g_palette[i*3 + 1] << 8; - col.blue = g_palette[i*3 + 2] << 8; - col.pixel = 0; + for (int i = 0; i < 64; i++) + { + GdkColor col; + col.red = g_palette[i*3 + 0] << 8; + col.green = g_palette[i*3 + 1] << 8; + col.blue = g_palette[i*3 + 2] << 8; + col.pixel = 0; - gdk_color_alloc( cmap, &col ); - } - - gtk_widget_set_default_colormap( cmap ); + gdk_color_alloc( cmap, &col ); } + + gtk_widget_set_default_colormap( cmap ); return TRUE; } @@ -467,15 +447,15 @@ int wxEntry( int argc, char *argv[] ) gtk_init( &argc, &argv ); - wxModule::RegisterModules(); - if (!wxModule::InitializeModules()) return FALSE; - if (!wxTheApp->InitVisual()) return 0; wxApp::CommonInit(); if (!wxTheApp->OnInitGui()) return 0; + wxModule::RegisterModules(); + if (!wxModule::InitializeModules()) return FALSE; + // Here frames insert themselves automatically // into wxTopLevelWindows by getting created // in OnInit(). diff --git a/src/gtk/win_gtk.c b/src/gtk/win_gtk.c index 40c65a8785..0f2d927bea 100644 --- a/src/gtk/win_gtk.c +++ b/src/gtk/win_gtk.c @@ -288,6 +288,7 @@ gtk_myfixed_realize (GtkWidget *widget) attributes.event_mask |= GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | + GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_MOTION_MASK | GDK_BUTTON1_MOTION_MASK | GDK_BUTTON2_MOTION_MASK | diff --git a/src/gtk/window.cpp b/src/gtk/window.cpp index 5d074e2afc..f49fb9cf9b 100644 --- a/src/gtk/window.cpp +++ b/src/gtk/window.cpp @@ -634,6 +634,17 @@ static gint gtk_window_button_release_callback( GtkWidget *widget, GdkEventButto static gint gtk_window_motion_notify_callback( GtkWidget *widget, GdkEventMotion *gdk_event, wxWindow *win ) { + if (gdk_event->is_hint) + { + int x = 0; + int y = 0; + GdkModifierType state; + gdk_window_get_pointer(gdk_event->window, &x, &y, &state); + gdk_event->x = x; + gdk_event->y = y; + gdk_event->state = state; + } + if (!win->IsOwnGtkWindow( gdk_event->window )) return TRUE; if (g_blockEventsOnDrag) return TRUE; @@ -646,7 +657,7 @@ static gint gtk_window_motion_notify_callback( GtkWidget *widget, GdkEventMotion if (win->GetClassInfo() && win->GetClassInfo()->GetClassName()) printf( win->GetClassInfo()->GetClassName() ); printf( ".\n" ); -*/ +*/ wxMouseEvent event( wxEVT_MOTION ); event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK); diff --git a/src/gtk1/app.cpp b/src/gtk1/app.cpp index dec83867a0..74560c6d6e 100644 --- a/src/gtk1/app.cpp +++ b/src/gtk1/app.cpp @@ -44,9 +44,6 @@ wxAppInitializerFunction wxApp::m_appInitFn = (wxAppInitializerFunction) NULL; extern wxList wxPendingDelete; extern wxResourceCache *wxTheResourceCache; -GdkVisual *wxVisualSetByExternal = (GdkVisual*) NULL; -GdkColormap *wxColormapSetByExternal = (GdkColormap*) NULL; - unsigned char g_palette[64*3] = { 0x0, 0x0, 0x0, @@ -174,45 +171,28 @@ wxApp::~wxApp(void) bool wxApp::InitVisual() { - if (wxVisualSetByExternal) - { - /* this happens in the wxModule code of the OpenGl canvas. - it chooses the best display for OpenGl and stores it - in wxDisplaySetByExternal. we then have to make it the - default for the system */ - - gtk_widget_set_default_visual( wxVisualSetByExternal ); - } - - if (wxColormapSetByExternal) - { - /* OpenGl also gives us a colormap */ - - gtk_widget_set_default_colormap( wxColormapSetByExternal ); - } - else - { - /* this initiates the standard palette as defined by GdkImlib - in the GNOME libraries. it ensures that all GNOME applications - use the same 64 colormap entries on 8-bit displays so you - can use several rather graphics-heavy applications at the - same time */ + return TRUE; + + /* this initiates the standard palette as defined by GdkImlib + in the GNOME libraries. it ensures that all GNOME applications + use the same 64 colormap entries on 8-bit displays so you + can use several rather graphics-heavy applications at the + same time */ - GdkColormap *cmap = gdk_colormap_new( gdk_visual_get_system(), TRUE ); + GdkColormap *cmap = gdk_colormap_new( gdk_visual_get_system(), TRUE ); - for (int i = 0; i < 64; i++) - { - GdkColor col; - col.red = g_palette[i*3 + 0] << 8; - col.green = g_palette[i*3 + 1] << 8; - col.blue = g_palette[i*3 + 2] << 8; - col.pixel = 0; + for (int i = 0; i < 64; i++) + { + GdkColor col; + col.red = g_palette[i*3 + 0] << 8; + col.green = g_palette[i*3 + 1] << 8; + col.blue = g_palette[i*3 + 2] << 8; + col.pixel = 0; - gdk_color_alloc( cmap, &col ); - } - - gtk_widget_set_default_colormap( cmap ); + gdk_color_alloc( cmap, &col ); } + + gtk_widget_set_default_colormap( cmap ); return TRUE; } @@ -467,15 +447,15 @@ int wxEntry( int argc, char *argv[] ) gtk_init( &argc, &argv ); - wxModule::RegisterModules(); - if (!wxModule::InitializeModules()) return FALSE; - if (!wxTheApp->InitVisual()) return 0; wxApp::CommonInit(); if (!wxTheApp->OnInitGui()) return 0; + wxModule::RegisterModules(); + if (!wxModule::InitializeModules()) return FALSE; + // Here frames insert themselves automatically // into wxTopLevelWindows by getting created // in OnInit(). diff --git a/src/gtk1/win_gtk.c b/src/gtk1/win_gtk.c index 40c65a8785..0f2d927bea 100644 --- a/src/gtk1/win_gtk.c +++ b/src/gtk1/win_gtk.c @@ -288,6 +288,7 @@ gtk_myfixed_realize (GtkWidget *widget) attributes.event_mask |= GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | + GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_MOTION_MASK | GDK_BUTTON1_MOTION_MASK | GDK_BUTTON2_MOTION_MASK | diff --git a/src/gtk1/window.cpp b/src/gtk1/window.cpp index 5d074e2afc..f49fb9cf9b 100644 --- a/src/gtk1/window.cpp +++ b/src/gtk1/window.cpp @@ -634,6 +634,17 @@ static gint gtk_window_button_release_callback( GtkWidget *widget, GdkEventButto static gint gtk_window_motion_notify_callback( GtkWidget *widget, GdkEventMotion *gdk_event, wxWindow *win ) { + if (gdk_event->is_hint) + { + int x = 0; + int y = 0; + GdkModifierType state; + gdk_window_get_pointer(gdk_event->window, &x, &y, &state); + gdk_event->x = x; + gdk_event->y = y; + gdk_event->state = state; + } + if (!win->IsOwnGtkWindow( gdk_event->window )) return TRUE; if (g_blockEventsOnDrag) return TRUE; @@ -646,7 +657,7 @@ static gint gtk_window_motion_notify_callback( GtkWidget *widget, GdkEventMotion if (win->GetClassInfo() && win->GetClassInfo()->GetClassName()) printf( win->GetClassInfo()->GetClassName() ); printf( ".\n" ); -*/ +*/ wxMouseEvent event( wxEVT_MOTION ); event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK); diff --git a/utils/glcanvas/Makefile b/utils/glcanvas/Makefile deleted file mode 100644 index 3f7a4dce0d..0000000000 --- a/utils/glcanvas/Makefile +++ /dev/null @@ -1 +0,0 @@ -include ../../setup/general/makedirs diff --git a/utils/glcanvas/docs/notes.txt b/utils/glcanvas/docs/notes.txt index c2049028dc..7bcb165caf 100644 --- a/utils/glcanvas/docs/notes.txt +++ b/utils/glcanvas/docs/notes.txt @@ -2,4 +2,4 @@ wxGLCanvas ---------- No known issues, though probably palettes aren't correctly -handled under Windows. +handled under Windows. They are ignored under GTK. diff --git a/utils/glcanvas/samples/cube/Makefile b/utils/glcanvas/samples/cube/Makefile new file mode 100644 index 0000000000..f24f7eb8ef --- /dev/null +++ b/utils/glcanvas/samples/cube/Makefile @@ -0,0 +1,16 @@ + +CC = g++ + +cube: cube.o glcanvas.o + $(CC) -o cube \ + cube.o glcanvas.o \ + `wx-config --libs` -lMesaGL -lMesaGLU + +cube.o: cube.cpp + $(CC) `wx-config --cflags` -I../../src -c cube.cpp + +glcanvas.o: ../../src/glcanvas.cpp + $(CC) `wx-config --cflags` `gtk-config --cflags` -I../../src -c ../../src/glcanvas.cpp + +clean: + rm -f *.o cube diff --git a/utils/glcanvas/samples/cube/cube.cpp b/utils/glcanvas/samples/cube/cube.cpp index 6a756b2893..675cdaba73 100644 --- a/utils/glcanvas/samples/cube/cube.cpp +++ b/utils/glcanvas/samples/cube/cube.cpp @@ -29,8 +29,6 @@ #include "cube.h" -IMPLEMENT_APP(MyApp) - // `Main program' equivalent, creating windows and returning main app frame bool MyApp::OnInit(void) { @@ -54,7 +52,7 @@ bool MyApp::OnInit(void) frame->m_canvas = new TestGLCanvas(frame, -1, wxPoint(0, 0), wxSize(200, 200)); - InitGL(); +// InitGL(); // Show the frame frame->Show(TRUE); @@ -81,6 +79,8 @@ void MyApp::InitGL(void) glEnable(GL_LIGHT0); } +IMPLEMENT_APP(MyApp) + BEGIN_EVENT_TABLE(MyFrame, wxFrame) EVT_MENU(wxID_EXIT, MyFrame::OnExit) END_EVENT_TABLE() @@ -169,8 +169,11 @@ void TestGLCanvas::OnSize(wxSizeEvent& event) int width, height; GetClientSize(& width, & height); - if ( GetContext() ) + if (GetContext()) + { + SetCurrent(); glViewport(0, 0, width, height); + } } void TestGLCanvas::OnEraseBackground(wxEraseEvent& event) diff --git a/utils/glcanvas/samples/isosurf/Makefile b/utils/glcanvas/samples/isosurf/Makefile new file mode 100644 index 0000000000..7722db17b0 --- /dev/null +++ b/utils/glcanvas/samples/isosurf/Makefile @@ -0,0 +1,16 @@ + +CC = g++ + +isosurf: isosurf.o glcanvas.o + $(CC) -o isosurf \ + isosurf.o glcanvas.o \ + `wx-config --libs` -lMesaGL -lMesaGLU + +isosurf.o: isosurf.cpp + $(CC) `wx-config --cflags` -I../../src -c isosurf.cpp + +glcanvas.o: ../../src/glcanvas.cpp + $(CC) `wx-config --cflags` `gtk-config --cflags` -I../../src -c ../../src/glcanvas.cpp + +clean: + rm -f *.o cube diff --git a/utils/glcanvas/samples/penguin/Makefile b/utils/glcanvas/samples/penguin/Makefile new file mode 100644 index 0000000000..5a3cfc9a81 --- /dev/null +++ b/utils/glcanvas/samples/penguin/Makefile @@ -0,0 +1,23 @@ + +CPP = g++ +CC = gcc + +Penguin: penguin.o trackball.o lw.o glcanvas.o + $(CPP) -o Penguin \ + penguin.o trackball.o lw.o glcanvas.o \ + `wx-config --libs` -lMesaGL -lMesaGLU + +penguin.o: penguin.cpp + $(CPP) `wx-config --cflags` -I../../src -c penguin.cpp + +lw.o: lw.c + $(CC) `wx-config --cflags` -I../../src -c lw.c + +trackball.o: trackball.c + $(CC) `wx-config --cflags` -I../../src -c trackball.c + +glcanvas.o: ../../src/glcanvas.cpp + $(CPP) `wx-config --cflags` `gtk-config --cflags` -I../../src -c ../../src/glcanvas.cpp + +clean: + rm -f *.o penguin diff --git a/utils/glcanvas/samples/penguin/lw.c b/utils/glcanvas/samples/penguin/lw.c new file mode 100644 index 0000000000..01decb7845 --- /dev/null +++ b/utils/glcanvas/samples/penguin/lw.c @@ -0,0 +1,426 @@ +/* + * Copyright (C) 1998 Janne Löf + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + + + +#include "lw.h" +#include +#include +#include + +#define wxInt32 int +#define wxUint32 unsigned int + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +#define MK_ID(a,b,c,d) ((((wxUint32)(a))<<24)| \ + (((wxUint32)(b))<<16)| \ + (((wxUint32)(c))<< 8)| \ + (((wxUint32)(d)) )) + +#define ID_FORM MK_ID('F','O','R','M') +#define ID_LWOB MK_ID('L','W','O','B') +#define ID_PNTS MK_ID('P','N','T','S') +#define ID_SRFS MK_ID('S','R','F','S') +#define ID_SURF MK_ID('S','U','R','F') +#define ID_POLS MK_ID('P','O','L','S') +#define ID_COLR MK_ID('C','O','L','R') + +static wxInt32 read_char(FILE *f) +{ + int c = fgetc(f); + return c; +} + +static wxInt32 read_short(FILE *f) +{ + return (read_char(f)<<8) | read_char(f); +} + +static wxInt32 read_long(FILE *f) +{ + return (read_char(f)<<24) | (read_char(f)<<16) | (read_char(f)<<8) | read_char(f); +} + +static GLfloat read_float(FILE *f) +{ + wxInt32 x = read_long(f); + return *(GLfloat*)&x; +} + +static int read_string(FILE *f, char *s) +{ + int c; + int cnt = 0; + do { + c = read_char(f); + if (cnt < LW_MAX_NAME_LEN) + s[cnt] = c; + else + s[LW_MAX_NAME_LEN-1] = 0; + cnt++; + } while (c != 0); + /* if length of string (including \0) is odd skip another byte */ + if (cnt%2) { + read_char(f); + cnt++; + } + return cnt; +} + +static void read_srfs(FILE *f, int nbytes, lwObject *lwo) +{ + int guess_cnt = lwo->material_cnt; + + while (nbytes > 0) { + lwMaterial *material; + + /* allocate more memory for materials if needed */ + if (guess_cnt <= lwo->material_cnt) { + guess_cnt += guess_cnt/2 + 4; + lwo->material = realloc(lwo->material, sizeof(lwMaterial)*guess_cnt); + } + material = lwo->material + lwo->material_cnt++; + + /* read name */ + nbytes -= read_string(f,material->name); + + /* defaults */ + material->r = 0.7; + material->g = 0.7; + material->b = 0.7; + } + lwo->material = realloc(lwo->material, sizeof(lwMaterial)*lwo->material_cnt); +} + + +static void read_surf(FILE *f, int nbytes, lwObject *lwo) +{ + int i; + char name[LW_MAX_NAME_LEN]; + lwMaterial *material = NULL; + + /* read surface name */ + nbytes -= read_string(f,name); + + /* find material */ + for (i=0; i< lwo->material_cnt; i++) { + if (strcmp(lwo->material[i].name,name) == 0) { + material = &lwo->material[i]; + break; + } + } + + /* read values */ + while (nbytes > 0) { + int id = read_long(f); + int len = read_short(f); + nbytes -= 6 + len + (len%2); + + switch (id) { + case ID_COLR: + material->r = read_char(f) / 255.0; + material->g = read_char(f) / 255.0; + material->b = read_char(f) / 255.0; + read_char(f); /* dummy */ + break; + default: + fseek(f, len+(len%2), SEEK_CUR); + } + } +} + + +static void read_pols(FILE *f, int nbytes, lwObject *lwo) +{ + int guess_cnt = lwo->face_cnt; + + while (nbytes > 0) { + lwFace *face; + int i; + + /* allocate more memory for polygons if necessary */ + if (guess_cnt <= lwo->face_cnt) { + guess_cnt += guess_cnt + 4; + lwo->face = realloc(lwo->face, sizeof(lwFace)*guess_cnt); + } + face = lwo->face + lwo->face_cnt++; + + /* number of points in this face */ + face->index_cnt = read_short(f); + nbytes -= 2; + + /* allocate space for points */ + face->index = calloc(sizeof(int)*face->index_cnt,1); + + /* read points in */ + for (i=0; iindex_cnt; i++) { + face->index[i] = read_short(f); + nbytes -= 2; + } + + /* read surface material */ + face->material = read_short(f); + nbytes -= 2; + + /* skip over detail polygons */ + if (face->material < 0) { + int det_cnt; + face->material = -face->material; + det_cnt = read_short(f); + nbytes -= 2; + while (det_cnt-- > 0) { + int cnt = read_short(f); + fseek(f, cnt*2+2, SEEK_CUR); + nbytes -= cnt*2+2; + } + } + face->material -= 1; + } + /* readjust to true size */ + lwo->face = realloc(lwo->face, sizeof(lwFace)*lwo->face_cnt); +} + + + +static void read_pnts(FILE *f, int nbytes, lwObject *lwo) +{ + int i; + lwo->vertex_cnt = nbytes / 12; + lwo->vertex = calloc(sizeof(GLfloat)*lwo->vertex_cnt*3, 1); + for (i=0; ivertex_cnt; i++) { + lwo->vertex[i*3+0] = read_float(f); + lwo->vertex[i*3+1] = read_float(f); + lwo->vertex[i*3+2] = read_float(f); + } +} + + + + + + +int lw_is_lwobject(const char *lw_file) +{ + FILE *f = fopen(lw_file, "rb"); + if (f) { + wxInt32 form = read_long(f); + wxInt32 nlen = read_long(f); + wxInt32 lwob = read_long(f); + fclose(f); + if (form == ID_FORM && nlen != 0 && lwob == ID_LWOB) + return TRUE; + } + return FALSE; +} + + +lwObject *lw_object_read(const char *lw_file) +{ + FILE *f = NULL; + lwObject *lw_object = NULL; + + wxInt32 form_bytes = 0; + wxInt32 read_bytes = 0; + + /* open file */ + f = fopen(lw_file, "rb"); + if (f == NULL) { + return NULL; + } + + /* check for headers */ + if (read_long(f) != ID_FORM) { + fclose(f); + return NULL; + } + form_bytes = read_long(f); + read_bytes += 4; + + if (read_long(f) != ID_LWOB) { + fclose(f); + return NULL; + } + + /* create new lwObject */ + lw_object = calloc(sizeof(lwObject),1); + + /* read chunks */ + while (read_bytes < form_bytes) { + wxInt32 id = read_long(f); + wxInt32 nbytes = read_long(f); + read_bytes += 8 + nbytes + (nbytes%2); + + switch (id) { + case ID_PNTS: + read_pnts(f, nbytes, lw_object); + break; + case ID_POLS: + read_pols(f, nbytes, lw_object); + break; + case ID_SRFS: + read_srfs(f, nbytes, lw_object); + break; + case ID_SURF: + read_surf(f, nbytes, lw_object); + break; + default: + fseek(f, nbytes + (nbytes%2), SEEK_CUR); + } + } + + fclose(f); + return lw_object; +} + + + +void lw_object_free(lwObject *lw_object) +{ + if (lw_object->face) { + int i; + for (i=0; iface_cnt; i++) + free(lw_object->face[i].index); + free(lw_object->face); + } + free(lw_object->material); + free(lw_object->vertex); + free(lw_object); +} + + + + + +#define PX(i) (lw_object->vertex[face->index[i]*3+0]) +#define PY(i) (lw_object->vertex[face->index[i]*3+1]) +#define PZ(i) (lw_object->vertex[face->index[i]*3+2]) +void lw_object_show(const lwObject *lw_object) +{ + int i,j; + int prev_index_cnt = -1; + int prev_material = -1; + GLfloat prev_nx = 0; + GLfloat prev_ny = 0; + GLfloat prev_nz = 0; + + for (i=0; iface_cnt; i++) { + GLfloat ax,ay,az,bx,by,bz,nx,ny,nz,r; + const lwFace *face = lw_object->face+i; + + /* ignore faces with less than 3 points */ + if (face->index_cnt < 3) + continue; + + /* calculate normal */ + ax = PX(1) - PX(0); + ay = PY(1) - PY(0); + az = PZ(1) - PZ(0); + + bx = PX(face->index_cnt-1) - PX(0); + by = PY(face->index_cnt-1) - PY(0); + bz = PZ(face->index_cnt-1) - PZ(0); + + nx = ay * bz - az * by; + ny = az * bx - ax * bz; + nz = ax * by - ay * bx; + + r = sqrt(nx*nx + ny*ny + nz*nz); + if (r < 0.000001) /* avoid division by zero */ + continue; + nx /= r; + ny /= r; + nz /= r; + + /* glBegin/glEnd */ + if (prev_index_cnt != face->index_cnt || prev_index_cnt > 4) { + if (prev_index_cnt > 0) glEnd(); + prev_index_cnt = face->index_cnt; + switch (face->index_cnt) { + case 3: + glBegin(GL_TRIANGLES); + break; + case 4: + glBegin(GL_QUADS); + break; + default: + glBegin(GL_POLYGON); + } + } + + /* update material if necessary */ + if (prev_material != face->material) { + prev_material = face->material; + glColor3f(lw_object->material[face->material].r, + lw_object->material[face->material].g, + lw_object->material[face->material].b); + } + + /* update normal if necessary */ + if (nx != prev_nx || ny != prev_ny || nz != prev_nz) { + prev_nx = nx; + prev_ny = ny; + prev_nz = nz; + glNormal3f(nx,ny,nz); + } + + /* draw polygon/triangle/quad */ + for (j=0; jindex_cnt; j++) + glVertex3f(PX(j),PY(j),PZ(j)); + + } + + /* if glBegin was called call glEnd */ + if (prev_index_cnt > 0) + glEnd(); +} + + +GLfloat lw_object_radius(const lwObject *lwo) +{ + int i; + double max_radius = 0.0; + + for (i=0; ivertex_cnt; i++) { + GLfloat *v = &lwo->vertex[i*3]; + double r = v[0]*v[0] + v[1]*v[1] + v[2]*v[2]; + if (r > max_radius) + max_radius = r; + } + return sqrt(max_radius); +} + +void lw_object_scale(lwObject *lwo, GLfloat scale) +{ + int i; + + for (i=0; ivertex_cnt; i++) { + lwo->vertex[i*3+0] *= scale; + lwo->vertex[i*3+1] *= scale; + lwo->vertex[i*3+2] *= scale; + } +} + + diff --git a/utils/glcanvas/samples/penguin/lw.h b/utils/glcanvas/samples/penguin/lw.h new file mode 100644 index 0000000000..9202019222 --- /dev/null +++ b/utils/glcanvas/samples/penguin/lw.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 1998 Janne Löf + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +#ifndef LW_H +#define LW_H + +#include + +#define LW_MAX_POINTS 200 +#define LW_MAX_NAME_LEN 500 + +typedef struct { + char name[LW_MAX_NAME_LEN]; + GLfloat r,g,b; +} lwMaterial; + +typedef struct { + int material; /* material of this face */ + int index_cnt; /* number of vertices */ + int *index; /* index to vertex */ + float *texcoord; /* u,v texture coordinates */ +} lwFace; + +typedef struct { + int face_cnt; + lwFace *face; + + int material_cnt; + lwMaterial *material; + + int vertex_cnt; + GLfloat *vertex; + +} lwObject; + + +int lw_is_lwobject(const char *lw_file); +lwObject *lw_object_read(const char *lw_file); +void lw_object_free( lwObject *lw_object); +void lw_object_show(const lwObject *lw_object); + +GLfloat lw_object_radius(const lwObject *lw_object); +void lw_object_scale (lwObject *lw_object, GLfloat scale); + +#endif /* LW_H */ + diff --git a/utils/glcanvas/samples/penguin/penguin.cpp b/utils/glcanvas/samples/penguin/penguin.cpp new file mode 100644 index 0000000000..9444b7ec08 --- /dev/null +++ b/utils/glcanvas/samples/penguin/penguin.cpp @@ -0,0 +1,236 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: penguin.cpp +// Purpose: wxGLCanvas demo program +// Author: Robert Roebling +// Modified by: +// Created: 04/01/98 +// RCS-ID: $Id$ +// Copyright: (c) Robert Roebling +// Licence: wxWindows licence +///////////////////////////////////////////////////////////////////////////// + +#ifdef __GNUG__ +#pragma implementation +#pragma interface +#endif + +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ +#pragma hdrstop +#endif + +#ifndef WX_PRECOMP +#include "wx/wx.h" +#endif + +#include "penguin.h" +#include + +#define VIEW_ASPECT 1.3 + +/* `Main program' equivalent, creating windows and returning main app frame */ +bool MyApp::OnInit(void) +{ + + /* Create the main frame window */ + MyFrame *frame = new MyFrame(NULL, "wxWindows OpenGL Demo", wxPoint(50, 50), wxSize(400, 300)); + + /* Make a menubar */ + wxMenu *fileMenu = new wxMenu; + + fileMenu->Append(wxID_EXIT, "E&xit"); + wxMenuBar *menuBar = new wxMenuBar; + menuBar->Append(fileMenu, "&File"); + frame->SetMenuBar(menuBar); + + frame->m_canvas = new TestGLCanvas(frame, -1, wxPoint(0, 0), wxSize(200, 200)); + + /* Load file wiht mesh data */ + frame->m_canvas->LoadLWO( "penguin.lwo" ); + + /* Show the frame */ + frame->Show(TRUE); + + return TRUE; +} + +IMPLEMENT_APP(MyApp) + +BEGIN_EVENT_TABLE(MyFrame, wxFrame) + EVT_MENU(wxID_EXIT, MyFrame::OnExit) +END_EVENT_TABLE() + +/* My frame constructor */ +MyFrame::MyFrame(wxFrame *frame, const wxString& title, const wxPoint& pos, + const wxSize& size, long style): + wxFrame(frame, -1, title, pos, size, style) +{ + m_canvas = NULL; +} + +/* Intercept menu commands */ +void MyFrame::OnExit(wxCommandEvent& event) +{ + Destroy(); +} + +bool MyFrame::OnClose(void) +{ + return TRUE; +} + +BEGIN_EVENT_TABLE(TestGLCanvas, wxGLCanvas) + EVT_SIZE(TestGLCanvas::OnSize) + EVT_PAINT(TestGLCanvas::OnPaint) + EVT_ERASE_BACKGROUND(TestGLCanvas::OnEraseBackground) + EVT_MOUSE_EVENTS(TestGLCanvas::OnMouse) +END_EVENT_TABLE() + +TestGLCanvas::TestGLCanvas(wxWindow *parent, wxWindowID id, + const wxPoint& pos, const wxSize& size, long style, const wxString& name): + wxGLCanvas(parent, id, pos, size, style, name) +{ + block = FALSE; +} + +TestGLCanvas::~TestGLCanvas(void) +{ + /* destroy mesh */ + lw_object_free(info.lwobject); +} + +void TestGLCanvas::OnPaint( wxPaintEvent& event ) +{ + /* must always be here */ + wxPaintDC dc(this); + + if (!GetContext()) return; + + SetCurrent(); + + /* initialize OpenGL */ + if (info.do_init == TRUE) + { + InitGL(); + info.do_init = FALSE; + } + + /* view */ + glMatrixMode( GL_PROJECTION ); + glLoadIdentity(); + gluPerspective( info.zoom, VIEW_ASPECT, 1, 100 ); + glMatrixMode( GL_MODELVIEW ); + + /* clear */ + glClearColor( .3, .4, .6, 1 ); + glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); + + /* transformations */ + GLfloat m[4][4]; + glLoadIdentity(); + glTranslatef( 0, 0, -30 ); + build_rotmatrix( m,info.quat ); + glMultMatrixf( &m[0][0] ); + + /* draw object */ + lw_object_show( info.lwobject ); + + /* flush */ + glFlush(); + + /* swap */ + SwapBuffers(); +} + +void TestGLCanvas::OnSize(wxSizeEvent& event) +{ + int width, height; + GetClientSize(& width, & height); + + if (GetContext()) + { + SetCurrent(); + glViewport(0, 0, width, height); + } +} + +void TestGLCanvas::OnEraseBackground(wxEraseEvent& event) +{ + /* Do nothing, to avoid flashing on MSW */ +} + +void TestGLCanvas::LoadLWO(const wxString &filename) +{ + /* test if lightwave object */ + if (!lw_is_lwobject(filename)) return; + + /* read lightwave object */ + lwObject *lwobject = lw_object_read(filename); + + /* scale */ + lw_object_scale(lwobject, 10.0 / lw_object_radius(lwobject)); + + /* set up mesh info */ + info.do_init = TRUE; + info.lwobject = lwobject; + info.beginx = 0; + info.beginy = 0; + info.zoom = 45; + trackball( info.quat, 0.0, 0.0, 0.0, 0.0 ); +} + +void TestGLCanvas::OnMouse( wxMouseEvent& event ) +{ + if (event.Dragging()) + { + /* drag in progress, simulate trackball */ + float spin_quat[4]; + trackball(spin_quat, + (2.0*info.beginx - m_width) / m_width, + ( m_height - 2.0*info.beginy) / m_height, + ( 2.0*event.GetX() - m_width) / m_width, + ( m_height - 2.0*event.GetY()) / m_height); + + add_quats( spin_quat, info.quat, info.quat ); + + /* orientation has changed, redraw mesh */ + Refresh(); + } + + info.beginx = event.GetX(); + info.beginy = event.GetY(); +} + +void TestGLCanvas::InitGL(void) +{ + GLfloat light0_pos[4] = { -50.0, 50.0, 0.0, 0.0 }; + GLfloat light0_color[4] = { .6, .6, .6, 1.0 }; /* white light */ + GLfloat light1_pos[4] = { 50.0, 50.0, 0.0, 0.0 }; + GLfloat light1_color[4] = { .4, .4, 1, 1.0 }; /* cold blue light */ + + /* remove back faces */ + glDisable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + + /* speedups */ + glEnable(GL_DITHER); + glShadeModel(GL_SMOOTH); + glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); + glHint(GL_POLYGON_SMOOTH_HINT, GL_FASTEST); + + /* light */ + glLightfv(GL_LIGHT0, GL_POSITION, light0_pos); + glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_color); + glLightfv(GL_LIGHT1, GL_POSITION, light1_pos); + glLightfv(GL_LIGHT1, GL_DIFFUSE, light1_color); + glEnable(GL_LIGHT0); + glEnable(GL_LIGHT1); + glEnable(GL_LIGHTING); + + glColorMaterial(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE); + glEnable(GL_COLOR_MATERIAL); +} + + diff --git a/utils/glcanvas/samples/penguin/penguin.h b/utils/glcanvas/samples/penguin/penguin.h new file mode 100644 index 0000000000..83b0708e1c --- /dev/null +++ b/utils/glcanvas/samples/penguin/penguin.h @@ -0,0 +1,84 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: penguin.h +// Purpose: wxGLCanvas demo program +// Author: Robert Roebling +// Modified by: +// Created: 04/01/98 +// RCS-ID: $Id$ +// Copyright: (c) Robert Roebling +// Licence: wxWindows licence +///////////////////////////////////////////////////////////////////////////// + +#ifndef _WX_PENGUIN_H_ +#define _WX_PENGUIN_H_ + + +#include "wx/defs.h" +#include "wx/app.h" +#include "wx/menu.h" +#include "wx/dcclient.h" + +#include "glcanvas.h" + +extern "C" { +#include "lw.h" +#include "trackball.h" +} + +/* information needed to display lightwave mesh */ +typedef struct +{ + gint do_init; /* true if initgl not yet called */ + lwObject *lwobject; /* lightwave object mesh */ + float beginx,beginy; /* position of mouse */ + float quat[4]; /* orientation of object */ + float zoom; /* field of view in degrees */ +} mesh_info; + + +/* Define a new application type */ +class MyApp: public wxApp +{ +public: + bool OnInit(void); +}; + +/* Define a new frame type */ +class TestGLCanvas; +class MyFrame: public wxFrame +{ +public: + MyFrame(wxFrame *frame, const wxString& title, const wxPoint& pos, const wxSize& size, + long style = wxDEFAULT_FRAME_STYLE); + + void OnExit(wxCommandEvent& event); + bool OnClose(void); +public: + TestGLCanvas* m_canvas; + +DECLARE_EVENT_TABLE() +}; + + +class TestGLCanvas: public wxGLCanvas +{ + public: + TestGLCanvas(wxWindow *parent, const wxWindowID id = -1, const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, long style = 0, const wxString& name = "TestGLCanvas"); + ~TestGLCanvas(void); + + void OnPaint(wxPaintEvent& event); + void OnSize(wxSizeEvent& event); + void OnEraseBackground(wxEraseEvent& event); + void LoadLWO( const wxString &filename); + void OnMouse( wxMouseEvent& event ); + void InitGL(void); + + mesh_info info; + bool block; + +DECLARE_EVENT_TABLE() +}; + +#endif + diff --git a/utils/glcanvas/samples/penguin/trackball.c b/utils/glcanvas/samples/penguin/trackball.c new file mode 100644 index 0000000000..f23d3db30b --- /dev/null +++ b/utils/glcanvas/samples/penguin/trackball.c @@ -0,0 +1,324 @@ +/* + * (c) Copyright 1993, 1994, Silicon Graphics, Inc. + * ALL RIGHTS RESERVED + * Permission to use, copy, modify, and distribute this software for + * any purpose and without fee is hereby granted, provided that the above + * copyright notice appear in all copies and that both the copyright notice + * and this permission notice appear in supporting documentation, and that + * the name of Silicon Graphics, Inc. not be used in advertising + * or publicity pertaining to distribution of the software without specific, + * written prior permission. + * + * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS" + * AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR + * FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON + * GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT, + * SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY + * KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION, + * LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF + * THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC. HAS BEEN + * ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE + * POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE. + * + * US Government Users Restricted Rights + * Use, duplication, or disclosure by the Government is subject to + * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph + * (c)(1)(ii) of the Rights in Technical Data and Computer Software + * clause at DFARS 252.227-7013 and/or in similar or successor + * clauses in the FAR or the DOD or NASA FAR Supplement. + * Unpublished-- rights reserved under the copyright laws of the + * United States. Contractor/manufacturer is Silicon Graphics, + * Inc., 2011 N. Shoreline Blvd., Mountain View, CA 94039-7311. + * + * OpenGL(TM) is a trademark of Silicon Graphics, Inc. + */ +/* + * Trackball code: + * + * Implementation of a virtual trackball. + * Implemented by Gavin Bell, lots of ideas from Thant Tessman and + * the August '88 issue of Siggraph's "Computer Graphics," pp. 121-129. + * + * Vector manip code: + * + * Original code from: + * David M. Ciemiewicz, Mark Grossman, Henry Moreton, and Paul Haeberli + * + * Much mucking with by: + * Gavin Bell + */ +#include +#include "trackball.h" + +/* + * This size should really be based on the distance from the center of + * rotation to the point on the object underneath the mouse. That + * point would then track the mouse as closely as possible. This is a + * simple example, though, so that is left as an Exercise for the + * Programmer. + */ +#define TRACKBALLSIZE (0.8) + +/* + * Local function prototypes (not defined in trackball.h) + */ +static float tb_project_to_sphere(float, float, float); +static void normalize_quat(float [4]); + +void +vzero(float *v) +{ + v[0] = 0.0; + v[1] = 0.0; + v[2] = 0.0; +} + +void +vset(float *v, float x, float y, float z) +{ + v[0] = x; + v[1] = y; + v[2] = z; +} + +void +vsub(const float *src1, const float *src2, float *dst) +{ + dst[0] = src1[0] - src2[0]; + dst[1] = src1[1] - src2[1]; + dst[2] = src1[2] - src2[2]; +} + +void +vcopy(const float *v1, float *v2) +{ + register int i; + for (i = 0 ; i < 3 ; i++) + v2[i] = v1[i]; +} + +void +vcross(const float *v1, const float *v2, float *cross) +{ + float temp[3]; + + temp[0] = (v1[1] * v2[2]) - (v1[2] * v2[1]); + temp[1] = (v1[2] * v2[0]) - (v1[0] * v2[2]); + temp[2] = (v1[0] * v2[1]) - (v1[1] * v2[0]); + vcopy(temp, cross); +} + +float +vlength(const float *v) +{ + return sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]); +} + +void +vscale(float *v, float div) +{ + v[0] *= div; + v[1] *= div; + v[2] *= div; +} + +void +vnormal(float *v) +{ + vscale(v,1.0/vlength(v)); +} + +float +vdot(const float *v1, const float *v2) +{ + return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2]; +} + +void +vadd(const float *src1, const float *src2, float *dst) +{ + dst[0] = src1[0] + src2[0]; + dst[1] = src1[1] + src2[1]; + dst[2] = src1[2] + src2[2]; +} + +/* + * Ok, simulate a track-ball. Project the points onto the virtual + * trackball, then figure out the axis of rotation, which is the cross + * product of P1 P2 and O P1 (O is the center of the ball, 0,0,0) + * Note: This is a deformed trackball-- is a trackball in the center, + * but is deformed into a hyperbolic sheet of rotation away from the + * center. This particular function was chosen after trying out + * several variations. + * + * It is assumed that the arguments to this routine are in the range + * (-1.0 ... 1.0) + */ +void +trackball(float q[4], float p1x, float p1y, float p2x, float p2y) +{ + float a[3]; /* Axis of rotation */ + float phi; /* how much to rotate about axis */ + float p1[3], p2[3], d[3]; + float t; + + if (p1x == p2x && p1y == p2y) { + /* Zero rotation */ + vzero(q); + q[3] = 1.0; + return; + } + + /* + * First, figure out z-coordinates for projection of P1 and P2 to + * deformed sphere + */ + vset(p1,p1x,p1y,tb_project_to_sphere(TRACKBALLSIZE,p1x,p1y)); + vset(p2,p2x,p2y,tb_project_to_sphere(TRACKBALLSIZE,p2x,p2y)); + + /* + * Now, we want the cross product of P1 and P2 + */ + vcross(p2,p1,a); + + /* + * Figure out how much to rotate around that axis. + */ + vsub(p1,p2,d); + t = vlength(d) / (2.0*TRACKBALLSIZE); + + /* + * Avoid problems with out-of-control values... + */ + if (t > 1.0) t = 1.0; + if (t < -1.0) t = -1.0; + phi = 2.0 * asin(t); + + axis_to_quat(a,phi,q); +} + +/* + * Given an axis and angle, compute quaternion. + */ +void +axis_to_quat(float a[3], float phi, float q[4]) +{ + vnormal(a); + vcopy(a,q); + vscale(q,sin(phi/2.0)); + q[3] = cos(phi/2.0); +} + +/* + * Project an x,y pair onto a sphere of radius r OR a hyperbolic sheet + * if we are away from the center of the sphere. + */ +static float +tb_project_to_sphere(float r, float x, float y) +{ + float d, t, z; + + d = sqrt(x*x + y*y); + if (d < r * 0.70710678118654752440) { /* Inside sphere */ + z = sqrt(r*r - d*d); + } else { /* On hyperbola */ + t = r / 1.41421356237309504880; + z = t*t / d; + } + return z; +} + +/* + * Given two rotations, e1 and e2, expressed as quaternion rotations, + * figure out the equivalent single rotation and stuff it into dest. + * + * This routine also normalizes the result every RENORMCOUNT times it is + * called, to keep error from creeping in. + * + * NOTE: This routine is written so that q1 or q2 may be the same + * as dest (or each other). + */ + +#define RENORMCOUNT 97 + +void +add_quats(float q1[4], float q2[4], float dest[4]) +{ + static int count=0; + float t1[4], t2[4], t3[4]; + float tf[4]; + + vcopy(q1,t1); + vscale(t1,q2[3]); + + vcopy(q2,t2); + vscale(t2,q1[3]); + + vcross(q2,q1,t3); + vadd(t1,t2,tf); + vadd(t3,tf,tf); + tf[3] = q1[3] * q2[3] - vdot(q1,q2); + + dest[0] = tf[0]; + dest[1] = tf[1]; + dest[2] = tf[2]; + dest[3] = tf[3]; + + if (++count > RENORMCOUNT) { + count = 0; + normalize_quat(dest); + } +} + +/* + * Quaternions always obey: a^2 + b^2 + c^2 + d^2 = 1.0 + * If they don't add up to 1.0, dividing by their magnitued will + * renormalize them. + * + * Note: See the following for more information on quaternions: + * + * - Shoemake, K., Animating rotation with quaternion curves, Computer + * Graphics 19, No 3 (Proc. SIGGRAPH'85), 245-254, 1985. + * - Pletinckx, D., Quaternion calculus as a basic tool in computer + * graphics, The Visual Computer 5, 2-13, 1989. + */ +static void +normalize_quat(float q[4]) +{ + int i; + float mag; + + mag = (q[0]*q[0] + q[1]*q[1] + q[2]*q[2] + q[3]*q[3]); + for (i = 0; i < 4; i++) q[i] /= mag; +} + +/* + * Build a rotation matrix, given a quaternion rotation. + * + */ +void +build_rotmatrix(float m[4][4], float q[4]) +{ + m[0][0] = 1.0 - 2.0 * (q[1] * q[1] + q[2] * q[2]); + m[0][1] = 2.0 * (q[0] * q[1] - q[2] * q[3]); + m[0][2] = 2.0 * (q[2] * q[0] + q[1] * q[3]); + m[0][3] = 0.0; + + m[1][0] = 2.0 * (q[0] * q[1] + q[2] * q[3]); + m[1][1]= 1.0 - 2.0 * (q[2] * q[2] + q[0] * q[0]); + m[1][2] = 2.0 * (q[1] * q[2] - q[0] * q[3]); + m[1][3] = 0.0; + + m[2][0] = 2.0 * (q[2] * q[0] - q[1] * q[3]); + m[2][1] = 2.0 * (q[1] * q[2] + q[0] * q[3]); + m[2][2] = 1.0 - 2.0 * (q[1] * q[1] + q[0] * q[0]); + m[2][3] = 0.0; + + m[3][0] = 0.0; + m[3][1] = 0.0; + m[3][2] = 0.0; + m[3][3] = 1.0; +} + diff --git a/utils/glcanvas/samples/penguin/trackball.h b/utils/glcanvas/samples/penguin/trackball.h new file mode 100644 index 0000000000..b676fb4e54 --- /dev/null +++ b/utils/glcanvas/samples/penguin/trackball.h @@ -0,0 +1,78 @@ +/* + * (c) Copyright 1993, 1994, Silicon Graphics, Inc. + * ALL RIGHTS RESERVED + * Permission to use, copy, modify, and distribute this software for + * any purpose and without fee is hereby granted, provided that the above + * copyright notice appear in all copies and that both the copyright notice + * and this permission notice appear in supporting documentation, and that + * the name of Silicon Graphics, Inc. not be used in advertising + * or publicity pertaining to distribution of the software without specific, + * written prior permission. + * + * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS" + * AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR + * FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON + * GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT, + * SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY + * KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION, + * LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF + * THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC. HAS BEEN + * ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE + * POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE. + * + * US Government Users Restricted Rights + * Use, duplication, or disclosure by the Government is subject to + * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph + * (c)(1)(ii) of the Rights in Technical Data and Computer Software + * clause at DFARS 252.227-7013 and/or in similar or successor + * clauses in the FAR or the DOD or NASA FAR Supplement. + * Unpublished-- rights reserved under the copyright laws of the + * United States. Contractor/manufacturer is Silicon Graphics, + * Inc., 2011 N. Shoreline Blvd., Mountain View, CA 94039-7311. + * + * OpenGL(TM) is a trademark of Silicon Graphics, Inc. + */ +/* + * trackball.h + * A virtual trackball implementation + * Written by Gavin Bell for Silicon Graphics, November 1988. + */ + +/* + * Pass the x and y coordinates of the last and current positions of + * the mouse, scaled so they are from (-1.0 ... 1.0). + * + * The resulting rotation is returned as a quaternion rotation in the + * first paramater. + */ +void +trackball(float q[4], float p1x, float p1y, float p2x, float p2y); + +/* + * Given two quaternions, add them together to get a third quaternion. + * Adding quaternions to get a compound rotation is analagous to adding + * translations to get a compound translation. When incrementally + * adding rotations, the first argument here should be the new + * rotation, the second and third the total rotation (which will be + * over-written with the resulting new total rotation). + */ +void +add_quats(float *q1, float *q2, float *dest); + +/* + * A useful function, builds a rotation matrix in Matrix based on + * given quaternion. + */ +void +build_rotmatrix(float m[4][4], float q[4]); + +/* + * This function computes a quaternion based on an axis (defined by + * the given vector) and an angle about which to rotate. The angle is + * expressed in radians. The result is put into the third argument. + */ +void +axis_to_quat(float a[3], float phi, float q[4]); + diff --git a/utils/glcanvas/src/Makefile b/utils/glcanvas/src/Makefile deleted file mode 100644 index 35ce1069fd..0000000000 --- a/utils/glcanvas/src/Makefile +++ /dev/null @@ -1 +0,0 @@ -include ../../../setup/general/makedirs diff --git a/utils/glcanvas/src/Makefile.in b/utils/glcanvas/src/Makefile.in deleted file mode 100644 index 79d15e4503..0000000000 --- a/utils/glcanvas/src/Makefile.in +++ /dev/null @@ -1,67 +0,0 @@ -# -# wxGLCanvas source makefile for Unix -# -# Copyright 1998, Robert Roebling -# - -# wxWindows base directory -WXBASEDIR=@WXBASEDIR@ - -# set the OS type for compilation -OS=@OS@ - -# compile a library only -RULE=gslib - -# needed for unactivated -NONE= - -# define library name -LIB_TARGET=wx_opengl_gtk -LIB_MAJOR=1 -LIB_MINOR=0 - -# define library sources - -LIB_CPP_SRC= \ -\ - glcanvas.cpp - -#define library objects -LIB_OBJ= \ -\ - $(LIB_CPP_SRC:.cpp=.o) - -all:: - -clean:: - -#additional things needed for compile -ADD_COMPILE= - -# include the definitions now -include ../../../../template.mak - -install:: - @echo "Installing library files and headers for libwx_opengl_gtk.." - @echo " Creating directory.." - @$(WXBASEDIR)/mkinstalldirs /usr/local/include/wx_opengl - @echo " Copying headers from /include/wx" - @cd $(WXBASEDIR)/utils/glcanvas/src ; \ - for f in *.h ; do \ - rm -f /usr/local/include/wx_opengl/$$f ; \ - $(INSTALL_DATA) $$f /usr/local/include/wx_opengl/$$f ; \ - done - @echo " Copying static library files to /usr/local/lib" - @cd $(WXBASEDIR)/lib/$(OS) ; \ - for f in libwx_opengl_gtk.a ; do \ - rm -f /usr/local/lib/$$f ; \ - $(INSTALL_DATA) $$f /usr/local/lib/$$f ; \ - done - @echo " Copying shared libraries to /usr/local/lib" - @cd $(WXBASEDIR)/lib/$(OS) ; \ - for f in libwx_opengl_gtk.so* ; do \ - rm -f /usr/local/lib/$$f ; \ - $(INSTALL_PROGRAM) $$f /usr/local/lib/$$f ; \ - done - diff --git a/utils/glcanvas/src/glcanvas.cpp b/utils/glcanvas/src/glcanvas.cpp index a668badcab..9e16370d1e 100644 --- a/utils/glcanvas/src/glcanvas.cpp +++ b/utils/glcanvas/src/glcanvas.cpp @@ -20,17 +20,19 @@ #include "wx/module.h" #include "wx/app.h" +extern "C" { #include "gtk/gtk.h" #include "gdk/gdk.h" -extern "C" { #include "gdk/gdkx.h" } +#include "wx/gtk/win_gtk.h" + //--------------------------------------------------------------------------- -// global variables +// global data //--------------------------------------------------------------------------- -XVisualInfo *g_visual_info = (XVisualInfo*) NULL; +XVisualInfo *g_vi = (XVisualInfo*) NULL; //--------------------------------------------------------------------------- // wxGLContext @@ -41,25 +43,25 @@ IMPLEMENT_CLASS(wxGLContext,wxObject) wxGLContext::wxGLContext( bool WXUNUSED(isRGB), wxWindow *win, const wxPalette& WXUNUSED(palette) ) { m_window = win; - m_widget = win->m_wxwindow; + m_widget = ((wxGLCanvas*)win)->m_glWidget; - wxCHECK_RET( g_visual_info != NULL, "invalid visual for OpenGl" ); + wxCHECK_RET( g_vi, "invalid visual for OpenGl" ); - m_glContext = glXCreateContext( GDK_DISPLAY(), g_visual_info, None, GL_TRUE ); + m_glContext = glXCreateContext( GDK_DISPLAY(), g_vi, None, GL_TRUE ); - wxCHECK_RET( m_glContext != NULL, "Couldn't create OpenGl context" ); - - glXMakeCurrent( GDK_DISPLAY(), GDK_WINDOW_XWINDOW(m_widget->window), m_glContext ); + wxCHECK_RET( m_glContext, "Couldn't create OpenGl context" ); } wxGLContext::~wxGLContext() { - if (m_glContext) - { - glXMakeCurrent( GDK_DISPLAY(), GDK_WINDOW_XWINDOW(m_widget->window), m_glContext ); + if (!m_glContext) return; - glXDestroyContext( GDK_DISPLAY(), m_glContext ); + if (m_glContext == glXGetCurrentContext()) + { + glXMakeCurrent( GDK_DISPLAY(), None, NULL); } + + glXDestroyContext( GDK_DISPLAY(), m_glContext ); } void wxGLContext::SwapBuffers() @@ -116,12 +118,71 @@ BEGIN_EVENT_TABLE(wxGLCanvas, wxScrolledWindow) EVT_SIZE(wxGLCanvas::OnSize) END_EVENT_TABLE() -wxGLCanvas::wxGLCanvas(wxWindow *parent, wxWindowID id, - const wxPoint& pos, const wxSize& size, long style, const wxString& name, - int *WXUNUSED(attribList), const wxPalette& palette): - wxScrolledWindow(parent, id, pos, size, style, name) +wxGLCanvas::wxGLCanvas( wxWindow *parent, wxWindowID id, + const wxPoint& pos, const wxSize& size, + long style, const wxString& name, + int *attribList, + const wxPalette& palette ) +{ + Create( parent, id, pos, size, style, name, attribList, palette ); +} + +bool wxGLCanvas::Create( wxWindow *parent, wxWindowID id, + const wxPoint& pos, const wxSize& size, + long style, const wxString& name, + int *attribList, + const wxPalette& palette ) { + if (!attribList) + { + int data[] = { GLX_RGBA, + GLX_DOUBLEBUFFER, + GLX_DEPTH_SIZE, 1, + None }; + attribList = (int*) data; + } + + Display *dpy = GDK_DISPLAY(); + + g_vi = glXChooseVisual( dpy, DefaultScreen(dpy), attribList ); + + GdkVisual *visual = gdkx_visual_get( g_vi->visualid ); + GdkColormap *colormap = gdk_colormap_new( gdkx_visual_get(g_vi->visualid), TRUE ); + + gtk_widget_push_colormap( colormap ); + gtk_widget_push_visual( visual ); + + m_glWidget = gtk_drawing_area_new(); + gtk_widget_set_events( m_glWidget, + GDK_EXPOSURE_MASK | + GDK_POINTER_MOTION_HINT_MASK | + GDK_POINTER_MOTION_MASK | + GDK_BUTTON_MOTION_MASK | + GDK_BUTTON1_MOTION_MASK | + GDK_BUTTON2_MOTION_MASK | + GDK_BUTTON3_MOTION_MASK | + GDK_BUTTON_PRESS_MASK | + GDK_BUTTON_RELEASE_MASK | + GDK_KEY_PRESS_MASK | + GDK_KEY_RELEASE_MASK | + GDK_ENTER_NOTIFY_MASK | + GDK_LEAVE_NOTIFY_MASK ); + + gtk_widget_pop_visual(); + gtk_widget_pop_colormap(); + + wxScrolledWindow::Create( parent, id, pos, size, style, name ); + + gtk_myfixed_put( GTK_MYFIXED(m_wxwindow), m_glWidget, 0, 0 ); + + gtk_widget_show( m_glWidget ); + m_glContext = new wxGLContext( TRUE, this, palette ); + + XFree( g_vi ); + g_vi = (XVisualInfo*) NULL; + + return TRUE; } wxGLCanvas::~wxGLCanvas() @@ -137,13 +198,12 @@ void wxGLCanvas::SwapBuffers() void wxGLCanvas::OnSize(wxSizeEvent& WXUNUSED(event)) { int width, height; - GetClientSize(& width, & height); - - if (m_glContext) + GetClientSize( &width, &height ); + if (m_glContext && GTK_WIDGET_REALIZED(m_glWidget) ) { - m_glContext->SetCurrent(); - - glViewport(0, 0, (GLint)width, (GLint)height); + SetCurrent(); + + glViewport(0, 0, (GLint)width, (GLint)height ); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glFrustum( -1.0, 1.0, -1.0, 1.0, 5.0, 15.0 ); @@ -161,39 +221,92 @@ void wxGLCanvas::SetColour( const char *colour ) if (m_glContext) m_glContext->SetColour( colour ); } -//-------------------------------------------------------------------- -// wxGLModule -//-------------------------------------------------------------------- - -class wxGLModule : public wxModule +void wxGLCanvas::SetSize( int x, int y, int width, int height, int sizeFlags ) { -public: - virtual bool OnInit(); - virtual void OnExit(); + if (m_resizing) return; // I don't like recursions + m_resizing = TRUE; + + if (m_parent->m_wxwindow == NULL) // i.e. wxNotebook + { + // don't set the size for children of wxNotebook, just take the values. + m_x = x; + m_y = y; + m_width = width; + m_height = height; + } + else + { + int old_width = m_width; + int old_height = m_height; + + if ((sizeFlags & wxSIZE_USE_EXISTING) == wxSIZE_USE_EXISTING) + { + if (x != -1) m_x = x; + if (y != -1) m_y = y; + if (width != -1) m_width = width; + if (height != -1) m_height = height; + } + else + { + m_x = x; + m_y = y; + m_width = width; + m_height = height; + } + + if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH) + { + if (width == -1) m_width = 80; + } + + if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT) + { + if (height == -1) m_height = 26; + } + + if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth; + if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight; + if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_maxWidth; + if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_maxHeight; + + wxPoint pt( m_parent->GetClientAreaOrigin() ); + gtk_myfixed_move( GTK_MYFIXED(m_parent->m_wxwindow), m_widget, m_x+pt.x, m_y+pt.y ); + + if ((old_width != m_width) || (old_height != m_height)) + { + gtk_widget_set_usize( m_widget, m_width, m_height ); + + gtk_drawing_area_size( GTK_DRAWING_AREA(m_glWidget), m_width, m_height ); + + GtkAllocation allo; + allo.x = 0; + allo.y = 0; + allo.width = m_width; + allo.height = m_height; + gtk_widget_size_allocate( m_glWidget, &allo ); + } + } -private: - DECLARE_DYNAMIC_CLASS(wxGLModule) -}; + m_sizeSet = TRUE; -IMPLEMENT_DYNAMIC_CLASS(wxGLModule, wxModule) + wxSizeEvent event( wxSize(m_width,m_height), GetId() ); + event.SetEventObject( this ); + GetEventHandler()->ProcessEvent( event ); -bool wxGLModule::OnInit() -{ - int data[] = { GLX_RGBA,GLX_RED_SIZE,1,GLX_GREEN_SIZE,1, - GLX_BLUE_SIZE,1,GLX_DOUBLEBUFFER,None}; + m_resizing = FALSE; +} - g_visual_info = glXChooseVisual( GDK_DISPLAY(), DefaultScreen(GDK_DISPLAY()), data ); - - wxCHECK_MSG( g_visual_info != NULL, FALSE, "Couldn't choose visual for OpenGl" ); - - wxVisualSetByExternal = gdkx_visual_get(g_visual_info->visualid); - - wxColormapSetByExternal = gdk_colormap_new( gdkx_visual_get(g_visual_info->visualid), TRUE ); - - return TRUE; +void wxGLCanvas::SetSize( int width, int height ) +{ + SetSize( -1, -1, width, height, wxSIZE_USE_EXISTING ); } -void wxGLModule::OnExit() +GtkWidget *wxGLCanvas::GetConnectWidget() { + return m_glWidget; } +bool wxGLCanvas::IsOwnGtkWindow( GdkWindow *window ) +{ + return (window == m_glWidget->window); +} diff --git a/utils/glcanvas/src/glcanvas.h b/utils/glcanvas/src/glcanvas.h index f277c771c9..c32e176a61 100644 --- a/utils/glcanvas/src/glcanvas.h +++ b/utils/glcanvas/src/glcanvas.h @@ -19,9 +19,11 @@ #include "wx/defs.h" #include "wx/scrolwin.h" +extern "C" { #include "GL/gl.h" #include "GL/glx.h" #include "GL/glu.h" +} //--------------------------------------------------------------------------- // classes @@ -75,9 +77,20 @@ class wxGLCanvas: public wxScrolledWindow DECLARE_CLASS(wxGLCanvas) public: - wxGLCanvas(wxWindow *parent, wxWindowID id = -1, const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxDefaultSize, long style = 0, - const wxString& name = "GLCanvas", int *attribList = 0, const wxPalette& palette = wxNullPalette); + wxGLCanvas( wxWindow *parent, wxWindowID id = -1, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = 0, const wxString& name = "GLCanvas", + int *attribList = (int*) NULL, + const wxPalette& palette = wxNullPalette ); + + bool Create( wxWindow *parent, wxWindowID id = -1, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = 0, const wxString& name = "GLCanvas", + int *attribList = (int*) NULL, + const wxPalette& palette = wxNullPalette ); + ~wxGLCanvas(); void SetCurrent(); @@ -86,11 +99,19 @@ class wxGLCanvas: public wxScrolledWindow void OnSize(wxSizeEvent& event); - inline wxGLContext* GetContext() const { return m_glContext; } + inline wxGLContext* GetContext() const { return m_glContext; } - protected: + // implementation - wxGLContext* m_glContext; // this is typedef-ed ptr, in fact + virtual void SetSize( int x, int y, int width, int height, + int sizeFlags = wxSIZE_AUTO ); + virtual void SetSize( int width, int height ); + + virtual GtkWidget *GetConnectWidget(); + bool IsOwnGtkWindow( GdkWindow *window ); + + wxGLContext *m_glContext; + GtkWidget *m_glWidget; DECLARE_EVENT_TABLE() }; -- 2.45.2