📄 lesson30.cpp
字号:
/*******************************************************************************/
/*********************************28/10/200*************************************/
/**********************Programmer: Dimitrios Christopoulos**********************/
/*
* Windows Frame Code Was Published By Jeff Molofee 2000
* Code Was Created By David Nikdel For NeHe Productions
* If You've Found This Code Useful, Please Let Me Know.
* Visit My Site At nehe.gamedev.net
*/
/*******************************************************************************/
#include <windows.h> // Header File For Windows
#include <math.h> // Header File For Math Library Routines
#include <stdio.h> // Header File For Standard I/O Routines
#include <stdlib.h> // Header File For Standard Library
#include <gl\gl.h> // Header File For The OpenGL32 Library
#include <gl\glu.h> // Header File For The GLu32 Library
#include "tvector.h"
#include "tmatrix.h"
#include "tray.h"
#include <mmsystem.h>
#include "image.h"
GLfloat spec[]={1.0, 1.0 ,1.0 ,1.0}; //sets specular highlight of balls
GLfloat posl[]={0,400,0,1}; //position of ligth source
GLfloat amb[]={0.2f, 0.2f, 0.2f ,1.0f}; //global ambient
GLfloat amb2[]={0.3f, 0.3f, 0.3f ,1.0f}; //ambient of lightsource
TVector dir(0,0,-10); //initial direction of camera
TVector pos(0,-50,1000); //initial position of camera
float camera_rotation=0; //holds rotation around the Y axis
TVector veloc(0.5,-0.1,0.5); //initial velocity of balls
TVector accel(0,-0.05,0); //acceleration ie. gravity of balls
TVector ArrayVel[10]; //holds velocity of balls
TVector ArrayPos[10]; //position of balls
TVector OldPos[10]; //old position of balls
int NrOfBalls; //sets the number of balls
double Time=0.6; //timestep of simulation
int hook_toball1=0, sounds=1; //hook camera on ball, and sound on/off
//Plane structure
struct Plane{
TVector _Position;
TVector _Normal;
};
//Cylinder structure
struct Cylinder{
TVector _Position;
TVector _Axis;
double _Radius;
};
//Explosion structure
struct Explosion{
TVector _Position;
float _Alpha;
float _Scale;
};
Plane pl1,pl2,pl3,pl4,pl5; //the 5 planes of the room
Cylinder cyl1,cyl2,cyl3; //the 2 cylinders of the room
GLUquadricObj *cylinder_obj; //Quadratic object to render the cylinders
GLuint texture[4], dlist; //stores texture objects and display list
Explosion ExplosionArray[20]; //holds max 20 explosions at once
//Perform Intersection tests with primitives
int TestIntersionPlane(const Plane& plane,const TVector& position,const TVector& direction, double& lamda, TVector& pNormal);
int TestIntersionCylinder(const Cylinder& cylinder,const TVector& position,const TVector& direction, double& lamda, TVector& pNormal,TVector& newposition);
void LoadGLTextures(); //Loads Texture Objects
void InitVars();
void idle();
HDC hDC=NULL; // Private GDI Device Context
HGLRC hRC=NULL; // Permanent Rendering Context
HWND hWnd=NULL; // Holds Our Window Handle
HINSTANCE hInstance; // Holds The Instance Of The Application
DEVMODE DMsaved; // Saves the previous screen settings (NEW)
bool keys[256]; // Array Used For The Keyboard Routine
bool active=TRUE; // Window Active Flag Set To TRUE By Default
bool fullscreen=TRUE; // Fullscreen Flag Set To Fullscreen Mode By Default
int ProcessKeys();
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); // Declaration For WndProc
/************************************************************************************/
/************************************************************************************/
// (no changes)
GLvoid ReSizeGLScene(GLsizei width, GLsizei height) // Resize And Initialize The GL Window
{
if (height==0) // Prevent A Divide By Zero By
{
height=1; // Making Height Equal One
}
glViewport(0,0,width,height); // Reset The Current Viewport
glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
glLoadIdentity(); // Reset The Projection Matrix
// Calculate The Aspect Ratio Of The Window
gluPerspective(50.0f,(GLfloat)width/(GLfloat)height,10.f,1700.0f);
glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
glLoadIdentity(); // Reset The Modelview Matrix
}
/************************************************************************************/
int InitGL(GLvoid) // All Setup For OpenGL Goes Here
{
float df=100.0;
glClearDepth(1.0f); // Depth Buffer Setup
glEnable(GL_DEPTH_TEST); // Enables Depth Testing
glDepthFunc(GL_LEQUAL); // The Type Of Depth Testing To Do
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Really Nice Perspective Calculations
glClearColor(0,0,0,0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glShadeModel(GL_SMOOTH);
glEnable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
glMaterialfv(GL_FRONT,GL_SPECULAR,spec);
glMaterialfv(GL_FRONT,GL_SHININESS,&df);
glEnable(GL_LIGHTING);
glLightfv(GL_LIGHT0,GL_POSITION,posl);
glLightfv(GL_LIGHT0,GL_AMBIENT,amb2);
glEnable(GL_LIGHT0);
glLightModelfv(GL_LIGHT_MODEL_AMBIENT,amb);
glEnable(GL_COLOR_MATERIAL);
glColorMaterial(GL_FRONT,GL_AMBIENT_AND_DIFFUSE);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
glEnable(GL_TEXTURE_2D);
LoadGLTextures();
//Construct billboarded explosion primitive as display list
//4 quads at right angles to each other
glNewList(dlist=glGenLists(1), GL_COMPILE);
glBegin(GL_QUADS);
glRotatef(-45,0,1,0);
glNormal3f(0,0,1);
glTexCoord2f(0.0f, 0.0f); glVertex3f(-50,-40,0);
glTexCoord2f(0.0f, 1.0f); glVertex3f(50,-40,0);
glTexCoord2f(1.0f, 1.0f); glVertex3f(50,40,0);
glTexCoord2f(1.0f, 0.0f); glVertex3f(-50,40,0);
glNormal3f(0,0,-1);
glTexCoord2f(0.0f, 0.0f); glVertex3f(-50,40,0);
glTexCoord2f(0.0f, 1.0f); glVertex3f(50,40,0);
glTexCoord2f(1.0f, 1.0f); glVertex3f(50,-40,0);
glTexCoord2f(1.0f, 0.0f); glVertex3f(-50,-40,0);
glNormal3f(1,0,0);
glTexCoord2f(0.0f, 0.0f); glVertex3f(0,-40,50);
glTexCoord2f(0.0f, 1.0f); glVertex3f(0,-40,-50);
glTexCoord2f(1.0f, 1.0f); glVertex3f(0,40,-50);
glTexCoord2f(1.0f, 0.0f); glVertex3f(0,40,50);
glNormal3f(-1,0,0);
glTexCoord2f(0.0f, 0.0f); glVertex3f(0,40,50);
glTexCoord2f(0.0f, 1.0f); glVertex3f(0,40,-50);
glTexCoord2f(1.0f, 1.0f); glVertex3f(0,-40,-50);
glTexCoord2f(1.0f, 0.0f); glVertex3f(0,-40,50);
glEnd();
glEndList();
return TRUE; // Initialization Went OK
}
/************************************************************************************/
int DrawGLScene(GLvoid) // Here's Where We Do All The Drawing
{
int i;
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
//set camera in hookmode
if (hook_toball1)
{
TVector unit_followvector=ArrayVel[0];
unit_followvector.unit();
gluLookAt(ArrayPos[0].X()+250,ArrayPos[0].Y()+250 ,ArrayPos[0].Z(), ArrayPos[0].X()+ArrayVel[0].X() ,ArrayPos[0].Y()+ArrayVel[0].Y() ,ArrayPos[0].Z()+ArrayVel[0].Z() ,0,1,0);
}
else
gluLookAt(pos.X(),pos.Y(),pos.Z(), pos.X()+dir.X(),pos.Y()+dir.Y(),pos.Z()+dir.Z(), 0,1.0,0.0);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glRotatef(camera_rotation,0,1,0);
//render balls
for (i=0;i<NrOfBalls;i++)
{
switch(i){
case 1: glColor3f(1.0f,1.0f,1.0f);
break;
case 2: glColor3f(1.0f,1.0f,0.0f);
break;
case 3: glColor3f(0.0f,1.0f,1.0f);
break;
case 4: glColor3f(0.0f,1.0f,0.0f);
break;
case 5: glColor3f(0.0f,0.0f,1.0f);
break;
case 6: glColor3f(0.65f,0.2f,0.3f);
break;
case 7: glColor3f(1.0f,0.0f,1.0f);
break;
case 8: glColor3f(0.0f,0.7f,0.4f);
break;
default: glColor3f(1.0f,0,0);
}
glPushMatrix();
glTranslated(ArrayPos[i].X(),ArrayPos[i].Y(),ArrayPos[i].Z());
gluSphere(cylinder_obj,20,20,20);
glPopMatrix();
}
glEnable(GL_TEXTURE_2D);
//render walls(planes) with texture
glBindTexture(GL_TEXTURE_2D, texture[3]);
glColor3f(1, 1, 1);
glBegin(GL_QUADS);
glTexCoord2f(1.0f, 0.0f); glVertex3f(320,320,320);
glTexCoord2f(1.0f, 1.0f); glVertex3f(320,-320,320);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-320,-320,320);
glTexCoord2f(0.0f, 0.0f); glVertex3f(-320,320,320);
glTexCoord2f(1.0f, 0.0f); glVertex3f(-320,320,-320);
glTexCoord2f(1.0f, 1.0f); glVertex3f(-320,-320,-320);
glTexCoord2f(0.0f, 1.0f); glVertex3f(320,-320,-320);
glTexCoord2f(0.0f, 0.0f); glVertex3f(320,320,-320);
glTexCoord2f(1.0f, 0.0f); glVertex3f(320,320,-320);
glTexCoord2f(1.0f, 1.0f); glVertex3f(320,-320,-320);
glTexCoord2f(0.0f, 1.0f); glVertex3f(320,-320,320);
glTexCoord2f(0.0f, 0.0f); glVertex3f(320,320,320);
glTexCoord2f(1.0f, 0.0f); glVertex3f(-320,320,320);
glTexCoord2f(1.0f, 1.0f); glVertex3f(-320,-320,320);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-320,-320,-320);
glTexCoord2f(0.0f, 0.0f); glVertex3f(-320,320,-320);
glEnd();
//render floor (plane) with colours
glBindTexture(GL_TEXTURE_2D, texture[2]);
glBegin(GL_QUADS);
glTexCoord2f(1.0f, 0.0f); glVertex3f(-320,-320,320);
glTexCoord2f(1.0f, 1.0f); glVertex3f(320,-320,320);
glTexCoord2f(0.0f, 1.0f); glVertex3f(320,-320,-320);
glTexCoord2f(0.0f, 0.0f); glVertex3f(-320,-320,-320);
glEnd();
//render columns(cylinders)
glBindTexture(GL_TEXTURE_2D, texture[0]); /* choose the texture to use.*/
glColor3f(0.5,0.5,0.5);
glPushMatrix();
glRotatef(90, 1,0,0);
glTranslatef(0,0,-500);
gluCylinder(cylinder_obj, 60, 60, 1000, 20, 2);
glPopMatrix();
glPushMatrix();
glTranslatef(200,-300,-500);
gluCylinder(cylinder_obj, 60, 60, 1000, 20, 2);
glPopMatrix();
glPushMatrix();
glTranslatef(-200,0,0);
glRotatef(135, 1,0,0);
glTranslatef(0,0,-500);
gluCylinder(cylinder_obj, 30, 30, 1000, 20, 2);
glPopMatrix();
//render/blend explosions
glEnable(GL_BLEND);
glDepthMask(GL_FALSE);
glBindTexture(GL_TEXTURE_2D, texture[1]);
for(i=0; i<20; i++)
{
if(ExplosionArray[i]._Alpha>=0)
{
glPushMatrix();
ExplosionArray[i]._Alpha-=0.01f;
ExplosionArray[i]._Scale+=0.03f;
glColor4f(1,1,0,ExplosionArray[i]._Alpha);
glScalef(ExplosionArray[i]._Scale,ExplosionArray[i]._Scale,ExplosionArray[i]._Scale);
glTranslatef((float)ExplosionArray[i]._Position.X()/ExplosionArray[i]._Scale, (float)ExplosionArray[i]._Position.Y()/ExplosionArray[i]._Scale, (float)ExplosionArray[i]._Position.Z()/ExplosionArray[i]._Scale);
glCallList(dlist);
glPopMatrix();
}
}
glDepthMask(GL_TRUE);
glDisable(GL_BLEND);
glDisable(GL_TEXTURE_2D);
return TRUE; // Keep Going
}
/************************************************************************************/
GLvoid KillGLWindow(GLvoid) // Properly Kill The Window
{
if (fullscreen) // Are We In Fullscreen Mode?
{
if (!ChangeDisplaySettings(NULL,CDS_TEST)) { // if the shortcut doesn't work
ChangeDisplaySettings(NULL,CDS_RESET); // Do it anyway (to get the values out of the registry)
ChangeDisplaySettings(&DMsaved,CDS_RESET); // change it to the saved settings
} else {
ChangeDisplaySettings(NULL,CDS_RESET);
}
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
}
}
/************************************************************************************/
/* This Code Creates Our OpenGL Window. Parameters Are: *
* title - Title To Appear At The Top Of The Window *
* width - Width Of The GL Window Or Fullscreen Mode *
* height - Height Of The GL Window Or Fullscreen Mode *
* bits - Number Of Bits To Use For Color (8/16/24/32) *
* fullscreenflag - Use Fullscreen Mode (TRUE) Or Windowed Mode (FALSE) */
BOOL CreateGLWindow(char* title, int width, int height, int bits, bool fullscreenflag)
{
GLuint PixelFormat; // Holds The Results After Searching For A Match
WNDCLASS wc; // Windows Class Structure
DWORD dwExStyle; // Window Extended Style
DWORD dwStyle; // Window Style
RECT WindowRect; // Grabs Rectangle Upper Left / Lower Right Values
WindowRect.left=(long)0; // Set Left Value To 0
WindowRect.right=(long)width; // Set Right Value To Requested Width
WindowRect.top=(long)0; // Set Top Value To 0
WindowRect.bottom=(long)height; // Set Bottom Value To Requested Height
fullscreen=fullscreenflag; // Set The Global Fullscreen Flag
hInstance = GetModuleHandle(NULL); // Grab An Instance For Our Window
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; // Redraw On Size, And Own DC For Window.
wc.lpfnWndProc = (WNDPROC) WndProc; // WndProc Handles Messages
wc.cbClsExtra = 0; // No Extra Window Data
wc.cbWndExtra = 0; // No Extra Window Data
wc.hInstance = hInstance; // Set The Instance
wc.hIcon = LoadIcon(NULL, IDI_WINLOGO); // Load The Default Icon
wc.hCursor = LoadCursor(NULL, IDC_ARROW); // Load The Arrow Pointer
wc.hbrBackground = NULL; // No Background Required For GL
wc.lpszMenuName = NULL; // We Don't Want A Menu
wc.lpszClassName = "OpenGL"; // Set The Class Name
EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &DMsaved); // save the current display state (NEW)
if (fullscreen) // Attempt Fullscreen Mode?
{
DEVMODE dmScreenSettings; // Device Mode
memset(&dmScreenSettings,0,sizeof(dmScreenSettings)); // Makes Sure Memory's Cleared
dmScreenSettings.dmSize=sizeof(dmScreenSettings); // Size Of The Devmode Structure
dmScreenSettings.dmPelsWidth = width; // Selected Screen Width
dmScreenSettings.dmPelsHeight = height; // Selected Screen Height
dmScreenSettings.dmBitsPerPel = bits; // Selected Bits Per Pixel
dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;
// Try To Set Selected Mode And Get Results. NOTE: CDS_FULLSCREEN Gets Rid Of Start Bar.
if (ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL)
{
// If The Mode Fails, Offer Two Options. Quit Or Use Windowed Mode.
if (MessageBox(NULL,"The Requested Fullscreen Mode Is Not Supported By\nYour Video Card. Use Windowed Mode Instead?","NeHe GL",MB_YESNO|MB_ICONEXCLAMATION)==IDYES)
{
fullscreen=FALSE; // Windowed Mode Selected. Fullscreen = FALSE
}
else
{
// Pop Up A Message Box Letting User Know The Program Is Closing.
MessageBox(NULL,"Program Will Now Close.","ERROR",MB_OK|MB_ICONSTOP);
return FALSE; // Return FALSE
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -