Sign in to follow this  

Angles between two spaceships (think Wing Commander) [ALMOST got it]

This topic is 2604 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm working on a 3d space shooter game like Wing Commander and the X-Wing series and I have quite some trouble with finding the angles between the player ship (ie. the camera) and another one.

In the most basic form, every ship has a position in space. For every ship, I have 17 (vertical angles) * 32 (horizontal angles) pre-rendered sprites. My goal is to calculate both these angles and use them to determine which of the sprites I need to use.

Of course, later on I want ships to have a direction as well, but let's keep it simple for now and just have them all face one way (0/0/-1) for example.

I tried some stuff with atan2 but it ended up only working in special cases, I don't really have the mathematical education at the moment to come up with my own algorithm. I basically have no idea where to start, I suspect there is some Matrix magic out there that can be used?

Does anybody have experience with this and could lend me a helping hand in trying to solve this?

Any feedback is extremely appreciated, as always. Thanks ahead of time!

[Edited by - d h k on October 24, 2010 3:37:57 PM]

Share this post


Link to post
Share on other sites
You know you are missing one angle of rotation, right? I am not sure what that thing you said about having them "all face one way (0/0/-1)" means.

I think I would represent the attitude of the ship as a quaternion, do the same thing with the attitudes for which you have sprites, and pick the sprite that fits best (the one that has the highest absolute value of dot product between quaternions).

Share this post


Link to post
Share on other sites
Quote:
Original post by alvaro
You know you are missing one angle of rotation, right? I am not sure what that thing you said about having them "all face one way (0/0/-1)" means.


Now I'm not sure what you mean. :D Do you mean I didn't mention rolling? Or that my atan2 approach misses an angle of rotation? If it's either of these two cases, then I'm well-aware of that. If not, please elaborate. With the all-facing-one-way I was just trying to simplify the situation by having all the other ships (apart from the "camera"/player ship) be static while in reality they all rotate around any axis as well of course.

Quote:
Original post by alvaro
I think I would represent the attitude of the ship as a quaternion, do the same thing with the attitudes for which you have sprites, and pick the sprite that fits best (the one that has the highest absolute value of dot product between quaternions).


Very interesting solution. Didn't even know there was such a thing as a dot product between quaternions but that would certainly work. I am a little concerned about performance however, considering I'd have to work with one quaternion per ship plus 544 (17 * 32 angles) static quaternions to test against. If I calculate the dot product of two quaternions 544 times for each ship in the scene every frame, wouldn't that nuke the speed?

Also, out of interest, any insight into how the old games did this? Probably not quaternions, right?

Share this post


Link to post
Share on other sites
First, take the matrix of your player and your enemy.
Invert your matrix, and multiply by the enemy matrix. This gets the enemy's matrix relative to you.

Then, take your resultant matrix and extract your yaw/pitch/roll from it to pick a sprite from your table by finding the one with the closest matching angles.

If you don't care about roll, you only have to transform the enemy's at vector by your inverse matrix. Then extract the yaw/pitch of just that vector.

Share this post


Link to post
Share on other sites
Here's another idea: If your unit quaternion is x*i + y*j + z*k + w, first of all w can be derived from the others, except for the sign. Since a quaternion and its opposite represent the same rotation, you can force w to be positive. Then quantize (x,y,z). For instance, using 10 different values for x, y and z you would need 1000 sprites.

I don't know how they did this in the old days, but I don't think it used to look too good, so I wouldn't try to reproduce it.

Share this post


Link to post
Share on other sites
Alright, trying it via matrices now. This is what I'm doing:


// GETTING ROTATION MATRIX FOR EVERY SPACESHIP AS WELL AS THE CAMERA
// (FROM DIRECTION VECTOR)

float yaw = atan2f ( direction.x, direction.y );
float pitch = atan2f ( direction.z, sqrt ( ( direction.x * direction.x ) + ( direction.y * direction.y ) ) );
// what about roll? ignore for now though

D3DXMatrixRotationYawPitchRoll ( &matrix, yaw, pitch, 0.0f );

// CALCULATING PROPER FRAME (OUT OF 32 HORIZONTAL AND 17 VERTICAL ONES)
// WHEN I DRAW A SPACESHIP

