GLProgramming.com

home :: about :: development guides :: irc :: forums :: search :: paste :: links :: contribute :: code dump

-> Click here to learn how to get live help <-


New Paste :: Recent Pastes:: Add Line Numbers


picking ray main.cpp by Pompei2
#include <stdio.h>
#include <math.h>

#include <GL/gl.h>
#include <GL/glu.h>
#include <SDL/SDL.h>

#include "camera.h"

/* -------------------------- */
/* Local prototypes           */
/* -------------------------- */
int mousePressed( int x, int y );
int Render3D( void );
int enter2DMode( void );
int enter3DMode( void );
int resizeWindow( void );
int cameraMovement( void );
int enterMainLoop(int in_iVideoFlags );
int initSDL( void );
int initGL( void );

/* -------------------------- */
/* Var's                      */
/* -------------------------- */
// The camera object.
CCamera *g_camera = NULL;
// The SDL Screen.
SDL_Surface *g_screen = NULL;

// The pick ray direction and origin.
SPos3D g_rayDir;
SPos3D g_rayOrig;

/** Transforms \a deg into radians. */
#define RAD( deg ) (deg) / 57.295779513f

/** Transforms \a rad into degrees. */
#define DEG( rad ) (rad) * 57.295779513f

int main(int argc, char *argv[] )
{
    int videoFlags = 0;

    /* Initialisations. */
    videoFlags = initSDL( );
    if( videoFlags < 0 )
        return -1;

    if( ERR_OK != initGL( ) )
        return -2;

    g_camera = new CCamera;

    resizeWindow( );
    /* End of initialisations. */

    enterMainLoop( videoFlags );

    /* de-init. */
    delete g_camera;
    SDL_Quit( );

    return 0;
}

/* General SDL video initialization function */
int initSDL( void )
{
    /* Flags to pass to SDL_SetVideoMode */
    int videoFlags;
    /* This holds some info about our display */
    const SDL_VideoInfo *videoInfo;

    /* First of all, init SDL */
    if( -1 == SDL_Init( SDL_INIT_VIDEO ) ) {
        printf( "SDL_Init: %s\n", SDL_GetError(  ) );
        return -1;
    }

    /* Fetch the video info */
    videoInfo = SDL_GetVideoInfo( );
    if( !videoInfo ) {
        printf( "SDL_Query: %s\n", SDL_GetError( ) );
        return -2;
    }

    /* The flags to pass to SDL_SetVideoMode */
    videoFlags  = SDL_OPENGL;          /* Enable OpenGL in SDL */
    videoFlags |= SDL_GL_DOUBLEBUFFER; /* Enable double buffering */
    videoFlags |= SDL_HWPALETTE;       /* Store the palette in hardware */

    /* This checks to see if surfaces can be stored in memory */
    if( videoInfo->hw_available )
        videoFlags |= SDL_HWSURFACE;
    else
        videoFlags |= SDL_SWSURFACE;

    /* This checks if hardware blits can be done */
    if( videoInfo->blit_hw )
        videoFlags |= SDL_HWACCEL;

    /* Sets up OpenGL double buffering */
    SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );

    /* get a SDL screen surface */
    g_screen = SDL_SetVideoMode( 800, 600, 32, videoFlags );
    if( !g_screen ) {
        printf( "SDL_Mode: %s\n", SDL_GetError( ) );
        return -3;
    }

    return videoFlags;
}

/* general OpenGL initialization function */
int initGL( void )
{
    glShadeModel( GL_SMOOTH );
    glClearColor( 0.0f, 0.0f, 0.5f, 0.0f );
    glClearDepth( 1.0f );

    glEnable( GL_DEPTH_TEST );
    glDepthFunc( GL_LEQUAL );

    return ERR_OK;
}

int enterMainLoop(int in_iVideoFlags )
{
    SDL_Event sdlEvent;
    bool bQuit = false;

    while( !bQuit ) {
        while( SDL_PollEvent( &sdlEvent ) ) {
            switch( sdlEvent.type ) {
            case SDL_MOUSEBUTTONDOWN:
                mousePressed( sdlEvent.button.x, sdlEvent.button.y );
                break;
            case SDL_QUIT:
                bQuit = true;
                break;
            default:
                break;
            }
        }
        Render3D( );
        enter2DMode( );
        enter3DMode( );
        SDL_GL_SwapBuffers( );
    }

    return ERR_OK;
}

