/* cardemo.c - A simple VR program to illustrate the
	use of movable nodes in scene graphs,
	for Eng 591, Virtual Reality Programming.

	Written September 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 = { { -50.0f, -25.0f, -50.0f }, { 0.0f, -0.3827f, 0.0f, 0.9239f } };
WTnode *Root = NULL;
WTviewpoint *Viewpoint = NULL;
WTsensor *Mouse = NULL;

WTnode *Car = NULL, *Wheels = NULL, *LeftWheel = NULL, *RightWheel = NULL;

int main ( int argc, char **argv )

{
	/* Local Variables */

	WTp3	right_rear  = {  4.0f, -1.0f, -6.0f },
		left_rear   = { -4.0f, -1.0f, -6.0f },
		right_front = {  4.0f, -1.0f,  5.0f },
		left_front  = { -4.0f, -1.0f,  5.0f };

	WTq left = { 0.0f, 1.0f, 0.0f, 0.0f };

	WTp3 lightPosition = { -100.0, -100.0, 0.0 };

	WTnode *sep = NULL, *wheel = NULL, *node = NULL;

	/* Intialize the Universe */
	
        WTuniverse_new( WTDISPLAY_DEFAULT, WTWINDOW_DEFAULT );
	
	/* Set some global variables */
	
        Root = WTuniverse_getrootnodes();
	Viewpoint = WTuniverse_getviewpoints();

        /* 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 */

        WTlightnode_newdirected( Root );
        node = WTlightnode_newpoint( Root );
	WTlightnode_setposition( node, lightPosition );
        WTnode_load( Root, "grounds.nff", 1.0 );

	/* First load the separator, the overall car transform,
	   and the car body itelf.  Save a pointer to the 
	   transform in the global variable "Car". */

        sep = WTsepnode_new( Root );
	Car = WTxformnode_new( sep );
	WTnode_load( sep, "carbody.nff", 1.0 );

	/* Now load and locate the rear wheels.	Save a local
	   pointer to the first wheel, for instancing. */

	wheel = WTmovnode_load( sep, "wheel.nff", 1.0 ); /* Right rear */
	WTnode_settranslation( wheel, right_rear );
	node = WTmovnode_instance( sep, wheel ); /* Left rear */
	WTnode_settranslation( node, left_rear );
	WTnode_setorientation( node, left );

	/* Next load a transform to be used later to turn the front wheels.
	   Save a global variable "Wheels" to point to this transform.
	   Then load the front wheels themselves. 
	
	   ( Note:  The above approach did not work, so separate pointers
	     are also saved to each individual front wheel */

	Wheels = WTxformnode_new( sep );
	RightWheel = WTmovnode_instance( sep, wheel ); /* Right front */
	WTnode_settranslation( RightWheel, right_front );
	LeftWheel = WTmovnode_instance( sep, wheel ); /* Left front */
	WTnode_settranslation( LeftWheel, left_front );
	WTnode_setorientation( LeftWheel, left );

	/* 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 ) {

        short key;
	WTp3 p3;
	WTq q;
	WTp3 step = { 0.0f, 0.0f, 1.0f }; /* Move car 1 step forward */

        /* Process Keyboard Input */

        key = WTkeyboard_getlastkey();

        if( key ) {

            switch( key ) {

                case 'f':
                case 'F': 
			WTnode_translate( Car, step, WTFRAME_LOCAL );
                        break;

                case 'R': /* Turn car right PI / 16 degrees */
			WTnode_axisrotation( Car, Y, PI/16.0, WTFRAME_LOCAL );
                        break;

                case 'L': /* Turn car left PI / 16 degrees */
			WTnode_axisrotation( Car, Y, -PI/16.0, WTFRAME_LOCAL );
                        break;

                case 'r': /* Turn wheels right PI / 16 degrees */
			/*WTnode_axisrotation( Wheels, Y, PI/16.0, WTFRAME_LOCAL );*/
			WTnode_axisrotation( LeftWheel, Y, PI/16.0, WTFRAME_LOCAL );
			WTnode_axisrotation( RightWheel, Y, PI/16.0, WTFRAME_LOCAL );
                        break;

                case 'l': /* Turn wheels left PI / 6 degrees */
			/*WTnode_axisrotation( Wheels, Y, -PI/16.0, WTFRAME_LOCAL );*/
			WTnode_axisrotation( LeftWheel, Y, -PI/16.0, WTFRAME_LOCAL );
			WTnode_axisrotation( RightWheel, Y, -PI/16.0, WTFRAME_LOCAL );
                        break;

		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 '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( "F or f: Move car forward.\n" );
                    	WTmessage( "L: Turn car left.\n" );
                    	WTmessage( "R: Turn car right.\n" );
                    	WTmessage( "l: Turn wheels left.\n" );
                    	WTmessage( "r: Turn wheels right.\n" );
			WTmessage( "P or p: Print scene graph.\n" );
	                break;

            }
        }

        return;

} /* End of UserActions */
