/****************************************************************************/
/*                                                                          */
/*  VolVis is a volume visualization system for investigating, manipulating */
/*  and rendering geometric and volumetric data.                            */
/*                                                                          */
/*  Copyright (C) 1993 by the Research Foundation of the State University   */
/*                            of New York                                   */
/*                                                                          */
/*  This program is free software; you can redistribute it and/or modify    */
/*  it under the terms of the GNU General Public License as published by    */
/*  the Free Software Foundation; either version 1, or (at your option)     */
/*  any later version.                                                      */
/*                                                                          */
/*  This program is distributed in the hope that it will be useful,         */
/*  but WITHOUT ANY WARRANTY; without even the implied warranty of          */
/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           */
/*  GNU General Public License for more details.                            */
/*                                                                          */
/*  You should have received a copy of the GNU General Public License       */
/*  along with this program; if not, write to the Free Software             */
/*  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.               */
/*                                                                          */
/*  For information on VolVis, contact us at:                               */
/*                                                                          */
/*                volvis@cs.sunysb.edu                         (email)      */
/*                                                                          */
/*                Lisa Sobierajski & Ricardo Avila             (US Mail)    */
/*                Department of Computer Science                            */
/*                State University of New York at Stony Brook               */
/*                Stony Brook, New York  11794-4400                         */
/*                                                                          */
/****************************************************************************/




/*
 *                  File: C_nav_cw.c
 *                Author: Hui Chen 
 *                  Date: 07/06/92
 *           Description: 
 *  Modification History:
 *
 *         who?         when?           why?
 *    -----------------------------------------------------------
 *
 */

# include <math.h>
# include <stdio.h>
# include <string.h>

# include "C_volvis.h"
# include "C_navigator.h"

#ifdef C_OL
#include	"OL_vv_ui.h"
#include	"OL_nav_frame.h"

extern OL_nav_contr_info	nav_cw_info;
#endif

#ifdef C_MOTIF	
extern C_NavCWInfo     nav_cw_info;
#endif

static C_NavCWParam	nav_cw_queue[5];
static int cw_ini_flag = 0;
static int cw_fnt_flag = 0;
static int cw_end_flag = 0;
static int cross_flag = 0;

void nav_transform();

/*
 *        Procedure Name: nav_push
 *          Return Value: void
 *       Input Variables: none
 *      Output Variables: none
 *      Update Variables: none
 *      Global Variables:
 *           Description:
 */

void nav_push()
{
#ifdef C_MOTIF
	extern float nav_set_x();
	extern float nav_set_y();
	extern float nav_set_z();

	extern float nav_ref_x();
	extern float nav_ref_y();
	extern float nav_ref_z();
#endif
/*
 * The ifdefs above and below are due to dependence upon each interface
 * for the various functions. They can be easily erased when
 * 1) A single function for translating a widget value to a float is used in
 * MOTIF (currently six seperate functions). Then
 * 2) The actual structures can be changed to have the same name in the 
 * includes, combined with conditional compilation at the top line.
 * Even better, a pointer to the structures could be passed, instead of
 * having global structures.
 */

#ifdef C_OL
	extern float	nav_set_float();
	extern OL_Nav_ui_info nav_ui_info;
#endif

	C_NavCWParam	nav_cw_param;
/*
 *	This section calls the motif functions mentioned above
 */
	nav_cw_param.global.nav_mode = nav_cw_info.nav_global.nav_mode;
	nav_cw_param.global.nav_coord = nav_cw_info.nav_global.nav_coord;
	nav_cw_param.global.nav_ref = nav_cw_info.nav_global.nav_ref;
	nav_cw_param.global.nav_option = nav_cw_info.nav_global.nav_option;

#ifdef C_MOTIF
	nav_cw_param.trans_amt.x = nav_set_x();
	nav_cw_param.trans_amt.y = nav_set_y();
	nav_cw_param.trans_amt.z = nav_set_z();

	nav_cw_param.ref_point.x = nav_ref_x();
	nav_cw_param.ref_point.y = nav_ref_y();
	nav_cw_param.ref_point.z = nav_ref_z();
#endif
#ifdef C_OL 
        nav_cw_param.trans_amt.x =
                nav_set_float( nav_ui_info.nav_control.transform_x);
        nav_cw_param.trans_amt.y =
                nav_set_float( nav_ui_info.nav_control.transform_y);
        nav_cw_param.trans_amt.z =
                nav_set_float( nav_ui_info.nav_control.transform_z);
 
        if((nav_cw_param.global.nav_mode == C_ROTATE ||
                        nav_cw_param.global.nav_mode == C_SCALE)&&
                                nav_cw_param.global.nav_ref == C_OTHER_REF)
        {
                nav_cw_param.ref_point.x =
                        nav_set_float( nav_ui_info.nav_control.world_x);
                nav_cw_param.ref_point.y =
                        nav_set_float( nav_ui_info.nav_control.world_y);
                nav_cw_param.ref_point.z =
                        nav_set_float( nav_ui_info.nav_control.world_z);
        }
 
#endif

	nav_cw_queue[cw_fnt_flag].global.nav_mode = nav_cw_info.nav_global.nav_mode;
	nav_cw_queue[cw_fnt_flag].global.nav_coord = nav_cw_info.nav_global.nav_coord;
	nav_cw_queue[cw_fnt_flag].global.nav_ref = nav_cw_info.nav_global.nav_ref;
	nav_cw_queue[cw_fnt_flag].global.nav_option = nav_cw_info.nav_global.nav_option;

	nav_cw_queue[cw_fnt_flag].trans_amt.x = nav_cw_param.trans_amt.x;
	nav_cw_queue[cw_fnt_flag].trans_amt.y = nav_cw_param.trans_amt.y;
	nav_cw_queue[cw_fnt_flag].trans_amt.z = nav_cw_param.trans_amt.z;

	nav_cw_queue[cw_fnt_flag].ref_point.x = nav_cw_param.ref_point.x;
	nav_cw_queue[cw_fnt_flag].ref_point.y = nav_cw_param.ref_point.y;
	nav_cw_queue[cw_fnt_flag].ref_point.z = nav_cw_param.ref_point.z;

	if (cw_ini_flag < 5) 
	{
	    cw_ini_flag = cw_fnt_flag;
	    cw_ini_flag++;
	    if (cw_fnt_flag < 4)
		cw_fnt_flag++;
	    else
		cw_fnt_flag = 0;
	}
	else 
	{
	    if (cw_end_flag == cw_fnt_flag) 
	    {	
		if (cw_end_flag < 4) 
		{
		    if (cross_flag == 0) 
		        cw_end_flag++;
		    cw_fnt_flag++;
		}
		else 
		{
		    if (cross_flag == 0) 
		        cw_end_flag = 0;
		    cw_fnt_flag = 0;
		}
	    }
	    else 
	    {
		if (cw_fnt_flag < 4) 
		{
		    cw_fnt_flag++;
		}
		else 
		{
		    cw_fnt_flag = 0;
		}
	    }
	}

	if (cross_flag == 1)
	    cross_flag = 0;

	nav_transform(nav_cw_param);

}

