Numerous changes to make module more versatile

pull/1/merge
Jak Daniels 2014-12-31 18:50:48 +00:00
parent 2541527cd7
commit ca41de0286
5 changed files with 141 additions and 113 deletions

View File

@ -41,6 +41,7 @@ namespace Flocking
private float m_desiredSeparation;
private float m_tolerance;
private float m_border;
private string m_name;
private Random m_rnd = new Random(Environment.TickCount);
@ -50,13 +51,14 @@ namespace Flocking
if( value < m_flock.Count ) {
m_flock.RemoveRange( 0, m_flock.Count - value );
} else while( value > m_flock.Count ) {
AddBird( "Bird"+m_flock.Count);
AddBird(m_name + m_flock.Count);
}
}
}
public FlockingModel( float maxSpeed, float maxForce, float neighbourDistance, float desiredSeparation, float tolerance, float border) {
m_maxSpeed = maxSpeed;
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;

View File

@ -42,7 +42,7 @@ using OpenSim.Framework.Console;
using Mono.Addins;
[assembly: Addin("OpenSimBirds", "0.2")]
[assembly: AddinDependency("OpenSim", "0.5")]
[assembly: AddinDependency("OpenSim.Region.Framework", OpenSim.VersionInfo.VersionNumber)]
namespace Flocking
{
@ -54,6 +54,7 @@ namespace Flocking
public string m_name = "OpenSimBirds";
private Scene m_scene;
private ICommandConsole m_console;
private FlockingModel m_model;
private FlockingView m_view;
private bool m_enabled = false;
@ -91,25 +92,11 @@ namespace Flocking
public void AddRegion (Scene scene)
{
m_log.InfoFormat("[{0}]: Adding region '{1}' to this module", m_name, 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_log.InfoFormat("[{0}]: No region section [{1}] found in configuration. Birds in this region are set to Disabled", m_name, scene.RegionInfo.RegionName);
m_enabled = false;
return;
}
@ -128,43 +115,36 @@ namespace Flocking
m_tolerance = cnf.GetFloat("BirdsTolerance", 5f);
m_borderSize = cnf.GetFloat("BirdsRegionBorderSize", 5f);
m_maxHeight = cnf.GetInt("BirdsMaxHeight", 256);
m_frameUpdateRate = cnf.GetInt("BirdsUpdateEveryNFrames", 1);
m_log.InfoFormat("[{0}] Enabled on channel {1} with Flock Size {2}", m_name, m_chatChannel, m_flockSize);
m_scene = scene;
m_console = MainConsole.Instance;
//register commands with the scene
RegisterCommands();
//register handlers
scene.EventManager.OnFrame += FlockUpdate;
scene.EventManager.OnChatFromClient += SimChatSent; //listen for commands sent from the client
m_scene.EventManager.OnFrame += FlockUpdate;
m_scene.EventManager.OnChatFromClient += SimChatSent; //listen for commands sent from the client
// init module
m_model = new FlockingModel(m_maxSpeed, m_maxForce, m_neighbourDistance, m_desiredSeparation, m_tolerance, m_borderSize);
m_view = new FlockingView(scene);
m_model = new FlockingModel(m_name, m_maxSpeed, m_maxForce, m_neighbourDistance, m_desiredSeparation, m_tolerance, m_borderSize);
m_view = new FlockingView(m_name, m_scene);
m_view.BirdPrim = m_birdPrim;
m_frame = 0;
FlockInitialise();
}
}
public void RegionLoaded (Scene scene)
{
if (m_enabled) {
//make a flow map for this scene
FlowMap flowMap = new FlowMap(scene, m_maxHeight, m_borderSize);
flowMap.Initialise();
// Generate initial flock values
m_model.Initialise (m_flockSize, flowMap);
// who is the owner for the flock in this region
m_owner = scene.RegionInfo.EstateSettings.EstateOwner;
m_view.PostInitialize (m_owner);
// Mark Module Ready for duty
//m_scene = scene;
if (m_enabled) {
// Mark Module Ready for duty
m_ready = true;
}
}
@ -191,9 +171,27 @@ namespace Flocking
#endregion
#region EventHandlers
#region Helpers
public void FlockUpdate ()
public void FlockInitialise()
{
//make a flow map for this scene
FlowMap flowMap = new FlowMap(m_scene, m_maxHeight, m_borderSize);
flowMap.Initialise();
// Generate initial flock values
m_model.Initialise(m_flockSize, flowMap);
// who is the owner for the flock in this region
m_owner = m_scene.RegionInfo.EstateSettings.EstateOwner;
m_view.PostInitialize(m_owner);
}
#endregion
#region EventHandlers
public void FlockUpdate ()
{
if (((m_frame++ % m_frameUpdateRate) != 0) || !m_ready || !m_enabled) {
return;
@ -247,13 +245,17 @@ namespace Flocking
if (args.Trim ().Length > 0) {
argStr = " <" + args + "> ";
}
m_scene.AddCommand (this, "flock-" + cmd, "flock-" + cmd + argStr, help, fn);
}
m_log.InfoFormat("[{0}]: Adding 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 all Flocking", HandleStopCmd);
AddCommand ("start", "", "Start Flocking", HandleStartCmd);
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 ("stats", "", "show flocking stats", HandleShowStatsCmd);
AddCommand ("prim", "name", "set the prim used for each bird to that passed in", HandleSetPrimCmd);
@ -262,7 +264,14 @@ namespace Flocking
private bool ShouldHandleCmd ()
{
return m_scene.ConsoleScene () == m_scene;
if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene))
{
m_log.InfoFormat("[{0}]: Command Ignored!", m_name);
return false;
} else {
m_log.InfoFormat("[{0}]: Command Executed!", m_name);
return true;
}
}
private bool IsInWorldCmd (ref string [] args)
@ -287,15 +296,46 @@ namespace Flocking
}
}
public void HandleDisableCmd(string module, string[] args)
{
if (m_ready && ShouldHandleCmd ()) {
m_log.InfoFormat("[{0}]: Bird flocking is disabled.", m_name);
m_enabled = false;
m_ready = false;
m_view.Clear();
}
}
public void HandleEnableCmd(string module, string[] args)
{
if (!m_ready && ShouldHandleCmd())
{
m_log.InfoFormat("[{0}]: Bird flocking is enabled.", m_name);
FlockInitialise();
m_enabled = true;
m_ready = true;
}
}
public void HandleStopCmd (string module, string[] args)
{
if (ShouldHandleCmd ()) {
m_log.Info ("stop the flocking capability");
if (m_enabled && m_ready && ShouldHandleCmd())
{
m_log.InfoFormat("[{0}]: Bird flocking is stopped.", m_name);
m_enabled = false;
m_view.Clear ();
}
}
public void HandleStartCmd(string module, string[] args)
{
if (!m_enabled && m_ready && ShouldHandleCmd())
{
m_log.InfoFormat("[{0}]: Bird flocking is started.", m_name);
m_enabled = true;
FlockUpdate();
}
}
void HandleSetFrameRateCmd (string module, string[] args)
{
if (ShouldHandleCmd ()) {
@ -304,15 +344,6 @@ namespace Flocking
}
}
public void HandleStartCmd (string module, string[] args)
{
if (ShouldHandleCmd ()) {
m_log.Info ("start the flocking capability");
m_enabled = true;
FlockUpdate ();
}
}
public void HandleSetSizeCmd (string module, string[] args)
{
if (ShouldHandleCmd ()) {

View File

@ -30,20 +30,24 @@ using System.Collections.Generic;
using OpenMetaverse;
using OpenSim.Framework;
using OpenSim.Region.Framework.Scenes;
using log4net;
namespace Flocking
{
public class FlockingView
{
private Scene m_scene;
private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
private Scene m_scene;
private UUID m_owner;
private String m_name;
private String m_birdPrim;
private Dictionary<string, SceneObjectGroup> m_sogMap = new Dictionary<string, SceneObjectGroup> ();
public FlockingView (Scene scene)
public FlockingView (String moduleName, Scene scene)
{
m_scene = scene;
m_name = moduleName;
m_scene = scene;
}
public void PostInitialize (UUID owner)
@ -60,6 +64,7 @@ namespace Flocking
//trash everything we have
foreach (string name in m_sogMap.Keys)
{
m_log.InfoFormat("[{0}]: Removing prim {1} from region {2}", m_name, name, m_scene.RegionInfo.RegionName);
RemoveSOGFromScene(name);
}
m_sogMap.Clear();
@ -78,17 +83,31 @@ namespace Flocking
SceneObjectGroup sog;
SceneObjectPart rootPart;
if (existing == null) {
SceneObjectGroup group = findByName (m_birdPrim);
sog = CopyPrim (group, bird.Id);
rootPart = sog.RootPart;
//set prim to phantom
sog.UpdatePrimFlags(rootPart.LocalId, false, false, true, false);
m_sogMap [bird.Id] = sog;
m_log.InfoFormat("[{0}]: Adding prim {1} from region {2}", m_name, bird.Id, m_scene.RegionInfo.RegionName);
m_scene.AddNewSceneObject (sog, false);
} else {
sog = existing.ParentGroup;
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);
// Fire script on_rez
sog.CreateScriptInstances(0, true, m_scene.DefaultScriptEngine, 1);
rootPart.ParentGroup.ResumeScripts();
rootPart.ScheduleFullUpdate();
}
private static Quaternion CalcRotationToEndpoint (SceneObjectGroup copy, Vector3 sv, Vector3 ev)
@ -133,7 +152,7 @@ namespace Flocking
private SceneObjectGroup MakeDefaultPrim (string name)
{
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);
prim.Name = name;

View File

@ -1,4 +1,6 @@
INonSharedRegion Module - ability to control flocks of prims within an OpenSim scene
INonSharedRegion Module - ability to control flocks of prims within an OpenSim scene.
***This module is currently broken, removing prims from the scene on disable does not work****
To build from source
@ -6,7 +8,8 @@ To build from source
Add OpenSimBirds source tree under opensim/addon-modules
./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.
Remember you need an .ini file in bin/addon-modules/OpenSimBirds/config/
OpenSimBirds has no external dependencies other than the dlls currently included in opensim.
The project generates a single dll - OpenSimBirds.Modules.dll which is copied into opensim/bin as part of the build step
@ -19,12 +22,13 @@ If you are running multiple regions on one simulator you can have different Bird
settings per region in the configuration file, in the exact same way you can
customize per Region setting in Regions.ini
The configuration file for this module is in:
The configuration file for this module should be placed in:
addon-modules/OpenSimBirds/config/OpenSimBirds.ini
bin/addon-modules/OpenSimBirds/config/OpenSimBirds.ini
and follows the same format as a Regions.ini file, where you specify setting for
each region using the [Region Name] section heading.
and follows the similar format as a Regions.ini file, where you specify setting for
each region using the [Region Name] section heading. There is an example .ini file
provided which should be edited and copied to the correct place above.
Here is an example config:
@ -76,22 +80,10 @@ 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
However maybe <= 300 simple linksets can perform as well.
I intend to allow inventory items and UUIDs to represent the birds - this is not written yet however.
Please Note
This module is currently only tested against opensim master. If it is found to work against a stable release,
then that behaviour ought to be considered as a bug - which I will attempt to fix in the next git push.
Next Steps
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.
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

View File

@ -1,16 +0,0 @@
;; 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.