Nehe OpenGL tutorial (25)

Source: Internet
Author: User

Lesson 1

Deformation and loading of 3D objects from a file:

In this lesson, you will learn how to load 3D models from files and smoothly transform from one model to another.

Welcome to this exciting lesson. In this lesson, we will introduce the deformation of the model. Note that each model must have the same vertex to correspond one to one and apply deformation.
In this lesson, we also want to teach you how to read model data from a file.
The start part of the file is the same as the previous one, with no changes.


Let's add several rotation variables to record the rotation information. Use CX, Cy, and CZ to set the position of the object on the screen.
The variable key is used to record the current model, and the step is used to set the intermediate steps between adjacent deformation. For example, if step is 200, it takes 200 times to change one object to another.
Finally, we use a variable to set whether to use deformation.

Rotation Angle of glfloat xrot, yrot, Zrt, // X, Y & Z axis
Xspeed, yspeed, zspeed, // X, Y & Z axis rotation speed
CX, Cy, CZ =-15; // Object Location

Int key = 1; // Object ID
Int step = 0, steps = 200; // Number of transformed steps
Bool morph = false; // whether to use Deformation


The following structure defines a three-dimensional Vertex

Typedef struct
{
Float x, y, z;
} Vertex;

The following structure uses vertices to describe a 3D object

Typedef struct // object structure
{
Int Verts; // Number of vertices in an object
Vertex * points; // pointer containing vertex data
} Object;

Maxver is used to record the maximum number of vertices in each object. If one object uses five vertices and the other uses 20 vertices, the number of vertices of the object is 20.
Then, four model objects are defined, and the intermediate state of the adjacent model deformation is saved in helper. Sour stores the original model object and DEST stores the model object to be deformed.

Int maxver; // The maximum number of vertices.
Object morph1, morph2, morph3, morph4, // Our four objects
Helper, * sour, * DEST; // help object, original object, and target object


The wndproc () function has not changed.


The following functions are used to allocate memory space for the model to save vertex data.

Void objallocate (Object * k, int N)
{
K-> points = (vertex *) malloc (sizeof (vertex) * n); // allocate memory space for n vertices
}

The following functions are used to release the memory space allocated for the model.

Void objfree (Object * K)
{
Free (k-> points );
}


The following code is used to read a row in a file.
We use a loop to read a maximum of 255 characters. When the '/N' carriage return occurs, we stop reading and return immediately.

Void readstr (File * F, char * string) // read a line of Characters
{
Do
{
Fgets (string, 255, f); // read a maximum of 255 characters
} While (string [0] = '/') | (string [0] = '/N'); // stops reading when a carriage return occurs.
Return; // return
}


The following code loads a model file, allocates memory for the model, and stores the data.

Void objload (char * Name, object * k) // load a model from a file
{
Int ver; // Number of saved vertices
Float RX, Ry, Rz; // Save the model location
File * filein; // The opened file handle.
Char oneline [2, 255]; // save 255 characters

Filein = fopen (name, "RT"); // open a text file for reading

Readstr (filein, oneline); // read a line of text
Sscanf (oneline, "vertices: % d/N", & Ver); // search for the string "vertices:" And save the vertex count in the ver variable.
K-> Verts = ver; // sets the number of vertices of the model.
Objallocate (K, Ver); // allocate memory for model data


The following loop reads the data of each row (I .e. each vertex) and saves it To the memory? /TD>

For (INT I = 0; I <ver; I ++) // loops all vertices
{
Readstr (filein, oneline); // read a row of data
Sscanf (oneline, "% F", & RX, & ry, & rZ); // store vertex data in RX, Ry, and Rz

K-> points [I]. x = RX; // Save the X coordinates of the current vertex.
K-> points [I]. Y = ry; // Save the Y coordinate of the current vertex.
K-> points [I]. z = RZ; // Save the zcoordinate of the current vertex
}
Fclose (filein); // close the file

If (ver> maxver) maxver = ver; // records the maximum number of vertices.
}