/*
 *        Procedure Name: nav_push
 *          Return Value: void
 *       Input Variables: none
 *      Output Variables: none
 *      Update Variables: none
 *      Global Variables:
 *           Description:
 */

void nav_pop()
{
	C_NavCWParam	nav_cw_param;
	int undo_flag;

	undo_flag = 0;

	if (cross_flag == 1) {
	   undo_flag = 1;
	   printf("Cannot undo!!!\n");
	}
	else {
	   if ((cw_fnt_flag-cw_end_flag) == 1) {
	        cw_fnt_flag--;
		cross_flag = 1;
	   }
	   else if ((cw_end_flag-cw_fnt_flag) == 4) {
	        cw_fnt_flag = 4;
		cross_flag = 1;
	   }
	   else {
		if (cw_fnt_flag == 0) {
		   if (cw_ini_flag == 5) 
		      cw_fnt_flag = 4;
		   else
	   	      undo_flag = 1;
		}
	   	else 
		   cw_fnt_flag--;
	   }
	}

	if (undo_flag == 0)
	{
	   nav_cw_param.global.nav_mode = 
		nav_cw_queue[cw_fnt_flag].global.nav_mode;

	   nav_cw_param.global.nav_coord = 
		nav_cw_queue[cw_fnt_flag].global.nav_coord;

	   nav_cw_param.global.nav_ref = 
		nav_cw_queue[cw_fnt_flag].global.nav_ref;

	   nav_cw_param.global.nav_option = 
		nav_cw_queue[cw_fnt_flag].global.nav_option;

	   nav_cw_param.trans_amt.x = - nav_cw_queue[cw_fnt_flag].trans_amt.x;
	   nav_cw_param.trans_amt.y = - nav_cw_queue[cw_fnt_flag].trans_amt.y;
	   nav_cw_param.trans_amt.z = - nav_cw_queue[cw_fnt_flag].trans_amt.z;

	   nav_cw_param.ref_point.x = nav_cw_queue[cw_fnt_flag].ref_point.x;
	   nav_cw_param.ref_point.y = nav_cw_queue[cw_fnt_flag].ref_point.y;
	   nav_cw_param.ref_point.z = nav_cw_queue[cw_fnt_flag].ref_point.z;

	   nav_transform(nav_cw_param);
	}
}

/*
 *        Procedure Name: nav_push
 *          Return Value: void
 *       Input Variables: none
 *      Output Variables: none
 *      Update Variables: none
 *      Global Variables:
 *           Description:
 */

