/***************************************************************************
* Copyright (C) 2004 by Raphael Langerhorst *
* raphael-langerhorst@gmx.at *
* *
* Permission is hereby granted, free of charge, to any person obtaining *
* a copy of this software and associated documentation files (the *
* "Software"), to deal in the Software without restriction, including *
* without limitation the rights to use, copy, modify, merge, publish, *
* distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to *
* the following conditions: *
* *
* The above copyright notice and this permission notice shall be *
* included in all copies or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, *
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*
* IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
***************************************************************************/
#include "GCamera.h"
#include <qapplication.h>
using namespace GCS;
namespace GCE
{
GCamera::GCamera(GOpenGLFrame* frame, GCS::GForm* form, QObject* parent, const char* name)
: QObject(parent,name),
KeyUpdateTime(QTime::currentTime()),
Frame(frame),
Form(form),
ViewDistancePercent(250),
SpeedFactor(200),
speedx(0),
speedy(0),
shutdown(true),
up_key_down(false),
down_key_down(false),
left_key_down(false),
right_key_down(false),
space_key_down(false)
{
qApp->installEventFilter(this);
connect(qApp,SIGNAL(aboutToQuit()),this,SLOT(stopCamera()));
if (Frame)
{
connect(Frame,SIGNAL(beforeRendering()),this,SLOT(update()));
}
}
GCamera::~GCamera()
{
}
void GCamera::update()
{
if (!shutdown)
{
// qDebug("updating camera");
double delta_t = KeyUpdateTime.restart()*0.001;
//update speeds:
if (up_key_down)
speedy += delta_t;
if (down_key_down)
speedy -= delta_t;
if (left_key_down)
speedx += delta_t;
if (right_key_down)
speedx -= delta_t;
//update position from form:
GVector3& pos = Frame->ViewProperties.ViewPosition;
GVector3& target = Frame->ViewProperties.ViewTarget;
GVector3& up = Frame->ViewProperties.ViewUp;
// qDebug(QString("Current form position before updating: %1").arg(Form->Position.toString()));
GVector3 dir = target - pos;
if (dir.length()==0)
dir.z = 1;
target.set(Form->Position);
dir.normalize();
if (space_key_down)
{
emit this->translationSpeedImpulse(dir*(delta_t*SpeedFactor));
// Form->Dynamics.Speed += dir*(delta_t*300);
}
dir.mul(Form->getRadiusMax()*this->ViewDistancePercent *0.01 );
pos = target - dir;
// qDebug(QString("Current form position after updating: %1").arg(Form->Position.toString()));
if (speedx != 0 || speedy != 0)
{
//@todo: don't modify the view properties directly if there is a camera element set, probably we should give the camera a pointer to the GMoveAgent that it should use for speed and rotation impulses!
// bool x_positive;
// bool y_positive;
if (dir.x != 0 || dir.y != 0 || dir.z != 0)
{
dir.turnAroundAxis(up,speedx);
GVector3 side = dir.cross(up);
side.normalize();
dir.turnAroundAxis(side,speedy);
pos = target - dir;
up = side.cross(dir);
up.normalize();
double factor = 0.99;
double abs_sub = 0.001;
double border = 0.001;
speedx *= factor*delta_t;
speedy *= factor*delta_t;
if (speedx > 0)
{
speedx -= abs_sub*delta_t;
if (speedx < border)
speedx = 0;
}
else if (speedx<0)
{
speedx += abs_sub*delta_t;
if (speedx > -border)
speedx = 0;
}
if (speedy > 0)
{
speedy -= abs_sub*delta_t;
if (speedy < border)
speedy = 0;
}
else if (speedy<0)
{
speedy += abs_sub*delta_t;
if (speedy > -border)
speedy = 0;
}
}
}
}
}
void GCamera::startCamera()
{
Q_CHECK_PTR(Frame);
Q_CHECK_PTR(Form);
if (Frame != NULL && Form != NULL)
{
this->shutdown = false;
this->KeyUpdateTime = QTime::currentTime();
}
}
void GCamera::stopCamera()
{
this->shutdown = true;
}
void GCamera::setFrame(GOpenGLFrame* frame)
{
if (Frame)
{
disconnect(Frame,SIGNAL(beforeRendering()),this,SLOT(update()));
}
this->Frame = frame;
if (Frame)
{
connect(Frame,SIGNAL(beforeRendering()),this,SLOT(update()));
}
}
void GCamera::setForm(GCS::GForm* form)
{
this->Form = form;
}
bool GCamera::eventFilter(QObject* watched, QEvent* e)
{
if (Frame)
{
if (!Frame->hasFocus())
return FALSE;
}
if (e->type() == QEvent::KeyPress)
{
QKeyEvent* ke = (QKeyEvent*)(e);
int key = ke->key();
// //@todo determine correct elapsed time (save key states and check which ones are down in the main thread, etc...)
// double delta = 0.01;
switch(key)
{
case Qt::Key_Left:
left_key_down = true;
break;
case Qt::Key_Right:
right_key_down = true;
break;
case Qt::Key_Up:
up_key_down = true;
break;
case Qt::Key_Down:
down_key_down = true;
break;
case Qt::Key_Space:
{
space_key_down = true;
break;
}
case Qt::Key_Return:
{
// Form->Dynamics.Speed.set(0,0,0);
emit stopMovement();
break;
}
case Qt::Key_Enter:
{
emit stopMovement();
// Form->Dynamics.Speed.set(0,0,0);
break;
}
default:
qDebug("unknown key");
return FALSE;
}
//if we get here the key press event has been processed:
// e->accept();
return TRUE;
}
else if (e->type() == QEvent::KeyRelease)
{
QKeyEvent* ke = (QKeyEvent*)(e);
int key = ke->key();
// //@todo determine correct elapsed time (save key states and check which ones are down in the main thread, etc...)
// double delta = 0.01;
switch(key)
{
case Qt::Key_Left:
left_key_down = false;
break;
case Qt::Key_Right:
right_key_down = false;
break;
case Qt::Key_Up:
up_key_down = false;
break;
case Qt::Key_Down:
down_key_down = false;
break;
case Qt::Key_Space:
{
space_key_down = false;
break;
}
}
//if we get here the key press event has been processed:
// e->accept();
return TRUE;
}
return false;
}
void GCamera::setViewDistance(int new_distance_percent)
{
if (new_distance_percent <= 0)
new_distance_percent = 1;
this->ViewDistancePercent = new_distance_percent;
}
void GCamera::setSpeedFactor(double speed_factor)
{
this->SpeedFactor = speed_factor;
}
};
syntax highlighted by Code2HTML, v. 0.9.1