Direct3D 9 and 360 degrees

Started by
31 comments, last by theo2005 12 years ago
Add MoveX and MoveY to LookAtX and LookAtY. As it stands you're positioned a ways away from the world origin and looking at a point that revolves around the origin.

Try this thought experiment: draw a circle on the floor. Now stand 10 feet away, and watch an ant walk around the circle. The effect should resemble what you're seeing in your code.

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]

Advertisement

Add MoveX and MoveY to LookAtX and LookAtY. As it stands you're positioned a ways away from the world origin and looking at a point that revolves around the origin.

Try this thought experiment: draw a circle on the floor. Now stand 10 feet away, and watch an ant walk around the circle. The effect should resemble what you're seeing in your code.


Wow, that actually fixed the movement problem that I didn't even mention here. But the mouse problem -- it goes back and forth when I turn away from the object. If I turn left, it will go left and after a certain point it will start going back until it reaches that certain point on the right side. So it keeps going like this:


oooooooXoooooooo
<--------------------->o
oooooooooooooooo

X being the object and the line the point where the camera looks at. The point is that it will never see the X that would be on the other side of the line, let alone make a 360 turn and see the object first from the other side.
('o' dont have any meaning here, I couldn't get the X to be in the middle)
Can you post your current code? I have a feeling I miscommunicated the correct fix for the problem.

Anyways, you really should do my thought experiment. I think it'll help you understand what you're seeing.

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]


D3DXMATRIX matView; // the view transform matrix


static float horizontal_angle = 0.0f; horizontal_angle -= mousestate.lX * 0.075f;
static float vertical_angle = 0.0f; vertical_angle -= mousestate.lY * 0.075f;
static float LookX = 0.0f; LookX = sin(horizontal_angle) * 20.0f;
static float LookY = 0.0f; LookY = cos(vertical_angle) * 20.0f;
/*static float LookX = 0.0f; LookX -= mousestate.lX * 0.003f;
static float LookY = 0.0f; LookY -= mousestate.lY * 0.003f; */
static float MoveX = 0.0f;
static float MoveY = 0.0f;
LookX += MoveX;
LookY += MoveY;
if(keystate[DIK_A] & 0x80)
{
MoveX += 0.3f;
//LookX += MoveX;
}
if(keystate[DIK_D] & 0x80)
{
MoveX -= 0.3f;
//LookX -= MoveX;
}
if(keystate[DIK_S] & 0x80)
{
MoveY += 0.3f;
//LookY += MoveY;
}
if(keystate[DIK_W] & 0x80)
{
MoveY -= 0.3f;
//LookY -= MoveY;
}
D3DXMatrixLookAtLH(&matView,
&D3DXVECTOR3 (MoveX, MoveY, 15.0f), // the camera position
&D3DXVECTOR3 (LookX, LookY, 0.0f), // the look-at position
&D3DXVECTOR3 (0.0f, 1.0f, 0.0f)); // the up direction
d3ddev->SetTransform(D3DTS_VIEW, &matView); // set the view transform to matView


Oh, I think I finally understood what you meant by the ant.

I need the camera to look around and along the circle, is that what you meant?
It came to me because I was looking at how other people were making the camera move.
I'm supposed to rotate the axes or something along those lines? (instead of making the camera look left or right)
But that wouldn't work either if the object is indeed the center of the world. It would just make the object rotate.
So if I had to guess, then perhaps I need a way to make the camera be in the center of the world instead.
But even so.. some calculations would probably be off the moment I move from there..
OK, I see what's going on.

You're never changing the Z coordinate of your look-at position, meaning that you never move in the horizontal plane. You just slide the X coordinate back and forth along a sinusoidal curve.

The formula should look like this:

LookAtX = MovePositionX + sin(horizontal_angle);
LookAtZ = MovePositionZ + cos(horizontal_angle);

Get horizontal movement working first, and then we can complicate things by throwing in the additional rotation to do vertical movement :-)

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]