D3DXMATRIX inv_camera;
D3DXMatrixInverse ( &inv_camera, NULL, &camera.matrix );
D3DXMatrixMultiply ( &inv_camera, &inv_camera, &matrix );

float yaw = ( ( D3DXToDegree ( atan2f ( inv_camera._21, inv_camera._11 ) ) + 180.0f ) / 360.0f ) * 32.0f;
float pitch = ( ( D3DXToDegree ( atan2f ( -inv_camera._31, sqrt ( inv_camera._32 * inv_camera._32 + inv_camera._33 * inv_camera._33 ) ) ) + 180.0f ) / 360.0f ) * 17.0f;



Had to do a whole lot of looking up formulas so I'm not 100% certain they are even correct. This gives me very erratic frames, definitely not correct at all.

What am I doing wrong? Thanks ahead of time!

Share this post


Link to post
Share on other sites
If all you have is the direction vector, don't convert it to angles then make a rotation matrix.

Make a look-at matrix. If i recall directx has a function for that, but as I don't use directx, I'm not having luck with a google for it.
For the most part the algorithm is:

zaxis = normal(At)
xaxis = normal(cross(Up, zaxis))
yaxis = cross(zaxis, xaxis)

Where Up is a guess at the up vector of the object.

And like I mentioned, if you only need the yaw and pitch, just transform the direction vector directly. You don't need to create a matrix for the enemy.

Also, I don't think you are taking into account the quadrant of the calculation. You need to check if the transformed direction is facing away (normally positive Z) or towards you so that you can pick the right half of the frames. atan2f returns the same values for the front two and the back two quadrants.

Share this post


Link to post
Share on other sites
UPDATE / THREAD REVIVAL

Wow, I'm super sorry that it took me this long to answer. I realized that I first had to implement a 6dof-camera properly before going on. I did, hopefully learned a bunch by doing that, and am now back with the same problem.

For reference, I do absolutely need to do this for all three rotational degrees of freedom (ie. with roll). Don't think I clarified this properly before. Sorry. :D

My camera now actually stores a forward, left and up axis (vector) so these calculations should be easier. This is my current attempt:


// RIGHT BEFORE WE RENDER AN ENEMY

D3DXMATRIX camera_view, object_view;

D3DXMatrixLookAtLH ( &camera_view, &camera.position, &D3DXVECTOR3 ( camera.position.x + camera.forward_axis.x, camera.position.y + camera.forward_axis.y, camera.position.z + camera.forward_axis.z ), &camera.up_axis );
D3DXMatrixInverse ( &camera_view, NULL, &camera_view );

// my object/enemy is at 0/0/0 in world space, looking down the z-axis
D3DXMatrixLookAtLH ( &object_view, &D3DXVECTOR3 ( 0.0f, 0.0f, 0.0f ), &D3DXVECTOR3 ( 0.0f, 0.0f, -1.0f ), &D3DXVECTOR3 ( 0.0f, -1.0f, 0.0f ) );

D3DXMatrixMultiply ( &camera_view, &camera_view, &object_view );

float yaw = ( ( D3DXToDegree ( atan2f ( camera_view._21, camera_view._11 ) ) + 180.0f ) / 360.0f ) * 32.0f;
float pitch = ( ( D3DXToDegree ( atan2f ( -camera_view._31, sqrt ( camera_view._32 * camera_view._32 + camera_view._33 * camera_view._33 ) ) ) + 180.0f ) / 360.0f ) * 17.0f;





As you can see, I'm now using D3DXMatrixLookAt as you recommended, KulSeran.

I realize the quadrant issues I'm getting into with using atan2f but at the moment, the above code actually gives me seemingly random results. If I just walk around the ship in a circle (keeping my cam target at the ship), it starts rotating properly, then all of the sudden stops for a bit. Then jumps to a frame showing it from the floor and so on.

What could I still be doing wrong. Any feedback is appreciated. And I promise I won't "forget" this thread again for such a long time!

Share this post


Link to post
Share on other sites
I'm not sure how on-topic this post is, but alvaro's post made me start to think about what the best way to discretize rotations is; that's the subject of what follows...

