extern wxApp *wxTheApp;
-extern GdkVisual *wxVisualSetByExternal;
-extern GdkColormap *wxColormapSetByExternal;
-
//-----------------------------------------------------------------------------
// global functions
//-----------------------------------------------------------------------------
/* 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();
extern wxApp *wxTheApp;
-extern GdkVisual *wxVisualSetByExternal;
-extern GdkColormap *wxColormapSetByExternal;
-
//-----------------------------------------------------------------------------
// global functions
//-----------------------------------------------------------------------------
/* 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();
extern wxList wxPendingDelete;
extern wxResourceCache *wxTheResourceCache;
-GdkVisual *wxVisualSetByExternal = (GdkVisual*) NULL;
-GdkColormap *wxColormapSetByExternal = (GdkColormap*) NULL;
-
unsigned char g_palette[64*3] =
{
0x0, 0x0, 0x0,
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;
}
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().
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 |
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;
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);
extern wxList wxPendingDelete;
extern wxResourceCache *wxTheResourceCache;
-GdkVisual *wxVisualSetByExternal = (GdkVisual*) NULL;
-GdkColormap *wxColormapSetByExternal = (GdkColormap*) NULL;
-
unsigned char g_palette[64*3] =
{
0x0, 0x0, 0x0,
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;
}
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().
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 |
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;
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);
+++ /dev/null
-include ../../setup/general/makedirs
----------
No known issues, though probably palettes aren't correctly
-handled under Windows.
+handled under Windows. They are ignored under GTK.
--- /dev/null
+
+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
#include "cube.h"
-IMPLEMENT_APP(MyApp)
-
// `Main program' equivalent, creating windows and returning main app frame
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);
glEnable(GL_LIGHT0);
}
+IMPLEMENT_APP(MyApp)
+
BEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_MENU(wxID_EXIT, MyFrame::OnExit)
END_EVENT_TABLE()
int width, height;
GetClientSize(& width, & height);
- if ( GetContext() )
+ if (GetContext())
+ {
+ SetCurrent();
glViewport(0, 0, width, height);
+ }
}
void TestGLCanvas::OnEraseBackground(wxEraseEvent& event)
--- /dev/null
+
+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
--- /dev/null
+
+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
--- /dev/null
+/*
+ * Copyright (C) 1998 Janne Löf <jlof@mail.student.oulu.fi>
+ *
+ * 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 <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+
+#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; i<face->index_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; i<lwo->vertex_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; i<lw_object->face_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; i<lw_object->face_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; j<face->index_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; i<lwo->vertex_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; i<lwo->vertex_cnt; i++) {
+ lwo->vertex[i*3+0] *= scale;
+ lwo->vertex[i*3+1] *= scale;
+ lwo->vertex[i*3+2] *= scale;
+ }
+}
+
+
--- /dev/null
+/*
+ * Copyright (C) 1998 Janne Löf <jlof@mail.student.oulu.fi>
+ *
+ * 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 <GL/gl.h>
+
+#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 */
+
--- /dev/null
+/////////////////////////////////////////////////////////////////////////////
+// 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 <GL/glu.h>
+
+#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);
+}
+
+
--- /dev/null
+/////////////////////////////////////////////////////////////////////////////
+// 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
+
--- /dev/null
+/*
+ * (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 <math.h>
+#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;
+}
+
--- /dev/null
+/*
+ * (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]);
+
+++ /dev/null
-include ../../../setup/general/makedirs
+++ /dev/null
-#
-# 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
-
#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
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()
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()
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 );
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);
+}
#include "wx/defs.h"
#include "wx/scrolwin.h"
+extern "C" {
#include "GL/gl.h"
#include "GL/glx.h"
#include "GL/glu.h"
+}
//---------------------------------------------------------------------------
// classes
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();
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()
};