//Called to update the display.
void display()
{
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    glClearDepth(1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    if(coneMesh && cylinderMesh && cubeTintMesh && cubeColorMesh && planeMesh)
    {
        const glm::vec3 &camPos = ResolveCamPosition();

        glutil::MatrixStack camMatrix;
        camMatrix.SetMatrix(CalcLookAtMatrix(camPos, camTarget, glm::vec3(0.0f, 1.0f, 0.0f)));

        glBindBuffer(GL_UNIFORM_BUFFER, globalMatricesUBO);
        glBufferSubData(GL_UNIFORM_BUFFER, sizeof(glm::mat4), sizeof(glm::mat4), glm::value_ptr(camMatrix.Top()));
        glBindBuffer(GL_UNIFORM_BUFFER, 0);

        glutil::MatrixStack modelMatrix;

        //Render the ground plane.
        {
            glutil::PushStack push(modelMatrix);

            modelMatrix.Scale(glm::vec3(100.0f, 1.0f, 100.0f));

            glUseProgram(UniformColor.theProgram);
            glUniformMatrix4fv(UniformColor.modelToWorldMatrixUnif, 1, GL_FALSE, glm::value_ptr(modelMatrix.Top()));
            glUniform4f(UniformColor.baseColorUnif, 0.302f, 0.416f, 0.0589f, 1.0f);
            planeMesh->Render();
            glUseProgram(0);
        }

        //Draw the trees
        DrawForest(modelMatrix);

        //Draw the building.
        {
            glutil::PushStack push(modelMatrix);
            modelMatrix.Translate(glm::vec3(20.0f, 0.0f, -10.0f));

            DrawParthenon(modelMatrix);
        }

        if(drawLookatPoint)
        {
            glDisable(GL_DEPTH_TEST);

            glutil::PushStack push(modelMatrix);

            modelMatrix.Translate(camTarget);

            modelMatrix.Scale(1.0f, 1.0f, 1.0f);

            glUseProgram(ObjectColor.theProgram);
            glUniformMatrix4fv(ObjectColor.modelToWorldMatrixUnif, 1, GL_FALSE, glm::value_ptr(modelMatrix.Top()));

            cubeColorMesh->Render();
            glUseProgram(0);
            glEnable(GL_DEPTH_TEST);
        }
    }
}
//Called to update the display.
//You should call glutSwapBuffers after all of your rendering to display what you rendered.
//If you need continuous updates of the screen, call glutPostRedisplay() at the end of the function.
void display()
{
	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
	glClearDepth(1.0f);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);


	if(g_pConeMesh && g_pCylinderMesh && g_pCubeTintMesh && g_pCubeColorMesh && g_pPlaneMesh)
	{
		g_camMatrix.SetMatrix(mainCharacter.AcquireCamera().CalcLookAtMatrix());

		glutil::MatrixStack modelMatrix;

		//Render the ground plane.
		{
			glutil::PushStack push(modelMatrix);
			modelMatrix.ApplyMatrix(g_camMatrix.Top());

			modelMatrix.Scale(glm::vec3(100.0f, 1.0f, 100.0f));

			glUseProgram(UniformColor.theProgram);
			glUniformMatrix4fv(UniformColor.modelToCameraMatrixUnif, 1, GL_FALSE, glm::value_ptr(modelMatrix.Top()));
			glUniform4f(UniformColor.baseColorUnif, 0.302f, 0.416f, 0.0589f, 1.0f);
			g_pPlaneMesh->Render();
			glUseProgram(0);
		}

		//Draw the trees
		DrawForest(UniformColorTint, modelMatrix, g_camMatrix);

		//Draw the building.
		{
			glutil::PushStack push(modelMatrix);
			modelMatrix.ApplyMatrix(g_camMatrix.Top());

			modelMatrix.Translate(glm::vec3(20.0f, 0.0f, -10.0f));

			DrawParthenon(UniformColorTint, ObjectColor, modelMatrix);
		}

		//Draw the treasure
		for(int i = 0; i < COUNT; i++)
		{
			if(littleTreasures[i].IsRemoved() == false)
			{
				glutil::PushStack push(modelMatrix);
				modelMatrix.ApplyMatrix(g_camMatrix.Top());
			
				littleTreasures[i].Update();
				littleTreasures[i].Render(UniformColorTint, modelMatrix);
			}
			else
			{
				littleTreasures[i].Spawn(g_parthenonBaseVolume, g_treeVolumes, ARRAY_COUNT(g_forest), mainCharacter.GetCollisionVolume()); 
			}
		}
	}

	HandleMouse();

	glutPostRedisplay();
	glutSwapBuffers();

	userMouse.OverrideLastPosition(userMouse.GetCurrentPosition());
}
void display()
{
	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
	glClearDepth(1.0f);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	if(g_pConeMesh && g_pCylinderMesh && g_pCubeTintMesh && g_pCubeColorMesh && g_pPlaneMesh)
	{
		const glm::vec3 &camPos = ResolveCamPosition();

		glutil::MatrixStack camMatrix;
		camMatrix.SetMatrix(CalcLookAtMatrix(camPos, g_camTarget, glm::vec3(0.0f, 1.0f, 0.0f)));

		glBindBuffer(GL_UNIFORM_BUFFER, g_GlobalMatricesUBO);
		glBufferSubData(GL_UNIFORM_BUFFER, sizeof(glm::mat4), sizeof(glm::mat4), glm::value_ptr(camMatrix.Top()));
		glBindBuffer(GL_UNIFORM_BUFFER, 0);

		glutil::MatrixStack modelMatrix;

		//Render the ground plane.
		{
			glutil::PushStack push(modelMatrix);

			modelMatrix.Scale(glm::vec3(200.0f, 1.0f, 200.0f));

			glUseProgram(Texture.theProgram);

			glUniformMatrix4fv(Texture.modelToWorldMatrixUnif, 1, GL_FALSE, glm::value_ptr(modelMatrix.Top()));
			glActiveTexture(GL_TEXTURE0);
			glBindTexture(GL_TEXTURE_2D, g_checkerTexture);
			g_pPlaneMesh->Render("tex");
			glUseProgram(0);

		}

		//Draw the trees
		DrawForest(modelMatrix);

		//Draw the building.
		{
			glutil::PushStack push(modelMatrix);
			modelMatrix.Translate(glm::vec3(20.0f, 0.0f, -10.0f));

		}

		{

			glutil::MatrixStack tempMat;

			float alpha = Framework::DegToRad(g_sphereCamRelPos.x + 90.0f);

			float fSinAlpha = sinf(alpha);
			float fCosAlpha = cosf(alpha);

			glutil::PushStack push(modelMatrix);

			modelMatrix.Translate(glm::vec3((g_camTarget.x + (fCosAlpha/2)), g_camTarget.y , (g_camTarget.z + (fSinAlpha/2))));
			modelMatrix.Scale(1.0f, 2.0f, 1.0f);

			glUseProgram(UniformColorTint.theProgram);
			glUniformMatrix4fv(UniformColorTint.modelToWorldMatrixUnif, 1, GL_FALSE, glm::value_ptr(modelMatrix.Top()));
			glUniform4f(UniformColorTint.baseColorUnif, 0.694f, 0.4f, 0.106f, 1.0f);
			g_pCylinderMesh->Render();
			glUseProgram(0);

		}

		{


			glutil::PushStack push(modelMatrix);

			glutil::MatrixStack tempMat;

			float alpha = Framework::DegToRad(g_sphereCamRelPos.x + 90.0f);

			float fSinAlpha =  sinf(alpha);
			float fCosAlpha =  cosf(alpha);

			glm::vec3 vector (((g_camTarget.x + fCosAlpha)), (g_camTarget.y + 2.0f), (g_camTarget.z + fSinAlpha));

			modelMatrix.Translate(vector);
			modelMatrix.Scale(1.0f, 1.5f, 1.0f);

			glUseProgram(UniformColorTint.theProgram);
			glUniformMatrix4fv(UniformColorTint.modelToWorldMatrixUnif, 1, GL_FALSE, glm::value_ptr(modelMatrix.Top()));
			glUniform4f(UniformColorTint.baseColorUnif, 0.694f, 0.4f, 0.106f, 1.0f);
			g_pCylinderMesh->Render();
			glUseProgram(0);

		}

		{


			glutil::PushStack push(modelMatrix);

			glutil::MatrixStack tempMat;

			float alpha = Framework::DegToRad(g_sphereCamRelPos.x + 90.0f);

			float fSinAlpha =   sinf(alpha);
			float fCosAlpha =   cosf(alpha);

			modelMatrix.Translate(glm::vec3((g_camTarget.x - fCosAlpha), (g_camTarget.y + 2.0f), (g_camTarget.z - fSinAlpha)));
			modelMatrix.Scale(1.0f, 1.5f, 1.0f);

			glUseProgram(UniformColorTint.theProgram);
			glUniformMatrix4fv(UniformColorTint.modelToWorldMatrixUnif, 1, GL_FALSE, glm::value_ptr(modelMatrix.Top()));
			glUniform4f(UniformColorTint.baseColorUnif, 0.694f, 0.4f, 0.106f, 1.0f);
			g_pCylinderMesh->Render();
			glUseProgram(0);

		}


		{
			glutil::PushStack push(modelMatrix);

			glutil::MatrixStack tempMat;

			float alpha = Framework::DegToRad(g_sphereCamRelPos.x + 90.0f);

			float fSinAlpha = sinf(alpha);
			float fCosAlpha = cosf(alpha);

			modelMatrix.Translate(glm::vec3((g_camTarget.x - (fCosAlpha/2)), g_camTarget.y, g_camTarget.z - (fSinAlpha/2)));
			modelMatrix.Scale(1.0f, 2.0f, 1.0f);

			glUseProgram(UniformColorTint.theProgram);
			glUniformMatrix4fv(UniformColorTint.modelToWorldMatrixUnif, 1, GL_FALSE, glm::value_ptr(modelMatrix.Top()));
			glUniform4f(UniformColorTint.baseColorUnif, 0.694f, 0.4f, 0.106f, 1.0f);
			g_pCylinderMesh->Render();
			glUseProgram(0);
		}

		{
			glutil::PushStack push(modelMatrix);

			modelMatrix.Translate(glm::vec3(g_camTarget.x, g_camTarget.y + 2.0f, g_camTarget.z));
			modelMatrix.Scale(2.0f, 2.0f, 2.0f);

			glUseProgram(UniformColorTint.theProgram);
			glUniformMatrix4fv(UniformColorTint.modelToWorldMatrixUnif, 1, GL_FALSE, glm::value_ptr(modelMatrix.Top()));
			glUniform4f(UniformColorTint.baseColorUnif, 0.694f, 0.4f, 0.106f, 1.0f);
			g_pCylinderMesh->Render();
			glUseProgram(0);
		}

		{
			glutil::PushStack push(modelMatrix);

			modelMatrix.Translate(glm::vec3(g_camTarget.x, g_camTarget.y + 4.0f, g_camTarget.z));
			modelMatrix.Scale(2.0f, 2.0f, 2.0f);

			glUseProgram(UniformColorTint.theProgram);
			glUniformMatrix4fv(UniformColorTint.modelToWorldMatrixUnif, 1, GL_FALSE, glm::value_ptr(modelMatrix.Top()));
			glUniform4f(UniformColorTint.baseColorUnif, 0.694f, 0.4f, 0.106f, 1.0f);
			g_pSphereMesh->Render();
			glUseProgram(0);
		}
	}

	glutSwapBuffers();
}
//Called to update the display.
//You should call glutSwapBuffers after all of your rendering to display what you rendered.
//If you need continuous updates of the screen, call glutPostRedisplay() at the end of the function.
void display()
{
	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
	glClearDepth(1.0f);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	if(g_pConeMesh && g_pCylinderMesh && g_pCubeTintMesh && g_pCubeColorMesh && g_pPlaneMesh)
	{
		const glm::vec3 &camPos = ResolveCamPosition();

		glutil::MatrixStack camMatrix;
		camMatrix.SetMatrix(CalcLookAtMatrix(camPos, g_camTarget, glm::vec3(0.0f, 1.0f, 0.0f)));

		glUseProgram(UniformColor.theProgram);
		glUniformMatrix4fv(UniformColor.worldToCameraMatrixUnif, 1, GL_FALSE, glm::value_ptr(camMatrix.Top()));
		glUseProgram(ObjectColor.theProgram);
		glUniformMatrix4fv(ObjectColor.worldToCameraMatrixUnif, 1, GL_FALSE, glm::value_ptr(camMatrix.Top()));
		glUseProgram(UniformColorTint.theProgram);
		glUniformMatrix4fv(UniformColorTint.worldToCameraMatrixUnif, 1, GL_FALSE, glm::value_ptr(camMatrix.Top()));
		glUseProgram(0);

		glutil::MatrixStack modelMatrix;

		//Render the ground plane.
		{
			glutil::PushStack push(modelMatrix);

			modelMatrix.Scale(glm::vec3(100.0f, 1.0f, 100.0f));

			glUseProgram(UniformColor.theProgram);
			glUniformMatrix4fv(UniformColor.modelToWorldMatrixUnif, 1, GL_FALSE, glm::value_ptr(modelMatrix.Top()));
			glUniform4f(UniformColor.baseColorUnif, 0.302f, 0.416f, 0.0589f, 1.0f);
			g_pPlaneMesh->Render();
			glUseProgram(0);
		}

		//Draw the trees
		DrawForest(modelMatrix);

		//Draw the building.
		{
			glutil::PushStack push(modelMatrix);
			modelMatrix.Translate(glm::vec3(20.0f, 0.0f, -10.0f));

			DrawParthenon(modelMatrix);
		}

		if(g_bDrawLookatPoint)
		{
			glDisable(GL_DEPTH_TEST);
			glm::mat4 idenity(1.0f);

			glutil::PushStack push(modelMatrix);

			glm::vec3 cameraAimVec = g_camTarget - camPos;
			modelMatrix.Translate(0.0f, 0.0, -glm::length(cameraAimVec));
			modelMatrix.Scale(1.0f, 1.0f, 1.0f);
		
			glUseProgram(ObjectColor.theProgram);
			glUniformMatrix4fv(ObjectColor.modelToWorldMatrixUnif, 1, GL_FALSE, glm::value_ptr(modelMatrix.Top()));
			glUniformMatrix4fv(ObjectColor.worldToCameraMatrixUnif, 1, GL_FALSE, glm::value_ptr(idenity));
			g_pCubeColorMesh->Render();
			glUseProgram(0);
			glEnable(GL_DEPTH_TEST);
		}
	}

	glutSwapBuffers();
}