/* * fish.java * Aleksey Potashnik (cs184-bk) * Created on PC, NT4, MSJ++ 1.1 * Lab5 */ import vrml.*; import vrml.node.*; import vrml.field.*; import java.lang.Math; import java.util.Random; public class fish extends Script { static final float TANK_RADIUS = 15; static final float TANK_HEIGHT = 7; private float velocity; private float tailAngle; private int tailShift; private SFRotation tail_changed; private SFVec3f curPos; private SFRotation rot_changed; private SFVec3f pos_changed; private float tailTurn; private int tailCur; private int tailDir; private float curX, curY, curZ, curA0; private float newX, newY, newZ; private float oldFrac; private Random rand; private int type; private SFVec3f lead_pos; private float fromLead; public void initialize () { velocity = ((SFFloat) getField ("velocity")).getValue(); tailAngle = ((SFFloat) getField ("tailAngle")).getValue(); tailShift = ((SFInt32) getField ("tailShift")).getValue(); tail_changed = (SFRotation) getField ("tail_changed"); rot_changed = (SFRotation) getField ("rot_changed"); pos_changed = (SFVec3f) getField ("pos_changed"); tailTurn = tailAngle / tailShift; tailCur = 0; tailDir = 1; tailUpdate(); oldFrac = 0; curPos = (SFVec3f) getField ("curPos"); newX = curX = curPos.getX(); newY = curY = curPos.getY(); newZ = curZ = curPos.getZ(); curA0 = ((SFFloat) getField ("curAngle0")).getValue(); rand = new Random(); type = ((SFInt32) getField ("Type")).getValue(); if (type == 1) { lead_pos = (SFVec3f) ((Node)((SFNode) getField ("lead")). getValue()).getExposedField("translation"); fromLead = ((SFFloat) getField ("fromLead")).getValue(); } } private void tailUpdate(){ tail_changed.setValue(0.0f, 1.0f, 0.0f, tailTurn * tailCur); if (Math.abs(tailCur) == tailShift) tailDir *= -1; tailCur += tailDir; } private void fishMove(float x, float y, float z){ curX = x; curY = y; curZ = z; pos_changed.setValue(curX, curY, curZ); } private void fishRotate(float a0){ rot_changed.setValue(0.0f, 1.0f, 0.0f, a0); } private void fishUpdate_lead(float dt){ float tr, xc, zc; float d = velocity * dt; float dist = (float)Math.sqrt( (newX - curX)*(newX - curX) + (newY - curY)*(newY - curY) + (newZ - curZ)*(newZ - curZ) ); float ratio; if (d >= dist){ fishMove(newX, newY, newZ); newY = TANK_HEIGHT * (0.2f + 0.6f * rand.nextFloat()); curA0 += (float)Math.PI/6; if (curA0 > 2 * Math.PI) curA0 -= 2 * Math.PI; tr = TANK_RADIUS * (0.3f + 0.6f * rand.nextFloat()); newX = tr * (float)Math.cos(curA0); newZ = -tr * (float)Math.sin(curA0); xc = newX - curX; zc = newZ - curZ; fishRotate((float)Math.atan2(xc, zc) + (float)Math.PI/2); } else { ratio = d/dist; fishMove(curX + ratio*(newX - curX), curY + ratio*(newY - curY), curZ + ratio*(newZ - curZ)); } } private void fishUpdate_fol(float dt){ float tr, xc, zc; float d = velocity * dt; float dist, ratio; newX = lead_pos.getX(); newY = lead_pos.getY(); newZ = lead_pos.getZ(); dist = (float)Math.sqrt( (newX - curX)*(newX - curX) + (newY - curY)*(newY - curY) + (newZ - curZ)*(newZ - curZ) ); xc = newX - curX; zc = newZ - curZ; fishRotate((float)Math.atan2(xc, zc) + (float)Math.PI/2); if (fromLead <= dist) { if (d > (dist - fromLead)) d = dist - fromLead; ratio = d / dist; fishMove(curX + ratio*(xc), curY + ratio*(newY - curY), curZ + ratio*(zc)); } } public void processEvent(Event e){ String name = e.getName(); float frac; if (name.equals("set_fraction")){ tailUpdate(); frac = ((ConstSFFloat)e.getValue()).getValue(); if (frac > oldFrac) { if (type == 0) fishUpdate_lead(frac - oldFrac); else fishUpdate_fol(frac - oldFrac); oldFrac = frac; } else oldFrac = 0; } } }