/****************************************************************************/
/*                                                                          */
/*  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_ide_spaceball.c
 *                  Author: He, Taosong
 *                  Date:   1/18/93
 *           Description: C routines for driving input device mouse
 *  Modification History:
 *
 *         who?         when?           why?
 *    -----------------------------------------------------------
 *
 */

/******************************************************************/
/*                The standard C include file                     */
/******************************************************************/


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


/******************************************************************/
/*                  VolVis include file                           */
/******************************************************************/

#include "C_volvis.h"
#include "C_ide.h"

static double velocity_x, velocity_y, velocity_z;

void C_ide_spaceball_reset_velocity()
{
    velocity_x = 0;
    velocity_y = 0;
    velocity_z = 0;
}

void dominate(data)
short data[3];
{
  short temp;
  register i;

  temp = abs(data[0]);

  for (i=1; i<=2; i++)
    if (abs(data[i]) > temp) temp = abs(data[i]);

  for (i=0; i<=2; i++)
    if (abs(data[i]) != temp ) data[i] = 0;
}

void C_spaceball_rotation(data, period, result)
short data[3];
short period;
float result[4][4];
{
  extern C_IDE_simulation_method C_ide_simulation_method;
  double scale_factor;

  if (C_ide_simulation_method.spaceball.rotation_dominate == 1)
    dominate(data);

  scale_factor=(double)(C_ide_simulation_method.spaceball.rotation_rate*period);

  gl_spaceball_rotate(data, scale_factor, result);
}

void C_spaceball_translate(data, period, result)
short data[3];
short period;
float result[3];
{
  extern C_IDE_simulation_method C_ide_simulation_method;
  extern C_IDE_window_information IDE_active_window_information;
  double scale_factor, period1;
  int scale_x, scale_y, scale_z, scale;

  if (C_ide_simulation_method.spaceball.translate_dominate == 1)
    dominate(data);


  scale_factor = (C_ide_simulation_method.spaceball.translation_rate*period);
  scale_factor = ldexp(scale_factor, -14);

  if (C_ide_simulation_method.spaceball.acceleration_velocity_mode
     == C_VELOCITY_MODE)
    {
     result[0] = (float)(data[0] * scale_factor);
     result[1] = (float)(data[1] * scale_factor);
     result[2] = (float)(data[2] * scale_factor);
   }
  else
    {
     velocity_x += data[0] * ldexp(period, -7);
     velocity_y += data[1] * ldexp(period, -7);
     velocity_z += data[2] * ldexp(period, -7); 

     result[0] = (float)(velocity_x * scale_factor);
     result[1] = (float)(velocity_y * scale_factor);
     result[2] = (float)(velocity_z * scale_factor);
    }

  scale_x = IDE_active_window_information.width;
  scale_y = IDE_active_window_information.height;
  if (scale_x > scale_y) scale = scale_x;
  else                   scale = scale_y;

  if (C_ide_simulation_method.unit == C_PIXEL)
    {
     result[0] *= scale;
     result[1] *= scale;
     result[2] *= scale;
    }
}

void C_spaceball_report_token()
{
  extern void spaceball_report_token();
  extern C_IDE_token ide_data_token[C_MAX_RD_NUMBER];
  char temp_str[100];

  sprintf(temp_str, "x2d %.2f y2d %.2f x:%.2f y:%.2f z:%.2f ", 
          ide_data_token[C_SPACEBALL].pos2d.x,
          ide_data_token[C_SPACEBALL].pos2d.y,
          ide_data_token[C_SPACEBALL].pos3d.x,
          ide_data_token[C_SPACEBALL].pos3d.y,
          ide_data_token[C_SPACEBALL].pos3d.z);

  spaceball_report_token(temp_str);
}

void generate_spaceball_token(trans_data, rota_data, period)
short trans_data[3], rota_data[3], period;
{
  extern C_identity3D();
  extern C_IDE_simulation_method C_ide_simulation_method;
  extern C_IDE_token ide_data_token[C_MAX_RD_NUMBER];
  float trans_position[3];

  if (C_ide_simulation_method.spaceball.translate_dominate !=2)
   {
     C_spaceball_translate(trans_data, period, trans_position);
     ide_data_token[C_SPACEBALL].pos3d.x += trans_position[0];
     ide_data_token[C_SPACEBALL].pos3d.y += trans_position[1];
     ide_data_token[C_SPACEBALL].pos3d.z += trans_position[2];
     ide_data_token[C_SPACEBALL].pos2d.x = ide_data_token[C_SPACEBALL].pos3d.x;
     ide_data_token[C_SPACEBALL].pos2d.y = ide_data_token[C_SPACEBALL].pos3d.y;
   }
  if (C_ide_simulation_method.spaceball.rotation_dominate !=2) 
   {
     C_spaceball_rotation(rota_data, period, 
              ide_data_token[C_SPACEBALL].rotation.matrix);
   }
  else
   {
     C_identity3D(&(ide_data_token[C_SPACEBALL].rotation));
   }

  C_spaceball_report_token();
}

void C_reset_spaceball()
{
  extern C_identity3D();
  extern C_IDE_token ide_data_token[C_MAX_RD_NUMBER];
#ifdef C_SGI
  extern void gl_init_spaceball_queue();
#endif

  C_identity3D(&(ide_data_token[C_SPACEBALL].rotation));
#ifdef C_SGI
  gl_init_spaceball_queue();
#endif

}
