package com.akjava.gwt.threecanvastest.client.birds; import com.akjava.gwt.lib.client.LogUtils; import com.akjava.gwt.three.client.js.THREE; import com.akjava.gwt.three.client.js.math.Vector3; import com.google.gwt.core.client.GWT; import com.google.gwt.core.client.JsArray; public class Boid { Vector3 position,velocity; Vector3 _goal; int _width = 500, _height = 500, _depth = 200, _neighborhoodRadius = 100; int _maxSpeed = 4;double _maxSteerForce = 0.1;boolean _avoidWalls = false; Vector3 vector = THREE.Vector3(); Vector3 _acceleration = THREE.Vector3(); public Vector3 getPosition() { return position; } public void setPosition(Vector3 position) { this.position = position; } public Vector3 getVelocity() { return velocity; } public void setVelocity(Vector3 velocity) { this.velocity = velocity; } public Boid(){ this.setPosition( THREE.Vector3()); this.setVelocity( THREE.Vector3()); } public void setGoal(Vector3 target ) { _goal = target; } public void setAvoidWalls(boolean value ) { _avoidWalls = value; } public void setWorldSize(int width, int height,int depth ) { _width = width; _height = height; _depth = depth; } public void run(Boid[] boids ) { if ( _avoidWalls ) { vector.set( - _width, this.position.getY(), this.position.getZ() ); vector = this.avoid( vector ); vector.multiplyScalar( 5 ); _acceleration.addSelf( vector ); vector.set( _width, this.position.getY(), this.position.getZ() ); vector = this.avoid( vector ); vector.multiplyScalar( 5 ); _acceleration.addSelf( vector ); vector.set( this.position.getX(), - _height, this.position.getZ() ); vector = this.avoid( vector ); vector.multiplyScalar( 5 ); _acceleration.addSelf( vector ); vector.set( this.position.getX(), _height, this.position.getZ() ); vector = this.avoid( vector ); vector.multiplyScalar( 5 ); _acceleration.addSelf( vector ); vector.set( this.position.getX(), this.position.getY(), - _depth ); vector = this.avoid( vector ); vector.multiplyScalar( 5 ); _acceleration.addSelf( vector ); vector.set( this.position.getX(), this.position.getY(), _depth ); vector = this.avoid( vector ); vector.multiplyScalar( 5 ); _acceleration.addSelf( vector ); }/* else { this.checkBounds(); } */ if ( Math.random() > 0.5 ) { this.flock( boids ); } this.move(); } public void flock(Boid[] boids){ if ( _goal !=null ) { _acceleration.addSelf( this.reach( _goal, 0.005 ) ); } _acceleration.addSelf( this.alignment( boids ) ); _acceleration.addSelf( this.cohesion( boids ) ); _acceleration.addSelf( this.separation( boids ) ); } public void move(){ this.velocity.addSelf( _acceleration ); double l = this.velocity.length(); if ( l > _maxSpeed ) { this.velocity.divideScalar( l / _maxSpeed ); } this.position.addSelf( this.velocity ); _acceleration.set( 0, 0, 0 ); } public void checkBounds(){ if ( this.position.getX() > _width ) this.position.setX(- _width) ; if ( this.position.getX() < - _width ) this.position.setX(_width); if ( this.position.getY() > _height ) this.position.setY(- _height) ; if ( this.position.getY() < - _height ) this.position.setY(_height); if ( this.position.getZ() > _depth ) this.position.setZ( - _depth); if ( this.position.getZ() < - _depth ) this.position.setZ( _depth); } public Vector3 avoid(Vector3 target ) { Vector3 steer = THREE.Vector3(); steer.copy( this.position ); steer.subSelf( target ); steer.multiplyScalar( 1 / this.position.distanceToSquared( target ) ); return steer; } public void repulse(Vector3 target){ double distance = this.position.distanceTo( target ); if ( distance < 150 ) { Vector3 steer = THREE.Vector3(); steer.sub( this.position, target ); steer.multiplyScalar( 0.5 / distance ); _acceleration.addSelf( steer ); } } public Vector3 reach(Vector3 target,double amount){ Vector3 steer = THREE.Vector3(); steer.sub( target, this.position ); steer.multiplyScalar( amount ); return steer; } public Vector3 alignment(Boid[] boids){ Boid boid; Vector3 velSum = THREE.Vector3(); int count = 0; for ( int i = 0, il = boids.length; i < il; i++ ) { if ( Math.random() > 0.6 ) continue; boid = boids[ i ]; double distance = boid.position.distanceTo( this.position ); if ( distance > 0 && distance <= _neighborhoodRadius ) { velSum.addSelf( boid.velocity ); count++; } } if ( count > 0 ) { velSum.divideScalar( count ); double l = velSum.length(); if ( l > _maxSteerForce ) { velSum.divideScalar( l / _maxSteerForce ); } } return velSum; } public Vector3 cohesion(Boid[] boids){ Boid boid; double distance; Vector3 posSum = THREE.Vector3(); Vector3 steer = THREE.Vector3(); int count = 0; for ( int i = 0, il = boids.length; i < il; i ++ ) { if ( Math.random() > 0.6 ) continue; boid = boids[ i ]; distance = boid.position.distanceTo( this.position ); if ( distance > 0 && distance <= _neighborhoodRadius ) { posSum.addSelf( boid.position ); count++; } } if ( count > 0 ) { posSum.divideScalar( count ); } steer.sub( posSum, this.position ); double l = steer.length(); if ( l > _maxSteerForce ) { steer.divideScalar( l / _maxSteerForce ); } return steer; } public Vector3 separation(Boid[] boids){ Boid boid; double distance; Vector3 posSum = THREE.Vector3(); Vector3 repulse = THREE.Vector3(); for ( int i = 0, il = boids.length; i < il; i ++ ) { if ( Math.random() > 0.6 ) continue; boid = boids[ i ]; distance = boid.position.distanceTo( this.position ); if ( distance > 0 && distance <= _neighborhoodRadius ) { repulse.sub( this.position, boid.position ); repulse.normalize(); repulse.divideScalar( distance ); posSum.addSelf( repulse ); } } return posSum; } }