void SpecialKeys(int key, int x, int y)
{
    if(key == GLUT_KEY_UP) objectFrame.RotateWorld(m3dDegToRad(-5.0f), 1.0f, 0.0f, 0.0f);
    if(key == GLUT_KEY_DOWN) objectFrame.RotateWorld(m3dDegToRad(5.0f), 1.0f, 0.0f, 0.0f);
    if(key == GLUT_KEY_LEFT) objectFrame.RotateWorld(m3dDegToRad(-5.0f), 0.0f, 1.0f, 0.0f);
    if(key == GLUT_KEY_RIGHT) objectFrame.RotateWorld(m3dDegToRad(5.0f), 0.0f, 1.0f, 0.0f);
    
    glutPostRedisplay();
}
Пример #2
0
    // /////////////////////////////////////////////////////////////////
    //
    // /////////////////////////////////////////////////////////////////
    void Frustrum::Init(const F32 fov, const F32 aspect, const F32 nearClip, const F32 farClip)
    {
        m_Fov = F32(m3dDegToRad(fov));
        m_Aspect = aspect;
        m_Near = nearClip;
        m_Far = farClip;

        F32 tanFovOver2 = F32(tan(m_Fov / 2.0f));
        F32 nearFov2 = m_Near * tanFovOver2;
        F32 farFov2 = m_Far * tanFovOver2;

        // Calculate the near & far right and near & far up vertices of the Frustrum.
        Vector3 nearRight = nearFov2 * m_Aspect * g_right;
        Vector3 farRight = farFov2 * m_Aspect * g_right;
        Vector3 nearUp = nearFov2 * g_up;
        Vector3 farUp = farFov2 * g_up;

        // points start in the upper right and go around clockwise
        m_NearClip[0] = (m_Near * g_forward) - nearRight + nearUp;
        m_NearClip[1] = (m_Near * g_forward) + nearRight + nearUp;
        m_NearClip[2] = (m_Near * g_forward) + nearRight - nearUp;
        m_NearClip[3] = (m_Near * g_forward) - nearRight - nearUp;

        m_FarClip[0] = (m_Far * g_forward) - farRight + farUp;
        m_FarClip[1] = (m_Far * g_forward) + farRight + farUp;
        m_FarClip[2] = (m_Far * g_forward) + farRight - farUp;
        m_FarClip[3] = (m_Far * g_forward) - farRight - farUp;

        m_Planes[Near] = Plane(m_NearClip[2], m_NearClip[1], m_NearClip[0]);
        m_Planes[Far] = Plane(m_FarClip[0], m_FarClip[1], m_FarClip[2]);
        m_Planes[Right] = Plane(m_FarClip[2], m_FarClip[1], g_originPt);
        m_Planes[Top] = Plane(m_FarClip[1], m_FarClip[0], g_originPt);
        m_Planes[Left] = Plane(m_FarClip[0], m_FarClip[3], g_originPt);
        m_Planes[Bottom] = Plane(m_FarClip[3], m_FarClip[2], g_originPt);
    }
Пример #3
0
void SpecialKeys(int key, int x, int y)
{
	float linear = 0.1f;
	float angular = float(m3dDegToRad(5.0f));

	if (key == GLUT_KEY_UP)
	{
		cameraFrame.MoveForward(linear);
	}

	if (key == GLUT_KEY_DOWN)
	{
		cameraFrame.MoveForward(-linear);
	}

	if (key == GLUT_KEY_LEFT)
	{
		cameraFrame.RotateWorld(angular, 0.0f, 1.0f, 0.0f);
	}

	if (key == GLUT_KEY_RIGHT)
	{
		cameraFrame.RotateWorld(-angular, 0.0f, 1.0f, 0.0f);
	}
}
Пример #4
0
void SpecialKeys(int key, int x, int y)
	{
	if(key == GLUT_KEY_UP)
		viewFrame.RotateWorld(m3dDegToRad(-5.0), 1.0f, 0.0f, 0.0f);

	if(key == GLUT_KEY_DOWN)
		viewFrame.RotateWorld(m3dDegToRad(5.0), 1.0f, 0.0f, 0.0f);
        
	if(key == GLUT_KEY_LEFT)
		viewFrame.RotateWorld(m3dDegToRad(-5.0), 0.0f, 1.0f, 0.0f);
        
	if(key == GLUT_KEY_RIGHT)
		viewFrame.RotateWorld(m3dDegToRad(5.0), 0.0f, 1.0f, 0.0f);

	// Refresh the Window
	glutPostRedisplay();
	}
