FreeFlyCamera::FreeFlyCamera(glm::vec3 position, float nearDistance, float farDistance, float verticalFieldOfView, double leafSize){
		m_Position = position;
		m_fPhi = PI;
		m_fTheta = 0;
		
		m_leafSize = leafSize;
		
		m_nearDistance = nearDistance;
		m_farDistance = farDistance;
		m_verticalFieldOfView = verticalFieldOfView;
		
		m_frustumNearPlanePoint = glm::vec3(0.f, 0.f, 0.f);
		m_frustumFarPlanePoint = glm::vec3(0.f, 0.f, 0.f);
		m_frustumTopPlanePoint = glm::vec3(0.f, 0.f, 0.f);
		m_frustumRightPlanePoint = glm::vec3(0.f, 0.f, 0.f);
		m_frustumBottomPlanePoint = glm::vec3(0.f, 0.f, 0.f);
		m_frustumLeftPlanePoint = glm::vec3(0.f, 0.f, 0.f);

		m_frustumNearPlaneNormal = glm::vec3(0.f, 0.f, 0.f);
		m_frustumFarPlaneNormal = glm::vec3(0.f, 0.f, 0.f);
		m_frustumTopPlaneNormal = glm::vec3(0.f, 0.f, 0.f);
		m_frustumRightPlaneNormal = glm::vec3(0.f, 0.f, 0.f);
		m_frustumBottomPlaneNormal = glm::vec3(0.f, 0.f, 0.f);
		m_frustumLeftPlaneNormal = glm::vec3(0.f, 0.f, 0.f);

		computeDirectionVectors();
		computeFrustumPlanes();
	}
void TerrainTessellation::draw(void)
{
    glClearColor( 0.7f, 0.8f, 1.0f, 1.0f);
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glEnable(GL_DEPTH_TEST);

    //
    // Compute matrices without the legacy matrix stack support
    //
    nv::matrix4f projectionMatrix;
    nv::perspective( projectionMatrix, 45.0f * 2.0f*NV_PI / 360.0f, (float)m_width/(float)m_height, 0.01f, 100.0f);
    nv::matrix4f invProjection = nv::inverse(projectionMatrix);

    nv::matrix4f viewMatrix;
    viewMatrix = m_transformer->getModelViewMat();
    nv::matrix4f invView = nv::inverse(viewMatrix);

    // compute frustum planes for culling
    nv::vec4f frustumPlanes[6];
    computeFrustumPlanes(viewMatrix, projectionMatrix, frustumPlanes);

    glViewport(0, 0, m_width, m_height);

    glBindProgramPipeline(0);

    //
    // update struct representing UBO
    //
    mParams.ModelView = viewMatrix;
    mParams.ModelViewProjection= projectionMatrix * viewMatrix;
    mParams.Projection = projectionMatrix;
    mParams.InvProjection = invProjection;
    mParams.InvView = invView;

    mParams.cull = mCull;
    mParams.lod = mLod;
    mParams.viewport = nv::vec4f(0.0, 0.0, (float) m_width, (float) m_height);
    mParams.lightDirWorld = mLightDir;
    mParams.lightDir = nv::vec3f(viewMatrix * nv::vec4f(normalize(mLightDir), 0.0));   // transform to eye space
    mParams.smoothNormals = mSmoothNormals;
    mParams.time = mTime;
    mParams.eyePosWorld = invView * nv::vec4f(0.0f, 0.0f, 0.0f, 1.0f);

    if (mAnimate) {
        mParams.translate.y -= getFrameDeltaTime()*2.0f;
    }

    for(int i=0; i<6; i++) {
        mParams.frustumPlanes[i] = frustumPlanes[i];
    }

    // bind the buffer for the UBO, and update it with the latest values from the CPU-side struct
    glBindBufferBase( GL_UNIFORM_BUFFER, 1, mUBO);
    glBindBuffer( GL_UNIFORM_BUFFER, mUBO);
    glBufferSubData( GL_UNIFORM_BUFFER, 0, sizeof(TessellationParams), &mParams);

    // enable / disable wireframe
    glPolygonMode( GL_FRONT_AND_BACK, mWireframe ? GL_LINE : GL_FILL);

    // query number of primitives
    glBeginQuery(GL_PRIMITIVES_GENERATED, mGPUQuery);

    drawTerrain();

    glEndQuery(GL_PRIMITIVES_GENERATED);

    glPolygonMode( GL_FRONT_AND_BACK, GL_FILL);

    drawSky();

    // update triangle count so we can display in UI
    glGetQueryObjectuiv(mGPUQuery, GL_QUERY_RESULT, &mNumPrimitives);
    mStatsText->SetValue(mNumPrimitives);

    if (mReload) {
        loadShaders();
        mReload = false;
        mTweakBar->syncValues();
    }
}
	void FreeFlyCamera::rotateUp(float degree){
		m_fTheta = glm::radians(degree);
		computeDirectionVectors();
		computeFrustumPlanes();
	}
	void FreeFlyCamera::moveFront(float const t){
		m_Position += glm::vec3(t * m_FrontVector.x, t * m_FrontVector.y, t * m_FrontVector.z);
		computeFrustumPlanes();
	}
	void FreeFlyCamera::resetView(float theta, float phi){
		m_fTheta = theta;
		m_fPhi = phi;
		computeDirectionVectors();
		computeFrustumPlanes();
	}