Jump to content
  • Advertisement
Sign in to follow this  
Juxxec

3D 8 directional sprite rotation based on facing direction relative to camera direction

This topic is 825 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

Greetings everyone!

I am trying to create a simple DOOM clone. I got some 8 directional sprites, which I want to draw in 3D dimentional space. I have an enemy class which has a facing direction. I also have a player with a camera. I want for the sprite to choose the correct direction depending on its facing direction and relative to the camera's viewing direction. I.e if I start going around in circles around the sprite it should rotate as well.

I want to achieve the same thing as in this animated picture:
2DSpriteCloudGL.gif

This is what I have tried so far, but it doesn't work correctly all of the time. Only for certain angles.
// Inside the enemy classvec3 playerToSprite = this->position - player.position;vec3 direction = this->facing_direction - playerToSprite;angle = radtodeg(arctan2(direction.x, direction.y));if (angle > 90){    angle = 450 - angle;}else{    angle = 90 - angle;}// Choose the correct sprite. Sprites 0 is the East facing sprite, 1 is the NorthEast, 2 is North and it goes on clockwisethis->sprite = sprites[angle / 45];
Can you help me to fix my code?


EDIT: I managed to solve my problem. Here is the complete solution:
// Camera facing direction (in 2D)// Direction is the direction at which the camera is looking at ( in 2D )vec2 camera = vec2(            cos(degtorad(CCamera::GetMainCamera()->transform.direction)),            -sin(degtorad (CCamera::GetMainCamera()->transform.direction)));// Object facing direction (in 2D)// direction is the facing direction of the sprite, i.e. the direction at which the sprite is Looking At. ( in 2D )vec2 facing = vec2(           cos(degtorad(self->transform->direction)),            -sin(degtorad(self->transform->direction)));// Dot productdouble cosine = dot(camera, facing);double angle = radtodeg(arctan2(facing.y, facing.x) - arctan2(camera.y, camera.x));if (angle > 90.0){    angle = 450.0 - angle;}else{    angle = 90.0 - angle;}self->sprite = sprite_set[floor(angle / 45.0)];
Edited by frob
Do not mark discussions as 'solved', this is not a Q/A site.

Share this post


Link to post
Share on other sites
Advertisement

arctan parameter order is usually (y, x) -- not (x, y).

 

Apart from that, I'd suggest just printing out some debug values as you spin the camera to see what values you get and compare them to what you are expecting to get, noting/looking into cases where the two differ.

Share this post


Link to post
Share on other sites

That trick you're doing might not help you correctly.The issue is a problem of trigonometry and analytical geometry.

You have two objects to concern yourself with, the character and the camera.

Let's say that the camera is looking directly at the character. The character is facing to the west. The camera is facing north.

 

The issue with the method you're using is that you can not easily discriminate in the facing of the character or the camera. You can't know that for sure. So you reduce this to vector math.

Recall an axis aligned Unit Cube.

If you take the DOT product of the camera's facing vector, and the surface normal's of each face of the cubes, you can find out which of the six sides is facing the camera the most by using the largest positive value. If a result returns negative or zero, you can ignore it because it means that the normal is facing away from the camera or it's perpendicular.

 

When we solve this problem with the aforementioned example, the result we will get is that the south cube face is the side that's currently facing the camera. Because the character is facing left, we see his left side.

 

Now, lets extend this to the eight sided problem.

Build an axis aligned octagon with unit normals. You can compute this and hard code this later. Just start with a normal of (1,0,0), and rotate it around the Z axis by 45 degrees eight times.

 

When you run your tests, you can compute this against the eight sides.

 

Your character's facing will simply be a flag that determines which one of the sides he's facing, and then can be used to logically choose the right sprite depending on which normal is most present to the camera.

 

Hope this helps!

Edited by Tangletail

Share this post


Link to post
Share on other sites

I managed to solve my problem! I edited my original post with the solution. Thank you all for your support.

Share this post


Link to post
Share on other sites

tangent is rise over run or y/x(sin/cos), not x/y(cotangent). That is not your issue though. Your setup is arbitrary and finite. If I were at home, I would post my implementation. I will later tonight after work if an appropriate answer has not been given.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!