Esempio n. 1
0
void display() {
    glEnable(GL_DEPTH_TEST);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    /*
     * See drawing.c for the definition of these routines.
     *
     * Note: Only one should be called at a time (based on the
     * display mode).
     */
    
    if (drawing3D()) {
        lightSource(true);
        draw3DModel();
    } // if
    
    else {
        lightSource(false);
        drawSurface();
    } // else

    glFlush();  /* Flush all executed OpenGL ops finish */

    onResize();

    /*
     * Since we are using double buffers, we need to call the swap
     * function every time we are done drawing.
     */
    glutSwapBuffers();
}
Esempio n. 2
0
cocos2d::Vec2 MaterialNode::getPositionForKeyShadow(float index) const {
	cocos2d::Vec2 vec = convertToWorldSpace(cocos2d::Vec2(_contentSize.width / 2, _contentSize.height / 2));
	cocos2d::Size screenSize = cocos2d::Director::getInstance()->getWinSize();
	cocos2d::Vec2 lightSource(screenSize.width / 2, screenSize.height);
	cocos2d::Vec2 normal = lightSource - vec;
	normal.normalize();

	normal = normal - cocos2d::Vec2(0, -1);

	float keySeed = index * MATERIAL_SHADOW_KEY_MOD;
	return cocos2d::Vec2(-keySeed / 2 + _padding.left, -keySeed / 2 + _padding.bottom) - normal * _shadowIndex * 0.5;
}
Esempio n. 3
0
void ShadowMapping::initialize(){

    std::shared_ptr<gland::BaseController> cameraController(new gland::CameraController(camera_, window_));
    std::shared_ptr<gland::BaseController> smController(new gland::SMController(params_, window_));
    controllers_.push_back(cameraController);  
    controllers_.push_back(smController);

    glfwSetKeyCallback(window_, &gland::Controller<gland::SMController>::keyCallback);

    params_["offsetFactor"] = gland::Param("Polygon offset factor");
    params_["offsetFactor"] = 4.0f;
    params_["offsetUnits"] = gland::Param("Polygon offset units");
    params_["offsetUnits"] = 4.0f;
    params_["renderDepth"] = gland::Param("Render depth");
    params_["renderDepth"] = false;
    params_["manualLight"] = gland::Param("Manual light");
    params_["manualLight"] = false;
    params_["angle"] = 0.0f;
    params_["lightSpeed"] = gland::Param("Light Rotation Speed");
    params_["lightSpeed"] = 1.0f;
    params_["lightRadius"] = gland::Param("Light circ. radius");
    params_["lightRadius"] = 10.0f;

    cameraController->generateHelpText(help_);
    smController->generateHelpText(help_);

    gland::ShaderDough shaderDough;
    
    shaderDough.addShaderFromFile("../src/shaders/shadowmapping_vs.glsl", GL_VERTEX_SHADER);
    shaderDough.addShaderFromFile("../src/shaders/shadowmapping_fs.glsl", GL_FRAGMENT_SHADER);

    gland::ShaderManager shaderManager;

    nViewProgram_ = shaderManager.cookDough(shaderDough);

    shaderPrograms_.push_back(nViewProgram_);

    //Light program
    gland::ShaderDough lightDough;
    
    lightDough.addShaderFromFile("../src/shaders/shadowmappinglight_vs.glsl", GL_VERTEX_SHADER);
    lightDough.addShaderFromFile("../src/shaders/shadowmappinglight_fs.glsl", GL_FRAGMENT_SHADER);

    nLightProgram_ = shaderManager.cookDough(lightDough);

    shaderPrograms_.push_back(nLightProgram_);

    //Depth program
    gland::ShaderDough depthDough;
    
    depthDough.addShaderFromFile("../src/shaders/shadowmappingdepth_vs.glsl", GL_VERTEX_SHADER);
    depthDough.addShaderFromFile("../src/shaders/shadowmappingdepth_fs.glsl", GL_FRAGMENT_SHADER);

    nDepthProgram_ = shaderManager.cookDough(depthDough);

    shaderPrograms_.push_back(nDepthProgram_);

    //Light source program
    gland::ShaderDough lightSourceDough;
    lightSourceDough.addShaderFromFile("../src/shaders/lightsource_vs.glsl", GL_VERTEX_SHADER);
    lightSourceDough.addShaderFromFile("../src/shaders/lightsource_fs.glsl", GL_FRAGMENT_SHADER);
    nLightSourceProgram_ = shaderManager.cookDough(lightSourceDough);
    shaderPrograms_.push_back(nLightSourceProgram_);

    //Frame buffer for depth
    glGenFramebuffers(1, &nDepthFbo_);
    glBindFramebuffer(GL_FRAMEBUFFER, nDepthFbo_);

    glGenTextures(1, &nDepthTex_);
    glBindTexture(GL_TEXTURE_2D, nDepthTex_);
    glTexStorage2D(GL_TEXTURE_2D, 11, GL_DEPTH_COMPONENT32F, DEPTH_TEXTURE_SIZE, DEPTH_TEXTURE_SIZE);
    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_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);

    glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, nDepthTex_, 0);

    glGenTextures(1, &nDepthDebug_);
    glBindTexture(GL_TEXTURE_2D, nDepthDebug_);
    glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32F, DEPTH_TEXTURE_SIZE, DEPTH_TEXTURE_SIZE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, nDepthDebug_, 0);

    glBindTexture(GL_TEXTURE_2D, 0);
    glBindFramebuffer(GL_FRAMEBUFFER, 0);


    //VAO for drawing depth texture
    glGenVertexArrays(1, &nQuadVao_);
    glBindVertexArray(nQuadVao_);


    glEnable(GL_DEPTH_TEST);

    //Add object
    std::string inputfile = "../res/sphere.obj";
    std::vector<tinyobj::shape_t> shapes;
    std::string err = tinyobj::LoadObj(shapes, inputfile.c_str());
    std::shared_ptr<gland::Body> obj(new gland::Body(shapes[0]));
    obj->setShader(nViewProgram_);
    obj->translate(3.0f, 0.0f, -3.0f);
    standardObjects_.push_back(obj);

    //Add another sphere
    std::shared_ptr<gland::Body> sphere2(new gland::Body(shapes[0]));
    sphere2->setShader(nViewProgram_);
    sphere2->translate(-10.0f, -0.0f, -2.0f);
    standardObjects_.push_back(sphere2);

    inputfile = "../res/thickblock.obj";
    err = tinyobj::LoadObj(shapes, inputfile.c_str());
    std::shared_ptr<gland::Body> floor(new gland::Body(shapes[0]));
    floor->setShader(nViewProgram_);
    floor->rotate(0.0f, 1.0f, 0.0f, 0.0f);
    floor->translate(0.0f, 0.0f, -5.0f);
    standardObjects_.push_back(floor);

    inputfile = "../res/monkey.obj";
    err = tinyobj::LoadObj(shapes, inputfile.c_str());
    std::shared_ptr<gland::Body> monkey(new gland::Body(shapes[0]));
    monkey->setShader(nViewProgram_);
    monkey->translate(-2.0f, -0.0f, 0.0f);
    standardObjects_.push_back(monkey);

    inputfile = "../res/light.obj";
    err = tinyobj::LoadObj(shapes, inputfile.c_str());
    std::shared_ptr<gland::Body> lightSource(new gland::Body(shapes[0]));
    lightSource->setShader(nLightSourceProgram_);
    lightSources_.push_back(lightSource);

    glEnable (GL_CULL_FACE); // cull face
    glCullFace (GL_BACK); // cull back face
    //glFrontFace (GL_CW); // GL_CCW for counter clock-wise
            
    //Look at center
    camera_->lookAt(glm::vec3(0.0f, 0.0f, 20.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));

}
Esempio n. 4
0
uniform mat3 m_3x3_inv_transp;
varying vec4 color;
 