(@ d h k : Sorry, this isn't really a reply to your most recent post. Hopefully someone will spot the bug though.)

Quote:
Original post by alvaro
I think I would represent the attitude of the ship as a quaternion, do the same thing with the attitudes for which you have sprites, and pick the sprite that fits best (the one that has the highest absolute value of dot product between quaternions).


Let me continue this line of thought for a second.

In n dimensions, the largest system of equiangular lines contains n(n+1)/2 lines. E.g., in 3d, you can have 3*4/2=6 equiangular lines (each line intersects the unit sphere twice; those 12 points are the vertices of a regular icosahedron).

The unit quaternions modulo antipodes is really the set of lines in R^4. So the largest system of equiangular rotations contains 4(4+1)/2=10 elements. I.e., 10 pairs of quaternions. These 20 quaternions are the direct 4d analogue of the 12 vertices of an icosahedron in 3d.

In the same way that one builds a geosphere by subdividing triangles starting with an icosahedron, it seems that one can likewise build a regular, as-close-to-equiangular-as-possible set of rotations by subdividing the tetrahedra that form the faces of the convex hull of these 20 vertices.

What one would need to figure out is which subsets of the vertices are the tetrahedra...

...

Another, more-easily-understood, and pretty good (if not as "perfect") method would simply be the 4d analogue of cubemaps.

There's a straightforward bijection between points on the sphere and points on the cube (for the cube-to-sphere direction, just normalize the points), which works in any dimension.

In 4d, the cube ("tesseract") has 2^4=16 faces, each of which is a 3d cube. Since quaternions are all modulo antipodes, we only really need half this number; we need 8 faces. Then, discretizing each face is easy as a 3d grid.

This isn't quite as good as the equiangular method, but seems reasonable.

...

I'm more interested in the equiangular method though. I may revise this post to expand on that.

[Edited by - Emergent on October 19, 2010 4:01:35 PM]

Share this post


Link to post
Share on other sites
Hi,

I can offer you another alternative. Not without its flaws but works good enough.
I used this on a J2ME game I was developing. Basically I had, in 2D, 24 frames
representing the rotation of objects.
Its the same kind of problem, discretization of possible rotations in order to
access a sprite, although here I only had 1 angle.

Basically, in 3D you can represent your orientation in several ways. People suggested quaternions, matrices and you can even use euler angles.

What I always considered simple is a direction vector (in 3D) and an angle of
rotation around that vector. Its easy to visualize (in your head) too.

A direction vector in 3D will be good for the following reasons:

1. You can easily determine the rotation angles (pitch/yaw) if given a vector.
2. If every ship has a direction vector, finding the relative vector between
them is trivial. Combined with 1 this gives you the relative angles between the
ships.


Now back to my game - I had only one angle but I'd divide it by the fixed factor
and get the frame number. If I had 24 frames for a given entity, the factor was
basically 15 degrees.

What you're left with is to know how to access your array of sprites correctly
based on the given angles and that's an easy problem of how you build the array.

I doubt you'll need more than that..

BTW, the code I implemented uses fixed point, not even floating point.

Share this post


Link to post
Share on other sites
Hi,

I forgot to add something -

You can update the direction vector rather easily, as you can rotate it by
any angle you wish using a matrix, or build it from a set of 2 angles (convert from spherical coordinates).

This solution is simple. It doesn't really have the generality of a quaternion
or orientation matrix. It doesn't really need to be integrated using a numerical
integrator such as Euler's or RK4.

Simple to visualize, simple to manipulate and update and good for your purpose, I believe.

Share this post


Link to post
Share on other sites
Hi,

I forgot to add something -

You can update the direction vector rather easily, as you can rotate it by
any angle you wish using a matrix, or build it from a set of 2 angles (convert from spherical coordinates).

This solution is simple. It doesn't really have the generality of a quaternion
or orientation matrix. It doesn't really need to be integrated using a numerical
integrator such as Euler's or RK4.

Simple to visualize, simple to manipulate and update and good for your purpose, I believe.

Share this post


Link to post
Share on other sites
Hi,

I forgot to add something -

You can update the direction vector rather easily, as you can rotate it by
any angle you wish using a matrix, or build it from a set of 2 angles (convert from spherical coordinates).

This solution is simple. It doesn't really have the generality of a quaternion
or orientation matrix. It doesn't really need to be integrated using a numerical
integrator such as Euler's or RK4.

Simple to visualize, simple to manipulate and update and good for your purpose, I believe.

Share this post


Link to post
Share on other sites
Okay, interesting. So let me, before I blindly rewrite my code, make sure I understood you correctly there. Let's also leave the roll out just for a second, I do need it in the end but I want to simplify this as much as possible first.

You suggest I simply store a direction vector for each object, basically a "forward axis" or a "normal" if you want. You say that:

Quote:
Original post by voguemaster
2. If every ship has a direction vector, finding the relative vector between
them is trivial.


Now this is what I'd like clarification on - how would I go about getting that relative vector between two direction vectors and then extracting pitch/yaw from these (the latter one I'm confident I can pull off myself with some basic research, the first one stumbles me).

