Rolling and pitching Marble

I have created a sphere, which rolls and pitches as user wish !! Need quick help !!

Here is the code :


#include"windows.h"
#include"GL/glut.h"
#include"math.h"

bool* keyBuffer = new bool[256],wired=false,isJumping=false;        // Key buffer to process arrow keys
float theta[]={0.0,0.0,0.0};                        // Rotating sphere
float size=20.0;                                    // Sphere longitude and latitude size
float radius=0.2;                                   // Sphere radius
float eyeX=0.0,eyeY=0.5,eyeZ=4.0;                   // Camera eye
float atX=0.0,atY=0.5,atZ=0.0;                      // Center of projection : Look at

void causeDelay(){
    for(int i=0;i<4000;i++)
    for(int j=0;j<4500;j++);
}

// Spins marble around based on axis and amount of fraction
void spin(int axis,float fraction){
    theta[axis]=fmod((theta[axis]+fraction),360.0);
}

// Moves marble forward and backward based on fraction param
void moveSphere(float fraction){
    float dirX,dirZ;
    dirX=atX-eyeX;
    dirZ=atZ-eyeZ;
    eyeX += dirX * fraction;
    eyeZ += dirZ * fraction;
    atX += dirX * fraction;
    atZ += dirZ * fraction;
}

// Strafes marble left and right based on fraction param
void strafeSphere(float fraction){
    float orthoX,orthoZ;
    orthoX = -(atZ-eyeZ);
    orthoZ = atX-eyeX;
    eyeX += orthoX * fraction;
    eyeZ += orthoZ * fraction;
    atX += orthoX * fraction;
    atZ += orthoZ * fraction;
}

// Rotate the camera
void rotateView(float fraction){
    float dirX,dirZ;
    dirX = atX - eyeX;
    dirZ = atZ - eyeZ;
    atZ = eyeZ + sin(fraction) * dirX + cos(fraction) * dirZ;
    atX = eyeX + cos(fraction) * dirX - sin(fraction) * dirZ;
    dirX = eyeX - atX;
    dirZ = eyeZ - atZ;
    eyeZ = atZ + sin(fraction) * dirX + cos(fraction) * dirZ;
    eyeX = atX + cos(fraction) * dirX - sin(fraction) * dirZ;
}

// Procesess the active arrow keys
void processKeys(){
    if(keyBuffer[GLUT_KEY_UP]){
        spin(0,1.0);
        moveSphere(0.01);
    }
    if(keyBuffer[GLUT_KEY_DOWN]){
        spin(0,-1.0);
        moveSphere(-0.01);
    }
    if(keyBuffer[GLUT_KEY_LEFT]){
        spin(2,0.5);
        strafeSphere(-0.01);
    }
    if(keyBuffer[GLUT_KEY_RIGHT]){
        spin(2,-0.5);
        strafeSphere(0.01);
    }
}

// Renders the marble
void renderSphere(){
    glPushAttrib(GL_ALL_ATTRIB_BITS);
    glPushMatrix();
    glColor3f(1.0,1.0,1.0);
    if(wired)
        glutWireSphere(radius,size<3?3:size,size<3?3:size);
    else
        glutSolidSphere(radius,size<3?3:size,size<3?3:size);
    glPopMatrix();
    glPopAttrib();
}

// Renders the map
void renderBase(){
    glColor3f(0.0,0.0,1.0);
    glBegin(GL_QUADS);
        glVertex3f(-3.0f, -1.0f, -50.0f);
        glVertex3f(-3.0f, -1.0f, -1.0f);
        glVertex3f( 3.0f, -1.0f, -1.0f);
        glVertex3f( 3.0f, -1.0f, -50.0f);
    glEnd();
}

// Main display function
void renderScene(){
    processKeys();
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();
    gluLookAt(  eyeX,eyeY,eyeZ,
                atX,atY,atZ,
                0.0,1.0,0.0);
    renderBase();
    glTranslatef(atX,atY-1.0,atZ-2.0);
    glRotatef(theta[0],1.0,0.0,0.0);
    glRotatef(theta[1],0.0,1.0,0.0);
    glRotatef(theta[2],0.0,0.0,1.0);
    renderSphere();
    glFlush();
    glutSwapBuffers();
}

// Sphere hops as you wish
void hopSphere(){
    int i=0;
    while(i<10){
        atY+=0.1;
        eyeY+=0.1;
        i++;
        renderScene();
        causeDelay();
    }
    while(i>0){
        atY-=0.1;
        eyeY-=0.1;
        i--;
        renderScene();
        causeDelay();
    }
}

// Reshape function done using perspective
void reshape(int w,int h){
    glViewport(0,0,w,h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(45.0f,(w*1.0)/(h>0?h:1.0),0.1,100.0);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

// Initialization of depth and lighting (TO BE DONE..)
void init(){
    glEnable(GL_DEPTH_TEST);
    ShowCursor(false);
    glutIgnoreKeyRepeat(0);
}

// Call back functions registered with keyboard

void keyDown(int key,int xx,int yy){
    keyBuffer[key]=true;
}

void keyUp(int key,int xx,int yy){
    keyBuffer[key]=false;
}

void keyPressed(unsigned char key,int xx,int yy){
    if(key==27)
        exit(0);
    if(key==32)
        hopSphere();
    if(key=='+')
        size++;
    if(key=='-')
        size=(size>3?size-1:3);
    if(key=='q'||key=='Q')
        rotateView(-0.05);
    if(key=='e'||key=='E')
        rotateView(0.05);
    if(key=='w'||key=='W')
        wired=!wired;
}

// Entry for game
int main(int argc,char** argv){
    glutInit(&argc,argv);
    glutInitDisplayMode(GLUT_RGBA|GLUT_DEPTH|GLUT_DOUBLE);
    glutGameModeString("1240x780:64@72");
    glutEnterGameMode();
    init();
    glutReshapeFunc(reshape);
    glutDisplayFunc(renderScene);
    //glutIdleFunc(spin);
    glutIdleFunc(renderScene);
    glutKeyboardFunc(keyPressed);
    glutSpecialFunc(keyDown);
    glutSpecialUpFunc(keyUp);
    glutMainLoop();
}

But, its not clean !!
[ul][li]Sphere is not placed on the base properly !! [/li] [li]Movement & pitch is not clean, its not wrt base !![/ul][/li]
Can any one guide me how to make it look more realistic ??

And, any idea how to marble fall when its not on the base ??


// Rotate the camera
void rotateView(float fraction){
    float dirX,dirZ;
//    dirX = atX - eyeX;
//    dirZ = atZ - eyeZ;
//    atZ = eyeZ + sin(fraction) * dirX + cos(fraction) * dirZ;
//    atX = eyeX + cos(fraction) * dirX - sin(fraction) * dirZ;
    dirX = eyeX - atX;
    dirZ = eyeZ - atZ;
    eyeZ = atZ + sin(fraction) * dirX + cos(fraction) * dirZ;
    eyeX = atX + cos(fraction) * dirX - sin(fraction) * dirZ;
}

This fixes rotation !!

and setting translate of sphere to

 glTranslatef(atX,atY-1.3,atZ-2.0); 

fixes its position !!

But realistic movement & pitching is still an issue !!
And idea for marble falling down too !! Please Reply SOON !!