/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */
#include "RenderScene.h"
#include "glm/gtx/transform.hpp"
#include "glm/gtc/matrix_inverse.hpp"
#include <glm/gtc/type_ptr.hpp>

RenderPrimitive::RenderPrimitive()
{
}

RenderPrimitive::~RenderPrimitive()
{
    glDeleteBuffers(1, &mVertexBuffer);
    glDeleteBuffers(1, &mNormalBuffer);
    glDeleteBuffers(1, &mTexCoordBuffer);
    glDeleteBuffers(1, &mIndicesBuffer);

    delete pProject;
    delete pColor;
}

class Material* RenderPrimitive::getMaterial()
{
	return this->pMaterial;
}

void RenderPrimitive::setMaterial(class Material* pMaterial)
{
	this->pMaterial = pMaterial;
}

unsigned int RenderPrimitive::getVerterCount()
{
	return this->mVerterCount;
}

void RenderPrimitive::setVerterCount(unsigned int count)
{
	this->mVerterCount = count;
}

unsigned int RenderPrimitive::getIndicesCount()
{
    return this->mIndicesCount;
}

void RenderPrimitive::setIndicesCount(unsigned int count)
{
    this->mIndicesCount = count;
}

DataType_E RenderPrimitive::getIndicesDataType()
{
    return this->mIndicesDataType;
}

void RenderPrimitive::setIndicesDataType(DataType_E type)
{
    this->mIndicesDataType = type;
}

unsigned int RenderPrimitive::getShaderVertexId()
{
	return this->mShaderVertexId;
}

void RenderPrimitive::setShaderVertexId(unsigned int id)
{
	this->mShaderVertexId = id;
}

unsigned int RenderPrimitive::getShaderNormalId()
{
	return this->mShaderNormalId;
}

void RenderPrimitive::setShaderNormalId(unsigned int id)
{
	this->mShaderNormalId = id;
}

unsigned int RenderPrimitive::getShaderCoord0Id()
{
	return this->mShaderCoord0Id;
}

void RenderPrimitive::setShaderCoord0Id(unsigned int id)
{
	this->mShaderCoord0Id = id;
}

unsigned int RenderPrimitive::getVertexBuffer()
{
	return this->mVertexBuffer;
}

void RenderPrimitive::setVertexBuffer(unsigned int bufferId)
{
	this->mVertexBuffer = bufferId;
}

unsigned int RenderPrimitive::getNormalBuffer()
{
	return this->mNormalBuffer;
}

void RenderPrimitive::setNormalBuffer(unsigned int bufferId)
{
	this->mNormalBuffer = bufferId;
}

unsigned int RenderPrimitive::getTexCoordBuffer()
{
	return this->mTexCoordBuffer;
}

void RenderPrimitive::setTexCoordBuffer(unsigned int bufferId)
{
	this->mTexCoordBuffer = bufferId;
}

unsigned int RenderPrimitive::getIndicesBuffer()
{
    return this->mIndicesBuffer;
}

void RenderPrimitive::setIndicesBuffer(unsigned int bufferId)
{
    this->mIndicesBuffer = bufferId;
}

void RenderPrimitive::setProject(glm::mat4* project)
{
    this->pProject = project;
}

glm::mat4* RenderPrimitive::getProject()
{
    return this->pProject;
}

void RenderPrimitive::setColor(glm::vec3* color)
{
    this->pColor = color;
}

glm::vec3* RenderPrimitive::getColor()
{
    return this->pColor;
}

void RenderPrimitive::setMatrix(glm::mat4* matrix)
{
    this->pMatrix = matrix;
}

glm::mat4* RenderPrimitive::getMatrix()
{
    return this->pMatrix;
}


RenderScene::RenderScene()
	: pScene (0)
{
}

RenderScene::~RenderScene()
{
	if(pScene != NULL) delete pScene;
    RenderPrimitive* pRenderPrimitive;
    unsigned int size = mPrimitiveVec.size();
	for (unsigned int i = 0; i < size; ++i)
	{
        pRenderPrimitive = mPrimitiveVec[i];
		if (0 != pRenderPrimitive)
			delete pRenderPrimitive;
	}
    mPrimitiveVec.clear();
}

