2.2 target problems of the specified camera
When defining the view matrix, You need to specify the target vector as the parameter, which sets the rotation of the camera.
Solution
When the camera is selected, the camera position remains unchanged. This means that the rotation depends on the change of the target point and up vector of the camera. You can use (,-1) Forward vector and apply the rotation to this vector to obtain the target vector, which generates a new target point. You can use the same method to obtain the up vector.
Working Principle
As shown in tutorial 2-1, a camera requires position, target, and up vectors to be uniquely identified. If you want the camera to rotate around a certain point, the position vector remains unchanged, but both the target and up vectors will change.
Given the rotation angle around the three axes, one method is to process the target position, but this will lead to complicated operations, and a clearer and faster method.
The simplest example: the camera is centered around the up vector at the initial position.
Rotation Let's first look at the initial coordinates of the camera at (0, 0, 0. It observes (0, 0,-1) Forward and uses the default (0, 1, 0) up vector as the upward direction. In this case, you can use the followingCode:
Vector3 cameraposition = new vector3 (0, 0, 0); vector3 cameratarget = new vector3 (0, 0,-1); vector3 cameraupvector = new vector3 (0, 1, 0 ); viewmatrix = matrix. createlookat (cameraposition, cameratarget, cameraupvector );
For example, you want to create a view matrix with 45 degrees of rotation around the up vector. If your head is the camera, this will make the head rotate 45 degrees to the right. When calculating the new view matrix, the position and up vectors remain unchanged, but you need to obtain the new target vector. You can get the new target vector by rotating the "Conversion" default (0, 0,-1) target vector with 45 degrees. This means that the vector you get is the rotation version of the initial target vector. The following code is used:
Matrix camerarotation = matrix. createrotationy (mathhelper. piover4); vector3 cameraposition = new vector3 (0, 0, 0); vector3 cameraupvector = new vector3 (0, 1, 0); vector3 cameraoriginaltarget = new vector3 (0, 0, -1); vector3 camerarotatedtarget = vector3.transform (cameraoriginaltarget, camerarotation); viewmatrix = matrix. createlookat (cameraposition, camerarotatedtarget, cameraupvector );
Note:A matrix is a powerful tool for expressing certain transformations. A matrix can represent rotation, translation, scaling, or a combination of these transformations. You can get more examples in tutorial 4-2.
The first line of code creates a matrix that represents 45 degrees of rotation around the Up axis, corresponding to PI/4 radian. The following code uses this rotation matrix to convert the initial (0, 0,-1) target vector and stores the rotated target vector in the camerarotatedtarget variable. This variable is used to create a new view matrix.
Note:This transformation is not mysterious; it is the product of a vector and a matrix. It simply performs 16 multiplication and 12 addition.
Example 2: Arbitrary Rotation of the camera at the initial position
Now let's look at a complicated example. You want the camera to rotate around any axis instead of the UP vector. For example, if you rotate 45 degrees around the (, 0) right axis, if your head is a camera, this will lead to an oblique 45-degree observation.
Because you only rotate the camera, the position vector remains unchanged. As in the previous example, the target vector changes because the camera needs to observe a different position.
However, in this case, the up vector also changes. In the previous example, you turn the header to the right, and the up vector does not change. In this example, the header is rotated up, and both the up vector and the target vector are changed.
The same method is used to transform up vectors and forward vectors: you store the rotation in a matrix and define the initial up vector. Then, use the rotation matrix to transform the initial vector to obtain the new up vector. The following code is used:
Matrix camerarotation = matrix. createrotationx (mathhelper. piover4); vector3 cameraposition = new vector3 (0, 0, 0); vector3 forward = new vector3 (0, 1, 0); vector3 cameraoriginaltarget = new vector3 (0, 0, -1); vector3 camerarotatedtarget = vector3.transform (cameraoriginaltarget, camerarotation); vector3 transform = vector3.transform (cameraoriginalupvector, camerarotation); viewmatrix = matrix. createlookat (cameraposition, camerarotatedtarget, camerarotatedupvector );
Here, the "arbitrary" rotation matrix is just a simple rotation around the X axis. This code can also handle any rotation. For example, in the following case, it combines the rotation on the three axes. The following code generates a matrix, which is a combination of degrees-45 degrees and 22.5 degrees on the Y axis and 90 degrees on the X axis:
Matrix camerarotation = matrix. createrotationx (mathhelper. piover2) * matrix. createrotationy (mathhelper. PI/8.0f) * matrix. createrotationz (-mathhelper. piover4 );
When a new forward vector and up vector are obtained, the camera position remains unchanged.
Example 3: The camera rotates at any position
In most cases, you want to set any rotation and specify the camera position. For example, the camera is in the position (10, 20, 30) and does not rotate. Very simple. The position vector of the camera is (10, 20, 30 ). Because there is no rotation, the camera observes (0, 0,-1) Forward Direction.
Note:Remember to specify the target instead of the target direction! It is wrong to use (,-1) as the target vector, because it will let the camera observe the point (,-1 ). For example, if you move the camera to a point (-10, 20, 30), if you still specify (,-1) as the target vector, the camera will still observe the point (,-1 ), the orientation of this camera will change!
To make the (, 30) camera orientation (,-1), you need to specify (, 29) as the target vector. You can obtain this vector by finding the camera position and target direction:
Vector3 cameraposition = new vector3 (10, 20, 30); vector3 cameraoriginaltarget = new vector3 (0, 0,-1); cameratargetpoint = cameraposition + cameraoriginaltarget;
Now, you can combine what you have learned. You will define a camera at (10, 20, 30) and can rotate it at will. Position vector (10, 20, 30) unchanged. The target vector is first defined as (0, 0,-1. To get the forward direction after rotation, you need to use the rotation matrix to transform it. Finally, you need to add (, 30) the target vector to the orientation of the camera (10, 20, 30 ). The up vector is obtained in the same way. The following is the final code:
Matrix camerarotation = matrix. createrotationx (mathhelper. piover2) * matrix. createrotationy (mathhelper. PI/8.0f) * matrix. createrotationz (-mathhelper. piover4); vector3 cameraposition = new vector3 (10, 20, 30); vector3 cameraoriginaltarget = new vector3 (0, 0,-1); vector3 forward = new vector3 (0, 1, 0); vector3 transform = vector3.transform (transform, camerarotation); vector3 transform = cameraposition + transform; vector3 transform = vector3.transform (transform, camerarotation); vector3 transform = cameraposition + transform; viewmatrix = matrix. createlookat (cameraposition, camerafinaltarget, camerafinalupvector );
Move the front, back, and left of the rotated camera
Now you have achieved the camera at the specified position and orientation in the correct direction. The new challenge is to move the camera before and after. If you want to move the camera forward, simply adding the (0, 0,-1) Forward vector to the position vector will not succeed, because you need to first obtain the forward vector of the corresponding rotating camera. You have used the rotation matrix transformation (0, 0,-1) Forward vector in the first example in this tutorial. With this transformed forward vector, to add it to the position vector:
Float movespeed = 0.5f; vector3 forward = new vector3 (,-1); vector3 forward = vector3.transform (cameraoriginalforward, camerarotation); cameraposition + = movespeed * forward;
Changing the value of movespeed can increase or decrease the speed at which the camera moves, because the value is multiplied by the forward direction that has been rotated.
The same method can also move the camera left and right. Processing is the (, 0) Right vector instead of the (,-1) Forward vector. We still need to first convert it to obtain the right vector corresponding to the current camera's rotation.
Float movespeed = 0.5f; vector3 outputs = new vector3 (1, 0, 0); vector3 outputs = vector3.transform (cameraoriginalright, camerarotation); cameraposition + = movespeed * inputs;
Code
In this method, the camera only needs to save the current position and rotation, and the view matrix must be updated when the position and rotation change. These changes usually come from user input. You can see the specific implementation in the 2-3 and 2-4 tutorials. Each matrix needs to be initialized. First, you need to set the camerarotation matrix as the unit matrix.
Protected override void initialize () {float viewangle = mathhelper. piover4; float aspectratio = graphics. graphicsdevice. viewport. aspectratio; float nearplane = 0.5f; float farplane = 100366f; projectionmatrix = matrix. createperspectivefieldofview (viewangle, aspectratio, nearplane, farplane); cameraposition = new vector3 (-5, 7, 14); camerarotation = matrix. createrotationx (-mathhelper. PI/8.0f) * matrix. createrotationy (-mathhelper. PI/8.0f); updateviewmatrix (); base. initialize ();} protected override void Update (gametime) {If (gamepad. getstate (playerindex. one ). buttons. back = buttonstate. pressed) This. exit (); movecameraforward (); base. update (gametime);} private void movecameraforward () {float movespeed = 0.05f; vector3 forward = new vector3 (0, 0,-1); vector3 forward = vector3.transform (cameraoriginalforward, camerarotation); cameraposition + = movespeed * camerarotatedforward; updateviewmatrix ();} private void updateviewmatrix () {vector3 cameraoriginaltarget = new vector3 (0, 0,-1 ); vector3 transform = new vector3 (0, 1, 0); vector3 transform = vector3.transform (transform, camerarotation); vector3 transform = cameraposition + transform; vector3 transform = vector3.transform (transform, camerarotation ); viewmatrix = matrix. createlookat (cameraposition, camerafinaltarget, camerarotatedupvector);} protected override void draw (gametime) {graphics. graphicsdevice. clear (color. cornflowerblue); // render coordcross using specified view and projection matrices ccross. draw (viewmatrix, projectionmatrix); base. draw (gametime );}
Extended reading matrix multiplication Sequence
See tutorial 4-2.
Change Coordinate System
The preceding forward (,-1) and up (, 0) methods are "official" xNa vectors, which can also be obtained using the vector3. Forward and vector3. Up shortcuts. But this is just an agreement. You can define a completely different coordinate system. For example, you can use (, 1) as the UP direction, (, 0) as the forward direction, (, 0) as the right direction, depending on your needs.
However, these three vectors must comply with one rule. In xNa, X, Y, and Z axes are the right-hand coordinate system. This means that once you know any two axes, you can know the direction of the third axis. Expand the thumb and forefoot of your right hand, bend the middle finger to make it perpendicular to the forefoot and thumb, and think of the three fingers as the coordinate axis. If it is the right coordinate system, then the X axis corresponds to the thumb, the Y axis corresponds to the index finger and the Z axis corresponds to the middle finger.
In this tutorial, the first coordinate system points to the right and the middle to the top. To represent the "official" xNa coordinate system, point your thumb to the right (positive X axis = right), and the index finger to the top (Y axis = Top ). Now you can see that the middle finger points to the rear (positive Z axis = rear), which is why there is a negative number in the official forward (,-1) Vector!