import vrml.*;
import vrml.node.*;
import vrml.field.*;
import java.lang.Math;
import java.util.*;
// 0 turn angle = +y direction (actually +z in VRML coords)
public class target extends Script
{
private Random rnd;
private double lasttime;
private float steptime = 1; // # seconds a single step takes
private SFVec3f translation; // position of target
private SFFloat speed;
private float vel[] = { 0, 0, 1 };
private float x, y, z;
private float sa[], sb[], sc[], sd[]; // points on square we're on
private float goDistance, goPassed;
// climb mode stuff
boolean isClimbMode;
// feet stuff
boolean isOddFeet;
private SFVec3f feet[];
float feetsrc[][]; // point where feet are moving from
float feetvec[][]; // normalized direction feet are moving
float feetdist[]; // distance foot will move
float feetpos[]; // distance foot has currently gone
float feetspeed[];
float feetoffsets[][] = { // ideal positions from target of feet
// forward, 0, side
{ 0.2f, 0, 0.4f },
{ 0.0f, 0, 0.4f },
{ -0.4f, 0, 0.4f },
{ 0.2f, 0, -0.4f },
{ 0.0f, 0, -0.4f },
{ -0.4f, 0, -0.4f } };
public void initialize( )
{
lasttime = 0;
rnd = new Random( );
translation = (SFVec3f)getEventOut( "translation" );
speed = (SFFloat)getField( "speed" );
sa = new float[3];
sb = new float[3];
sc = new float[3];
sd = new float[3];
x = -12f;
y = -11f;
z = 0.0f;
isClimbMode = true;
isOddFeet = true; // start off moving odd feet
// load the current feet positions
feetsrc = new float[6][3];
feetvec = new float[6][3];
feetdist = new float[6];
feetpos = new float[6];
feetspeed = new float[6];
loadsquare( );
loaddirection( );
}
private void normalize( float vec[] )
{
double len = Math.sqrt( vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2] );
vec[0] /= len;
vec[1] /= len;
vec[2] /= len;
}
private float clamp( float val, float min, float max )
{
if( val < min )
return min;
else if( val > max )
return max;
else
return val;
}
// finds the distance between line la,lb, and point p
private float dptol( float px, float py, float lax, float lay,
float lbx, float lby )
{
float ax = lbx - lax;
float ay = lby - lay;
float bx = px - lax;
float by = py - lay;
// vector a cross vector b (make up third dimension)
float axbz = ax*by - ay*bx;
return (float)( Math.sqrt( axbz*axbz ) /
Math.sqrt( ax*ax + ay*ay ) );
}
// loads the current triangle coordinates from the current position
private void loadsquare( )
{
// indexes of upper left
int ix = (int)Math.floor( x + 16f );
int iy = (int)Math.floor( y + 16f );
// index of upper left vertex
sa[0] = (float)ix - 16f;
sa[1] = terrain[ix][iy];
sa[2] = (float)iy - 16f;
// upper right
sb[0] = sa[0] + 1;
sb[1] = terrain[ix+1][iy];
sb[2] = sa[2];
// lower left
sc[0] = sa[0];
sc[1] = terrain[ix][iy+1];
sc[2] = sa[2] + 1;
// lower right
sd[0] = sa[0] + 1;
sd[1] = terrain[ix+1][iy+1];
sd[2] = sa[2] + 1;
}
// returns the elevation of the current position
private float getElevation( )
{
double xfrac = x - Math.floor(x);
double yfrac = y - Math.floor( y );
double zt = (sb[1]-sa[1])*xfrac + sa[1];
double zb = (sd[1]-sc[1])*xfrac + sc[1];
return (float)( (zb-zt)*yfrac + zt );
}
// save as getElevation but for an arbitrary point
private float getElevationPt( float xpt, float ypt )
{
double xfrac = xpt - Math.floor( xpt );
double yfrac = ypt - Math.floor( ypt );
double zt = (sb[1]-sa[1])*xfrac + sa[1];
double zb = (sd[1]-sc[1])*xfrac + sc[1];
return (float)( (zb-zt)*yfrac + zt );
}
// returns the angle in radians between the two vectors
private float angleBetweenVect( float a[], float b[] )
{
return (float)Math.acos( ( a[0]*b[0] + a[1]*b[1] + a[2]*b[2] ) /
( Math.sqrt( a[0]*a[0] + a[1]*a[1] + a[2]*a[2] ) *
Math.sqrt( b[0]*b[0] + b[1]*b[1] + b[2]*b[2] ) ) );
}
private void printpoint( float pt[] )
{
System.out.println( "point:("+pt[0]+","+pt[2]+","+pt[1] + ")" );
}
// called by loaddirection to check a line
private boolean checkline( float pta[], float ptb[] )
{
// check if the specified line contains the current elevation
if( ! ( ( pta[1] > z && ptb[1] < z ) ||
( pta[1] < z && ptb[1] > z ) ) )
return false;
// now we know the line contains the current elevation,
// we need to find the point on the line sharing our elevation
float dx, dy; // point on line sharing our elevation
float frac = ( z - pta[1] ) / ( ptb[1] - pta[1] );
dx = pta[0] + ( ptb[0] - pta[0] ) * frac;
dy = pta[2] + ( ptb[2] - pta[2] ) * frac;
// make sure angle between point and direction isn't too big ~30deg
float lp[] = { dx - x, 0, dy - y };
if( angleBetweenVect( lp, vel ) > 0.6 )
return false;
float angle = (float)( Math.atan( lp[2]+lp[0] ) );
vel[0] = (float)Math.cos(angle) * speed.getValue( );
vel[1] = 0;
vel[2] = (float)Math.sin(angle) * speed.getValue( );
goDistance = (float)Math.sqrt( lp[0]*lp[0] + lp[2]*lp[2] );
goPassed = 0;
isClimbMode = false;
return true;
}
// returns true if the current position is in the loaded square
private boolean PtInRect( )
{
if( x > sa[0] && x < sa[0]+1 && y > sa[2] && y < sa[2]+1 )
return true;
return false;
}
// puts us into climb mode and picks the directio & distance
private void loadClimbMode( )
{
isClimbMode = true;
float angle = (float)( rnd.nextGaussian( ) * 0.2f +
Math.atan(vel[2]/vel[0]) );
goDistance=0.3f;
goPassed = 0;
vel[0] = (float)(Math.cos(angle)*0.1);
vel[2] = (float)(Math.sin(angle)*0.1);
}
// called when he gets too close to a wall
private void bounce( )
{
//x = (float)( rnd.nextGaussian( ) * 10 );
// y = (float)( rnd.nextGaussian( ) * 10 );
if( Math.abs( x ) > Math.abs( y ) )
{ // bounce off x wall
vel[0] = - vel[0];
}
else
{ // boucne off y wall
vel[2] = - vel[2];
}
goDistance = 4;
goPassed = 0;
}
private void loaddirection( )
{
z = getElevation( );
if( Math.abs( x ) > 13 || Math.abs( y ) > 13 )
{
bounce( );
return;
}
if( rnd.nextGaussian( ) > 0 )
{
if( checkline( sa, sb ) )
{ // try top line
return;
}
else if( checkline( sa, sc ) )
{ // left line
return;
}
else if( checkline( sb, sd ) )
{ // right line
return;
}
else if( checkline( sc, sd ) )
{ // bottom line
return;
}
else
loadClimbMode( );
}
else
{
if( checkline( sb, sd ) )
{ // right line
return;
}
else if( checkline( sc, sd ) )
{ // bottom line
return;
}
else if( checkline( sa, sb ) )
{ // try top line
return;
}
else if( checkline( sa, sc ) )
{ // left line
return;
}
else
loadClimbMode( );
}
}
private void advanceClimbMode( float t )
{
if( ! PtInRect( ) )
{ // entered a new square
loadsquare( );
}
float dx = vel[0]*t, dy = vel[2]*t;
goPassed += (float)Math.sqrt( dx*dx + dy*dy );
if( goPassed > goDistance )
{
loaddirection( );
}
x += dx;
y += dy;
}
private void advanceWalkMode( float t )
{
float dx = vel[0]*t, dy = vel[2]*t;
x += dx;
y += dy;
goPassed += (float)Math.sqrt( dx*dx + dy*dy );
if( goPassed > goDistance )
{
loadsquare( );
loaddirection( );
}
}
// fills the destination position with the specified foot's dest coords
// ignores up & down component for everything
private void getNewFootTarget( int num, float dest[] )
{
double direction = Math.atan( vel[2] / vel[0] );
double mag = Math.sqrt( feetoffsets[num][0]*feetoffsets[num][0] +
feetoffsets[num][2]*feetoffsets[num][2] );
direction += Math.atan( feetoffsets[num][2] / feetoffsets[num][0] );
dest[0] = (float)( x + mag*Math.cos( direction ) );
dest[1] = 0;
dest[2] = (float)( y + mag*Math.sin( direction ) );
}
private void beginNewFootMove( int num )
{
float dest[] = new float[3];
double direction = Math.atan( vel[2] / vel[0] );
double mag = Math.sqrt( feetoffsets[num][0]*feetoffsets[num][0] +
feetoffsets[num][2]*feetoffsets[num][2] );
direction += Math.atan( feetoffsets[num][2] / feetoffsets[num][0] );
dest[0] = (float)( x + mag*Math.cos( direction ) );
dest[1] = 0;
dest[2] = (float)( y + mag*Math.sin( direction ) );
float pos[] = new float[3];
feetsrc[num][0] += feetpos[num]*feetvec[num][0];
feetsrc[num][2] += feetpos[num]*feetvec[num][2];
// normalized direction vector
feetvec[num][0] = dest[0] - feetsrc[num][0];
feetvec[num][1] = 0;
feetvec[num][2] = dest[2] - feetsrc[num][2];
feetdist[num] = (float)Math.sqrt( feetvec[num][0]*feetvec[num][0] +
feetvec[num][2]*feetvec[num][2] );
feetvec[num][0] /= feetdist[num];
feetvec[num][2] /= feetdist[num];
feetpos[num] = 0;
feetspeed[num] = feetdist[num] / steptime;
}
// returns whether or not this foot is done with movement
private boolean movefoot( int num, double t )
{
if( feetpos[num] > feetdist[num] )
{
return true;
}
feetpos[num] += feetspeed[num] * t;
float pos[] = new float[3];
pos[0] = feetsrc[num][0] + feetpos[num]*feetvec[num][0];
pos[2] = feetsrc[num][2] + feetpos[num]*feetvec[num][2];
pos[1] = getElevationPt( pos[0], pos[2] );
feet[num].setValue( pos );
return false;
}
// returns whether or not the feet need to be switched
private boolean movefeet( double t )
{
boolean redo = false;
if( isOddFeet )
{
if( movefoot( 1, t ) )
return true;
movefoot( 3, t );
movefoot( 5, t );
}
else
{
if( movefoot( 0, t ) )
return true;
movefoot( 2, t );
movefoot( 4, t );
}
return false;
}
private void timer( )
{
// time delta from last frame
double curtime = (double)(System.currentTimeMillis() / 1000.0);
double t;
if( lasttime == 0 )
t = 0.01f;
else
t = curtime - lasttime;
lasttime = curtime;
if( isClimbMode )
advanceClimbMode( (float)t );
else
advanceWalkMode( (float)t );
// set position (our z is world's y -- up)
float pos[] = { x, 0, y };
translation.setValue( pos );
}
public void processEvent( Event e )
{
String EventName = e.getName( );
if( EventName.equals( "setfraction" ) )
timer( );
}
float terrain[][] =
{
{ 0.30f, 0.74f, 0.65f, 0.77f, 0.34f, 0.94f, 0.60f, 0.80f, 0.23f, 0.66f, 0.71f, 0.77f, 0.29f, 0.87f, 0.49f, 0.60f, 0.17f, 0.41f, 0.36f, 0.61f, 0.44f, 0.78f, 0.73f, 0.91f, 0.32f, 0.43f, 0.49f, 0.55f, 0.19f, 0.71f, 0.43f, 0.55f, 0.00f },
{ 0.78f, 1.07f, 1.07f, 0.87f, 0.90f, 0.87f, 1.12f, 0.74f, 0.80f, 0.77f, 0.93f, 0.74f, 0.58f, 0.68f, 0.76f, 0.84f, 0.41f, 0.55f, 1.07f, 0.76f, 1.17f, 1.18f, 1.05f, 0.90f, 0.67f, 0.98f, 0.97f, 0.87f, 0.98f, 0.68f, 0.82f, 0.42f, 0.38f },
{ 0.52f, 1.13f, 0.85f, 0.89f, 0.87f, 1.32f, 0.92f, 1.15f, 0.64f, 0.66f, 0.59f, 0.76f, 0.81f, 0.81f, 0.77f, 1.26f, 0.27f, 0.69f, 0.82f, 0.77f, 0.93f, 1.36f, 0.91f, 1.22f, 0.88f, 1.22f, 0.77f, 0.65f, 0.78f, 0.76f, 0.45f, 0.78f, 0.35f },
{ 0.84f, 0.78f, 1.21f, 0.95f, 1.06f, 1.09f, 1.00f, 0.92f, 0.89f, 0.92f, 1.12f, 1.01f, 0.74f, 0.77f, 1.13f, 1.31f, 0.51f, 0.98f, 0.76f, 0.66f, 0.74f, 1.21f, 1.16f, 0.88f, 0.87f, 1.29f, 1.26f, 1.02f, 0.68f, 1.12f, 0.70f, 0.72f, 0.88f },
{ 0.61f, 0.70f, 0.75f, 0.91f, 0.59f, 0.99f, 0.83f, 1.10f, 0.64f, 0.86f, 0.61f, 1.01f, 0.54f, 0.90f, 0.95f, 1.17f, 0.37f, 0.96f, 0.85f, 0.81f, 0.50f, 0.85f, 0.71f, 1.19f, 0.83f, 1.18f, 1.10f, 0.86f, 0.50f, 1.07f, 0.64f, 0.76f, 0.62f },
{ 1.12f, 1.05f, 1.34f, 1.20f, 0.78f, 1.30f, 1.32f, 1.20f, 0.99f, 1.27f, 1.22f, 1.03f, 1.08f, 1.10f, 0.95f, 0.90f, 0.90f, 0.69f, 0.89f, 1.07f, 0.85f, 1.16f, 1.21f, 0.79f, 1.36f, 1.14f, 1.32f, 1.23f, 0.96f, 1.01f, 1.03f, 0.97f, 0.76f },
{ 0.69f, 0.99f, 1.11f, 1.31f, 0.83f, 1.41f, 1.00f, 1.31f, 0.91f, 1.12f, 0.95f, 0.95f, 0.99f, 1.10f, 0.80f, 1.30f, 0.46f, 1.14f, 0.85f, 1.08f, 0.81f, 0.86f, 0.77f, 1.14f, 0.89f, 1.22f, 1.17f, 1.32f, 1.15f, 1.16f, 0.70f, 0.98f, 0.89f },
{ 1.05f, 0.82f, 1.37f, 1.31f, 1.24f, 1.27f, 1.05f, 0.86f, 1.02f, 1.31f, 1.05f, 1.05f, 1.17f, 1.11f, 1.45f, 1.34f, 0.95f, 0.89f, 0.89f, 1.17f, 0.85f, 1.16f, 0.93f, 1.11f, 1.23f, 1.34f, 1.33f, 1.22f, 1.10f, 1.15f, 1.06f, 0.97f, 1.04f },
{ 0.65f, 1.27f, 0.96f, 1.09f, 0.71f, 1.19f, 1.00f, 1.31f, 0.69f, 1.03f, 1.16f, 1.31f, 1.06f, 1.28f, 1.04f, 0.94f, 0.49f, 0.88f, 0.98f, 0.95f, 0.71f, 1.18f, 0.74f, 0.75f, 0.59f, 1.13f, 0.72f, 0.99f, 0.61f, 0.87f, 0.96f, 0.86f, 0.63f },
{ 1.11f, 1.05f, 1.05f, 1.22f, 1.32f, 1.34f, 1.22f, 1.00f, 1.07f, 1.44f, 1.63f, 1.55f, 1.18f, 1.21f, 1.63f, 1.43f, 1.09f, 0.98f, 0.93f, 1.25f, 1.07f, 1.32f, 1.19f, 1.13f, 0.95f, 1.27f, 1.36f, 1.05f, 1.04f, 1.11f, 1.10f, 1.28f, 1.25f },
{ 1.05f, 1.38f, 0.96f, 1.12f, 1.24f, 1.21f, 1.02f, 1.31f, 0.99f, 1.42f, 1.19f, 1.58f, 1.15f, 1.41f, 1.28f, 1.22f, 0.78f, 0.85f, 0.80f, 1.14f, 1.16f, 1.60f, 1.12f, 1.21f, 1.05f, 1.26f, 1.15f, 1.13f, 0.94f, 1.08f, 1.21f, 1.50f, 1.29f },
{ 1.15f, 1.46f, 1.30f, 1.14f, 1.19f, 1.38f, 1.37f, 1.60f, 0.89f, 1.50f, 1.43f, 1.52f, 1.57f, 1.43f, 1.70f, 1.24f, 1.12f, 0.89f, 1.32f, 0.91f, 1.38f, 1.33f, 1.22f, 1.31f, 1.40f, 1.28f, 1.38f, 1.17f, 1.27f, 1.52f, 1.41f, 1.38f, 1.41f },
{ 1.10f, 1.62f, 1.21f, 1.43f, 1.01f, 1.61f, 1.30f, 1.14f, 0.74f, 1.28f, 1.19f, 1.36f, 1.10f, 1.69f, 1.38f, 1.43f, 0.89f, 1.14f, 1.01f, 1.19f, 0.75f, 1.08f, 1.13f, 1.26f, 1.04f, 1.09f, 1.00f, 1.27f, 0.81f, 1.10f, 1.10f, 1.23f, 0.99f },
{ 1.53f, 1.36f, 1.60f, 1.61f, 1.18f, 1.27f, 1.35f, 1.16f, 1.09f, 1.41f, 1.35f, 1.38f, 1.40f, 1.30f, 1.71f, 1.40f, 1.34f, 1.32f, 1.30f, 1.20f, 1.43f, 1.16f, 1.54f, 1.59f, 1.48f, 1.51f, 1.33f, 1.21f, 1.14f, 1.10f, 1.32f, 1.11f, 1.28f },
{ 0.98f, 1.25f, 1.26f, 1.30f, 0.89f, 0.94f, 0.92f, 1.23f, 1.14f, 1.55f, 1.12f, 1.68f, 1.05f, 1.69f, 1.36f, 1.45f, 0.97f, 1.03f, 1.05f, 1.21f, 1.23f, 1.49f, 1.25f, 1.78f, 1.27f, 1.48f, 1.16f, 1.16f, 0.96f, 1.42f, 1.02f, 1.40f, 0.94f },
{ 0.97f, 1.15f, 1.17f, 1.23f, 0.93f, 0.90f, 1.10f, 1.22f, 1.13f, 1.17f, 1.53f, 1.37f, 1.32f, 1.18f, 1.18f, 1.39f, 0.85f, 1.28f, 1.21f, 1.59f, 1.49f, 1.68f, 1.68f, 1.59f, 1.57f, 1.45f, 1.39f, 1.51f, 1.17f, 1.18f, 1.31f, 1.24f, 0.81f },
{ 0.60f, 1.08f, 1.26f, 1.46f, 1.16f, 1.33f, 1.45f, 1.46f, 0.87f, 1.21f, 1.27f, 1.28f, 1.13f, 1.37f, 1.06f, 1.07f, 0.57f, 0.78f, 0.91f, 1.41f, 0.97f, 1.18f, 1.00f, 1.40f, 0.92f, 1.34f, 1.13f, 1.45f, 0.90f, 1.51f, 1.12f, 1.29f, 0.48f },
{ 1.00f, 1.39f, 1.28f, 1.60f, 1.32f, 1.66f, 1.63f, 1.43f, 1.16f, 1.53f, 1.63f, 1.56f, 1.52f, 1.25f, 1.36f, 1.02f, 1.01f, 1.23f, 1.58f, 1.56f, 1.50f, 1.40f, 1.35f, 1.24f, 1.13f, 1.34f, 1.48f, 1.37f, 1.37f, 1.08f, 1.35f, 1.34f, 0.83f },
{ 1.00f, 1.06f, 1.12f, 1.54f, 1.40f, 1.83f, 1.35f, 1.46f, 1.32f, 1.39f, 1.24f, 1.63f, 1.18f, 1.61f, 1.18f, 1.61f, 1.18f, 1.65f, 1.33f, 1.26f, 1.38f, 1.41f, 1.23f, 1.66f, 1.31f, 1.29f, 1.06f, 1.48f, 1.21f, 1.42f, 0.91f, 1.37f, 0.84f },
{ 1.09f, 1.34f, 1.61f, 1.48f, 1.29f, 1.47f, 1.41f, 1.45f, 1.44f, 1.61f, 1.35f, 1.25f, 1.30f, 1.47f, 1.50f, 1.43f, 1.16f, 1.53f, 1.81f, 1.41f, 1.46f, 1.46f, 1.41f, 1.62f, 1.19f, 1.50f, 1.50f, 1.49f, 1.62f, 1.18f, 1.18f, 1.18f, 1.18f },
{ 0.97f, 1.59f, 1.38f, 1.22f, 0.89f, 1.38f, 1.12f, 1.47f, 0.89f, 1.16f, 1.11f, 1.36f, 0.92f, 1.23f, 1.00f, 1.30f, 0.90f, 1.45f, 1.32f, 1.41f, 1.21f, 1.44f, 1.21f, 1.38f, 0.95f, 1.04f, 1.09f, 1.16f, 1.05f, 1.17f, 0.95f, 1.28f, 0.68f },
{ 1.51f, 1.23f, 1.44f, 1.25f, 1.47f, 1.47f, 1.31f, 1.51f, 1.07f, 1.16f, 1.47f, 1.45f, 1.14f, 1.31f, 1.48f, 1.24f, 1.47f, 1.63f, 1.55f, 1.55f, 1.90f, 1.54f, 1.60f, 1.61f, 1.19f, 1.12f, 1.42f, 1.67f, 1.44f, 1.56f, 1.44f, 1.36f, 0.93f },
{ 1.08f, 1.23f, 1.10f, 1.45f, 1.33f, 1.36f, 1.24f, 1.45f, 1.23f, 1.49f, 1.15f, 1.34f, 1.24f, 1.61f, 1.29f, 1.49f, 1.26f, 1.53f, 1.23f, 1.46f, 1.62f, 1.78f, 1.34f, 1.37f, 1.02f, 1.50f, 1.09f, 1.72f, 1.37f, 1.48f, 1.20f, 1.40f, 0.93f },
{ 1.40f, 1.10f, 1.10f, 1.27f, 1.38f, 1.15f, 1.20f, 1.26f, 1.36f, 1.35f, 1.10f, 1.49f, 1.43f, 1.45f, 1.18f, 1.12f, 1.53f, 1.56f, 1.46f, 1.75f, 1.51f, 1.58f, 1.54f, 1.29f, 1.20f, 1.44f, 1.34f, 1.74f, 1.53f, 1.35f, 1.30f, 1.22f, 1.12f },
{ 0.75f, 1.00f, 0.93f, 1.20f, 0.85f, 1.22f, 1.04f, 1.21f, 0.72f, 1.46f, 1.27f, 1.55f, 1.22f, 1.36f, 1.33f, 1.31f, 0.92f, 1.63f, 1.38f, 1.29f, 0.92f, 1.56f, 1.21f, 1.26f, 0.84f, 1.27f, 0.94f, 0.98f, 0.92f, 1.33f, 0.86f, 1.13f, 0.45f },
{ 0.81f, 1.30f, 1.07f, 1.14f, 1.37f, 1.24f, 1.44f, 1.32f, 1.36f, 1.42f, 1.44f, 1.63f, 1.50f, 1.70f, 1.50f, 1.28f, 1.57f, 1.22f, 1.46f, 1.40f, 1.48f, 1.60f, 1.19f, 1.22f, 0.93f, 1.23f, 1.51f, 1.49f, 1.26f, 1.27f, 1.23f, 0.74f, 0.86f },
{ 0.75f, 0.97f, 1.07f, 1.36f, 1.04f, 1.34f, 0.96f, 0.95f, 1.00f, 1.15f, 1.26f, 1.88f, 1.55f, 1.52f, 1.44f, 1.77f, 1.38f, 1.63f, 1.04f, 1.22f, 1.30f, 1.58f, 1.02f, 1.48f, 1.01f, 1.45f, 1.17f, 1.20f, 1.33f, 1.46f, 1.05f, 1.01f, 0.46f },
{ 0.81f, 1.25f, 1.39f, 1.02f, 0.93f, 1.30f, 1.36f, 1.02f, 1.21f, 1.27f, 1.69f, 1.49f, 1.38f, 1.43f, 1.62f, 1.10f, 1.79f, 1.39f, 1.19f, 1.10f, 1.49f, 1.26f, 1.26f, 1.22f, 0.98f, 1.02f, 1.42f, 1.15f, 1.42f, 1.30f, 1.16f, 0.82f, 0.60f },
{ 0.71f, 1.09f, 0.97f, 1.15f, 0.65f, 1.02f, 0.97f, 1.03f, 0.89f, 1.40f, 1.24f, 1.54f, 1.07f, 1.49f, 1.06f, 1.20f, 1.25f, 1.68f, 1.22f, 1.22f, 0.80f, 1.14f, 0.95f, 1.07f, 0.91f, 1.01f, 1.02f, 1.10f, 0.92f, 0.87f, 0.75f, 0.67f, 0.42f },
{ 1.21f, 0.83f, 1.06f, 1.26f, 1.25f, 1.30f, 1.27f, 1.24f, 1.38f, 1.60f, 1.51f, 1.59f, 1.28f, 1.21f, 1.52f, 1.46f, 1.82f, 1.65f, 1.29f, 1.24f, 0.95f, 1.37f, 0.96f, 1.22f, 0.98f, 1.20f, 1.38f, 1.26f, 1.43f, 1.35f, 1.05f, 0.64f, 0.75f },
{ 0.93f, 1.12f, 0.71f, 1.26f, 0.96f, 1.34f, 1.21f, 1.39f, 1.12f, 1.52f, 1.20f, 1.55f, 1.23f, 1.22f, 1.14f, 1.31f, 1.39f, 1.46f, 1.32f, 1.53f, 0.96f, 1.22f, 0.88f, 1.27f, 0.84f, 1.28f, 1.23f, 1.42f, 1.06f, 1.37f, 0.77f, 1.09f, 0.61f },
{ 0.79f, 1.11f, 1.13f, 1.14f, 0.94f, 1.48f, 1.44f, 1.44f, 1.17f, 1.04f, 1.21f, 1.49f, 1.27f, 1.55f, 1.16f, 1.41f, 1.13f, 1.46f, 1.64f, 1.54f, 1.07f, 1.21f, 1.14f, 1.26f, 1.03f, 1.35f, 1.38f, 1.45f, 0.89f, 0.98f, 0.99f, 0.86f, 0.61f },
{ 0.21f, 0.55f, 0.71f, 1.27f, 0.91f, 1.55f, 1.23f, 0.94f, 0.64f, 0.88f, 0.88f, 1.27f, 0.84f, 1.00f, 1.07f, 1.18f, 0.68f, 1.41f, 1.27f, 1.35f, 0.92f, 1.51f, 1.14f, 1.17f, 0.73f, 0.87f, 0.94f, 0.96f, 0.63f, 1.04f, 0.50f, 0.59f, 0.21f }
};
}