moved files around

This commit is contained in:
ejcoumans
2006-05-25 19:18:29 +00:00
commit e061ec1ebf
1024 changed files with 349445 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,50 @@
/*************************************************************************
* *
* Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
* All rights reserved. Email: russ@q12.org Web: www.q12.org *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of EITHER: *
* (1) The GNU Lesser General Public License as published by the Free *
* Software Foundation; either version 2.1 of the License, or (at *
* your option) any later version. The text of the GNU Lesser *
* General Public License is included with this library in the *
* file LICENSE.TXT. *
* (2) The BSD-style license that is included with this library in *
* the file LICENSE-BSD.TXT. *
* *
* 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 files *
* LICENSE.TXT and LICENSE-BSD.TXT for more details. *
* *
*************************************************************************/
/* functions supplied and used by the platform specific code */
#ifndef __DS_INTERNAL_H
#define __DS_INTERNAL_H
#include "drawstuff/drawstuff.h"
// supplied by platform specific code
void dsPlatformSimLoop (int window_width, int window_height,
dsFunctions *fn, int initial_pause);
// used by platform specific code
void dsStartGraphics (int width, int height, dsFunctions *fn);
void dsDrawFrame (int width, int height, dsFunctions *fn, int pause);
void dsStopGraphics();
void dsMotion (int mode, int deltax, int deltay);
int dsGetShadows();
void dsSetShadows (int a);
int dsGetTextures();
void dsSetTextures (int a);
#endif

View File

@@ -0,0 +1,28 @@
//{{NO_DEPENDENCIES}}
// Microsoft Developer Studio generated include file.
// Used by resources.rc
//
#define IDD_MSGDLG 101
#define IDR_MENU1 102
#define IDD_ABOUT 103
#define IDR_ACCELERATOR1 104
#define IDC_LIST1 1000
#define IDM_EXIT 40001
#define IDM_ABOUT 40002
#define IDM_PAUSE 40003
#define IDM_PERF_MONITOR 40004
#define IDM_SHADOWS 40005
#define IDM_TEXTURES 40006
#define IDM_SAVE_SETTINGS 40007
#define IDM_SINGLE_STEP 40008
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 108
#define _APS_NEXT_COMMAND_VALUE 40009
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

View File

@@ -0,0 +1,153 @@
//Microsoft Developer Studio generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
//#include "afxres.h"
// added by RLS to make this work with windres
#include "winresrc.h"
#define IDC_STATIC (-1)
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
IDD_ABOUT DIALOG DISCARDABLE 0, 0, 257, 105
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "About"
FONT 8, "MS Sans Serif"
BEGIN
DEFPUSHBUTTON "OK",IDOK,200,84,50,14
LTEXT "Simulation test environment",IDC_STATIC,7,7,243,8
LTEXT "Change the camera position by clicking + dragging in the main window.",
IDC_STATIC,7,24,243,8
LTEXT "Left button - pan and tilt.",IDC_STATIC,25,37,225,8
LTEXT "Right button - forward and sideways.",IDC_STATIC,25,48,
225,8
LTEXT "Left + Right button (or middle button) - sideways and up.",
IDC_STATIC,25,59,225,8
END
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE DISCARDABLE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE DISCARDABLE
BEGIN
//"#include ""afxres.h""\r\n"
"\0"
END
3 TEXTINCLUDE DISCARDABLE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Menu
//
IDR_MENU1 MENU DISCARDABLE
BEGIN
POPUP "&File"
BEGIN
MENUITEM "&Exit\tCtrl+X", IDM_EXIT
END
POPUP "&Simulation"
BEGIN
MENUITEM "&Pause\tCtrl+P", IDM_PAUSE
MENUITEM "Single Step\tCtrl+O", IDM_SINGLE_STEP
MENUITEM "Performance &Monitor", IDM_PERF_MONITOR
MENUITEM SEPARATOR
MENUITEM "&Shadows\tCtrl+S", IDM_SHADOWS, CHECKED
MENUITEM "&Textures\tCtrl+T", IDM_TEXTURES, CHECKED
MENUITEM SEPARATOR
MENUITEM "S&ave Settings", IDM_SAVE_SETTINGS
END
POPUP "&Help"
BEGIN
MENUITEM "&About", IDM_ABOUT
END
END
/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO DISCARDABLE
BEGIN
IDD_ABOUT, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 250
VERTGUIDE, 25
TOPMARGIN, 7
BOTTOMMARGIN, 98
END
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Accelerator
//
IDR_ACCELERATOR1 ACCELERATORS DISCARDABLE
BEGIN
"O", IDM_SINGLE_STEP, VIRTKEY, CONTROL, NOINVERT
"P", IDM_PAUSE, VIRTKEY, CONTROL, NOINVERT
"S", IDM_SHADOWS, VIRTKEY, CONTROL, NOINVERT
"T", IDM_TEXTURES, VIRTKEY, CONTROL, NOINVERT
"X", IDM_EXIT, VIRTKEY, CONTROL, NOINVERT
END
#endif // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