The following function calculates the displacement of each transformation of vertex I Based on the set interval.

Vertex calculate (int I) // calculates the displacement of each transformation of vertex I
{
Vertex;
A. X = (sour-> points [I]. X-Dest-> points [I]. X)/steps;
A. Y = (sour-> points [I]. Y-Dest-> points [I]. Y)/steps;
A. z = (sour-> points [I]. Z-Dest-> points [I]. Z)/steps;
Return;
}

The resizeglscene () function has not changed.

Glvoid resizeglscene (glsizei width, glsizei height)


The following function completes initialization and sets the hybrid mode to translucent.

Int initgl (glvoid)
{
Glblendfunc (gl_src_alpha, gl_one); // sets the semi-transparent hybrid mode.
Glclearcolor (0.0f, 0.0f, 0.0f, 0.0f); // sets the clear color to black.
Glcleardepth (1.0); // you can specify a value of 1 in the deep cache.
Gldepthfunc (gl_less); // sets the deep test function.
Glable (gl_depth_test); // enable deep Test
Glshademodel (gl_smooth); // sets the color mode to smooth color.
Glhint (gl_perspective_correction_hint, gl_nicest );

The following code loads our model object

Maxver = 0; // The maximum number of initialized vertices is 0.
Objload ("Data/sphere.txt", & morph1); // load the Ball Model
Objload ("Data/torus.txt", & morph2); // load the Ring Model
Objload ("Data/tube.txt", & morph3); // load the cube Model


The fourth model is not read from the file. We randomly generate model points between (-7,-7,-7)-(7, 7, it has 486 vertices like the model we load.

Objallocate (& morph4, 486); // allocate memory resources for the fourth model
For (INT I = 0; I <486; I ++) // set 486 vertices at random.
{
Morph4.points [I]. x = (float) (RAND () % 14000)/1000)-7;
Morph4.points [I]. Y = (float) (RAND () % 14000)/1000)-7;
Morph4.points [I]. z = (float) (RAND () % 14000)/1000)-7;
}


Initialize the intermediate model as a sphere and set both the original and target models as the sphere.

Objload ("Data/sphere.txt", & helper );
Sour = DEST = & morph1;

Return true; // Initialization is complete, and a success is returned.
}


The following is the specific drawing code. We will first set the model changes so that we can better observe them.

Void drawglscene (glvoid)
{
Glclear (gl_color_buffer_bit | gl_depth_buffer_bit); // clear the cache
Glloadidentity (); // reset the model transformation matrix
Gltranslatef (CX, Cy, CZ); // pan and rotate
Glrotatef (xrot, 1, 0, 0 );
Glrotatef (yrot, 0, 0 );
Glrotatef (Zrt, 0, 0, 1 );

Xrot + = xspeed; yrot + = yspeed; Zrt + = zspeed; // increase the rotation angle according to the rotation speed.

Glfloat Tx, Ty, TZ; // temporary vertex variable
Vertex Q; // Save the temporary vertex of the intermediate Computation

Next we will plot the points in the model. If deformation is enabled, the intermediate process points of deformation will be calculated.

Glbegin (gl_points); // starts point painting.
For (INT I = 0; I <morph1.verts; I ++) // draw each vertex in Model 1 cyclically
{
If (morph) q = calculate (I); else Q. x = Q. Y = Q. z = 0; // If deformation is enabled, the intermediate model is calculated.
Helper. Points [I]. X-= Q. X;
Helper. Points [I]. Y-= Q. Y;
Helper. Points [I]. Z-= Q. Z;
Tx = helper. Points [I]. X; // Save the calculation result to the X, Y, and Z variables.
Ty = helper. Points [I]. Y;
TZ = helper. Points [I]. Z;

To make the animation smooth, we have drawn three intermediate state points. Change the deformation process from blue-green to blue.

Glcolor3f (, 1); // set the color
Glvertex3f (TX, Ty, Tz); // draw a vertex
Glcolor3f (0, 0.5f, 1); // change the color to blue.
TX-= 2 * q. X; ty-= 2 * q. Y; ty-= 2 * q. Y; // If deformation is enabled, draw the vertex after two steps.
Glvertex3f (TX, Ty, Tz );
Glcolor3f (, 1); // blue the color
TX-= 2 * q. X; ty-= 2 * q. Y; ty-= 2 * q. Y; // If deformation is enabled, draw the vertex after two steps.
Glvertex3f (TX, Ty, Tz );
}
Glend (); // draw end


If deformation is enabled, the incremental step parameter is added and the next vertex is drawn.

// If deformation is enabled, the number of deformation steps is increased.
If (morph & step <= steps) Step ++; else {morph = false; sour = DEST; step = 0 ;}
Return true; // everything is OK
}


