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

#ifdef X11
#include <X11/Intrinsic.h>
#include <X11/keysym.h>
#include <Xm/Xm.h>
#include <GL/glx.h>
#include <GLwMDrawA.h>
#endif
#include <windows.h>
#include <GL/glu.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#ifdef X11
#include <sys/time.h>
#else
#include <time.h>
#endif
#ifdef WIN32
#include "stonehen.h"
#endif
#include "atmosphe.h"
#include "scene.h"
#include "callback.h"
int cb_demo_mode = 0;
float demo_time;
#ifdef X11
extern Widget glw;
extern XtAppContext app_context;
GLXContext glx_context;
#endif
static int needs_wp = 0;
#ifdef X11
static XtWorkProcId workproc = NULL;
#else
static int workproc = 0;
#endif
static int winx, winy;
static int button_down = 0;
int mousex, mousey;
/* What's moving */
GLint target;
/* Location of the telescope */
GLfloat tx, ty;
/* Movements of the camera position to be applied at the next redraw */
float rot_pendx = 0, rot_pendz = 0, trans_pend = 0;
/* How fast the camera is moving */
float trans_speed = 0;
/* This is how fast demo time moves relative to real time */
GLfloat time_scale = 0;
TimeDate last_update;
float last_time = 0;
const float time_fudge = 1000;
inline unsigned long current_time()
{
#ifdef X11
struct timeval time;
gettimeofday(&time, NULL);
return (time.tv_sec * 1000000 + time.tv_usec);
#else
return (GetTickCount() * 1000);
#endif
}
inline float clamp(float x, float min, float max)
{
if (x < min) return min;
else if (x > max) return max;
else return x;
}
static void add_workproc(Widget w)
{
needs_wp++;
#ifdef X11
if (workproc == NULL)
workproc = XtAppAddWorkProc(app_context, drawWP, NULL);
#else
workproc = SetTimer(w, 1, 1000, NULL);
#endif
}
static void remove_workproc(Widget w)
{
needs_wp--;
if (needs_wp == 0) {
#ifdef X11
XtRemoveWorkProc(workproc);
workproc = NULL;
#else
KillTimer(w, 1);
workproc = 0;
#endif
} else if (needs_wp < 0) {
fprintf(stderr, "Internal Error: No workproc to remove!\n");
needs_wp = 0;
workproc = NULL;
}
}
static void reset_viewer()
{
scene_viewer_center();
}
#ifdef X11
void intToggleCB(Widget w, XtPointer client_data, XtPointer call_data)
{
int *data;
XmToggleButtonCallbackStruct *ptr;
ptr = (XmToggleButtonCallbackStruct *)call_data;
data = (int *)client_data;
*data = ptr->set;
// This redraw may or may not be needed - do it to be safe
drawWP(NULL);
}
void initCB(Widget w)
{
Arg args[1];
XVisualInfo *vi;
glw = w;
XtSetArg(args[0], GLwNvisualInfo, &vi);
XtGetValues(w, args, 1);
glx_context = glXCreateContext(XtDisplay(w), vi, 0, GL_FALSE);
GLwDrawingAreaMakeCurrent(w, glx_context);
scene_init();
last_update.read_time();
resetViewerCB(NULL, NULL, NULL);
}
void exposeCB(Widget w)
{
drawWP(NULL);
}
#endif
void resizeCB(Widget w, XtPointer client_data, XtPointer call)
{
#ifdef X11
GLwDrawingAreaCallbackStruct *call_data;
GLwDrawingAreaMakeCurrent(w, glx_context);
call_data = (GLwDrawingAreaCallbackStruct *)call;
winx = call_data->width;
winy = call_data->height;
#else
RECT rect;
GetClientRect(w, &rect);
winx = WINDSIZEX(rect);
winy = WINDSIZEY(rect);
#endif
glViewport(0, 0, winx, winy);
aspect = (GLfloat)winx / (GLfloat)winy;
}
void inputCB(Widget w, XtPointer client_data, XtPointer call_data)
{
GLwDrawingAreaCallbackStruct *call;
int bufsize = 5;
#ifdef X11
char buffer[5];
KeySym key;
XComposeStatus compose;
#endif
float dx, dy, r1, r2;
#ifdef X11
GLwDrawingAreaMakeCurrent(w, glx_context);
#endif
call = (GLwDrawingAreaCallbackStruct *)call_data;
switch(call->event->type) {
case ButtonPress:
last_time = current_time();
button_down = call->event->xbutton.button;
mousex = call->event->xbutton.x;
mousey = call->event->xbutton.y;
/* Determine if the target should be the camera position
* or the telescope */
if (use_telescope) {
scene_get_position_telescope(&tx, &ty);
scene_get_radius_telescope(&r1);
dx = (tx + .5) - ((GLfloat)(winx - mousex)/(GLfloat)winx);
dy = (ty + .5) - ((GLfloat)(winy - mousey)/(GLfloat)winy);
r2 = sqrt(dx*dx + dy*dy);
if (r2 < r1) target = name_telescope;
else target = name_background;
} else target = name_background;
add_workproc(w);
break;
case ButtonRelease:
#ifdef X11
if (call->event->xbutton.button == Button3) {
/* Use Button3 to stop */
if (trans_speed) remove_workproc(w);
trans_speed = 0;
}
#endif
remove_workproc(w);
button_down = 0;
break;
case MotionNotify:
switch(button_down) {
case Button1:
/* Use Button1 to control the way in which the viewer is looking
* or to move the telescope around */
if (target == name_background) {
dx = (float)(call->event->xmotion.x - mousex) / (float)winx;
dy = (float)(call->event->xmotion.y - mousey) / (float)winy;
rot_pendx -= dy * fov;
rot_pendz -= dx * fov;
} else {
dx = (float)(mousex - call->event->xmotion.x) / (float)winx;
dy = (float)(mousey - call->event->xmotion.y) / (float)winy;
tx += dx;
ty += dy;
tx = clamp(tx, -.5, .5);
ty = clamp(ty, -.5, .5);
scene_position_telescope(tx, ty);
}
break;
case Button2:
/* Use Button2 to change speed */
dx = (float)(mousex - call->event->xmotion.x) /
(float)winx;
if (dx && !trans_speed) add_workproc(w);
#ifdef WIN32
else if (!dx && trans_speed) remove_workproc(w);
#endif
trans_speed += dx;
break;
}
mousex = call->event->xmotion.x;
mousey = call->event->xmotion.y;
break;
#ifdef X11 // We can handle our own keys...
case KeyPress:
XLookupString(&(call->event->xkey), buffer, bufsize, &key, &compose);
if (key == XK_Escape) exit(0);
break;
#endif
default:
break;
}
}
const float speed_t = .5;
const float speed_r = 15.;
const float speed_rx = 10.;
void demo_mode_update(float dt)
{
float t;
if (!cb_demo_mode) return;
dt /= 1000000;
demo_time += dt;
t = demo_time;
if (t < 10.5) {
trans_speed = speed_t;
return;
} else t -= 10.5;
if (t < 1) {
trans_speed = 0;
rot_pendz = 0;
return;
} else t -= 1;
if (t < 3.) {
trans_speed = 0.;
rot_pendz = dt * speed_r;
return;
} else t -= 3.;
if (t < 2.) {
rot_pendx = -dt * speed_rx;
return;
} else t -= 2.;
if (t < 2.) {
return;
} else t -= 2.;
if (t < 2.) {
rot_pendx = dt * speed_rx;
return;
} else t -= 2.;
if (t < 3.) {
trans_speed = 0.;
rot_pendz = dt * speed_r;
return;
} else t -= 3.;
if (t < 30.) {
trans_speed = speed_t;
rot_pendz = 0;
return;
} else t -= 30.;
if (t < 1.) {
trans_speed = 0;
return;
} else t -= 1.;
if (t < 1.3) {
rot_pendz = -dt * speed_r;
return;
} else t -= 1.3;
// Pan back to see entire thing
if (t < 23) {
trans_speed = speed_t;
return;
} else t -= 23;
// Hold before starting over
if (t < 20) {
trans_speed = 0;
return;
}
else t -= 20;
demo_time = 0.;
reset_viewer();
}
Boolean drawWP(Widget w)
{
/* Right now, there's two completely independent time measurements:
* one for the time of day in the demo and one for changing the camera
* position */
TimeDate t, dt;
float elapsed_time, time;
#ifdef WIN32
HDC hDC;
#endif
if (time_scale != 0.0) {
t.read_time();
dt = (t - last_update) * time_scale;
scene_inc_time(dt);
last_update = t;
}
time = current_time();
if (time - last_time > time_fudge) {
elapsed_time = time - last_time;
demo_mode_update(elapsed_time);
trans_pend = trans_speed * (elapsed_time / 1000000);
last_time = time;
}
scene_viewer_rotatex(rot_pendx);
scene_viewer_rotatez(rot_pendz);
scene_viewer_translate(trans_pend);
rot_pendx = 0;
rot_pendz = 0;
trans_pend = 0;
#ifdef X11
GLwDrawingAreaMakeCurrent(glw, glx_context);
scene_render();
/* This is a total hack */
// if (!use_antialias)
GLwDrawingAreaSwapBuffers(glw);
#else
hDC = GetDC(w);
scene_render();
SwapBuffers(hDC);
ReleaseDC(w, hDC);
#endif
return FALSE;
}
#ifdef X11
void weatherCB(Widget w, XtPointer client_data, XtPointer call_data)
{
Weather *data;
XmToggleButtonCallbackStruct *ptr;
ptr = (XmToggleButtonCallbackStruct *)call_data;
if (ptr->set) scene_set_weather(*((Weather *)client_data));
drawWP(NULL);
}
#endif
void currentTimeCB(Widget w)
{
scene_set_time(TimeDate().read_time());
drawWP(w);
}
void time10amCB(Widget w)
{
scene_set_time(TimeDate(10, 0));
drawWP(w);
}
void time12pmCB(Widget w)
{
scene_set_time(TimeDate(12, 0));
drawWP(w);
}
void time4pmCB(Widget w)
{
scene_set_time(TimeDate(16, 0));
drawWP(w);
}
void timeSpeedCB(Widget w, XtPointer client_data, XtPointer call_data)
{
#ifdef X11
if (!((XmToggleButtonCallbackStruct *)call_data)->set) return;
time_scale = (int)client_data;
#endif
if (time_scale == 0.0) remove_workproc(w);
else add_workproc(w);
last_update.read_time();
}
void demo_modeCB(Widget w, XtPointer client_data, XtPointer call_data)
{
#ifdef X11
int val = ((XmToggleButtonCallbackStruct *)call_data)->set;
#else
int val = cb_demo_mode;
#endif
if (!val) {
remove_workproc(w);
resetViewerCB(w, NULL, NULL);
last_time = current_time();
} else {
reset_viewer();
add_workproc(w);
trans_speed = 0;
demo_time = 0;
rot_pendx = -5;
}
drawWP(w);
}
void resetViewerCB(Widget w, XtPointer client_data, XtPointer call_data)
{
trans_speed = 0;
rot_pendx = rot_pendz = trans_pend = 0;
rot_pendx = -5;
reset_viewer();
return;
}
void exitCB(Widget w, XtPointer client_data, XtPointer call_data)
{
exit(0);
}