class Scene* RenderScene::loadScene(const std::string& directory, 
    const std::string& file)
{
	class Scene* pScene = new Scene();
	loadJson.setJsonInfo(directory, file);
	if (!loadJson.parseJsonFile())
	{
		return 0;
	}

	loadJson.parseScene(pScene);
	return pScene;
}

class Scene* RenderScene::loadScene(glTFHandle* handle)
{ 
    class Scene* pScene = new Scene();
    pScene->setGltfHandle(handle);
    loadJson.parseScene(pScene);
    return pScene;
}

glTFHandle* RenderScene::initScene(const glTFFile* jsonfile)
{
    if(0 == jsonfile)
        return 0;
    string tmpStr(jsonfile->buffer);
    loadJson.setJsonInfo(tmpStr);
    if (!loadJson.parseJsonFile())
        return 0;
    string tmpFileName(jsonfile->filename);
    return loadJson.getFileNameInJson(tmpFileName);
}

unsigned int RenderScene::bindAttribute(const class Attribute* pAttr)
{
	unsigned int bufferId;
	glGenBuffers(1, &bufferId);
	glBindBuffer(GL_ARRAY_BUFFER, bufferId);
	glBufferData(GL_ARRAY_BUFFER, pAttr->getDataCount() * pAttr->getByteStride(),
				pAttr->getAttributeData(), GL_STATIC_DRAW);
	return bufferId;
}

unsigned int RenderScene::bindIndices(const class Attribute* pAttr)
{
    unsigned int bufferId;
    glGenBuffers(1, &bufferId);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bufferId);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, 
                pAttr->getDataCount() * pAttr->getByteStride(),
				pAttr->getAttributeData(), GL_STATIC_DRAW);
    return bufferId;
}

void RenderScene::constructMesh(const std::string meshName, glm::mat4* pmatrix)
{
	const Mesh* pMesh = pScene->findMesh(meshName);
	unsigned int size = pMesh->getPrimitiveVecSize();
	for (unsigned int i = 0; i < size; ++i)
		constructPrimitive(pMesh->getPrimitiveVec(i), pmatrix);
}

void RenderScene::constructPrimitive(const Primitives* pPrimitive, 
    glm::mat4* pmatrix)
{
    class Material* pMaterial;
    pMaterial = pScene->findMaterial(pPrimitive->getMaterialIndex());
    if (0 == pMaterial)
        return;
	class RenderPrimitive* pRenderPrimitive = new(std::nothrow) RenderPrimitive();
    if (0 == pRenderPrimitive)
        return;
    getAttributeShaderId(pMaterial, pRenderPrimitive);
    bindAttributeBuffer(pPrimitive, pRenderPrimitive);
	pRenderPrimitive->setMaterial(pMaterial);  
    glm::mat4* pProject = calcProjectionMatrix();
    pRenderPrimitive->setProject(pProject);
    glm::vec3* pColor = calcLightColor();
    pRenderPrimitive->setColor(pColor);
    pRenderPrimitive->setMatrix(pmatrix);
	setPrimitiveVec(pRenderPrimitive);
}

void RenderScene::getAttributeShaderId(class Material* pMaterial,
    class RenderPrimitive* pRP)
{
    unsigned int shader_id;
    class TechAttribute* pAttribute;
    class Technique* pTechnique;
    pTechnique = pScene->findTechnique(pMaterial->getTechniqueId());
    if (0 == pTechnique)
    {
        return;
    }

    pAttribute = pTechnique->getTechAttribute("a_position");
    if (0 != pAttribute)
    {
        shader_id = glGetAttribLocation(pTechnique->getProgramId(),
            pAttribute->getAttributeName().c_str());
        pRP->setShaderVertexId(shader_id);
    }

