Das ganze funktioniert mit der Tastatureigabe Gimbal Lock frei, die Tastatureingabe sieht ungefähr so aus:
Code:
if (receiver.keyPressed(KEY_UP) || receiver.keyDown(KEY_UP))
{
//!myShip_Node->setRotation( core::vector3df (myShip_Node->getRotation().X - rotSpeed, myShip_Node->getRotation().Y, myShip_Node->getRotation().Z));
myShip_Node->setQRotationX(-rotSpeed);
}
if (receiver.keyPressed(KEY_DOWN) || receiver.keyDown(KEY_DOWN))
{
//!myShip_Node->setRotation( core::vector3df (myShip_Node->getRotation().X + rotSpeed, myShip_Node->getRotation().Y, myShip_Node->getRotation().Z));
myShip_Node->setQRotationX(rotSpeed);
}
if (receiver.keyPressed(KEY_LEFT) || receiver.keyDown(KEY_LEFT))
{
//!myShip_Node->setRotation( core::vector3df (myShip_Node->getRotation().X, myShip_Node->getRotation().Y - rotSpeed, myShip_Node->getRotation().Z));
myShip_Node->setQRotationY(-rotSpeed);
}
if (receiver.keyPressed(KEY_RIGHT) || receiver.keyDown(KEY_RIGHT))
{
//!myShip_Node->setRotation( core::vector3df (myShip_Node->getRotation().X, myShip_Node->getRotation().Y + rotSpeed, myShip_Node->getRotation().Z));
myShip_Node->setQRotationY(rotSpeed);
}
das auskommentierte war der vorherige zustand welcher erst gar keine Probleme mittels Z-Rotation zuliess aber zu einem Gimbal Lock führte.
EDIT: ganz vergessen... das ewige toEuler rumgegurke mit der deg/rad umwandlung war mir zu dumm darum gibts auch noch die funktion hier welche oben ja verwendet wird
Code:
//! returns the Eulers
vector3df shipObject::getEuler()
{
vector3df myRot;
myQuat.toEuler(myRot);
myRot = vector3df(core::radToDeg(myRot.X), core::radToDeg(myRot.Y), core::radToDeg(myRot.Z) );
return myRot;
}
EDIT ende
die jetzte verwendete rotation ist zu vergleichen mit dieser hier aus dem englischen forum
http://irrlicht.sourceforge.net/phpBB2/ ... highlight= welche aber auch zu Gimbal locks führen kann.
die Quaternionfunktionen habe ich übrigens von diesen hier übernommen und lediglich in c++ gecoded:
http://www.boristheengineer.co.uk/gamem ... rnions.gmlwie gesagt das ganze funktioniert auch mit einer tastatureingabe.
Mein aktueller Versuch das ganze zu automatisieren sieht so aus:
Code:
bool shipObject::trackToAnimator()
{
f32 rotSpeed = 0.25;
if( trackSeeker() && trackToAngleReached == false) //!trackToAngleReachedX and trackToAngleReachedY needs to be done here
{
trackTargetPos = trackTargetNode->getAbsolutePosition();
quaternion rotQuat;
vector3df fromVect = emptyZ->getAbsolutePosition();
rotQuat.rotationFromTo(fromVect, trackTargetPos);
vector3df qte;
rotQuat.toEuler(qte);
eulerToTarget = vector3df(radToDeg(qte.X), radToDeg(qte.Y), radToDeg(qte.Z));
f32 tx = radToDeg(qte.X);
f32 ty = radToDeg(qte.Y);
f32 tz = radToDeg(qte.Z);
f32 rsX;
f32 rsY;
f32 ttx = sqrtf(tx * tx);
f32 tty = sqrtf(ty * ty);
if ( ttx > tty )
{
rsX = rotSpeed;
rsY = rotSpeed;// / ttx * tty;
}
else
{
rsX = rotSpeed;// / tty * ttx;
rsY = rotSpeed;
}
f32 myRotX;
f32 myRotY;
//!x
if ( tx > 0 && trackToAngleReachedX == false )
{
if (tx - rsX < 0)
{
myRotX = tx;
trackToAngleReachedX = true;
}
else
{
myRotX = rsX;;
}
}
if ( tx < 0 && trackToAngleReachedX == false )
{
if (tx + rsX > 0)
{
myRotX = -tx;
trackToAngleReachedX = true;
}
else
{
myRotX = -rsX;
}
}
//!y
if ( ty > 0 && trackToAngleReachedY == false )
{
if (ty - rsY < 0)
{
myRotY = ty;
trackToAngleReachedY = true;
}
else
{
myRotY = rsY;
}
}
if ( ty < 0 && trackToAngleReachedY == false )
{
if (ty + rsY > 0)
{
myRotY = -ty;
trackToAngleReachedY = true;
}
else
{
myRotY = -rsY;
}
}
animateQRotationXY(myRotX, myRotY);
//!setting the vars for Artifacial Horizon
rotatingSet = true;
zeroHorizonReached = false;
if (trackToAngleReachedX == true && trackToAngleReachedY == true)
{
trackToAngleReached = true;
}
else
{
trackToAngleReached = false;
}
}
}
Code:
bool shipObject::trackSeeker()//!returns true if trackTargetNode still Exists
{
return true;//just for testreasons
}
Code:
void shipObject::trackTo(shipObject* targetNode)
{
trackTargetNode = targetNode;
trackToAngleReached = false;
trackToAngleReachedX = false;
trackToAngleReachedY = false;
}
Code:
quaternion shipObject::quaternion_fly_anim(f32 angleX, f32 angleY)//!angle in degree
{
std::cout << "\n angle x " << angleY;
f32 angX;
angX = core::degToRad(angleX)/2;
quaternion rotQuatX;
rotQuatX.W = cosf(angX);
rotQuatX.X = sinf(angX);
rotQuatX.Y = 0;
rotQuatX.Z = 0;
f32 angY;
angY = core::degToRad(angleY)/2;
quaternion rotQuatY;
rotQuatY.W = cosf(angY);
rotQuatY.X = 0;
rotQuatY.Y = sinf(angY);
rotQuatY.Z = 0;
quaternion resultQuat;
resultQuat = multiply_quaternion_right( myQuat, rotQuatX);
resultQuat = multiply_quaternion_right( resultQuat, rotQuatY);
return resultQuat;
}
Code:
void shipObject::animateQRotationXY(f32 angleX, f32 angleY)
{
myQuat = quaternion_fly_anim(angleX, angleY);
this->setRotation(getEuler());
rotatingSet = true;
zeroHorizonReached = false;
}
die Tausend versuche dazwischen lasse ich mal aussenvor...
dazwischen gabs natürlich noch die SLERP vaariante:
Code:
trackTargetPos = trackTargetNode->getAbsolutePosition();
quaternion rotQuat;
vector3df fromVect = emptyZ->getAbsolutePosition();
rotQuat.rotationFromTo(fromVect, trackTargetPos);
vector3df qte;
rotQuat.toEuler(qte);
vector3df qta;
myQuat.toEuler(qta);
eulerToTarget = vector3df(radToDeg(qte.X), radToDeg(qte.Y), radToDeg(qte.Z));
eulerFrom = vector3df(radToDeg(qta.X), radToDeg(qta.Y), radToDeg(qta.Z));
quaternion resultQuat;
resultQuat.slerp (eulerFrom, eulerToTarget, 1);
vector3df qtr;
resultQuat.toEuler(qtr);
vector3df resultVect = vector3df(radToDeg(qtr.X), radToDeg(qtr.Y), radToDeg(qtr.Z));
this->setRotation(resultVect);
das ganze natürlich auch als langsam animiert aber so oder so bleibt die animation irgendwo mittendrin stehen weil 1 erreicht wird und auch hier bei 1 leibts mitten drin stecken.
emptyZ ist übrigens ein Empty Node der ein child von myShip ist und an position 0.0.1 positioniert ist also in forward richtung des schiffes und sich mit dreht und somit einen aushilfsvector darstellt.
Dazwischen gabs so gefühlte tausend andere versionen die ich zwar ausbuddeln und regenerieren könnte aber naja.