OpenGL Note 5

Source: Internet
Author: User

OpenGL getting started [5]



Today I want to talk about the content of 3D transformation. The course is boring. This is mainly because many functions cannot describe their effects when they are used independently. I have to give a comprehensive example at the end. I hope you can see it in one breath. Reading only once may not be enough. If you feel confused, read it twice. If you have any questions, follow the instructions below.
I have also used several images to help me understand them.


When we draw a geometric image above, do you think our plot scope is too narrow? Coordinates can only be from-1 to 1, and can only be the right X axis, Y axis up, Z axis vertical screen. These limitations cause a lot of inconvenience to our drawing.

We live in a 3D world-if we want to observe an object, we can:
1. Observe it from different locations. (View transformation)
2. Move or rotate it. Of course, if it is just an object in a computer, we can also zoom in or out it. (Model Transformation)
3. If you draw an object, you can choose whether to use a perspective effect of "near Big, far and small. In addition, we may only want to see part of the object, not all (clipping ). (Projection Transformation)
4. We may want to draw the entire picture, but it only occupies part of the paper, not all. (View-view conversion)
These can be implemented in OpenGL.

OpenGL transformation is actually implemented through matrix multiplication. Whether it is moving, rotating, or scaling, the current matrix is multiplied by a new matrix. I will not describe the matrix here. If you are interested, you can look at linear algebra (most of the students should have learned it ).
OpenGL can operate the Matrix directly at the bottom layer. However, as a beginner, this does not make much sense. I will not introduce it here.


1. model transformation and view Transformation
From the perspective of "relative movement", changing the position and direction of the observation point and changing the position and direction of the object are equivalent. In OpenGL, the same functions are even used to implement these two functions.
Since both model and view transformations are implemented through matrix operations, you should first set the current operation matrix to "Model View matrix" Before transformation ". The gl_modelview parameter is used to call the glmatrixmode function, as shown in the following code:
Glmatrixmode (gl_modelview );
In general, we need to set the current matrix as a unit matrix before transformation. This also requires only one line of code:
Glloadidentity ();

Then, you can perform model transformation and view transformation. Model and view transformation involves three functions:
Gltranslate * to multiply the current matrix with a matrix that represents a moving object. The three parameters represent the displacement values on the three coordinates respectively.
Glrotate *, which is used to multiply the current matrix and a matrix representing the rotated object. An object rotates in a straight line from (0, 0) to (x, y, z) counterclockwise. The angle parameter indicates the rotation angle.
Glscale * is used to multiply the current matrix and a matrix representing a scaled object. X, Y, and Z respectively indicate the scaling ratio in this direction.

