Выбрать главу

 glRotatef(xrot,1,0,0); // Rotate On The X Axis By xrot

 glRotatef(yrot,0,1,0); // Rotate On The Y Axis By yrot

 glRotatef(zrot,0,0,1); // Rotate On The Z Axis By zrot

 xrot+=xspeed; yrot+=yspeed; zrot+=zspeed; // Increase xrot,yrot & zrot by xspeed, yspeed & zspeed

 GLfloat tx,ty,tz; // Temp X, Y & Z Variables

 VERTEX q; // Holds Returned Calculated Values For One Vertex

Now we draw the points and do our calculations if morphing is enabled. glBegin(GL_POINTS) tells OpenGL that each vertex that we specify will be drawn as a point on the screen.

We create a loop to loop through all the vertices. You could use maxver, but because every object has the same number of vertices we'll use morph1.verts.

Inside the loop we check to see if morph is TRUE. If it is we calculate the movement for the current point (i). q.x, q.y and q.z will hold the results. If morph is false, q.x, q.y and q.z will be set to 0 (preventing movement).

the points in the helper object are moved based on the results of we got from calculate(i). (remember earlier that we calculated a point would have to move 0.1 unit to make it from 40 to 20 in 200 steps).

We adjust the each points value on the x, y and z axis by subtracting the number of units to move from helper.

The new helper point is stored in tx, ty and tz. (t{x/y/z}=helper.points[i].{x/y/z}).

 glBegin(GL_POINTS); // Begin Drawing Points

  for(int i=0;i<morph1.verts;i++) // Loop Through All The Verts Of morph1 (All Objects Have

  { // The Same Amount Of Verts For Simplicity, Could Use maxver Also)

   if (morph) q=calculate(i);

   else q.x=q.y=q.z=0; // If morph Is True Calculate Movement Otherwise Movement=0

   helper.points[i].x-=q.x; // Subtract q.x Units From helper.points[i].x (Move On X Axis)

   helper.points[i].y-=q.y; // Subtract q.y Units From helper.points[i].y (Move On Y Axis)

   helper.points[i].z-=q.z; // Subtract q.z Units From helper.points[i].z (Move On Z Axis)

   tx=helper.points[i].x; // Make Temp X Variable Equal To Helper's X Variable

   ty=helper.points[i].y; // Make Temp Y Variable Equal To Helper's Y Variable

   tz=helper.points[i].z; // Make Temp Z Variable Equal To Helper's Z Variable

Now that we have the new position calculated it's time to draw our points. We set the color to a bright bluish color, and the draw the first point with glVertex3f(tx,ty,tz). This draws a point at the newly calculated position.

We then darken the color a little, and move 2 steps in the direction we just calculated instead of one. This moves the point to the newly calculated position, and then moves it again in the same direction. So if it was travelling left at 0.1 units, the next dot would be at 0.2 units. After calculating 2 positions ahead we draw the second point.

Finally we set the color to dark blue, and calculate even further ahead. This time using our example we would move 0.4 units to the left instead of 0.1 or 0.2. The end result is a little tail of particles following as the dots move. With blending, this creates a pretty cool effect!

glEnd() tells OpenGL we are done drawing points.

   glColor3f(0,1,1); // Set Color To A Bright Shade Of Off Blue

   glVertex3f(tx,ty,tz); // Draw A Point At The Current Temp Values (Vertex)

   glColor3f(0,0.5f,1); // Darken Color A Bit

   tx-=2*q.x; ty-=2*q.y; ty-=2*q.y; // Calculate Two Positions Ahead

   glVertex3f(tx,ty,tz); // Draw A Second Point At The Newly Calculate Position

   glColor3f(0,0,1); // Set Color To A Very Dark Blue

   tx-=2*q.x; ty-=2*q.y; ty-=2*q.y; // Calculate Two More Positions Ahead

   glVertex3f(tx,ty,tz); // Draw A Third Point At The Second New Position

  } // This Creates A Ghostly Tail As Points Move

 glEnd(); // Done Drawing Points

The last thing we do is check to see if morph is TRUE and step is less than steps (200). If step is less than 200, we increase step by 1.

If morph is false or step is greater than or equal to steps (200), morph is set to FALSE, the sour (source) object is set to equal the dest (destination) object, and step is set back to 0. This tells the program that morphing is not happening or it has just finished.

 // If We're Morphing And We Haven't Gone Through All 200 Steps Increase Our Step Counter

 // Otherwise Set Morphing To False, Make Source=Destination And Set The Step Counter Back To Zero.

 if (morph && step<=steps) step++;

 else {

  morph=FALSE;

  sour=dest;

  step=0;

 }

}

The KillGLWindow() code hasn't changed much. The only real difference is that we free all of the objects from memory before we kill the windows. This prevents memory leaks, and is good practice ;)

GLvoid KillGLWindow(GLvoid) // Properly Kill The Window {

 objfree(&morph1); // Jump To Code To Release morph1 Allocated Ram

 objfree(&morph2); // Jump To Code To Release morph2 Allocated Ram

 objfree(&morph3); // Jump To Code To Release morph3 Allocated Ram

 objfree(&morph4); // Jump To Code To Release morph4 Allocated Ram

 objfree(&helper); // Jump To Code To Release helper Allocated Ram

 if (fullscreen) // Are We In Fullscreen Mode?

 {

  ChangeDisplaySettings(NULL,0); // If So Switch Back To The Desktop

  ShowCursor(TRUE); // Show Mouse Pointer

 }

 if (hRC) // Do We Have A Rendering Context?

 {

  if (!wglMakeCurrent(NULL, NULL)) // Are We Able To Release The DC And RC Contexts?

  {

   MessageBox(NULL, "Release Of DC And RC Failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);

  }

  if (!wglDeleteContext(hRC)) // Are We Able To Delete The RC?

  {

   MessageBox(NULL, "Release Rendering Context Failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);

  }

  hRC=NULL; // Set RC To NULL

 }

 if (hDC && !ReleaseDC(hWnd, hDC)) // Are We Able To Release The DC

 {

  MessageBox(NULL, "Release Device Context Failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);

  hDC=NULL; // Set DC To NULL

 }

 if (hWnd && !DestroyWindow(hWnd)) // Are We Able To Destroy The Window?

 {

  MessageBox(NULL, "Could Not Release hWnd.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);

  hWnd=NULL; // Set hWnd To NULL

 }

 if (!UnregisterClass("OpenGL",hInstance)) // Are We Able To Unregister Class

 {

  MessageBox(NULL, "Could Not Unregister Class.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);

  hInstance=NULL; // Set hInstance To NULL

 }

}

The CreateGLWindow() and WndProc() code hasn't changed. So I'll skip over it.

BOOL CreateGLWindow() // Creates The GL Window