Many changes to support per region configuration and project name change

pull/1/merge
Jak Daniels 2014-12-24 16:29:19 +00:00
parent d75428a078
commit d18d37faf6
11 changed files with 242 additions and 188 deletions

View File

@ -20,3 +20,8 @@
refactored the code refactored the code
added some more config items to set the region border size (no go zone) and the max height added some more config items to set the region border size (no go zone) and the max height
added support to the module for varregions added support to the module for varregions
24/12/2014
renamed the modeul to OpenSimBirds, changed all references to [Bb]oids to [Bb]irds in code
change the configuration to use own ini file and to setup per region configurations
changed Util class to BirdsUtil to avoid clash with OpenSim.Util

View File

@ -1,5 +1,5 @@
The following people have contributed to the development of the OpenSimBoids module The following people have contributed to the development of the OpenSimBirds module
* Jon Cundill - initial implementation * Jon Cundill - initial implementation
* Jak Daniels - refactor for opensim 0.8.x and varregions * Jak Daniels - refactor for opensim 0.8.x and varregions and per region configuration

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) Contributors, https://github.com/jonc/osboids * Copyright (c) Contributors, https://github.com/jonc/osbirds
* See CONTRIBUTORS.TXT for a full list of copyright holders. * See CONTRIBUTORS.TXT for a full list of copyright holders.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -31,7 +31,7 @@ using OpenMetaverse;
namespace Flocking namespace Flocking
{ {
public class Boid 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;
@ -43,33 +43,33 @@ namespace Flocking
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.Boid"/> 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 boid /// L. the initial position of this bird
/// </param> /// </param>
/// <param name='ms'> /// <param name='ms'>
/// Ms. max speed this boid can attain /// Ms. max speed this bird can attain
/// </param> /// </param>
/// <param name='mf'> /// <param name='mf'>
/// Mf. max force / acceleration this boid can extert /// Mf. max force / acceleration this bird can extert
/// </param> /// </param>
public Boid (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;
} }
@ -87,15 +87,15 @@ namespace Flocking
} }
/// <summary> /// <summary>
/// Moves our boid 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='boids'> /// <param name='birds'>
/// Boids. all the other chaps in the scene /// Birds. all the other chaps in the scene
/// </param> /// </param>
public void MoveInSceneRelativeToFlock (List<Boid> boids) public void MoveInSceneRelativeToFlock (List<Bird> birds)
{ {
// we would like to stay with our mates // we would like to stay with our mates
Flock (boids); Flock (birds);
// our first priority is to not hurt ourselves // our first priority is to not hurt ourselves
AvoidObstacles (); AvoidObstacles ();
@ -119,13 +119,13 @@ namespace Flocking
/// our desire to move towards the flock centre /// our desire to move towards the flock centre
/// ///
/// </summary> /// </summary>
void Flock (List<Boid> boids) void Flock (List<Bird> birds)
{ {
// calc the force vectors on this boid // calc the force vectors on this bird
Vector3 sep = Separate (boids); // Separation Vector3 sep = Separate (birds); // Separation
Vector3 ali = Align (boids); // Alignment Vector3 ali = Align (birds); // Alignment
Vector3 coh = Cohesion (boids); // Cohesion Vector3 coh = Cohesion (birds); // Cohesion
// Arbitrarily weight these forces // Arbitrarily weight these forces
//TODO: expose these consts //TODO: expose these consts
@ -135,7 +135,7 @@ namespace Flocking
//coh.mult(1.0); //coh.mult(1.0);
coh *= 1.0f; coh *= 1.0f;
// Add the force vectors to the current acceleration of the boid // 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);
@ -159,7 +159,7 @@ namespace Flocking
m_vel += m_acc; m_vel += m_acc;
// Limit speed // Limit speed
//m_vel.limit(maxspeed); //m_vel.limit(maxspeed);
m_vel = Util.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;
@ -209,7 +209,7 @@ namespace Flocking
//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 = Util.Limit (steer, m_model.MaxForce); steer = BirdsUtil.Limit (steer, m_model.MaxForce);
} else { } else {
steer = Vector3.Zero; steer = Vector3.Zero;
} }
@ -257,7 +257,7 @@ namespace Flocking
// 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 )
@ -265,19 +265,19 @@ namespace Flocking
} }
/// <summary> /// <summary>
/// Separate ourselves from the specified boids. /// 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='boids'> /// <param name='birds'>
/// Boids. all the boids in the scene /// Birds. all the birds in the scene
/// </param> /// </param>
Vector3 Separate (List<Boid> boids) 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 boid in the system, check if it's too close // For every bird in the system, check if it's too close
foreach (Boid other in boids) { 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)) {
@ -301,24 +301,24 @@ namespace Flocking
steer *= m_model.MaxSpeed; steer *= m_model.MaxSpeed;
steer -= m_vel; steer -= m_vel;
//steer.limit(maxforce); //steer.limit(maxforce);
steer = Util.Limit (steer, m_model.MaxForce); steer = BirdsUtil.Limit (steer, m_model.MaxForce);
} }
return steer; return steer;
} }
/// <summary> /// <summary>
/// Align our boid within the flock. /// Align our bird within the flock.
/// For every nearby boid 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='boids'> /// <param name='birds'>
/// Boids. all the boids 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<Boid> boids) 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 (Boid other in boids) { 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;
@ -336,7 +336,7 @@ namespace Flocking
steer *= m_model.MaxSpeed; steer *= m_model.MaxSpeed;
steer -= m_vel; steer -= m_vel;
//steer.limit(maxforce); //steer.limit(maxforce);
steer = Util.Limit (steer, m_model.MaxForce); steer = BirdsUtil.Limit (steer, m_model.MaxForce);
} }
return steer; return steer;
@ -344,18 +344,18 @@ namespace Flocking
/// <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 boids, 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='boids'> /// <param name='birds'>
/// Boids. the boids in the scene /// Birds. the birds in the scene
/// </param> /// </param>
Vector3 Cohesion (List<Boid> boids) 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 (Boid other in boids) { 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

View File

@ -1,5 +1,6 @@
/* /*
* Copyright (c) Contributors, https://github.com/jonc/osboids * Copyright (c) Contributors, https://github.com/jonc/osboids
* https://github.com/JakDaniels/OpenSimBirds
* See CONTRIBUTORS.TXT for a full list of copyright holders. * See CONTRIBUTORS.TXT for a full list of copyright holders.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -29,7 +30,7 @@ using OpenMetaverse;
namespace Flocking namespace Flocking
{ {
public class Util public class BirdsUtil
{ {
public static Vector3 Limit (Vector3 initial, float maxLen) public static Vector3 Limit (Vector3 initial, float maxLen)
{ {

View File

@ -1,5 +1,6 @@
/* /*
* Copyright (c) Contributors, https://github.com/jonc/osboids * Copyright (c) Contributors, https://github.com/jonc/osboids
* https://github.com/JakDaniels/OpenSimBirds
* See CONTRIBUTORS.TXT for a full list of copyright holders. * See CONTRIBUTORS.TXT for a full list of copyright holders.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -32,13 +33,13 @@ namespace Flocking
{ {
public class FlockingModel public class FlockingModel
{ {
private List<Boid> m_flock = new List<Boid>(); 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 Random m_rnd = new Random(Environment.TickCount); private Random m_rnd = new Random(Environment.TickCount);
@ -49,7 +50,7 @@ namespace Flocking
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 while( value > m_flock.Count ) { } else while( value > m_flock.Count ) {
AddBoid( "boid"+m_flock.Count); AddBird( "Bird"+m_flock.Count);
} }
} }
} }
@ -59,15 +60,15 @@ namespace Flocking
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 AddBoid (string name) void AddBird (string name)
{ {
Boid boid = new Boid (name, this, m_flowMap); Bird Bird = new Bird (name, this, m_flowMap);
// find an initial random location for this Boid // 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);
@ -79,8 +80,8 @@ namespace Flocking
zInit = m_rnd.Next(m_flowMap.LengthZ); zInit = m_rnd.Next(m_flowMap.LengthZ);
} }
boid.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 (boid); m_flock.Add (Bird);
} }
public float MaxSpeed { public float MaxSpeed {
@ -108,14 +109,14 @@ namespace Flocking
{ {
m_flowMap = flowMap; m_flowMap = flowMap;
for (int i = 0; i < num; i++) { for (int i = 0; i < num; i++) {
AddBoid ("boid"+i ); AddBird ("Bird"+i );
} }
} }
public List<Boid> UpdateFlockPos () public List<Bird> UpdateFlockPos ()
{ {
foreach (Boid b in m_flock) { foreach (Bird b in m_flock) {
b.MoveInSceneRelativeToFlock(m_flock); // Passing the entire list of boids to each boid individually b.MoveInSceneRelativeToFlock(m_flock); // Passing the entire list of Birds to each Bird individually
} }
return m_flock; return m_flock;

View File

@ -1,5 +1,6 @@
/* /*
* Copyright (c) Contributors, https://github.com/jonc/osboids * Copyright (c) Contributors, https://github.com/jonc/osboids
* https://github.com/JakDaniels/OpenSimBirds
* See CONTRIBUTORS.TXT for a full list of copyright holders. * See CONTRIBUTORS.TXT for a full list of copyright holders.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -26,9 +27,11 @@
*/ */
using System; using System;
using System.Timers; using System.Timers;
using System.Net;
using System.IO;
using System.Text;
using System.Collections.Generic; using System.Collections.Generic;
using OpenMetaverse; using OpenMetaverse;
using System.IO;
using Nini.Config; using Nini.Config;
using System.Threading; using System.Threading;
using log4net; using log4net;
@ -38,19 +41,18 @@ using OpenSim.Framework;
using OpenSim.Framework.Console; using OpenSim.Framework.Console;
using Mono.Addins; using Mono.Addins;
[assembly: Addin("BoidsModule", "0.1")] [assembly: Addin("OpenSimBirds", "0.2")]
[assembly: AddinDependency("OpenSim", "0.5")] [assembly: AddinDependency("OpenSim", "0.5")]
namespace Flocking namespace Flocking
{ {
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "OpenSimBirds")]
public class FlockingModule : INonSharedRegionModule public class FlockingModule : INonSharedRegionModule
{ {
#region Fields #region Fields
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);
static object m_sync = new object();
public string m_name = "BoidsModule"; public string m_name = "OpenSimBirds";
private Scene m_scene; private Scene m_scene;
private FlockingModel m_model; private FlockingModel m_model;
private FlockingView m_view; private FlockingView m_view;
@ -59,7 +61,7 @@ namespace Flocking
private uint m_frame = 0; private uint m_frame = 0;
private int m_frameUpdateRate = 1; private int m_frameUpdateRate = 1;
private int m_chatChannel = 118; private int m_chatChannel = 118;
private string m_boidPrim; private string m_birdPrim;
private int m_flockSize = 100; private int m_flockSize = 100;
private float m_maxSpeed; private float m_maxSpeed;
private float m_maxForce; private float m_maxForce;
@ -68,49 +70,67 @@ namespace Flocking
private float m_tolerance; private float m_tolerance;
private float m_borderSize; private float m_borderSize;
private int m_maxHeight; private int m_maxHeight;
static object m_sync = new object();
public IConfigSource m_config;
private UUID m_owner; private UUID m_owner;
#endregion #endregion
#region IRegionModuleBase implementation #region IRegionModuleBase implementation
public string Name { get { return m_name; } }
public Type ReplaceableInterface { get { return null; } }
public bool IsSharedModule { get { return false; } }
public void Initialise (IConfigSource source) public void Initialise (IConfigSource source)
{ {
//check if we are in the ini files m_config = source;
//if so get some physical constants out of them and pass into the model
IConfig config = source.Configs ["Boids"];
if (config != null) {
m_chatChannel = config.GetInt ("chat-channel", 118);
m_boidPrim = config.GetString ("boid-prim", "boidPrim");
m_flockSize = config.GetInt ("flock-size", 100);
m_maxSpeed = config.GetFloat("max-speed", 3f);
m_maxForce = config.GetFloat("max-force", 0.25f);
m_neighbourDistance = config.GetFloat("neighbour-dist", 25f);
m_desiredSeparation = config.GetFloat("desired-separation", 20f);
m_tolerance = config.GetFloat("tolerance", 5f);
m_borderSize = config.GetFloat("border-size", 5f);
m_maxHeight = config.GetInt("max-height", 256);
m_enabled = config.GetBoolean("enabled", false);
}
if (m_enabled)
{
m_log.InfoFormat("[BOIDS] Enabled on channel {0} with Flock Size {1}", m_chatChannel, m_flockSize);
//m_ready = true;
return;
}
} }
public void PostInitialise()
{
}
public void AddRegion (Scene scene) public void AddRegion (Scene scene)
{ {
m_scene = scene; m_log.InfoFormat("[{0}]: Adding region '{1}' to this module", m_name, scene.RegionInfo.RegionName);
m_log.InfoFormat ("[BOIDS]: Adding {0}", scene.RegionInfo.RegionName);
string moduleConfigFile = Path.Combine(Util.configDir(), "../addon-modules/" + m_name + "/config/" + m_name + ".ini");
m_log.InfoFormat("[{0}]: Loading from config file {1}", m_name, moduleConfigFile);
try
{
m_config = new IniConfigSource(moduleConfigFile);
}
catch (Exception)
{
m_log.InfoFormat("[{0}]: No module config file '{1}' was found! Tide in this region is set to Disabled", m_name, moduleConfigFile);
m_enabled = false;
m_config = null;
return;
}
IConfig cnf = m_config.Configs[scene.RegionInfo.RegionName];
if (cnf == null)
{
m_log.InfoFormat("[{0}]: No region section [{1}] found in config file {2}. Tide in this region is set to Disabled", m_name, scene.RegionInfo.RegionName, moduleConfigFile);
m_enabled = false;
return;
}
m_enabled = cnf.GetBoolean("BirdsEnabled", false);
if (m_enabled) if (m_enabled)
{ {
m_chatChannel = cnf.GetInt("BirdsChatChannel", 118);
m_birdPrim = cnf.GetString("BirdsPrim", "birdPrim");
m_flockSize = cnf.GetInt("BirdsFlockSize", 100);
m_maxSpeed = cnf.GetFloat("BirdsMaxSpeed", 3f);
m_maxForce = cnf.GetFloat("BirdsMaxForce", 0.25f);
m_neighbourDistance = cnf.GetFloat("BirdsNeighbourDistance", 25f);
m_desiredSeparation = cnf.GetFloat("BirdsDesiredSeparation", 20f);
m_tolerance = cnf.GetFloat("BirdsTolerance", 5f);
m_borderSize = cnf.GetFloat("BirdsRegionBorderSize", 5f);
m_maxHeight = cnf.GetInt("BirdsMaxHeight", 256);
m_log.InfoFormat("[{0}] Enabled on channel {1} with Flock Size {2}", m_name, m_chatChannel, m_flockSize);
//register commands //register commands
RegisterCommands(); RegisterCommands();
@ -121,7 +141,9 @@ namespace Flocking
// init module // init module
m_model = new FlockingModel(m_maxSpeed, m_maxForce, m_neighbourDistance, m_desiredSeparation, m_tolerance, m_borderSize); m_model = new FlockingModel(m_maxSpeed, m_maxForce, m_neighbourDistance, m_desiredSeparation, m_tolerance, m_borderSize);
m_view = new FlockingView(scene); m_view = new FlockingView(scene);
m_view.BoidPrim = m_boidPrim; m_view.BirdPrim = m_birdPrim;
m_frame = 0;
m_scene = scene;
} }
} }
@ -147,7 +169,8 @@ namespace Flocking
public void RemoveRegion (Scene scene) public void RemoveRegion (Scene scene)
{ {
if (m_enabled) { m_log.InfoFormat("[{0}]: Removing region '{1}' from this module", m_name, scene.RegionInfo.RegionName);
if (m_enabled) {
m_ready = false; m_ready = false;
scene.EventManager.OnFrame -= FlockUpdate; scene.EventManager.OnFrame -= FlockUpdate;
scene.EventManager.OnChatFromClient -= SimChatSent; scene.EventManager.OnChatFromClient -= SimChatSent;
@ -164,19 +187,6 @@ namespace Flocking
} }
} }
public string Name {
get { return m_name; }
}
public bool IsSharedModule {
get { return false; }
}
public Type ReplaceableInterface
{
get { return null; }
}
#endregion #endregion
#region EventHandlers #region EventHandlers
@ -187,13 +197,13 @@ namespace Flocking
return; return;
} }
//m_log.InfoFormat("update my boids"); //m_log.InfoFormat("update my birds");
// work out where everyone has moved to // work out where everyone has moved to
// and tell the scene to render the new positions // and tell the scene to render the new positions
lock( m_sync ) { lock( m_sync ) {
List<Boid > boids = m_model.UpdateFlockPos (); List<Bird > birds = m_model.UpdateFlockPos ();
m_view.Render (boids); m_view.Render (birds);
} }
} }
@ -244,8 +254,8 @@ namespace Flocking
AddCommand ("start", "", "Start Flocking", HandleStartCmd); AddCommand ("start", "", "Start Flocking", HandleStartCmd);
AddCommand ("size", "num", "Adjust the size of the flock ", HandleSetSizeCmd); AddCommand ("size", "num", "Adjust the size of the flock ", HandleSetSizeCmd);
AddCommand ("stats", "", "show flocking stats", HandleShowStatsCmd); AddCommand ("stats", "", "show flocking stats", HandleShowStatsCmd);
AddCommand ("prim", "name", "set the prim used for each boid to that passed in", HandleSetPrimCmd); AddCommand ("prim", "name", "set the prim used for each bird to that passed in", HandleSetPrimCmd);
AddCommand ("framerate", "num", "[debugging] only update boids every <num> frames", HandleSetFrameRateCmd); AddCommand ("framerate", "num", "[debugging] only update birds every <num> frames", HandleSetFrameRateCmd);
} }
private bool ShouldHandleCmd () private bool ShouldHandleCmd ()
@ -268,7 +278,7 @@ namespace Flocking
if (inWorld) { if (inWorld) {
IClientAPI ownerAPI = null; IClientAPI ownerAPI = null;
if (m_scene.TryGetClient (m_owner, out ownerAPI)) { if (m_scene.TryGetClient (m_owner, out ownerAPI)) {
ownerAPI.SendBlueBoxMessage (m_owner, "Boids", response); ownerAPI.SendBlueBoxMessage (m_owner, "Birds", response);
} }
} else { } else {
MainConsole.Instance.Output (response); MainConsole.Instance.Output (response);
@ -316,7 +326,7 @@ namespace Flocking
{ {
if (ShouldHandleCmd ()) { if (ShouldHandleCmd ()) {
bool inWorld = IsInWorldCmd (ref args); bool inWorld = IsInWorldCmd (ref args);
ShowResponse ("Num Boids = " + m_model.Size, inWorld); ShowResponse ("Num Birds = " + m_model.Size, inWorld);
} }
} }
@ -325,7 +335,7 @@ namespace Flocking
if (ShouldHandleCmd ()) { if (ShouldHandleCmd ()) {
string primName = args[1]; string primName = args[1];
lock(m_sync) { lock(m_sync) {
m_view.BoidPrim = primName; m_view.BirdPrim = primName;
m_view.Clear(); m_view.Clear();
} }
} }

View File

@ -1,5 +1,6 @@
/* /*
* Copyright (c) Contributors, https://github.com/jonc/osboids * Copyright (c) Contributors, https://github.com/jonc/osboids
* https://github.com/JakDaniels/OpenSimBirds
* See CONTRIBUTORS.TXT for a full list of copyright holders. * See CONTRIBUTORS.TXT for a full list of copyright holders.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -36,7 +37,7 @@ namespace Flocking
{ {
private Scene m_scene; private Scene m_scene;
private UUID m_owner; private UUID m_owner;
private String m_boidPrim; private String m_birdPrim;
private Dictionary<string, SceneObjectGroup> m_sogMap = new Dictionary<string, SceneObjectGroup> (); private Dictionary<string, SceneObjectGroup> m_sogMap = new Dictionary<string, SceneObjectGroup> ();
@ -50,8 +51,8 @@ namespace Flocking
m_owner = owner; m_owner = owner;
} }
public String BoidPrim { public String BirdPrim {
set{ m_boidPrim = value;} set{ m_birdPrim = value;}
} }
public void Clear () public void Clear ()
@ -64,36 +65,36 @@ namespace Flocking
m_sogMap.Clear(); m_sogMap.Clear();
} }
public void Render (List<Boid> boids) public void Render (List<Bird> birds)
{ {
foreach (Boid boid in boids) { foreach (Bird bird in birds) {
DrawBoid (boid); DrawBird (bird);
} }
} }
private void DrawBoid (Boid boid) private void DrawBird (Bird bird)
{ {
SceneObjectPart existing = m_scene.GetSceneObjectPart (boid.Id); SceneObjectPart existing = m_scene.GetSceneObjectPart (bird.Id);
SceneObjectGroup sog; SceneObjectGroup sog;
if (existing == null) { if (existing == null) {
SceneObjectGroup group = findByName (m_boidPrim); SceneObjectGroup group = findByName (m_birdPrim);
sog = CopyPrim (group, boid.Id); sog = CopyPrim (group, bird.Id);
m_sogMap [boid.Id] = sog; m_sogMap [bird.Id] = sog;
m_scene.AddNewSceneObject (sog, false); m_scene.AddNewSceneObject (sog, false);
} else { } else {
sog = existing.ParentGroup; sog = existing.ParentGroup;
} }
Quaternion rotation = CalcRotationToEndpoint (sog, sog.AbsolutePosition, boid.Location); Quaternion rotation = CalcRotationToEndpoint (sog, sog.AbsolutePosition, bird.Location);
sog.UpdateGroupRotationPR( boid.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())));
// boid 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);
@ -132,8 +133,8 @@ namespace Flocking
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 ();

View File

@ -1,5 +1,6 @@
/* /*
* Copyright (c) Contributors, https://github.com/jonc/osboids * Copyright (c) Contributors, https://github.com/jonc/osboids
* https://github.com/JakDaniels/OpenSimBirds
* See CONTRIBUTORS.TXT for a full list of copyright holders. * See CONTRIBUTORS.TXT for a full list of copyright holders.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -33,20 +34,20 @@ 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];
} }
@ -58,9 +59,9 @@ namespace Flocking
} }
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() {
@ -140,7 +141,7 @@ namespace Flocking
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 ||

View File

@ -1,45 +1,56 @@
Region Module - ability to control flocks of prims within an OpenSim scene INonSharedRegion Module - ability to control flocks of prims within an OpenSim scene
To build from source To build from source
Add OpenSimBoids source tree under opensim/addon-modules Add OpenSimBirds source tree under opensim/addon-modules
./runprebuild.sh against opensim root to build this module into the solution ./runprebuild.sh against opensim root to build this module into the solution
then xbuild, or build within Visual Studio / Monodevelop to produce the binaries then xbuild, or build within Visual Studio / Monodevelop to produce the binaries
OpenSimBoids has no external dependencies other than the dlls currently included in opensim. OpenSimBirds has no external dependencies other than the dlls currently included in opensim.
The project generates a single dll - OpenSimBoids.Modules.dll which is copied into opensim/bin as part of the build step The project generates a single dll - OpenSimBirds.Modules.dll which is copied into opensim/bin as part of the build step
Configuration Configuration
To become active, the module needs to be both referenced and enabled in the ini files. Otherwise it does nothing on startup To become active, the module needs enabled in the ini file. Otherwise it does nothing on startup.
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
Entry is as follows and in addition various config parameters are available to control the flock dynamics. The configuration file for this module is in:
addon-modules/OpenSimBirds/config/OpenSimBirds.ini
[Boids] and follows the same format as a Regions.ini file, where you specify setting for
each region using the [Region Name] section heading.
enabled = true ;removing the Boids group or setting enabled=false will switch off the module
flock-size = 100 ;the number of Boids to flock Here is an example config:
max-speed = 3 ;how far each boid can travel per update
max-force = 0.25 ;the maximum acceleration allowed to the current velocity of the boid ;; Set the Birds settings per named region
neighbour-dist = 25 ;max distance for other boids to be considered in the same flock as us
desired-separation = 20 ;how far away from other boids we would like to stay [Test Region 1]
tolerance = 5 ;how close to the edges of things can we get without being worried
border-size = 5 ;how close to the edge of a region can we get? BirdsEnabled = True ;set to false to disable the module in this region
max-height = 256 ;how high are we allowed to flock BirdsFlockSize = 100 ;the number of birds to flock
boid-prim = fish01 ;By default the module will create a flock of plain wooden spheres, BirdsMaxSpeed = 3 ;how far each bird can travel per update
;however this can be overridden to the name of an existing prim that BirdsMaxForce = 0.25 ;the maximum acceleration allowed to the current velocity of the bird
;needs to already exist in the scene - i.e. be rezzed in the region. BirdsNeighbourDistance = 25 ;max distance for other birds to be considered in the same flock as us
BirdsDesiredSeparation = 20 ;how far away from other birds we would like to stay
BirdsTolerance = 5 ;how close to the edges of things can we get without being worried
BirdsBorderSize = 5 ;how close to the edge of a region can we get?
BirdsMaxHeight = 256 ;how high are we allowed to flock
BirdsPrim = seagull01 ;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.
Various runtime commands control the flocking module behaviour - described below. These can either be invoked Various runtime commands control the flocking module behaviour - described below. These can either be invoked
from the Console or in world by directing them to a chat channel. To specify which channel to use: from the Console or in world by directing them to a chat channel. To specify which channel to use:
chat-channel = 118 the chat channel to listen for boid commands on chat-channel = 118 the chat channel to listen for Bird commands on
@ -48,29 +59,24 @@ Runtime Commands
The following commands, which can either be issued on the Console, or via a chat channel in-world, control the behaviour The following commands, which can either be issued on the Console, or via a chat channel in-world, control the behaviour
of the flock at runtime of the flock at runtime
flock-stop or /118 stop ;stop all flocking and remove boids from the region flock-stop or /118 stop ;stop all flocking and remove birds from the region
flock-start or /118 start ;start the flocking simulation flock-start or /118 start ;start the flocking simulation
flock-size <num> or /118 size <num> ;change the size of the flock flock-size <num> or /118 size <num> ;change the size of the flock
flock-prim <name> or /118 prim <name> ;change the boid prim to one already rezzed in the scene flock-prim <name> or /118 prim <name> ;change the bird prim to one already rezzed in the scene
flock-framerate <num> or /118 framerate <num> ;only update the flock positions every <num> frames flock-framerate <num> or /118 framerate <num> ;only update the flock positions every <num> frames
;only really useful for photography and debugging boid ;only really useful for photography and debugging bird
;behaviour ;behaviour
Boid prims Bird prims
Any currently rezzed in-scene-object can be used as the boid prim. However fps is very much affected by the Any currently rezzed in-scene-object can be used as the bird prim. However fps is very much affected by the
complexity of the entity to use. It is easier to throw a single prim (or sculpty) around the scene than it is to 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. 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. However maybe <= 300 simple linksets can perform as well.
I intend to allow inventory items and UUIDs to represent the boids - this is not written yet however. I intend to allow inventory items and UUIDs to represent the birds - this is not written yet however.
Prebuilt binaries etc.. to follow
Please Note Please Note
@ -79,16 +85,13 @@ This module is currently only tested against opensim master. If it is found to w
then that behaviour ought to be considered as a bug - which I will attempt to fix in the next git push. then that behaviour ought to be considered as a bug - which I will attempt to fix in the next git push.
Status
probably made it to alpha by now ...
Next Steps Next Steps
I want to improve the ability of the boids to avoid obstacles within the scene. Current avoidance is pretty basic, and I want to improve the ability of the birds to avoid obstacles within the scene. Current avoidance is pretty basic, and
only functions correctly about fifty percent of the time. Need to improve this without increasing computational cost. only functions correctly about fifty percent of the time. Need to improve this without increasing computational cost.
Licence: all files released under a BSD licence Licence: all files released under a BSD licence
If you have any question please contact Jak Daniels, jak@ateb.co.uk

16
config/OpenSimBirds.ini Normal file
View File

@ -0,0 +1,16 @@
;; Set the Birds settings per named region
[Test Region 1]
BirdsEnabled = True ;set to false to disable the module in this region
BirdsFlockSize = 100 ;the number of birds to flock
BirdsMaxSpeed = 3 ;how far each bird can travel per update
BirdsMaxForce = 0.25 ;the maximum acceleration allowed to the current velocity of the bird
BirdsNeighbourDistance = 25 ;max distance for other birds to be considered in the same flock as us
BirdsDesiredSeparation = 20 ;how far away from other birds we would like to stay
BirdsTolerance = 5 ;how close to the edges of things can we get without being worried
BirdsBorderSize = 5 ;how close to the edge of a region can we get?
BirdsMaxHeight = 256 ;how high are we allowed to flock
BirdsPrim = seagull01 ;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.

View File

@ -0,0 +1,16 @@
;; Set the Birds settings per named region
[Test Region 1]
BirdsEnabled = True ;set to false to disable the module in this region
BirdsFlockSize = 100 ;the number of birds to flock
BirdsMaxSpeed = 3 ;how far each bird can travel per update
BirdsMaxForce = 0.25 ;the maximum acceleration allowed to the current velocity of the bird
BirdsNeighbourDistance = 25 ;max distance for other birds to be considered in the same flock as us
BirdsDesiredSeparation = 20 ;how far away from other birds we would like to stay
BirdsTolerance = 5 ;how close to the edges of things can we get without being worried
BirdsBorderSize = 5 ;how close to the edge of a region can we get?
BirdsMaxHeight = 256 ;how high are we allowed to flock
BirdsPrim = seagull01 ;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.