Пример #5
0
Camerak::Camerak(GLMatrixStack *pMVMin)
{
	this->pMVM = pMVMin;
	movement_rate = 0.03f;//change this
	rotation_rate = float(m3dDegToRad(1.0f));
	cam.SetOrigin(49,1.3,39);
	camMx = new M3DMatrix44f[1];
	//cam.RotateLocalY(1.57075);
}
// called on arrow keys
void SpecialKeys(int key, int x, int y){
    float linear = 0.1f;
    float angular = float(m3dDegToRad(5.0f));

    // TODO - flatten movement to the XZ axis

    if(key == GLUT_KEY_UP)
        cameraFrame.MoveForward(linear);
    if(key == GLUT_KEY_DOWN)
        cameraFrame.MoveForward(-linear);
    if(key == GLUT_KEY_LEFT)
        cameraFrame.RotateWorld(angular, 0.0f, 1.0f, 0.0f);
    if(key == GLUT_KEY_RIGHT)
        cameraFrame.RotateWorld(-angular, 0.0f, 1.0f, 0.0f);
}
Пример #7
0
void keyFunc(int key, int x, int y)
{
    static const float step = 0.1f;
    static const float angle = m3dDegToRad(4);
    switch (key)
    {
    case GLUT_KEY_UP:
        objectFrame.RotateWorld(-angle, 1, 0, 0);
        break;

    case GLUT_KEY_DOWN:
        objectFrame.RotateWorld(angle, 1, 0, 0);
        break;

    case GLUT_KEY_LEFT:
        objectFrame.RotateWorld(-angle, 0, 1, 0);
        break;

    case GLUT_KEY_RIGHT:
        objectFrame.RotateWorld(angle, 0, 1, 0);
        break;

    case GLUT_KEY_HOME:
        cameraFrame.MoveForward(step);
        break;

    case GLUT_KEY_END:
        cameraFrame.MoveForward(-step);
        break;

    // enable/disable anisotropy
    case GLUT_KEY_F1:
        if (isAnisotropySupported) {
            isAnisotropy = !isAnisotropy;
            if (isAnisotropy)
                glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, largest);
            else
                glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0f);
        }
        break;
    default:
        break;
    }

    glutPostRedisplay();
}
Пример #8
0
void movingCylinder()
{

    static CStopWatch cameraTimer;
    float fTime = cameraTimer.GetElapsedSeconds();
    cameraTimer.Reset();

    float linear = fTime * 3.0f;
    float angular = fTime * float(m3dDegToRad(15.0f));

    if(isMoveForward == true) cameraFrame.MoveForward(linear);
    if(isMoveBack == true) cameraFrame.MoveForward(-linear);
    if(isRotateLeft == true) cameraFrame.RotateWorld(angular, 0.0f, 1.0f, 0.0f);
    if(isRotateRight == true) cameraFrame.RotateWorld(-angular, 0.0f, 1.0f, 0.0f);
    if(isRotateUp == true) cameraFrame.RotateWorld(angular, 1.0f, 0.0f, 0.0f);
    if(isRotateDown == true) cameraFrame.RotateWorld(-angular, 1.0f, 0.0f, 0.0f);
}
Пример #9
0
// Called to draw scene
void RenderScene(void)
    {
    M3DMatrix44f   transformationMatrix;   // Storeage for rotation matrix
    static GLfloat yRot = 0.0f;         // Rotation angle for animation
    yRot += 0.5f;
        
    // Clear the window with current clearing color
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        
    // Build a rotation matrix
    m3dRotationMatrix44(transformationMatrix, m3dDegToRad(yRot), 0.0f, 1.0f, 0.0f);
    transformationMatrix[12] = 0.0f;
    transformationMatrix[13] = 0.0f;
    transformationMatrix[14] = -2.5f;
        
    DrawTorus(transformationMatrix);

    // Do the buffer Swap
    glutSwapBuffers();
    }
Пример #10
0
///////////////////////////////////////////////////////////////////////////////
// Update the camera based on user input, toggle display modes
// 
void SpecialKeys(int key, int x, int y)
{ 
	static CStopWatch cameraTimer;
	float fTime = cameraTimer.GetElapsedSeconds();
	cameraTimer.Reset(); 

	float linear = fTime * 0.60f;
	float angular = fTime * float(m3dDegToRad(60.0f));

	if(key == GLUT_KEY_UP)
		cameraFrame.MoveForward(linear);

	if(key == GLUT_KEY_DOWN)
		cameraFrame.MoveForward(-linear);

	if(key == GLUT_KEY_LEFT)
		cameraFrame.RotateWorld(angular, 0.0f, 1.0f, 0.0f);

	if(key == GLUT_KEY_RIGHT)
		cameraFrame.RotateWorld(-angular, 0.0f, 1.0f, 0.0f);
}
Пример #11
0
void SceneShader()
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

	GLfloat VColor[] = {0.25f,0.25f,0.25f,1.0f};

	M3DMatrix44f RotationMatrix;
	Rot += 1.0f; 

	//get the Rotation Matrix 
	//m3dDegToRad: translate angle to radian
	m3dRotationMatrix44(RotationMatrix, m3dDegToRad(Rot), 0.0f, 0.0f, 1.0f);  

	//use the flat shader
	shaderManager.UseStockShader(GLT_SHADER_FLAT, RotationMatrix ,VColor);

	SquareRotationBatch.Draw();

	// Swap buffers, and immediately refresh
	glutSwapBuffers();   
	glutPostRedisplay(); 
}
Пример #12
0
///////////////////////////////////////////////////////////////////////////////
// Update the camera based on user input, toggle display modes
// 
void SpecialKeys(int key, int x, int y)
{ 
    static CStopWatch cameraTimer;
    float fTime = cameraTimer.GetElapsedSeconds();
    cameraTimer.Reset(); 

    float linear = fTime * 3.0f;
    float angular = fTime * float(m3dDegToRad(60.0f));

    if(key == GLUT_KEY_LEFT)
    {
        worldAngle += angular*50;
        if(worldAngle > 360)
            worldAngle -= 360;
    }

    if(key == GLUT_KEY_RIGHT)
    {
        worldAngle -= angular*50;
        if(worldAngle < 360)
            worldAngle += 360;
    }
}
void RenderScence(void)
{

	static CStopWatch rotTimer;
	float yRot = rotTimer.GetElapsedSeconds() * 60.0f;//每秒旋转60度?

	//Clear the window and the depth buffer
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	M3DMatrix44f mTranslate, mRotate, mModelView, mModelViewProjection;

	//生成一个平移矩阵,用于将花环移回视野中,有个问题,1.0f会是什么效果?1.0会看不见花托。有可能截头体是世界坐标1.0-1000.0f是指距离camera的。所以此矩阵是相对于摄像机的操作,移到摄像机面前2.5f深度距离处
	//即摄像机所在的地方为原点(0,0,0)
	m3dTranslationMatrix44(mTranslate, 0.0f, 0.0f, -2.5f);

	//生成旋转矩阵 以y为轴,旋转时间t产生的旋转角 yRot
	m3dRotationMatrix44(mRotate, m3dDegToRad(yRot), 0.0f, 1.0f, 0.0f);

	//组合为模型变换矩阵,而原模型矩阵在最右边,即先旋转再平移 ?
	m3dMatrixMultiply44(mModelView, mTranslate, mRotate);

	//组合成模型投影矩阵,而原模型矩阵在最右边,先做模型变换再投影 ?
	m3dMatrixMultiply44(mModelViewProjection, viewFrustum.GetProjectionMatrix(), mModelView);

	GLfloat vBlack[] = { 1.0f, 1.0f, 1.0f, 1.0f };

	//选择要配置的渲染操作类型,非smooth,每种模式对应的参数要熟悉才能正确使用
	shaderManger.UseStockShader(GLT_SHADER_FLAT, mModelViewProjection, vBlack);//黑色背景?不是,是设置当前画笔颜色

	torusBatch.Draw();

	glutSwapBuffers();

	glutPostRedisplay();

	//整个流程是:先旋转在平移,然后进行投影剪裁,最后光栅化。UseStockShader 和draw函数之前的变换管线还是不清晰
}
Пример #14
0
#include "Ostrich.h"
#include "Turtle.h"
//#include "Dolphin.h"

/* ------------------------- */
/* Disable console on WIN_32 */
#if defined(__WIN32__) || defined(_WIN32)
#pragma comment(linker, "/subsystem:\"windows\" \
/entry:\"mainCRTStartup\"")
#endif

/* ------------------------------- */

const int   ORIG_WINDOW_SIZE[] = { 1000, 1000 };
const float CAMERA_LINEAR_STEP = 0.1f;
const float CAMERA_ANGULAR_STEP = float(m3dDegToRad(5.0f));
const float FRUSTUM_FIELD_OF_VIEW = 35.0f;
const float FRUSTUM_NEAR_PLANE = 0.1f;
const float FRUSTUM_FAR_PLANE = 100.0f;

/* ------------------------------- */

const float FLOOR_GRID_WIDTH = 40.0f;
const float FLOOR_GRID_INCREMENT = 0.5f;
const float FLOOR_HEIGHT = -0.65f;
const float REFLECTING_ALPHA = 0.5f;
const float NONREFLECTING_ALPHA = 1.0f;

/* ------------------------------- */

const float FERRIS_WHEEL_POSITION[] = { 0.0f, 0.0f, -2.5f };
Пример #15
0
///////////////////////////////////////////////////////////////////////////////
// This function does any needed initialization on the rendering context. 
// This is the first opportunity to do any OpenGL related tasks.
void SetupRC()
{
    GLbyte *pBytes;
    GLint nWidth, nHeight, nComponents;
    GLenum format;

    shaderManager.InitializeStockShaders();

    // Black background
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f );
    glEnable(GL_DEPTH_TEST);
    glLineWidth(2.5f);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);

    transformPipeline.SetMatrixStacks(modelViewMatrix, projectionMatrix);

    cameraFrame.MoveForward(-15.0f);
    cameraFrame.MoveUp(6.0f);
    cameraFrame.RotateLocalX(float(m3dDegToRad(20.0f)));
    
    MakeCube(cubeBatch);
    MakeFloor(floorBatch);

    // Make top
    topBlock.Begin(GL_TRIANGLE_FAN, 4, 1);
        topBlock.Normal3f(0.0f, 1.0f, 0.0f);
        topBlock.MultiTexCoord2f(0, 0.0f, 0.0f);
        topBlock.Vertex3f(-1.0f, 1.0f, 1.0f);

        topBlock.Normal3f(0.0f, 1.0f, 0.0f);
        topBlock.MultiTexCoord2f(0, 1.0f, 0.0f);
        topBlock.Vertex3f(1.0f, 1.0f, 1.0f);

        topBlock.Normal3f(0.0f, 1.0f, 0.0f);
        topBlock.MultiTexCoord2f(0, 1.0f, 1.0f);
        topBlock.Vertex3f(1.0f, 1.0f, -1.0f);

        topBlock.Normal3f(0.0f, 1.0f, 0.0f);
        topBlock.MultiTexCoord2f(0, 0.0f, 1.0f);
        topBlock.Vertex3f(-1.0f, 1.0f, -1.0f);
    topBlock.End();

    // Make Front
    frontBlock.Begin(GL_TRIANGLE_FAN, 4, 1);
        frontBlock.Normal3f(0.0f, 0.0f, 1.0f);
        frontBlock.MultiTexCoord2f(0, 0.0f, 0.0f);
        frontBlock.Vertex3f(-1.0f, -1.0f, 1.0f);

        frontBlock.Normal3f(0.0f, 0.0f, 1.0f);
        frontBlock.MultiTexCoord2f(0, 1.0f, 0.0f);
        frontBlock.Vertex3f(1.0f, -1.0f, 1.0f);

        frontBlock.Normal3f(0.0f, 0.0f, 1.0f);
        frontBlock.MultiTexCoord2f(0, 1.0f, 1.0f);
        frontBlock.Vertex3f(1.0f, 1.0f, 1.0f);

        frontBlock.Normal3f(0.0f, 0.0f, 1.0f);
        frontBlock.MultiTexCoord2f(0, 0.0f, 1.0f);
        frontBlock.Vertex3f(-1.0f, 1.0f, 1.0f);
    frontBlock.End();

    // Make left
    leftBlock.Begin(GL_TRIANGLE_FAN, 4, 1);
        leftBlock.Normal3f(-1.0f, 0.0f, 0.0f);
        leftBlock.MultiTexCoord2f(0, 0.0f, 0.0f);
        leftBlock.Vertex3f(-1.0f, -1.0f, -1.0f);

        leftBlock.Normal3f(-1.0f, 0.0f, 0.0f);
        leftBlock.MultiTexCoord2f(0, 1.0f, 0.0f);
        leftBlock.Vertex3f(-1.0f, -1.0f, 1.0f);

        leftBlock.Normal3f(-1.0f, 0.0f, 0.0f);
        leftBlock.MultiTexCoord2f(0, 1.0f, 1.0f);
        leftBlock.Vertex3f(-1.0f, 1.0f, 1.0f);

        leftBlock.Normal3f(-1.0f, 0.0f, 0.0f);
        leftBlock.MultiTexCoord2f(0, 0.0f, 1.0f);
        leftBlock.Vertex3f(-1.0f, 1.0f, -1.0f);
    leftBlock.End();

    // Create shadow projection matrix
    GLfloat floorPlane[] = { 0.0f, 1.0f, 0.0f, 1.0f};
    m3dMakePlanarShadowMatrix(shadowMatrix, floorPlane, vLightPos);

    // Load up four textures  
    glGenTextures(4, textures);
        
    // Wood floor
    pBytes = gltReadTGABits("floor.tga", &nWidth, &nHeight, &nComponents, &format);
    glBindTexture(GL_TEXTURE_2D, textures[0]);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexImage2D(GL_TEXTURE_2D,0,nComponents,nWidth, nHeight, 0,
        format, GL_UNSIGNED_BYTE, pBytes);
    free(pBytes);

    // One of the block faces
    pBytes = gltReadTGABits("Block4.tga", &nWidth, &nHeight, &nComponents, &format);
    glBindTexture(GL_TEXTURE_2D, textures[1]);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexImage2D(GL_TEXTURE_2D,0,nComponents,nWidth, nHeight, 0,
        format, GL_UNSIGNED_BYTE, pBytes);
    free(pBytes);

    // Another block face
    pBytes = gltReadTGABits("block5.tga", &nWidth, &nHeight, &nComponents, &format);
        glBindTexture(GL_TEXTURE_2D, textures[2]);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexImage2D(GL_TEXTURE_2D,0,nComponents,nWidth, nHeight, 0,
        format, GL_UNSIGNED_BYTE, pBytes);
    free(pBytes);

    // Yet another block face
    pBytes = gltReadTGABits("block6.tga", &nWidth, &nHeight, &nComponents, &format);
        glBindTexture(GL_TEXTURE_2D, textures[3]);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexImage2D(GL_TEXTURE_2D,0,nComponents,nWidth, nHeight, 0,
        format, GL_UNSIGNED_BYTE, pBytes);
    free(pBytes);
}
Пример #16
0
/////////////////////////////////////////////////////////////////
// Window procedure, handles all messages for this program
LRESULT CALLBACK WndProc(HWND hWnd,	UINT message, WPARAM wParam, LPARAM lParam)
{
    static HGLRC hRC;		// Permenant Rendering context
    static HDC hDC;			// Private GDI Device context

    switch (message)
    {
    // Window creation, setup for OpenGL
    case WM_CREATE:
        // Store the device context
        hDC = GetDC(hWnd);

        // The screen and desktop may have changed, so do this again
        FindBestPF(hDC, &startupOptions.nPixelFormat, &startupOptions.nPixelFormatMS);

        // Set pixelformat
        if(startupOptions.bFSAA == TRUE && (startupOptions.nPixelFormatMS != 0))
            SetPixelFormat(hDC, startupOptions.nPixelFormatMS, NULL);
        else
            SetPixelFormat(hDC, startupOptions.nPixelFormat, NULL);

        // Create the rendering context and make it current
        hRC = wglCreateContext(hDC);
        wglMakeCurrent(hDC, hRC);

        SetupRC(hDC);

        break;

    // Check for ESC key
    case WM_CHAR:
        if(wParam == 27)
            DestroyWindow(hWnd);
        break;

    // Window is either full screen, or not visible
    case WM_ACTIVATE:
    {
        // Ignore this altogether unless we are in full screen mode
        if(startupOptions.bFullScreen == TRUE)
        {
            // Construct windowplacement structure
            WINDOWPLACEMENT wndPlacement;
            wndPlacement.length = sizeof(WINDOWPLACEMENT);
            wndPlacement.flags = WPF_RESTORETOMAXIMIZED;
            wndPlacement.ptMaxPosition.x = 0;
            wndPlacement.ptMaxPosition.y = 0;
            wndPlacement.ptMinPosition.x = 0;
            wndPlacement.ptMinPosition.y = 0;
            wndPlacement.rcNormalPosition.bottom = startupOptions.devMode.dmPelsHeight;
            wndPlacement.rcNormalPosition.left = 0;
            wndPlacement.rcNormalPosition.top = 0;
            wndPlacement.rcNormalPosition.right = startupOptions.devMode.dmPelsWidth;

            // Switching away from window
            if(LOWORD(wParam) == WA_INACTIVE)
            {
                wndPlacement.showCmd = SW_SHOWMINNOACTIVE;
                SetWindowPlacement(hWnd, &wndPlacement);
                ShowCursor(TRUE);
            }
            else    // Switching back to window
            {
                wndPlacement.showCmd = SW_RESTORE;
                SetWindowPlacement(hWnd, &wndPlacement);
                ShowCursor(FALSE);
            }
        }
    }
    break;


    // Window is being destroyed, cleanup
    case WM_DESTROY:
        // Kill the timer that we created
        KillTimer(hWnd,101);

        ShutdownRC();

        // Deselect the current rendering context and delete it
        wglMakeCurrent(hDC,NULL);
        wglDeleteContext(hRC);

        // Tell the application to terminate after the window
        // is gone.
        PostQuitMessage(0);
        break;

    // Window is resized.
    case WM_SIZE:
        // Call our function which modifies the clipping
        // volume and viewport
        ChangeSize(LOWORD(lParam), HIWORD(lParam));
        break;

    // The painting function.  This message sent by Windows
    // whenever the screen needs updating.
    case WM_PAINT:
    {
        // Only poll keyboard when this window has focus
        if(GetFocus() == hWnd)
        {
            float fTime;
            float fLinear, fAngular;

            // Get the time since the last time we rendered a frame
            LARGE_INTEGER lCurrent;
            QueryPerformanceCounter(&lCurrent);

            fTime = (float)(lCurrent.QuadPart - CameraTimer.QuadPart) /
                    (float)CounterFrequency.QuadPart;

            CameraTimer = lCurrent;

            // Camera motion will be time based. This keeps the motion constant
            // regardless of frame rate. Higher frame rates produce smoother
            // animation and motion, they should not produce "faster" motion.
            fLinear = fTime * 1.0f;
            fAngular = (float)m3dDegToRad(60.0f * fTime);

            // Move the camera around, poll the keyboard
            if(GetAsyncKeyState(VK_UP))
                frameCamera.MoveForward(fLinear);

            if(GetAsyncKeyState(VK_DOWN))
                frameCamera.MoveForward(-fLinear);

            if(GetAsyncKeyState(VK_LEFT))
                frameCamera.MoveForward(fAngular);

            if(GetAsyncKeyState(VK_RIGHT))
                frameCamera.MoveForward(-fAngular);
        }

        // Call OpenGL drawing code
        RenderScene();

        // Call function to swap the buffers
        SwapBuffers(hDC);

        // Not validated on purpose, gives and endless series
        // of paint messages... this is akin to having
        // a rendering loop
        //ValidateRect(hWnd,NULL);
    }
    break;

    default:   // Passes it on if unproccessed
        return (DefWindowProc(hWnd, message, wParam, lParam));

    }

    return (0L);
}
///////////////////////////////////////////////////////////////////////////////
// Update the camera based on user input, toggle display modes
// 
void SpecialKeys(int key, int x, int y)
{
	static CStopWatch cameraTimer;
	float fTime = cameraTimer.GetElapsedSeconds();
	cameraTimer.Reset(); 

	float linear = fTime * 3.0f;
	float angular = fTime * float(m3dDegToRad(60.0f));

	if(key == GLUT_KEY_UP)
		cameraFrame.MoveForward(linear);

	if(key == GLUT_KEY_DOWN)
		cameraFrame.MoveForward(-linear);

	if(key == GLUT_KEY_LEFT)
		cameraFrame.RotateWorld(angular, 0.0f, 1.0f, 0.0f);

	if(key == GLUT_KEY_RIGHT)
		cameraFrame.RotateWorld(-angular, 0.0f, 1.0f, 0.0f);

	static bool bF2IsDown = false;
	if(key == GLUT_KEY_F2)
	{
		if(bF2IsDown == false)
		{
			bF2IsDown = true;
			bUseFBO = !bUseFBO;
		}
	}
	else
	{
		bF2IsDown = false; 
	}

#ifndef OPENGL_ES
	if(key == GLUT_KEY_F3)
	{
		glActiveTexture(GL_TEXTURE1);
		glBindTexture(GL_TEXTURE_BUFFER_ARB, texBOTexture);
		glTexBufferARB(GL_TEXTURE_BUFFER_ARB, GL_R32F, texBO[0]); // FIX THIS IN GLEE
		glActiveTexture(GL_TEXTURE0);
	}
	else if(key == GLUT_KEY_F4)
	{
		glActiveTexture(GL_TEXTURE1);
		glBindTexture(GL_TEXTURE_BUFFER_ARB, texBOTexture);
		glTexBufferARB(GL_TEXTURE_BUFFER_ARB, GL_R32F, texBO[1]); // FIX THIS IN GLEE
		glActiveTexture(GL_TEXTURE0);
	}
	else if(key == GLUT_KEY_F5)
	{
		glActiveTexture(GL_TEXTURE1);
		glBindTexture(GL_TEXTURE_BUFFER_ARB, texBOTexture);
		glTexBufferARB(GL_TEXTURE_BUFFER_ARB, GL_R32F, texBO[2]); // FIX THIS IN GLEE
		glActiveTexture(GL_TEXTURE0);
	}
#endif

	 // Refresh the Window
	 glutPostRedisplay();
}