void nav_transform(nav_cw_param)
C_NavCWParam	nav_cw_param;
{
	extern void		nav_update();
	extern C_World		world;
	extern C_View		view;

	int		loop;
	int		volume_num;
	C_FPosition	local_center,
			world_center;


	switch (nav_cw_param.global.nav_mode)
	{
	  case C_ROTATE:
	    switch (nav_cw_param.global.nav_coord)
	    {
	      case C_LOCAL_COORD:
		switch (nav_cw_param.global.nav_ref)
		{
		  case C_ORIGIN_REF:
		    for (loop = 0; loop < world.num_volumes; loop++)
		    {
		      /***************************************************/
		      /* ROTATE Volume About ORIGIN_REF Using LOCAL CSys */
		      /***************************************************/
		      if (world.volume[loop]->modifiable)
		      {
			C_rotate_volume_local(world.volume[loop], C_X_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.x), 
				&(world.volume[loop]->c_sys.origin) );
			C_rotate_volume_local(world.volume[loop], C_Y_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.y), 
				&(world.volume[loop]->c_sys.origin) );
			C_rotate_volume_local(world.volume[loop], C_Z_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.z), 
				&(world.volume[loop]->c_sys.origin) );
		      }
		    }
		    for (loop = 0; loop < world.num_lights; loop++)
		    {
		      /**************************************************/
		      /* ROTATE Light About ORIGIN_REF Using LOCAL CSys */
		      /**************************************************/
		      if (world.light[loop]->modifiable)
		      {
			switch ( world.light[loop]->light_type )
			{
			  case C_POINT_LIGHT:
			    C_message("Rotating light origin has no effect\n");
			    break;

			  default:
			    C_error_message("Internal Error: NAVCW_LIGHT1");
			}
		      }
		    }
		    /*************************************************/
		    /* ROTATE View About ORIGIN_REF Using LOCAL CSys */
		    /*************************************************/
		    if (view.modifiable)
		    {
			C_rotate_view_local(&(view), C_X_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.x), 
				&(view.c_sys.origin) );
			C_rotate_view_local(&(view), C_Y_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.y), 
				&(view.c_sys.origin) );
			C_rotate_view_local(&(view), C_Z_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.z), 
				&(view.c_sys.origin) );
		    }
		    
		    break;

		  case C_CENTER_REF:
		    for (loop = 0; loop < world.num_volumes; loop++)
		    {
		      /***************************************************/
		      /* ROTATE Volume About CENTER_REF Using LOCAL CSys */
		      /***************************************************/
		      if (world.volume[loop]->modifiable)
		      {
			local_center.x = world.volume[loop]->x_size_units/2.0;
			local_center.y = world.volume[loop]->y_size_units/2.0;
			local_center.z = world.volume[loop]->z_size_units/2.0;

			/*printf(" %f %f %f %f %f %f\n",
				nav_cw_param.trans_amt.x,
				nav_cw_param.trans_amt.y,
				nav_cw_param.trans_amt.z,
				local_center.x,
				local_center.y,
				local_center.z);
			*/
			C_transform_fposition( &local_center, &world_center,
					&(world.volume[loop]->ltow_units) );

			C_rotate_volume_local(world.volume[loop], C_X_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.x), 
				&world_center );
			C_rotate_volume_local(world.volume[loop], C_Y_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.y), 
				&world_center );
			C_rotate_volume_local(world.volume[loop], C_Z_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.z), 
				&world_center );
		      }
		    }
		    /**************************************************/
		    /* ROTATE Light About CENTER_REF Using LOCAL CSys */
		    /**************************************************/
		    for (loop = 0; loop < world.num_lights; loop++)
		    {
		      if (world.light[loop]->modifiable)
		      {
			switch ( world.light[loop]->light_type )
			{
			  case C_POINT_LIGHT:
			    C_message("Rotating light center has no effect\n");
			    break;

			  default:
			    C_error_message("Internal Error: NAVCW_LIGHT2");
			}
		      }
		    }
		    /*************************************************/
		    /* ROTATE View About CENTER_REF Using LOCAL CSys */
		    /*************************************************/
		    if (view.modifiable)
		    {
			C_rotate_view_local(&(view), C_X_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.x), 
				&(view.c_sys.origin) );
			C_rotate_view_local(&(view), C_Y_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.y), 
				&(view.c_sys.origin) );
			C_rotate_view_local(&(view), C_Z_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.z), 
				&(view.c_sys.origin) );
		    }
		    
		    break;

		  case C_OTHER_REF:
		    for (loop = 0; loop < world.num_volumes; loop++)
		    {
		      /**************************************************/
		      /* ROTATE Volume About OTHER_REF Using LOCAL CSys */
		      /**************************************************/
		      if(world.volume[loop]->modifiable)
		      {
			C_rotate_volume_local(world.volume[loop], C_X_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.x), 
				&(nav_cw_param.ref_point) );
			C_rotate_volume_local(world.volume[loop], C_Y_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.y), 
				&(nav_cw_param.ref_point) );
			C_rotate_volume_local(world.volume[loop], C_Z_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.z), 
				&(nav_cw_param.ref_point) );
		      }
		    }
		    for (loop = 0; loop < world.num_lights; loop++)
		    {
		      /*************************************************/
		      /* ROTATE Light About OTHER_REF Using LOCAL CSys */
		      /*************************************************/
		      if(world.light[loop]->modifiable)
		      {
			    C_rotate_light_local(world.light[loop], C_X_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.x), 
				&(nav_cw_param.ref_point) );
			    C_rotate_light_local(world.light[loop], C_Y_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.y), 
				&(nav_cw_param.ref_point) );
			    C_rotate_light_local(world.light[loop], C_Z_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.z), 
				&(nav_cw_param.ref_point) );
		      }
		    }
		    /************************************************/
		    /* ROTATE View About OTHER_REF Using LOCAL CSys */
		    /************************************************/
		    if(view.modifiable)
		    {
			C_rotate_view_local(&(view), C_X_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.x), 
				&(nav_cw_param.ref_point) );
			C_rotate_view_local(&(view), C_Y_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.y), 
				&(nav_cw_param.ref_point) );
			C_rotate_view_local(&(view), C_Z_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.z), 
				&(nav_cw_param.ref_point) );
		    }
		    
		    break;
		}
		break;

	      case C_GLOBAL_COORD:
		
		switch(nav_cw_param.global.nav_ref)
		{
		  case C_ORIGIN_REF:
		    for(loop = 0; loop < world.num_volumes; loop++)
		    {
		      /**********************************/
		      /* ROTATE Volume About ORIGIN_REF */
		      /**********************************/
		      if (world.volume[loop]->modifiable)
		      {
			if ( nav_cw_param.global.nav_option == 0 )
			{
			    /* Use The WORLD Coordinate System */
			    C_rotate_volume_world(world.volume[loop], C_X_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.x), 
				&(world.volume[loop]->c_sys.origin) );
			    C_rotate_volume_world(world.volume[loop], C_Y_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.y), 
				&(world.volume[loop]->c_sys.origin) );
			    C_rotate_volume_world(world.volume[loop], C_Z_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.z), 
				&(world.volume[loop]->c_sys.origin) );
			}
			else if( nav_cw_param.global.nav_option == 1 )
			{
			    /* Use The VIEW Coordinate System */
			    C_rotate_volume_view(world.volume[loop], 
				&(view), C_X_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.x),
				&(world.volume[loop]->c_sys.origin) );
			    C_rotate_volume_view(world.volume[loop], 
				&(view), C_Y_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.y),
				&(world.volume[loop]->c_sys.origin) );
			    C_rotate_volume_view(world.volume[loop], 
				&(view), C_Z_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.z),
				&(world.volume[loop]->c_sys.origin) );
			}
			else
			{
			    /* Use A VOLUME's Coordinate System */
			    volume_num = nav_cw_param.global.nav_option - 2;

			    C_rotate_volume_volume(world.volume[loop],
				world.volume[volume_num], C_X_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.x),
				&(world.volume[loop]->c_sys.origin) );
			    C_rotate_volume_volume(world.volume[loop],
				world.volume[volume_num], C_Y_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.y),
				&(world.volume[loop]->c_sys.origin) );
			    C_rotate_volume_volume(world.volume[loop],
				world.volume[volume_num], C_Z_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.z),
				&(world.volume[loop]->c_sys.origin) );
			}
		      }
		    }
		    for(loop = 0; loop < world.num_lights; loop++)
		    {
		      /****************************************************/
		      /* ROTATE A Light About ORIGIN_REF Using WORLD CSys */
		      /****************************************************/
		      if(world.light[loop]->modifiable)
		      {
			switch( world.light[loop]->light_type )
			{
			  case C_POINT_LIGHT:
			    C_message("Rotating light origin has no effect\n");
			    break;

			  default:
			    C_error_message("Internal Error: NAVCW_LIGHT1");
			}
		      }
		    }
		    if(view.modifiable)
		    {
		        /********************************/
		        /* ROTATE View About ORIGIN_REF */
		        /********************************/
			if ( nav_cw_param.global.nav_option == 0 )
			{
			    /* Use The WORLD Coordinate System */
			    C_rotate_view_world(&(view), C_X_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.x), 
				&(view.c_sys.origin) );
			    C_rotate_view_world(&(view), C_Y_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.y), 
				&(view.c_sys.origin) );
			    C_rotate_view_world(&(view), C_Z_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.z), 
				&(view.c_sys.origin) );
			}
			else if( nav_cw_param.global.nav_option == 1 )
			{
			    /* Use The VIEW Coordinate System */
			    /***********************************/
			    /* Note: A View's ORIGIN == CENTER */
			    /***********************************/
			    C_rotate_view_local(&(view), C_X_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.x), 
				&(view.c_sys.origin) );
			    C_rotate_view_local(&(view), C_Y_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.y), 
				&(view.c_sys.origin) );
			    C_rotate_view_local(&(view), C_Z_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.z), 
				&(view.c_sys.origin) );
			}
			else
			{
			    /* Use A VOLUME's Coordinate System */
			    volume_num = nav_cw_param.global.nav_option - 2;

			    C_rotate_view_volume(&(view),
				world.volume[volume_num], C_X_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.x), 
				&(view.c_sys.origin) );
			    C_rotate_view_volume(&(view),
				world.volume[volume_num], C_Y_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.y), 
				&(view.c_sys.origin) );
			    C_rotate_view_volume(&(view), 
				world.volume[volume_num], C_Z_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.z), 
				&(view.c_sys.origin) );
			}
		    }
		    
		    break;

		  case C_CENTER_REF:
		    for (loop = 0; loop < world.num_volumes; loop++)
		    {
		      /**********************************/
		      /* ROTATE Volume About CENTER_REF */
		      /**********************************/
		      if (world.volume[loop]->modifiable)
		      {
			local_center.x = world.volume[loop]->x_size_units/2.0;
			local_center.y = world.volume[loop]->y_size_units/2.0;
			local_center.z = world.volume[loop]->z_size_units/2.0;

			C_transform_fposition( &local_center, &world_center,
					&(world.volume[loop]->ltow_units) );

			if ( nav_cw_param.global.nav_option == 0 )
			{
			    /* Use The WORLD Coordinate System */
			    C_rotate_volume_world(world.volume[loop], C_X_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.x), 
				&world_center );
			    C_rotate_volume_world(world.volume[loop], C_Y_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.y), 
				&world_center );
			    C_rotate_volume_world(world.volume[loop], C_Z_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.z), 
				&world_center );
			}
			else if( nav_cw_param.global.nav_option == 1 )
			{
			  /* Use The VIEW Coordinate System */
			  C_rotate_volume_view(world.volume[loop], 
				&(view), C_X_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.x),
				&world_center );
			  C_rotate_volume_view(world.volume[loop], 
				&(view), C_Y_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.y),
				&world_center );
			  C_rotate_volume_view(world.volume[loop], 
				&(view), C_Z_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.z),
				&world_center );
			}
			else
			{
			    /* Use A VOLUME's Coordinate System */
			    volume_num = nav_cw_param.global.nav_option - 2;

			    C_rotate_volume_volume(world.volume[loop],
				world.volume[volume_num], C_X_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.x),
				&world_center );
			    C_rotate_volume_volume(world.volume[loop],
				world.volume[volume_num], C_Y_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.y),
				&world_center );
			    C_rotate_volume_volume(world.volume[loop],
				world.volume[volume_num], C_Z_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.z),
				&world_center );
			}
		      }
		    }
		    /***************************************************/
		    /* ROTATE Lights About CENTER_REF Using WORLD CSys */
		    /***************************************************/
		    for (loop = 0; loop < world.num_lights; loop++)
		    {
		      if (world.light[loop]->modifiable)
		      {
			switch ( world.light[loop]->light_type )
			{
			  case C_POINT_LIGHT:
			    C_message("Rotating light center has no effect\n");
			    break;

			  default:
			    C_error_message("Internal Error: NAVCW_LIGHT2");
			}
		      }
		    }
		    if (view.modifiable)
		    {
			/********************************/
			/* ROTATE View About CENTER_REF */
			/********************************/
			/***********************************/
			/* Note: A View's ORIGIN == CENTER */
			/***********************************/
			if ( nav_cw_param.global.nav_option == 0 )
			{
			    /* Use The WORLD Coordinate System */
			    C_rotate_view_world(&(view), C_X_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.x), 
				&(view.c_sys.origin) );
			    C_rotate_view_world(&(view), C_Y_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.y), 
				&(view.c_sys.origin) );
			    C_rotate_view_world(&(view), C_Z_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.z), 
				&(view.c_sys.origin) );
			}
			else if( nav_cw_param.global.nav_option == 1 )
			{
			    /* Use The VIEW Coordinate System */
			    C_rotate_view_local(&(view), C_X_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.x), 
				&(view.c_sys.origin) );
			    C_rotate_view_local(&(view), C_Y_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.y), 
				&(view.c_sys.origin) );
			    C_rotate_view_local(&(view), C_Z_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.z), 
				&(view.c_sys.origin) );
			}
			else
			{
			    /* Use A VOLUME's Coordinate System */
			    volume_num = nav_cw_param.global.nav_option - 2;

			    C_rotate_view_volume(&(view),
				world.volume[volume_num], C_X_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.x), 
				&(view.c_sys.origin) );
			    C_rotate_view_volume(&(view),
				world.volume[volume_num], C_Y_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.y), 
				&(view.c_sys.origin) );
			    C_rotate_view_volume(&(view), 
				world.volume[volume_num], C_Z_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.z), 
				&(view.c_sys.origin) );
			}
		    }
		    
		    break;

		  case C_OTHER_REF:
		    for (loop = 0; loop < world.num_volumes; loop++)
		    {
		      if (world.volume[loop]->modifiable)
		      {
			/*********************************/
			/* ROTATE Volume About OTHER_REF */
			/*********************************/
			if ( nav_cw_param.global.nav_option == 0 )
			{
			    /* Use The WORLD Coordinate System */
			    C_rotate_volume_world(world.volume[loop], C_X_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.x), 
				&(nav_cw_param.ref_point) );
			    C_rotate_volume_world(world.volume[loop], C_Y_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.y), 
				&(nav_cw_param.ref_point) );
			    C_rotate_volume_world(world.volume[loop], C_Z_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.z), 
				&(nav_cw_param.ref_point) );
			}
			else if( nav_cw_param.global.nav_option == 1 )
			{
			    /* Use The VIEW Coordinate System */
			    C_rotate_volume_view(world.volume[loop], 
				&(view), C_X_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.x),
				&(nav_cw_param.ref_point) );
			    C_rotate_volume_view(world.volume[loop], 
				&(view), C_Y_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.y),
				&(nav_cw_param.ref_point) );
			    C_rotate_volume_view(world.volume[loop], 
				&(view), C_Z_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.z),
				&(nav_cw_param.ref_point) );
			}
			else
			{
			    /* Use A VOLUME's Coordinate System */
			    volume_num = nav_cw_param.global.nav_option - 2;

			    C_rotate_volume_volume(world.volume[loop],
				world.volume[volume_num], C_X_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.x),
				&(nav_cw_param.ref_point) );
			    C_rotate_volume_volume(world.volume[loop],
				world.volume[volume_num], C_Y_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.y),
				&(nav_cw_param.ref_point) );
			    C_rotate_volume_volume(world.volume[loop],
				world.volume[volume_num], C_Z_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.z),
				&(nav_cw_param.ref_point) );
			}
		      }
		    }
		    for (loop = 0; loop < world.num_lights; loop++)
		    {
		      if (world.light[loop]->modifiable)
		      {
			/***************************************************/
			/* ROTATE A Light About OTHER_REF Using WORLD CSys */
			/***************************************************/
			if ( nav_cw_param.global.nav_option == 0 )
			{
			    C_rotate_light_world(world.light[loop], C_X_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.x), 
				&(nav_cw_param.ref_point) );
			    C_rotate_light_world(world.light[loop], C_Y_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.y), 
				&(nav_cw_param.ref_point) );
			    C_rotate_light_world(world.light[loop], C_Z_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.z), 
				&(nav_cw_param.ref_point) );
			}
			else if( nav_cw_param.global.nav_option == 1 )
			{
			    /* Use View Coordinate System */
			    C_rotate_light_view( world.light[loop],
				&(view), C_X_AXIS, 
				C_Deg_To_Rad(nav_cw_param.trans_amt.x),
				&(nav_cw_param.ref_point) );
			    C_rotate_light_view( world.light[loop],
				&(view), C_Y_AXIS, 
				C_Deg_To_Rad(nav_cw_param.trans_amt.y),
				&(nav_cw_param.ref_point) );
			    C_rotate_light_view( world.light[loop],
				&(view), C_Z_AXIS, 
				C_Deg_To_Rad(nav_cw_param.trans_amt.z),
				&(nav_cw_param.ref_point) );
			}
			else
			{
			    /* Use Another Volume's Coordinate System */
			    volume_num = nav_cw_param.global.nav_option - 2;

			    C_rotate_light_volume( world.light[loop],
				world.volume[volume_num], C_X_AXIS, 
				C_Deg_To_Rad(nav_cw_param.trans_amt.x),
				&(nav_cw_param.ref_point) );
			    C_rotate_light_volume( world.light[loop],
				world.volume[volume_num], C_Y_AXIS, 
				C_Deg_To_Rad(nav_cw_param.trans_amt.y),
				&(nav_cw_param.ref_point) );
			    C_rotate_light_volume( world.light[loop],
				world.volume[volume_num], C_Z_AXIS, 
				C_Deg_To_Rad(nav_cw_param.trans_amt.z),
				&(nav_cw_param.ref_point) );
			}
		      }
		    }
		    if (view.modifiable)
		    {
			/************************************************/
			/* ROTATE View About OTHER_REF Using WORLD CSys */
			/************************************************/
			if ( nav_cw_param.global.nav_option == 0 )
			{
			    C_rotate_view_world(&(view), C_X_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.x), 
				&(nav_cw_param.ref_point) );
			    C_rotate_view_world(&(view), C_Y_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.y), 
				&(nav_cw_param.ref_point) );
			    C_rotate_view_world(&(view), C_Z_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.z), 
				&(nav_cw_param.ref_point) );
			}
			else if( nav_cw_param.global.nav_option == 1 )
			{
			    /* Use View Coordinate System */
			    C_rotate_view_local(&(view), C_X_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.x), 
				&(nav_cw_param.ref_point) );
			    C_rotate_view_local(&(view), C_Y_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.y), 
				&(nav_cw_param.ref_point) );
			    C_rotate_view_local(&(view), C_Z_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.z), 
				&(nav_cw_param.ref_point) );
			}
			else
			{
			    /* Use Another Volume's Coordinate System */
			    volume_num = nav_cw_param.global.nav_option - 2;

			    C_rotate_view_volume(&(view),
				world.volume[volume_num], C_X_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.x), 
				&(nav_cw_param.ref_point) );
			    C_rotate_view_volume(&(view),
				world.volume[volume_num], C_Y_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.y), 
				&(nav_cw_param.ref_point) );
			    C_rotate_view_volume(&(view), 
				world.volume[volume_num], C_Z_AXIS,
				C_Deg_To_Rad(nav_cw_param.trans_amt.z), 
				&(nav_cw_param.ref_point) );
			}
		    }
		    
		    break;
		}
		break;
	    }
	    break;

	  case C_TRANSLATE:
	    switch (nav_cw_param.global.nav_coord)
	    {
	      case C_LOCAL_COORD:
		    for (loop = 0; loop < world.num_volumes; loop++)
		    {
		      /*************************************/
		      /* TRANSLATE Volume Using LOCAL CSys */
		      /*************************************/
		      if (world.volume[loop]->modifiable)
		      {
			C_translate_volume_local(world.volume[loop], 
				nav_cw_param.trans_amt.x, 
				nav_cw_param.trans_amt.y, 
				nav_cw_param.trans_amt.z );
		      }
		    }
		    for (loop = 0; loop < world.num_lights; loop++)
		    {
		      /************************************/
		      /* TRANSLATE Light Using LOCAL CSys */
		      /************************************/
		      if (world.light[loop]->modifiable)
		      {
			C_translate_light_local(world.light[loop], 
				nav_cw_param.trans_amt.x, 
				nav_cw_param.trans_amt.y, 
				nav_cw_param.trans_amt.z );
		      }
		    }
		    /***********************************/
		    /* TRANSLATE View Using LOCAL CSys */
		    /***********************************/
		    if ( view.modifiable )
		    {
			C_translate_view_local( &view,
				nav_cw_param.trans_amt.x, 
				nav_cw_param.trans_amt.y, 
				nav_cw_param.trans_amt.z );
		    }
		    
		    break;
	      case C_GLOBAL_COORD:
		    for (loop = 0; loop < world.num_volumes; loop++)
		    {
		      if (world.volume[loop]->modifiable)
		      {
		         /*************************************/
		         /* TRANSLATE Volume Using WORLD CSys */
		         /*************************************/
		         if( nav_cw_param.global.nav_option == 0 )
		         {
			   /* Use The World Coordinate System */
			   C_translate_volume_world( world.volume[loop],
				nav_cw_param.trans_amt.x, 
				nav_cw_param.trans_amt.y, 
				nav_cw_param.trans_amt.z );
		         }
		         else if( nav_cw_param.global.nav_option == 1 )
		         {
			   /* Use View Coordinate System */
			   C_translate_volume_view( world.volume[loop],
				&(view),
				nav_cw_param.trans_amt.x, 
				nav_cw_param.trans_amt.y, 
				nav_cw_param.trans_amt.z );
		         }
		         else
		         {
			   /* Use A VOLUME's Coordinate System */
			   volume_num = nav_cw_param.global.nav_option - 2;

			   C_translate_volume_volume( world.volume[loop],
				world.volume[volume_num],
				nav_cw_param.trans_amt.x, 
				nav_cw_param.trans_amt.y, 
				nav_cw_param.trans_amt.z );
		         }
		      }
		    }
		    for (loop = 0; loop < world.num_lights; loop++)
		    {
		      if (world.light[loop]->modifiable)
		      {
		         /************************************/
		         /* TRANSLATE Light Using WORLD CSys */
		         /************************************/
		         if( nav_cw_param.global.nav_option == 0 )
		         {
			   /* Use The World Coordinate System */
			   C_translate_light_world( world.light[loop],
				nav_cw_param.trans_amt.x, 
				nav_cw_param.trans_amt.y, 
				nav_cw_param.trans_amt.z );
		         }
		         else if( nav_cw_param.global.nav_option == 1 )
		         {
			   /* Use View Coordinate System */
			   C_translate_light_view( world.light[loop],
				&(view),
				nav_cw_param.trans_amt.x, 
				nav_cw_param.trans_amt.y, 
				nav_cw_param.trans_amt.z );
		         }
		         else
		         {
			   /* Use A VOLUME's Coordinate System */
			   volume_num = nav_cw_param.global.nav_option - 2;

			   C_translate_light_volume( world.light[loop],
				world.volume[volume_num],
				nav_cw_param.trans_amt.x, 
				nav_cw_param.trans_amt.y, 
				nav_cw_param.trans_amt.z );
		         }
		      }
		    }
		    if ( view.modifiable )
		    {
		         /***********************************/
		         /* TRANSLATE View Using LOCAL CSys */
		         /***********************************/
		         if( nav_cw_param.global.nav_option == 0 )
		         {
			   /* Use The World Coordinate System */
			   C_translate_view_world( &view,
				nav_cw_param.trans_amt.x, 
				nav_cw_param.trans_amt.y, 
				nav_cw_param.trans_amt.z );
		         }
		         else if( nav_cw_param.global.nav_option == 1 )
		         {
			   /* Use View Coordinate System */
			   C_translate_view_local( &view,
				nav_cw_param.trans_amt.x, 
				nav_cw_param.trans_amt.y, 
				nav_cw_param.trans_amt.z );
		         }
		         else
		         {
			   /* Use A VOLUME's Coordinate System */
			   volume_num = nav_cw_param.global.nav_option - 2;

			   C_translate_view_volume(  &view,
				world.volume[volume_num],
				nav_cw_param.trans_amt.x, 
				nav_cw_param.trans_amt.y, 
				nav_cw_param.trans_amt.z );
		         }
		    }

		    break;
	    }
	    break;

	  case C_SCALE:
	    switch (nav_cw_param.global.nav_ref)
	    {
		  case C_ORIGIN_REF:
		    for (loop = 0; loop < world.num_volumes; loop++)
		    {
		      /**************************************************/
		      /* SCALE Volume About ORIGIN_REF Using LOCAL CSys */
		      /**************************************************/
		      if (world.volume[loop]->modifiable)
		      {
			C_scale_volume_local(world.volume[loop], 
				nav_cw_param.trans_amt.x, 
				nav_cw_param.trans_amt.y, 
				nav_cw_param.trans_amt.z,
				&(world.volume[loop]->c_sys.origin) );
		      }
		    }
		    for (loop = 0; loop < world.num_lights; loop++)
		    {
		      /*************************************************/
		      /* SCALE Light About ORIGIN_REF Using LOCAL CSys */
		      /*************************************************/
		      if (world.light[loop]->modifiable)
		      {
			switch ( world.light[loop]->light_type )
			{
			  case C_POINT_LIGHT:
				
				C_message("Scale point light = no effect\n");
				break;
			
			  default:

				C_error_message("Internal Error: NAVCW_LIGHT3");
			}
		      }
		    }
		    /************************************************/
		    /* SCALE View About ORIGIN_REF Using LOCAL CSys */
		    /************************************************/
		    if ( view.modifiable )
		    {

/**** 	This Section Needs Some Thought!!!!
	Scaling A View In Perspective Is NOT Valid
	Maybe We Should Just Scale The View In Pixels
*****/
			C_scale_view_local( &view,
				nav_cw_param.trans_amt.x, 
				nav_cw_param.trans_amt.y, 
				nav_cw_param.trans_amt.z,
				&(view.c_sys.origin) );
		    }
		
		    
		    break;

		  case C_CENTER_REF:

		    for (loop = 0; loop < world.num_volumes; loop++)
		    {
		      /**************************************************/
		      /* SCALE Volume About CENTER_REF Using LOCAL CSys */
		      /**************************************************/
		      if (world.volume[loop]->modifiable)
		      {
			local_center.x = world.volume[loop]->x_size_units/2.0;
			local_center.y = world.volume[loop]->y_size_units/2.0;
			local_center.z = world.volume[loop]->z_size_units/2.0;

			C_transform_fposition( &local_center, &world_center,
					&(world.volume[loop]->ltow_units) );

			C_scale_volume_local(world.volume[loop], 
				nav_cw_param.trans_amt.x, 
				nav_cw_param.trans_amt.y, 
				nav_cw_param.trans_amt.z, &world_center );
		      }
		    }
		    for (loop = 0; loop < world.num_lights; loop++)
		    {
		      /*************************************************/
		      /* SCALE Light About CENTER_REF Using LOCAL CSys */
		      /*************************************************/
		      if (world.light[loop]->modifiable)
		      {
			switch ( world.light[loop]->light_type )
			{
			  case C_POINT_LIGHT:
				
				C_message("Scale point light = no effect\n");
				break;
			
			  default:

				C_error_message("Internal Error: NAVCW_LIGHT4");
			}
		      }
		    }
		    /************************************************/
		    /* SCALE View About CENTER_REF Using LOCAL CSys */
		    /************************************************/
		    if ( view.modifiable )
		    {
/**** 	This Section Needs Some Thought!!!!
	Scaling A View In Perspective Is NOT Valid
	Maybe We Should Just Scale The View In Pixels
*****/
			C_scale_view_local( &view,
				nav_cw_param.trans_amt.x, 
				nav_cw_param.trans_amt.y, 
				nav_cw_param.trans_amt.z,
				&(view.c_sys.origin) );
		    }
		    
		    break;

		  case C_OTHER_REF:
		    for (loop = 0; loop < world.num_volumes; loop++)
		    {
		      /*************************************************/
		      /* SCALE Volume About OTHER_REF Using LOCAL CSys */
		      /*************************************************/
		      if (world.volume[loop]->modifiable)
		      {
			C_scale_volume_local(world.volume[loop], 
				nav_cw_param.trans_amt.x, 
				nav_cw_param.trans_amt.y, 
				nav_cw_param.trans_amt.z, 
				&nav_cw_param.ref_point );
		      }
		    }
		    for (loop = 0; loop < world.num_lights; loop++)
		    {
		      /************************************************/
		      /* SCALE Light About OTHER_REF Using LOCAL CSys */
		      /************************************************/
		      if (world.light[loop]->modifiable)
		      {
			switch ( world.light[loop]->light_type )
			{
			  case C_POINT_LIGHT:
				
				C_message("Scale point light = no effect\n");
				break;
			
			  default:

				C_error_message("Internal Error: NAVCW_LIGHT5");
			}
		      }
		    }
		    /***********************************************/
		    /* SCALE View About OTHER_REF Using LOCAL CSys */
		    /***********************************************/
		    if ( view.modifiable )
		    {
/**** 	This Section Needs Some Thought!!!!
	Scaling A View In Perspective Is NOT Valid
	Maybe We Should Just Scale The View In Pixels
*****/
			C_scale_view_local( &view,
				nav_cw_param.trans_amt.x, 
				nav_cw_param.trans_amt.y, 
				nav_cw_param.trans_amt.z,
				&(nav_cw_param.ref_point) );
		    }
		    
		    break;
	    }
	    C_update_world_extent();
	    break;
	}
	nav_update();
}

