import vrml.*; import vrml.node.*; import vrml.field.*; import java.lang.Math; import java.util.*; public class fish 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 SFFloat leaderx; private float leaderlastx; private Random rnd; //private SFVec3f leaderpos; private SFNode leadernode; private float maxdist, mindist; 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" ); leaderx = (SFFloat)getEventIn( "leaderx" ); y = initheight.getValue(); z = initradius.getValue(); x = initrotation.getValue( ); maxdist = ((SFFloat)getField( "maxdist" )).getValue(); mindist = ((SFFloat)getField( "mindist" )).getValue(); leadernode = (SFNode)getField( "leader" ); // leadernodepos = (SFVec3f)((Node)((SFNode)getField( "leader" )). // getValue()).getExposedField( "translation" ); leaderlastx = 0; } 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.001; 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 ); // get leader's position SFVec3f leaderpos = (SFVec3f)((Node)leadernode.getValue()). getExposedField( "translation" ); float lpos[] = new float[3]; leaderpos.getValue(lpos); lpos[0] = leaderlastx; //System.out.println( lpos[0] ); double dist[] = new double[3]; dist[0] = lpos[0] - x; dist[1] = lpos[1] - y; dist[2] = lpos[2] - z; double ldist = Math.sqrt( dist[0]*dist[0] + dist[1]*dist[1] + dist[2]*dist[2] ); // System.out.print( "lpos[2] = " + lpos[2] ); //System.out.print( " z = " + z ); //System.out.print( "\n" ); // normalize distance vector dist[0] /= ldist; dist[1] /= ldist; dist[2] /= ldist; // System.out.println( ldist ); if( ldist < mindist ) { double force = (mindist-ldist) * (mindist-ldist) * 0.1; ax -= dist[0]*force; ay -= dist[1]*force; az -= dist[2]*force; } else if( ldist > maxdist ) { double force = clamp((ldist-maxdist) * (ldist-maxdist) * .1, -0.1, 0.1); ax += dist[0]*force; ay += dist[1]*force; az += dist[2]*force; } 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; // ax *= 0.7; ax *= 1 / (t/6 + 1); 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() ); if( EventName.equals( "leaderx" ) ) leaderlastx = ((ConstSFFloat)e.getValue()).getValue(); } }