NeHe_OpenGL _ Lesson 9 moving images in 3D space

Source: Internet
Author: User
Tags ranges

Http://52coding.com/nehe-3d-space-picture-moving

I changed it to the wsad control on the keyboard. I haven't learned OpenGL for many days and forgot how to use specialKeyboard. Press the t key to enable the flashing effect (I feel a little brighter)

Download the code (do not pay attention to modifying the points. This requires 1 point)

# Include "stdafx. h" # define glu_disable_atexit_hack # include "glaux. h" // the header file of the GLaux library # include "glut. h" // The following lines are newly added. Twinkle and tp are Boolean variables, indicating that they can only be set to TRUE or FALSE. Twinkle is used to track whether/* the flickering effect is enabled. Tp is used to check whether the 'T' key is pressed or released. (tp = TRUE when pressed, tp = FALSE when released ). */BOOL twinkle; // the flickering star BOOL tp; // is 'T' pressed? // Num tracks the number of stars on the screen. This number is defined as a constant. This means that it cannot be modified in future code. This is because you cannot redefine an array. Therefore, if we define a number/group of 50 stars and then increase num to 51, the "CKER: array out of bounds" error will occur 』. However, you can (or only) modify the number on this/* line at will. However, do not change the num value later unless you want to see a disaster. */Const int num = 50; // number of stars drawn/* create a structure. The word structure sounds a little scary, but not actually. A structure uses a set of simple types of data (and variables) to express a large combination of similar data. We know that we are keeping track of the stars. You can see that the seventh row below is stars, and each star has three integer color values. The third row contains three integers: int r, g, and B. A red (r), a green (g), and a blue (B ). in addition, each star is different from the center of the screen, and can be an angle of any 360 degrees from the center of the screen. If you look at the fourth row below, we will find that we use a floating point number called dist to keep track of the distance. the fifth line uses a floating point number called angle to keep track of the angle value of the stars. Therefore, we use a set of data to describe the color, distance, and angle of the stars on the screen. Unfortunately, we track more than one star. However, you only need to create an array star instead of creating 50 red values, 50 green values, 50 Blue values, 50 distance values, and 50 angle values. Each element of the star array is of the stars type, which stores all the data describing the stars. The star array is created in the eighth row below. The eighth line looks like this: stars star [num]. The array type is stars structure. The array can store information of all stars structures. The array name is star. The array size is [num]. Elements in the stars structure are stored in the array. the trace structure elements are much easier than the variables separated by the tracing. however, this is also very stupid, because we cannot change the constant num to increase or decrease the number of stars. */Typedef struct // create a structure for the stars {int r, g, B; // The GLfloat dist color of the stars; // The distance from the stars to the center GLfloat angle; // The angle of the current star} stars; // The structure is named starsstars star [num]; // use the 'stars' structure to generate a 'start' array containing 'num' elements/* Next we will set several tracking variables: the distance variable (zoom) between the stars and the observer ), the angle (tilt) of the stars we see and the variable spin that rotates the flickering stars around the Z axis. The loop variable is used to draw 50 stars. Texture [1] is used to store a black-and-white texture. If you need more textures, you should increase the size of the texture array to the number of textures you decide to use. */GLfloat zoom =-15.0f; // The distance between the stars and the observer GLfloat tilt = 90.0f; // GLfloat spin of the stars; // The rotation GLuint loop of the flickering stars; // global Loop variable GLuint texture [1]; // store a texture/* The code above is the code we use to load the texture. I don't want to explain this code in detail. This is exactly the same as the code we used in Lesson 6, 7, and 8. The uploaded map is star.bmp. Here we use glGenTextures (1, & texture [0]) to generate a texture. The texture is linearly filtered. */AUX_RGBImageRec * LoadBMP (char * Filename) // load the bitmap FILE {File * FILE = NULL; // File handle if (! Filename) // confirm that the file name {printf ("can't open! \ N "); return NULL; // if no return is NULL} File = fopen (Filename," r "); // check whether the File exists if (File) // does the file exist? {Fclose (File); // close the File handle return auxDIBImageLoad (Filename); // load the bitmap and return the pointer} return NULL; // If loading fails, return NULL}/* The code below (call the code above) loads the bitmap and converts it to a texture. The variable is used to track whether the texture has been loaded and created. */Int LoadGLTextures () // load the bitmap and convert it to the texture {int Status = FALSE; // Status Indicator AUX_RGBImageRec * TextureImage = new AUX_RGBImageRec; // allocate the storage space memset (TextureImage, 0, sizeof (void *) * 1) for the texture; // set the pointer to NULL // load the bitmap, and check the error, if the bitmap file is not found, exit if (TextureImage = LoadBMP ("maid") {Status = TRUE; // set Status to TRUEglGenTextures (1, & texture [0]); // create a texture // create a linear filtered texture glBindTexture (GL_TEXTURE_2D, texture [0]); glTexParameteri (GL_TEXTURE_2D, GL _ TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri (latency, latency, GL_LINEAR); glTexImage2D (latency, 0, 3, TextureImage-> sizeX, TextureImage-> sizeY, 0, GL_RGB, latency, textureImage-> data);} else {printf ("failed texture \ n"); return FALSE;} if (TextureImage) // if the texture exists {if (TextureImage-> data) // If the texture image contains {free (TextureImage-> data); // release the memory occupied by the texture image} free (TextureImage); // release the image structure} Return Status; // return Status value}/* now sets the OpenGL rendering mode. Here we do not plan to use deep testing. If you use the code in Lesson 1, check whether glDepthFunc (GL_LEQUAL); and glable (GL_DEPTH_TEST); are removed. Otherwise, the effect you see will be messy. Texture ing is used here, so make sure you have added the code that is not included in the first lesson. You will notice that we have enabled texture ing through blending. [Why Don't I need a deep test?] */int InitGL (GLvoid) // All OpenGL settings are started here {if (! LoadGLTextures () // call the texture loading subroutine {return FALSE; // if not loaded, return FALSE} GL_TEXTURE_2D; // enable texture ing glShadeModel (GL_SMOOTH ); // enable the shadow smooth glClearColor (0.0f, 0.0f, 0.0f, 0.5f); // The black background glClearDepth (1.0f); // sets the depth cache glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST ); // real fine-grained perspective correction glBlendFunc (GL_SRC_ALPHA, GL_ONE); // set the color mixing function to achieve the translucent Effect of GL_BLEND; // enable the color mixing function. * The following is the new code. Set the start angle, distance, and color of each star. You will notice how easy it is to modify the structure attributes. All 50 stars are cyclically set. All we need to do to change the angle of star [1] is star [1]. angle = {A value}; that's that simple! */For (loop = 0; loop <num; loop ++) // create a loop to set all stars {star [loop]. angle = 0.0f; // all stars start from a zero angle./* the distance between the stars in the loop and the center is to divide the value of the loop by the total number of stars and multiply the value by 5.0f. Basically, this makes the next star a little farther away from the center than the previous one. In this way, when the loop is 50 (the last star), the loop divided by num is exactly 1.0f. Multiply by 5.0f because 1.0f * 5.0f is 5.0f. 「 CKER: Nonsense! How is this foreigner like Kong Yiji! :) "5.0f is very close to the screen edge. I don't want stars to fly out of the screen. 5.0f is the best choice. Of course, if you set the scene to more in-depth on the screen, you may be able to use a value greater than 5.0f, but the stars look smaller (because of perspective ). You will also notice that the color of each star ranges from 0 ~ A random number between 255. You may wonder why the color value range here is not OpenGL's usual 0.0f ~ Between 1.0f. The color setting function we use here is glColor4ub, rather than the previous glColor4f. Ub indicates that the parameter is of the Unsigned Byte type. The value range of a byte is 0 ~ 255. Here, using the byte value to obtain a random integer seems easier than taking a random number at a floating point. */Star [loop]. dist = (float (loop)/num) * 5.0f; // calculate the distance from the star to the center. r = rand () % 256; // set the random Red star [loop] for star [loop]. g = rand () % 256; // set the random Red star [loop] for star [loop]. B = rand () % 256; // set random red weight for star [loop]} return TRUE; // Initialize all OK}/* the code for Resize is the same, now let's transfer the drawing code. If you use the code of Lesson 1 and delete the old DrawGLScene code, just copy the following code. In fact, there are only two lines of code in the first lesson, so there is not much to delete. */Void DrawGLScene (GLvoid) // This process includes all the drawing code {glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear the screen and depth cache glBindTexture (GL_TEXTURE_2D, texture [0]); // select the texture for (loop = 0; loop <num; loop ++) // cyclically set all stars {glLoadIdentity (); // reset the model observation matrix glTranslatef (0.0f, 0.0f, zoom) before drawing each star; // go deep into the glRotatef (tilt, 1.0f, 0.0f, 0.0f) on the screen ); // tilt angle/* Now let's move the stars. The stars start at the center of the screen. The first thing we need to do is to rotate the scenario along the Y axis. If we rotate for 90 degrees, the X axis is no longer from left to right, and it will go out of the screen. For example. Suppose you are standing in the middle of the house. Suppose the wall on the left is "-x", the wall on the front is "-z", and the wall on the right is "+ x". The wall on the back is "+ z. Add the entire house and turn right 90 degrees, but you are not moving, then the front wall will be-x instead of-z. All other walls also move. -Z appears on the right, + z appears on the left, and + x appears on your back. Nervous system disorder? Through the rotation scenario, we changed the direction of the x and z planes. The second line of code moves a positive value along the X axis. Usually, the positive value on the X axis represents moving to the right side of the screen (that is, the normal positive value on the X axis), but because we rotate the coordinate system around the Y axis, the positive value of the X axis can be any direction. If we turn to 180 degrees, the image is reversed on the left and right of the screen. Therefore, when we move forward along the x axis, it may be left, right, forward or backward. */GlRotatef (star [loop]. angle, 0.0f, 1.0f, 0.0f); // rotate to the angle glTranslatef (star [loop] of the currently painted stars. dist, 0.0f, 0.0f); // code that moves forward along the X axis/* followed by tips. A star is actually a plane texture. Now you have drawn a quadrilateral in the center of the screen and attached the texture, which looks good. Everything is as you think. However, when you convert the texture along the Y axis to 90 degrees, there are only two sides on the right and left to you on the screen. It looks like a thin line. This is not what we want. We want the stars to always face us, regardless of how the screen is rotated or skewed. We achieve this by offsetting any rotation of the stars before drawing them. You can use reverse order to offset the rotation. When we tilt the screen, we actually rotate the stars from the current angle. Through Reverse Order, We "reverse rotate" the stars from the current angle. It is to rotate the stars with the negative value of the current angle. That is to say, if we rotate the stars for 10 degrees, we rotate them for another 10 degrees so that the stars can face the screen again on that axis. The first line below offsets the Rotation along the Y axis. Then, we also need to offset the screen skew along the X axis. To do this, we only need to rotate the screen-tilt. After the rotation of x and Y axes is offset, the stars face us completely. */GlRotatef (-star [loop]. angle, 0.0f, 1.0f, 0.0f); // cancel the glRotatef (-tilt, 1.0f, 0.0f, 0.0f) of the current star angle; // cancel the screen tilt/* If twinkle is TRUE, first draw a non-rotating star on the screen: subtract the total number of stars (num) from the current number of Stars (loop) And then subtract 1, to extract the different colors of each star (this is because the cycle ranges from 0 to num-1 ). For example, when the result is 10, we use the color of star 10. In this way, the colors of adjacent stars are always different. This is not a good method, but it is very effective. The last value is the alpha channel component. The smaller the value, the darker the star. Because twinkle is enabled, each star is finally drawn twice. The program runs slowly, depending on the performance of your machine. However, the colors of the stars that are drawn twice are combined to produce great results. At the same time, because the first time the stars are not rotated, the stars after twinkle is enabled seem to have an animation effect. (If you cannot understand it here, check the running effect of the program .) It is worth noting that it is easy to color textures. Although the texture itself is black and white, the texture will become any color we choose before drawing it. In addition, it is worth noting that the color value we use here is byte type, rather than the usual floating point number. This is even true for alpha-channel components. */If (twinkle) // enable the flickering effect {// use a byte value to specify a color glColor4ub (star [(num-loop)-1]. r, star [(num-loop)-1]. g, star [(num-loop)-1]. b, 255); glBegin (GL_QUADS); // start to draw the glTexCoord2f (0.0f, 0.0f) mapped by texture; glVertex3f (-1.0f,-1.0f, 0.0f ); random (1.0f, 0.0f); glVertex3f (1.0f,-1.0f, 0.0f); random (1.0f, 1.0f); glVertex3f (1.0f, 1.0f, 0.0f); glTexCoord2f (0.0f, 1.0f ); glVertex3f (-1.0f, 1.0f, 0.0f); glEnd (); // The End Of The quadrilateral plot} // Now draw the second time of the stars. The only difference from the previous Code is that the stars will be drawn this time, and the stars will rotate around the z axis this time. GlRotatef (spin, 0.0f, 0.0f, 1.0f); // rotate the stars around the z axis. // use a byte value to specify a color glColor4ub (star [loop]. r, star [loop]. g, star [loop]. b, 255); glBegin (GL_QUADS); // start to draw the glTexCoord2f (0.0f, 0.0f) mapped by texture; glVertex3f (-1.0f,-1.0f, 0.0f ); random (1.0f, 0.0f); glVertex3f (1.0f,-1.0f, 0.0f); random (1.0f, 1.0f); glVertex3f (1.0f, 1.0f, 0.0f); glTexCoord2f (0.0f, 1.0f ); glVertex3f (-1.0f, 1.0f, 0.0f); glEnd ();/* the following code indicates the motion of the stars. We increase the spin value to rotate all the stars (in public rotation ). Then, the rotation angle of each star is increased by loop/num. This allows the stars farther away from the center to become faster. At last, the distance between each star and the center of the screen is reduced. In this way, the stars seem to be constantly sucked into the center of the screen. */Spin + = 0.01f; // star [loop]. angle + = float (loop)/num; // Changes the Rotation angle of the star [loop]. dist-= 0.01f; // change the distance from the stars to the center/* then check whether the stars have touched the center of the screen. When a star hits the center of the screen, we assign it a new color and then move 5 units away. The star will embark on its journey to return to the center of the screen. */If (star [loop]. dist <0.0f) // does the star arrive at the center? {star [loop]. dist + = 5.0f; // move 5 units out of the cluster star [loop]. r = rand () % 256; // assign a new red star [loop]. g = rand () % 256; // assign a new green component star [loop]. B = rand () % 256; // assign a new blue weight} glFlush (); // you must add this sentence printf (". ");} void ReSizeFunc (int width, int height) {glViewport (0, 0, width, height); glMatrixMode (GL_PROJECTION); glLoadIdentity (); gluPerspective (45, width/height, 0.1, 100); glMatrixMode (GL_MODELVIEW); glLoadI Dentity ();} void KeyBoardFunc (unsigned char key, int x, int y) {printf ("% x \ n", key); if (VK_ESCAPE = key) {exit (0);}/* Now let's add the monitoring keyboard code. Move down to WinMain (). Find a row of SwapBuffers (hDC. We will add the keyboard monitoring code behind this line. The code checks whether the T key is pressed. If the T key is pressed and released again, the code in the if block will be executed. If twinkle is set to FALSE, it is set to TRUE. And vice versa. As long as the T key is pressed, tp becomes TRUE. This prevents code in the block from being repeatedly executed if you keep pressing the T key. */If ('T' = key) | ('T' = key ))&&! Tp) // whether the T key has been pressed and the tp value is FALSE {tp = TRUE; // If so, set tp to TRUEtwinkle =! Twinkle; // flip the value of twinkle} // the following code checks whether the T key is released. If yes, make tp = FALSE. Unless the value of tp is FALSE, NO/* occurs when the T key is pressed. So this line of code is very important. */If ('T '! = Key) & ('T '! = Key) // has the T key been released? {Tp = FALSE; // If yes, tp is FALSE}/* check whether the top or bottom arrow keys are pressed for the remaining code. */If ('W' = key) // has the arrow key been pressed? {Tilt-= 0.5f; // the screen is tilted up.} if ('s '= key) // has the arrow key been pressed? {Tilt + = 0.5f; // screen tilt down} if ('A' = key) // has the page flip key been pressed? {zoom-= 0.2f; // zoom out} if ('D' = key) // press the flip-down key? {Zoom + = 0.2f; // zoom in} DrawGLScene ();} int main (int argc, char * argv []) {gluinit (& argc, argv ); fig ); glukeyboardfunc (KeyBoardFunc); InitGL (); glumainloop (); return 0 ;}

Flashing effect not enabled:

After flashing is Enabled:

 

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.