The killglwindow () function is basically unchanged, but the code for releasing 5 model memory is added.

Objfree (& morph1); // release Model 1 memory
Objfree (& morph2); // release Model 2 memory
Objfree (& morph3); // release model 3 memory
Objfree (& morph4); // release model 4 Memory
Objfree (& helper); // release model 5 memory


The createglwindow () function has not changed.

Bool createglwindow ()

Lresult callback wndproc ()


In the winmain () function, we added some keyboard-controlled functions.

If (Keys [vk_prior]) // whether the Pageup key is pressed
Zspeed + = 0.01f; // press to increase the rotation speed around the Z axis

If (Keys [vk_next]) // whether the Pagedown key is pressed
Zspeed-= 0.01f; // press to reduce the rotation speed around the Z axis

If (Keys [vk_down]) // whether the downstream key is pressed
Xspeed + = 0.01f; // press it to increase the rotation speed around the X axis.

If (Keys [vk_up]) // whether the up arrow key is pressed
Xspeed-= 0.01f; // press to reduce the rotation speed around the X axis

If (Keys [vk_right]) // whether the right arrow key is pressed
Yspeed + = 0.01f; // press to increase the rotation speed along the Y axis

If (Keys [vk_left]) // whether the left arrow key is pressed
Yspeed-= 0.01f; // press to reduce the rotation speed along the Y axis
If (Keys ['q']) // whether the Q key is pressed
CZ-= 0.01f; // it moves to the screen

If (Keys ['Z']) // whether the z key is pressed
CZ + = 0.01f; // it moves out of the screen

If (Keys ['W']) // whether the W key is pressed
Cy + = 0.01f; // yes, it is moved up

If (Keys ['s ']) // whether the key is pressed
Cy-= 0.01f; // Yes, move down

If (Keys ['D']) // whether the key D is pressed
Cx + = 0.01f; // Yes, move to the right

If (Keys ['a']) // whether the key A is pressed
CX-= 0.01f; // yes, it is moved to the left

Keys 1, 2, 3, and 4 are used to set the target model for deformation.

If (Keys ['1'] & (key! = 1 )&&! Morph) // if 1 is pressed, it is transformed to model 1
{
Key = 1;
Morph = true;
DeST = & morph1;
}
If (Keys ['2'] & (key! = 2 )&&! Morph) // If 2 is pressed, it is transformed to model 1
{
Key = 2;
Morph = true;
DeST = & morph2;
}
If (Keys ['3'] & (key! = 3 )&&! Morph) // If 3 is pressed, it is transformed to model 1
{
Key = 3;
Morph = true;
DeST = & morph3;
}
If (Keys ['4'] & (key! = 4 )&&! Morph) // If 4 is pressed, it is transformed to model 1
{
Key = 4;
Morph = true;
DeST = & morph4;
}


I hope you like this tutorial. I believe you have learned deformation animation.
Piotr ciesak code is very novel. I hope you can learn how to load 3D models from files through this tutorial.
 

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.