    pAttribute = pTechnique->getTechAttribute("a_normal");
    if (0 != pAttribute)
    {
        shader_id = glGetAttribLocation(pTechnique->getProgramId(),
            pAttribute->getAttributeName().c_str());
        pRP->setShaderNormalId(shader_id);
    }

    pAttribute = pTechnique->getTechAttribute("a_texcoord0");
    if (0 != pAttribute)
    {
        shader_id = glGetAttribLocation(pTechnique->getProgramId(),
            pAttribute->getAttributeName().c_str());
        pRP->setShaderCoord0Id(shader_id);
    }
}

void RenderScene::bindAttributeBuffer(const Primitives* pPrimitive,
    class RenderPrimitive* pRP)
{
    const class Attribute* pVertice;
    pVertice = pScene->findAttribute(pPrimitive->getAttributeIndex("POSITION"));
    if (0 != pVertice)
    {
        pRP->setVertexBuffer(bindAttribute(pVertice));
        pRP->setVerterCount(pVertice->getDataCount());
    }

    const class Attribute* pNormal;
    pNormal = pScene->findAttribute(pPrimitive->getAttributeIndex("NORMAL"));
    if (0 != pNormal)
        pRP->setNormalBuffer(bindAttribute(pNormal));
    const class Attribute* pTexcoord;
    pTexcoord = pScene->findAttribute(pPrimitive->getAttributeIndex("TEXCOORD_0"));
    if (0 != pTexcoord)
    {
        float* pData = (float*)pTexcoord->getAttributeData();
        unsigned int size = pTexcoord->getDataCount();
        for (unsigned int i = 0; i < size; i++)
        {
            pData[i*2+1] = 1 - pData[i*2+1];
        }
        pRP->setTexCoordBuffer(bindAttribute(pTexcoord));
    }

    const class Attribute* pIndices;
    pIndices = pScene->findAttribute(pPrimitive->getIndicesIndex());
    if (0 != pIndices)
    {
        pRP->setIndicesBuffer(bindIndices(pIndices));
        pRP->setIndicesCount(pIndices->getDataCount());
        pRP->setIndicesDataType(pIndices->getDataType());
    }
}

void RenderScene::setPrimitiveVec(class RenderPrimitive* pPrim)
{
	(this->mPrimitiveVec).push_back(pPrim);
}

class RenderPrimitive* RenderScene::getPrimitiveVec(unsigned int index)
{
	if (this->mPrimitiveVec.size() <= index)
		return 0;
	return this->mPrimitiveVec[index];
}

unsigned int RenderScene::getPrimitiveVecSize()
{
	return this->mPrimitiveVec.size();
}

glm::mat4* RenderScene::calcProjectionMatrix()
{
    const class Node* pParentNode = pScene->getRootNode();
    glm::mat4 projection;
    if (!pParentNode->getFlagCamera())
        projection = glm::perspective(37.8492f, 1.5f, 1.0f, 10000.0f);
    else
    {
        Camera* cCamera  = pScene->findCamera(pScene->getCameraIndex());
        projection = glm::perspective(cCamera->getYFov(),
            cCamera->getAspectRatio(),cCamera->getNear(), cCamera->getFar());
    }
    glm::mat4* pProject = (glm::mat4*) new (std::nothrow) glm::mat4;
    if (0 == pProject)
        return 0;
    memcpy(pProject, glm::value_ptr(projection), sizeof(glm::mat4));
    return pProject;
}

glm::vec3* RenderScene::calcLightColor()
{
    glm::vec3* pLightColor;
    Vector3D vec_color = pLight->getColor();
    pLightColor = new(std::nothrow) glm::vec3(vec_color.x, vec_color.y, 
                                              vec_color.z);
    return pLightColor;
}

void RenderScene::initOpengl()
{
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    glClear(GL_COLOR_BUFFER_BIT);
    glEnable(GL_TEXTURE_2D);
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);
    glDepthFunc(GL_LESS);
}