struct lightSource
{
  vec4 position;
  vec4 diffuse;
  float constantAttenuation, linearAttenuation, quadraticAttenuation;
  float spotCutoff, spotExponent;
  vec3 spotDirection;
};

lightSource light0 = lightSource(
    vec4(0.0,  1.0,  2.0, 1.0),
    vec4(1.0, 1.0, 1.0, 1.0),
    0.0, 1.0, 0.0,
    80.0, 20.0,
    vec3(-1.0, -0.5, -1.0)
);
 
struct material
{
  vec4 diffuse;
};
material mymaterial = material(vec4(1.0, 0.8, 0.8, 1.0));
 
void main(void)
{
  mat4 mvp = p*v*m;
  vec3 normalDirection = normalize(m_3x3_inv_transp * v_normal);
  vec3 lightDirection;
void RTRRadianceRenderer::execute()
{
    //If kd-tree exists, free them.
    if (diffusePhotonMap != nullptr)
    {
        delete diffusePhotonMap;
    }
    if (causticPhotonMap != nullptr)
    {
        delete causticPhotonMap;
    }

    std::vector<RTRRenderElement*> emissionElements;
    for (auto element : elements)
    {
        if (element->material->emissionStrength > 0.0001)
        {
            //qDebug() << "Emission object!";
            emissionElements.push_back(element);
        }
    }

    /*for (int i = 0; i < 20; i++)
    {
        qDebug() << sampler->generateInteger(0, emissionElements.size() - 1);
    }*/

    //QVector<Photon*> diffusePhotons;
    const int PHOTON_COUNT = 500000;

    while(allPhotons.size() < PHOTON_COUNT)
    {
        RTRVector3D lightSource(-1.2 + sampler->generateRandomNumber(-1.0, 1.0)
                                                        , 0 + sampler->generateRandomNumber(-2.0, 2.0)
                                                        , 4.99);
        RTRVector3D lightDirection;
        lightDirection = sampler->generateRandomDirection();
        /*do {
            lightDirection = sampler->generateRandomDirection();
        } while(lightDirection.z() > 0);*/
        lightDirection.vectorNormalize();
        renderPhoton(lightSource, lightDirection, allPhotons, false);
        if (allPhotons.size() % 1000 == 0)
        {
            qDebug() << allPhotons.size();
        }
    }
    int causticPhotonCount = 0;
    int diffusePhotonCount = 0;
    for(int i = 0; i < PHOTON_COUNT; i++)
    {
        if(allPhotons[i]->type == Photon::Type::CAUSTIC)
        {
            causticPhotonCount++;
        }
        else
        {
            diffusePhotonCount++;
        }
    }
    qDebug() << "CAUSTIC " << causticPhotonCount;
    qDebug() << "DIFFUSE " << diffusePhotonCount;
    stlDiffusePhotons.clear();
    stlDiffusePhotons = allPhotons.toStdVector();
    while(causticPhotons.size() < 5000)
    {
        RTRVector3D lightSource(-1.2 + sampler->generateRandomNumber(-1.0, 1.0)
                                                          , 0 + sampler->generateRandomNumber(-2.0, 2.0)
                                                          , 4.99);
        RTRVector3D lightDirection;
        do {
            lightDirection = sampler->generateRandomDirection();
        } while(lightDirection.z() > 0);
        lightDirection.vectorNormalize();
        renderPhoton(lightSource, lightDirection, causticPhotons, true);
        //qDebug() << causticPhotons.size();
        if (causticPhotons.size() > 0 && causticPhotons.size() % 1000 == 0)
        {
            qDebug() << causticPhotons.size();
        }
    }
    stlCausticPhotons.clear();
    stlCausticPhotons = causticPhotons.toStdVector();
    causticPhotonAdapter = new NanoFlannPhotonAdaptor(stlCausticPhotons);
    diffusePhotonAdapter = new NanoFlannPhotonAdaptor(stlDiffusePhotons);
    causticPhotonMap = new PhotonKdTree(3, *causticPhotonAdapter);
    causticPhotonMap->buildIndex();
    diffusePhotonMap = new PhotonKdTree(3, *diffusePhotonAdapter);
    diffusePhotonMap->buildIndex();
    //causticPhotonMap = NearestSearchKdTree<Photon*, double, 3, AccessRTRVector3D>::construct(causticPhotons.toStdVector());
    //diffusePhotonMap = NearestSearchKdTree<Photon, double, 3, AccessRTRVector3D>::construct(diffusePhotons.toStdVector());
    qDebug() << causticPhotons.size();
    qDebug() << stlDiffusePhotons.size();
}
Esempio n. 6
0
/*
 *  OpenGL (GLUT) calls this routine to display the scene
 */
void display()
{
   //  Erase the window and the depth buffer
   glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
   //  Enable Z-buffering in OpenGL
   glEnable(GL_DEPTH_TEST);
   //  Undo previous transformations
   glLoadIdentity();
   //  Orthogonal - set world orientation
   //glTranslated(pos[0],0,pos[1]);
   glRotatef(ph,1,0,0);
   glRotatef(th,0,1,0);
    
    //  Flat or smooth shading
    glShadeModel(smooth ? GL_SMOOTH : GL_FLAT);
    
    // Add light to the scene
    if (light)
    {
        //  Translate intensity to color vectors
        float Ambient[]   = {0.01*ambient ,0.01*ambient ,0.01*ambient ,1.0};
        float Diffuse[]   = {0.01*diffuse ,0.01*diffuse ,0.01*diffuse ,1.0};
        float Specular[]  = {0.01*specular,0.01*specular,0.01*specular,1.0};
        //  Light position
        float Position[]  = {distance*Cos(zh),ylight,distance*Sin(zh),1.0};
        //  Draw light position as ball (still no lighting here)
        glColor3f(1,1,1);
        lightSource(Position[0],Position[1],Position[2] , 0.1);
        //  OpenGL should normalize normal vectors
        glEnable(GL_NORMALIZE);
        //  Enable lighting
        glEnable(GL_LIGHTING);
        //  Location of viewer for specular calculations
        glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER,local);
        //  glColor sets ambient and diffuse color materials
        glColorMaterial(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE);
        glEnable(GL_COLOR_MATERIAL);
        //  Enable light 0
        glEnable(GL_LIGHT0);
        //  Set ambient, diffuse, specular components and position of light 0
        glLightfv(GL_LIGHT0,GL_AMBIENT ,Ambient);
        glLightfv(GL_LIGHT0,GL_DIFFUSE ,Diffuse);
        glLightfv(GL_LIGHT0,GL_SPECULAR,Specular);
        glLightfv(GL_LIGHT0,GL_POSITION,Position);
    }
    else
        glDisable(GL_LIGHTING);
    // Draw Bell towers
    bell(8,2,-6,.25);
    bell(-8,2,-6,.25);
    
    for (int i = -9; i <= 9; i+=2){
        for (int j = -5; j <= 5; j +=4){
            floorTiles(i,-.5,j,1.2,0);
        }
    }
    for (int i = -8; i <= 8; i+=2){
        for (int j = -3; j <= 5; j +=4){
            floorTiles(i,-.5,j,1.2,.5);
        }
    }
   
    
   // Draw Game grid
     for (int k = -4; k <= -1; k++){
        cube(k,0,-4, .5,.5,.5 , 0);
        cube(k,0,4, .5,.5,.5 , 0);
        cube(-4,0,k, .5,.5,.5 , 0);
        cube(4,0,k, .5,.5,.5 , 0);
    }
    for (int k = 1; k <= 4; k++){
        cube(k,0,-4, .5,.5,.5 , 0);
        cube(k,0,4, .5,.5,.5 , 0);
        cube(-4,0,k, .5,.5,.5 , 0);
        cube(4,0,k, .5,.5,.5 , 0);
    }
    for (int k = -10; k <= 10; k++){
        cube(k,0,-6, .5,.5,.5 , 0);
        cube(k,0,6, .5,.5,.5 , 0);
    }
    for (int k = -6; k <= 6; k++){
        cube(-10,0,k, .5,.5,.5 , 0);
        cube(10,0,k, .5,.5,.5 , 0);
    }
    for (int k = -4; k <= 4; k++){
        cube(-8,0,k, .5,.5,.5 , 0);
        cube(8,0,k, .5,.5,.5 , 0);
    }
    for (int k = -6; k <= -5; k++){
        cube(-6,0,k, .5,.5,.5 , 0);
        cube(6,0,k, .5,.5,.5 , 0);
    }
    for (int k = -3; k <= 3; k++){
        cube(-6,0,k, .5,.5,.5 , 0);
        cube(6,0,k, .5,.5,.5 , 0);
    }
    for (int k = 5; k <= 6; k++){
        cube(-6,0,k, .5,.5,.5 , 0);
        cube(6,0,k, .5,.5,.5 , 0);
    }
    for (int j = -2; j <= -1; j++){
        cube(j,0,-2, .5,.5,.5 , 0);
        cube(j,0,2, .5,.5,.5 , 0);
        cube(-2,0,j, .5,.5,.5 , 0);
        cube(2,0,j, .5,.5,.5 , 0);
    }
    for (int l = 1; l <= 2; l++){
        cube(l,0,-2, .5,.5,.5 , 0);
        cube(l,0,2, .5,.5,.5 , 0);
        cube(-2,0,l, .5,.5,.5 , 0);
        cube(2,0,l, .5,.5,.5 , 0);
    }
    for (int i = -6; i <= 6; i++){
        for (int j = -10; j <= 10; j++){
            if (balls[i+6][j+10] == 1){
                ball(j,0,i, 0.1,4);
            }
        }
    }
    
   // Draw ghosts and animate movement
    //Red Ghost Movement
    if (redTrack == 0){
        posx1 += dx;
        ghost(posx1,0,-5 , 0.4, 0, 0);
        if (posx1 >= -7){
            redTrack = 1;
        }
        glutIdleFunc(idle);
    }
    else if (redTrack == 1){
        posz1 += dx;
        ghost(-7,0,posz1 , 0.4, 0, 0);
        if (posz1 >= 5){
            redTrack = 2;
        }
        glutIdleFunc(idle);
    }
    else if (redTrack == 2){
        posx1 -= dx;
        ghost(posx1,0,5 , 0.4, 0, 0);
        if (posx1 <= -9){
            redTrack = 3;
        }
        glutIdleFunc(idle);
    }
    else if (redTrack == 3){
        posz1 -= dx;
        ghost(-9,0,posz1 , 0.4, 0, 0);
        if (posz1 <= -5){
            redTrack = 0;
        }
        glutIdleFunc(idle);
    }
   
    //Blue Ghost Movement
    if (blueTrack == 0){
        posx2 += dx;
        ghost(posx2,0,-5 , 0.4, 0, 1);
        if (posx2 >= 5){
            blueTrack = 1;
        }
        glutIdleFunc(idle);
    }
    else if (blueTrack == 1){
        posz2 += dx;
        ghost(5,0,posz2 , 0.4, 0, 1);
        if (posz2 >= 5){
            blueTrack = 2;
        }
        glutIdleFunc(idle);
    }
    else if (blueTrack == 2){
        posx2 -= dx;
        ghost(posx2,0,5 , 0.4, 0, 1);
        if (posx2 <= -5){
            blueTrack = 3;
        }
        glutIdleFunc(idle);
    }
    else if (blueTrack == 3){
        posz2 -= dx;
        ghost(-5,0,posz2 , 0.4, 0, 1);
        if (posz2 <= -5){
            blueTrack = 0;
        }
        glutIdleFunc(idle);
    }
    
    //Pink Ghost Movement
    if (pinkTrack == 0){
        posx3 += dx;
        ghost(posx3,0,-5 , 0.4, 0, 2);
        if (posx3 >= 9){
            pinkTrack = 1;
        }
        glutIdleFunc(idle);
    }
    else if (pinkTrack == 1){
        posz3 += dx;
        ghost(9,0,posz3 , 0.4, 0, 2);
        if (posz3 >= 5){
            pinkTrack = 2;
        }
        glutIdleFunc(idle);
    }
    else if (pinkTrack == 2){
        posx3 -= dx;
        ghost(posx3,0,5 , 0.4, 0, 2);
        if (posx3 <= 7){
            pinkTrack = 3;
        }
        glutIdleFunc(idle);
    }
    else if (pinkTrack == 3){
        posz3 -= dx;
        ghost(7,0,posz3 , 0.4, 0, 2);
        if (posz1 <= -5){
            pinkTrack = 0;
        }
        glutIdleFunc(idle);
    }
    
    //Orange Ghost Movement
    if (orangeTrack == 0){
        posx4 += dx;
        ghost(posx4,0,-3 , 0.4, 0, 3);
        if (posx4 >= 3){
            orangeTrack = 1;
        }
        glutIdleFunc(idle);
    }
    else if (orangeTrack == 1){
        posz4 += dx;
        ghost(3,0,posz4 , 0.4, 0, 3);
        if (posz4 >= 0){
            orangeTrack = 2;
        }
        glutIdleFunc(idle);
    }
    else if (orangeTrack == 2){
        posx4 += dx;
        ghost(posx4,0,0 , 0.4, 0, 3);
        if (posx4 >= 5){
            orangeTrack = 3;
        }
        glutIdleFunc(idle);
    }
    else if (orangeTrack == 3){
        posz4 -= dx;
        ghost(5,0,posz4 , 0.4, 0, 3);
        if (posz4 <= -4){
            orangeTrack = 4;
        }
        glutIdleFunc(idle);
    }
    else if (orangeTrack == 4){
        posx4 += dx;
        ghost(posx4,0,-4 , 0.4, 0, 3);
        if (posx4 >= 7){
            orangeTrack = 5;
        }
        glutIdleFunc(idle);
    }
    else if (orangeTrack == 5){
        posz4 += dx;
        ghost(7,0,posz4 , 0.4, 0, 3);
        if (posz4 >= 4){
            orangeTrack = 6;
        }
        glutIdleFunc(idle);
    }
    else if (orangeTrack == 6){
        posx4 -= dx;
        ghost(posx4,0,4 , 0.4, 0, 3);
        if (posx4 <= 5){
            orangeTrack = 7;
        }
        glutIdleFunc(idle);
    }
    else if (orangeTrack == 7){
        posz4 += dx;
        ghost(5,0,posz4 , 0.4, 0, 3);
        if (posz4 >= 5){
            orangeTrack = 8;
        }
        glutIdleFunc(idle);
    }
    else if (orangeTrack == 8){
        posx4 -= dx;
        ghost(posx4,0,5 , 0.4, 0, 3);
        if (posx4 <= -5){
            orangeTrack = 9;
        }
        glutIdleFunc(idle);
    }
    else if (orangeTrack == 9){
        posz4 -= dx;
        ghost(-5,0,posz4 , 0.4, 0, 3);
        if (posz4 <= 4){
            orangeTrack = 10;
        }
        glutIdleFunc(idle);
    }
    else if (orangeTrack == 10){
        posx4 -= dx;
        ghost(posx4,0,4 , 0.4, 0, 3);
        if (posx4 <= -7){
            orangeTrack = 11;
        }
        glutIdleFunc(idle);
    }
    else if (orangeTrack == 11){
        posz4 -= dx;
        ghost(-7,0,posz4 , 0.4, 0, 3);
        if (posz4 <= -4){
            orangeTrack = 12;
        }
        glutIdleFunc(idle);
    }
    else if (orangeTrack == 12){
        posx4 += dx;
        ghost(posx4,0,-4 , 0.4, 0, 3);
        if (posx4 >= -5){
            orangeTrack = 13;
        }
        glutIdleFunc(idle);
    }
    else if (orangeTrack == 13){
        posz4 += dx;
        ghost(-5,0,posz4 , 0.4, 0, 3);
        if (posz4 >= 0){
            orangeTrack = 14;
        }
        glutIdleFunc(idle);
    }
    else if (orangeTrack == 14){
        posx4 += dx;
        ghost(posx4,0,0 , 0.4, 0, 3);
        if (posx4 >= -3){
            orangeTrack = 15;
        }
        glutIdleFunc(idle);
    }
    else if (orangeTrack == 15){
        posz4 -= dx;
        ghost(-3,0,posz4 , 0.4, 0, 3);
        if (posz4 <= -3){
            orangeTrack = 16;
        }
        glutIdleFunc(idle);
    }
    else if (orangeTrack == 16){
        posx4 += dx;
        ghost(posx4,0,-3 , 0.4, 0, 3);
        if (posx4 >= 0){
            orangeTrack = 0;
        }
        glutIdleFunc(idle);
    }
    
    // Win condition
    if (score == 132){
        glPopMatrix();
        glDisable(GL_LIGHTING);
        //  Display parameters
        glColor3f(1,1,1);
        glWindowPos2i(400,400);
        Print("Congratulations: You Win");
        pos[0] = 0;
        pos[1] = 0;
    }
    
   // Detect ghost collision
   if ((pos[0] == posx1 && pos[1] == posz1) ||
        (pos[0] == posx2 && pos[1] == posz2) ||
        (pos[0] == posx3 && pos[1] == posz3) ||
        (pos[0] == posx4 && pos[1] == posz4)){
        lives--;
        dead = 1;
        if (lives == 0){
            done = 1;
        }
    }
    // Draw Pacman
    if (dead == 0){
        pacman(pos[0],0,pos[1], .4,0,press);
    }
    else if (done == 1){
        glPopMatrix();
        glDisable(GL_LIGHTING);
        //  Display parameters
        glColor3f(1,1,1);
        glWindowPos2i(400,400);
        Print("Game Over");
        pos[0] = 0;
        pos[1] = 0;
    }
    else{
        pos[0] = 0;
        pos[1] = 0;
        dead = 0;
        pacman(pos[0],0,pos[1], .4,0,press);
        glutPostRedisplay();
    }

   glPopMatrix();
   glDisable(GL_LIGHTING);
   //  Display parameters
   glColor3f(1,1,1);
   glWindowPos2i(5,5);
   Print("Lives:%i Score=%i",lives,score);
   //  Render the scene and make it visible
   glFlush();
   glutSwapBuffers();
}