osx.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  1. /*************************************************************************
  2. * *
  3. * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
  4. * All rights reserved. Email: [email protected] Web: www.q12.org *
  5. * *
  6. * This library is free software; you can redistribute it and/or *
  7. * modify it under the terms of EITHER: *
  8. * (1) The GNU Lesser General Public License as published by the Free *
  9. * Software Foundation; either version 2.1 of the License, or (at *
  10. * your option) any later version. The text of the GNU Lesser *
  11. * General Public License is included with this library in the *
  12. * file LICENSE.TXT. *
  13. * (2) The BSD-style license that is included with this library in *
  14. * the file LICENSE-BSD.TXT. *
  15. * *
  16. * This library is distributed in the hope that it will be useful, *
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
  19. * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
  20. * *
  21. *************************************************************************/
  22. // Platform-specific code for Mac OS X using Carbon+AGL
  23. //
  24. // Created using x11.cpp and the window-initialization -routines from GLFW
  25. // as reference.
  26. // Not thoroughly tested and is certain to contain deficiencies and bugs
  27. #include <ode/odeconfig.h>
  28. #include "config.h"
  29. #include <stdlib.h>
  30. #include <string.h>
  31. #include <stdarg.h>
  32. #ifdef HAVE_SYS_TIME_H
  33. #include <sys/time.h>
  34. #endif
  35. #include <drawstuff/drawstuff.h>
  36. #include <drawstuff/version.h>
  37. #include "internal.h"
  38. #include <OpenGL/gl.h>
  39. #include <GLUT/glut.h>
  40. // Global variables
  41. static bool paused = false; // 1 if in `pause' mode
  42. static bool singlestep = false; // 1 if single step key pressed
  43. static bool writeframes = false; // 1 if frame files to be written
  44. static int windowWidth = -1;
  45. static int windowHeight = -1;
  46. static int mouseButtonMode = 0;
  47. static bool mouseWithOption = false; // Set if dragging the mouse with alt pressed
  48. static bool mouseWithControl = false; // Set if dragging the mouse with ctrl pressed
  49. static dsFunctions* functions = NULL;
  50. static int windowReference;
  51. static int frame = 1;
  52. static int prev_x = 0;
  53. static int prev_y = 0;
  54. //***************************************************************************
  55. // error handling for unix
  56. static void printMessage (const char *msg1, const char *msg2, va_list ap)
  57. {
  58. fflush (stderr);
  59. fflush (stdout);
  60. fprintf (stderr,"\n%s: ",msg1);
  61. vfprintf (stderr,msg2,ap);
  62. fprintf (stderr,"\n");
  63. fflush (stderr);
  64. }
  65. extern "C" void dsError (const char *msg, ...)
  66. {
  67. va_list ap;
  68. va_start (ap,msg);
  69. printMessage ("Error",msg,ap);
  70. va_end (ap);
  71. exit (1);
  72. }
  73. extern "C" void dsDebug (const char *msg, ...)
  74. {
  75. va_list ap;
  76. va_start (ap,msg);
  77. printMessage ("INTERNAL ERROR",msg,ap);
  78. va_end (ap);
  79. // *((char *)0) = 0; ... commit SEGVicide ?
  80. abort();
  81. }
  82. extern "C" void dsPrint (const char *msg, ...)
  83. {
  84. va_list ap;
  85. va_start (ap,msg);
  86. vprintf (msg,ap);
  87. va_end (ap);
  88. }
  89. static void captureFrame( int num ){
  90. fprintf( stderr,"\rcapturing frame %04d", num );
  91. unsigned char buffer[windowWidth*windowHeight][3];
  92. glReadPixels( 0, 0, windowWidth, windowHeight, GL_RGB, GL_UNSIGNED_BYTE, &buffer );
  93. char s[100];
  94. sprintf (s,"frame%04d.ppm",num);
  95. FILE *f = fopen (s,"wb");
  96. if( !f ){
  97. dsError( "can't open \"%s\" for writing", s );
  98. }
  99. fprintf( f,"P6\n%d %d\n255\n", windowWidth, windowHeight );
  100. for( int y=windowHeight-1; y>-1; y-- ){
  101. fwrite( buffer[y*windowWidth], 3*windowWidth, 1, f );
  102. }
  103. fclose (f);
  104. }
  105. extern "C" void dsStop()
  106. {
  107. }
  108. extern "C" double dsElapsedTime()
  109. {
  110. #if HAVE_GETTIMEOFDAY
  111. static double prev=0.0;
  112. timeval tv ;
  113. gettimeofday(&tv, 0);
  114. double curr = tv.tv_sec + (double) tv.tv_usec / 1000000.0 ;
  115. if (!prev)
  116. prev=curr;
  117. double retval = curr-prev;
  118. prev=curr;
  119. if (retval>1.0) retval=1.0;
  120. if (retval<dEpsilon) retval=dEpsilon;
  121. return retval;
  122. #else
  123. return 0.01666; // Assume 60 fps
  124. #endif
  125. }
  126. int osxGetModifierMask()
  127. {
  128. return glutGetModifiers() & ~GLUT_ACTIVE_SHIFT;
  129. }
  130. void osxKeyEventHandler( unsigned char key, int x, int y )
  131. {
  132. unsigned char uppercase;
  133. if (key >= 'a' && key <= 'z')
  134. uppercase = key - ('a' - 'A');
  135. else
  136. uppercase = key;
  137. int modifierMask = osxGetModifierMask();
  138. if (modifierMask == 0)
  139. {
  140. if( key >= ' ' && key <= 126 && functions -> command )
  141. functions -> command( key );
  142. }
  143. else if (modifierMask & GLUT_ACTIVE_CTRL)
  144. {
  145. // ctrl+key was pressed
  146. uppercase += 'A' - 1;
  147. switch(uppercase ){
  148. case 'T':
  149. dsSetTextures( !dsGetTextures() );
  150. break;
  151. case 'S':
  152. dsSetShadows( !dsGetShadows() );
  153. break;
  154. case 'X':
  155. exit(0);
  156. break;
  157. case 'P':
  158. paused = !paused;
  159. singlestep = false;
  160. break;
  161. case 'O':
  162. if( paused ){
  163. singlestep = true;
  164. }
  165. break;
  166. case 'V': {
  167. float xyz[3],hpr[3];
  168. dsGetViewpoint( xyz,hpr );
  169. printf( "Viewpoint = (%.4f,%.4f,%.4f,%.4f,%.4f,%.4f)\n", xyz[0], xyz[1], xyz[2], hpr[0], hpr[1], hpr[2] );
  170. break;
  171. }
  172. case 'W':
  173. writeframes = !writeframes;
  174. if( writeframes ){
  175. printf( "Now writing frames to PPM files\n" );
  176. }
  177. break;
  178. }
  179. }
  180. }
  181. void osxMouseEventHandler(int button, int state, int x, int y)
  182. {
  183. prev_x = x;
  184. prev_y = y;
  185. bool buttonDown = false;
  186. switch( state ){
  187. case GLUT_DOWN:
  188. buttonDown = true;
  189. case GLUT_UP:
  190. if( button == GLUT_LEFT_BUTTON ){
  191. int modifierMask = osxGetModifierMask();
  192. if( modifierMask & GLUT_ACTIVE_CTRL ){
  193. // Ctrl+button == right
  194. button = GLUT_RIGHT_BUTTON;
  195. mouseWithControl = true;
  196. }
  197. else if( modifierMask & GLUT_ACTIVE_ALT ){
  198. // Alt+button == left+right
  199. mouseButtonMode = 5;
  200. mouseWithOption = true;
  201. return;
  202. }
  203. }
  204. if( buttonDown ){
  205. if( button == GLUT_LEFT_BUTTON ) mouseButtonMode |= 1; // Left
  206. if( button == GLUT_MIDDLE_BUTTON ) mouseButtonMode |= 2; // Middle
  207. if( button == GLUT_RIGHT_BUTTON ) mouseButtonMode |= 4; // Right
  208. }
  209. else{
  210. if( button == GLUT_LEFT_BUTTON ) mouseButtonMode &= (~1); // Left
  211. if( button == GLUT_MIDDLE_BUTTON ) mouseButtonMode &= (~2); // Middle
  212. if( button == GLUT_RIGHT_BUTTON ) mouseButtonMode &= (~4); // Right
  213. }
  214. return;
  215. }
  216. }
  217. void osxMotionEventHandler(int x, int y)
  218. {
  219. dsMotion( mouseButtonMode, x - prev_x, y - prev_y );
  220. prev_x = x;
  221. prev_y = y;
  222. }
  223. void osxWindowReshapeEventHandler(int width, int height)
  224. {
  225. windowWidth = width;
  226. windowHeight = height;
  227. }
  228. static void osxCreateMainWindow( int width, int height )
  229. {
  230. int argc = 1;
  231. char* argv[2];
  232. argv[0] = (char*)"";
  233. argv[1] = NULL;
  234. glutInit(&argc, argv);
  235. glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
  236. glutInitWindowSize(width, height);
  237. windowReference = glutCreateWindow("ODE - Drawstuff");
  238. windowWidth = width;
  239. windowHeight = height;
  240. }
  241. void osxRedisplayEventHandler()
  242. {
  243. dsDrawFrame( windowWidth, windowHeight, functions, paused && !singlestep );
  244. singlestep = false;
  245. glutSwapBuffers();
  246. // capture frames if necessary
  247. if( !paused && writeframes ){
  248. captureFrame( frame );
  249. frame++;
  250. }
  251. }
  252. void osxTimerEventHandler(int);
  253. void osxInstallTimerHandler()
  254. {
  255. glutTimerFunc(1000/60, osxTimerEventHandler, 0);
  256. }
  257. void osxTimerEventHandler(int)
  258. {
  259. glutPostRedisplay();
  260. osxInstallTimerHandler();
  261. }
  262. int osxInstallEventHandlers()
  263. {
  264. glutKeyboardFunc(osxKeyEventHandler);
  265. glutMouseFunc(osxMouseEventHandler);
  266. glutMotionFunc(osxMotionEventHandler);
  267. glutDisplayFunc(osxRedisplayEventHandler);
  268. glutReshapeFunc(osxWindowReshapeEventHandler);
  269. osxInstallTimerHandler();
  270. return GL_TRUE;
  271. }
  272. extern void dsPlatformSimLoop( int givenWindowWidth, int givenWindowHeight, dsFunctions *fn, int givenPause ){
  273. functions = fn;
  274. paused = givenPause;
  275. osxCreateMainWindow( givenWindowWidth, givenWindowHeight );
  276. osxInstallEventHandlers();
  277. dsStartGraphics( windowWidth, windowHeight, fn );
  278. static bool firsttime=true;
  279. if( firsttime )
  280. {
  281. fprintf
  282. (
  283. stderr,
  284. "\n"
  285. "Simulation test environment v%d.%02d\n"
  286. " Ctrl-P : pause / unpause (or say `-pause' on command line).\n"
  287. " Ctrl-O : single step when paused.\n"
  288. " Ctrl-T : toggle textures (or say `-notex' on command line).\n"
  289. " Ctrl-S : toggle shadows (or say `-noshadow' on command line).\n"
  290. " Ctrl-V : print current viewpoint coordinates (x,y,z,h,p,r).\n"
  291. " Ctrl-W : write frames to ppm files: frame/frameNNN.ppm\n"
  292. " Ctrl-X : exit.\n"
  293. "\n"
  294. "Change the camera position by clicking + dragging in the window.\n"
  295. " Left button - pan and tilt.\n"
  296. " Right button (or Ctrl + button) - forward and sideways.\n"
  297. " Left + Right button (or middle button, or Alt + button) - sideways and up.\n"
  298. "\n",DS_VERSION >> 8,DS_VERSION & 0xff
  299. );
  300. firsttime = false;
  301. }
  302. if( fn -> start ) fn->start();
  303. glutMainLoop();
  304. }