void RenderScene::createDefaultLight()
{
    if (pScene->getLight())
        pLight = new Light();
    else
        pLight = pScene->findLight(pScene->GetLightIndex());
    glLightfv(GL_LIGHT0, GL_AMBIENT, pLight->getColorAmbient());
    glLightfv(GL_LIGHT0, GL_DIFFUSE, pLight->getColorDiffuse());
    glLightfv(GL_LIGHT0, GL_SPECULAR, pLight->getColorSpecular());
    glLightf( GL_LIGHT0, GL_SPOT_CUTOFF, 45.0 );
}

void RenderScene::createDefaultCamera()
{
    glm::vec3 vDelta = pScene->getVertexMax() - pScene->getVertexMin();
    glm::vec3 vHalf =  pScene->getVertexMin() + (vDelta / 2.0f);

    float fPos = sqrt (vDelta.x*vDelta.x+vDelta.y*vDelta.y+vDelta.z*vDelta.z);
    if (fPos>=3000)
    {
        pCamera = new CPhysicalCamera(glm::vec3(0.0f,-fPos/5, fPos*0.8f),
            vHalf,
            glm::vec3(.0f, 1.0f, 0.0f));
    } 
    else
    {
        pCamera = new CPhysicalCamera(glm::vec3(0.0f, -fPos, fPos*2),
            vHalf,
            glm::vec3(.0f, 1.0f, 0.0f));
    }
    pCamera->flength = fPos;
    pCamera->SetRotationAngle();
}

void RenderScene::initRender(glTFHandle* handle)
{ 
    initOpengl();
    pScene = loadScene(handle);
    if (0 == pScene)
        return;

    createDefaultLight();
    createDefaultCamera();
    const class Node* pNode;
    unsigned int nSize = pScene->getNodeSize();
    for (unsigned int i = 0; i < nSize; ++i)
    {
        pNode = pScene->getNode(i);
        if (pNode->hasMesh())
        {
            unsigned int mSize = pNode->getMeshIndexSize();
            for (unsigned int i = 0; i < mSize; ++i)
                constructMesh(pNode->getMeshIndex(i), pNode->getMatrix());
        }
    }
    pFPSCounter =new FPSCounter();
    pFPSCounter->loadFPSShader(&mShaderProgram);

}