/* Enterinto the 2D mode, this means 1 unit is 1 pixel */
int enter2DMode( void )
{
    /* Note, there may be other things you need to change,
     * depending on how you have your OpenGL state set up
     */
    glPushAttrib( GL_ENABLE_BIT );
    glDisable( GL_DEPTH_TEST );
    glDisable( GL_CULL_FACE  );
    glDisable( GL_LIGHTING );
    glEnable( GL_TEXTURE_2D );

    /* This allows alpha blending of 2D textures. */
    glEnable( GL_BLEND );
    glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );

    glMatrixMode( GL_PROJECTION );
    glLoadIdentity( );

    /* Set the orthonormed system to the pixel unit (1 unit = 1 pixel) */
    glOrtho( 0.0, 800, 600, 0.0, 0.0, 1.0 );

    glMatrixMode( GL_MODELVIEW );
    glLoadIdentity( );

    glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );

    return ERR_OK;
}

/* Goes backinto the 3D mode */
int enter3DMode( void )
{
    glPopAttrib( );
    resizeWindow( );
    return ERR_OK;
}

int resizeWindow( void )
{
    /* width/height ration */
    float fRatio = 800.0f / 600.0f;

    /* change to the projection matrix and set our viewing volume. */
    glMatrixMode( GL_PROJECTION );
    glLoadIdentity( );

    /* Set our perspective and move around. */
    /* I dont know why, but i tested it: 30 is the perfect value ; on bigger values,
     * when drawing things far away, sometimes you see them mirrored on the top !?
     * Go ask mathematical genies to know why :p and then tell me ^^
     */
    gluPerspective( 30.0f, fRatio, 1.0f, 1000.0f );

    /* Make sure we're chaning the model view and not the projection */
    glMatrixMode( GL_MODELVIEW );

    /* Reset The View */
    glLoadIdentity( );
    cameraMovement( );

    return ERR_OK;
}

int cameraMovement( void )
{
    float a = RAD(SDL_GetTicks() / 75.0f);

    g_camera->setPos( 0.1f, 10 * sinf(a), 10 * cosf(a) );
    g_camera->target( 1.0f, 1.0f, 0.0f );
    g_camera->render( );

    return ERR_OK;
}

int Render3D( void )
{
    /* Clear The Screen And The Depth Buffer */
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

    // Draw the pick ray, with origin 0 (so we can see it.)
    glBegin( GL_LINES );
    glColor3f( 1.0f, 1.0f, 1.0f );
    glVertex3f( 0.0f, 0.0f, 0.0f );
    glColor3f( 0.5f, 0.5f, 0.5f );
    glVertex3f( g_rayDir.x, g_rayDir.y, g_rayDir.z );
    glEnd( );

    // Draw the XYZ axes. */
    glBegin( GL_LINES );
    glColor3f( 1.0f, 0.0f, 0.0f );
    glVertex3f( 0.0f, 0.0f, 0.0f );
    glVertex3f( 1000.0f, 0.0f, 0.0f );
    glColor3f( 0.0f, 1.0f, 0.0f );
    glVertex3f( 0.0f, 0.0f, 0.0f );
    glVertex3f( 0.0f, 1000.0f, 0.0f );
    glColor3f( 0.0f, 0.0f, 1.0f );
    glVertex3f( 0.0f, 0.0f, 0.0f );
    glVertex3f( 0.0f, 0.0f,-1000.0f );
    glEnd( );
}

int mousePressed( int x, int y )
{
    SPos3D v0;
    SPos3D v1;
    double proj[16];
    double modv[16];
    int viewport[4];

    // Get the matrices.
    g_camera->getModelviewMatrix ( modv );
    g_camera->getProjectionMatrix( proj );
    glGetIntegerv( GL_VIEWPORT, viewport );

    gluUnProject( x, y, 0.0f, modv, proj, viewport, (double *)&v0.x, (double *)&v0.y, (double *)&v0.z );
    gluUnProject( x, y, 1.0f, modv, proj, viewport, (double *)&v1.x, (double *)&v1.y, (double *)&v1.z );

    g_rayDir = v1 - v0;
    v_normalize( &g_rayDir );

    g_rayOrig.x = g_camera->x( );
    g_rayOrig.y = g_camera->y( );
    g_rayOrig.z = g_camera->z( );

    printf( "origin: (%f,%f,%f)\n", g_rayOrig.x, g_rayOrig.y, g_rayOrig.z );
    printf( "direct: (%f,%f,%f)\n", g_rayDir.x,  g_rayDir.y,  g_rayDir.z );

    return ERR_OK;
}