DirectX/XNA Camera Problem

Started by
5 comments, last by jpetrie 16 years, 10 months ago
Hi, I'm a complete newbie to writing 3D games and I was curious, when setting up the camera to view a simple mesh on screen, why when I positioned the camera to look straight down from above the mesh, everything goes invisible. If I make even the *slightest angle* away from directly above the target position of the camera, then everything displays fine however. Is this what's meant to happen - if so could someone briefly explain why please. Otherwise, is there another way to make it visible even from a top-down perspective? Here's the important part of my code for setting up the camera: effect.World = transforms[mesh.ParentBone.Index] * Matrix.CreateRotationY(modelRotation) * Matrix.CreateTranslation(modelPosition); effect.View = Matrix.CreateLookAt(cameraPosOffset + cameraPosition, cameraPosition, Vector3.Up); effect.Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45.0f), aspectRatio, 1f, 1000.0f); Thanks in advance.
Advertisement
I'm not certain but it sounds like this would be caused by looking straight at the direction of your up vector.

If your up vector is 0,1,0 and you have your camera look at this position then you won't see anything. Try changing your up vector to 1,0,0 or 0,0,1 as a test with your camera looking straight at the model. If you see your model then you are definitely looking at the wrong direction with your camera. Change your orientation and you'll be set.

Otherwise, let us know and I'm sure you'll get some more assistance.

Webby
WebsiteWill's on the right track.

Construction of the viewing transformation matrix involves making an orthonormal basis -- two vectors are are required for this. In this case, one of those vectors (the camera's direction vector) is extracted from the specified camera location and target point. The second vector is the "up" vector, which can be chosen arbitrarily. The default is to choose the world space up vector, which is usually (0,1,0).

Recall that forming an orthonormal basis involves cross products, in particular, the first step is to compute the cross product of the two initial vectors. Recall also that the cross product of parallel vectors is undefined (in practice most vector library implements will return a zero vector). This renders the rest of the view matrix computation useless, since the result is going to be invalid.

There are many solutions. The most straightforward is to test if your direction vector is roughly the same as your proposed up vector, and if so select another arbitrary up vector (usually (1,0,0) or (0,0,1)).
Thank you both for your replies. To simplify my situation, it seems that I'm looking directly down with the camera, while the world up vector is defined as (0, 0, 1), so they would be parallel (but in opposite directions, which is irrelevant in this case). If I understand your explanation (jpetrie), then this means that the view matrix computation is thus going to be useless in my situation, as you thought. Does this mean I should permanently choose another vector for the world up vector (like (1,0,0) or (0,0,1) as you suggested), or even change the world up vector during the running of the game loop (might seem kind of strange, but I'm not familiar if it is a common work-around)? Well I'll have another play with it and hopefully everything should turn out fine.
Quote:
Does this mean I should permanently choose another vector for the world up vector (like (1,0,0) or (0,0,1) as you suggested), or even change the world up vector during the running of the game loop (might seem kind of strange, but I'm not familiar if it is a common work-around)?

You cannot permanently select a different up vector. If you choose (0,1,0) for up, the camera cannot look along a vector that is parallel to (0,1,0). If you choose (1,0,0), the camera cannot look along a vector that is parallel to (1,0,0). Et cetera. The brute force solution I was suggesting involves comparing the camera's direction vector and the camera's up vector prior to calling CreateLookAt() and changing the value of the vector for that particular call:
Vector3 direction = target - position;Vector3 up(0,1,0);if(direction.IsParallelTo(up))  up = Vector3(1,0,0);Matrix lookAt = Matrix.CreateLookAt(position,target,up);


That's all.

Another solution (and my preferred method) is not to bother at all with explicit direction vectors and have the camera object store a quaternion defining the orientation of the camera's local basis vectors in the world coordinate system. This method is slightly more involved, however.
Ok that clarifies matters. No clue what a quaternion is, since I really am a total newbie to the 3D side of game writing, but the rest is all clear and I'd rather not deal with that yet anyway. Now if I'm right, when I change the world up vector, I ought to change the *camera target* vector accordingly too.
Quote:
Now if I'm right, when I change the world up vector, I ought to change the *camera target* vector accordingly too.

Nope. Remember, you're changing the up vector's value because it is the same as the direction vector's value (or nearly so). The direction vector (formed from the position and target) is already correct, it's just the up vector you need to alter.

The up vector you supply to the function is not necessarily the actual up vector for the camera space basis. It does not necessarily actually dictate which direction is up... only which direction is "kindof up," since you can pass in values such that the direction vector and up vector are not perpendicular, and so the true up vector, computed by the second cross product in the orthonormal basis construction, will not be exactly the same as the up vector you passed.

This topic is closed to new replies.

Advertisement