View File

@@ -0,0 +1,486 @@
/*************************************************************************
* *
* Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
* All rights reserved. Email: russ@q12.org Web: www.q12.org *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of EITHER: *
* (1) The GNU Lesser General Public License as published by the Free *
* Software Foundation; either version 2.1 of the License, or (at *
* your option) any later version. The text of the GNU Lesser *
* General Public License is included with this library in the *
* file LICENSE.TXT. *
* (2) The BSD-style license that is included with this library in *
* the file LICENSE-BSD.TXT. *
* *
* 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 files *
* LICENSE.TXT and LICENSE-BSD.TXT for more details. *
* *
*************************************************************************/
#ifdef WIN32 // this prevents warnings when dependencies built
#include <windows.h>
#endif
#include <ode/config.h>
#include <GL/gl.h>
#include "resource.h"
#include "internal.h"
//***************************************************************************
// application globals
static HINSTANCE ghInstance = 0;
static int gnCmdShow = 0;
static HACCEL accelerators = 0;
static HWND main_window = 0;
//***************************************************************************
// error and message handling
static void errorBox (char *title, char *msg, va_list ap)
{
char s[1000];
vsprintf (s,msg,ap);
MessageBox (0,s,title,MB_OK | MB_APPLMODAL | MB_ICONEXCLAMATION);
}
static void dsWarning (char *msg, ...)
{
va_list ap;
va_start (ap,msg);
errorBox ("Warning",msg,ap);
}
extern "C" void dsError (char *msg, ...)
{
va_list ap;
va_start (ap,msg);
errorBox ("Error",msg,ap);
exit (1);
}
extern "C" void dsDebug (char *msg, ...)
{
va_list ap;
va_start (ap,msg);
errorBox ("INTERNAL ERROR",msg,ap);
// *((char *)0) = 0; ... commit SEGVicide ?
abort();
exit (1); // should never get here, but just in case...
}
extern "C" void dsPrint (char *msg, ...)
{
va_list ap;
va_start (ap,msg);
vprintf (msg,ap);
}
//***************************************************************************
// rendering thread
// globals used to communicate with rendering thread
static volatile int renderer_run = 1;
static volatile int renderer_pause = 0; // 0=run, 1=pause
static volatile int renderer_ss = 0; // single step command
static volatile int renderer_width = 1;
static volatile int renderer_height = 1;
static dsFunctions *renderer_fn = 0;
static volatile HDC renderer_dc = 0;
static volatile int keybuffer[16]; // fifo ring buffer for keypresses
static volatile int keybuffer_head = 0; // index of next key to put in (modified by GUI)
static volatile int keybuffer_tail = 0; // index of next key to take out (modified by renderer)
static void setupRendererGlobals()
{
renderer_run = 1;
renderer_pause = 0;
renderer_ss = 0;
renderer_width = 1;
renderer_height = 1;
renderer_fn = 0;
renderer_dc = 0;
keybuffer[16];
keybuffer_head = 0;
keybuffer_tail = 0;
}
static DWORD WINAPI renderingThread (LPVOID lpParam)
{
// create openGL context and make it current
HGLRC glc = wglCreateContext (renderer_dc);
if (glc==NULL) dsError ("could not create OpenGL context");
if (wglMakeCurrent (renderer_dc,glc) != TRUE)
dsError ("could not make OpenGL context current");
// test openGL capabilities
int maxtsize=0;
glGetIntegerv (GL_MAX_TEXTURE_SIZE,&maxtsize);
if (maxtsize < 128) dsWarning ("max texture size too small (%dx%d)",
maxtsize,maxtsize);
dsStartGraphics (renderer_width,renderer_height,renderer_fn);
if (renderer_fn->start) renderer_fn->start();
while (renderer_run) {
// need to make local copy of renderer_ss to help prevent races
int ss = renderer_ss;
dsDrawFrame (renderer_width,renderer_height,renderer_fn,
renderer_pause && !ss);
if (ss) renderer_ss = 0;
// read keys out of ring buffer and feed them to the command function
while (keybuffer_head != keybuffer_tail) {
if (renderer_fn->command) renderer_fn->command (keybuffer[keybuffer_tail]);
keybuffer_tail = (keybuffer_tail+1) & 15;
}
// swap buffers
SwapBuffers (renderer_dc);
}
if (renderer_fn->stop) renderer_fn->stop();
dsStopGraphics();
// delete openGL context
wglMakeCurrent (NULL,NULL);
wglDeleteContext (glc);
return 123; // magic value used to test for thread termination
}
//***************************************************************************
// window handling
// callback function for "about" dialog box
static LRESULT CALLBACK AboutDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam,
LPARAM lParam)
{
switch (uMsg) {
case WM_INITDIALOG:
return TRUE;
case WM_COMMAND:
switch (wParam) {
case IDOK:
EndDialog (hDlg, TRUE);
return TRUE;
}
break;
}
return FALSE;
}
// callback function for the main window
static LRESULT CALLBACK mainWndProc (HWND hWnd, UINT msg, WPARAM wParam,
LPARAM lParam)
{
static int button=0,lastx=0,lasty=0;
int ctrl = wParam & MK_CONTROL;
switch (msg) {
case WM_LBUTTONDOWN:
case WM_MBUTTONDOWN:
case WM_RBUTTONDOWN:
if (msg==WM_LBUTTONDOWN) button |= 1;
else if (msg==WM_MBUTTONDOWN) button |= 2;
else button |= 4;
lastx = SHORT(LOWORD(lParam));
lasty = SHORT(HIWORD(lParam));
SetCapture (hWnd);
break;
case WM_LBUTTONUP:
case WM_MBUTTONUP:
case WM_RBUTTONUP:
if (msg==WM_LBUTTONUP) button &= ~1;
else if (msg==WM_MBUTTONUP) button &= ~2;
else button &= ~4;
if (button==0) ReleaseCapture();
break;
case WM_MOUSEMOVE: {
int x = SHORT(LOWORD(lParam));
int y = SHORT(HIWORD(lParam));
if (button) dsMotion (button,x-lastx,y-lasty);
lastx = x;
lasty = y;
break;
}
case WM_CHAR: {
if (wParam >= ' ' && wParam <= 126) {
int nexth = (keybuffer_head+1) & 15;
if (nexth != keybuffer_tail) {
keybuffer[keybuffer_head] = wParam;
keybuffer_head = nexth;
}
}
break;
}
case WM_SIZE:
// lParam will contain the size of the *client* area!
renderer_width = LOWORD(lParam);
renderer_height = HIWORD(lParam);
break;
case WM_COMMAND:
switch (wParam & 0xffff) {
case IDM_ABOUT:
DialogBox (ghInstance,MAKEINTRESOURCE(IDD_ABOUT),hWnd,
(DLGPROC) AboutDlgProc);
break;
case IDM_PAUSE: {
renderer_pause ^= 1;
CheckMenuItem (GetMenu(hWnd),IDM_PAUSE,
renderer_pause ? MF_CHECKED : MF_UNCHECKED);
if (renderer_pause) renderer_ss = 0;
break;
}
case IDM_SINGLE_STEP: {
renderer_ss = 1;
break;
}
case IDM_PERF_MONITOR: {
dsWarning ("Performance monitor not yet implemented.");
break;
}
case IDM_TEXTURES: {
static int tex = 1;
tex ^= 1;
CheckMenuItem (GetMenu(hWnd),IDM_TEXTURES,
tex ? MF_CHECKED : MF_UNCHECKED);
dsSetTextures (tex);
break;
}
case IDM_SHADOWS: {
static int shadows = 1;
shadows ^= 1;
CheckMenuItem (GetMenu(hWnd),IDM_SHADOWS,
shadows ? MF_CHECKED : MF_UNCHECKED);
dsSetShadows (shadows);
break;
}
case IDM_SAVE_SETTINGS: {
dsWarning ("\"Save Settings\" not yet implemented.");
break;
}
case IDM_EXIT:
PostQuitMessage (0);
break;
}
break;
case WM_CLOSE:
PostQuitMessage (0);
break;
default:
return (DefWindowProc (hWnd, msg, wParam, lParam));
}
return 0;
}
// this comes from an MSDN example. believe it or not, this is the recommended
// way to get the console window handle.
static HWND GetConsoleHwnd()
{
// the console window title to a "unique" value, then find the window
// that has this title.
char title[1024];
wsprintf (title,"DrawStuff:%d/%d",GetTickCount(),GetCurrentProcessId());
SetConsoleTitle (title);
Sleep(40); // ensure window title has been updated
return FindWindow (NULL,title);
}
static void drawStuffStartup()
{
static int startup_called = 0;
if (startup_called) return;
startup_called = 1;
ghInstance = GetModuleHandleA (NULL);
gnCmdShow = SW_SHOWNORMAL; // @@@ fix this later
// redirect standard I/O to a new console (except on cygwin)
#ifndef CYGWIN
FreeConsole();
if (AllocConsole()==0) dsError ("AllocConsole() failed");
if (freopen ("CONIN$","rt",stdin)==0) dsError ("could not open stdin");
if (freopen ("CONOUT$","wt",stdout)==0) dsError ("could not open stdout");
if (freopen ("CONOUT$","wt",stderr)==0) dsError ("could not open stderr");
BringWindowToTop (GetConsoleHwnd());
SetConsoleTitle ("DrawStuff Messages");
#endif
// register the window class
WNDCLASS wc;
wc.style = CS_OWNDC | CS_VREDRAW | CS_HREDRAW;
wc.lpfnWndProc = mainWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = ghInstance;
wc.hIcon = LoadIcon (NULL,IDI_APPLICATION);
wc.hCursor = LoadCursor (NULL,IDC_ARROW);
wc.hbrBackground = (HBRUSH) (COLOR_WINDOW+1);
wc.lpszMenuName = MAKEINTRESOURCE(IDR_MENU1);
wc.lpszClassName = "SimAppClass";
if (RegisterClass (&wc)==0) dsError ("could not register window class");
// load accelerators
accelerators = LoadAccelerators (ghInstance,
MAKEINTRESOURCE(IDR_ACCELERATOR1));
if (accelerators==NULL) dsError ("could not load accelerators");
}
void dsPlatformSimLoop (int window_width, int window_height,
dsFunctions *fn, int initial_pause)
{
drawStuffStartup();
setupRendererGlobals();
renderer_pause = initial_pause;
// create window - but first get window size for desired size of client area.
// if this adjustment isn't made then the openGL area will be shifted into
// the nonclient area and determining the frame buffer coordinate from the
// client area coordinate will be hard.
RECT winrect;
winrect.left = 50;
winrect.top = 80;
winrect.right = winrect.left + window_width;
winrect.bottom = winrect.top + window_height;
DWORD style = WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
AdjustWindowRect (&winrect,style,1);
char title[100];
sprintf (title,"Simulation test environment v%d.%02d",
DS_VERSION >> 8,DS_VERSION & 0xff);
main_window = CreateWindow ("SimAppClass",title,style,
winrect.left,winrect.top,winrect.right-winrect.left,winrect.bottom-winrect.top,
NULL,NULL,ghInstance,NULL);
if (main_window==NULL) dsError ("could not create main window");
ShowWindow (main_window, gnCmdShow);
HDC dc = GetDC (main_window); // get DC for this window
if (dc==NULL) dsError ("could not get window DC");
// set pixel format for DC
PIXELFORMATDESCRIPTOR pfd = {
sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd
1, // version number
PFD_DRAW_TO_WINDOW | // support window
PFD_SUPPORT_OPENGL | // support OpenGL
PFD_DOUBLEBUFFER, // double buffered
PFD_TYPE_RGBA, // RGBA type
24, // 24-bit color depth
0, 0, 0, 0, 0, 0, // color bits ignored
0, // no alpha buffer
0, // shift bit ignored
0, // no accumulation buffer
0, 0, 0, 0, // accum bits ignored
32, // 32-bit z-buffer
0, // no stencil buffer
0, // no auxiliary buffer
PFD_MAIN_PLANE, // main layer
0, // reserved
0, 0, 0 // layer masks ignored
};
// get the best available match of pixel format for the device context
int iPixelFormat = ChoosePixelFormat (dc,&pfd);
if (iPixelFormat==0)
dsError ("could not find a good OpenGL pixel format");
// set the pixel format of the device context
if (SetPixelFormat (dc,iPixelFormat,&pfd)==FALSE)
dsError ("could not set DC pixel format for OpenGL");
// **********
// start the rendering thread
// set renderer globals
renderer_dc = dc;
renderer_width = window_width;
renderer_height = window_height;
renderer_fn = fn;
DWORD threadId, thirdParam = 0;
HANDLE hThread;
hThread = CreateThread(
NULL, // no security attributes
0, // use default stack size
renderingThread, // thread function
&thirdParam, // argument to thread function
0, // use default creation flags
&threadId); // returns the thread identifier
if (hThread==NULL) dsError ("Could not create rendering thread");
// **********
// start GUI message processing
MSG msg;
while (GetMessage (&msg,main_window,0,0)) {
if (!TranslateAccelerator (main_window,accelerators,&msg)) {
TranslateMessage (&msg);
DispatchMessage (&msg);
}
}
// terminate rendering thread
renderer_run = 0;
DWORD ret = WaitForSingleObject (hThread,2000);
if (ret==WAIT_TIMEOUT) dsWarning ("Could not kill rendering thread (1)");
DWORD exitcode=0;
if (!(GetExitCodeThread (hThread,&exitcode) && exitcode == 123))
dsWarning ("Could not kill rendering thread (2)");
CloseHandle (hThread); // dont need thread handle anymore
// destroy window
DestroyWindow (main_window);
}
extern "C" void dsStop()
{
// just calling PostQuitMessage() here wont work, as this function is
// typically called from the rendering thread, not the GUI thread.
// instead we must post the message to the GUI window explicitly.
if (main_window) PostMessage (main_window,WM_QUIT,0,0);
}
//***************************************************************************
// windows entry point
//
// NOTE: WinMain is not guaranteed to be called with MinGW, because MinGW
// always calls main if it is defined and most users of this library will
// define their own main. So the startup functionality is kept in
// zDriverStartup(), which is also called when dsSimulationLoop() is called.
extern "C" int main (int argc, char **argv);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
drawStuffStartup();
return main (0,0); // @@@ should really pass cmd line arguments
}

