Android OpenGL ES (vi)----into three dimensions create a projection matrix and a rotation matrix in your code

Source: Internet
Author: User

We are now ready to add a perspective projection to the code. The Android Matrix class prepares two methods for it------frustumm () and Perspectivem (). Unfortunately, Frustumm () has a flaw that affects certain types of projections, and Perspectivem () is only introduced from the Android version of ICS, which is not available in earlier versions of Android. We can simply support ICS and the versions above, but this will throw away a large portion of the market, and some users still run earlier versions of Android.


As an alternative, we can create our own method to implement the projection matrix.



1. Create your own Perspectivem

To create a new class Matrixhelper in the toolkit, add the following method signature at the beginning:

public static void Perspectivem (float[] m,float yfovindegress,float aspect,float n,float f) {


Calculate focal length


The first thing we need to do is calculate the focal length, which will be based on the field of view on the Y axis. Just after the method signature, add the following code:

Final float angleinradians= (float) (yfovindegress*math.pi/180.0);
Final float a= (float) (1.0/math.tan (angleinradians/2.0));

We use the Java Math class to calculate the tangent function because it requires a radian angle, so we convert the field of view from degrees to radians. Then calculate the focal length.


Output matrix


We can now have a more mathematical proof of the previous section to write the matrix directly, adding the following code:

M[0]=a/aspect;
m[1]=0f;
m[2]=0f;
m[3]=0f;


m[4]=0f;
M[5]=a;
m[6]=0f;
m[7]=0f;


m[8]=0f;
m[9]=0f;
m[10]=-((f+n)/(f-n));
m[11]=-1f;


m[12]=0f;
m[13]=0f;
m[14]=-((2f*f*n)/(f-n));
m[15]=0f;


This is where the matrix data is stored in the floating-point array defined by the parameter m, which requires at least 16 elements. OpenGL stores matrix data in column-based order, which means that we write a column of data at a time instead of one line at a time. The top four values are the first column, the next set of four numbers is the second column, and so on.



2. Start using the projection matrix


We will now use that perspective projection matrix instead. Open your rendering class and remove all the code from onsurfacechanged (), leaving only the Glviewport () call, adding the following code:


Matrixhelper.perspectivem (ProjectionMatrix, A, (float) width/(float) Height, 1f, 10f);


This creates a perspective projection with a 45-degree view. The viewport begins with a Z-value of 1 and ends at a z-value of-10.


After adding Matrixhelper import, continue the previous program to run, you can find that the desktop is missing, because we did not give the table z position, by default z in the position of 0. Because the visual vertebral body starts at the position of Z-1, we can't see the table unless we move it to that distance.


Do not hardcode Z values, let's use a translation matrix to move the table out before projecting using a projection matrix. By convention, we refer to this matrix as the model matrix.


Moving objects using a model matrix


At the top of the class, add the following definition of the matrix:


Private final float[] modelmatrix=new float[16];


We're going to use this matrix to move the desktop to that distance. At the end of Onsurfacechanged (), add the following code:


Matrix.setidentitym (Modelmatrix, 0);
Matrix.translatem (MODELMATRIX,0,0F,0F,-2F);


This is to set the model matrix to the unit matrix, which is shifted 2 along the z-axis. When we multiply the coordinates of the desktop with this matrix, those coordinates will eventually move 2 units along the z axis in a negative direction.


Multiply once or multiply two times


Now we have to make a choice: we still need to apply this matrix to each vertex, so the first option is to add an additional matrix to the vertex shader. We multiply each vertex with this model matrix, let them move 2 units in negative direction along the z axis, and then multiply each vertex with the projection matrix. In this way, OpenGL can do perspective division and transform these vertices into normalized device coordinates.


If you don't want to be so troublesome, there is a better way: we can multiply the model matrix with the projection matrix, get a matrix, and pass the matrix to the vertex shader. In this way, we can keep only one matrix in the shader.


Select the appropriate order


To figure out which order we should use, let's take a look at the mathematical operations that use only the projection matrix:



V Ertexeye represents the position of the vertex in the scene before the projection matrix is multiplied. Once we have added the model matrix to move the table, this mathematical operation looks like this.



V Ertexmodel represents the position of the vertex before the model matrix is put into the scene. Merge the two expressions together, and finally get the following formula:



To replace the two matrices with a matrix, we have to multiply the projection matrix by the model matrix, which is to put the projection matrix on the left and the model matrix on the right.


Update code uses a matrix


Let's encapsulate this new matrix code and add the following code to the translate () call in Onsurfacechanged ():


Final float[] Temp=new float[16];
Matrix.multiplymm (temp,0,projectionmatrix,0,modelmatrix,0);
System.arraycopy (temp, 0, ProjectionMatrix, 0, temp.length);


Whenever you multiply a two matrix, you need a temporary variable to store its results. If you try to write the result directly, the result will be undefined.


We first create a temporary floating-point group to store its temporary results, and then call Multiplymm () to multiply the projection matrix and the model matrix, and the result is stored in the temporary array. Next, we call System.arraycopy () to save the result back to Projectmatrix, which now contains the combined effect of the model matrix and the projection matrix.


If we run this program now, we will find that this is still a flat desktop.



3. Increase rotation


Now that we have a well-configured projection matrix and a model matrix of movable tables, all we need to do is rotate the table so that we can see it from a certain angle. If we use the rotation matrix, we just need one line of code to do it. We have never used rotations and now take some time to understand how these rotations work.


We need to figure out what axis we need to rotate and how many degrees to rotate around. Let's look again:



To figure out how an object rotates around a given axis, we'll use the right-hand coordinate rule: Extend your right hand, make a fist, and let the thumb point toward the positive axis. If it is a positive angle of rotation, the curled finger will tell you how an object rotates around that axis. When you point the thumb to the positive x-axis, look at how the direction of rotation follows the axis of the finger curl.

Try this rotation with the x-axis, y-axis, and z-axis, respectively. If rotated around the y-axis, the table rotates horizontally around its top and low end. If you rotate around the z axis, the table rotates within a circle. What we want to do is make the table rotate backwards around the x-axis, because it makes the table look more layered.


Rotation matrix


We will use a rotation matrix to do the actual rotation. The rotation matrix uses sine and cosine trigonometric functions to convert the rotation into a scaling factor. Here is the definition of the matrix used to rotate around the x axis:



Then the matrix used to rotate around the y axis:



Finally, there is a matrix used to rotate around the Z axis:



It is also possible to combine all matrices into a common rotation matrix so that they can be rotated based on any angle and vector.


As a test, let's try to rotate around the x axis. We start at a point where it is at the origin of a unit, that is, the Y value is 1. Rotate it 90 degrees around the x-axis. First, let's prepare this rotation matrix:



Let's multiply this matrix with the position vector of this point to see what we Got:



This point is moved from (0,1,0) to (0,0,1). If we look back at the rotation axis above and use the right hand rule for the x-axis, we can see how the forward rotation moves a point along a circle around the x-axis.



4. Add rotation to the code


We are now ready to add this spin to the code. Go back to onsurfacechanged (), adjust the translation matrix, and add a rotation matrix, as follows:


Matrix.translatem (modelmatrix,0,0f,0f,-2.5f);
Matrix.rotatem (modelmatrix,0,-60f,1f,0f,0f);


We put this table a little further, because once we had it rotated, the bottom of it would be closer to us. We then rotate it around the x-axis-60 degrees, which puts the table at a good angle, just as we stand in front of it.

This table should now look as follows:


Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.

Android OpenGL ES (vi)----into three dimensions create a projection matrix and a rotation matrix in your code

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.