First attempt at adding John Tsiombikas' spaceball support for X11. It compiles under Windows but the demo program does not. See e-mail from John Tsiombikas dated 10/15/2009 9:43 AM.
git-svn-id: https://svn.code.sf.net/p/freeglut/code/trunk@837 7f0cb862-5218-0410-a997-914c9d46530a
This commit is contained in:
parent
755316c21d
commit
803c4f86a2
7
.gitattributes
vendored
7
.gitattributes
vendored
@ -94,6 +94,12 @@ freeglut/freeglut/progs/demos/smooth_opengl3/Makefile.am -text
|
||||
freeglut/freeglut/progs/demos/smooth_opengl3/smooth_opengl3.c -text
|
||||
freeglut/freeglut/progs/demos/smooth_opengl3/smooth_opengl3.dsp -text
|
||||
freeglut/freeglut/progs/demos/smooth_opengl3/smooth_opengl3Static.dsp -text
|
||||
freeglut/freeglut/progs/demos/spaceball/Makefile.am -text
|
||||
freeglut/freeglut/progs/demos/spaceball/spaceball.c -text
|
||||
freeglut/freeglut/progs/demos/spaceball/spaceball.dsp -text
|
||||
freeglut/freeglut/progs/demos/spaceball/vmath.c -text
|
||||
freeglut/freeglut/progs/demos/spaceball/vmath.h -text
|
||||
freeglut/freeglut/progs/demos/spaceball/vmath.inl -text
|
||||
freeglut/freeglut/src/Makefile.am svn_keywords=Author+Date+Id+Revision
|
||||
freeglut/freeglut/src/freeglut_callbacks.c svn_keywords=Author+Date+Id+Revision
|
||||
freeglut/freeglut/src/freeglut_cursor.c svn_keywords=Author+Date+Id+Revision
|
||||
@ -112,6 +118,7 @@ freeglut/freeglut/src/freeglut_main.c svn_keywords=Author+Date+Id+Revision
|
||||
freeglut/freeglut/src/freeglut_menu.c svn_keywords=Author+Date+Id+Revision
|
||||
freeglut/freeglut/src/freeglut_misc.c svn_keywords=Author+Date+Id+Revision
|
||||
freeglut/freeglut/src/freeglut_overlay.c svn_keywords=Author+Date+Id+Revision
|
||||
freeglut/freeglut/src/freeglut_spaceball.c -text
|
||||
freeglut/freeglut/src/freeglut_state.c svn_keywords=Author+Date+Id+Revision
|
||||
freeglut/freeglut/src/freeglut_stroke_mono_roman.c svn_keywords=Author+Date+Id+Revision
|
||||
freeglut/freeglut/src/freeglut_stroke_roman.c svn_keywords=Author+Date+Id+Revision
|
||||
|
@ -95,5 +95,5 @@ if test "x$enable_debug" = xyes; then
|
||||
fi
|
||||
|
||||
# Generate output.
|
||||
AC_CONFIG_FILES([Makefile doc/Makefile include/GL/Makefile include/Makefile progs/Makefile progs/demos/CallbackMaker/Makefile progs/demos/Fractals/Makefile progs/demos/Fractals_random/Makefile progs/demos/Lorenz/Makefile progs/demos/Makefile progs/demos/One/Makefile progs/demos/shapes/Makefile progs/demos/smooth_opengl3/Makefile src/Makefile])
|
||||
AC_CONFIG_FILES([Makefile doc/Makefile include/GL/Makefile include/Makefile progs/Makefile progs/demos/CallbackMaker/Makefile progs/demos/Fractals/Makefile progs/demos/Fractals_random/Makefile progs/demos/Lorenz/Makefile progs/demos/Makefile progs/demos/One/Makefile progs/demos/shapes/Makefile progs/demos/smooth_opengl3/Makefile progs/demos/spaceball/Makefile src/Makefile])
|
||||
AC_OUTPUT
|
||||
|
@ -1,2 +1,2 @@
|
||||
EXTRA_DIST = demos.dsw
|
||||
SUBDIRS = CallbackMaker Fractals Fractals_random Lorenz One shapes smooth_opengl3
|
||||
SUBDIRS = CallbackMaker Fractals Fractals_random Lorenz One shapes smooth_opengl3 spaceball
|
||||
|
@ -159,6 +159,18 @@ Package=<4>
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "spaceball"=.\spaceball\spaceball.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Global:
|
||||
|
||||
Package=<5>
|
||||
|
6
freeglut/freeglut/progs/demos/spaceball/Makefile.am
Normal file
6
freeglut/freeglut/progs/demos/spaceball/Makefile.am
Normal file
@ -0,0 +1,6 @@
|
||||
EXTRA_DIST = spaceball.c vmath.c vmath.h vmath.inl
|
||||
|
||||
noinst_PROGRAMS = spaceball
|
||||
spaceball_SOURCES = spaceball.c vmath.c
|
||||
spaceball_LDFLAGS = -export-dynamic ../../../src/lib@LIBRARY@.la
|
||||
spaceball_CFLAGS = -I$(top_srcdir)/include $(X_CFLAGS)
|
173
freeglut/freeglut/progs/demos/spaceball/spaceball.c
Normal file
173
freeglut/freeglut/progs/demos/spaceball/spaceball.c
Normal file
@ -0,0 +1,173 @@
|
||||
/* Spaceball demo
|
||||
*
|
||||
* Written by John Tsiombikas <nuclear@member.fsf.org>
|
||||
* (converted from the libspnav cube example)
|
||||
*
|
||||
* Use the spaceball to move and rotate the colored cube.
|
||||
* Pressing any button will reset the cube at its original location.
|
||||
*
|
||||
* Press escape or q to exit.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <GL/freeglut.h>
|
||||
#include "vmath.h"
|
||||
|
||||
void draw_cube(void);
|
||||
|
||||
/* callbacks */
|
||||
void disp(void);
|
||||
void reshape(int x, int y);
|
||||
void keyb(unsigned char key, int x, int y);
|
||||
void sbmot(int x, int y, int z); /* spaceball translation */
|
||||
void sbrot(int x, int y, int z); /* spaceball rotation */
|
||||
void sbbut(int bn, int state); /* spaceball button */
|
||||
|
||||
vec3_t pos = {0, 0, -6};
|
||||
quat_t rot = {0, 0, 0, 1};
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
glutInit(&argc, argv);
|
||||
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
|
||||
glutCreateWindow("spaceball demo");
|
||||
|
||||
glutDisplayFunc(disp);
|
||||
glutReshapeFunc(reshape);
|
||||
glutKeyboardFunc(keyb);
|
||||
glutSpaceballMotionFunc(sbmot);
|
||||
glutSpaceballRotateFunc(sbrot);
|
||||
glutSpaceballButtonFunc(sbbut);
|
||||
|
||||
glEnable(GL_CULL_FACE);
|
||||
|
||||
glutMainLoop();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void disp(void)
|
||||
{
|
||||
mat4_t xform;
|
||||
|
||||
quat_to_mat(xform, rot);
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
glTranslatef(pos.x, pos.y, pos.z);
|
||||
glMultTransposeMatrixf((float*)xform);
|
||||
|
||||
draw_cube();
|
||||
|
||||
glutSwapBuffers();
|
||||
}
|
||||
|
||||
void draw_cube(void)
|
||||
{
|
||||
glBegin(GL_QUADS);
|
||||
/* face +Z */
|
||||
glNormal3f(0, 0, 1);
|
||||
glColor3f(1, 0, 0);
|
||||
glVertex3f(-1, -1, 1);
|
||||
glVertex3f(1, -1, 1);
|
||||
glVertex3f(1, 1, 1);
|
||||
glVertex3f(-1, 1, 1);
|
||||
/* face +X */
|
||||
glNormal3f(1, 0, 0);
|
||||
glColor3f(0, 1, 0);
|
||||
glVertex3f(1, -1, 1);
|
||||
glVertex3f(1, -1, -1);
|
||||
glVertex3f(1, 1, -1);
|
||||
glVertex3f(1, 1, 1);
|
||||
/* face -Z */
|
||||
glNormal3f(0, 0, -1);
|
||||
glColor3f(0, 0, 1);
|
||||
glVertex3f(1, -1, -1);
|
||||
glVertex3f(-1, -1, -1);
|
||||
glVertex3f(-1, 1, -1);
|
||||
glVertex3f(1, 1, -1);
|
||||
/* face -X */
|
||||
glNormal3f(-1, 0, 0);
|
||||
glColor3f(1, 1, 0);
|
||||
glVertex3f(-1, -1, -1);
|
||||
glVertex3f(-1, -1, 1);
|
||||
glVertex3f(-1, 1, 1);
|
||||
glVertex3f(-1, 1, -1);
|
||||
/* face +Y */
|
||||
glNormal3f(0, 1, 0);
|
||||
glColor3f(0, 1, 1);
|
||||
glVertex3f(-1, 1, 1);
|
||||
glVertex3f(1, 1, 1);
|
||||
glVertex3f(1, 1, -1);
|
||||
glVertex3f(-1, 1, -1);
|
||||
/* face -Y */
|
||||
glNormal3f(0, -1, 0);
|
||||
glColor3f(1, 0, 1);
|
||||
glVertex3f(-1, -1, -1);
|
||||
glVertex3f(1, -1, -1);
|
||||
glVertex3f(1, -1, 1);
|
||||
glVertex3f(-1, -1, 1);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
/* 45deg fov */
|
||||
#define FOV (M_PI / 4.0)
|
||||
|
||||
void reshape(int x, int y)
|
||||
{
|
||||
float aspect = (float)x / (float)y;
|
||||
float halfy = tan(FOV / 2.0);
|
||||
float halfx = halfy * aspect;
|
||||
|
||||
glViewport(0, 0, x, y);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
glFrustum(-halfx, halfx, -halfy, halfy, 1.0, 1000.0);
|
||||
}
|
||||
|
||||
void keyb(unsigned char key, int x, int y)
|
||||
{
|
||||
switch(key) {
|
||||
case 'q':
|
||||
case 'Q':
|
||||
case 27:
|
||||
exit(0);
|
||||
|
||||
case ' ':
|
||||
/* reset initial view */
|
||||
pos = v3_cons(0, 0, -6);
|
||||
rot = quat_cons(1, 0, 0, 0);
|
||||
glutPostRedisplay();
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void sbmot(int x, int y, int z)
|
||||
{
|
||||
pos.x += x * 0.001;
|
||||
pos.y += y * 0.001;
|
||||
pos.z -= z * 0.001;
|
||||
glutPostRedisplay();
|
||||
}
|
||||
|
||||
void sbrot(int x, int y, int z)
|
||||
{
|
||||
float axis_len = sqrt(x * x + y * y + z * z);
|
||||
rot = quat_rotate(rot, axis_len * 0.001, -x / axis_len, -y / axis_len, z / axis_len);
|
||||
glutPostRedisplay();
|
||||
}
|
||||
|
||||
void sbbut(int bn, int state)
|
||||
{
|
||||
if(state == GLUT_DOWN) {
|
||||
pos = v3_cons(0, 0, -6);
|
||||
rot = quat_cons(1, 0, 0, 0);
|
||||
glutPostRedisplay();
|
||||
}
|
||||
}
|
96
freeglut/freeglut/progs/demos/spaceball/spaceball.dsp
Normal file
96
freeglut/freeglut/progs/demos/spaceball/spaceball.dsp
Normal file
@ -0,0 +1,96 @@
|
||||
# Microsoft Developer Studio Project File - Name="spaceball" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||
|
||||
CFG=spaceball - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "spaceball.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "spaceball.mak" CFG="spaceball - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "spaceball - Win32 Release" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE "spaceball - Win32 Debug" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "spaceball - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
|
||||
!ELSEIF "$(CFG)" == "spaceball - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "spaceball - Win32 Release"
|
||||
# Name "spaceball - Win32 Debug"
|
||||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||
# End Group
|
||||
# Begin Group "Header Files"
|
||||
|
||||
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||||
# End Group
|
||||
# Begin Group "Resource Files"
|
||||
|
||||
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
|
||||
# End Group
|
||||
# End Target
|
||||
# End Project
|
16
freeglut/freeglut/progs/demos/spaceball/vmath.c
Normal file
16
freeglut/freeglut/progs/demos/spaceball/vmath.c
Normal file
@ -0,0 +1,16 @@
|
||||
#include <math.h>
|
||||
#include "vmath.h"
|
||||
|
||||
quat_t quat_rotate(quat_t q, float angle, float x, float y, float z)
|
||||
{
|
||||
quat_t rq;
|
||||
float half_angle = angle * 0.5;
|
||||
float sin_half = sin(half_angle);
|
||||
|
||||
rq.w = cos(half_angle);
|
||||
rq.x = x * sin_half;
|
||||
rq.y = y * sin_half;
|
||||
rq.z = z * sin_half;
|
||||
|
||||
return quat_mul(q, rq);
|
||||
}
|
31
freeglut/freeglut/progs/demos/spaceball/vmath.h
Normal file
31
freeglut/freeglut/progs/demos/spaceball/vmath.h
Normal file
@ -0,0 +1,31 @@
|
||||
#ifndef VMATH_H_
|
||||
#define VMATH_H_
|
||||
|
||||
typedef struct { float x, y, z; } vec3_t;
|
||||
typedef struct { float x, y, z, w; } vec4_t;
|
||||
|
||||
typedef vec4_t quat_t;
|
||||
|
||||
typedef float mat4_t[4][4];
|
||||
|
||||
/* vector functions */
|
||||
static inline vec3_t v3_cons(float x, float y, float z);
|
||||
static inline float v3_dot(vec3_t v1, vec3_t v2);
|
||||
|
||||
/* quaternion functions */
|
||||
static inline quat_t quat_cons(float s, float x, float y, float z);
|
||||
static inline vec3_t quat_vec(quat_t q);
|
||||
static inline quat_t quat_mul(quat_t q1, quat_t q2);
|
||||
static inline void quat_to_mat(mat4_t res, quat_t q);
|
||||
quat_t quat_rotate(quat_t q, float angle, float x, float y, float z);
|
||||
|
||||
/* matrix functions */
|
||||
static inline void m4_cons(mat4_t m,
|
||||
float m11, float m12, float m13, float m14,
|
||||
float m21, float m22, float m23, float m24,
|
||||
float m31, float m32, float m33, float m34,
|
||||
float m41, float m42, float m43, float m44);
|
||||
|
||||
#include "vmath.inl"
|
||||
|
||||
#endif /* VMATH_H_ */
|
68
freeglut/freeglut/progs/demos/spaceball/vmath.inl
Normal file
68
freeglut/freeglut/progs/demos/spaceball/vmath.inl
Normal file
@ -0,0 +1,68 @@
|
||||
/* vector functions */
|
||||
static inline vec3_t v3_cons(float x, float y, float z)
|
||||
{
|
||||
vec3_t res;
|
||||
res.x = x;
|
||||
res.y = y;
|
||||
res.z = z;
|
||||
return res;
|
||||
}
|
||||
|
||||
static inline vec3_t quat_vec(quat_t q)
|
||||
{
|
||||
vec3_t v;
|
||||
v.x = q.x;
|
||||
v.y = q.y;
|
||||
v.z = q.z;
|
||||
return v;
|
||||
}
|
||||
|
||||
static inline float v3_dot(vec3_t v1, vec3_t v2)
|
||||
{
|
||||
return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
|
||||
}
|
||||
|
||||
/* quaternion functions */
|
||||
static inline quat_t quat_cons(float s, float x, float y, float z)
|
||||
{
|
||||
quat_t q;
|
||||
q.x = x;
|
||||
q.y = y;
|
||||
q.z = z;
|
||||
q.w = s;
|
||||
return q;
|
||||
}
|
||||
|
||||
static inline quat_t quat_mul(quat_t q1, quat_t q2)
|
||||
{
|
||||
quat_t res;
|
||||
vec3_t v1 = quat_vec(q1);
|
||||
vec3_t v2 = quat_vec(q2);
|
||||
|
||||
res.w = q1.w * q2.w - v3_dot(v1, v2);
|
||||
res.x = v2.x * q1.w + v1.x * q2.w + (v1.y * v2.z - v1.z * v2.y);
|
||||
res.y = v2.y * q1.w + v1.y * q2.w + (v1.z * v2.x - v1.x * v2.z);
|
||||
res.z = v2.z * q1.w + v1.z * q2.w + (v1.x * v2.y - v1.y * v2.x);
|
||||
return res;
|
||||
}
|
||||
|
||||
static inline void quat_to_mat(mat4_t res, quat_t q)
|
||||
{
|
||||
m4_cons(res, 1.0 - 2.0 * q.y*q.y - 2.0 * q.z*q.z, 2.0 * q.x * q.y + 2.0 * q.w * q.z, 2.0 * q.z * q.x - 2.0 * q.w * q.y, 0,
|
||||
2.0 * q.x * q.y - 2.0 * q.w * q.z, 1.0 - 2.0 * q.x*q.x - 2.0 * q.z*q.z, 2.0 * q.y * q.z + 2.0 * q.w * q.x, 0,
|
||||
2.0 * q.z * q.x + 2.0 * q.w * q.y, 2.0 * q.y * q.z - 2.0 * q.w * q.x, 1.0 - 2.0 * q.x*q.x - 2.0 * q.y*q.y, 0,
|
||||
0, 0, 0, 1);
|
||||
}
|
||||
|
||||
/* matrix functions */
|
||||
static inline void m4_cons(mat4_t m,
|
||||
float m11, float m12, float m13, float m14,
|
||||
float m21, float m22, float m23, float m24,
|
||||
float m31, float m32, float m33, float m34,
|
||||
float m41, float m42, float m43, float m44)
|
||||
{
|
||||
m[0][0] = m11; m[0][1] = m12; m[0][2] = m13; m[0][3] = m14;
|
||||
m[1][0] = m21; m[1][1] = m22; m[1][2] = m23; m[1][3] = m24;
|
||||
m[2][0] = m31; m[2][1] = m32; m[2][2] = m33; m[2][3] = m34;
|
||||
m[3][0] = m41; m[3][1] = m42; m[3][2] = m43; m[3][3] = m44;
|
||||
}
|
@ -28,6 +28,7 @@ lib@LIBRARY@_la_SOURCES = freeglut_callbacks.c \
|
||||
freeglut_geometry.c \
|
||||
freeglut_init.c \
|
||||
freeglut_input_devices.c \
|
||||
freeglut_spaceball.c \
|
||||
freeglut_joystick.c \
|
||||
freeglut_main.c \
|
||||
freeglut_menu.c \
|
||||
|
@ -301,6 +301,8 @@ void FGAPIENTRY glutWindowStatusFunc( void (* callback)( int ) )
|
||||
void FGAPIENTRY glutSpaceballMotionFunc( void (* callback)( int, int, int ) )
|
||||
{
|
||||
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpaceballMotionFunc" );
|
||||
fgInitialiseSpaceball();
|
||||
|
||||
SET_CALLBACK( SpaceMotion );
|
||||
}
|
||||
|
||||
@ -310,6 +312,8 @@ void FGAPIENTRY glutSpaceballMotionFunc( void (* callback)( int, int, int ) )
|
||||
void FGAPIENTRY glutSpaceballRotateFunc( void (* callback)( int, int, int ) )
|
||||
{
|
||||
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpaceballRotateFunc" );
|
||||
fgInitialiseSpaceball();
|
||||
|
||||
SET_CALLBACK( SpaceRotation );
|
||||
}
|
||||
|
||||
@ -319,6 +323,8 @@ void FGAPIENTRY glutSpaceballRotateFunc( void (* callback)( int, int, int ) )
|
||||
void FGAPIENTRY glutSpaceballButtonFunc( void (* callback)( int, int ) )
|
||||
{
|
||||
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpaceballButtonFunc" );
|
||||
fgInitialiseSpaceball();
|
||||
|
||||
SET_CALLBACK( SpaceButton );
|
||||
}
|
||||
|
||||
|
@ -564,9 +564,9 @@ enum
|
||||
/* Presently ignored */
|
||||
CB_Select,
|
||||
CB_OverlayDisplay,
|
||||
CB_SpaceMotion,
|
||||
CB_SpaceRotation,
|
||||
CB_SpaceButton,
|
||||
CB_SpaceMotion, /* presently implemented only on UNIX/X11 */
|
||||
CB_SpaceRotation, /* presently implemented only on UNIX/X11 */
|
||||
CB_SpaceButton, /* presently implemented only on UNIX/X11 */
|
||||
CB_Dials,
|
||||
CB_ButtonBox,
|
||||
CB_TabletMotion,
|
||||
@ -853,6 +853,19 @@ int fgInputDeviceDetect( void );
|
||||
void fgInitialiseInputDevices( void );
|
||||
void fgInputDeviceClose( void );
|
||||
|
||||
/* spaceball device functions, defined in freeglut_spaceball.c */
|
||||
void fgInitialiseSpaceball( void );
|
||||
void fgSpaceballClose( void );
|
||||
void fgSpaceballSetWindow( SFG_Window *window );
|
||||
|
||||
int fgHasSpaceball( void );
|
||||
int fgSpaceballNumButtons( void );
|
||||
|
||||
#if TARGET_HOST_POSIX_X11
|
||||
int fgIsSpaceballXEvent( const XEvent *ev );
|
||||
void fgSpaceballHandleXEvent( const XEvent *ev );
|
||||
#endif
|
||||
|
||||
/* Setting the cursor for a given window */
|
||||
void fgSetCursor ( SFG_Window *window, int cursorID );
|
||||
|
||||
|
@ -980,6 +980,10 @@ void FGAPIENTRY glutMainLoopEvent( void )
|
||||
switch( event.type )
|
||||
{
|
||||
case ClientMessage:
|
||||
if(fgIsSpaceballXEvent(&event)) {
|
||||
fgSpaceballHandleXEvent(&event);
|
||||
break;
|
||||
}
|
||||
/* Destroy the window when the WM_DELETE_WINDOW message arrives */
|
||||
if( (Atom) event.xclient.data.l[ 0 ] == fgDisplay.DeleteWindow )
|
||||
{
|
||||
|
456
freeglut/freeglut/src/freeglut_spaceball.c
Normal file
456
freeglut/freeglut/src/freeglut_spaceball.c
Normal file
@ -0,0 +1,456 @@
|
||||
/* Spaceball support for Linux.
|
||||
* Written by John Tsiombikas <nuclear@member.fsf.org>
|
||||
*
|
||||
* This code supports 3Dconnexion's 6-dof space-whatever devices.
|
||||
* It can communicate with either the proprietary 3Dconnexion daemon (3dxsrv)
|
||||
* free spacenavd (http://spacenav.sourceforge.net), through the "standard"
|
||||
* magellan X-based protocol.
|
||||
*/
|
||||
|
||||
#include <GL/freeglut.h>
|
||||
#include "freeglut_internal.h"
|
||||
|
||||
#if TARGET_HOST_POSIX_X11
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
enum {
|
||||
SPNAV_EVENT_ANY, /* used by spnav_remove_events() */
|
||||
SPNAV_EVENT_MOTION,
|
||||
SPNAV_EVENT_BUTTON /* includes both press and release */
|
||||
};
|
||||
|
||||
struct spnav_event_motion {
|
||||
int type;
|
||||
int x, y, z;
|
||||
int rx, ry, rz;
|
||||
unsigned int period;
|
||||
int *data;
|
||||
};
|
||||
|
||||
struct spnav_event_button {
|
||||
int type;
|
||||
int press;
|
||||
int bnum;
|
||||
};
|
||||
|
||||
typedef union spnav_event {
|
||||
int type;
|
||||
struct spnav_event_motion motion;
|
||||
struct spnav_event_button button;
|
||||
} spnav_event;
|
||||
|
||||
|
||||
static int spnav_x11_open(Display *dpy, Window win);
|
||||
static int spnav_x11_window(Window win);
|
||||
static int spnav_x11_event(const XEvent *xev, spnav_event *event);
|
||||
static int spnav_close(void);
|
||||
static int spnav_fd(void);
|
||||
static int spnav_remove_events(int type);
|
||||
|
||||
static SFG_Window *spnav_win;
|
||||
#endif
|
||||
|
||||
static int sball_initialized;
|
||||
|
||||
|
||||
void fgInitialiseSpaceball(void)
|
||||
{
|
||||
if(sball_initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
#if TARGET_HOST_POSIX_X11
|
||||
{
|
||||
Window w;
|
||||
|
||||
if(!fgStructure.CurrentWindow) {
|
||||
fgWarning("fgInitialiseSpaceball: no current window!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
w = fgStructure.CurrentWindow->Window.Handle;
|
||||
if(spnav_x11_open(fgDisplay.Display, w) == -1) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
sball_initialized = 1;
|
||||
}
|
||||
|
||||
void fgSpaceballClose(void)
|
||||
{
|
||||
#if TARGET_HOST_POSIX_X11
|
||||
spnav_close();
|
||||
#endif
|
||||
}
|
||||
|
||||
int fgHasSpaceball(void)
|
||||
{
|
||||
if(!sball_initialized) {
|
||||
fgInitialiseSpaceball();
|
||||
if(!sball_initialized) {
|
||||
fgWarning("fgInitialiseSpaceball failed\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#if TARGET_HOST_POSIX_X11
|
||||
/* XXX this function should somehow query the driver if there's a device
|
||||
* plugged in, as opposed to just checking if there's a driver to talk to.
|
||||
*/
|
||||
return spnav_fd() == -1 ? 0 : 1;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
int fgSpaceballNumButtons(void)
|
||||
{
|
||||
if(!sball_initialized) {
|
||||
fgInitialiseSpaceball();
|
||||
if(!sball_initialized) {
|
||||
fgWarning("fgInitialiseSpaceball failed\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#if TARGET_HOST_POSIX_X11
|
||||
return 2; /* TODO implement this properly */
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void fgSpaceballSetWindow(SFG_Window *window)
|
||||
{
|
||||
if(!sball_initialized) {
|
||||
fgInitialiseSpaceball();
|
||||
if(!sball_initialized) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#if TARGET_HOST_POSIX_X11
|
||||
if(spnav_win != window) {
|
||||
spnav_x11_window(window->Window.Handle);
|
||||
spnav_win = window;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#if TARGET_HOST_POSIX_X11
|
||||
int fgIsSpaceballXEvent(const XEvent *xev)
|
||||
{
|
||||
spnav_event sev;
|
||||
|
||||
if(!sball_initialized) {
|
||||
fgInitialiseSpaceball();
|
||||
if(!sball_initialized) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return spnav_x11_event(xev, &sev);
|
||||
}
|
||||
|
||||
void fgSpaceballHandleXEvent(const XEvent *xev)
|
||||
{
|
||||
spnav_event sev;
|
||||
|
||||
if(!sball_initialized) {
|
||||
fgInitialiseSpaceball();
|
||||
if(!sball_initialized) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(spnav_x11_event(xev, &sev)) {
|
||||
switch(sev.type) {
|
||||
case SPNAV_EVENT_MOTION:
|
||||
if(sev.motion.x | sev.motion.y | sev.motion.z) {
|
||||
INVOKE_WCB(*spnav_win, SpaceMotion, (sev.motion.x, sev.motion.y, sev.motion.z));
|
||||
}
|
||||
if(sev.motion.rx | sev.motion.ry | sev.motion.rz) {
|
||||
INVOKE_WCB(*spnav_win, SpaceRotation, (sev.motion.rx, sev.motion.ry, sev.motion.rz));
|
||||
}
|
||||
spnav_remove_events(SPNAV_EVENT_MOTION);
|
||||
break;
|
||||
|
||||
case SPNAV_EVENT_BUTTON:
|
||||
INVOKE_WCB(*spnav_win, SpaceButton, (sev.button.bnum, sev.button.press ? GLUT_DOWN : GLUT_UP));
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
The following code is part of libspnav, part of the spacenav project (spacenav.sf.net)
|
||||
Copyright (C) 2007-2009 John Tsiombikas <nuclear@member.fsf.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
OF SUCH DAMAGE.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
|
||||
static Window get_daemon_window(Display *dpy);
|
||||
static int catch_badwin(Display *dpy, XErrorEvent *err);
|
||||
|
||||
static Display *dpy;
|
||||
static Window app_win;
|
||||
static Atom motion_event, button_press_event, button_release_event, command_event;
|
||||
|
||||
enum {
|
||||
CMD_APP_WINDOW = 27695,
|
||||
CMD_APP_SENS
|
||||
};
|
||||
|
||||
#define IS_OPEN dpy
|
||||
|
||||
struct event_node {
|
||||
spnav_event event;
|
||||
struct event_node *next;
|
||||
};
|
||||
|
||||
static int spnav_x11_open(Display *display, Window win)
|
||||
{
|
||||
if(IS_OPEN) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
dpy = display;
|
||||
|
||||
motion_event = XInternAtom(dpy, "MotionEvent", True);
|
||||
button_press_event = XInternAtom(dpy, "ButtonPressEvent", True);
|
||||
button_release_event = XInternAtom(dpy, "ButtonReleaseEvent", True);
|
||||
command_event = XInternAtom(dpy, "CommandEvent", True);
|
||||
|
||||
if(!motion_event || !button_press_event || !button_release_event || !command_event) {
|
||||
dpy = 0;
|
||||
return -1; /* daemon not started */
|
||||
}
|
||||
|
||||
if(spnav_x11_window(win) == -1) {
|
||||
dpy = 0;
|
||||
return -1; /* daemon not started */
|
||||
}
|
||||
|
||||
app_win = win;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int spnav_close(void)
|
||||
{
|
||||
if(dpy) {
|
||||
spnav_x11_window(DefaultRootWindow(dpy));
|
||||
app_win = 0;
|
||||
dpy = 0;
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int spnav_x11_window(Window win)
|
||||
{
|
||||
int (*prev_xerr_handler)(Display*, XErrorEvent*);
|
||||
XEvent xev;
|
||||
Window daemon_win;
|
||||
|
||||
if(!IS_OPEN) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(!(daemon_win = get_daemon_window(dpy))) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
prev_xerr_handler = XSetErrorHandler(catch_badwin);
|
||||
|
||||
xev.type = ClientMessage;
|
||||
xev.xclient.send_event = False;
|
||||
xev.xclient.display = dpy;
|
||||
xev.xclient.window = win;
|
||||
xev.xclient.message_type = command_event;
|
||||
xev.xclient.format = 16;
|
||||
xev.xclient.data.s[0] = ((unsigned int)win & 0xffff0000) >> 16;
|
||||
xev.xclient.data.s[1] = (unsigned int)win & 0xffff;
|
||||
xev.xclient.data.s[2] = CMD_APP_WINDOW;
|
||||
|
||||
XSendEvent(dpy, daemon_win, False, 0, &xev);
|
||||
XSync(dpy, False);
|
||||
|
||||
XSetErrorHandler(prev_xerr_handler);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int spnav_fd(void)
|
||||
{
|
||||
if(dpy) {
|
||||
return ConnectionNumber(dpy);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*static int spnav_wait_event(spnav_event *event)
|
||||
{
|
||||
if(dpy) {
|
||||
for(;;) {
|
||||
XEvent xev;
|
||||
XNextEvent(dpy, &xev);
|
||||
|
||||
if(spnav_x11_event(&xev, event) > 0) {
|
||||
return event->type;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int spnav_poll_event(spnav_event *event)
|
||||
{
|
||||
if(dpy) {
|
||||
if(XPending(dpy)) {
|
||||
XEvent xev;
|
||||
XNextEvent(dpy, &xev);
|
||||
|
||||
return spnav_x11_event(&xev, event);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}*/
|
||||
|
||||
static Bool match_events(Display *dpy, XEvent *xev, char *arg)
|
||||
{
|
||||
int evtype = *(int*)arg;
|
||||
|
||||
if(xev->type != ClientMessage) {
|
||||
return False;
|
||||
}
|
||||
|
||||
if(xev->xclient.message_type == motion_event) {
|
||||
return !evtype || evtype == SPNAV_EVENT_MOTION ? True : False;
|
||||
}
|
||||
if(xev->xclient.message_type == button_press_event ||
|
||||
xev->xclient.message_type == button_release_event) {
|
||||
return !evtype || evtype == SPNAV_EVENT_BUTTON ? True : False;
|
||||
}
|
||||
return False;
|
||||
}
|
||||
|
||||
static int spnav_remove_events(int type)
|
||||
{
|
||||
int rm_count = 0;
|
||||
|
||||
if(dpy) {
|
||||
XEvent xev;
|
||||
|
||||
while(XCheckIfEvent(dpy, &xev, match_events, (char*)&type)) {
|
||||
rm_count++;
|
||||
}
|
||||
return rm_count;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int spnav_x11_event(const XEvent *xev, spnav_event *event)
|
||||
{
|
||||
int i;
|
||||
int xmsg_type;
|
||||
|
||||
if(xev->type != ClientMessage) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
xmsg_type = xev->xclient.message_type;
|
||||
|
||||
if(xmsg_type != motion_event && xmsg_type != button_press_event &&
|
||||
xmsg_type != button_release_event) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(xmsg_type == motion_event) {
|
||||
event->type = SPNAV_EVENT_MOTION;
|
||||
event->motion.data = &event->motion.x;
|
||||
|
||||
for(i=0; i<6; i++) {
|
||||
event->motion.data[i] = xev->xclient.data.s[i + 2];
|
||||
}
|
||||
event->motion.period = xev->xclient.data.s[8];
|
||||
} else {
|
||||
event->type = SPNAV_EVENT_BUTTON;
|
||||
event->button.press = xmsg_type == button_press_event ? 1 : 0;
|
||||
event->button.bnum = xev->xclient.data.s[2];
|
||||
}
|
||||
return event->type;
|
||||
}
|
||||
|
||||
|
||||
static Window get_daemon_window(Display *dpy)
|
||||
{
|
||||
Window win, root_win;
|
||||
XTextProperty wname;
|
||||
Atom type;
|
||||
int fmt;
|
||||
unsigned long nitems, bytes_after;
|
||||
unsigned char *prop;
|
||||
|
||||
root_win = DefaultRootWindow(dpy);
|
||||
|
||||
XGetWindowProperty(dpy, root_win, command_event, 0, 1, False, AnyPropertyType, &type, &fmt, &nitems, &bytes_after, &prop);
|
||||
if(!prop) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
win = *(Window*)prop;
|
||||
XFree(prop);
|
||||
|
||||
if(!XGetWMName(dpy, win, &wname) || strcmp("Magellan Window", (char*)wname.value) != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return win;
|
||||
}
|
||||
|
||||
static int catch_badwin(Display *dpy, XErrorEvent *err)
|
||||
{
|
||||
char buf[256];
|
||||
|
||||
if(err->error_code == BadWindow) {
|
||||
/* do nothing? */
|
||||
} else {
|
||||
XGetErrorText(dpy, err->error_code, buf, sizeof buf);
|
||||
fprintf(stderr, "Caught unexpected X error: %s\n", buf);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* TARGET_HOST_POSIX_X11 */
|
@ -675,10 +675,14 @@ int FGAPIENTRY glutDeviceGet( GLenum eWhat )
|
||||
return 0;
|
||||
|
||||
case GLUT_HAS_SPACEBALL:
|
||||
return fgHasSpaceball();
|
||||
|
||||
case GLUT_HAS_TABLET:
|
||||
return 0;
|
||||
|
||||
case GLUT_NUM_SPACEBALL_BUTTONS:
|
||||
return fgSpaceballNumButtons();
|
||||
|
||||
case GLUT_NUM_TABLET_BUTTONS:
|
||||
return 0;
|
||||
|
||||
|
@ -593,12 +593,17 @@ void fgSetWindow ( SFG_Window *window )
|
||||
{
|
||||
#if TARGET_HOST_POSIX_X11
|
||||
if ( window )
|
||||
{
|
||||
glXMakeContextCurrent(
|
||||
fgDisplay.Display,
|
||||
window->Window.Handle,
|
||||
window->Window.Handle,
|
||||
window->Window.Context
|
||||
);
|
||||
|
||||
/* also register this window to receive spaceball events */
|
||||
fgSpaceballSetWindow(window);
|
||||
}
|
||||
#elif TARGET_HOST_MS_WINDOWS
|
||||
if( fgStructure.CurrentWindow )
|
||||
ReleaseDC( fgStructure.CurrentWindow->Window.Handle,
|
||||
|
Reference in New Issue
Block a user