D3DXMATRIX matView; // the view transform matrix

static float MouseSpeed = 0.0075f;

if (keystate[DIK_F1])
{
MouseSpeed += 0.0001f;
}
else if (keystate[DIK_F2])
{
if (MouseSpeed > 0.0001f)
{
MouseSpeed -= 0.0001f;
}
}
static float horizontal_angle = 0.0f; horizontal_angle += mousestate.lX * MouseSpeed;
static float vertical_angle = 0.0f; vertical_angle += mousestate.lY * MouseSpeed;

static float LookX = 0.0f; LookX = (sin(horizontal_angle) * 20.0f);
static float LookY = 0.0f; LookY = (cos(vertical_angle) * 20.0f) - 20.0f;
static float LookZ = 0.0f;

static float MoveX = 0.0f;
static float MoveY = 0.0f;
static float MoveZ = 0.0f;
if(keystate[DIK_A] & 0x80)
{
MoveX -= 0.3f;
}
if(keystate[DIK_D] & 0x80)
{
MoveX += 0.3f;
}
if(keystate[DIK_S] & 0x80)
{
MoveY -= 0.3f;
}
if(keystate[DIK_W] & 0x80)
{
MoveY += 0.3f;
}
//in order for the camera to keep looking in the same direction
LookX += MoveX;
LookY += MoveY;
LookZ = MoveZ + (cos(horizontal_angle) * 20.0f); //this one has something to do with turning around 360*
D3DXMatrixLookAtLH(&matView,
&D3DXVECTOR3 (MoveX, MoveY, MoveZ), // the camera position
&D3DXVECTOR3 (LookX, LookY, LookZ), // the look-at position
&D3DXVECTOR3 (0.0f, 1.0f, 0.0f)); // the up direction
d3ddev->SetTransform(D3DTS_VIEW, &matView); // set the view transform to matView


So there it is, I did not believe it, but the horizontal movement works now.

I also tried to get vertical movement to work INSTEAD, and it did work, but after moving away from the object,
I noticed that what it did was move like around the orbit...

In any case, how to get vertical movement to work as well?

I still don't understand what the Z coordinates do in terms of the camera.
At first I thought that it's like zoom in or zoom out, but that's not it.
X and Y points at where the camera should look, but Z never seemed to do anything,
except in terms of moving in and out.

Oh and..

LookY = (cos(vertical_angle) * 20.0f) - 20.0f;


For some reason, the camera looked down in terms of the object, so I had to substract 20.0f for it to look perfectly at the object. Why is that?
The object is positioned at:


D3DXMatrixTranslation(&matTranslateA, 0.0f, 0.0f, 15.0f); //15.0f away from the camera
I would strongly suggest you get a refresher in basic 3-space Cartesian geometry. This is pretty elementary mathematics and you'll need a very solid grasp of it to do 3D graphics programming.

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]


I would strongly suggest you get a refresher in basic 3-space Cartesian geometry. This is pretty elementary mathematics and you'll need a very solid grasp of it to do 3D graphics programming.


I'm really sorry, but I, nor anybody else in my class (or even the next class) has learned 3D Cartesian geometry/analytic geometry.
Everything we have been doing so far is only 2D (with the exception of formulas for cubes and pyramids).

It seems like the kind of stuff you learn in the university.

If you are only willing to share formulas (which will help me temporarily) without an explanation (and I'm not expecting to get a math course from you or anybody else on this forum), then I suppose I have no choice but to bother the physics teacher at my school (again).

I actually tried to explain my problem to the math teacher (without getting into the programming), but she just redirected me to the physics teacher, who needed more information to help me anyway.
You can get the basic formulas from here, or general Google searches for "3D Euler angle rotations." It should help you get started even if you don't have the foundations in the maths yet.

By the way, I have to say it's impressive that you're willing to forge ahead with this and learn on your own ahead of the "normal pace." Good on ya, and keep it up.

Good luck :-)

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]