void RenderScene::renderPrimitive(class RenderPrimitive* pPrimitive)
{
	class Material* pMaterial = pPrimitive->getMaterial();
	class Technique* pTechnique = 
        pScene->findTechnique(pMaterial->getTechniqueId());
	if (!pTechnique->getProgramState())
		return;
	pTechnique->useTechnique();
    unsigned int progId = pTechnique->getProgramId();
    glm::mat4* pMatrix = pPrimitive->getMatrix();
    glm::mat4 modelViewMatrix = pCamera->getModelViewMatrix(pMatrix);
    mShaderProgram.setUniform(progId, "u_modelViewMatrix", modelViewMatrix);
    mShaderProgram.setUniform(progId, "u_modelViewMatrix", modelViewMatrix);
    glm::mat3 normalMatrix(*pMatrix);
    glm::mat3 NormalInverseTranspose = glm::mat3(pCamera->Look()) *
        (glm::transpose(glm::inverse(normalMatrix)));
    mShaderProgram.setUniform(progId, "u_normalMatrix", NormalInverseTranspose);
    mShaderProgram.setUniform(progId, "u_projectionMatrix", 
        pPrimitive->getProject());
    mShaderProgram.setUniform(progId, "u_light0Color", pPrimitive->getColor());
    int textureId = 0;
    std::string properName;
    const class MaterialProperty* pProper;
	unsigned int size = pMaterial->getMaterialProperSize();
	for (unsigned int i = 0; i < size; ++i)
	{
		pProper = pMaterial->getMaterialProper(i);
        properName = "u_" + pProper->getPropertyName();
        switch (pProper->getDataType())
        {
        case DataType_FLOAT:
            mShaderProgram.setUniform(progId, properName.c_str(),
                (float*)(pProper->getPropertyData()));
            break;
        case DataType_FLOAT_VEC2:
            mShaderProgram.setUniform(progId, properName.c_str(),
                (glm::vec2*)(pProper->getPropertyData()));
            break;
        case DataType_FLOAT_VEC3:
            mShaderProgram.setUniform(progId, properName.c_str(),
                (glm::vec3*)(pProper->getPropertyData()));
            break;
        case DataType_FLOAT_VEC4:
            mShaderProgram.setUniform(progId, properName.c_str(),
                (glm::vec4*)(pProper->getPropertyData()));
            break;
        case DataType_FLOAT_MAT3:
            mShaderProgram.setUniform(progId, properName.c_str(),
                (glm::mat3*)(pProper->getPropertyData()));
            break;
        case DataType_FLOAT_MAT4:
            mShaderProgram.setUniform(progId, properName.c_str(),
                (glm::mat4*)(pProper->getPropertyData()));
            break;
        case DataType_SAMPLER_2D:
            {
                mShaderProgram.setUniform(progId, properName.c_str(),
                    textureId);
                Texture* oneTexture = 
                    pScene->findTexture(pProper->getImagePath());
                oneTexture->bindTexture(textureId);
                textureId++;
                break;
            }              
        default:
            break;
        }
	}
    upLoadAttribute(pPrimitive->getShaderVertexId(),
        pPrimitive->getVertexBuffer(), 3);
    upLoadAttribute(pPrimitive->getShaderNormalId(), 
        pPrimitive->getNormalBuffer(), 3);
    if (textureId >0)
    {
        upLoadAttribute(pPrimitive->getShaderCoord0Id(),
            pPrimitive->getTexCoordBuffer(), 2);
    }
    setStates(pTechnique);
    pFPSCounter->gpuTimeStampStart();
    drawTriangle(pPrimitive);
    pFPSCounter->gpuTimeStampEnd();
    pFPSCounter->gpuTimeAccumulation();
    glUseProgram(0);
    glDisableVertexAttribArray(pPrimitive->getShaderVertexId());
    glDisableVertexAttribArray(pPrimitive->getShaderNormalId());
    if (textureId > 0)
        glDisableVertexAttribArray(pPrimitive->getShaderCoord0Id());
}

void RenderScene::upLoadAttribute(unsigned int shaderId, unsigned int bufferId, 
    int size)
{
	glEnableVertexAttribArray(shaderId);
	glBindBuffer(GL_ARRAY_BUFFER, bufferId);
	glVertexAttribPointer(shaderId, size, GL_FLOAT, GL_FALSE, 0, (void*)0);
	return;
}

void RenderScene::drawTriangle(class RenderPrimitive* pPrimitive)
{
	if (pPrimitive->getIndicesCount() > 0)
	{
		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, pPrimitive->getIndicesBuffer());
		glDrawElements(GL_TRIANGLES, pPrimitive->getIndicesCount(), 
			pPrimitive->getIndicesDataType(), 0);
	}
	else
	{
		glDrawArrays(GL_TRIANGLES, 0, pPrimitive->getVerterCount());
	}
}

void RenderScene::render(void* lpParam)
{
    pFPSCounter->timeStampStart();
    pFPSCounter->gpuAccumulationTimeclear();
	glTFViewport* pViewport = (glTFViewport*)lpParam;
    glViewport(pViewport->x, pViewport->y, pViewport->width, pViewport->height);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	unsigned int pSize = getPrimitiveVecSize();
	for (unsigned int i = 0; i < pSize; ++i)
	{
		renderPrimitive(getPrimitiveVec(i));
	}
    pFPSCounter->timeStampEnd();
    pFPSCounter->printFPS(pViewport);

    SwapBuffers(wglGetCurrentDC());
}

void RenderScene::releaseRender(void* lpParam)
{
    loadJson.releaseFileName();    
	return;
}

