//
// WandBehaviorJ3D.java
//

/*
VisAD system for interactive analysis and visualization of numerical
data.  Copyright (C) 1996 - 2017 Bill Hibbard, Curtis Rueden, Tom
Rink, Dave Glowacki, Steve Emmerson, Tom Whittaker, Don Murray, and
Tommy Jasmin.

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.

This library 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
Library General Public License for more details.

You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA
*/

package visad.java3d;

import visad.*;

import javax.media.j3d.*;
import javax.vecmath.*;

import java.util.*;

/**
   WandBehaviorJ3D is the VisAD class for wand behaviors for Java3D
   it works with ImmersaDeskDisplayRendererJ3D
*/

/* extend MouseBehaviorJ3D to inherit multiply_matrix, make_matrix, etc */
public class WandBehaviorJ3D extends MouseBehaviorJ3D
       implements Runnable, MouseBehavior {

  /** DisplayRenderer for Display */
  ImmersaDeskDisplayRendererJ3D display_renderer;
  DisplayImpl display;

  private Thread wandThread;

  // use vpTrans for head motion from tracker,
  // and for left-button wand motion
  private TransformGroup vpTrans;

  // initial Transform3D from vpTrans
  private Transform3D init_trans;

  private float[] head_position = new float[3];
  private float[] wand_position = new float[3];
  private float[] wand_vector = new float[3];
  // integral of wand_vector during left == true
  private float[] travel_position = new float[3];
  // wand button states
  private boolean left = false, center = false, right = false;
  // previous right wand button state
  private boolean last_right;

  private DataRenderer direct_renderer = null;

  private TrackdJNI hack;

  public WandBehaviorJ3D(ImmersaDeskDisplayRendererJ3D r,
                         int tracker_shmkey, int controller_shmkey)
         throws VisADException {
    super();
    display_renderer = r;
    display = display_renderer.getDisplay();

    hack = new TrackdJNI(tracker_shmkey, controller_shmkey);

    last_right = false;
  }

  /* override MouseBehaviorJ3D.initialize() to do start Thread */
  public void initialize() {
    wandThread = new Thread(this);
    wandThread.start();
    vpTrans = display_renderer.getViewTrans();

    init_trans = new Transform3D();
    vpTrans.getTransform(init_trans);
  }

  /* override MouseBehaviorJ3D.processStimulus() to do nothing */
  public void processStimulus(Enumeration criteria) {
  }

  public void stop() {
    wandThread = null;
  }


  // QUESTION? values of these BOLD variables QUESTION?
  private static int DELAY = 50; // ms
  private static int NSENSORS = 4;
  private static int NBUTTONS = 3;

  // sensor numbers
  private static int HEAD = 0;
  private static int WAND = 1;

  // button numbers
  private static int LEFT = 0;
  private static int CENTER = 1;
  private static int RIGHT = 2;

  // angle numbers
  private static int ELEVATION = 0;
  private static int AZIMUTH = 1;
  private static int ROLL = 2;

  // graphics distance (feet?) per second
  private float TRAVEL_SPEED = 4.0f;

  // scale factors for head / wand translation (negative?)
  // NOTE - you may need to adjust these for your ImmersaDesk
  private float HEAD_SCALE = 0.10f;
  private float WAND_SCALE = 1.5f;

  // offsets for head / wand translation
  // NOTE - you may need to adjust these for your ImmersaDesk
  private float HEADX_OFFSET = 0.0f;
  private float HEADY_OFFSET = -3.0f;
  private float HEADZ_OFFSET = 5.0f;
  private float WANDX_OFFSET = -0.5f;
  private float WANDY_OFFSET = -2.0f;
  private float WANDZ_OFFSET = 0.0f;

  // length of direct manipulation ray
  private float RAY_LENGTH = 2.0f;


  public void run() {
    Thread me = Thread.currentThread();
    int[] number_of_sensors = new int[1];
    float[] sensor_positions = new float[NSENSORS * 3];
    float[] sensor_angles = new float[NSENSORS * 3];
    float[] sensor_matrices = new float[NSENSORS * 4 * 4];
    int[] number_of_buttons = new int[1];
    int[] button_states = new int[NBUTTONS];
    int nprint = 1000 / DELAY;
    travel_position[0] = 0.0f;
    travel_position[1] = 0.0f;
    travel_position[2] = 0.0f;
    while (wandThread == me) {
      try {
        synchronized (this) {
          wait(DELAY);
        }
      }
      catch(InterruptedException e) {
        // control doesn't normally come here
      }
      number_of_sensors[0] = NSENSORS;
      number_of_buttons[0] = NBUTTONS;
      hack.getTrackd(number_of_sensors, sensor_positions, sensor_angles,
                     sensor_matrices, number_of_buttons, button_states);
/*
      nprint--;
      if (nprint <= 0) {
        nprint = 1000 / DELAY;
        for (int i=0; i 

Ads help maintain this website.