summaryrefslogtreecommitdiffstats
path: root/matchblox/engine/C_MatchBloxEngine.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'matchblox/engine/C_MatchBloxEngine.cpp')
-rw-r--r--matchblox/engine/C_MatchBloxEngine.cpp359
1 files changed, 267 insertions, 92 deletions
diff --git a/matchblox/engine/C_MatchBloxEngine.cpp b/matchblox/engine/C_MatchBloxEngine.cpp
index e9c9473..93a178f 100644
--- a/matchblox/engine/C_MatchBloxEngine.cpp
+++ b/matchblox/engine/C_MatchBloxEngine.cpp
@@ -4,7 +4,11 @@
#include <string>
#include <iostream>
+#define _USE_MATH_DEFINES
+#include <math.h>
+
#include "C_MatchBloxEngine.h"
+#include "message_input.h"
#include "C_3DObject.h"
#include "C_Environment.h"
@@ -13,6 +17,9 @@
#include "C_Box.h"
#include "C_Log.h"
#include "bitmap.h"
+#include "message_queue.h"
+#include "message_input.h"
+
C_MatchBloxEngine::C_MatchBloxEngine(const char *f_strModelPath,
const char *f_strLogFile,
@@ -40,9 +47,11 @@ C_MatchBloxEngine::C_MatchBloxEngine(const char *f_strModelPath,
m_CurrentBox = BS_SMALL;
//init the world bounding box
- m_WorldBox.m_Min = Vect3D_t(-50.0, -50.0, -50.0);
- m_WorldBox.m_Max = Vect3D_t(50.0, 50.0, 0.0);
+ m_WorldBox.m_Min = Vect3D_t(-15.0, -5.0, -15.0);
+ m_WorldBox.m_Max = Vect3D_t(15.0, 15.0, 15.0);
+ //m_DotHist.clear();
+ //m_DotHistSize = 15;
}
C_MatchBloxEngine::~C_MatchBloxEngine()
@@ -55,25 +64,76 @@ C_MatchBloxEngine::~C_MatchBloxEngine()
GameResult C_MatchBloxEngine::ProcessMsgs(void)
{
- //msgStruct l_msg;
+ struct messageq_s *message;
+
+ while (message = messageq_get(MESSAGE_RENDERER))
+ {
+ switch(message->sender)
+ {
+ case MESSAGE_INPUT_KEYBOARD:
+ break;
+ case MESSAGE_INPUT_MOUSE:
+ break;
+ case MESSAGE_INPUT_WIIMOTE:
+ //get message payload
+ //??how to interpret the message payload??
+ //wiimote ir dots have a range of 1024x768 in xy which can easily be mapped to world xycoords
+ //for the z coordinate: we know the size of the sensorbar, the reach of a human arm is <1m so
+ //if we map the initial z distance (in mm) -iz- (taken in ES_GET_READY) to be 0 and -z to be iz - 250mm
+ //and +z to be iz + 250 mm we have 3d input!!
+ //process button presses
+
+ //process ir data
+ input_payload_wiimote *l_pMsg;
+ l_pMsg = (input_payload_wiimote*)message->payload;
+
+ //for(int i=0; i<4; i++)
+ {
+ if (l_pMsg->btns && WIIMOTE_BUTTON_A)
+ {
+ //init depth
+ Vect3D_t l_relPos;
+ if (CalcWiimoteRelativeCursorPos(l_pMsg, &l_relPos))
+ {
+ m_dInitialWiimoteDist = l_relPos.z;
+ }
+ else
+ {
+ m_dInitialWiimoteDist = 500.0;
+ }
+ }
+ else
+ {
+ Vect3D_t l_WorldPos;
+ if (ConvertWiimoteToWorld(l_pMsg, &l_WorldPos))
+ {
+ m_pBlock[0]->SetPos(l_WorldPos);
+ }
+ }
+
+ //std::cout << "Dot["<<i<<"] ("<< l_pMsg->Dot[i].RawX <<","<< l_pMsg->Dot[i].RawY <<")\n";
+ }
+
+ //if (m_State == ES_GET_READY)
+ //{
+ // //if player has pressed the A button
+ // //take the initial z distance
+
+ // //perhaps we should do a countdown 3.. 2.. 1.. GO! but this requires another engine state
+ //}
+ //if (m_State == ES_PLAYING_GRAB_BLOCK || m_State == ES_PLAYING_PUT_BLOCK)
+ //{
+ // //convert ir data to cursor pos in world coordinates
+
+ // Vect3D_t tmpPos(l_pMsg->x, l_pMsg->y, l_pMsg->z);
+ // CursorMove(tmpPos);
+ //}
+ break;
+ default:
+ std::cout << "Undefined message! Sender: " << message->sender << std::endl;
+ }
+ }
- ////process message queue
- //while (!f_Queue.empty())
- //{
- // //get the first msg
- // l_msg = f_Queue.front();
- // f_Queue.pop();
-
- // switch (l_msg.m_MessageType)
- // {
- // case WII_CURSOR_MOVE:
- //
- // break;
-
- // case WII_BUTTON_PRESS:
- // break;
- // }
- //}
return GR_BUSY;
}
@@ -102,8 +162,9 @@ void C_MatchBloxEngine::Render_Basics(unsigned int f_uiElapsedTime)
//if (m_pCurrentSession)
//{
m_pBox[(int)m_CurrentBox]->Render();
- //for (int i=0; i<4; i++)
- //m_pBlock[i]->Render(f_uiElapsedTime);
+ m_pBlock[0]->Render(f_uiElapsedTime);
+ /* for (int i=0; i<4; i++)
+ m_pBlock[i]->Render(f_uiElapsedTime);*/
// m_pHand->Render(f_uiElapsedTime);
//}
@@ -153,42 +214,20 @@ void C_MatchBloxEngine::Render(unsigned int f_uiElapsedTime)
break;
}
- //glPushMatrix();
-
- //double l_dSeconds = (double)f_uiElapsedTime/1000.0;
-
- //glRotated(l_dSeconds * 5.0, 0.0, 1.0, 0.0);
- ////glRotated(l_dSeconds * 10, 0.0, 0.0, 1.0);
-
- //m_pEnvMap->Render();
-
- //glPopMatrix();
-
- //m_pBox[0]->Render();
-
- //for(int i=0; i<4; i++)
- //{
- // glPushMatrix();
- // m_pBlock[i]->Render(f_uiElapsedTime);
- // glPopMatrix();
- //}
-
}
bool C_MatchBloxEngine::NewGame(int f_iUserID, int f_iGameId, BoxSize f_BS)
{
if(m_State == ES_INITIALISED)
{
- //log new game
+ m_CurrentBox = f_BS;
//prepare a session struct for administration
- m_pCurrentSession = new GameSession(8, f_BS);
+ m_pCurrentSession = new GameSession(m_GameSettings.m_iNrOfTurns, f_BS);
//randomize the box tiles
- m_pBox[(int)m_pCurrentSession->m_BoxSize]->RandomizeTiles();
+ m_pBox[(int)m_CurrentBox]->RandomizeTiles();
- m_CurrentBox = f_BS;
-
//set state to GET READY
m_State = ES_GET_READY;
@@ -202,13 +241,11 @@ bool C_MatchBloxEngine::StartGame()
{
if (m_State == ES_GET_READY)
{
- BlockType l_Block;
-
//start the session timer
- l_Block = m_pCurrentSession->StartSession();
+ m_CurrentBlock = m_pCurrentSession->StartSession();
//move a block into the sky
- m_pBlock[(int)l_Block]->SetPos(0.0, 0.0, 15.0);
+ m_pBlock[(int)m_CurrentBlock ]->SetPos(0.0, 0.0, 15.0);
m_State = ES_PLAYING_GRAB_BLOCK;
@@ -226,7 +263,7 @@ bool C_MatchBloxEngine::Pause()
//save current state
m_SavedState = m_State;
- //probably do something with a time variable
+ m_pCurrentSession->PauseSession();
//set current state to paused
m_State = ES_PAUSED;
@@ -244,8 +281,8 @@ bool C_MatchBloxEngine::Resume()
//restore previous state
m_State = m_SavedState;
- //restore timers
- //
+ //restore timer
+ m_pCurrentSession->ResumeSession();
return true;
}
@@ -260,7 +297,12 @@ bool C_MatchBloxEngine::Abort()
//set state to initialised
m_State = ES_INITIALISED;
- //..
+ //delete session (if there is any)
+ if (m_pCurrentSession)
+ {
+ delete m_pCurrentSession;
+ m_pCurrentSession = NULL;
+ }
return true;
}
@@ -455,52 +497,185 @@ void C_MatchBloxEngine::CursorMove(Vect3D_t &f_NewCursorPos)
}
-bool C_MatchBloxEngine::CursorMove_PutBlock(Vect3D_t &f_CursPos, BoundingBox_t &f_CursBBox)
+//bool C_MatchBloxEngine::CursorMove_PutBlock(Vect3D_t &f_CursPos, BoundingBox_t &f_CursBBox)
+//{
+// //check if the block is being put in the right hole
+// //by testing whether the position of the cursor is close
+// //enough to the center of the correct hole
+// //note that the hole positions are relative to the position
+// //of the box
+// bool l_bCollision = false;
+// Vect3D_t l_AbsHolePos = m_pBox[m_CurrentBox]->GetPos() +
+// m_pTiles[m_CurrentBlock]->GetPos();
+// Vect3D_t l_PosDif = l_AbsHolePos - f_CursPos;
+// double l_dXZProximity = l_PosDif.x * l_PosDif.x +
+// l_PosDif.y * l_PosDif.y;
+//
+// if (l_dXZProximity < m_GameSettings.m_dMinProximity)
+// {
+// //the block the player is holding is considered to be in the right hole
+// //l_bCollision = false;
+//
+// //?? would it not be better to check for bounding box intersection with hole?
+// l_bCollision = !(m_pTiles[m_CurrentBlock]->GetAbsBoundBox() +
+// m_pBox[m_CurrentBox]->GetPos()).Overlap(f_CursBBox);
+//
+// //now check if the block is far enough in the hole to count as a point
+// if (l_PosDif.z > m_GameSettings.m_dHoleDepth)
+// {
+// //yipee!! we have got a winner!!
+// m_CurrentBlock = m_pCurrentSession->NewTurn();
+//
+// //m_GameState
+// }
+//
+//
+//
+// }
+//
+// return false;
+//}
+
+//bool C_MatchBloxEngine::CursorMove_GrabBlock(Vect3D_t &f_CursPos, BoundingBox_t &f_CursBBox)
+//{
+// //grabbing a block: just check for bounding box intersection
+// if (m_pBlock[(int)m_CurrentBlock]->GetAbsBoundBox().Overlap(f_CursBBox))
+// {
+//
+// }
+// return true;
+//}
+
+
+bool C_MatchBloxEngine::FindIRDots(input_payload_wiimote *f_pWiimote, ir_dot_t f_Dot[2])
{
- //check if the block is being put in the right hole
- //by testing whether the position of the cursor is close
- //enough to the center of the correct hole
- //note that the hole positions are relative to the position
- //of the box
- bool l_bCollision = false;
- Vect3D_t l_AbsHolePos = m_pBox[m_CurrentBox]->GetPos() +
- m_pTiles[m_CurrentBlock]->GetPos();
- Vect3D_t l_PosDif = l_AbsHolePos - f_CursPos;
- double l_dXZProximity = l_PosDif.x * l_PosDif.x +
- l_PosDif.y * l_PosDif.y;
-
- if (l_dXZProximity < m_GameSettings.m_dMinProximity)
+ //find the pair of ir dots with the largest squared distance
+ int mdist = 0, //max length
+ dist2,dx,dy,
+ dot0, dot1;
+
+ //loop through all combinations
+ for(int i = 0; i < 4; i++)
{
- //the block the player is holding is considered to be in the right hole
- //l_bCollision = false;
-
- //?? would it not be better to check for bounding box intersection with hole?
- l_bCollision = !(m_pTiles[m_CurrentBlock]->GetAbsBoundBox() +
- m_pBox[m_CurrentBox]->GetPos()).Overlap(f_CursBBox);
-
- //now check if the block is far enough in the hole to count as a point
- if (l_PosDif.z > m_GameSettings.m_dHoleDepth)
+ for (int j = i+1; j < 4; j++)
{
- //yipee!! we have got a winner!!
- m_CurrentBlock = m_pCurrentSession->NewTurn();
-
- //m_GameState
+ //check if the ir dots are found
+ if (f_pWiimote->ir.dot[i].visible &&
+ f_pWiimote->ir.dot[j].visible)
+ {
+ //compute the squared distance
+ dx = f_pWiimote->ir.dot[i].rx - f_pWiimote->ir.dot[j].rx;
+ dy = f_pWiimote->ir.dot[i].ry - f_pWiimote->ir.dot[j].ry;
+ dist2 = dx*dx + dy*dy;
+
+ if (dist2 > mdist)
+ {
+ mdist = dist2;
+ dot0 = i;
+ dot1 = j;
+ //std::cout << "(" << i << "," << j <<") " << mdist << std::endl;
+ }
+ }
}
-
-
-
}
- return false;
+ if (mdist > 0)
+ {
+ std::cout << "Winner - (" << dot0 << "," << dot1 <<") " << mdist << " numdots: " << (int)f_pWiimote->ir.num_dots << std::endl;
+ //left down is f_Dot[0]
+ if (f_pWiimote->ir.dot[dot0].rx < f_pWiimote->ir.dot[dot1].ry ||
+ (f_pWiimote->ir.dot[dot0].rx == f_pWiimote->ir.dot[dot1].ry &&
+ f_pWiimote->ir.dot[dot0].rx < f_pWiimote->ir.dot[dot1].ry))
+ {
+ f_Dot[0] = f_pWiimote->ir.dot[dot0];
+ f_Dot[1] = f_pWiimote->ir.dot[dot1];
+ }
+ else
+ {
+ f_Dot[0] = f_pWiimote->ir.dot[dot1];
+ f_Dot[1] = f_pWiimote->ir.dot[dot0];
+ }
+
+ return true;
+ }
+ else
+ {
+ //std::cout << "nothing...\n";
+ return false;
+ }
}
-bool C_MatchBloxEngine::CursorMove_GrabBlock(Vect3D_t &f_CursPos, BoundingBox_t &f_CursBBox)
+
+bool C_MatchBloxEngine::CalcWiimoteRelativeCursorPos(input_payload_wiimote *f_pWiimote, Vect3D_t *f_pRelPos)
{
- //grabbing a block: just check for bounding box intersection
- if (m_pBlock[(int)m_CurrentBlock]->GetAbsBoundBox().Overlap(f_CursBBox))
- {
-
- }
+ //get two ir dots
+ ir_dot_t l_Dot[2];
+
+ if (!FindIRDots(f_pWiimote, l_Dot))
+ return false;
+
+ //dotpair l_dp(l_Dot[0], l_Dot[1]);
+ //m_DotHist.push_front(l_dp);
+ //if (m_DotHist.size() > m_DotHistSize)
+ // m_DotHist.pop_back();
+
+ ////calculate the average dots
+ //l_Dot[0].RawX = l_Dot[0].RawY = l_Dot[1].RawX = l_Dot[1].RawY = 0;
+ //for(list<dotpair>::iterator it = m_DotHist.begin(); it != m_DotHist.end(); it++)
+ //{
+ // l_Dot[0].RawX += it->first.RawX; l_Dot[0].RawY += it->first.RawY;
+ // l_Dot[1].RawX += it->second.RawX; l_Dot[1].RawY += it->second.RawY;
+ //}
+ //l_Dot[0].RawX /= (double)m_DotHist.size(); l_Dot[0].RawY /= (double)m_DotHist.size();
+ //l_Dot[1].RawX /= (double)m_DotHist.size(); l_Dot[1].RawY /= (double)m_DotHist.size();
+
+
+ //invert the x and y axis
+ l_Dot[0].rx = 1016 - l_Dot[0].ry;
+ l_Dot[1].rx = 1016 - l_Dot[1].ry;
+ l_Dot[0].rx = 760 - l_Dot[0].ry;
+ l_Dot[1].rx = 760 - l_Dot[1].ry;
+
+ double l_dX = (double)l_Dot[0].rx - l_Dot[1].rx, //difference in x coordinates
+ l_dY = (double)l_Dot[0].ry - l_Dot[1].ry, //difference in y coordinates
+ l_dDotDist = sqrt(l_dX*l_dX + l_dY*l_dY), //distance between ir dots (in camera pixels)
+ l_dRadPerPixel = ( 41.0 * (M_PI/180.0) ) /1016.0, //radians per camera pixel: x view angel = 41 deg, 1016 pixels
+ l_dDotAngle = l_dRadPerPixel * l_dDotDist; //the angle between the lines from the camera through the two
+ //ir dots (in radians)
+
+ f_pRelPos->x = (double)(l_Dot[0].rx + l_Dot[1].rx)/2.0; //camera x coordinate [0,1016]
+ f_pRelPos->y = (double)(l_Dot[0].ry + l_Dot[1].ry)/2.0; //camera y coordinate [0,760]
+ f_pRelPos->z = (0.5 * 205.0) / tan(0.5 * l_dDotAngle); //the distance between the sensorbar and wiimote (in mm)
+ //std::cout << "(" << f_pRelPos->x << "," << f_pRelPos->y << "," << f_pRelPos->z << ")\n";
+
return true;
}
+bool C_MatchBloxEngine::ConvertWiimoteToWorld(input_payload_wiimote *f_pWiimote, Vect3D_t *f_pWorldPos)
+{
+ Vect3D_t l_RelPos;
+
+ if (!CalcWiimoteRelativeCursorPos(f_pWiimote, &l_RelPos))
+ return false;
+
+ //use the world bounding box dimensions to convert the relative position to world coordinates
+
+ //z is in mm, cap it to 250mm from the initial wiimote distance
+ //using the initial distance
+ l_RelPos.z = l_RelPos.z - m_dInitialWiimoteDist + 250;
+ if (l_RelPos.z < 0.0) l_RelPos.z = 0.0;
+ else if (l_RelPos.z > 500.0) l_RelPos.z = 500.0;
+
+ //Vect3D_t l_WorldSize(m_WorldBox.m_Max - m_WorldBox.m_Min);
+ Vect3D_t l_WorldSize;
+ l_WorldSize.x = m_WorldBox.m_Max.x - m_WorldBox.m_Min.x;
+ l_WorldSize.y = m_WorldBox.m_Max.y - m_WorldBox.m_Min.y;
+ l_WorldSize.z = m_WorldBox.m_Max.z - m_WorldBox.m_Min.z;
+
+ f_pWorldPos->x = m_WorldBox.m_Min.x + ((l_RelPos.x * l_WorldSize.x)/1016.0); //1016 pixels in x
+ f_pWorldPos->y = m_WorldBox.m_Min.y + ((l_RelPos.y * l_WorldSize.y)/ 760.0); // 769 pixels in y
+ f_pWorldPos->z = m_WorldBox.m_Min.z + ((l_RelPos.z * l_WorldSize.z)/ 500.0);// 500 mm in z
+
+ //std::cout << "(" << f_pWorldPos->x << "," << f_pWorldPos->y << "," << f_pWorldPos->z << ")\n";
+ return true;
+} \ No newline at end of file