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/FlockingModule.cs b/Module/BirdsModule/FlockingModule.cs
index f093140..4148ae6 100644
--- a/Module/BirdsModule/FlockingModule.cs
+++ b/Module/BirdsModule/FlockingModule.cs
@@ -43,8 +43,10 @@ using OpenSim.Framework.Console;
using Mono.Addins;
using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list;
-[assembly: Addin("OpenSimBirds", "0.2")]
+[assembly: Addin("OpenSimBirds", OpenSim.VersionInfo.VersionNumber + "0.3")]
[assembly: AddinDependency("OpenSim.Region.Framework", OpenSim.VersionInfo.VersionNumber)]
+[assembly: AddinDescription("OpenSimBirds module.")]
+[assembly: AddinAuthor("Jak Daniels")]
namespace Flocking
{
@@ -58,31 +60,31 @@ namespace Flocking
private string m_regionConfigDir = "";
private Scene m_scene;
private ICommandConsole m_console;
- private FlockingModel m_model;
- private FlockingView m_view;
- private bool m_startup = true;
- private bool m_enabled = false;
- private bool m_ready = false;
- private uint m_frame = 0;
- private int m_frameUpdateRate = 1;
- private int m_chatChannel = 118;
- private string m_birdPrim;
- private int m_flockSize = 50;
+ private FlockingModel m_model;
+ private FlockingView m_view;
+ private bool m_enabled = false;
+ private bool m_startup = false;
+ private bool m_ready = false;
+ private uint m_frame = 0;
+ private int m_frameUpdateRate = 1;
+ private int m_chatChannel = 118;
+ private string m_birdPrim;
+ private int m_flockSize = 50;
private int m_maxFlockSize = 100;
- private float m_maxSpeed;
- private float m_maxForce;
- private float m_neighbourDistance;
- private float m_desiredSeparation;
- private float m_tolerance;
+ private float m_maxSpeed;
+ private float m_maxForce;
+ private float m_neighbourDistance;
+ private float m_desiredSeparation;
+ private float m_tolerance;
private float m_borderSize;
private int m_maxHeight;
- private Vector3 m_shoutPos = new Vector3(128f, 128f, 30f);
+ private Vector3 m_shoutPos = new Vector3(128f, 128f, 30f);
static object m_sync = new object();
private List m_allowedControllers = new List();
public IConfigSource m_config;
- private UUID m_owner;
+ private UUID m_owner;
#endregion
#region IRegionModuleBase implementation
@@ -92,28 +94,28 @@ namespace Flocking
public bool IsSharedModule { get { return false; } }
public void Initialise (IConfigSource source)
- {
+ {
m_config = source;
- }
+ }
- public void AddRegion (Scene scene)
- {
+ public void AddRegion (Scene scene)
+ {
IConfig cnf;
m_log.InfoFormat("[{0}]: Adding region {1} to this module", m_name, scene.RegionInfo.RegionName);
cnf = m_config.Configs["Startup"];
m_regionConfigDir = cnf.GetString("regionload_regionsdir", Path.Combine(Util.configDir(), "bin/Regions/"));
-
+
cnf = m_config.Configs[scene.RegionInfo.RegionName];
if (cnf == null)
{
- m_log.InfoFormat("[{0}]: No region section [{1}] found in addon-modules/{2}/config/*.ini configuration files.", m_name, scene.RegionInfo.RegionName, m_name);
+ m_log.InfoFormat("[{0}]: No region section [{1}] found in {2} configuration file.", m_name, scene.RegionInfo.RegionName, m_regionConfigDir);
//string moduleConfigFile = Path.Combine(Util.configDir(),m_name + ".ini");
string moduleConfigFile = Path.Combine(m_regionConfigDir, "Regions.ini");
try
{
- m_log.InfoFormat("[{0}]: Checking {1} for [{2}] section containing valid config keys", m_name, moduleConfigFile, scene.RegionInfo.RegionName);
+ m_log.InfoFormat("[{0}]: Checking {1} for [{2}] section", m_name, moduleConfigFile, scene.RegionInfo.RegionName);
m_config = new IniConfigSource(moduleConfigFile);
cnf = m_config.Configs[scene.RegionInfo.RegionName];
}
@@ -124,18 +126,23 @@ namespace Flocking
if (cnf == null)
{
- m_log.InfoFormat("[{0}]: No region section [{1}] found in configuration {2}. Birds in this region are set to Disabled", m_name, scene.RegionInfo.RegionName, moduleConfigFile);
- m_enabled = false;
- return;
+ m_log.InfoFormat("[{0}]: No region section [{1}] found in configuration {2}.", m_name, scene.RegionInfo.RegionName, moduleConfigFile);
+
+ cnf = m_config.Configs[scene.RegionInfo.RegionName];
+ if (cnf == null)
+ {
+ m_log.InfoFormat("[{0}]: No region section [{1}] found in main configuration. Module is disabled.", m_name, scene.RegionInfo.RegionName);
+ return;
+ }
}
}
- m_startup = cnf.GetBoolean("BirdsModuleStartup", true);
+ m_enabled = cnf.GetBoolean("BirdsModuleEnabled", false);
- if (m_startup)
+ if (m_enabled)
{
m_scene = scene;
- m_enabled = cnf.GetBoolean("BirdsEnabled", false);
+ m_startup = cnf.GetBoolean("BirdsShowOnStartup", false);
m_chatChannel = cnf.GetInt("BirdsChatChannel", 118);
m_birdPrim = cnf.GetString("BirdsPrim", "birdPrim");
m_flockSize = cnf.GetInt("BirdsFlockSize", 20);
@@ -185,7 +192,7 @@ namespace Flocking
m_log.InfoFormat("[{0}] No command security was defined in the config. Any user may possibly configure this module from a script!", m_name);
}
- m_log.InfoFormat("[{0}] Module is {1} listening for commands on channel {2} with Flock Size {3}", m_name, m_enabled ? "enabled and" : "disabled, but still", m_chatChannel, m_flockSize);
+ m_log.InfoFormat("[{0}] Module is {1} listening for commands on channel {2} with Flock Size {3}", m_name, m_startup ? "enabled and" : "disabled, but still", m_chatChannel, m_flockSize);
m_console = MainConsole.Instance;
//register commands with the scene
@@ -205,19 +212,18 @@ namespace Flocking
m_shoutPos = new Vector3(scene.RegionInfo.RegionSizeX / 2f, scene.RegionInfo.RegionSizeY / 2f, 30f);
FlockInitialise();
-
}
- else m_log.InfoFormat("[{0}] Module is disabled in Region {1}", m_name, scene.RegionInfo.RegionName);
- }
+ else m_log.InfoFormat("[{0}] Module is disabled in region {1}", m_name, scene.RegionInfo.RegionName);
+ }
- public void RegionLoaded (Scene scene)
- {
- if (m_startup)
+ public void RegionLoaded (Scene scene)
+ {
+ if (m_enabled)
{
// Mark Module Ready for duty
- m_ready = true;
- }
- }
+ m_ready = true;
+ }
+ }
public void PrimsLoaded(Scene scene)
{
@@ -225,22 +231,22 @@ namespace Flocking
ClearPersisted();
}
- public void RemoveRegion (Scene scene)
- {
+ public void RemoveRegion (Scene scene)
+ {
m_log.InfoFormat("[{0}]: Removing region {1} from this module", m_name, scene.RegionInfo.RegionName);
- if (m_startup) {
+ if (m_enabled) {
m_view.Clear();
- scene.EventManager.OnFrame -= FlockUpdate;
- scene.EventManager.OnChatFromClient -= SimChatSent;
+ scene.EventManager.OnFrame -= FlockUpdate;
+ scene.EventManager.OnChatFromClient -= SimChatSent;
scene.EventManager.OnChatFromWorld -= SimChatSent;
scene.EventManager.OnPrimsLoaded -= PrimsLoaded;
m_ready = false;
}
- }
+ }
public void Close()
{
- if (m_startup)
+ if (m_enabled)
{
m_scene.EventManager.OnFrame -= FlockUpdate;
m_scene.EventManager.OnChatFromClient -= SimChatSent;
@@ -250,7 +256,7 @@ namespace Flocking
}
}
- #endregion
+ #endregion
#region Helpers
@@ -292,25 +298,25 @@ namespace Flocking
#region EventHandlers
public void FlockUpdate ()
- {
- if (!m_ready || !m_enabled || ((m_frame++ % m_frameUpdateRate) != 0))
+ {
+ if (!m_ready || !m_startup || ((m_frame++ % m_frameUpdateRate) != 0))
{
- return;
- }
-
- //m_log.InfoFormat("update my birds");
-
- // work out where everyone has moved to
- // and tell the scene to render the new positions
- lock( m_sync ) {
- List birds = m_model.UpdateFlockPos ();
- m_view.Render (birds);
- }
- }
-
- protected void SimChatSent (Object x, OSChatMessage msg)
- {
- if (msg.Channel != m_chatChannel) return; // not for us
+ return;
+ }
+
+ //m_log.InfoFormat("update my birds");
+
+ // work out where everyone has moved to
+ // and tell the scene to render the new positions
+ lock( m_sync ) {
+ List birds = m_model.UpdateFlockPos ();
+ m_view.Render (birds);
+ }
+ }
+
+ protected void SimChatSent (Object x, OSChatMessage msg)
+ {
+ if (msg.Channel != m_chatChannel) return; // not for us
if (m_allowedControllers.Count > 0)
{
bool reject = true;
@@ -325,27 +331,27 @@ namespace Flocking
if (reject) return; //not for us
}
- // try and parse a valid cmd from this msg
- string cmd = msg.Message; //.ToLower ();
-
- //stick ui in the args so we know to respond in world
- //bit of a hack - but lets us use CommandDelegate inWorld
- string[] args = (cmd + " ").Split (" ".ToCharArray ());
-
- if (cmd.StartsWith ("stop")) {
- HandleStopCmd (m_name, args);
- } else if (cmd.StartsWith ("start")) {
- HandleStartCmd (m_name, args);
+ // try and parse a valid cmd from this msg
+ string cmd = msg.Message; //.ToLower ();
+
+ //stick ui in the args so we know to respond in world
+ //bit of a hack - but lets us use CommandDelegate inWorld
+ string[] args = (cmd + " ").Split (" ".ToCharArray ());
+
+ if (cmd.StartsWith ("stop")) {
+ HandleStopCmd (m_name, args);
+ } else if (cmd.StartsWith ("start")) {
+ HandleStartCmd (m_name, args);
} else if (cmd.StartsWith("enable")) {
HandleEnableCmd(m_name, args);
} else if (cmd.StartsWith("disable")) {
HandleDisableCmd(m_name, args);
- } else if (cmd.StartsWith ("size")) {
- HandleSetSizeCmd (m_name, args);
- } else if (cmd.StartsWith ("stats")) {
- HandleShowStatsCmd (m_name, args);
- } else if (cmd.StartsWith ("prim")) {
- HandleSetPrimCmd (m_name, args);
+ } else if (cmd.StartsWith ("size")) {
+ HandleSetSizeCmd (m_name, args);
+ } else if (cmd.StartsWith ("stats")) {
+ HandleShowStatsCmd (m_name, args);
+ } else if (cmd.StartsWith ("prim")) {
+ HandleSetPrimCmd (m_name, args);
} else if (cmd.StartsWith("speed")) {
HandleSetMaxSpeedCmd(m_name, args);
} else if (cmd.StartsWith("force")) {
@@ -356,36 +362,35 @@ namespace Flocking
HandleSetDesiredSeparationCmd(m_name, args);
} else if (cmd.StartsWith("tolerance")) {
HandleSetToleranceCmd(m_name, args);
- } else if (cmd.StartsWith ("framerate")) {
- HandleSetFrameRateCmd (m_name, args);
- }
-
- }
+ } else if (cmd.StartsWith ("framerate")) {
+ HandleSetFrameRateCmd (m_name, args);
+ }
+ }
- #endregion
-
- #region Command Handling
-
- private void AddCommand (string cmd, string args, string help, CommandDelegate fn)
- {
- string argStr = "";
- if (args.Trim ().Length > 0) {
- argStr = " <" + args + "> ";
- }
+ #endregion
+
+ #region Command Handling
+
+ private void AddCommand (string cmd, string args, string help, CommandDelegate fn)
+ {
+ string argStr = "";
+ if (args.Trim ().Length > 0) {
+ argStr = " <" + args + "> ";
+ }
m_log.InfoFormat("[{0}]: Adding console command {1} - {2} to region {3}", m_name, "birds-" + cmd + argStr, help, m_scene.RegionInfo.RegionName);
//m_scene.AddCommand (this, "birds-" + cmd, "birds-" + cmd + argStr, help, fn);
m_console.Commands.AddCommand(m_name, false, "birds-" + cmd, "birds-" + cmd + argStr, help, fn);
}
- private void RegisterCommands ()
- {
- AddCommand ("stop", "", "Stop Birds Flocking", HandleStopCmd);
- AddCommand ("start", "", "Start Birds Flocking", HandleStartCmd);
- AddCommand ("enable", "", "Enable Birds Flocking", HandleEnableCmd);
- AddCommand ("disable", "", "Disable Birds Flocking", HandleDisableCmd);
- AddCommand ("size", "num", "Adjust the size of the flock ", HandleSetSizeCmd);
- AddCommand ("prim", "name", "Set the prim used for each bird to that passed in", HandleSetPrimCmd);
- AddCommand ("speed", "num", "Set the maximum velocity each bird may achieve", HandleSetMaxSpeedCmd);
+ private void RegisterCommands ()
+ {
+ AddCommand("stop", "", "Stop Birds Flocking", HandleStopCmd);
+ AddCommand("start", "", "Start Birds Flocking", HandleStartCmd);
+ AddCommand("enable", "", "Enable Birds Flocking", HandleEnableCmd);
+ AddCommand("disable", "", "Disable Birds Flocking", HandleDisableCmd);
+ AddCommand("size", "num", "Adjust the size of the flock ", HandleSetSizeCmd);
+ AddCommand("prim", "name", "Set the prim used for each bird to that passed in", HandleSetPrimCmd);
+ AddCommand("speed", "num", "Set the maximum velocity each bird may achieve", HandleSetMaxSpeedCmd);
AddCommand("force", "num", "Set the maximum force each bird may accelerate", HandleSetMaxForceCmd);
AddCommand("distance", "num", "Set the maximum distance that other birds are to be considered in the same flock as us", HandleSetNeighbourDistanceCmd);
AddCommand("separation", "num", "How far away from other birds we would like to stay", HandleSetDesiredSeparationCmd);
@@ -400,7 +405,6 @@ namespace Flocking
if (comms != null)
{
comms.RegisterScriptInvocation(this, "birdsGetStats");
-
}
}
@@ -408,36 +412,37 @@ namespace Flocking
{
return ""; //currently a placeholder
}
-
- private bool ShouldHandleCmd ()
- {
+
+ private bool ShouldHandleCmd ()
+ {
if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) {
return false;
}
return true;
- }
-
- private bool IsInWorldCmd (ref string [] args)
- {
- if (args.Length > 0 && args [args.Length - 1].Equals ("")) {
+ }
+
+ private bool IsInWorldCmd (ref string [] args)
+ {
+ if (args.Length > 0 && args [args.Length - 1].Equals ("")) {
m_log.InfoFormat("[{0}]: Inworld command detected in region {1}", m_name, m_scene.RegionInfo.RegionName);
- return true;
- }
+ return true;
+ }
return false;
- }
-
- private void ShowResponse (string response, bool inWorld)
- {
- if (inWorld) {
- //IClientAPI ownerAPI = null;
- //if (m_scene.TryGetClient (m_owner, out ownerAPI)) {
- // ownerAPI.SendBlueBoxMessage (m_owner, "Birds", response);
- //}
+ }
+
+ private void ShowResponse (string response, bool inWorld)
+ {
+ if (inWorld) {
+ //IClientAPI ownerAPI = null;
+ //if (m_scene.TryGetClient (m_owner, out ownerAPI)) {
+ // ownerAPI.SendBlueBoxMessage (m_owner, "Birds", response);
+ //}
SendSimChat(response, m_chatChannel);
- } else {
- MainConsole.Instance.Output (response);
- }
- }
+ } else {
+ if (m_ready)
+ MainConsole.Instance.Output (response);
+ }
+ }
private void SendSimChat(string msg, int channel)
{
@@ -448,7 +453,7 @@ namespace Flocking
{
if (m_ready && ShouldHandleCmd ()) {
m_log.InfoFormat("[{0}]: Bird flocking is disabled in region {1}.", m_name, m_scene.RegionInfo.RegionName);
- m_enabled = false;
+ m_startup = false;
//m_ready = false;
m_view.Clear();
}
@@ -459,60 +464,59 @@ namespace Flocking
if (m_ready && ShouldHandleCmd())
{
m_log.InfoFormat("[{0}]: Bird flocking is enabled in region {1}.", m_name, m_scene.RegionInfo.RegionName);
- m_enabled = true;
+ m_startup = true;
//m_ready = true;
}
}
-
- public void HandleStopCmd (string module, string[] args)
- {
- if (m_enabled && m_ready && ShouldHandleCmd())
+
+ public void HandleStopCmd (string module, string[] args)
+ {
+ if (m_startup && m_ready && ShouldHandleCmd())
{
m_log.InfoFormat("[{0}]: Bird flocking is stopped in region {1}.", m_name, m_scene.RegionInfo.RegionName);
- m_enabled = false;
- }
- }
+ m_startup = false;
+ }
+ }
public void HandleStartCmd(string module, string[] args)
{
- if (!m_enabled && m_ready && ShouldHandleCmd())
+ if (!m_startup && m_ready && ShouldHandleCmd())
{
m_log.InfoFormat("[{0}]: Bird flocking is started in region {1}.", m_name, m_scene.RegionInfo.RegionName);
- m_enabled = true;
+ m_startup = true;
FlockUpdate();
}
}
- void HandleSetFrameRateCmd (string module, string[] args)
- {
+ void HandleSetFrameRateCmd (string module, string[] args)
+ {
if (m_ready && ShouldHandleCmd())
{
- int frameRate = Convert.ToInt32( args[1] );
- m_frameUpdateRate = frameRate;
+ int frameRate = Convert.ToInt32( args[1] );
+ m_frameUpdateRate = frameRate;
m_log.InfoFormat("[{0}]: Bird updates set to every {1} frames in region {2}.", m_name, frameRate, m_scene.RegionInfo.RegionName);
- }
- }
+ }
+ }
- public void HandleSetSizeCmd (string module, string[] args)
- {
+ public void HandleSetSizeCmd (string module, string[] args)
+ {
if (m_ready && ShouldHandleCmd())
{
- lock( m_sync ) {
- int newSize = Convert.ToInt32(args[1]);
+ lock( m_sync ) {
+ int newSize = Convert.ToInt32(args[1]);
if (newSize > m_maxFlockSize) newSize = m_maxFlockSize;
m_view.Clear();
m_model.Size = newSize;
m_log.InfoFormat("[{0}]: Bird flock size is set to {1} in region {2}.", m_name, newSize, m_scene.RegionInfo.RegionName);
-
- }
- }
- }
-
- public void HandleShowStatsCmd (string module, string[] args)
- {
+ }
+ }
+ }
+
+ public void HandleShowStatsCmd (string module, string[] args)
+ {
if (m_ready && ShouldHandleCmd())
{
- bool inWorld = IsInWorldCmd (ref args);
+ bool inWorld = IsInWorldCmd (ref args);
int i;
int s=m_model.Size;
UUID primUuid;
@@ -523,8 +527,8 @@ namespace Flocking
m_log.InfoFormat("[{0}]: Sending bird statistics to region {1}.", m_name, m_scene.RegionInfo.RegionName);
}
- ShowResponse("birds-started = " + (m_enabled ? "True" : "False"), inWorld);
- ShowResponse("birds-enabled = " + (m_ready ? "True" : "False"), inWorld);
+ ShowResponse("birds-enabled = " + (m_enabled ? "True" : "False"), inWorld);
+ ShowResponse("birds-startup = " + (m_ready ? "True" : "False"), inWorld);
ShowResponse("birds-prim = " + m_view.BirdPrim, inWorld);
ShowResponse("birds-framerate = " + m_frameUpdateRate, inWorld);
ShowResponse("birds-maxsize = " + m_maxFlockSize, inWorld);
@@ -560,21 +564,21 @@ namespace Flocking
ShowResponse("birds-prim" + i + " = " + m_name + i + " : " + primUuid.ToString() + " : " + avUuids.Trim(), inWorld);
}
- }
- }
-
- public void HandleSetPrimCmd (string module, string[] args)
- {
+ }
+ }
+
+ public void HandleSetPrimCmd (string module, string[] args)
+ {
if (m_ready && ShouldHandleCmd())
{
- string primName = args[1];
- lock(m_sync) {
- m_view.BirdPrim = primName;
+ string primName = args[1];
+ lock(m_sync) {
+ m_view.BirdPrim = primName;
m_log.InfoFormat("[{0}]: Bird prim is set to {1} in region {2}.", m_name, primName, m_scene.RegionInfo.RegionName);
- m_view.Clear();
- }
- }
- }
+ m_view.Clear();
+ }
+ }
+ }
public void HandleSetMaxSpeedCmd(string module, string[] args)
{
@@ -641,8 +645,6 @@ namespace Flocking
}
}
- #endregion
-
- }
-
+ #endregion
+ }
}
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;
+ }
+ }
+
+
}
diff --git a/README.md b/README.md
index 3ed3808..85d8131 100644
--- a/README.md
+++ b/README.md
@@ -25,13 +25,13 @@ Configuration:
If you have the module added to or compiled with your OpenSim build then it will run a instance of itself once per region.
By default it will configure itself to some sensible defaults and will sit quietly in the background waiting for commands
-from the console, or from in-world. It will not enable itself (i.e. rez some birds) until commanded to do so, or
-configured to do so in the .ini file. It is possible to completely stop the module from doing anything (including
+from the console, or from in-world. It will not enable itself (i.e. rez some birds) until commanded to do so, or
+configured to do so in the .ini file. It is possible to completely stop the module from doing anything (including
listening for commands), but you must have a particular setting in the .ini file for that region (see below) - in other
words, you must have a config for it!
To become active, the module needs to be enabled in the ini file or commanded to do so from inworld or the console.
-Otherwise it does nothing on startup except listen for commands. If you are running multiple regions on one simulator you
+Otherwise it does nothing on startup except listen for commands. If you are running multiple regions on one simulator you
can have different Birds settings per region in the configuration file, in the exact same way you can customize per Region
setting in Regions.ini
@@ -59,9 +59,9 @@ Here is an example config:
;; Set the Birds settings per named region
[Test Region 1]
-
- BirdsModuleStartup = True ;this is the default and determines whether the module does anything
- BirdsEnabled = True ;set to false to disable the birds from appearing in this region
+
+ BirdsModuleEnabled = True ;this is the default and determines whether the module does anything
+ BirdsShowOnStartup = True ;set to false to disable the birds from appearing in this region
BirdsFlockSize = 50 ;the number of birds to flock
BirdsMaxFlockSize = 100 ;the maximum flock size that can be created (keeps things sane)
BirdsMaxSpeed = 3 ;how far each bird can travel per update
@@ -72,9 +72,9 @@ Here is an example config:
BirdsBorderSize = 5 ;how close to the edge of a region can we get?
BirdsMaxHeight = 256 ;how high are we allowed to flock
BirdsUpdateEveryNFrames = 1 ;update bird positions every N simulator frames
- BirdsPrim = SeaGull1 ;By default the module will create a flock of plain wooden spheres,
+ BirdsPrim = SeaGull1 ;By default the module will create a flock of plain wooden spheres,
;however this can be overridden to the name of an existing prim that
- ;needs to already exist in the scene - i.e. be rezzed in the region.
+ ;needs to already exist in the scene - i.e. be rezzed in the region.
;who is allowed to send commands via chat or script: list of UUIDs or ESTATE_OWNER or ESTATE_MANAGER
;or everyone if not specified
@@ -94,7 +94,7 @@ Runtime Commands:
The following commands, which can be issued on the Console or via in-world chat or scripted chat on the BirdsChatChannel
to control the birds at runtime:
- birds-stop or /118 stop ;stop all birds flocking
+ birds-stop or /118 stop ;stop all birds flocking
birds-start or /118 start ;start all birds flocking
birds-enable or /118 enable ;enable the flocking simulation if disabled and rez new birds
birds-disable or /118 disable ;stop all birds and remove them from the scene
@@ -122,8 +122,8 @@ Security:
By default anyone can send commands to the module from within a script or via the in-world chat on the 'BirdsChatChannel' channel.
You should use a high negative value for channel if you want to allow script access, but not in-world chat. Further you can restrict
which users are allowed to control the module using the 'BirdsAllowedControllers' setting. This is a comma separated list of user UUIDs,
-but it may also contain one of the pre-defined constants ESTATE_OWNER (evaluates to the UUID of the estate owner) and ESTATE_MANAGER
-(evaluates to a list of estate manager UUIDS).
+but it may also contain one of the pre-defined constants ESTATE_OWNER (evaluates to the UUID of the estate owner) and ESTATE_MANAGER
+(evaluates to a list of estate manager UUIDS).
* For commands sent from in-world chat, it is the UUID of the avatar sending the command that is checked against the list.
* For commands sent from a script it is the UUID of the owner of the prim in which the script resides that is checked against the list.
@@ -134,7 +134,7 @@ Any currently rezzed in-scene-object can be used as the bird prim. However fps i
complexity of the entity to use. It is easier to throw a single prim (or sculpty) around the scene than it is to
throw the constituent parts of a 200 linked prim dragon.
-Tests show that <= 500 single prims can be flocked effectively - depending on system and network
+Tests show that <= 500 single prims can be flocked effectively - depending on system and network
However maybe <= 300 simple linksets can perform as well.
Network Traffic:
@@ -186,9 +186,9 @@ is an example output:
In the above example, there is one avatar sitting on bird-prim18. For more than one avatar the UUID list will be separated by spaces.
-Please Note:
+Please Note:
-This module is currently only tested against opensim master.
+This module is currently only tested against opensim master.
Licence: all files released under a BSD licence
If you have any question please contact Jak Daniels, jak@ateb.co.uk