My space shooter features a ship with two guns, which is controlled by the mouse (the ship flies after the cursor, like in Microsoft's Freelancer). Now i need a method for pointing both of the guns at the cursor. The guns are seperate meshes with the ship as their parent, and their origin is at the point i want to rotate them about. Now i need to find a way to get the angles they have to rotate with.
I tried finding a collision between the mouse ray and a plane and then using math to find the angle to the intersection point. However, things became very complicated, it didnt work and i couldn't find the error. This is the code I used:
//gun aiming
line3d<f32> aimline = colmgr->getRayFromScreenCoordinates(gl->device->getCursorControl()->getPosition(),
camera.camera);
matrix4 m;
m.setRotationDegrees(ships[0].shipnode->getRotation());
vector3df temp1, temp2, temp3;
temp1 = vector3df(0.0f, 1.0f, 1.0f);
temp2 = vector3df(-1.0f, 0.0f, 100.0f);
temp3 = vector3df(1.0f, 0.0f, 100.0f);
m.transformVect(temp1);
m.transformVect(temp2);
m.transformVect(temp3);
temp1 += ships[0].shipnode->getPosition();
temp2 += ships[0].shipnode->getPosition();
temp3 += ships[0].shipnode->getPosition();
plane3d<f32> plane(temp1, temp2, temp3);
plane.getIntersectionWithLine(aimline.getMiddle(), aimline.getVector(), temp1);
temp2 = ships[0].gunnode[0]->getPosition();
m.setRotationDegrees(ships[0].gunnode[0]->getRotation());
temp3 = vector3df(0.0f, 0.0f, 1000.0f);
m.transformVect(temp3);
temp3 += ships[0].gunnode[0]->getPosition();
line3d<f32> templine(ships[0].gunnode[0]->getPosition(), temp3);
temp3 = templine.getClosestPoint(temp1);
float angle, a, b;
a = (float)temp2.getDistanceFrom(temp1);
b = (float)temp1.getDistanceFrom(temp3);
angle = b/a;
angle = (float)asin((double) angle);
angle = angle * (180/PI);
ships[0].gunnode[0]->setRotation(vector3df(-angle,
ships[0].gunnode[0]->getRotation().Y,
ships[0].gunnode[0]->getRotation().Z));
}
I hope someone can either spot the bug or propose a better method for doing this. Thanks alot!
Complicated aiming issue
-
Guest
I didn't read all your code, this is how I would do it:
- create some kind of cube around your spaceship (not visible)
- determine the point on that cube where your mouse is facing (or plane, I think you did this)
- keep track of your shaceships direction vector
- create a vector from your ships position to the point on the cube/plane
basically thats it, you now have a vector you currently looking at (direction vector) and a target-vector (from your ship to the new rotation point). now use the dot-product, calculate the reverse cosine and convert the radians to degree (et voila you can rotate your space ship with euler angles).
(I hope I understood you right, ask if you have any question)
- create some kind of cube around your spaceship (not visible)
- determine the point on that cube where your mouse is facing (or plane, I think you did this)
- keep track of your shaceships direction vector
- create a vector from your ships position to the point on the cube/plane
basically thats it, you now have a vector you currently looking at (direction vector) and a target-vector (from your ship to the new rotation point). now use the dot-product, calculate the reverse cosine and convert the radians to degree (et voila you can rotate your space ship with euler angles).
(I hope I understood you right, ask if you have any question)
Here's a function I found on forums, from Arras, it's added to IrrSpintz, it should help you a lot -
Add this to vector3d.h and I also added a function to line3d to get the angle of the line -
Code: Select all
// Added, got from Arras on the Irrlicht forums
//! Gets the Y and Z rotations of a vector
//! \return A vector representing the rotation ( in degrees ) of
//! this vector.
vector3d<T> getYZangle ( )
{
vector3d<T> angle;
angle.Y = atan2 ( X, Z );
angle.Y *= (f32)GRAD_PI;
if ( angle.Y < 0.0f ) angle.Y += 360.0f;
if ( angle.Y >= 360.0f ) angle.Y -= 360.0f;
float z1;
z1 = sqrt ( X * X + Z * Z );
angle.X = atan2 ( z1, Y);
angle.X *= (f32)GRAD_PI;
angle.X -= 90.0f;
if ( angle.X < 0.0f ) angle.X += 360.0f;
if ( angle.X >= 360 ) angle.X -= 360.0f;
return angle;
}
Code: Select all
vector3d<T> getYXangle ( )
{
vector3d<T> direction = end - start;
return direction.getYZangle ( );
}

-
Guest
What exactly do dot products do? That's the mathematical part where i screwed up: there are two guns on my ship. It's not the ship that needs to rotate, but the guns. They need to be aiming at the mouse cursor. Both guns are near the front of my ship, and i plan to rotate them simply by setRotation() cus their middle point is also the point they should be rotating about.
So after i find the vector of the mouse ray intersection with the plane, how do i go from there?
So after i find the vector of the mouse ray intersection with the plane, how do i go from there?
In reference to Freelancer, it pointed the guns at a point on the object that the mouse was over. It actually seems to have a collision mesh that would allow your mouse to slip "between the cracks" just a bit. It uses that, and apparently a far plane. I don't know the math of doing so but get the intersection point between each gun and the 2d-to-3d position of the mouse on the object the mouse is over, whether a mesh or the far plane. I think there is a mouse and mesh collision demo that comes with Irrlicht.
-
piot
for each gun on your ship you do the following...Anonymous wrote:What exactly do dot products do? That's the mathematical part where i screwed up: there are two guns on my ship. It's not the ship that needs to rotate, but the guns. They need to be aiming at the mouse cursor. Both guns are near the front of my ship, and i plan to rotate them simply by setRotation() cus their middle point is also the point they should be rotating about.
So after i find the vector of the mouse ray intersection with the plane, how do i go from there?
let's say you store the point of the intersection with the plane in "target" (or the ship you are aiming at, whatever..). and you store the position of your gun in "position". you also store the direction your gun is currently facing in "old". now you first caluclate the new direction vector of the gun (=facing to the target)
vector3df new = target - position;
now you have the "old" direction and the "new" direction. you now have to calculate the degree between the "old" and "new" vector..
Code: Select all
// calculate radians to degree (for the dot product)
#define RAD2DEG(x) ((x) * 57.295779513082320876798154814105f)
// first normalise both (important!)
old.normalise(); new.normalise();
f32 dot = new.dotProduct( old );
f32 angle = RAD_TO_DEG( acosf( dot ) );
Code: Select all
vector3df cross = new.crossProduct( old );
RotateMatrixAroundAxis( yourmatrix, cross, angle );
hope this helps...
-
Guest