Note that I always say "multiply with xx", instead of simply saying "this function is rotating" or "this function is moving". There is a reason for this. I will talk about it right away.
Assume that the current matrix is a matrix of units, multiply it by a matrix R that represents rotation, multiply it by a matrix T that represents movement, and then multiply the final matrix by the coordinate matrix V of each vertex. Therefore, the transformed vertex coordinates are (RT) V ). Because of the combination rate of matrix multiplication, (RT) V) = (R (TV), in other words, it is actually moving first and then rotating. That is, the actual conversion order is the opposite of the write order in the code. Because the results obtained by "first move, then rotate" and "first rotate and then move" are very different, you need to pay special attention to this point when you are a beginner.
OpenGL is designed to achieve higher efficiency. However, it is also very painful to consider how to reverse a complex 3D image every time. Another idea is introduced here to make the Code look more natural (the code written is actually exactly the same, but the method used when considering the problem is different ).
As we can imagine, the coordinates are not fixed. During rotation, the coordinate system rotates with the object. When moving, the coordinate system moves with the object. In this way, you do not need to consider the code reverse order.

The above are all about changing the position and direction of an object. To change the position of the observation point, you can also use the glrotate * And gltranslate * functions: glulookat. It has many parameters. The first three parameters represent the position of the observation point, the middle three parameters represent the position of the observation target, and the last three parameters represent the position from (0, 0, 0) to a straight line (x, y, z), which represents the "top" direction that the observer Deems.


2. Projection Transformation
A projection transformation defines a visible space. objects other than the visible space are not drawn to the screen. (Note: from now on, the coordinates can no longer be-1.0 to 1.0 !)
OpenGL supports two types of projection transformations: Perspective Projection and normal projection. Projection is also implemented using matrices. To operate the projection matrix, use the gl_projection parameter to call the glmatrixmode function.
Glmatrixmode (gl_projection );
In general, we need to set the current matrix as a unit matrix before transformation.
Glloadidentity ();

The result of perspective projection is similar to a photo, which has the effect of being close to big and small. For example, taking a picture of a railway track forward in the front of the locomotive, the two rails seem to have crossed in the distance.
You can use the glfrustum function to set the current visible space to the Perspective Projection space. The parameter meanings include:

Statement: this image is from www.opengl.org. It is a picture of the book OpenGL programming guide. Since the old version of this book (the first version, 1994) has been circulating on the internet, I hope I have not touched on copyright issues.
You can also use more commonly used gluperspective functions. The parameter meanings include:

Statement: this image is from www.opengl.org. It is a picture of the book OpenGL programming guide. Since the old version of this book (the first version, 1994) has been circulating on the internet, I hope I have not touched on copyright issues.

Normal projection is equivalent to the result observed in an infinite distance. It is just an ideal state. However, for computers, using positive projection may lead to better running speed.
You can use the glortho function to set the current visible space to a positive projection space. The parameter meanings include:

Statement: this image is from www.opengl.org. It is a picture of the book OpenGL programming guide. Since the old version of this book (the first version, 1994) has been circulating on the internet, I hope I have not touched on copyright issues.

If the drawing space itself is two-dimensional, you can use gluortho2d. Its usage is similar to glorgho.


3. Modify the view
When everything is ready, you just need to draw pixels to the screen. At this time, the last question remains: Which area of the window should the pixel be drawn? Normally, the entire window is completely filled by default, but we can only fill in half. (That is, fill the entire image in half of the window)

Statement: this image is from www.opengl.org. It is a picture of the book OpenGL programming guide. Since the old version of this book (the first version, 1994) has been circulating on the internet, I hope I have not touched on copyright issues.

Use glviewport to define the view. The first two parameters define the lower left foot (0, 0 indicates the bottom left) of the view, and the last two parameters are width and height.

4. Operation matrix Stack
This is the Getting Started tutorial. Let's briefly introduce the stack. You can think of a stack as a stack of plates. At the beginning, there was no plate. You could put it up one by one or pick it up one by one. Each removal is the last tray to be placed. Generally, when a computer implements a stack, the stack capacity is limited. If there are too many plates, an error will occur. Of course, if you do not have a plate, you may have to pick it up again.
When performing a matrix operation, we may need to save a matrix and restore it later. When we need to save it, call the glpushmatrix function, which is equivalent to putting the matrix (equivalent to a plate) on the stack. When you need to restore the last save, call the glpopmatrix function, which is equivalent to removing the matrix from the stack. OpenGL requires that the stack capacity can contain at least 32 matrices. In some OpenGL implementations, the stack capacity actually exceeds 32. Therefore, you do not have to worry too much about the Matrix capacity.
Generally, it is more convenient and faster to save and restore data before performing the first transformation and then performing the inverse transformation.
Note: Both the Model View matrix and the projection matrix have corresponding stacks. Use glmatrixmode to specify whether the current operation is a model view matrix or a projection matrix.

5. Comprehensive examples
Now, the basic knowledge of view transformation is almost finished. But we cannot end it like this. Because the content of this course is too boring, if you give examples separately, the effect may be poor. I have to give a comprehensive example for your reference. As for the actual understanding, it depends on everyone's efforts. If you have less time to talk about it, go to the topic.

We want to create a three-dimensional scenario, including the sun, Earth, and moon. Assume that there are 12 months in a year and 30 days each month. Every year, the Earth rotates around the sun. Every month, the moon circle the earth. That is, there are 360 days in a year. The number of the given date (0 ~ 359), the relative positions of the sun, Earth, and moon must be drawn. (This is designed for programming convenience. If you need to make a more realistic situation, it is only some numerical processing, and has little to do with OpenGL)
First, let us determine that these three celestial bodies are spherical and their trajectory is in the same horizontal plane, and establish the following coordinate system: the center of the Sun is the origin, the plane where the trajectory of the celestial body is located represents the plane determined by the X and Y axes. On the first day of each year, the Earth is in the positive direction of the X axis, and the moon is in the positive direction of the earth's X axis.
The next step is to establish a visual space. Note: The radius of the sun is much shorter than the distance from the sun to the Earth. If we directly use the length ratio obtained from astronomical observations, the size of the sun will be ignored when the entire window represents an hour of the Earth's orbit. Therefore, we can only multiply the radius of several celestial bodies to meet our observation needs. (For Baidu, the approximate radius of the sun, Earth, and moon is 696000 km, 6378 km, and 1738 km respectively. The distance from the Earth to the sun is about 0.15 billion km = 150000000 km, and the distance from the moon to the Earth is about 380000 km .)
Let's assume some data and modify the radius of the three celestial bodies to 69600000 (100 times), 15945000 (2500 times), and 4345000 (5000 times ). Change the distance from the Earth to the Moon to 38000000 (up 100 times ). The distance from the Earth to the Sun remains unchanged.
To make the earth and the moon very close to us, we still don't need to change the observation points and the observation direction to observe them. We put the observation points in this position: (0,-200000000, 0) -- because the Earth's orbital radius is 150000000, we can get an integer and get-200000000. Set the observation target to the origin (that is, the sun center), and select the positive direction of the Z axis as the "upper" side. Of course, we can also move the observation point to the "TOP" side to get (0,-200000000,200 usd00), so that we can get a look-down effect of 45 degrees.
To get the perspective effect, we use gluperspective to set the visual space. It is assumed that the angle of view is 60 degrees (if this angle is found inappropriate during debugging, it can be modified. The value I selected at the end is 75 .), The aspect ratio is 1.0. The nearest visible distance is 1.0, and the farthest visible distance is 200000000*2 = 400000000. That is: gluperspective (60, 1, 1, 400000000 );


5. Comprehensive examples
Now, the basic knowledge of view transformation is almost finished. But we cannot end it like this. Because the content of this course is too boring, if you give examples separately, the effect may be poor. I have to give a comprehensive example for your reference. As for the actual understanding, it depends on everyone's efforts. If you have less time to talk about it, go to the topic.

We want to create a three-dimensional scenario, including the sun, Earth, and moon. Assume that there are 12 months in a year and 30 days each month. Every year, the Earth rotates around the sun. Every month, the moon circle the earth. That is, there are 360 days in a year. The number of the given date (0 ~ 359), the relative positions of the sun, Earth, and moon must be drawn. (This is designed for programming convenience. If you need to make a more realistic situation, it is only some numerical processing, and has little to do with OpenGL)
First, let us determine that these three celestial bodies are spherical and their trajectory is in the same horizontal plane, and establish the following coordinate system: the center of the Sun is the origin, the plane where the trajectory of the celestial body is located represents the plane determined by the X and Y axes. On the first day of each year, the Earth is in the positive direction of the X axis, and the moon is in the positive direction of the earth's X axis.
The next step is to establish a visual space. Note: The radius of the sun is much shorter than the distance from the sun to the Earth. If we directly use the length ratio obtained from astronomical observations, the size of the sun will be ignored when the entire window represents an hour of the Earth's orbit. Therefore, we can only multiply the radius of several celestial bodies to meet our observation needs. (For Baidu, the approximate radius of the sun, Earth, and moon is 696000 km, 6378 km, and 1738 km respectively. The distance from the Earth to the sun is about 0.15 billion km = 150000000 km, and the distance from the moon to the Earth is about 380000 km .)
Let's assume some data and modify the radius of the three celestial bodies to 69600000 (100 times), 15945000 (2500 times), and 4345000 (2500 times ). Change the distance from the Earth to the Moon to 38000000 (up 100 times ). The distance from the Earth to the Sun remains unchanged.
To make the earth and the moon very close to us, we still don't need to change the observation points and the observation direction to observe them. We put the observation points in this position: (0,-200000000, 0) -- because the Earth's orbital radius is 150000000, we can get an integer and get-200000000. Set the observation target to the origin (that is, the sun center), and select the positive direction of the Z axis as the "upper" side. Of course, we can also move the observation point to the "TOP" side to get (0,-200000000,200 usd00), so that we can get a look-down effect of 45 degrees.
To get the perspective effect, we use gluperspective to set the visual space. It is assumed that the angle of view is 60 degrees (if this angle is found inappropriate during debugging, it can be modified. The value I selected at the end is 75 .), The aspect ratio is 1.0. The nearest visible distance is 1.0, and the farthest visible distance is 200000000*2 = 400000000. That is: gluperspective (60, 1, 1, 400000000 );


Now let's take a look at how to draw these three celestial bodies.
For the sake of simplicity, we think of all three celestial bodies as the regular sphere. In the glut utility we use, there is a ready-made function to draw the sphere: glusolidsphere, which is used to draw a sphere at the "origin. Since coordinates can be freely transformed using the gltranslate * And glrotate * functions, we can draw a sphere at any position. The function has three parameters: the first parameter represents the radius of the sphere, and the last two parameters represent the number of "planes". Simply put, the accuracy of the sphere increases, of course, the lower the speed. Here we just set the last two parameters to 20.
The sun is at the coordinate origin, so it does not need to undergo any transformation and can be directly drawn.
The Earth must be a little more complex and need to change coordinates. Since the number of days passed this year is known to be day, the earth turns to the angle of day/The number of days in a year * 360 degrees. It has been assumed that every year is 360 days, so the earth turns to day. So we can solve the problem through the following code:
Glrotatef (day, 0, 0,-1 );
/* Note that the earth's public rotation is "from West to East", so it is a clockwise rotation in the negative direction of the Z axis */
Gltranslatef (Earth Orbit Radius, 0, 0 );
Glusolidsphere (Earth radius, 20, 20 );
The moon is the most complex. Because it not only has to go around the Earth, but also has to go around the sun. However, if we choose the Earth as a reference, the movement of the moon is a simple circular motion. If we plot the Earth first and then the moon, we only need to perform a transformation similar to the earth:
Glrotatef (moon rotation angle, 0, 0,-1 );
Gltranslatef (Moon orbital radius, 0, 0 );
Glusolidsphere (Moon radius, 20, 20 );
However, this "Rotation Angle of the Moon" cannot be simply understood as day/day of a month at 30*360 degrees. Because when we plot the earth, the coordinates have already been rotated. The current rotation is based on the previous rotation, so you still need to process this "difference ". We can write it as: Day/30*360-day, that is, minus the original angle that has been switched. This is just a simple process. Of course, you can use glpushmatrix to save the matrix before creating the Earth, and then use glpopmatrix to restore the matrix after drawing the earth. Design a formula for the Moon location unrelated to the Earth location to draw the moon. Generally, the latter method is better than the former method, because the floating point operation is not accurate, that is, we calculate the location of the Earth itself is not accurate. Using this inaccurate number to calculate the position of the moon will lead to the accumulation of "inaccurate" components, and excessive "inaccurate" May cause errors. We didn't think about this in this small program, but it doesn't mean this issue is not important.
Note: OpenGL draws objects in 3D coordinates to a two-dimensional screen, and the order of drawing is in the order of code. Therefore, the objects drawn later will cover the objects first drawn, even if the objects drawn later are the "back" of the objects first drawn. Deep testing can solve this problem. The method is as follows: 1. Call the glable function with the gl_depth_test parameter to start the deep test. 2. When necessary (usually at the beginning of each screen drawing), clear the depth buffer, that is, glclear (gl_depth_buffer_bit). glclear (gl_color_buffer_bit) and glclear (gl_depth_buffer_bit) it can be merged:
Glclear (gl_color_buffer_bit | gl_depth_buffer_bit );
The latter may run faster than the former.


So far, we can finally get the complete code of the entire "Sun, earth and moon" system.


Code:
--------------------------------------------------------------------------------
// The Sun, Earth, and moon
// Assume that every month is 30 days.
// 12 months a year, totaling 360 days
Static int day = 200; // The variation of day: from 0 to 359
Void mydisplay (void)
{
Glenable (gl_depth_test );
Glclear (gl_color_buffer_bit | gl_depth_buffer_bit );

Glmatrixmode (gl_projection );
Glloadidentity ();
Gluperspective (75, 1, 1, 400000000 );
Glmatrixmode (gl_modelview );
Glloadidentity ();
Glulookat (0,-200000000,200 1000000, 0, 0, 0, 0, 0, 1 );

// Draw the red "Sun"
Glcolor3f (1.0f, 0.0f, 0.0f );
Glusolidsphere (69600000, 20, 20 );
// Draw a blue earth"
Glcolor3f (0.0f, 0.0f, 1.0f );
Glrotatef (day/360.0*360.0, 0.0f, 0.0f,-1.0f );
Gltranslatef (150000000, 0.0f, 0.0f );
Glusolidsphere (15945000, 20, 20 );
// Draw a yellow "moon"
Glcolor3f (1.0f, 1.0f, 0.0f );
Glrotatef (day/30.0*360.0-day/360.0*360.0, 0.0f, 0.0f,-1.0f );
Gltranslatef (38000000, 0.0f, 0.0f );
Glusolidsphere (4345000, 20, 20 );

Glflush ();
}
--------------------------------------------------------------------------------



Modify the value of day to see if the screen is changed.


Summary: at the beginning of this lesson, we formally entered the 3D OpenGL world.
OpenGL transforms a three-dimensional object into a two-dimensional image through matrix transformation, and then displays the object on the screen. To specify the matrix of the current operation, we use the glmatrixmode function.
We can move, rotate the observation point, or move or rotate an object. The functions used are gltranslate * And glrotate *.
We can scale an object. The function used is glscale *.
We can define a visual space, which can be a "positive projection" (using glortho or gluortho2d) or a "Perspective Projection" (using glfrustum or gluperspective ).
We can define the window range to be drawn. The function used is glviewport.
The matrix has its own "stack" to facilitate storage and recovery. This is helpful in drawing complex images. The functions used are glpushmatrix and glpopmatrix.

Well, the hard lesson is over. I know that the content of this lesson is very boring, even the last example is. But I don't have a better solution. I hope you can stick to it. Don't worry. After you get familiar with the course content, it will be easy and pleasant in the future.

= =====
================================= To be continued ======================== =====

OpenGL Note 5

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.