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