Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

497 lines
9.5 KiB

  1. #ifdef X11
  2. #include <X11/Intrinsic.h>
  3. #include <X11/keysym.h>
  4. #include <Xm/Xm.h>
  5. #include <GL/glx.h>
  6. #include <GLwMDrawA.h>
  7. #endif
  8. #include <windows.h>
  9. #include <GL/glu.h>
  10. #include <math.h>
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #ifdef X11
  14. #include <sys/time.h>
  15. #else
  16. #include <time.h>
  17. #endif
  18. #ifdef WIN32
  19. #include "stonehen.h"
  20. #endif
  21. #include "atmosphe.h"
  22. #include "scene.h"
  23. #include "callback.h"
  24. int cb_demo_mode = 0;
  25. float demo_time;
  26. #ifdef X11
  27. extern Widget glw;
  28. extern XtAppContext app_context;
  29. GLXContext glx_context;
  30. #endif
  31. static int needs_wp = 0;
  32. #ifdef X11
  33. static XtWorkProcId workproc = NULL;
  34. #else
  35. static int workproc = 0;
  36. #endif
  37. static int winx, winy;
  38. static int button_down = 0;
  39. int mousex, mousey;
  40. /* What's moving */
  41. GLint target;
  42. /* Location of the telescope */
  43. GLfloat tx, ty;
  44. /* Movements of the camera position to be applied at the next redraw */
  45. float rot_pendx = 0, rot_pendz = 0, trans_pend = 0;
  46. /* How fast the camera is moving */
  47. float trans_speed = 0;
  48. /* This is how fast demo time moves relative to real time */
  49. GLfloat time_scale = 0;
  50. TimeDate last_update;
  51. float last_time = 0;
  52. const float time_fudge = 1000;
  53. inline unsigned long current_time()
  54. {
  55. #ifdef X11
  56. struct timeval time;
  57. gettimeofday(&time, NULL);
  58. return (time.tv_sec * 1000000 + time.tv_usec);
  59. #else
  60. return (GetTickCount() * 1000);
  61. #endif
  62. }
  63. inline float clamp(float x, float min, float max)
  64. {
  65. if (x < min) return min;
  66. else if (x > max) return max;
  67. else return x;
  68. }
  69. static void add_workproc(Widget w)
  70. {
  71. needs_wp++;
  72. #ifdef X11
  73. if (workproc == NULL)
  74. workproc = XtAppAddWorkProc(app_context, drawWP, NULL);
  75. #else
  76. workproc = SetTimer(w, 1, 1000, NULL);
  77. #endif
  78. }
  79. static void remove_workproc(Widget w)
  80. {
  81. needs_wp--;
  82. if (needs_wp == 0) {
  83. #ifdef X11
  84. XtRemoveWorkProc(workproc);
  85. workproc = NULL;
  86. #else
  87. KillTimer(w, 1);
  88. workproc = 0;
  89. #endif
  90. } else if (needs_wp < 0) {
  91. fprintf(stderr, "Internal Error: No workproc to remove!\n");
  92. needs_wp = 0;
  93. workproc = NULL;
  94. }
  95. }
  96. static void reset_viewer()
  97. {
  98. scene_viewer_center();
  99. }
  100. #ifdef X11
  101. void intToggleCB(Widget w, XtPointer client_data, XtPointer call_data)
  102. {
  103. int *data;
  104. XmToggleButtonCallbackStruct *ptr;
  105. ptr = (XmToggleButtonCallbackStruct *)call_data;
  106. data = (int *)client_data;
  107. *data = ptr->set;
  108. // This redraw may or may not be needed - do it to be safe
  109. drawWP(NULL);
  110. }
  111. void initCB(Widget w)
  112. {
  113. Arg args[1];
  114. XVisualInfo *vi;
  115. glw = w;
  116. XtSetArg(args[0], GLwNvisualInfo, &vi);
  117. XtGetValues(w, args, 1);
  118. glx_context = glXCreateContext(XtDisplay(w), vi, 0, GL_FALSE);
  119. GLwDrawingAreaMakeCurrent(w, glx_context);
  120. scene_init();
  121. last_update.read_time();
  122. resetViewerCB(NULL, NULL, NULL);
  123. }
  124. void exposeCB(Widget w)
  125. {
  126. drawWP(NULL);
  127. }
  128. #endif
  129. void resizeCB(Widget w, XtPointer client_data, XtPointer call)
  130. {
  131. #ifdef X11
  132. GLwDrawingAreaCallbackStruct *call_data;
  133. GLwDrawingAreaMakeCurrent(w, glx_context);
  134. call_data = (GLwDrawingAreaCallbackStruct *)call;
  135. winx = call_data->width;
  136. winy = call_data->height;
  137. #else
  138. RECT rect;
  139. GetClientRect(w, &rect);
  140. winx = WINDSIZEX(rect);
  141. winy = WINDSIZEY(rect);
  142. #endif
  143. glViewport(0, 0, winx, winy);
  144. aspect = (GLfloat)winx / (GLfloat)winy;
  145. }
  146. void inputCB(Widget w, XtPointer client_data, XtPointer call_data)
  147. {
  148. GLwDrawingAreaCallbackStruct *call;
  149. int bufsize = 5;
  150. #ifdef X11
  151. char buffer[5];
  152. KeySym key;
  153. XComposeStatus compose;
  154. #endif
  155. float dx, dy, r1, r2;
  156. #ifdef X11
  157. GLwDrawingAreaMakeCurrent(w, glx_context);
  158. #endif
  159. call = (GLwDrawingAreaCallbackStruct *)call_data;
  160. switch(call->event->type) {
  161. case ButtonPress:
  162. last_time = current_time();
  163. button_down = call->event->xbutton.button;
  164. mousex = call->event->xbutton.x;
  165. mousey = call->event->xbutton.y;
  166. /* Determine if the target should be the camera position
  167. * or the telescope */
  168. if (use_telescope) {
  169. scene_get_position_telescope(&tx, &ty);
  170. scene_get_radius_telescope(&r1);
  171. dx = (tx + .5) - ((GLfloat)(winx - mousex)/(GLfloat)winx);
  172. dy = (ty + .5) - ((GLfloat)(winy - mousey)/(GLfloat)winy);
  173. r2 = sqrt(dx*dx + dy*dy);
  174. if (r2 < r1) target = name_telescope;
  175. else target = name_background;
  176. } else target = name_background;
  177. add_workproc(w);
  178. break;
  179. case ButtonRelease:
  180. #ifdef X11
  181. if (call->event->xbutton.button == Button3) {
  182. /* Use Button3 to stop */
  183. if (trans_speed) remove_workproc(w);
  184. trans_speed = 0;
  185. }
  186. #endif
  187. remove_workproc(w);
  188. button_down = 0;
  189. break;
  190. case MotionNotify:
  191. switch(button_down) {
  192. case Button1:
  193. /* Use Button1 to control the way in which the viewer is looking
  194. * or to move the telescope around */
  195. if (target == name_background) {
  196. dx = (float)(call->event->xmotion.x - mousex) / (float)winx;
  197. dy = (float)(call->event->xmotion.y - mousey) / (float)winy;
  198. rot_pendx -= dy * fov;
  199. rot_pendz -= dx * fov;
  200. } else {
  201. dx = (float)(mousex - call->event->xmotion.x) / (float)winx;
  202. dy = (float)(mousey - call->event->xmotion.y) / (float)winy;
  203. tx += dx;
  204. ty += dy;
  205. tx = clamp(tx, -.5, .5);
  206. ty = clamp(ty, -.5, .5);
  207. scene_position_telescope(tx, ty);
  208. }
  209. break;
  210. case Button2:
  211. /* Use Button2 to change speed */
  212. dx = (float)(mousex - call->event->xmotion.x) /
  213. (float)winx;
  214. if (dx && !trans_speed) add_workproc(w);
  215. #ifdef WIN32
  216. else if (!dx && trans_speed) remove_workproc(w);
  217. #endif
  218. trans_speed += dx;
  219. break;
  220. }
  221. mousex = call->event->xmotion.x;
  222. mousey = call->event->xmotion.y;
  223. break;
  224. #ifdef X11 // We can handle our own keys...
  225. case KeyPress:
  226. XLookupString(&(call->event->xkey), buffer, bufsize, &key, &compose);
  227. if (key == XK_Escape) exit(0);
  228. break;
  229. #endif
  230. default:
  231. break;
  232. }
  233. }
  234. const float speed_t = .5;
  235. const float speed_r = 15.;
  236. const float speed_rx = 10.;
  237. void demo_mode_update(float dt)
  238. {
  239. float t;
  240. if (!cb_demo_mode) return;
  241. dt /= 1000000;
  242. demo_time += dt;
  243. t = demo_time;
  244. if (t < 10.5) {
  245. trans_speed = speed_t;
  246. return;
  247. } else t -= 10.5;
  248. if (t < 1) {
  249. trans_speed = 0;
  250. rot_pendz = 0;
  251. return;
  252. } else t -= 1;
  253. if (t < 3.) {
  254. trans_speed = 0.;
  255. rot_pendz = dt * speed_r;
  256. return;
  257. } else t -= 3.;
  258. if (t < 2.) {
  259. rot_pendx = -dt * speed_rx;
  260. return;
  261. } else t -= 2.;
  262. if (t < 2.) {
  263. return;
  264. } else t -= 2.;
  265. if (t < 2.) {
  266. rot_pendx = dt * speed_rx;
  267. return;
  268. } else t -= 2.;
  269. if (t < 3.) {
  270. trans_speed = 0.;
  271. rot_pendz = dt * speed_r;
  272. return;
  273. } else t -= 3.;
  274. if (t < 30.) {
  275. trans_speed = speed_t;
  276. rot_pendz = 0;
  277. return;
  278. } else t -= 30.;
  279. if (t < 1.) {
  280. trans_speed = 0;
  281. return;
  282. } else t -= 1.;
  283. if (t < 1.3) {
  284. rot_pendz = -dt * speed_r;
  285. return;
  286. } else t -= 1.3;
  287. // Pan back to see entire thing
  288. if (t < 23) {
  289. trans_speed = speed_t;
  290. return;
  291. } else t -= 23;
  292. // Hold before starting over
  293. if (t < 20) {
  294. trans_speed = 0;
  295. return;
  296. }
  297. else t -= 20;
  298. demo_time = 0.;
  299. reset_viewer();
  300. }
  301. Boolean drawWP(Widget w)
  302. {
  303. /* Right now, there's two completely independent time measurements:
  304. * one for the time of day in the demo and one for changing the camera
  305. * position */
  306. TimeDate t, dt;
  307. float elapsed_time, time;
  308. #ifdef WIN32
  309. HDC hDC;
  310. #endif
  311. if (time_scale != 0.0) {
  312. t.read_time();
  313. dt = (t - last_update) * time_scale;
  314. scene_inc_time(dt);
  315. last_update = t;
  316. }
  317. time = current_time();
  318. if (time - last_time > time_fudge) {
  319. elapsed_time = time - last_time;
  320. demo_mode_update(elapsed_time);
  321. trans_pend = trans_speed * (elapsed_time / 1000000);
  322. last_time = time;
  323. }
  324. scene_viewer_rotatex(rot_pendx);
  325. scene_viewer_rotatez(rot_pendz);
  326. scene_viewer_translate(trans_pend);
  327. rot_pendx = 0;
  328. rot_pendz = 0;
  329. trans_pend = 0;
  330. #ifdef X11
  331. GLwDrawingAreaMakeCurrent(glw, glx_context);
  332. scene_render();
  333. /* This is a total hack */
  334. // if (!use_antialias)
  335. GLwDrawingAreaSwapBuffers(glw);
  336. #else
  337. hDC = GetDC(w);
  338. scene_render();
  339. SwapBuffers(hDC);
  340. ReleaseDC(w, hDC);
  341. #endif
  342. return FALSE;
  343. }
  344. #ifdef X11
  345. void weatherCB(Widget w, XtPointer client_data, XtPointer call_data)
  346. {
  347. Weather *data;
  348. XmToggleButtonCallbackStruct *ptr;
  349. ptr = (XmToggleButtonCallbackStruct *)call_data;
  350. if (ptr->set) scene_set_weather(*((Weather *)client_data));
  351. drawWP(NULL);
  352. }
  353. #endif
  354. void currentTimeCB(Widget w)
  355. {
  356. scene_set_time(TimeDate().read_time());
  357. drawWP(w);
  358. }
  359. void time10amCB(Widget w)
  360. {
  361. scene_set_time(TimeDate(10, 0));
  362. drawWP(w);
  363. }
  364. void time12pmCB(Widget w)
  365. {
  366. scene_set_time(TimeDate(12, 0));
  367. drawWP(w);
  368. }
  369. void time4pmCB(Widget w)
  370. {
  371. scene_set_time(TimeDate(16, 0));
  372. drawWP(w);
  373. }
  374. void timeSpeedCB(Widget w, XtPointer client_data, XtPointer call_data)
  375. {
  376. #ifdef X11
  377. if (!((XmToggleButtonCallbackStruct *)call_data)->set) return;
  378. time_scale = (int)client_data;
  379. #endif
  380. if (time_scale == 0.0) remove_workproc(w);
  381. else add_workproc(w);
  382. last_update.read_time();
  383. }
  384. void demo_modeCB(Widget w, XtPointer client_data, XtPointer call_data)
  385. {
  386. #ifdef X11
  387. int val = ((XmToggleButtonCallbackStruct *)call_data)->set;
  388. #else
  389. int val = cb_demo_mode;
  390. #endif
  391. if (!val) {
  392. remove_workproc(w);
  393. resetViewerCB(w, NULL, NULL);
  394. last_time = current_time();
  395. } else {
  396. reset_viewer();
  397. add_workproc(w);
  398. trans_speed = 0;
  399. demo_time = 0;
  400. rot_pendx = -5;
  401. }
  402. drawWP(w);
  403. }
  404. void resetViewerCB(Widget w, XtPointer client_data, XtPointer call_data)
  405. {
  406. trans_speed = 0;
  407. rot_pendx = rot_pendz = trans_pend = 0;
  408. rot_pendx = -5;
  409. reset_viewer();
  410. return;
  411. }
  412. void exitCB(Widget w, XtPointer client_data, XtPointer call_data)
  413. {
  414. exit(0);
  415. }