Thanks a ton for the help so far. I really hope I can get this working.

Share this post


Link to post
Share on other sites
Ok,

If I understand your problem correctly, the player's eye point (the camera) is basically in the cockpit, right ? Just like in X-Wing (although that game had an outside view, it was a chase camera so its not that much different).

So, the relative angle between the player's ship and the enemy will determine which frame you're using, right ?

So, given the system I suggested, finding the relative angle between them is done by finding the relative vector (which is just substraction) and then converting to angles.

Once you have the angles (spherical coordinates, remember that), you basically divide each with the factor I mentions earlier (36 possible directions for example means a factor of 10), in order to get the index into the array.

Since your array is a 2D array, you have two indices from the two angles.

You just need to build the array in a convention that matches the result of the calculation.

Share this post


Link to post
Share on other sites
You're absolutely right. Your solution sounds extremely easy. I just gave it a try but the end result is still rather random-looking. From time to time it'll actually look right but then I move the camera some more and it just throws the enemy ship around, turn it full 180 degrees or something. That's certainly not all that's wrong though, from some angles it has yaw and pitch mixed up (moving the camera left makes the ship angle go lower vertically for example), while from other angles the directions are correct.

This is my code, as always, right before rendering an enemy ship when determining which textures from the 2D array of textures to use, ie. which pre-rendered angle perspective:


// calculating the relative vector, I did try flipping this as well
// direction is the forward vector of this particular enemy ship
D3DXVECTOR3 v_rel = direction - camera.forward_axis;

// extracting yaw and pitch (in radians) from that relative vector
float yaw = atan2f ( v_rel.x, v_rel.y );
float pitch = atan2f ( v_rel.z, sqrtf ( ( v_rel.x * v_rel.x ) + ( v_rel.y * v_rel.y ) ) );

// converting so that we now have yaw and pitch values from ranges 0-32 and 0-17 respectively (instead of 0-360)
yaw = ( ( D3DXToDegree ( yaw ) + 180.0f ) / 360.0f ) * 32.0f;
pitch = ( ( D3DXToDegree ( pitch ) + 180.0f ) / 360.0f ) * 17.0f;

// determining the texture from the 2D array to use based on yaw and pitch
sprite_slot = ( int ) ( pitch - 1 ) * 32 + ( int ) yaw;