View File

@@ -0,0 +1,383 @@
/*************************************************************************
* *
* Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
* All rights reserved. Email: russ@q12.org Web: www.q12.org *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of EITHER: *
* (1) The GNU Lesser General Public License as published by the Free *
* Software Foundation; either version 2.1 of the License, or (at *
* your option) any later version. The text of the GNU Lesser *
* General Public License is included with this library in the *
* file LICENSE.TXT. *
* (2) The BSD-style license that is included with this library in *
* the file LICENSE-BSD.TXT. *
* *
* 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 files *
* LICENSE.TXT and LICENSE-BSD.TXT for more details. *
* *
*************************************************************************/
// main window and event handling for X11
#include <ode/config.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/keysym.h>
#include <GL/glx.h>
#include <drawstuff/drawstuff.h>
#include <drawstuff/version.h>
#include "internal.h"
//***************************************************************************
// error handling for unix
static void printMessage (char *msg1, char *msg2, va_list ap)
{
fflush (stderr);
fflush (stdout);
fprintf (stderr,"\n%s: ",msg1);
vfprintf (stderr,msg2,ap);
fprintf (stderr,"\n");
fflush (stderr);
}
extern "C" void dsError (char *msg, ...)
{
va_list ap;
va_start (ap,msg);
printMessage ("Error",msg,ap);
exit (1);
}
extern "C" void dsDebug (char *msg, ...)
{
va_list ap;
va_start (ap,msg);
printMessage ("INTERNAL ERROR",msg,ap);
// *((char *)0) = 0; ... commit SEGVicide ?
abort();
}
extern "C" void dsPrint (char *msg, ...)
{
va_list ap;
va_start (ap,msg);
vprintf (msg,ap);
}
//***************************************************************************
// openGL window
// X11 display info
static Display *display=0;
static int screen=0;
static XVisualInfo *visual=0; // best visual for openGL
static Colormap colormap=0; // window's colormap
static Atom wm_protocols_atom = 0;
static Atom wm_delete_window_atom = 0;
// window and openGL
static Window win=0; // X11 window, 0 if not initialized
static int width=0,height=0; // window size
static GLXContext glx_context=0; // openGL rendering context
static int last_key_pressed=0; // last key pressed in the window
static int run=1; // 1 if simulation running
static int pause=0; // 1 if in `pause' mode
static int singlestep=0; // 1 if single step key pressed
static int writeframes=0; // 1 if frame files to be written
static void createMainWindow (int _width, int _height)
{
// create X11 display connection
display = XOpenDisplay (NULL);
if (!display) dsError ("can not open X11 display");
screen = DefaultScreen(display);
// get GL visual
static int attribList[] = {GLX_RGBA, GLX_DOUBLEBUFFER, GLX_DEPTH_SIZE,16,
GLX_RED_SIZE,4, GLX_GREEN_SIZE,4,
GLX_BLUE_SIZE,4, None};
visual = glXChooseVisual (display,screen,attribList);
if (!visual) dsError ("no good X11 visual found for OpenGL");
// create colormap
colormap = XCreateColormap (display,RootWindow(display,screen),
visual->visual,AllocNone);
// initialize variables
win = 0;
width = _width;
height = _height;
glx_context = 0;
last_key_pressed = 0;
if (width < 1 || height < 1) dsDebug (0,"bad window width or height");
// create the window
XSetWindowAttributes attributes;
attributes.background_pixel = BlackPixel(display,screen);
attributes.colormap = colormap;
attributes.event_mask = ButtonPressMask | ButtonReleaseMask |
KeyPressMask | KeyReleaseMask | ButtonMotionMask | PointerMotionHintMask |
StructureNotifyMask;
win = XCreateWindow (display,RootWindow(display,screen),50,50,width,height,
0,visual->depth, InputOutput,visual->visual,
CWBackPixel | CWColormap | CWEventMask,&attributes);
// associate a GLX context with the window
glx_context = glXCreateContext (display,visual,0,GL_TRUE);
if (!glx_context) dsError ("can't make an OpenGL context");
// set the window title
XTextProperty window_name;
window_name.value = (unsigned char *) "Simulation";
window_name.encoding = XA_STRING;
window_name.format = 8;
window_name.nitems = strlen((char *) window_name.value);
XSetWMName (display,win,&window_name);
// participate in the window manager 'delete yourself' protocol
wm_protocols_atom = XInternAtom (display,"WM_PROTOCOLS",False);
wm_delete_window_atom = XInternAtom (display,"WM_DELETE_WINDOW",False);
if (XSetWMProtocols (display,win,&wm_delete_window_atom,1)==0)
dsError ("XSetWMProtocols() call failed");
// pop up the window
XMapWindow (display,win);
XSync (display,win);
}
static void destroyMainWindow()
{
glXDestroyContext (display,glx_context);
XDestroyWindow (display,win);
XSync (display,0);
display = 0;
win = 0;
glx_context = 0;
}
static void handleEvent (XEvent &event, dsFunctions *fn)
{
static int mx=0,my=0; // mouse position
static int mode = 0; // mouse button bits
switch (event.type) {
case ButtonPress: {
if (event.xbutton.button == Button1) mode |= 1;
if (event.xbutton.button == Button2) mode |= 2;
if (event.xbutton.button == Button3) mode |= 4;
mx = event.xbutton.x;
my = event.xbutton.y;
}
return;
case ButtonRelease: {
if (event.xbutton.button == Button1) mode &= (~1);
if (event.xbutton.button == Button2) mode &= (~2);
if (event.xbutton.button == Button3) mode &= (~4);
mx = event.xbutton.x;
my = event.xbutton.x;
}
return;
case MotionNotify: {
if (event.xmotion.is_hint) {
Window root,child;
unsigned int mask;
XQueryPointer (display,win,&root,&child,&event.xbutton.x_root,
&event.xbutton.y_root,&event.xbutton.x,&event.xbutton.y,
&mask);
}
dsMotion (mode, event.xmotion.x - mx, event.xmotion.y - my);
mx = event.xmotion.x;
my = event.xmotion.y;
}
return;
case KeyPress: {
KeySym key;
XLookupString (&event.xkey,NULL,0,&key,0);
if ((event.xkey.state & ControlMask) == 0) {
if (key >= ' ' && key <= 126 && fn->command) fn->command (key);
}
else if (event.xkey.state & ControlMask) {
switch (key) {
case 't': case 'T':
dsSetTextures (dsGetTextures() ^ 1);
break;
case 's': case 'S':
dsSetShadows (dsGetShadows() ^ 1);
break;
case 'x': case 'X':
run = 0;
break;
case 'p': case 'P':
pause ^= 1;
singlestep = 0;
break;
case 'o': case 'O':
if (pause) singlestep = 1;
break;
case 'v': case 'V': {
float xyz[3],hpr[3];
dsGetViewpoint (xyz,hpr);
printf ("Viewpoint = (%.4f,%.4f,%.4f,%.4f,%.4f,%.4f)\n",
xyz[0],xyz[1],xyz[2],hpr[0],hpr[1],hpr[2]);
break;
}
case 'w': case 'W':
writeframes ^= 1;
if (writeframes) printf ("Now writing frames to PPM files\n");
break;
}
}
last_key_pressed = key; // a kludgy place to put this...
}
return;
case KeyRelease: {
// hmmmm...
}
return;
case ClientMessage:
if (event.xclient.message_type == wm_protocols_atom &&
event.xclient.format == 32 &&
Atom(event.xclient.data.l[0]) == wm_delete_window_atom) {
run = 0;
return;
}
return;
case ConfigureNotify:
width = event.xconfigure.width;
height = event.xconfigure.height;
return;
}
}
// return the index of the highest bit
static int getHighBitIndex (unsigned int x)
{
int i = 0;
while (x) {
i++;
x >>= 1;
}
return i-1;
}
// shift x left by i, where i can be positive or negative
#define SHIFTL(x,i) (((i) >= 0) ? ((x) << (i)) : ((x) >> (-i)))
static void captureFrame (int num)
{
fprintf (stderr,"capturing frame %04d\n",num);
char s[100];
sprintf (s,"frame/frame%04d.ppm",num);
FILE *f = fopen (s,"wb");
if (!f) dsError ("can't open \"%s\" for writing",s);
fprintf (f,"P6\n%d %d\n255\n",width,height);
XImage *image = XGetImage (display,win,0,0,width,height,~0,ZPixmap);
int rshift = 7 - getHighBitIndex (image->red_mask);
int gshift = 7 - getHighBitIndex (image->green_mask);
int bshift = 7 - getHighBitIndex (image->blue_mask);
for (int y=0; y<height; y++) {
for (int x=0; x<width; x++) {
unsigned long pixel = XGetPixel (image,x,y);
unsigned char b[3];
b[0] = SHIFTL(pixel & image->red_mask,rshift);
b[1] = SHIFTL(pixel & image->green_mask,gshift);
b[2] = SHIFTL(pixel & image->blue_mask,bshift);
fwrite (b,3,1,f);
}
}
fclose (f);
XDestroyImage (image);
}
void dsPlatformSimLoop (int window_width, int window_height, dsFunctions *fn,
int initial_pause)
{
pause = initial_pause;
createMainWindow (window_width, window_height);
glXMakeCurrent (display,win,glx_context);
dsStartGraphics (window_width,window_height,fn);
fprintf (stderr,
"\n"
"Simulation test environment v%d.%02d\n"
" Ctrl-P : pause / unpause (or say `-pause' on command line).\n"
" Ctrl-O : single step when paused.\n"
" Ctrl-T : toggle textures (or say `-notex' on command line).\n"
" Ctrl-S : toggle shadows (or say `-noshadow' on command line).\n"
" Ctrl-V : print current viewpoint coordinates (x,y,z,h,p,r).\n"
" Ctrl-W : write frames to ppm files: frame/frameNNN.ppm\n"
" Ctrl-X : exit.\n"
"\n"
"Change the camera position by clicking + dragging in the window.\n"
" Left button - pan and tilt.\n"
" Right button - forward and sideways.\n"
" Left + Right button (or middle button) - sideways and up.\n"
"\n",DS_VERSION >> 8,DS_VERSION & 0xff);
if (fn->start) fn->start();
int frame = 1;
run = 1;
while (run) {
// read in and process all pending events for the main window
XEvent event;
while (run && XPending (display)) {
XNextEvent (display,&event);
handleEvent (event,fn);
}
dsDrawFrame (width,height,fn,pause && !singlestep);
singlestep = 0;
glFlush();
glXSwapBuffers (display,win);
XSync (display,0);
// capture frames if necessary
if (pause==0 && writeframes) {
captureFrame (frame);
frame++;
}
};
if (fn->stop) fn->stop();
dsStopGraphics();
destroyMainWindow();
}
extern "C" void dsStop()
{
run = 0;
}