import vrml.*; import vrml.node.*; import vrml.field.*; import java.lang.Math; import java.util.*; public class leadfish extends Script { private double x, y, z; // potition private double vx, vy, vz; // velocity private double ax, ay, az; // acceleration private int timecount; private double lasttime; private SFRotation rotation; private SFVec3f translation; private SFRotation bodyrot; private SFFloat myx; private Random rnd; public void initialize( ) { vx = 1; vy = 0; vz = 0; ax = 0; ay = 0; az = 0; timecount = 0; lasttime = 0; rnd = new Random( ); rotation = (SFRotation)getField( "rotation" ); bodyrot = (SFRotation)getField( "bodyrot" ); translation = (SFVec3f)getField( "translation" ); SFFloat initrotation = (SFFloat)getField( "initrotation" ); SFFloat initradius = (SFFloat)getField( "initradius" ); SFFloat initheight = (SFFloat)getField( "initheight" ); myx = (SFFloat)getEventOut( "myx" ); y = initheight.getValue(); z = initradius.getValue(); x = initrotation.getValue( ); } private double clamp( double val, double min, double max ) { if( val < min ) return min; else if( val > max ) return max; else return val; } public void timer( float frac ) { // time elapsed before this frame if( frac < lasttime ) timecount ++; double t = (double)timecount + (double)frac - lasttime; lasttime = (double)timecount + (double)frac; // randomized acceleration double acoeff = 0.01; ax = ax + acoeff * rnd.nextGaussian( ); ay = clamp( ay + acoeff * rnd.nextGaussian( ), -0.05, 0.05 ); az = clamp( az + acoeff * rnd.nextGaussian( ), -0.05, 0.05 ); x = x + vx*t + ax*t*t; y = clamp( y + vy*t + ay*t*t, -3.5, 3.5 ); z = clamp( z + vz*t + az*t*t, 2, 7.5 ); vx = 2 * ax * t; vy = 2 * ay * t; vz = 2 * az * t; if( vx < 0.5 ) ax += 0.05; else if( vx > 1 ) ax -= 0.05; if( y < -2.5 ) ay += 0.1; else if( y > 2.5 ) ay -= 0.1; if( z < 3 ) az += 0.1; else if( z > 6.5 ) az -= 0.1; // rotation around tank float rot[] = new float[4]; rot[0] = 0; rot[1] = 1; rot[2] = 0; rot[3] = (float)( (x/50) * 6.28 ); // tank circumfrence =~50 rotation.setValue( rot ); myx.setValue( (float)x ); // translation vertically and radially float tr[] = new float[3]; tr[0] = 0; tr[1] = (float)y; tr[2] = (float)z; translation.setValue( tr ); // fish body rotation is around cross product of straight (1,0,0) // and the rotation its travelling rot[0] = 0; rot[1] = (float)(- vz); rot[2] = (float)vy; // amount of fish body rotation is computed from dot product: // v1.v2=|v1|*|v2|*cos(angle) // v1 = 1,0,0, v2 = velocity vector double totalVelocity = Math.sqrt( vx*vx + vy*vy + vz*vz ); rot[3] = (float)Math.acos(vx/totalVelocity); bodyrot.setValue( rot ); } public void processEvent( Event e ) { String EventName = e.getName( ); if( EventName.equals( "setfraction" ) ) timer( ((ConstSFFloat)e.getValue()).getValue() ); } }