ColrCube.c


/* colrcube.c - A simple VR program to illustrate the
        color cube and the dynamic modification of 
        vertex colors.
        for Eng 591, Virtual Reality Programming.

        Written October 1999 by John T. Bell

        Last modified _________ by __________
*/


#include <stdlib.h>
#include <stdio.h>
#include "wt.h"

/* Function Prototypes */

void UserActions( void );

/* Global Variables - Use only when NECESSARY */

WTpq InitialView = { { 75.0f, -55.0f, -200.0f }, { 0.0f, 0.0f, 0.0f, 1.0f } };
WTnode *Root = NULL;
WTviewpoint *Viewpoint = NULL;
WTsensor *Mouse = NULL;
WTfont3d *Font = NULL;

WTnode *RedPlane = NULL, *GreenPlane = NULL, *BluePlane = NULL;
WTnode *RedText = NULL, *GreenText = NULL, *BlueText = NULL;
WTnode *RedXform = NULL, *GreenXform = NULL, *BlueXform = NULL;
unsigned char Red = 128, Green = 128, Blue = 128;

int main ( int argc, char **argv )

{
        /* Local Variables */

        char buffer[ 80 ];
        unsigned char red, green, blue;
        int i;

        WTp3 p3, lightPosition = { -100.0, -100.0, 0.0 };
        WTpq redpq =   { { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.7071f, 0.0f, 0.7071f } };
        WTpq greenpq = { { 0.0f, 0.0f, 0.0f }, { 0.7071f, 0.0f, 0.0f, 0.7071f } };

        WTp3 redp3 = { 30.0f, -15.0f, 0.0f }, greenp3 = { 30.0f, 5.0f, 0.0f },
                bluep3 = { 30.0f, 25.0f, 0.0f };

        WTp3 lightDirections[ 6 ] = { { 1.0f, 0.0f, 0.0f }, { -1.0f, 0.0f, 0.0f },
                { 0.0f, 1.0f, 0.0f }, { 0.0f, -1.0f, 0.0f }, { 0.0f, 0.0f, 1.0f },
                { 0.0f, 0.0f, -1.0f } };

        WTnode *node = NULL, *textSep = NULL;
        WTgeometry *geo = NULL;
        WTvertex *vertex = NULL;

        /* Intialize the Universe */
        
        WTuniverse_new( WTDISPLAY_DEFAULT, WTWINDOW_DEFAULT );
        
        /* Set some global variables */
        
        Root = WTuniverse_getrootnodes();
        Viewpoint = WTuniverse_getviewpoints();
        WTuniverse_setbgrgb( 255, 255, 255 );

        /* Set up devices */

        WTkeyboard_open();

        Mouse = WTmouse_new();
        if( !Mouse )
            WTerror( "Sorry;  A mouse is required to run"
                " this program.\n" );
        else {
            WTmotionlink_new( Mouse, Viewpoint, WTSOURCE_SENSOR, 
                    WTTARGET_VIEWPOINT );
        }

        /* Build the scene graph */

        /* The lights have to be arranged carefully.
           We want full illumination on the planes, all sides,
           but the text needs angled light for 3D shading.
        
           The lights hung off of textSep will only illuminate
           the 3-D text.  The following six lights will fully
           illuminate the color planes from all sides, withou
           affecting the 3-D text */


        textSep = WTsepnode_new( Root );
        WTlightnode_newdirected( textSep );
        node = WTlightnode_newpoint( textSep );
        WTlightnode_setposition( node, lightPosition );

        for( i = 0; i < 6; i++ ) {
                node = WTlightnode_newdirected( Root );
                WTlightnode_setdirection( node, lightDirections[ i ] );
        }

        /* Create the Color Cube in wire frame mode */

        geo = WTgeometry_newblock( 50.0f, 50.0f, 50.0f, TRUE );
        WTgeometry_beginedit( geo );
        for( vertex = WTgeometry_getvertices( geo ); vertex; 
                vertex = WTvertex_next ( vertex ) ) {

                WTgeometry_getvertexposition( geo, vertex, p3 );
                red = 255 * ( p3[ X ] > 0.0f );
                green = 255 * ( p3[ Y ] < 0.0f );
                blue = 255 * ( p3[ Z ] > 0.0f );
                WTgeometry_setvertexrgb( geo, vertex, red, green, blue );
        }
        WTgeometry_endedit( geo );
        WTgeometry_setrenderingstyle( geo, WTRENDER_WIREFRAME, TRUE );
        WTgeometrynode_new( Root, geo );

        /* Create the Red Color Plane and Text */

        geo = WTgeometry_newrectangle ( 50.0f, 50.0f, TRUE );
        WTgeometry_transform( geo, &redpq );
        vertex = WTgeometry_getvertices( geo );
        WTgeometry_beginedit( geo );
        for( i = 0; i < 4; i++ ) {
                WTgeometry_setvertexrgb( geo, vertex, Red, 
                        ( ( i + 1 ) / 2 == 1 ) * 255, ( i < 2 ) * 255 );
                vertex = WTvertex_next( vertex );
        }
        WTgeometry_endedit( geo );
        RedPlane = WTmovgeometrynode_new( Root, geo );

        Font = WTfont3d_load( "RCFONT3D.NFF" ); /* Needed once only */

        sprintf( buffer, "Red   = %3d ( %f )", Red, Red / 255.0f );
        geo = WTgeometry_newtext3d( Font, buffer );
        WTgeometry_setrgb( geo, Red, 0, 0 );
        RedXform = WTmovsepnode_new( textSep );
        WTnode_settranslation( RedXform, redp3 );
        RedText = WTgeometrynode_new( RedXform, geo );

        /* Create the Green Color Planes and Text */

        geo = WTgeometry_newrectangle ( 50.0f, 50.0f, TRUE );
        WTgeometry_transform( geo, &greenpq );
        vertex = WTgeometry_getvertices( geo );
        WTgeometry_beginedit( geo );
        for( i = 0; i < 4; i++ ) {
                WTgeometry_setvertexrgb( geo, vertex, ( i < 2 ) * 255, 
                        Green, ( ( i + 1 ) / 2 == 1 ) * 255 );
                vertex = WTvertex_next( vertex );
        }
        WTgeometry_endedit( geo );
        GreenPlane = WTmovgeometrynode_new( Root, geo );

        sprintf( buffer, "Green = %3d ( %f )", Green, Green / 255.0f );
        geo = WTgeometry_newtext3d( Font, buffer );
        WTgeometry_setrgb( geo, 0, Green, 0 );
        GreenXform = WTmovsepnode_new( textSep );
        WTnode_settranslation( GreenXform, greenp3 );
        GreenText = WTgeometrynode_new( GreenXform, geo );

        /* Create the Blue Color Planes and Text */

        geo = WTgeometry_newrectangle ( 50.0f, 50.0f, TRUE );
        /* Blue Plane needs no rotation */
        vertex = WTgeometry_getvertices( geo );
        WTgeometry_beginedit( geo );
        for( i = 0; i < 4; i++ ) {
                WTgeometry_setvertexrgb( geo, vertex, ( i < 2 ) * 255, 
                        ( ( i + 1 ) / 2 == 1 ) * 255, Blue );
                vertex = WTvertex_next( vertex );
        }
        WTgeometry_endedit( geo );
        BluePlane = WTmovgeometrynode_new( Root, geo );

        sprintf( buffer, "Blue  = %3d ( %f )", Blue, Blue / 255.0f );
        geo = WTgeometry_newtext3d( Font, buffer );
        WTgeometry_setrgb( geo, 0, 0, Blue );
        BlueXform = WTmovsepnode_new( textSep );
        WTnode_settranslation( BlueXform, bluep3 );
        BlueText = WTgeometrynode_new( BlueXform, geo );

        /* Initialize the viewpoint */

        /*WTwindow_zoomviewpoint( WTuniverse_getcurrwindow() );*/
        WTviewpoint_moveto( Viewpoint, &InitialView );
        
        /* Setup the action function */
        
        WTuniverse_setactions( UserActions );

        /* The "go" function runs the simulation.  
           It doesn't return until we quit. */

           
        WTuniverse_ready();
        WTuniverse_go();
        
        /* And now to clean up our toys and go home. */

        WTuniverse_delete();

        return 0;

/* End of Main Routine */

/********************************************************************************/

void UserActions( void ) {

        unsigned char red, green, blue;
        char buffer[ 80 ];
        short key;
        WTp3 p3;
        WTq q;

        WTvertex *vertex;
        WTgeometry *geo;

        /* Process Keyboard Input */

        key = WTkeyboard_getlastkey();

        if( key ) {

            switch( key ) {

                case 'i':
                case 'I':
                        WTviewpoint_getposition( Viewpoint, p3 );
                        WTviewpoint_getorientation( Viewpoint, q );
                        WTp3_print( p3, "Current Position: " );
                        WTq_print( q, "Current Orientation: " );
                        break;

                case 'q':
                case 'Q': 
                        WTuniverse_stop();
                        break;

                case 'p':
                case 'P':
                        WTnode_print( Root );
                        break;

                case '0':
                        WTviewpoint_moveto( Viewpoint, &InitialView );
                        break;

                case 'r':
                        if( Red <= 0 ) break;
                        Red -= 2;  /* Will be incremented 1 in next case */

                case 'R':
                        if( Red >= 255 && key == 'R' ) break;
                        Red++;
                        WTp3_init( p3 );
                        p3[ X ] = 50.0f * ( Red / 255.0f - 0.5f );
                        WTnode_settranslation( RedPlane, p3 );
                        geo = WTnode_getgeometry( RedPlane );
                        WTgeometry_beginedit( geo );
                        for( vertex = WTgeometry_getvertices( geo ); vertex;
                                vertex = WTvertex_next( vertex ) ) {

                                WTgeometry_getvertexrgb( geo, vertex, &red, &green, &blue );
                                WTgeometry_setvertexrgb( geo, vertex, Red, green, blue );
                        }
                        WTgeometry_endedit( geo );

                        sprintf( buffer, "Red   = %3d ( %f )", Red, Red / 255.0f );
                        geo = WTgeometry_newtext3d( Font, buffer );
                        WTgeometry_setrgb( geo, Red, 0, 0 );
                        WTnode_delete( RedText );
                        RedText = WTgeometrynode_new( RedXform, geo );

                        break;

                case 'g':
                        if( Green <= 0 ) break;
                        Green -= 2;  /* Will be incremented 1 in next case */

                case 'G':
                        if( Green >= 255 && key == 'G' ) break;
                        Green++;
                        WTp3_init( p3 );
                        p3[ Y ] = 50.0f * ( - Green / 255.0f + 0.5f );
                        WTnode_settranslation( GreenPlane, p3 );
                        geo = WTnode_getgeometry( GreenPlane );
                        WTgeometry_beginedit( geo );
                        for( vertex = WTgeometry_getvertices( geo ); vertex;
                                vertex = WTvertex_next( vertex ) ) {

                                WTgeometry_getvertexrgb( geo, vertex, &red, &green, &blue );
                                WTgeometry_setvertexrgb( geo, vertex, red, Green, blue );
                        }
                        WTgeometry_endedit( geo );

                        sprintf( buffer, "Green = %3d ( %f )", Green, Green / 255.0f );
                        geo = WTgeometry_newtext3d( Font, buffer );
                        WTgeometry_setrgb( geo, 0, Green, 0 );
                        WTnode_delete( GreenText );
                        GreenText = WTgeometrynode_new( GreenXform, geo );

                        break;

                case 'b':
                        if( Blue <= 0 ) break;
                        Blue -= 2;  /* Will be incremented 1 in next case */

                case 'B':
                        if( Blue >= 255 && key == 'B' ) break;
                        Blue++;
                        WTp3_init( p3 );
                        p3[ Z ] = 50.0f * ( Blue / 255.0f - 0.5f );
                        WTnode_settranslation( BluePlane, p3 );
                        geo = WTnode_getgeometry( BluePlane );
                        WTgeometry_beginedit( geo );
                        for( vertex = WTgeometry_getvertices( geo ); vertex;
                                vertex = WTvertex_next( vertex ) ) {

                                WTgeometry_getvertexrgb( geo, vertex, &red, &green, &blue );
                                WTgeometry_setvertexrgb( geo, vertex, red, green, Blue );
                        }
                        WTgeometry_endedit( geo );

                        sprintf( buffer, "Blue  = %3d ( %f )", Blue, Blue / 255.0f );
                        geo = WTgeometry_newtext3d( Font, buffer );
                        WTgeometry_setrgb( geo, 0, 0, Blue );
                        WTnode_delete( BlueText );
                        BlueText = WTgeometrynode_new( BlueXform, geo );

                        break;

                case 'h':  /* Help - Fall through to default */
                case 'H':
                case '?':   

                default:
                        WTmessage( "\nThe following keys are active:\n\n" );
                            WTmessage( "Q or q: Quit.\n" );
                            WTmessage( "0 ( zero ): Reset\n" );
                        WTmessage( "P or p: Print scene graph.\n" );
                        break;

            }
        }

        return;

/* End of UserActions */