/*
* Written By:
* Michael Laforest < para >
* Email: < thepara (--AT--) g m a i l [--DOT--] com >
*
* Copyright 2006-2007
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program 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
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
* $Header$
*/
#include
#include /* for SDL_Init, SDL_Quit */
#include /* for SDL_GetError */
#include /* for SDL_Event, SDL_PollEvent, etc */
#include /* for SDL_GL_SetAttribute, etc */
#ifndef WIIUSE_MAC
#include /* for glVertex3f, GLfloat, etc */
#include /* for gluLookAt, gluOrtho2D, etc */
#include /* for glutSolidTeapot */
#else
/* Mac doesn't use the same folders for OpenGL/GLUT includes */
#include /* for glVertex3f, GLfloat, etc */
#include /* for gluLookAt, gluOrtho2D, etc */
#include /* for glutSolidTeapot */
#endif
#ifndef WIIUSE_WIN32
#include /* for timeval, gettimeofday */
#include /* for time */
#include /* for usleep */
#else
#include
#endif
#include /* for printf */
#define PI 3.14159265358979323846
#define PI_DIV_180 0.017453292519943296
#define deg PI_DIV_180
#define MAX_WIIMOTES 2
GLint width = 1024, height = 768;
GLfloat backColor[4] = {1.0, 1.0, 1.0, 1.0};
wiimote** wiimotes = NULL;
int last_dots[4][2] = {{0}};
int xcoord = 0;
int ycoord = 0;
#ifdef WIN32
DWORD last_render;
#else
struct timeval last_render;
int last_sec = 0;
int fps = 0;
#endif
enum render_mode_t {
IR = 1,
TEAPOT
};
enum render_mode_t render_mode = IR;
/* light information */
struct light_t {
GLfloat position[4];
GLfloat spotDirection[3];
GLfloat ambient[4];
GLfloat diffuse[4];
GLfloat specular[4];
GLfloat spotCutoff;
GLfloat spotExponent;
GLfloat spotAttenuation[3]; /* [0] = constant, [1] = linear, [2] = quadratic */
};
struct light_t light = {
{ 1.0, 1.0, -2.0, 1.0 },
{ -1.0, -1.0, 2.0 },
{ 0.0, 0.0, 0.0, 1.0 },
{ 1.0, 1.0, 1.0, 1.0 },
{ 1.0, 1.0, 1.0, 1.0 },
180.0, 0.0,
{ 1.0, 0.0, 0.0 }
};
/* material information */
struct material_t {
GLfloat ambient[4];
GLfloat diffuse[4];
GLfloat specular[4];
GLfloat emission[4];
GLfloat shininess;
};
struct material_t red_plastic = {
{ 0.3, 0.0, 0.0, 1.0 },
{ 0.3, 0.0, 0.0, 1.0 },
{ 0.8, 0.6, 0.6, 1.0 },
{ 0.0, 0.0, 0.0, 1.0 },
32.0
};
void handle_event(struct wiimote_t* wm);
void display();
void update_light(GLenum l, struct light_t* lptr);
void set_material(struct material_t* mptr);
void resize_window(GLint new_width, GLint new_height);
void handle_event(struct wiimote_t* wm) {
if (IS_JUST_PRESSED(wm, WIIMOTE_BUTTON_PLUS)) {
wiiuse_motion_sensing(wm, 1);
}
if (IS_JUST_PRESSED(wm, WIIMOTE_BUTTON_MINUS)) {
wiiuse_motion_sensing(wm, 0);
}
if (IS_JUST_PRESSED(wm, WIIMOTE_BUTTON_UP)) {
wiiuse_set_ir(wm, 1);
}
if (IS_JUST_PRESSED(wm, WIIMOTE_BUTTON_DOWN)) {
wiiuse_set_ir(wm, 0);
}
if (IS_JUST_PRESSED(wm, WIIMOTE_BUTTON_B)) {
wiiuse_toggle_rumble(wm);
}
if (IS_JUST_PRESSED(wm, WIIMOTE_BUTTON_ONE)) {
int level;
WIIUSE_GET_IR_SENSITIVITY(wm, &level);
wiiuse_set_ir_sensitivity(wm, level + 1);
}
if (IS_JUST_PRESSED(wm, WIIMOTE_BUTTON_TWO)) {
int level;
WIIUSE_GET_IR_SENSITIVITY(wm, &level);
wiiuse_set_ir_sensitivity(wm, level - 1);
}
#if 0
if (IS_JUST_PRESSED(wm, WIIMOTE_BUTTON_A)) {
if (render_mode == IR) {
render_mode = TEAPOT;
} else {
render_mode = IR;
}
resize_window(width, height);
}
#endif
}
#define DRAW_TRIANGLE(x, y, z, s) do { \
glVertex3f(x, y-s, z); \
glVertex3f(x+s, y+s, z); \
glVertex3f(x-s, y+s, z); \
} while (0)
int can_render() {
/* quick fps limit to ~60fps -- not too fancy, could be better */
#ifdef WIN32
if (GetTickCount() < (last_render + 16)) {
return 0;
}
last_render = GetTickCount();
return 1;
#else
struct timeval now;
long elapsed_usec = 0;
gettimeofday(&now, NULL);
if (now.tv_usec > 1000000) {
now.tv_usec -= 1000000;
++now.tv_sec;
}
if (now.tv_sec > last_render.tv_sec) {
elapsed_usec = ((now.tv_sec - last_render.tv_sec) * 1000000);
}
if (now.tv_usec > last_render.tv_usec) {
elapsed_usec += now.tv_usec - last_render.tv_usec;
} else {
elapsed_usec += last_render.tv_usec - now.tv_usec;
}
if (time(NULL) > last_sec) {
printf("fps: %i\n", fps);
fps = 0;
last_sec = time(NULL);
}
if (elapsed_usec < 16000) {
return 0;
}
last_render = now;
++fps;
return 1;
#endif
}
void display() {
int i, wm;
float size = 5;
if (!can_render()) {
return;
}
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
if (render_mode == IR) {
/* draw the IR stuff */
glDisable(GL_LIGHTING);
glBegin(GL_TRIANGLES);
/* green center */
glColor3f(0.0, 1.0, 0.0);
DRAW_TRIANGLE(width / 2, height / 2, 0, size);
glEnd();
for (wm = 0; wm < MAX_WIIMOTES; ++wm) {
glBegin(GL_TRIANGLES);
/* red ir */
glColor3f(1.0, 0.0, 0.0);
for (i = 0; i < 4; ++i) {
if (wiimotes[wm]->ir.dot[i].visible) {
DRAW_TRIANGLE(wiimotes[wm]->ir.dot[i].rx, wiimotes[wm]->ir.dot[i].ry, 0, size);
}
}
/* yellow corrected ir */
glColor3f(1.0, 1.0, 0.0);
for (i = 0; i < 4; ++i) {
if (wiimotes[wm]->ir.dot[i].visible) {
DRAW_TRIANGLE(wiimotes[wm]->ir.dot[i].x, wiimotes[wm]->ir.dot[i].y, 0, size);
}
}
/* blue cursor */
glColor3f(0.0, 0.0, 1.0);
DRAW_TRIANGLE(wiimotes[wm]->ir.x, wiimotes[wm]->ir.y - size, 0, size);
glEnd();
}
} else {
/* draw the teapot */
gluLookAt(0.0, 0.0, -5.0,
0.0, 0.0, 0.0,
0.0, 1.0, 0.0);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
update_light(GL_LIGHT0, &light);
set_material(&red_plastic);
glRotatef(wiimotes[0]->orient.roll, 0.0f, 0.0f, 1.0f);
glRotatef(wiimotes[0]->orient.pitch, 1.0f, 0.0f, 0.0f);
glutSolidTeapot(1);
}
SDL_GL_SwapBuffers();
}
void update_light(GLenum l, struct light_t* lptr) {
glLightfv(l, GL_POSITION, lptr->position);
glLightfv(l, GL_DIFFUSE, lptr->diffuse);
glLightfv(l, GL_SPECULAR, lptr->specular);
glLightfv(l, GL_AMBIENT, lptr->ambient);
glLightfv(l, GL_SPOT_DIRECTION, lptr->spotDirection);
glLightf(l, GL_SPOT_CUTOFF, lptr->spotCutoff);
glLightf(l, GL_SPOT_EXPONENT, lptr->spotExponent);
glLightf(l, GL_CONSTANT_ATTENUATION, lptr->spotAttenuation[0]);
glLightf(l, GL_LINEAR_ATTENUATION, lptr->spotAttenuation[1]);
glLightf(l, GL_QUADRATIC_ATTENUATION, lptr->spotAttenuation[2]);
}
void set_material(struct material_t* mptr) {
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mptr->ambient);
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mptr->diffuse);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mptr->specular);
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, mptr->shininess);
glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, mptr->emission);
}
void resize_window(GLint new_width, GLint new_height) {
int wm;
width = new_width;
height = new_height;
if (new_height == 0) {
new_height = 1;
}
SDL_SetVideoMode(width, height, 16, SDL_RESIZABLE | SDL_OPENGL);
glViewport(0, 0, new_width, new_height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if (render_mode == IR) {
gluOrtho2D(0, width, height, 0);
} else {
gluPerspective(60.0f, (float)new_width / (float)new_height, 0.1f, 100.0f);
}
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
width = new_width;
height = new_height;
for (wm = 0; wm < MAX_WIIMOTES; ++wm) {
wiiuse_set_ir_vres(wiimotes[wm], width, height);
}
}
#ifndef WIN32
int main(int argc, char** argv) {
#else
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
#endif
int found, connected;
int wm;
/* printf("wiiuse version = %s\n", wiiuse_version()); */
wiimotes = wiiuse_init(MAX_WIIMOTES);
found = wiiuse_find(wiimotes, MAX_WIIMOTES, 5);
if (!found) {
return 0;
}
connected = wiiuse_connect(wiimotes, MAX_WIIMOTES);
if (connected) {
printf("Connected to %i wiimotes (of %i found).\n", connected, found);
} else {
printf("Failed to connect to any wiimote.\n");
return 0;
}
wiiuse_set_leds(wiimotes[0], WIIMOTE_LED_1 | WIIMOTE_LED_4);
wiiuse_set_leds(wiimotes[1], WIIMOTE_LED_2 | WIIMOTE_LED_4);
wiiuse_rumble(wiimotes[0], 1);
#ifndef WIN32
usleep(200000);
#else
Sleep(200);
#endif
wiiuse_rumble(wiimotes[0], 0);
/* enable IR and motion sensing for all wiimotes */
for (wm = 0; wm < MAX_WIIMOTES; ++wm) {
wiiuse_motion_sensing(wiimotes[wm], 1);
wiiuse_set_ir(wiimotes[wm], 1);
}
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
printf("Failed to initialize SDL: %s\n", SDL_GetError());
return 0;
}
SDL_WM_SetCaption("wiiuse SDL IR Example", "wiiuse SDL IR Example");
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
/* set window size */
width = wiimotes[0]->ir.vres[0];
height = wiimotes[0]->ir.vres[1];
SDL_SetVideoMode(width, height, 16, SDL_RESIZABLE | SDL_OPENGL);
for (wm = 0; wm < MAX_WIIMOTES; ++wm) {
wiiuse_set_ir_vres(wiimotes[wm], width, height);
}
/* set OpenGL stuff */
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glEnable(GL_NORMALIZE);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDepthFunc(GL_LEQUAL);
glClearColor(0, 0, 0, 0);
/* set the size of the window */
resize_window(width, height);
display();
#ifdef WIN32
last_render = GetTickCount();
#endif
while (1) {
SDL_Event event;
if (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_VIDEORESIZE: {
/* resize the window */
resize_window(event.resize.w, event.resize.h);
break;
}
case SDL_QUIT: {
/* shutdown */
SDL_Quit();
wiiuse_cleanup(wiimotes, MAX_WIIMOTES);
return 0;
}
default: {
}
}
}
if (wiiuse_poll(wiimotes, MAX_WIIMOTES)) {
/*
* This happens if something happened on any wiimote.
* So go through each one and check if anything happened.
*/
int i = 0;
for (; i < MAX_WIIMOTES; ++i) {
switch (wiimotes[i]->event) {
case WIIUSE_EVENT:
/* a generic event occurred */
handle_event(wiimotes[i]);
break;
default:
break;
}
}
}
display();
}
}