diff --git a/Module/BirdsModule/Birds.cs b/Module/BirdsModule/Birds.cs index 2b7916c..2b7f0b8 100644 --- a/Module/BirdsModule/Birds.cs +++ b/Module/BirdsModule/Birds.cs @@ -31,343 +31,343 @@ using OpenMetaverse; namespace Flocking { - public class Bird - { - private static readonly ILog m_log = LogManager.GetLogger (System.Reflection.MethodBase.GetCurrentMethod ().DeclaringType); - private string m_id; - - private Vector3 m_loc; - private Vector3 m_vel; - private Vector3 m_acc; - private Random m_rndnums = new Random (Environment.TickCount); - - private FlockingModel m_model; - private FlowMap m_flowMap; + public class Bird + { + private static readonly ILog m_log = LogManager.GetLogger (System.Reflection.MethodBase.GetCurrentMethod ().DeclaringType); + private string m_id; + + private Vector3 m_loc; + private Vector3 m_vel; + private Vector3 m_acc; + private Random m_rndnums = new Random (Environment.TickCount); + + private FlockingModel m_model; + private FlowMap m_flowMap; private int m_regionX; private int m_regionY; private int m_regionZ; private float m_regionBorder; - - /// - /// Initializes a new instance of the class. - /// - /// - /// L. the initial position of this bird - /// - /// - /// Ms. max speed this bird can attain - /// - /// - /// Mf. max force / acceleration this bird can extert - /// - public Bird (string id, FlockingModel model, FlowMap flowMap) - { - m_id = id; - m_acc = Vector3.Zero; - m_vel = new Vector3 (m_rndnums.Next (-1, 1), m_rndnums.Next (-1, 1), m_rndnums.Next (-1, 1)); - m_model = model; - m_flowMap = flowMap; + + /// + /// Initializes a new instance of the class. + /// + /// + /// L. the initial position of this bird + /// + /// + /// Ms. max speed this bird can attain + /// + /// + /// Mf. max force / acceleration this bird can extert + /// + public Bird (string id, FlockingModel model, FlowMap flowMap) + { + m_id = id; + m_acc = Vector3.Zero; + m_vel = new Vector3 (m_rndnums.Next (-1, 1), m_rndnums.Next (-1, 1), m_rndnums.Next (-1, 1)); + m_model = model; + m_flowMap = flowMap; m_regionX = m_flowMap.LengthX; m_regionY = m_flowMap.LengthY; m_regionZ = m_flowMap.LengthZ; m_regionBorder = m_flowMap.Border; - } - - public Vector3 Location { - get { return m_loc;} - set { m_loc = value; } - } + } - public Vector3 Velocity { - get { return m_vel;} - } - - public String Id { - get {return m_id;} - } - - /// - /// Moves our bird in the scene relative to the rest of the flock. - /// - /// - /// Birds. all the other chaps in the scene - /// - public void MoveInSceneRelativeToFlock (List birds) - { - // we would like to stay with our mates - Flock (birds); + public Vector3 Location { + get { return m_loc;} + set { m_loc = value; } + } - // our first priority is to not hurt ourselves - AvoidObstacles (); - - // then we want to avoid any threats - // this not implemented yet - - - // ok so we worked our where we want to go, so ... - UpdatePositionInScene (); - - } + public Vector3 Velocity { + get { return m_vel;} + } - /// - /// Move within our flock - /// - /// We accumulate a new acceleration each time based on three rules - /// these are: - /// our separation from our closest neighbours, - /// our desire to keep travelling within the local flock, - /// our desire to move towards the flock centre - /// - /// - void Flock (List birds) - { - - // calc the force vectors on this bird - Vector3 sep = Separate (birds); // Separation - Vector3 ali = Align (birds); // Alignment - Vector3 coh = Cohesion (birds); // Cohesion - - // Arbitrarily weight these forces - //TODO: expose these consts - sep *= 1.5f; //.mult(1.5); - //ali.mult(1.0); - ali *= 1.0f; - //coh.mult(1.0); - coh *= 1.0f; - - // Add the force vectors to the current acceleration of the bird - //acc.add(sep); - m_acc += sep; - //acc.add(ali); - m_acc += ali; - //acc.add(coh); - m_acc += coh; - } - + public String Id { + get {return m_id;} + } - /// - /// Method to update our location within the scene. - /// update our location in the world based on our - /// current location, velocity and acceleration - /// taking into account our max speed - /// - /// - void UpdatePositionInScene () - { - // Update velocity - //vel.add(acc); - m_vel += m_acc; - // Limit speed - //m_vel.limit(maxspeed); - m_vel = BirdsUtil.Limit (m_vel, m_model.MaxSpeed); - m_loc += m_vel; - // Reset accelertion to 0 each cycle - m_acc *= 0.0f; - } - - /// - /// Seek the specified target. Move into that flock - /// Accelerate us towards where we want to go - /// - /// - /// Target. the position within the flock we would like to achieve - /// - void Seek (Vector3 target) - { - m_acc += Steer (target, false); - } - - /// - /// Arrive the specified target. Slow us down, as we are almost there - /// - /// - /// Target. the flock we would like to think ourselves part of - /// - void arrive (Vector3 target) - { - m_acc += Steer (target, true); - } + /// + /// Moves our bird in the scene relative to the rest of the flock. + /// + /// + /// Birds. all the other chaps in the scene + /// + public void MoveInSceneRelativeToFlock (List birds) + { + // we would like to stay with our mates + Flock (birds); - /// A method that calculates a steering vector towards a target - /// Takes a second argument, if true, it slows down as it approaches the target - Vector3 Steer (Vector3 target, bool slowdown) - { - Vector3 steer; // The steering vector - Vector3 desired = Vector3.Subtract(target, m_loc); // A vector pointing from the location to the target - float d = desired.Length (); // Distance from the target is the magnitude of the vector - // If the distance is greater than 0, calc steering (otherwise return zero vector) - if (d > 0) { - // Normalize desired - desired.Normalize (); - // Two options for desired vector magnitude (1 -- based on distance, 2 -- maxspeed) - if ((slowdown) && (d < 100.0f)) { - desired *= (m_model.MaxSpeed * (d / 100.0f)); // This damping is somewhat arbitrary - } else { - desired *= m_model.MaxSpeed; - } - // Steering = Desired minus Velocity - //steer = target.sub(desired,m_vel); - steer = Vector3.Subtract (desired, m_vel); - //steer.limit(maxforce); // Limit to maximum steering force - steer = BirdsUtil.Limit (steer, m_model.MaxForce); - } else { - steer = Vector3.Zero; - } - return steer; - } + // our first priority is to not hurt ourselves + AvoidObstacles (); - - /// - /// Borders this instance. - /// if we get too close wrap us around - /// CHANGE THIS to navigate away from whatever it is we are too close to - /// - void AvoidObstacles () - { - //look tolerance metres ahead - Vector3 normVel = Vector3.Normalize(m_vel); - Vector3 inFront = m_loc + Vector3.Multiply(normVel, m_model.Tolerance); - if( m_flowMap.WouldHitObstacle( m_loc, inFront ) ) { - AdjustVelocityToAvoidObstacles (); - - } - } + // then we want to avoid any threats + // this not implemented yet - void AdjustVelocityToAvoidObstacles () - { - for( int i = 1; i < 5; i++ ) { - Vector3 normVel = Vector3.Normalize(m_vel); - int xDelta = m_rndnums.Next (-i, i); - int yDelta = m_rndnums.Next (-i, i); - int zDelta = m_rndnums.Next (-i, i); - normVel.X += xDelta; - normVel.Y += yDelta; - normVel.Z += zDelta; - Vector3 inFront = m_loc + Vector3.Multiply(normVel, m_model.Tolerance); - if( !m_flowMap.WouldHitObstacle( m_loc, inFront ) ) { - m_vel.X += xDelta; - m_vel.Y += yDelta; - m_vel.Z += zDelta; - //m_log.Info("avoided"); - return; - } - } - //m_log.Info("didn't avoid"); - // try increaing our acceleration - // or try decreasing our acceleration - // or turn around - coz where we came from was OK - if (m_loc.X < m_regionBorder || m_loc.X > m_regionX - m_regionBorder) - m_vel.X = -m_vel.X; + + // ok so we worked our where we want to go, so ... + UpdatePositionInScene (); + + } + + /// + /// Move within our flock + /// + /// We accumulate a new acceleration each time based on three rules + /// these are: + /// our separation from our closest neighbours, + /// our desire to keep travelling within the local flock, + /// our desire to move towards the flock centre + /// + /// + void Flock (List birds) + { + + // calc the force vectors on this bird + Vector3 sep = Separate (birds); // Separation + Vector3 ali = Align (birds); // Alignment + Vector3 coh = Cohesion (birds); // Cohesion + + // Arbitrarily weight these forces + //TODO: expose these consts + sep *= 1.5f; //.mult(1.5); + //ali.mult(1.0); + ali *= 1.0f; + //coh.mult(1.0); + coh *= 1.0f; + + // Add the force vectors to the current acceleration of the bird + //acc.add(sep); + m_acc += sep; + //acc.add(ali); + m_acc += ali; + //acc.add(coh); + m_acc += coh; + } + + + /// + /// Method to update our location within the scene. + /// update our location in the world based on our + /// current location, velocity and acceleration + /// taking into account our max speed + /// + /// + void UpdatePositionInScene () + { + // Update velocity + //vel.add(acc); + m_vel += m_acc; + // Limit speed + //m_vel.limit(maxspeed); + m_vel = BirdsUtil.Limit (m_vel, m_model.MaxSpeed); + m_loc += m_vel; + // Reset accelertion to 0 each cycle + m_acc *= 0.0f; + } + + /// + /// Seek the specified target. Move into that flock + /// Accelerate us towards where we want to go + /// + /// + /// Target. the position within the flock we would like to achieve + /// + void Seek (Vector3 target) + { + m_acc += Steer (target, false); + } + + /// + /// Arrive the specified target. Slow us down, as we are almost there + /// + /// + /// Target. the flock we would like to think ourselves part of + /// + void arrive (Vector3 target) + { + m_acc += Steer (target, true); + } + + /// A method that calculates a steering vector towards a target + /// Takes a second argument, if true, it slows down as it approaches the target + Vector3 Steer (Vector3 target, bool slowdown) + { + Vector3 steer; // The steering vector + Vector3 desired = Vector3.Subtract(target, m_loc); // A vector pointing from the location to the target + float d = desired.Length (); // Distance from the target is the magnitude of the vector + // If the distance is greater than 0, calc steering (otherwise return zero vector) + if (d > 0) { + // Normalize desired + desired.Normalize (); + // Two options for desired vector magnitude (1 -- based on distance, 2 -- maxspeed) + if ((slowdown) && (d < 100.0f)) { + desired *= (m_model.MaxSpeed * (d / 100.0f)); // This damping is somewhat arbitrary + } else { + desired *= m_model.MaxSpeed; + } + // Steering = Desired minus Velocity + //steer = target.sub(desired,m_vel); + steer = Vector3.Subtract (desired, m_vel); + //steer.limit(maxforce); // Limit to maximum steering force + steer = BirdsUtil.Limit (steer, m_model.MaxForce); + } else { + steer = Vector3.Zero; + } + return steer; + } + + + /// + /// Borders this instance. + /// if we get too close wrap us around + /// CHANGE THIS to navigate away from whatever it is we are too close to + /// + void AvoidObstacles () + { + //look tolerance metres ahead + Vector3 normVel = Vector3.Normalize(m_vel); + Vector3 inFront = m_loc + Vector3.Multiply(normVel, m_model.Tolerance); + if( m_flowMap.WouldHitObstacle( m_loc, inFront ) ) { + AdjustVelocityToAvoidObstacles (); + + } + } + + void AdjustVelocityToAvoidObstacles () + { + for( int i = 1; i < 5; i++ ) { + Vector3 normVel = Vector3.Normalize(m_vel); + int xDelta = m_rndnums.Next (-i, i); + int yDelta = m_rndnums.Next (-i, i); + int zDelta = m_rndnums.Next (-i, i); + normVel.X += xDelta; + normVel.Y += yDelta; + normVel.Z += zDelta; + Vector3 inFront = m_loc + Vector3.Multiply(normVel, m_model.Tolerance); + if( !m_flowMap.WouldHitObstacle( m_loc, inFront ) ) { + m_vel.X += xDelta; + m_vel.Y += yDelta; + m_vel.Z += zDelta; + //m_log.Info("avoided"); + return; + } + } + //m_log.Info("didn't avoid"); + // try increaing our acceleration + // or try decreasing our acceleration + // or turn around - coz where we came from was OK + if (m_loc.X < m_regionBorder || m_loc.X > m_regionX - m_regionBorder) + m_vel.X = -m_vel.X; if (m_loc.Y < m_regionBorder || m_loc.Y > m_regionY - m_regionBorder) - m_vel.Y = -m_vel.Y; - if (m_loc.Z < 21 || m_loc.Z > m_regionZ ) - m_vel.Z = -m_vel.Z; - } - - /// - /// Separate ourselves from the specified birds. - /// keeps us a respectable distance from our closest neighbours whilst still - /// being part of our local flock - /// - /// - /// Birds. all the birds in the scene - /// - Vector3 Separate (List birds) - { - Vector3 steer = new Vector3 (0, 0, 0); - int count = 0; - // For every bird in the system, check if it's too close - foreach (Bird other in birds) { - float d = Vector3.Distance (m_loc, other.Location); - // If the distance is greater than 0 and less than an arbitrary amount (0 when you are yourself) - if ((d > 0) && (d < m_model.DesiredSeparation)) { - // Calculate vector pointing away from neighbor - Vector3 diff = Vector3.Subtract (m_loc, other.Location); - diff.Normalize (); - diff = Vector3.Divide (diff, d); - steer = Vector3.Add (steer, diff); - count++; // Keep track of how many - } - } - // Average -- divide by how many - if (count > 0) { - steer /= (float)count; - } + m_vel.Y = -m_vel.Y; + if (m_loc.Z < 21 || m_loc.Z > m_regionZ ) + m_vel.Z = -m_vel.Z; + } - // As long as the vector is greater than 0 - if (steer.Length () > 0) { - // Implement Reynolds: Steering = Desired - Velocity - steer.Normalize (); - steer *= m_model.MaxSpeed; - steer -= m_vel; - //steer.limit(maxforce); - steer = BirdsUtil.Limit (steer, m_model.MaxForce); - } - return steer; - } + /// + /// Separate ourselves from the specified birds. + /// keeps us a respectable distance from our closest neighbours whilst still + /// being part of our local flock + /// + /// + /// Birds. all the birds in the scene + /// + Vector3 Separate (List birds) + { + Vector3 steer = new Vector3 (0, 0, 0); + int count = 0; + // For every bird in the system, check if it's too close + foreach (Bird other in birds) { + float d = Vector3.Distance (m_loc, other.Location); + // If the distance is greater than 0 and less than an arbitrary amount (0 when you are yourself) + if ((d > 0) && (d < m_model.DesiredSeparation)) { + // Calculate vector pointing away from neighbor + Vector3 diff = Vector3.Subtract (m_loc, other.Location); + diff.Normalize (); + diff = Vector3.Divide (diff, d); + steer = Vector3.Add (steer, diff); + count++; // Keep track of how many + } + } + // Average -- divide by how many + if (count > 0) { + steer /= (float)count; + } - /// - /// Align our bird within the flock. - /// For every nearby bird in the system, calculate the average velocity - /// and move us towards that - this keeps us moving with the flock. - /// - /// - /// Birds. all the birds in the scene - we only really care about those in the neighbourdist - /// - Vector3 Align (List birds) - { - Vector3 steer = new Vector3 (0, 0, 0); - int count = 0; - foreach (Bird other in birds) { - float d = Vector3.Distance (m_loc, other.Location); - if ((d > 0) && (d < m_model.NeighbourDistance)) { - steer += other.Velocity; - count++; - } - } - if (count > 0) { - steer /= (float)count; - } + // As long as the vector is greater than 0 + if (steer.Length () > 0) { + // Implement Reynolds: Steering = Desired - Velocity + steer.Normalize (); + steer *= m_model.MaxSpeed; + steer -= m_vel; + //steer.limit(maxforce); + steer = BirdsUtil.Limit (steer, m_model.MaxForce); + } + return steer; + } - // As long as the vector is greater than 0 - if (steer.Length () > 0) { - // Implement Reynolds: Steering = Desired - Velocity - steer.Normalize (); - steer *= m_model.MaxSpeed; - steer -= m_vel; - //steer.limit(maxforce); - steer = BirdsUtil.Limit (steer, m_model.MaxForce); - - } - return steer; - } + /// + /// Align our bird within the flock. + /// For every nearby bird in the system, calculate the average velocity + /// and move us towards that - this keeps us moving with the flock. + /// + /// + /// Birds. all the birds in the scene - we only really care about those in the neighbourdist + /// + Vector3 Align (List birds) + { + Vector3 steer = new Vector3 (0, 0, 0); + int count = 0; + foreach (Bird other in birds) { + float d = Vector3.Distance (m_loc, other.Location); + if ((d > 0) && (d < m_model.NeighbourDistance)) { + steer += other.Velocity; + count++; + } + } + if (count > 0) { + steer /= (float)count; + } - /// - /// MAintain the cohesion of our local flock - /// For the average location (i.e. center) of all nearby birds, calculate our steering vector towards that location - /// - /// - /// Birds. the birds in the scene - /// - Vector3 Cohesion (List birds) - { - - Vector3 sum = Vector3.Zero; // Start with empty vector to accumulate all locations - int count = 0; - - foreach (Bird other in birds) { - float d = Vector3.Distance (m_loc, other.Location); - if ((d > 0) && (d < m_model.NeighbourDistance)) { - sum += other.Location; // Add location - count++; - } - } - if (count > 0) { - sum /= (float)count; - return Steer (sum, false); // Steer towards the location - } - return sum; - } - } + // As long as the vector is greater than 0 + if (steer.Length () > 0) { + // Implement Reynolds: Steering = Desired - Velocity + steer.Normalize (); + steer *= m_model.MaxSpeed; + steer -= m_vel; + //steer.limit(maxforce); + steer = BirdsUtil.Limit (steer, m_model.MaxForce); + + } + return steer; + } + + /// + /// MAintain the cohesion of our local flock + /// For the average location (i.e. center) of all nearby birds, calculate our steering vector towards that location + /// + /// + /// Birds. the birds in the scene + /// + Vector3 Cohesion (List birds) + { + + Vector3 sum = Vector3.Zero; // Start with empty vector to accumulate all locations + int count = 0; + + foreach (Bird other in birds) { + float d = Vector3.Distance (m_loc, other.Location); + if ((d > 0) && (d < m_model.NeighbourDistance)) { + sum += other.Location; // Add location + count++; + } + } + if (count > 0) { + sum /= (float)count; + return Steer (sum, false); // Steer towards the location + } + return sum; + } + } } diff --git a/Module/BirdsModule/BirdsUtil.cs b/Module/BirdsModule/BirdsUtil.cs index 9b32ee2..9e55b1a 100644 --- a/Module/BirdsModule/BirdsUtil.cs +++ b/Module/BirdsModule/BirdsUtil.cs @@ -30,23 +30,23 @@ using OpenMetaverse; namespace Flocking { - public class BirdsUtil - { - public static Vector3 Limit (Vector3 initial, float maxLen) - { - float currLen = initial.Length (); - float ratio = 1.0f; - - if (currLen > maxLen) { - ratio = currLen / maxLen; - } - - return initial /= ratio; - - } - - + public class BirdsUtil + { + public static Vector3 Limit (Vector3 initial, float maxLen) + { + float currLen = initial.Length (); + float ratio = 1.0f; - } + if (currLen > maxLen) { + ratio = currLen / maxLen; + } + + return initial /= ratio; + + } + + + + } } diff --git a/Module/BirdsModule/FlockingModel.cs b/Module/BirdsModule/FlockingModel.cs index f13dff1..066348c 100644 --- a/Module/BirdsModule/FlockingModel.cs +++ b/Module/BirdsModule/FlockingModel.cs @@ -31,105 +31,105 @@ using OpenMetaverse; namespace Flocking { - public class FlockingModel - { + public class FlockingModel + { private List m_flock = new List(); - private FlowMap m_flowMap; - private float m_maxSpeed; - private float m_maxForce; - private float m_neighbourDistance; - private float m_desiredSeparation; - private float m_tolerance; + private FlowMap m_flowMap; + private float m_maxSpeed; + private float m_maxForce; + private float m_neighbourDistance; + private float m_desiredSeparation; + private float m_tolerance; private float m_border; private string m_name; - - private Random m_rnd = new Random(Environment.TickCount); - - public int Size { - get {return m_flock.Count;} - set { - //if( value < m_flock.Count ) { - // m_flock.RemoveRange( 0, m_flock.Count - value ); - //} else + + private Random m_rnd = new Random(Environment.TickCount); + + public int Size { + get {return m_flock.Count;} + set { + //if( value < m_flock.Count ) { + // m_flock.RemoveRange( 0, m_flock.Count - value ); + //} else m_flock = new List(); while( value > m_flock.Count ) { - AddBird(m_name + m_flock.Count); - } - } - } - - public FlockingModel(string moduleName, float maxSpeed, float maxForce, float neighbourDistance, float desiredSeparation, float tolerance, float border) { + AddBird(m_name + m_flock.Count); + } + } + } + + public FlockingModel(string moduleName, float maxSpeed, float maxForce, float neighbourDistance, float desiredSeparation, float tolerance, float border) { m_name = moduleName; m_maxSpeed = maxSpeed; - m_maxForce = maxForce; - m_neighbourDistance = neighbourDistance; - m_desiredSeparation = desiredSeparation; - m_tolerance = tolerance; + m_maxForce = maxForce; + m_neighbourDistance = neighbourDistance; + m_desiredSeparation = desiredSeparation; + m_tolerance = tolerance; m_border = border; - } + } - void AddBird (string name) - { - Bird Bird = new Bird (name, this, m_flowMap); - - // find an initial random location for this Bird - // somewhere not within an obstacle - int xInit = m_rnd.Next(m_flowMap.LengthX); - int yInit = m_rnd.Next(m_flowMap.LengthY); - int zInit = m_rnd.Next(m_flowMap.LengthZ); - - while( m_flowMap.IsWithinObstacle( xInit, yInit, zInit ) ){ - xInit = m_rnd.Next(m_flowMap.LengthX); - yInit = m_rnd.Next(m_flowMap.LengthY); - zInit = m_rnd.Next(m_flowMap.LengthZ); - } - - Bird.Location = new Vector3 (Convert.ToSingle(xInit), Convert.ToSingle(yInit), Convert.ToSingle(zInit)); - m_flock.Add (Bird); - } - - public float MaxSpeed { - get {return m_maxSpeed;} + void AddBird (string name) + { + Bird Bird = new Bird (name, this, m_flowMap); + + // find an initial random location for this Bird + // somewhere not within an obstacle + int xInit = m_rnd.Next(m_flowMap.LengthX); + int yInit = m_rnd.Next(m_flowMap.LengthY); + int zInit = m_rnd.Next(m_flowMap.LengthZ); + + while( m_flowMap.IsWithinObstacle( xInit, yInit, zInit ) ){ + xInit = m_rnd.Next(m_flowMap.LengthX); + yInit = m_rnd.Next(m_flowMap.LengthY); + zInit = m_rnd.Next(m_flowMap.LengthZ); + } + + Bird.Location = new Vector3 (Convert.ToSingle(xInit), Convert.ToSingle(yInit), Convert.ToSingle(zInit)); + m_flock.Add (Bird); + } + + public float MaxSpeed { + get {return m_maxSpeed;} set { m_maxSpeed = value; } - } - - public float MaxForce { - get {return m_maxForce;} + } + + public float MaxForce { + get {return m_maxForce;} set { m_maxForce = value; } - } + } - public float NeighbourDistance { - get {return m_neighbourDistance;} + public float NeighbourDistance { + get {return m_neighbourDistance;} set { m_neighbourDistance = value; } - } - - public float DesiredSeparation { - get {return m_desiredSeparation;} + } + + public float DesiredSeparation { + get {return m_desiredSeparation;} set { m_desiredSeparation = value; } - } - - public float Tolerance { - get {return m_tolerance;} + } + + public float Tolerance { + get {return m_tolerance;} set { m_tolerance = value; } - } - + } - public void Initialise (int num, FlowMap flowMap) - { - m_flowMap = flowMap; - for (int i = 0; i < num; i++) { - AddBird (m_name + i ); - } - } - public List UpdateFlockPos () - { - foreach (Bird b in m_flock) { - b.MoveInSceneRelativeToFlock(m_flock); // Passing the entire list of Birds to each Bird individually - } - - return m_flock; - } - } + public void Initialise (int num, FlowMap flowMap) + { + m_flowMap = flowMap; + for (int i = 0; i < num; i++) { + AddBird (m_name + i ); + } + } + + public List UpdateFlockPos () + { + foreach (Bird b in m_flock) { + b.MoveInSceneRelativeToFlock(m_flock); // Passing the entire list of Birds to each Bird individually + } + + return m_flock; + } + } } diff --git a/Module/BirdsModule/FlockingView.cs b/Module/BirdsModule/FlockingView.cs index 5dda6dd..8b22aec 100644 --- a/Module/BirdsModule/FlockingView.cs +++ b/Module/BirdsModule/FlockingView.cs @@ -34,34 +34,34 @@ using log4net; namespace Flocking { - public class FlockingView - { + public class FlockingView + { private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); private Scene m_scene; - private UUID m_owner; + private UUID m_owner; private String m_name; - private String m_birdPrim; - - private Dictionary m_sogMap = new Dictionary (); - - public FlockingView (String moduleName, Scene scene) - { - m_name = moduleName; - m_scene = scene; - } - - public void PostInitialize (UUID owner) - { - m_owner = owner; - } - - public String BirdPrim { - get { return m_birdPrim; } - set{ m_birdPrim = value;} - } + private String m_birdPrim; - public void Clear () - { + private Dictionary m_sogMap = new Dictionary (); + + public FlockingView (String moduleName, Scene scene) + { + m_name = moduleName; + m_scene = scene; + } + + public void PostInitialize (UUID owner) + { + m_owner = owner; + } + + public String BirdPrim { + get { return m_birdPrim; } + set{ m_birdPrim = value;} + } + + public void Clear () + { //trash everything we have foreach (string name in m_sogMap.Keys) { @@ -71,103 +71,103 @@ namespace Flocking } m_sogMap.Clear(); m_scene.ForceClientUpdate(); - } + } public void Render(List birds) - { - foreach (Bird bird in birds) { - DrawBird (bird); - } - } - - private void DrawBird (Bird bird) - { - SceneObjectPart existing = m_scene.GetSceneObjectPart (bird.Id); + { + foreach (Bird bird in birds) { + DrawBird (bird); + } + } + + private void DrawBird (Bird bird) + { + SceneObjectPart existing = m_scene.GetSceneObjectPart (bird.Id); - SceneObjectGroup sog; + SceneObjectGroup sog; SceneObjectPart rootPart; - if (existing == null) { + if (existing == null) { m_log.InfoFormat("[{0}]: Adding prim {1} in region {2}", m_name, bird.Id, m_scene.RegionInfo.RegionName); SceneObjectGroup group = findByName (m_birdPrim); - sog = CopyPrim (group, bird.Id); + sog = CopyPrim (group, bird.Id); rootPart = sog.RootPart; rootPart.AddFlag(PrimFlags.Temporary); rootPart.AddFlag(PrimFlags.Phantom); //set prim to phantom //sog.UpdatePrimFlags(rootPart.LocalId, false, false, true, false); - m_sogMap [bird.Id] = sog; - m_scene.AddNewSceneObject (sog, false); + m_sogMap [bird.Id] = sog; + m_scene.AddNewSceneObject (sog, false); // Fire script on_rez sog.CreateScriptInstances(0, true, m_scene.DefaultScriptEngine, 1); rootPart.ParentGroup.ResumeScripts(); rootPart.ScheduleFullUpdate(); sog.DetachFromBackup(); - } else { - sog = existing.ParentGroup; + } else { + sog = existing.ParentGroup; m_sogMap[bird.Id] = sog; //rootPart = sog.RootPart; //set prim to phantom //sog.UpdatePrimFlags(rootPart.LocalId, false, false, true, false); - } - - Quaternion rotation = CalcRotationToEndpoint (sog, sog.AbsolutePosition, bird.Location); - sog.UpdateGroupRotationPR( bird.Location, rotation); - } - - private static Quaternion CalcRotationToEndpoint (SceneObjectGroup copy, Vector3 sv, Vector3 ev) - { - //llSetRot(llRotBetween(<1,0,0>,llVecNorm(targetPosition - llGetPos()))); - // bird wil fly x forwards and Z up - - Vector3 currDirVec = Vector3.UnitX; - Vector3 desiredDirVec = Vector3.Subtract (ev, sv); - desiredDirVec.Normalize (); + } - Quaternion rot = Vector3.RotationBetween (currDirVec, desiredDirVec); - return rot; - } - - private SceneObjectGroup CopyPrim (SceneObjectGroup prim, string name) - { - SceneObjectGroup copy = prim.Copy (true); - copy.Name = name; - copy.DetachFromBackup (); - return copy; - } - - private SceneObjectGroup findByName (string name) - { - SceneObjectGroup retVal = null; - foreach (EntityBase e in m_scene.GetEntities()) { - if (e.Name == name) { - retVal = (SceneObjectGroup)e; - break; - } - } - // can't find it so make a default one - if (retVal == null) { + Quaternion rotation = CalcRotationToEndpoint (sog, sog.AbsolutePosition, bird.Location); + sog.UpdateGroupRotationPR( bird.Location, rotation); + } + + private static Quaternion CalcRotationToEndpoint (SceneObjectGroup copy, Vector3 sv, Vector3 ev) + { + //llSetRot(llRotBetween(<1,0,0>,llVecNorm(targetPosition - llGetPos()))); + // bird wil fly x forwards and Z up + + Vector3 currDirVec = Vector3.UnitX; + Vector3 desiredDirVec = Vector3.Subtract (ev, sv); + desiredDirVec.Normalize (); + + Quaternion rot = Vector3.RotationBetween (currDirVec, desiredDirVec); + return rot; + } + + private SceneObjectGroup CopyPrim (SceneObjectGroup prim, string name) + { + SceneObjectGroup copy = prim.Copy (true); + copy.Name = name; + copy.DetachFromBackup (); + return copy; + } + + private SceneObjectGroup findByName (string name) + { + SceneObjectGroup retVal = null; + foreach (EntityBase e in m_scene.GetEntities()) { + if (e.Name == name) { + retVal = (SceneObjectGroup)e; + break; + } + } + // can't find it so make a default one + if (retVal == null) { m_log.InfoFormat("[{0}]: Prim named {1} was not found in region {2}. Making default wooden sphere.", m_name, name, m_scene.RegionInfo.RegionName); - retVal = MakeDefaultPrim (name); - } + retVal = MakeDefaultPrim (name); + } - return retVal; - } + return retVal; + } - private SceneObjectGroup MakeDefaultPrim (string name) - { - PrimitiveBaseShape shape = PrimitiveBaseShape.CreateSphere (); - shape.Scale = new Vector3 (0.5f, 0.5f, 0.5f); + private SceneObjectGroup MakeDefaultPrim (string name) + { + PrimitiveBaseShape shape = PrimitiveBaseShape.CreateSphere (); + shape.Scale = new Vector3 (0.5f, 0.5f, 0.5f); SceneObjectGroup prim = new SceneObjectGroup(m_owner, new Vector3((float)m_scene.RegionInfo.RegionSizeX / 2, (float)m_scene.RegionInfo.RegionSizeY / 2, 25f), shape); - prim.Name = name; - prim.DetachFromBackup (); - m_scene.AddNewSceneObject (prim, false); + prim.Name = name; + prim.DetachFromBackup (); + m_scene.AddNewSceneObject (prim, false); - return prim; - } + return prim; + } - } + } } diff --git a/Module/BirdsModule/FlowMap.cs b/Module/BirdsModule/FlowMap.cs index 464828a..148e36b 100644 --- a/Module/BirdsModule/FlowMap.cs +++ b/Module/BirdsModule/FlowMap.cs @@ -32,170 +32,170 @@ using OpenSim.Region.Framework.Scenes; namespace Flocking { - public class FlowMap - { - private Scene m_scene; + public class FlowMap + { + private Scene m_scene; private float[, ,] m_flowMap; private uint regionX; private uint regionY; private uint regionZ; private float regionBorder; - - public FlowMap (Scene scene, int maxHeight, float borderSize) - { - m_scene = scene; + + public FlowMap (Scene scene, int maxHeight, float borderSize) + { + m_scene = scene; regionX = m_scene.RegionInfo.RegionSizeX; regionY = m_scene.RegionInfo.RegionSizeY; regionZ = (uint)maxHeight; regionBorder = borderSize; m_flowMap = new float[regionX, regionY, regionZ]; - } - - public int LengthX { - get {return (int)regionX;} - } - public int LengthY { - get {return (int)regionY;} - } - public int LengthZ { - get {return (int)regionZ;} - } + } + + public int LengthX { + get {return (int)regionX;} + } + public int LengthY { + get {return (int)regionY;} + } + public int LengthZ { + get {return (int)regionZ;} + } public int Border { get {return (int)regionBorder;} } - - public void Initialise() { - //fill in the boundaries - for( int x = 0; x < regionX; x++ ) { - for( int y = 0; y < regionY; y++ ) { - m_flowMap[x,y,0] = 100f; - m_flowMap[x,y, regionZ-1] = 100f; - } - } - for( int x = 0; x < regionX; x++ ) { - for( int z = 0; z < regionZ; z++ ) { - m_flowMap[x,0,z] = 100f; - m_flowMap[x,regionY-1,z] = 100f; - } - } - for( int y = 0; y < regionY; y++ ) { - for( int z = 0; z < regionZ; z++ ) { - m_flowMap[0,y,z] = 100f; - m_flowMap[regionX-1,y,z] = 100f; - } - } - - //fill in the terrain - for( int x = 0; x < regionX; x++ ) { - for( int y = 0; y < regionY; y++ ) { - int zMax = Convert.ToInt32(m_scene.GetGroundHeight( x, y )); - for( int z = 1; z < zMax; z++ ) { - m_flowMap[x,y,z] = 100f; - } - } - } - - // fill in the things - foreach( EntityBase entity in m_scene.GetEntities() ) { - if( entity is SceneObjectGroup ) { - SceneObjectGroup sog = (SceneObjectGroup)entity; - - //todo: ignore phantom - float fmaxX, fminX, fmaxY, fminY, fmaxZ, fminZ; - int maxX, minX, maxY, minY, maxZ, minZ; - sog.GetAxisAlignedBoundingBoxRaw( out fminX, out fmaxX, out fminY, out fmaxY, out fminZ, out fmaxZ ); - - minX = Convert.ToInt32(fminX); - maxX = Convert.ToInt32(fmaxX); - minY = Convert.ToInt32(fminY); - maxY = Convert.ToInt32(fmaxX); - minZ = Convert.ToInt32(fminZ); - maxZ = Convert.ToInt32(fmaxZ); - - for( int x = minX; x < maxX; x++ ) { - for( int y = minY; y < maxY; y++ ) { - for( int z = minZ; z < maxZ; z++ ) { - m_flowMap[x,y,z] = 100f; - } - } - } - } - } - } - public bool WouldHitObstacle (Vector3 currPos, Vector3 targetPos) - { - bool retVal = false; - //fail fast - if( IsOutOfBounds(targetPos) ) { - retVal = true; - } else if( IsWithinObstacle(targetPos) ) { - retVal = true; - } else if( IntersectsObstacle (currPos, targetPos) ) { - retVal = true; - } - - return retVal; - } - - public bool IsOutOfBounds(Vector3 targetPos) { - bool retVal = false; - if( targetPos.X < regionBorder || - targetPos.X > regionX - regionBorder || + public void Initialise() { + //fill in the boundaries + for( int x = 0; x < regionX; x++ ) { + for( int y = 0; y < regionY; y++ ) { + m_flowMap[x,y,0] = 100f; + m_flowMap[x,y, regionZ-1] = 100f; + } + } + for( int x = 0; x < regionX; x++ ) { + for( int z = 0; z < regionZ; z++ ) { + m_flowMap[x,0,z] = 100f; + m_flowMap[x,regionY-1,z] = 100f; + } + } + for( int y = 0; y < regionY; y++ ) { + for( int z = 0; z < regionZ; z++ ) { + m_flowMap[0,y,z] = 100f; + m_flowMap[regionX-1,y,z] = 100f; + } + } + + //fill in the terrain + for( int x = 0; x < regionX; x++ ) { + for( int y = 0; y < regionY; y++ ) { + int zMax = Convert.ToInt32(m_scene.GetGroundHeight( x, y )); + for( int z = 1; z < zMax; z++ ) { + m_flowMap[x,y,z] = 100f; + } + } + } + + // fill in the things + foreach( EntityBase entity in m_scene.GetEntities() ) { + if( entity is SceneObjectGroup ) { + SceneObjectGroup sog = (SceneObjectGroup)entity; + + //todo: ignore phantom + float fmaxX, fminX, fmaxY, fminY, fmaxZ, fminZ; + int maxX, minX, maxY, minY, maxZ, minZ; + sog.GetAxisAlignedBoundingBoxRaw( out fminX, out fmaxX, out fminY, out fmaxY, out fminZ, out fmaxZ ); + + minX = Convert.ToInt32(fminX); + maxX = Convert.ToInt32(fmaxX); + minY = Convert.ToInt32(fminY); + maxY = Convert.ToInt32(fmaxX); + minZ = Convert.ToInt32(fminZ); + maxZ = Convert.ToInt32(fmaxZ); + + for( int x = minX; x < maxX; x++ ) { + for( int y = minY; y < maxY; y++ ) { + for( int z = minZ; z < maxZ; z++ ) { + m_flowMap[x,y,z] = 100f; + } + } + } + } + } + } + + public bool WouldHitObstacle (Vector3 currPos, Vector3 targetPos) + { + bool retVal = false; + //fail fast + if( IsOutOfBounds(targetPos) ) { + retVal = true; + } else if( IsWithinObstacle(targetPos) ) { + retVal = true; + } else if( IntersectsObstacle (currPos, targetPos) ) { + retVal = true; + } + + return retVal; + } + + public bool IsOutOfBounds(Vector3 targetPos) { + bool retVal = false; + if( targetPos.X < regionBorder || + targetPos.X > regionX - regionBorder || targetPos.Y < regionBorder || - targetPos.Y > regionY - regionBorder || - targetPos.Z < regionBorder || - targetPos.Z > regionZ - regionBorder ) { - - retVal = true; - } - - return retVal; - } + targetPos.Y > regionY - regionBorder || + targetPos.Z < regionBorder || + targetPos.Z > regionZ - regionBorder ) { - public bool IntersectsObstacle (Vector3 currPos, Vector3 targetPos) - { - bool retVal = false; - // Ray trace the Vector and fail as soon as we hit something - Vector3 direction = targetPos - currPos; - float length = direction.Length(); - // check every metre - for( float i = 1f; i < length; i += 1f ) { - Vector3 rayPos = currPos + ( direction * i ); - //give up if we go OOB on this ray - if( IsOutOfBounds( rayPos ) ){ - retVal = true; - break; - } - else if( IsWithinObstacle( rayPos ) ) { - retVal = true; - break; - } - } - - return retVal; - } - - public bool IsWithinObstacle( Vector3 targetPos ) { - return IsWithinObstacle(Convert.ToInt32(targetPos.X), Convert.ToInt32(targetPos.Y),Convert.ToInt32(targetPos.Z)); - } - - public bool IsWithinObstacle( int x, int y, int z ) { - bool retVal = false; + retVal = true; + } + + return retVal; + } + + public bool IntersectsObstacle (Vector3 currPos, Vector3 targetPos) + { + bool retVal = false; + // Ray trace the Vector and fail as soon as we hit something + Vector3 direction = targetPos - currPos; + float length = direction.Length(); + // check every metre + for( float i = 1f; i < length; i += 1f ) { + Vector3 rayPos = currPos + ( direction * i ); + //give up if we go OOB on this ray + if( IsOutOfBounds( rayPos ) ){ + retVal = true; + break; + } + else if( IsWithinObstacle( rayPos ) ) { + retVal = true; + break; + } + } + + return retVal; + } + + public bool IsWithinObstacle( Vector3 targetPos ) { + return IsWithinObstacle(Convert.ToInt32(targetPos.X), Convert.ToInt32(targetPos.Y),Convert.ToInt32(targetPos.Z)); + } + + public bool IsWithinObstacle( int x, int y, int z ) { + bool retVal = false; if (x >= LengthX || y >= LengthY || z >= LengthZ) { - retVal = true; + retVal = true; } else if (x < 0 || y < 0 || z < 0) { - retVal = true; - } else if (m_flowMap[x,y,z] > 50f) { - retVal = true; - } - return retVal; - } - } - - + retVal = true; + } else if (m_flowMap[x,y,z] > 50f) { + retVal = true; + } + return retVal; + } + } + + }