I'm really sorry, but I, nor anybody else in my class (or even the next class) has learned 3D Cartesian geometry/analytic geometry.
Everything we have been doing so far is only 2D (with the exception of formulas for cubes and pyramids).[/quote]
But if you don't know anything about 3D geometry how do you expect to understand 3D matrix transformations/projections, sense of ordinary space, all that stuff? Not that I'm saying it's impossible but it will be difficult without a knowledge of the basics. Otherwise magic constants (such as the 20's in your code) start appearing and you have no idea why.

Anyway. The D3DXMatrixLookAtLH function takes as an input a 3D coordinate which specifies the location (in "world" space) of the camera, and a 3D coordinate which specifies the location of the target (thus the direction in which the camera is looking can be obtained by a subtraction). The third parameter is the up vector but it can be kept to (0, 1, 0) until you want to perform "roll" rotation (i.e. rotation along the Z axis).

In your code the camera's target is derived from the mouse position in an incorrect manner. What happens is that your camera's target (what the camera is looking at) is rotating along a non-obvious curve centered on the origin (because you messed up with the angle calculation). I suspect you want the camera target to rotate in a graceful curve as you move the mouse around (like a spherical magnet would slide all around another). [color=#ff0000]You need to use spherical coordinates for this, (this is why you need to know 3D geometry) which map two angles and a radius onto a sphere's surface. The formulas are not obvious to the beginner but work (more on wikipedia):

For a horizontal angle Phi and a vertical angle Theta (both in radians), and a radius R, the corresponding point on the sphere (centered on the origin, translate if needed):

X = R * cos(Phi) * sin(Theta)
Y = R * Sin(Theta)
Z = R * sin(Phi) * Sin(Theta)

(assuming the Y axis goes upwards).

Now if you put this in your code, instead of the "ant around a circle" result Apoch described earlier, you will get an "ant around a sphere" result. Now if you add MoveX to LookX and MoveY to LookY and MoveZ to LookZ, then you will have translated the rotation center onto the camera's position, which means you will be able to look around in every direction by moving the mouse around (like in FPS shooters, for instance). Finally, the radius of the rotation does not matter because it will not change the direction the camera is facing (in the LookAt function, the direction ends up being normalized, so any scaling factor is cancelled out).

As for the the magic constant in the code which "sorta kinda worked", I suspect it simply happened to reduce the visible error to a minimum (while still being completely wrong).

So the final correct code would be:


LookX = cos(angleX) * sin(angleY)
LookY = Sin(angleY)
LookZ = sin(angleX) * Sin(angleY)

MoveX, MoveY, MoveZ as usual (keyboard is used to move around)


And:

D3DXMatrixLookAtLH(&matView,
&D3DXVECTOR3 (MoveX, MoveY, MoveZ), // the camera position
&D3DXVECTOR3 (LookX + MoveX, LookY + MoveY, LookZ + MoveZ), // the look-at position
&D3DXVECTOR3 (0.0f, 1.0f, 0.0f)); // the up direction


And there you have it, you reinvented camera rotation in its simplest form. With this code you should be able to use the keyboard to move around the world, and use the mouse to naturally look around (which is what you wanted, right?)

Also, make sure you put bounds on the Theta (angleY) angle so that the camera cannot "flip vertically" because then everything will be inverted. In real life this would correspond to looking forward, then looking upwards, until you bend your neck backwards (and same for looking downwards), which results in an extremely unintuitive sense of direction, so for player sanity we usually ensure -pi/2 < angleY < pi/2, although this may depend on the API (conventions and stuff). But that's just a minor detail.

-------------------

I may have made mistakes in the post above, but I think this is what you were looking for. If not, then I did not understand your problem so if it is so can you reformulate it in the simplest way possible (what do you want to achieve?)

“If I understand the standard right it is legal and safe to do this but the resulting value could be anything.”

This topic is closed to new replies.

Advertisement