Complicated aiming issue

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
Post Reply
Guest

Complicated aiming issue

Post by Guest »

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!
Guest

Post by Guest »

i seem to have posted twice.... sorry for that.
Guest

Post by 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)
Spintz
Posts: 1688
Joined: Thu Nov 04, 2004 3:25 pm

Post by Spintz »

Here's a function I found on forums, from Arras, it's added to IrrSpintz, it should help you a lot -

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;
}
Add this to vector3d.h and I also added a function to line3d to get the angle of the line -

Code: Select all

vector3d<T> getYXangle ( )
{
	vector3d<T> direction = end - start;
	return direction.getYZangle ( );
}
Image
Guest

Post by 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?
namik
Posts: 11
Joined: Thu Nov 03, 2005 8:12 pm
Contact:

Post by namik »

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

Post by piot »

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?
for each gun on your ship you do the following...

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 ) );
you now have the "angle" between the vectors. since you are coding a space game, you guns can face in any direction. so need another vector to rotate your gun around (this is called the orthogonal vector of "new" and "old", think of a plane that is defined by 2 vectors, the orthogonal vector would be perpendicular to that plane or the surface normal).

Code: Select all

vector3df cross = new.crossProduct( old );
RotateMatrixAroundAxis( yourmatrix, cross, angle );
the RotateMatrix.. function is not included in irrlicht, found nothing similar. try google (but rotating the matrix of your gun around an axis is much less work than rotating with euler angles (you have to calculate all three for each axis)).

hope this helps...
Guest

Post by Guest »

Thx alot, i will post once more to ask for a solution for rotating the gun around that axis.
Post Reply