Win32 OpenGL programming (7) 3D view transformation-the key to true 3D
Write by nine days Yan Ling (jtianling) -- blog.csdn.net/vagrxie
Discuss newsgroups and documents
Abstract
This article introduces the concept of view transformation from the camera metaphor, explains the key functions of view transformation, and uses an example to demonstrate the dynamic changes in the graphic display effect response when parameters change, then it adds the identification and processing of the front and back of the polygon When 3D images are drawn. It can be regarded as a real 3D entry.
Camera analogy
In OpenGL programming guide
"Unifies all 3D transformations into an interesting real-world model.
1. The process of determining the camera Location corresponds to "view transformation" (viewing transformations)
2. The process of determining the Object Location corresponds to "modeling transformations)
3. The process of determining the camera magnification corresponds to projection transformations)
4. The process of determining the Photo size corresponds to "viewport transformations)
The actual photography process follows this process, and we also follow this process when processing 3D images. Among them, the above four transformations are what I will introduce today.
View transformation-determine the View Angle
Objects in real life, from different perspectives, we see different things, this also caused the famous "Golden Shield event" (in fact, it is a fable-_-!) in history -_-!), On the one hand, yundun and yundun are both gold and silver ......
Step into the 3D world with Win32 OpenGL programming (6)
"(Later referred to as xo6, this series of articles is similar) the last and most complex triangle cone in this example is the rotation of the triangle itself, and our viewing angle has not changed. Now, in turn, the triangle cone does not move, so we can move our own position to see the different directions of the triangle cone. In real life, you cannot always let others rotate the sculpture with it -_-! At this time, you have to move around. At this time, we changed the angle of observation, but it was indeed the different sides of the sculpture. As shown in the following example, we can observe this simple triangle cone from different points of view. See the following example:
// Observer position
Glfloat gviewposx;
Glfloat gviewposy;
Glfloat gviewposz = 1.0;
// View orientation of the observer
Glfloat gviewdirx = 0.0;
Glfloat gviewdiry= 0.0;
Glfloat g viewdirz = 0.0;
Glfloat gviewupdirx = 0.0;
Glfloat gviewupdiry = 1.0;
Glfloat gviewupdirz = 0.0;
// Change the position or view
Bool gbchangepos = true;
// Do all the plotting work here
Void sceneshow (glvoid)
{
Glclear (gl_color_buffer_bit );
Glcolor3f (1.0, 0.0, 0.0 );
Glpushmatrix ();
Drawsmoothcolorpyramid (0.5 );
Glpopmatrix ();
Glloadidentity ();
Glulookat (gviewposx, gviewposy, gviewposz, gviewdirx, gviewdiry, gviewdirz, gviewupdirx, gviewupdiry, gviewupdirz );
Glflush ();
}
//////////////////////////////////////// ///////////////////
Int game_main (void * parms = NULL, int num_parms = 0)
{
DWORD dwstarttime;
Dwstarttime = gettickcount ();
// This is the main loop of the game, do all your processing
// Here
// For now test if user is hitting ESC and send wm_close
If (keydown (vk_escape ))
Sendmessage (ghwnd, wm_close, 0, 0 );
If (gbchangepos)
{
If (keydown (vk_up ))
{
Gviewposy + = 0.01;
Gviewposz = SQRT (1.0-gviewposy * gviewposy );
}
If (keydown (vk_down ))
{
Gviewposy-= 0.01;
Gviewposz = SQRT (1.0-gviewposy * gviewposy );
}
If (keydown (vk_left ))
{
Gviewposx ++ = 0.01;
Gviewposz = SQRT (1.0-gviewposx * gviewposx );
}
If (keydown (vk_right ))
{
Gviewposx-= 0.01;
Gviewposz = SQRT (1.0-gviewposx * gviewposx );
}
}
Else
{
If (keydown (vk_up ))
{
Gviewdiry + = 0.01;
}
If (keydown (vk_down ))
{
G viewdiry-= 0.01;
}
If (keydown (vk_left ))
{
Gviewdirx ++ = 0.01;
}
If (keydown (vk_right ))
{
Gviewdirx-= 0.01;
}
}
If (keydown (vk_numpad8 ))
{
Gviewupdiry + = 0.01;
}
If (keydown (vk_numpad2 ))
{
Gviewupdiry-= 0.01;
}
If (keydown (vk_numpad6 ))
{
Gviewupdirx + = 0.01;
}
If (keydown (vk_numpad4 ))
{
Gviewupdirx-= 0.01;
}
Sceneshow ();
// Control Frame Rate
While (gettickcount ()-dwstarttime <time_in_frame)
{
Sleep (1 );
}
// Return success or failure or your own return code here
Return (1 );
} // End game_main
Although the program code is very long, it is mainly used to demonstrate all the parameters. In fact, the subject is not complicated. The main new function is glulookat, and its function is called as its name, it is to determine where you are from (where look from, the first three parameters), where to see (where look at, three parameters in the middle), how to see (how to look, the last three parameters). The preceding example shows the changes in the graphic response after each parameter change.
OpenGL Reference Manual
:
Glulookat-define a viewing Transformation
C Specification
Void glulookat (gldouble eyex,
Gldouble eyey,
Gldouble Eyez,
Gldouble centerx,
Gldouble centery,
Gldouble centerz,
Gldouble UPX,
Gldouble upy,
Gldouble upz );
Parameters
Eyex, eyey, Eyez
Specifies the position of the eye point.
Centerx, centery, centerz
Specifies the position of the reference point.
UPX, upy, upz
Specifies the direction of the UP vector.
In this example, the position of the observer is saved through the global variable, and the direction is changed by the up and down keys to observe the triangle cone from different angles. As a demonstration, I locked the direction of observation at the beginning, always oriented to the triangle cone of observation, and through calculation, the observer always maintains the same distance with the observed item, so that the effect of the observed position change can be seen most, however, at present, only the direction changes at the front of the object are implemented. When the front is crossed, the increasing value needs to be reduced by programming due to the Quadrant change, then change the plus and minus signs of another auxiliary variable. For example, when the time is always up and on time, the Y coordinate keeps increasing, but when the value is y = 1.0, it needs to be reduced, and the Z coordinate is also changed to a negative value, this is because it has reached the rear of the object.
When you press the Insert key and press the top, bottom, left, and right to change the direction of view, you will find that when the observation direction is right, the object moves to the left until it is removed from the screen, this is like starting to face the screen and constantly turning the head to the right, then the screen will move to the left. When the angle of your head is large enough, you will no longer see the screen.
When you use the keyboard's 8426 direction control, the angle of observation is changed to the upward angle, just as if you were looking at the screen with your head, let's take a look at the specific demonstration effect. Here we provide
In the old saying, only key fragments are added to save space. For the complete source code, see the 2009-10-25/glviewingtrans directory in the source code of my blog, for more information about how to obtain the source code, see the description at the end of the article.
In this example, it is strongly recommended that you run the program to feel what the 3D conversion is in the game, which is actually the case. Since all images are 3D, why do some games have to restrict your viewing angle? There are also new words such as 2.5D and 2.8d (I don't know how to name them), but after learning the view transformation, I will understand that the restriction angle simplifies the process, as I did here, although it is already a real 3D triangle cone, I still do not provide 720 degrees of random rotation, because when moving to the other side of the object, the processing method is somewhat changed. It will be troublesome to change it. You must know that the 2D plane has four quadrants, but what about 3D? There are more than eight quadrants. The calculation method for each quadrants in view transformation is not the same. My programs are much simpler, and those 2. XD game programs are naturally simpler.
Polygon Display Mode
After you have determined the angle of view, you will find that there is a problem with the original triangle cone, and the back shows -_-! See the above, but this is not feasible. The problem is that we did not tell OpenGL that the side is the back, that side is the front, and OpenGL's default practical method is to deal with it regardless of the front and back, naturally, we have to tell OpenGL to handle it in the way we want to handle it. For example, we want to display it on the front and not on the back (what a normal requirement ), then we can use the glpolygonmode function to specify.
OpenGL Reference Manual
:
Glpolygonmode-select a polygon Rasterization Mode
C Specification
Void glpolygonmode (glenum face,
Glenum mode );
Parameters
Face
Specifies the polygons that mode applies.
Must be
Gl_front for front-facing polygons,
Gl_back for back-facing polygons,
Or gl_front_and_back for front-and back-facing polygons.
Mode
Specifies how polygons will be rasterized.
Accepted values are
Gl_point,
Gl_line, and
Gl_fill.
The initial value is gl_fill for both front-and back-facing polygons.
To meet our requirements, you only need to call this function as follows:
Glpolygonmode (gl_front, gl_fill );
Glpolygonmode (gl_back, gl_line );
This indicates that the back will not be filled, but how does OpenGL know which is the front and which is the back? You can use glfrontface to specify,
OpenGL Reference Manual
:
Glfrontface-define front-and back-facing polygons
C Specification
Void glfrontface (glenum mode );
Parameters
Mode
Specifies the orientation of front-facing polygons.
Gl_cw and gl_ccw are accepted.
The initial value is gl_ccw.
OpenGL is not stupid enough to specify the front and the aspect of a specific plane. It is determined by the direction of vertex drawing, openGL uses this function to specify the direction in which the polygon represents the front and back sides. By default, the front is clockwise and the front is clockwise. Think about the advantages of this function and it is convenient to specify it, when you draw a vertex, you just need to consider it. You don't need to specify it again. Then, it is still valid. The front side is looking at something counter-clockwise. It is really clockwise when it comes to the opposite side -_-! (Nonsense)
For example:
Void drawsmoothcolorpyramid (glfloat adsize)
{
Static glfloat fpyramiddatas [] = {0.0, 1.0, 0.0, // Vertex on the triangle cone
-1.0, 0.0, 1.0, // left front vertex of the bottom
1.0, 0.0, 1.0, // bottom right bottom Vertex
0.0, 0.0,-1.0}; // bottom vertex of the bottom surface
Glfloat fpyramidsizedatas [sizeof (fpyramiddatas)/sizeof (glfloat)] = {0 };
// Calculate the size
For (INT I = 0; I <12; ++ I)
{
Fpyramidsizedatas [I] = fpyramiddatas [I] * adsize;
}
Static glfloat fpyramidcolors [] = {0.0, 0.0, 0.0,
1.0, 0.0, 0.0,
0.0, 1.0, 0.0,
0.0, 0.0, 1.0 };
// Static glubyte ubyindices [] = {0, 1, 2, // front
// 0, 1, 3, // left side
// 0, 2, 3, // right side
// 1, 2, 3}; // bottom
Static glubyte ubyindices [] = {0, 1, 2, // front
0, 3, 1, // left side
0, 2, 3, // right side
1, 3, 2}; // bottom
Glenableclientstate (gl_vertex_array );
Glableclientstate (gl_color_array );
Glvertexpointer (3, gl_float, 0, fpyramidsizedatas );
Glcolorpointer (3, gl_float, 0, fpyramidcolors );
Glpolygonmode (gl_front, gl_fill );
Glpolygonmode (gl_back, gl_line );
For (INT I = 0; I <4; ++ I)
{
Gldrawelements (gl_triangles, 3, gl_unsigned_byte, ubyindices + I * 3 );
}
}
This is a relatively normal triangular cone display effect. The original vertex sequence is commented out, and the new direction is correct. You can compare it, the original order of the left side and the bottom side is wrong. You can also try to run the problematic code. The result is that you can see the back on the front, when you move to the left side and the bottom side, you can see that it is blank -_-! It can be used as an effect to implement the container, but if you really want to display it, it will be done without adding vertex data ........
To save space, only key clips are posted. For the complete source code, see the 2009-10-25/glpolygonface directory of the source code of my blog. For more information about obtaining the complete source code of my blog, see the article.
Polygon surface removal
In addition, in fact, we have specified the back to draw a contour (gl_line), but since it is the back, why do we have to outline it? It can be completely eliminated. glcullface does this.
OpenGL Reference Manual
:
Glcullface-specify whether front-or back-facing facets can be culled
C Specification
Void glcullface (glenum mode );
Parameters
Mode
Specifies whether front-or back-facets are candidates for culling.
Symbolic Constants
Gl_front, gl_back, and gl_front_and_back are accepted.
The initial value is gl_back.
Since the back is specified, this function is very simple to use. It is nothing more than calling glcullface (gl_back) to remove the back polygon (although you can remove the front or all of them ), in addition, you need to use glable (gl_cull_face) to enable the removal function when removing objects. For speed, OpenGL is usually disabled by default, and we are also used to it. The code to be added is actually simple:
// Starts OpenGL initialization.
Void sceneinit (int w, int H)
{
Glenum err = glewinit ();
If (Err! = Glew_ OK)
{
MessageBox (null, _ T ("error"), _ T ("glew init failed."), mb_ OK );
Exit (-1 );
}
Glclearcolor (0.0, 0.0, 0.0, 0.0 );
Glable (gl_cull_face );
Glcullface (gl_back );
}
However, it should be noted that after the backend is removed, the backend needs to be re-rendered when the angle of view is switched to the front of the back, which is less efficient. In fact, when such a simple program does not enable backend removal, the conversion from the front to the back is very smooth. After it is enabled, the conversion will be obviously slow, however, the advantage is that resources are not occupied when the backend is not displayed. If it is enabled or not, you can only check the situation.
In order to save space, only key clips are posted. For the complete source code, see the 2009-10-25/glcullface directory of the source code of my blog. For more information about how to obtain the complete source code of the blog, see the article.
References
1. OpenGL Reference Manual
, OpenGL Reference Manual
2. OpenGL
OpenGL programming guide
), Dave shreiner, Mason Woo, Jackie neider, Tom Davis
Xu Bo, Mechanical Industry Press
3. nehe OpenGL tutorials, In the http://nehe.gamedev.net/
You can find the tutorials and related code to download. (The PDF version of the tutorials is available) nehe also developed an object-oriented framework. As a demo program, this framework is very suitable. There are also Chinese Versions
Take all the necessary information.
4. OpenGL getting started, by eastcowboy, this is a good tutorial I have found on the Internet. It is quite complete and popular. This is the first address: http://bbs.pfan.cn/post-184355.html
In this series, the next article "Win32 OpenGL programming (8) 3D model transformation and its Combined Application
"
Other articles in this OpenGL Series
1.
Win32 OpenGL programming (1) steps required for OpenGL programming under Win32
"
2. Win32 OpenGL programming (2) searching for missing OpenGL functions
"
3. Win32 OpenGL programming (3) Basic Elements (points, straight lines, polygon)
"
4. Win32 OpenGL programming (4) 2D graphics BASICS (advanced knowledge of color and coordinate systems)
"
5. Win32 OpenGL programming (5) vertices Array
"
6. Win32 OpenGL programming (6) entering the 3D world
"
Application Example: Win32 OpenGL 2D programming series -- drawing of jigsaw puzzle
"
Complete source code retrieval instructions
Due to space limitations, this article generally only posts the main focus of the Code, the full version of the Code with a project (or makefile) (if any) can be downloaded in Google code using mercurial. The article is stored in different directories on the date published by the blog post. Use mercurial to clone the following database:
Https://blog-sample-code.jtianling.googlecode.com/hg/
For how to use mercurial, see Introduction and brief introduction to the distributed and next-generation version control system mercurial.
"
If you only want to browse all the code, you can go to Google Code to view it. the following URL:
Http://code.google.com/p/jtianling/source/browse? Repo = blog-Sample-code
The author of the original article retains the copyright reprinted. Please indicate the original author and give a link
Write by nine days Yan Ling (jtianling) -- blog.csdn.net/vagrxie