bool RenderScene::setStates(Technique *pTechnique)
{
    if (1 == pTechnique->getTechState()->blendEnable)
    {
        glEnable(GL_BLEND);
        glBlendEquation(pTechnique->getTechState()->blendEquation);
        glBlendFunc(pTechnique->getTechState()->blendFuncSfactor,
            pTechnique->getTechState()->blendFuncDfactor);
    }
    else
        glDisable(GL_BLEND);

    if (1 == pTechnique->getTechState()->cullFaceEnable)
        glEnable(GL_CULL_FACE);
    else
        glDisable(GL_CULL_FACE);

    if (1 == pTechnique->getTechState()->depthMask)
        glDepthMask(GL_TRUE);
    else
        glDepthMask(GL_FALSE);

    if (1 == pTechnique->getTechState()->depthTestEnable)
        glEnable(GL_DEPTH_TEST);
    else
        glDisable(GL_DEPTH_TEST);

    return true;
}

CPhysicalCamera* RenderScene::getCamera()
{
    return pCamera;
}

void RenderScene::renderToBuffer(glTFViewport* pViewport, unsigned char * buffer)
{
    createRenderObj(pViewport->width, pViewport->height);
    createTextureObj(pViewport->width, pViewport->height);
    createFrameBufferObj(pViewport->width, pViewport->height);
    glBindFramebuffer(GL_FRAMEBUFFER, mFBOID);
    glViewport(pViewport->x, pViewport->y, pViewport->width, pViewport->height);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glEnable(GL_DEPTH_TEST);
    unsigned int pSize = getPrimitiveVecSize();
    for (unsigned int i = 0; i < pSize; ++i)
        renderPrimitive(getPrimitiveVec(i));
    glDisable(GL_DEPTH_TEST);
    bool result = true;
    GLenum fbResult = glCheckFramebufferStatus(GL_FRAMEBUFFER);
    if( fbResult != GL_FRAMEBUFFER_COMPLETE )
        result = false;
    glReadPixels(0, 0, pViewport->width, pViewport->height, GL_BGR, 
        GL_UNSIGNED_BYTE, buffer);
    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    glDeleteFramebuffers(1, &mFBOID);
    glDeleteRenderbuffers(1,&mRBOID);
    glDeleteTextures(1,&mTextureObj);
}

void RenderScene::createRenderObj(int width, int height)
{
    glGenRenderbuffers(1, &mRBOID);
    glBindRenderbuffer(GL_RENDERBUFFER, mRBOID);
    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height);
    glBindRenderbuffer(GL_RENDERBUFFER, 0);
}

void RenderScene::createTextureObj(int width, int height)
{
    glGenTextures(1, &mTextureObj);
    glBindTexture(GL_TEXTURE_2D, mTextureObj);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, 
        GL_UNSIGNED_BYTE, NULL);
    glBindTexture(GL_TEXTURE_2D, 0);
}

bool RenderScene::createFrameBufferObj(int width, int height)
{
    GLenum status;
    glGenFramebuffers(1, &mFBOID);
    status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
    if (status != GL_FRAMEBUFFER_COMPLETE)
        return false;
    glBindFramebuffer(GL_FRAMEBUFFER, mFBOID);
    glBindTexture(GL_TEXTURE_2D, mTextureObj);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 
        mTextureObj, 0);
    status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
    if (status != GL_FRAMEBUFFER_COMPLETE)
        return false;
    glBindTexture(GL_TEXTURE_2D, 0);
    glBindRenderbuffer(GL_RENDERBUFFER, mRBOID);
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, 
        GL_RENDERBUFFER, mRBOID);
    status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
    if (status != GL_FRAMEBUFFER_COMPLETE)
        return false;
    glBindRenderbuffer(GL_RENDERBUFFER, 0);
    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    return true;
}

void RenderScene::getCameraPos(glm::vec3* Eye,glm::vec3* view,glm::vec3* up)
{
    *Eye =  pCamera->vEye;
    *view = pCamera->vView;
    *up = pCamera->vUp;
}

void RenderScene::renderRotateCamera(double horizontal, double vertical,
    double planar, double time)
{
    pCamera->rotateCamera(horizontal,vertical,planar,time);
}
void RenderScene::renderMoveCamera(double x, double y, double z,
    double time)
{
    pCamera->moveCamera(x,y,z,time);
}