Am I still doing something wrong? Or is this definitely right and the error has to be in my direction vectors for camera and ship (I'm very, very sure these are correct tho).

Thanks a TON for your help, rating++!

I *hope* I can get this to work, would be soooo important for this project of mine. :D

Share this post


Link to post
Share on other sites
Hi,

A few things to consider with this calculation I'm not sure you're aware of:

1. If you're using the CRT version of the atan2 function (atan2f) which I think you are, then the Y component is the first argument to the function, not X.

2. The result given by atan2f returns the arc-tangent but the signs determine the quadrant. For simplicity's sake, if I draw from my own example then:

I have 24 frames in my sprite "sheet", indices are [0..23]
I have a direction vector (x,y).
I convert it with atan2(y,x). Note that if y>0, the angle will be positive. If y<0, the angle will be negative. Now, I worked with a convention that angle 0 is aligned with the positive X-axis, while 180 is negative X-axis (basically the unit circle).
This means that I had to negate the Y component before passing it to atan2, otherwise I'm not working in the convention of the function.

Now, since the angle can turn out negative, I did something simple like this to revert back to my convention:

angle = (angle >= 0) ? angle : angle+360;

(this was done is fixed point but that's the basic idea).

Once I had the angle in "my" convention, it was trivial.


So the moral is -

1. Check your signs.
2. Check the calculation with simple inputs. For example, player's direction is 0,0,1 or something simple and the enemy's direction something like 1,1,1.
Try various inputs to make sure you're going through the calculation properly.

Share this post


Link to post
Share on other sites
Okay, makes sense. I did follow your sign-checking advice and flipped the parameters for atan2f to follow the y/x order. That didn't change anything from tho looks of it though. I also realized that, since the result wasn't just wrong in one sense (ie. right frames but in the wrong orientation or whatever) but rather totally unpredictable, I'd go ahead and hard-code direction vectors to check the math.

What do you know, there is a problem somewhere. I want to get only yaw to work first, so the pitch is hard-coded to be 180 (ie. neutral to the camera).


D3DXVECTOR3 t1 ( 0.0f, 0.0f, -1.0f ), t2 ( 0.0f, 0.0f, 1.0f );
D3DXVECTOR3 v_rel = t1 - t2;

float yaw = atan2f ( -v_rel.y, v_rel.x );
float pitch = 180.0f;

yaw = D3DXToDegree ( yaw );
yaw = ( yaw >= 0.0f ) ? yaw : yaw + 360.0f;

// DEBUG OUTPUT OF YAW AND PITCH HERE

yaw = ( yaw / 360.0f ) * 32.0f;
pitch = ( pitch / 360.0f ) * 17.0f;
sprite_slot = ( int ) ( pitch - 1.0f ) * 32 + ( int ) yaw;



These are the different yaw values I get for hard-coded direction vectors:


t2 yaw
-1/0/0 0
1/0/0 180
0/0/-1 0
0/0/1 0

(t1 is 0/0/-1 throughout)


Clearly, there is something very wrong here. I'm absolutely out of ideas - can this be a problem of signs anymore even? If so, what am I doing wrong?

Thanks again.

Share this post


Link to post
Share on other sites
That output looks correct to me for the given input. It's not immediately clear to me though how your algorithm is intended to work, so I can't offer much beyond that in the way of specific comments.

I don't have a lot of experience with games that use this particular technique, but it seems to me that if all the ships involved are capable of full 6DOF motion, a lot of sprites would be required in order to represent all the possible relative orientations suitably. Did other games that used this technique impose some additional constraints to cut down on the number of sprites required?

If you really do need to represent all possible relative orientations (quantized, of course), then it seems a quaternion-based solution (as discussed previously) might be more suitable. The relative orientation between the viewer and the object in question can easily be computed, at which point it becomes a matter of choosing the sprite that most closely matches the resulting orientation quaternion. I imagine you can do better than a brute-force search for this; although I only skimmed the post, it seems something like what Emergent was describing might be appropriate.

This is probably similar to what Emergent was talking about, but you can 'compress' a quaternion into 3-d vector form by negating it if the value of w is negative, and then dropping the w component. This leaves you with a 3-d vector with length in the range [0, 1].

You can think of this vector as a vector (i.e. with direction and length), or as a point that falls somewhere in the unit sphere. Conceptually, we want to discretize the interior of a unit sphere and assign a sprite to each 'cell'.

One way to approach this might be to break it into two steps. First, if the input vector does not represent identity (or close to it), intersect a ray with direction parallel to the input vector with the surface of the sphere, and identify the 'cell' in which the intersection point falls. This requires discretizing the surface of the sphere somehow, but we'll set that problem aside for now.

Each cell on the sphere surface corresponds to a subset of the set of sprites; a specific sprite from this subset is then chosen based on the length of the vector.

Another approach might be simply to use a 3-d grid of cells. Finding the cell corresponding to the input orientation would then be O(1), so there would be no concerns with respect to performance.

This is all speculative of course, and I may be overlooking something or other, but given the problem description, what I'd probably try first would be:

- Use a regular 3-d grid (subdivision of the unit cube) to represent the possible orientations, with those cells that fall within the unit circle corresponding to orientations in compressed quaternion form.
- Generate the sprite for each cell procedurally somehow (presumably you're using a modeling program of some sort to generate the sprites).
- To render the correct sprite, compute the relative orientation between the viewer and the object in question in quaternion form, compress the quaternion, and then find the cell in the 'sprite grid' in which the resulting point falls.

Again though, all completely speculative.

Share this post


Link to post
Share on other sites
Thanks first of all. Let me go through your post step-by-step...

Quote:
Original post by jyk
That output looks correct to me for the given input. It's not immediately clear to me though how your algorithm is intended to work, so I can't offer much beyond that in the way of specific comments.


I'm trying to follow voguemaster's advice - leaving roll out of the equation for the moment - and extracting pitch and yaw angles from a vector. In the latest code segment I posted, I also left the pitch calculation out so I was really expecting to get yaw values between 0-360 from the vector. In a game like Wolfenstein you'd do the same to draw sprites that aren't billboards. With my camera direction being fixed for the moment at 0/0/-1 I'd have expected a yaw of 0 for 0/0/-1 enemy ship direction, 90 for 1/0/0, 180 for 0/0/1 and 270 for -1/0/0. Or something similar.

Quote:
Original post by jyk
I don't have a lot of experience with games that use this particular technique, but it seems to me that if all the ships involved are capable of full 6DOF motion, a lot of sprites would be required in order to represent all the possible relative orientations suitably. Did other games that used this technique impose some additional constraints to cut down on the number of sprites required?


Well, other ships don't need full 6DOF if it isn't possible (without rendering a buttload of additional frames) - just 6DOF for the camera would be fine. So far I have 32x17 (ie. 544) frames per ship for every angle (32 yaws and 17 pitches - 17 so that there is a neutral pitch in the middle). Obviously it would not be an option to add, say, 24 roll angles in there. It already takes a while to load 544 textures per ship class into RAM.

My plan was to do it without roll first and then hoping I could figure a way out where I rotate the actual Direct3D billboard quad that I use to render a ship. Then also shift the texture index somehow as well of course.

FOR REFERENCE: I'm actually willing to leave roll completely out of the picture. I'd be satisfied if I got the right frame for any yaw/pitch combination only.

In regards to the rest of your post, jyk, that was sort of what I was afraid of. Do you think, with the additional information I gave above and no roll, it would be possible to pull this off as voguemaster suggested.

Share this post


Link to post
Share on other sites
Quote:
Do you think, with the additional information I gave above and no roll, it would be possible to pull this off as voguemaster suggested.
I don't know. It seems to me that even if only the player is allowed full 6DOF motion, you'll still need to represent every possible orientation (quantized) for the other ships (because if the player is allowed full 6DOF motion, the player will be able to view the other ships from any angle).

I imagine you're doing things this way for a reason, but at the risk of asking an obvious question, why not simply use 3-d models? It would be far easier overall, I think. If it's just the visual effect you're after, you could even render the models to texture in real time at low resolution, and then render quads using the generated textures using point sampling.

But as for your question, I'm really not sure off the top of my head how what you're describing would be done using spherical or Euler angles. Maybe someone else will be able to offer a better suggestion, but for a fully 6DOF sprite-based simulation, it seems to me that something like what Emergent or I described earlier would be your best bet. (Assuming the grid-based method I proposed would actually work, I think it might not be quite as hard to implement as it might sound; the hardest part, I think, would be auto-generating the requisite sprites.)

[Edit: I didn't really address the 'no roll' idea in the above, so it may not be entirely relevant.]

Share this post


Link to post
Share on other sites
Here's another idea (I haven't read the entire thread carefully, so this may be no more than a repeat of what's already been discussed).

If you just want to pick one of your 544 sprites based on the relative orientation of the two ships, I'd think the way to proceed would be to transform the forward direction vector of the other ship into the player ship's local space, convert this vector to spherical coordinates, and choose a sprite accordingly. (I don't think this is what you're doing currently - I got the impression that you're subtracting one direction vector from another, but I'm not sure how useful that is.)

So there are basically three steps:

1. Transform the other ship's forward direction vector into the player ship's local space.

2. Perform a Cartesian-to-spherical-coordinate conversion.

3. Compute the sprite index from the spherical coordinates.

Share this post


Link to post
Share on other sites
Quote:
Original post by jyk
So there are basically three steps:

1. Transform the other ship's forward direction vector into the player ship's local space.

2. Perform a Cartesian-to-spherical-coordinate conversion.

3. Compute the sprite index from the spherical coordinates.


That's exactly the plan. Awesome, thanks a ton.

Now, for the first step, is it correct to retrieve a view matrix for the camera (using D3DXMatrixLookAtLH) and multiply the ship's forward direction vector by that to bring it into the player's local space (view space as it may be called). Or do i need to multiply by the inverse of the camera view matrix? Always get this wrong and I can never seem to find a good place to look these things up.

EDIT: In any case, this is my current attempt based on your approach, jyk:


D3DXMATRIX camera_view;

// retrieve the inverse of the camera matrix (also tried without inverting)
D3DXMatrixLookAtLH ( &camera_view, &camera.position, &D3DXVECTOR3 ( camera.position.x + camera.forward_axis.x, camera.position.y + camera.forward_axis.y, camera.position.z + camera.forward_axis.z ), &camera.up_axis );
D3DXMatrixInverse ( &camera_view, NULL, &camera_view );

// and multiply this ship's direction vector with that
D3DXVECTOR4 tmp;
D3DXVec3Transform ( &tmp, &direction, &camera_view );

// calculate rho and s as helpers, then phi and theta (referred to as yaw and pitch)
float rho = sqrtf ( tmp.x * tmp.x + tmp.y * tmp.y + tmp.z * tmp.z );
float yaw = acosf ( tmp.z / rho );
float s = sqrtf ( tmp.x * tmp.x + tmp.y * tmp.y );
float pitch;

if ( tmp.x < 0 )
pitch = D3DX_PI - asinf ( tmp.y / s );
else
pitch = asinf ( tmp.y / s );

yaw = D3DXToDegree ( yaw );
pitch = D3DXToDegree ( pitch );






Now, when I check the values of yaw and pitch here, they always seem to end up being "-1.#IND". I played around with a couple of things but to no avail (ie. no conversion to degrees, no inverting the camera matrix). Any further info?

Reading up on #IND, apparently that signifies a divide by zero? Not sure how this can happen/what to do against it.

[Edited by - d h k on October 24, 2010 4:37:21 PM]

Share this post


Link to post
Share on other sites
Quote:
Now, for the first step, is it correct to retrieve a view matrix for the camera (using D3DXMatrixLookAtLH) and multiply the ship's forward direction vector by that to bring it into the player's local space (view space as it may be called).
Yes, that should work.
Quote:
Or do i need to multiply by the inverse of the camera view matrix?
No, the inverse of the view matrix would just be the model ('forward') matrix for the player ship; it's the inverse (view) transform that you want.
Quote:
*** Source Snippet Removed ***

Now, when I check the values of yaw and pitch here, they always seem to end up being "-1.#IND". I played around with a couple of things but to no avail (ie. no conversion to degrees, no inverting the camera matrix). Any further info?

Reading up on #IND, apparently that signifies a divide by zero? Not sure how this can happen/what to do against it.
You're inverting the (already inverted) view matrix in that code, so you'll want to take that out. As for the spherical coordinate conversion code, I didn't proof it, but I would recommend using atan2() rather than asin()/acos() so that you won't have to worry (as much) about invalid input due to numerical error.

Beyond that, I'd recommend stepping through the code in the debugger and seeing if you can determine where things are going wrong. First, make sure the matrix itself is valid. If it is, try to determine which of the operations is producing invalid results, and why.

Share this post


Link to post
Share on other sites
Hi guys, sorry for the late response.

It seems I made a mistake. You do need to transform the enemy's direction vector into the player's coord system. Finding the relative vector is something completely different and I probably got confused with something else.

That's where you always have to ask yourself - in what coordinate system am I working ?

Other than what jyk pointed out I don't know how else we can help you. Like I said, try simple inputs and check the calculations..

Again, sorry for the mistake, must be the time...

Share this post


Link to post
Share on other sites

This topic is 2604 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this