/* 
Mihut Ionescu       Francis Li
SID#:  12398942     SID#:  13086460
CS 184
LAB5
Developed on PC (Win95).
*/

import vrml.*;
import vrml.node.*;
import vrml.field.*;
import java.util.*;

public class FlockBehavior extends Script {
  private float MAX_RADIUS = 2.0f;
  
  private SFNode leader;
  private long seed;
  private SFVec3f currentTranslation; 
  private SFVec3f set_translation; 
  
  private Random randomGenerator;
  private float dx, dy, dz;
  private float previousFraction;
  private float[] previousTranslation;
  private float[] offset;
  
  private float[] getTranslation(SFNode node) {
    float[] loc = new float[3];
    SFVec3f vect = (SFVec3f) ((Node) node.getValue ()).getExposedField ("translation");
    
    loc[0] = vect.getX ();
    loc[1] = vect.getY ();
    loc[2] = vect.getZ ();
    
    return loc;
    }
  
  private float getRandom () {
    return 2.0f * (randomGenerator.nextFloat () - 0.5f);
    }
  
  public void initialize() {
    float[] rotation = new float[4];
    
    leader = (SFNode) getField ("leader");  
    seed = (long) ((SFInt32) getField ("seed")).getValue ();
    currentTranslation = (SFVec3f) getField("currentTranslation");
    set_translation = (SFVec3f) getEventOut("set_translation");
    
    float[] loc = getTranslation (leader);
    
    offset = new float[3];
    offset[0] = currentTranslation.getX ();
    offset[1] = currentTranslation.getY ();
    offset[2] = currentTranslation.getZ ();   
    
    currentTranslation.setValue (loc[0] + currentTranslation.getX (), loc[1] + currentTranslation.getY (), loc[2] + currentTranslation.getZ ());
    
    randomGenerator = new Random(seed);
    dx = getRandom () * MAX_RADIUS;
    dy = getRandom () * MAX_RADIUS;
    dz = getRandom () * MAX_RADIUS;
    previousFraction = 0.0f;
    previousTranslation = new float[3];
    previousTranslation[0] = currentTranslation.getX();
    previousTranslation[1] = currentTranslation.getY();
    previousTranslation[2] = currentTranslation.getZ();
    }
  
  public void processEvent(Event e) {
    String eventName = e.getName();
    
    if (eventName.equals("set_fraction"))
      set_fraction(((ConstSFFloat) e.getValue()).getValue());
    }
  
  private void set_fraction(float fraction) {
    float x = currentTranslation.getX();
    float y = currentTranslation.getY();
    float z = currentTranslation.getZ();
    
    if (fraction < previousFraction) {
      float[] loc = getTranslation (leader);

      dx = getRandom () * MAX_RADIUS + loc[0] + offset[0] - x;
      dy = getRandom () * MAX_RADIUS + loc[1] + offset[1] - y;
      dz = getRandom () * MAX_RADIUS + loc[2] + offset[2] - z;
      
      previousTranslation[0] = x;
      previousTranslation[1] = y;
      previousTranslation[2] = z;
      }   
    x = previousTranslation[0] + fraction * dx;
    y = previousTranslation[1] + fraction * dy;
    z = previousTranslation[2] + fraction * dz;
    currentTranslation.setValue(x, y, z);
    set_translation.setValue(currentTranslation);
    previousFraction = fraction;
    }
  }