📄 main.cpp
字号:
//***********************************************************************//
// //
// - "Talk to me like I'm a 3 year old!" Programming Lessons - //
// //
// $Author: DigiBen digiben@gametutorials.com //
// //
// $Program: Bezier Curve //
// //
// $Description: Moves a sphere along a bezier curve //
// //
// $Date: 10/8/01 //
// //
//***********************************************************************//
// This is a compiler directive that includes libraries (For Visual Studio)
// You can manually include the libraries in the "Project->settings" menu under
// the "Link" tab.
#pragma comment(lib, "opengl32.lib")
#pragma comment(lib, "glu32.lib")
#include "main.h" // This includes our header file
bool g_bFullScreen = true; // Set full screen as default
HWND g_hWnd; // This is the handle for the window
RECT g_rRect; // This holds the window dimensions
HDC g_hDC; // General HDC - (handle to device context)
HGLRC g_hRC; // General OpenGL_DC - Our Rendering Context for OpenGL
HINSTANCE g_hInstance; // This holds the global hInstance for UnregisterClass() in DeInit()
//////////// *** NEW *** ////////// *** NEW *** ///////////// *** NEW *** ////////////////////
// This tutorial shows you how to create a bezier curve. This is a VERY handy
// bit of knowledge to have, especially as we see how popular curved surfaces
// in games are becoming (starting with Quake). Some examples of when we would
// use a curve is for Tunnels, camera movements, etc... To demonstrate using a bezier
// curve, we will create a sphere that we can use the RIGHT and LEFT arrow keys
// to move a across a rendered curve. Creating a bezier curve is simple, but
// the math at first can be intimidating. Basically, a bezier curve has at least
// 3 points. The first point is the starting point of the curve. The second point
// is the control point of the curve. A control point "controls" the arc of the curve.
// The third point is the end point of the curve. In this tutorial we will use 4 control
// points (including the start and end point). The first and last point will be where
// the curve starts and stops, and the middle 2 points will be used to shape the curve.
//
#define BALL_SPEED 0.02f // This is how fast our camera moves
#define MAX_STEPS 25.0f // This is the amount of steps we want to draw the curve
// We create a class that has an X, Y and Z. We will use this point class
// to store our XYZ points of the curve.
struct CVector3 // Remember, we use a C in front to show it's a class
{
public:
float x, y, z; // We just want a float for a X Y and Z.
};
float g_CurrentTime = 0.0f; // This is the current position of the sphere along the curve (0 to 1)
CVector3 g_vStartPoint = {-4, 0, 0}; // This is the starting point of the curve
CVector3 g_vControlPoint1 = {-2, 3, 2}; // This is the first control point of the curve
CVector3 g_vControlPoint2 = { 2, -3, -2}; // This is the second control point of the curve
CVector3 g_vEndPoint = { 4, 0, 0}; // This is the end point of the curve
//////////// *** NEW *** ////////// *** NEW *** ///////////// *** NEW *** ////////////////////
///////////////////////////////// INIT GAME WINDOW \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
/////
///// This function initializes the game window.
/////
///////////////////////////////// INIT GAME WINDOW \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
void Init(HWND hWnd)
{
g_hWnd = hWnd; // Assign the window handle to a global window handle
GetClientRect(g_hWnd, &g_rRect); // Assign the windows rectangle to a global RECT
InitializeOpenGL(g_rRect.right, g_rRect.bottom); // Init OpenGL with the global rect
//////////// *** NEW *** ////////// *** NEW *** ///////////// *** NEW *** ////////////////////
// Just to give the sphere more realism, we enable the default
// lights for shading. First we turn on a light, turn lighting on,
// then enable coloring. We need to enable color functions like glColor3f()
// since lighting is on. If we don't all objects will be white.
glEnable(GL_LIGHT0); // Turn on this light
glEnable(GL_LIGHTING); // Turn lighting on
glEnable(GL_COLOR_MATERIAL); // Since lighting is on, allow glColor*() functions
//////////// *** NEW *** ////////// *** NEW *** ///////////// *** NEW *** ////////////////////
}
///////////////////////////////// MAIN GAME LOOP \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
/////
///// This function Handles the main game loop
/////
///////////////////////////////// MAIN GAME LOOP \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
WPARAM MainLoop()
{
MSG msg;
bool bRedraw = false;
while(1) // Do our infinate loop
{ // Check if there was a message
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if(msg.message == WM_QUIT) // If the message wasnt to quit
break;
TranslateMessage(&msg); // Find out what the message does
DispatchMessage(&msg); // Execute the message
}
else // if there wasn't a message
{
RenderScene(); // Update the screen every frame
}
}
DeInit(); // Clean up and free all allocated memory
return(msg.wParam); // Return from the program
}
///////////////////////////////// POINT ON CURVE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
/////
///// This function returns an XYZ point along the curve, depending on t (0 to 1)
/////
///////////////////////////////// POINT ON CURVE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
CVector3 PointOnCurve(CVector3 p1, CVector3 p2, CVector3 p3, CVector3 p4, float t)
{
float var1, var2, var3;
CVector3 vPoint = {0.0f, 0.0f, 0.0f};
// Here is the juice of our tutorial. Below is the equation for a 4 control point
// bezier curve:
// B(t) = P1 * ( 1 - t )^3 + P2 * 3 * t * ( 1 - t )^2 + P3 * 3 * t^2 * ( 1 - t ) + P4 * t^3
// Yes I agree, this isn't the most intuitive equation, but it is pretty straight forward.
// If you got up to Trig, you will notice that this is a polynomial. That is what a curve is.
// "t" is the time from 0 to 1. You could also think of it as the distance along the
// curve, because that is really what it is. P1 - P4 are the 4 control points.
// They each have an (x, y, z) associated with them. You notice that there is a lot of
// (1 - t) 's? Well, to clean up our code we will try to contain some of these
// repetitions into variables. This helps our repeated computations as well.
// Store the (1 - t) in a variable because it is used frequently
var1 = 1 - t;
// Store the (1 - t)^3 into a variable to cut down computation and create clean code
var2 = var1 * var1 * var1;
// Store the t^3 in a variable to cut down computation and create clean code
var3 = t * t * t;
// Now that we have some computation cut down, we just follow the equation above.
// If you multiply and simplify the equation, you come up with what we have below.
// If you don't see how we came to here from the equation, multiply the equation
// out and it will become more clear. I don't intend to go into any more detail
// on the math of a bezier curve, because there are far better places out there
// with graphical displays and tons of examples. Look in our * Quick Notes *
// for an EXCELLENT web site that does just this. It derives everything and has
// excellent visuals. It's the best I have seen so far.
vPoint.x = var2*p1.x + 3*t*var1*var1*p2.x + 3*t*t*var1*p3.x + var3*p4.x;
vPoint.y = var2*p1.y + 3*t*var1*var1*p2.y + 3*t*t*var1*p3.y + var3*p4.y;
vPoint.z = var2*p1.z + 3*t*var1*var1*p2.z + 3*t*t*var1*p3.z + var3*p4.z;
// Now we should have the point on the curve, so let's return it.
return(vPoint);
}
///////////////////////////////// DRAW SPHERE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
/////
///// This function renders a sphere to a given XYZ and with a given radius
/////
///////////////////////////////// DRAW SPHERE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
void DrawSphere(float x, float y, float z, float radius)
{
// To use Quadrics, we need to create a new one first. This is done below.
// The GLUquadricObj type is defined with the GLU32 library and associated header file.
GLUquadricObj *pSphere = gluNewQuadric(); // Get a Quadric off the stack
// Let's put on a matrix so what ever we do it doesn't effect the rest of
// the objects we will display.
glPushMatrix(); // Push on a new matrix
glTranslatef(x, y, z); // Move the sphere to the desired (x, y, z)
// Draw the a sphere with a given radius and a width and height detail
// of 15 (15 by 15 is a good level of detail. The lower the detail the
// more jagged the sphere becomes, where the high the detail the more round it is.
gluSphere(pSphere, radius, 15, 15); // Draw the sphere with a radius of 0.2
glPopMatrix(); // Pop the current matrix
// Since we are done rendering the Quadric, we can free the object.
// gluDeleteQuadric() takes the object to be released. If you have a lot
// of Quadrics, you might not want to allocate and free them every frame.
gluDeleteQuadric(pSphere); // Free the quadric object
}
///////////////////////////////// RENDER SCENE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
/////
///// This function renders the entire scene.
/////
///////////////////////////////// RENDER SCENE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
void RenderScene()
{
//////////// *** NEW *** ////////// *** NEW *** ///////////// *** NEW *** ////////////////////
static float rotateY = 0.0f; // Create a static variable for rotation
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer
glLoadIdentity(); // Reset The matrix
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -