[ODE] Stability in ODE
Timothy J. Wood
tjw at omnigroup.com
Thu Jul 25 19:58:02 2002
--Apple-Mail-1--47056944
Content-Transfer-Encoding: 7bit
Content-Type: text/plain;
charset=US-ASCII;
format=flowed
Well, I'm still trying to write some basic code of my own -- I just
wrote the stability test since I saw some weird glitches in the box
dropping example.
As far as the native Mac OS X port, here is what I have so far (as a
diff against the head of CVS). This doesn't handle mouse input, for
example -- if any of the examples actually use that, I could certainly
add it, though.
First there is a new file in drawstuff/src
--Apple-Mail-1--47056944
Content-Disposition: attachment;
filename=macosx.mm
Content-Transfer-Encoding: 7bit
Content-Type: application/octet-stream;
x-unix-mode=0664;
name="macosx.mm"
/*************************************************************************
* *
* 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. *
* *
*************************************************************************/
#include <ode/config.h>
#include "internal.h"
#import <Cocoa/Cocoa.h>
#import <AppKit/NSOpenGL.h>
#import <OpenGL/gl.h>
#import <pthread.h>
//***************************************************************************
// application globals
@interface SimWindow : NSWindow
@end
static SimWindow *window;
//***************************************************************************
// error and message handling
static void errorBox (char *title, char *msg, va_list ap)
{
NSString *formatString, *msgString;
formatString = [[NSString alloc] initWithCString: msg];
msgString = [[NSString alloc] initWithFormat: formatString arguments: ap];
[formatString release];
#warning TJW: Run a sheet relative to our window
NSLog(@"msg=%@", msgString);
[msgString release];
}
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 NSOpenGLPixelFormat *renderer_pixelFormat = nil;
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_pixelFormat = nil;
keybuffer[16];
keybuffer_head = 0;
keybuffer_tail = 0;
}
static void *renderingThread (void *arg)
{
// create openGL context and make it current
NSOpenGLContext *glc;
glc = [[NSOpenGLContext alloc] initWithFormat: renderer_pixelFormat shareContext:nil];
if (glc==NULL) dsError ("could not create OpenGL context");
[glc setView: [window contentView]];
[glc makeCurrentContext];
if ([NSOpenGLContext currentContext] != glc)
dsError ("could not make OpenGL context current");
// test openGL capabilities
GLint 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
[glc flushBuffer];
}
if (renderer_fn->stop) renderer_fn->stop();
dsStopGraphics();
// delete openGL context
[NSOpenGLContext clearCurrentContext];
[glc release];
return arg;
}
//***************************************************************************
// window handling
// callback function for the main window
@implementation SimWindow
- (void) mouseDown: (NSEvent *) event;
{
NSLog(@"event = %@", event);
NSLog(@"key = %d", [window isKeyWindow]);
NSLog(@"main = %d", [window isMainWindow]);
}
- (void) keyDown: (NSEvent *) event;
{
NSString *characters;
unsigned int characterIndex, characterCount;
unichar c;
NSLog(@"event = %@", event);
characters = [event charactersIgnoringModifiers];
characterCount = [characters length];
for (characterIndex = 0; characterIndex < characterCount; characterIndex++) {
c = [characters characterAtIndex: characterIndex];
if (c < ' ' || c > 126)
continue;
int nexth = (keybuffer_head+1) & 15;
if (nexth != keybuffer_tail) {
keybuffer[keybuffer_head] = c;
keybuffer_head = nexth;
}
}
}
@end
#if 0
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;
}
#endif
#if 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);
}
#endif
static void drawStuffStartup()
{
static int startup_called = 0;
if (startup_called) return;
startup_called = 1;
NSAutoreleasePool *pool;
pool = [[NSAutoreleasePool alloc] init];
[NSApplication sharedApplication];
[pool release];
}
void dsPlatformSimLoop (int window_width, int window_height,
dsFunctions *fn, int initial_pause)
{
NSAutoreleasePool *pool;
pool = [[NSAutoreleasePool alloc] init];
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.
NSRect frame;
frame.origin.x = 50;
frame.origin.y = 80;
frame.size.width = window_width;
frame.size.height = window_height;
window = [[SimWindow alloc] initWithContentRect:frame
styleMask:NSTitledWindowMask|NSClosableWindowMask|NSMiniaturizableWindowMask
backing:NSBackingStoreBuffered
defer:NO];
NSString *title;
title = [[NSString alloc] initWithFormat: @"Simulation test environment v%d.%02d", DS_VERSION >> 8,DS_VERSION & 0xff];
[window setTitle: title];
[title release];
if (!window) dsError ("could not create main window");
[window makeKeyAndOrderFront:nil];
[window setAcceptsMouseMovedEvents: YES];
[window makeKeyWindow];
NSLog(@"can key = %d", [window canBecomeKeyWindow]);
NSLog(@"can main = %d", [window canBecomeMainWindow]);
NSLog(@"key = %d", [window isKeyWindow]);
NSLog(@"main = %d", [window isMainWindow]);
// Set up pixel format
NSOpenGLPixelFormatAttribute attributes[] = {
NSOpenGLPFADoubleBuffer,
NSOpenGLPFAColorSize, (NSOpenGLPixelFormatAttribute)24,
NSOpenGLPFADepthSize, (NSOpenGLPixelFormatAttribute)24,
(NSOpenGLPixelFormatAttribute)0
};
renderer_pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes: attributes];
if (!renderer_pixelFormat)
dsError ("could not find a good OpenGL pixel format");
// **********
// start the rendering thread
// set renderer globals
renderer_width = window_width;
renderer_height = window_height;
renderer_fn = fn;
pthread_t thread = NULL;
int rc;
rc = pthread_create(&thread, NULL, renderingThread, NULL);
if (rc || thread==NULL) dsError ("Could not create rendering thread");
// **********
// start GUI message processing
[pool release];
[NSApp run];
#if 0
// 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);
#endif
}
extern "C" void dsStop()
{
#warning TJW: Finish me
abort();
#if 0
// 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);
#endif
}
#if 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
}
#endif
--Apple-Mail-1--47056944
Content-Transfer-Encoding: 7bit
Content-Type: text/plain;
charset=US-ASCII;
format=flowed
Then some diffs:
--Apple-Mail-1--47056944
Content-Disposition: attachment;
filename=macosx.patch
Content-Transfer-Encoding: 7bit
Content-Type: application/octet-stream;
x-unix-mode=0664;
name="macosx.patch"
Index: Makefile
===================================================================
RCS file: /cvsroot/ode/Makefile,v
retrieving revision 1.7
diff -c -r1.7 Makefile
*** Makefile 2002/06/25 23:46:13 1.7
--- Makefile 2002/07/26 02:56:22
***************
*** 71,77 ****
ifeq ($(WINDOWS),1)
DRAWSTUFF_SRC = drawstuff/src/drawstuff.cpp drawstuff/src/windows.cpp
RESOURCE_FILE=lib/resources.RES
! else
DRAWSTUFF_SRC = drawstuff/src/drawstuff.cpp drawstuff/src/x11.cpp
endif
--- 71,84 ----
ifeq ($(WINDOWS),1)
DRAWSTUFF_SRC = drawstuff/src/drawstuff.cpp drawstuff/src/windows.cpp
RESOURCE_FILE=lib/resources.RES
! endif
!
! ifeq ($(MACOSX),1)
! DRAWSTUFF_SRC = drawstuff/src/drawstuff.cpp
! DRAWSTUFF_SRC_MM = drawstuff/src/macosx.mm
! endif
!
! ifndef DRAWSTUFF_SRC
DRAWSTUFF_SRC = drawstuff/src/drawstuff.cpp drawstuff/src/x11.cpp
endif
***************
*** 118,124 ****
# object file names
ODE_PREGEN_OBJECTS=$(ODE_PREGEN_SRC:%.c=%$(OBJ))
ODE_OBJECTS=$(ODE_SRC:%.cpp=%$(OBJ)) $(ODE_PREGEN_OBJECTS)
! DRAWSTUFF_OBJECTS=$(DRAWSTUFF_SRC:%.cpp=%$(OBJ)) $(RESOURCE_FILE)
# side-effect variables causing creation of files containing lists of
# filenames to be linked, to work around command-line-length limitations
--- 125,134 ----
# object file names
ODE_PREGEN_OBJECTS=$(ODE_PREGEN_SRC:%.c=%$(OBJ))
ODE_OBJECTS=$(ODE_SRC:%.cpp=%$(OBJ)) $(ODE_PREGEN_OBJECTS)
! ifeq ($(MACOSX),1)
! DRAWSTUFF_OBJECTS_MM = $(DRAWSTUFF_SRC_MM:%.mm=%$(OBJ))
! endif
! DRAWSTUFF_OBJECTS=$(DRAWSTUFF_SRC:%.cpp=%$(OBJ)) $(RESOURCE_FILE) $(DRAWSTUFF_OBJECTS_MM)
# side-effect variables causing creation of files containing lists of
# filenames to be linked, to work around command-line-length limitations
Index: config/makefile.osx
===================================================================
RCS file: /cvsroot/ode/config/makefile.osx,v
retrieving revision 1.1
diff -c -r1.1 makefile.osx
*** config/makefile.osx 2001/12/25 06:22:48 1.1
--- config/makefile.osx 2002/07/26 02:56:22
***************
*** 2,19 ****
DEL_CMD=rm -f
CC=cc
OBJ=.o
! C_FLAGS=-c -Wall -fno-rtti -fno-exceptions -Wall
C_INC=-I
C_OUT=-o
C_EXEOUT=-o
C_DEF=-D
C_OPT=-O
AR=ar rc
! RANLIB=
LIB_PREFIX=lib
LIB_SUFFIX=.a
! LINK_OPENGL=-L/usr/X11R6/lib -L/usr/X11/lib -L/usr/lib/X11R6 -L/usr/lib/X11 -lX11 -lGL -lGLU
! LINK_MATH=-lm
ifeq ($(BUILD),release)
OPT=2
--- 2,20 ----
DEL_CMD=rm -f
CC=cc
OBJ=.o
! C_FLAGS=-c -Wall -fno-rtti -fno-exceptions -Wall -DMACOSX
C_INC=-I
C_OUT=-o
C_EXEOUT=-o
C_DEF=-D
C_OPT=-O
AR=ar rc
! RANLIB=ranlib
LIB_PREFIX=lib
LIB_SUFFIX=.a
! LINK_OPENGL=-framework Cocoa -framework OpenGL -lstdc++
! LINK_MATH=
! MACOSX=1
ifeq ($(BUILD),release)
OPT=2
***************
*** 24,26 ****
--- 25,30 ----
OPT=0
C_FLAGS+=-g
endif
+
+ %$(OBJ): %.mm
+ $(CC) $(C_FLAGS) $(C_INC)$(INCPATH) $(DEFINES) $(C_OPT)$(OPT) $(C_OUT)$@ $<
Index: drawstuff/src/drawstuff.cpp
===================================================================
RCS file: /cvsroot/ode/drawstuff/src/drawstuff.cpp,v
retrieving revision 1.20
diff -c -r1.20 drawstuff.cpp
*** drawstuff/src/drawstuff.cpp 2002/06/25 23:46:14 1.20
--- drawstuff/src/drawstuff.cpp 2002/07/26 02:56:22
***************
*** 41,48 ****
--- 41,53 ----
#endif
#include <ode/config.h>
+ #ifdef MACOSX
+ #include <OpenGL/gl.h>
+ #include <OpenGL/glu.h>
+ #else
#include <GL/gl.h>
#include <GL/glu.h>
+ #endif
#include "drawstuff/drawstuff.h"
#include "internal.h"
--Apple-Mail-1--47056944
Content-Transfer-Encoding: 7bit
Content-Type: text/plain;
charset=US-ASCII;
format=flowed
-tim
On Thursday, July 25, 2002, at 07:00 PM, maddocks@metservice.com wrote:
> How did you get on with this?
>
> You say that you have drawstuff running natively. Would you care to
> share your port?
>
> Henry
--Apple-Mail-1--47056944--