aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/CoreModules/World/Wind
diff options
context:
space:
mode:
authorCharles Krinke2009-03-31 02:33:19 +0000
committerCharles Krinke2009-03-31 02:33:19 +0000
commit54a27f9f5c556e518c2ba18b9a5494d517dfd041 (patch)
tree5da9db44878c217e0c1872da0f963d88575ef8ff /OpenSim/Region/CoreModules/World/Wind
parentUpdate svn properties, add copyright header, formatting cleanup. (diff)
downloadopensim-SC_OLD-54a27f9f5c556e518c2ba18b9a5494d517dfd041.zip
opensim-SC_OLD-54a27f9f5c556e518c2ba18b9a5494d517dfd041.tar.gz
opensim-SC_OLD-54a27f9f5c556e518c2ba18b9a5494d517dfd041.tar.bz2
opensim-SC_OLD-54a27f9f5c556e518c2ba18b9a5494d517dfd041.tar.xz
Thank you kindly, MCortez for a patch that:
With some support from HomerH, this patch adds support for Wind Model plugins via the mono.Addin framework. * Adds console & OSSL access to Wind Parameters * Adds plug-in support for custom wind models * Provides two example Wind Model plug-ins Documentation for the wind module is temporarily located at http://code.google.com/p/flotsam/wiki/CoreWindModule [^] -- will move this documentation to http://opensimulator.org [^] after the patch has been committed.
Diffstat (limited to 'OpenSim/Region/CoreModules/World/Wind')
-rw-r--r--OpenSim/Region/CoreModules/World/Wind/IWindModelPlugin.cs56
-rw-r--r--OpenSim/Region/CoreModules/World/Wind/Plugins/ConfigurableWind.cs211
-rw-r--r--OpenSim/Region/CoreModules/World/Wind/Plugins/SimpleRandomWind.cs139
-rw-r--r--OpenSim/Region/CoreModules/World/Wind/WindModule.cs410
4 files changed, 716 insertions, 100 deletions
diff --git a/OpenSim/Region/CoreModules/World/Wind/IWindModelPlugin.cs b/OpenSim/Region/CoreModules/World/Wind/IWindModelPlugin.cs
new file mode 100644
index 0000000..29b0ed5
--- /dev/null
+++ b/OpenSim/Region/CoreModules/World/Wind/IWindModelPlugin.cs
@@ -0,0 +1,56 @@
1using System;
2using System.Collections.Generic;
3
4using Nini.Config;
5using OpenSim.Framework;
6using OpenMetaverse;
7using OpenSim.Region.Framework.Scenes;
8
9namespace OpenSim.Region.CoreModules.World.Wind
10{
11 public interface IWindModelPlugin : IPlugin
12 {
13 /// <summary>
14 /// Brief description of this plugin's wind model
15 /// </summary>
16 string Description { get; }
17
18 /// <summary>
19 /// Provides access to the wind configuration, if any.
20 /// </summary>
21 void WindConfig(Scene scene, IConfig windConfig);
22
23 /// <summary>
24 /// Update wind.
25 /// </summary>
26 void WindUpdate(uint frame);
27
28 /// <summary>
29 /// Returns the wind vector at the given local region coordinates.
30 /// </summary>
31 Vector3 WindSpeed(float x, float y, float z);
32
33 /// <summary>
34 /// Generate a 16 x 16 Vector2 array of wind speeds for LL* based viewers
35 /// </summary>
36 /// <returns>Must return a Vector2[256]</returns>
37 Vector2[] WindLLClientArray();
38
39 /// <summary>
40 /// Retrieve a list of parameter/description pairs.
41 /// </summary>
42 /// <returns></returns>
43 Dictionary<string, string> WindParams();
44
45 /// <summary>
46 /// Set the specified parameter
47 /// </summary>
48 void WindParamSet(string param, float value);
49
50 /// <summary>
51 /// Get the specified parameter
52 /// </summary>
53 float WindParamGet(string param);
54
55 }
56}
diff --git a/OpenSim/Region/CoreModules/World/Wind/Plugins/ConfigurableWind.cs b/OpenSim/Region/CoreModules/World/Wind/Plugins/ConfigurableWind.cs
new file mode 100644
index 0000000..2f5cc31
--- /dev/null
+++ b/OpenSim/Region/CoreModules/World/Wind/Plugins/ConfigurableWind.cs
@@ -0,0 +1,211 @@
1using System;
2using System.Collections.Generic;
3using System.Reflection;
4
5using log4net;
6using OpenMetaverse;
7
8using OpenSim.Region.CoreModules.World.Wind;
9
10namespace OpenSim.Region.CoreModules.World.Wind.Plugins
11{
12 class ConfigurableWind : Mono.Addins.TypeExtensionNode, IWindModelPlugin
13 {
14 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
15
16 private Vector2[] m_windSpeeds = new Vector2[16 * 16];
17 private Random m_rndnums = new Random(Environment.TickCount);
18
19 private float m_avgStrength = 5.0f; // Average magnitude of the wind vector
20 private float m_avgDirection = 0.0f; // Average direction of the wind in degrees
21 private float m_varStrength = 5.0f; // Max Strength Variance
22 private float m_varDirection = 30.0f;// Max Direction Variance
23 private float m_rateChange = 1.0f; //
24
25 private Vector2 m_curPredominateWind = new Vector2();
26
27
28
29 #region IPlugin Members
30
31 public string Version
32 {
33 get { return "1.0.0.0"; }
34 }
35
36 public string Name
37 {
38 get { return "ConfigurableWind"; }
39 }
40
41 public void Initialise()
42 {
43
44 }
45
46 #endregion
47
48 #region IDisposable Members
49
50 public void Dispose()
51 {
52 m_windSpeeds = null;
53 }
54
55 #endregion
56
57 #region IWindModelPlugin Members
58
59 public void WindConfig(OpenSim.Region.Framework.Scenes.Scene scene, Nini.Config.IConfig windConfig)
60 {
61 if( windConfig != null )
62 {
63 // Uses strength value if avg_strength not specified
64 m_avgStrength = windConfig.GetFloat("strength", 5.0F);
65 m_avgStrength = windConfig.GetFloat("avg_strength", 5.0F);
66
67 m_avgDirection = windConfig.GetFloat("avg_direction", 0.0F);
68 m_varStrength = windConfig.GetFloat("var_strength", 5.0F);
69 m_varDirection = windConfig.GetFloat("var_direction", 30.0F);
70 m_rateChange = windConfig.GetFloat("rate_change", 1.0F);
71
72 LogSettings();
73 }
74 }
75
76 public void WindUpdate(uint frame)
77 {
78 double avgAng = m_avgDirection * (Math.PI/180.0f);
79 double varDir = m_varDirection * (Math.PI/180.0f);
80
81 // Prevailing wind algorithm
82 // Inspired by Kanker Greenacre
83
84 // TODO:
85 // * This should probably be based on in-world time.
86 // * should probably move all these local variables to class members and constants
87 double time = DateTime.Now.TimeOfDay.Seconds / 86400;
88
89 double theta = time * (2 * Math.PI) * m_rateChange;
90
91 double offset = Math.Sin(theta) * Math.Sin(theta*2) * Math.Sin(theta*9) * Math.Cos(theta*4);
92
93 double windDir = avgAng + (varDir * offset);
94
95 offset = Math.Sin(theta) * Math.Sin(theta*4) + (Math.Sin(theta*13) / 3);
96 double windSpeed = m_avgStrength + (m_varStrength * offset);
97
98 if (windSpeed<0)
99 windSpeed=0;
100
101
102
103 m_curPredominateWind.X = (float)Math.Cos(windDir);
104 m_curPredominateWind.Y = (float)Math.Sin(windDir);
105
106 m_curPredominateWind.Normalize();
107 m_curPredominateWind.X *= (float)windSpeed;
108 m_curPredominateWind.Y *= (float)windSpeed;
109
110 for (int y = 0; y < 16; y++)
111 {
112 for (int x = 0; x < 16; x++)
113 {
114 m_windSpeeds[y * 16 + x] = m_curPredominateWind;
115 }
116 }
117 }
118
119 public Vector3 WindSpeed(float fX, float fY, float fZ)
120 {
121 return new Vector3(m_curPredominateWind, 0.0f);
122 }
123
124 public Vector2[] WindLLClientArray()
125 {
126 return m_windSpeeds;
127 }
128
129 public string Description
130 {
131 get
132 {
133 return "Provides a predominate wind direction that can change within configured variances for direction and speed.";
134 }
135 }
136
137 public System.Collections.Generic.Dictionary<string, string> WindParams()
138 {
139 Dictionary<string, string> Params = new Dictionary<string, string>();
140
141 Params.Add("avgStrength", "average wind strength");
142 Params.Add("avgDirection", "average wind direction in degrees");
143 Params.Add("varStrength", "allowable variance in wind strength");
144 Params.Add("varDirection", "allowable variance in wind direction in +/- degrees");
145 Params.Add("rateChange", "rate of change");
146
147 return Params;
148 }
149
150 public void WindParamSet(string param, float value)
151 {
152 switch (param)
153 {
154 case "avgStrength":
155 m_avgStrength = value;
156 break;
157 case "avgDirection":
158 m_avgDirection = value;
159 break;
160 case "varStrength":
161 m_varStrength = value;
162 break;
163 case "varDirection":
164 m_varDirection = value;
165 break;
166 case "rateChange":
167 m_rateChange = value;
168 break;
169 }
170 }
171
172 public float WindParamGet(string param)
173 {
174 switch (param)
175 {
176 case "avgStrength":
177 return m_avgStrength;
178 case "avgDirection":
179 return m_avgDirection;
180 case "varStrength":
181 return m_varStrength;
182 case "varDirection":
183 return m_varDirection;
184 case "rateChange":
185 return m_rateChange;
186 default:
187 throw new Exception(String.Format("Unknown {0} parameter {1}", this.Name, param));
188
189 }
190 }
191
192
193
194 #endregion
195
196
197 private void LogSettings()
198 {
199 m_log.InfoFormat("[ConfigurableWind] Average Strength : {0}", m_avgStrength);
200 m_log.InfoFormat("[ConfigurableWind] Average Direction : {0}", m_avgDirection);
201 m_log.InfoFormat("[ConfigurableWind] Varience Strength : {0}", m_varStrength);
202 m_log.InfoFormat("[ConfigurableWind] Varience Direction : {0}", m_varDirection);
203 m_log.InfoFormat("[ConfigurableWind] Rate Change : {0}", m_rateChange);
204 }
205
206 #region IWindModelPlugin Members
207
208
209 #endregion
210 }
211}
diff --git a/OpenSim/Region/CoreModules/World/Wind/Plugins/SimpleRandomWind.cs b/OpenSim/Region/CoreModules/World/Wind/Plugins/SimpleRandomWind.cs
new file mode 100644
index 0000000..040a3c4
--- /dev/null
+++ b/OpenSim/Region/CoreModules/World/Wind/Plugins/SimpleRandomWind.cs
@@ -0,0 +1,139 @@
1using System;
2using System.Collections.Generic;
3
4using OpenMetaverse;
5
6
7namespace OpenSim.Region.CoreModules.World.Wind.Plugins
8{
9 class SimpleRandomWind : Mono.Addins.TypeExtensionNode, IWindModelPlugin
10 {
11 private Vector2[] m_windSpeeds = new Vector2[16 * 16];
12 private float m_strength = 1.0f;
13 private Random m_rndnums = new Random(Environment.TickCount);
14
15
16 #region IPlugin Members
17
18 public string Version
19 {
20 get { return "1.0.0.0"; }
21 }
22
23 public string Name
24 {
25 get { return "SimpleRandomWind"; }
26 }
27
28 public void Initialise()
29 {
30
31 }
32
33 #endregion
34
35 #region IDisposable Members
36
37 public void Dispose()
38 {
39 m_windSpeeds = null;
40 }
41
42 #endregion
43
44 #region IWindModelPlugin Members
45
46 public void WindConfig(OpenSim.Region.Framework.Scenes.Scene scene, Nini.Config.IConfig windConfig)
47 {
48 if( windConfig != null )
49 {
50 if( windConfig.Contains("strength") )
51 {
52 m_strength = windConfig.GetFloat("strength", 1.0F);
53 }
54 }
55 }
56
57 public void WindUpdate(uint frame)
58 {
59 for (int y = 0; y < 16; y++)
60 {
61 for (int x = 0; x < 16; x++)
62 {
63 m_windSpeeds[y * 16 + x].X = (float)(m_rndnums.NextDouble() * 2d - 1d); // -1 to 1
64 m_windSpeeds[y * 16 + x].Y = (float)(m_rndnums.NextDouble() * 2d - 1d); // -1 to 1
65 m_windSpeeds[y * 16 + x].X *= m_strength;
66 m_windSpeeds[y * 16 + x].Y *= m_strength;
67 }
68 }
69 }
70
71 public Vector3 WindSpeed(float fX, float fY, float fZ)
72 {
73 Vector3 windVector = new Vector3(0.0f, 0.0f, 0.0f);
74
75 int x = (int)fX / 16;
76 int y = (int)fY / 16;
77
78 if (x < 0) x = 0;
79 if (x > 15) x = 15;
80 if (y < 0) y = 0;
81 if (y > 15) y = 15;
82
83 if (m_windSpeeds != null)
84 {
85 windVector.X = m_windSpeeds[y * 16 + x].X;
86 windVector.Y = m_windSpeeds[y * 16 + x].Y;
87 }
88
89 return windVector;
90
91 }
92
93 public Vector2[] WindLLClientArray()
94 {
95 return m_windSpeeds;
96 }
97
98 public string Description
99 {
100 get
101 {
102 return "Provides a simple wind model that creates random wind of a given strength in 16m x 16m patches.";
103 }
104 }
105
106 public System.Collections.Generic.Dictionary<string, string> WindParams()
107 {
108 Dictionary<string, string> Params = new Dictionary<string, string>();
109
110 Params.Add("strength", "wind strength");
111
112 return Params;
113 }
114
115 public void WindParamSet(string param, float value)
116 {
117 switch (param)
118 {
119 case "strength":
120 m_strength = value;
121 break;
122 }
123 }
124
125 public float WindParamGet(string param)
126 {
127 switch (param)
128 {
129 case "strength":
130 return m_strength;
131 default:
132 throw new Exception(String.Format("Unknown {0} parameter {1}", this.Name, param));
133 }
134 }
135
136 #endregion
137
138 }
139}
diff --git a/OpenSim/Region/CoreModules/World/Wind/WindModule.cs b/OpenSim/Region/CoreModules/World/Wind/WindModule.cs
index 87e6fd9..26901a4 100644
--- a/OpenSim/Region/CoreModules/World/Wind/WindModule.cs
+++ b/OpenSim/Region/CoreModules/World/Wind/WindModule.cs
@@ -27,57 +27,125 @@
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Reflection;
31using log4net;
32using Mono.Addins;
30using Nini.Config; 33using Nini.Config;
31using OpenMetaverse; 34using OpenMetaverse;
32using OpenSim.Framework; 35using OpenSim.Framework;
33using OpenSim.Region.Framework.Interfaces; 36using OpenSim.Region.Framework.Interfaces;
34using OpenSim.Region.Framework.Scenes; 37using OpenSim.Region.Framework.Scenes;
35 38
39using OpenSim.Region.CoreModules.World.Wind;
40
36namespace OpenSim.Region.CoreModules 41namespace OpenSim.Region.CoreModules
37{ 42{
38 public class WindModule : IWindModule 43 public class WindModule : IWindModule
39 { 44 {
40// private static readonly log4net.ILog m_log 45 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
41// = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
42 46
43 private int m_frame = 0; 47 private uint m_frame = 0;
44 private int m_frame_mod = 150; 48 private uint m_frameLastUpdateClientArray = 0;
49 private int m_frameUpdateRate = 150;
45 private Random m_rndnums = new Random(Environment.TickCount); 50 private Random m_rndnums = new Random(Environment.TickCount);
46 private Scene m_scene = null; 51 private Scene m_scene = null;
47 private bool m_ready = false; 52 private bool m_ready = false;
48 private float m_strength = 1.0F; 53
49 private bool m_enabled = true; 54 private bool m_enabled = true;
50 55
56 private IWindModelPlugin m_activeWindPlugin = null;
57 private const string m_dWindPluginName = "SimpleRandomWind";
58 private Dictionary<string, IWindModelPlugin> m_availableWindPlugins = new Dictionary<string, IWindModelPlugin>();
59
51 // Simplified windSpeeds based on the fact that the client protocal tracks at a resolution of 16m 60 // Simplified windSpeeds based on the fact that the client protocal tracks at a resolution of 16m
52 private Vector2[] windSpeeds = new Vector2[16 * 16]; 61 private Vector2[] windSpeeds = new Vector2[16 * 16];
53 62
54 private Dictionary<UUID, ulong> m_rootAgents = new Dictionary<UUID, ulong>(); 63 #region IRegion Methods
55 64
56 public void Initialise(Scene scene, IConfigSource config) 65 public void Initialise(Scene scene, IConfigSource config)
57 { 66 {
58 IConfig windConfig = config.Configs["Wind"]; 67 IConfig windConfig = config.Configs["Wind"];
68 string desiredWindPlugin = m_dWindPluginName;
59 69
60 if (windConfig != null) 70 if (windConfig != null)
61 { 71 {
62 m_enabled = windConfig.GetBoolean("enabled", true); 72 m_enabled = windConfig.GetBoolean("enabled", true);
63 m_strength = windConfig.GetFloat("strength", 1.0F); 73
74 m_frameUpdateRate = windConfig.GetInt("wind_update_rate", 150);
75
76 // Determine which wind model plugin is desired
77 if (windConfig.Contains("wind_plugin"))
78 {
79 desiredWindPlugin = windConfig.GetString("wind_plugin");
80 }
64 } 81 }
65 82
66 if (m_enabled) 83 if (m_enabled)
67 { 84 {
85 m_log.InfoFormat("[WIND] Enabled with an update rate of {0} frames.", m_frameUpdateRate);
68 86
69 m_scene = scene; 87 m_scene = scene;
70 m_frame = 0; 88 m_frame = 0;
71 89
90 // Register all the Wind Model Plug-ins
91 foreach (IWindModelPlugin windPlugin in AddinManager.GetExtensionObjects("/OpenSim/WindModule"))
92 {
93 m_log.InfoFormat("[WIND] Found Plugin: {0}", windPlugin.Name);
94 m_availableWindPlugins.Add(windPlugin.Name, windPlugin);
95 }
96
97 // Check for desired plugin
98 if (m_availableWindPlugins.ContainsKey(desiredWindPlugin))
99 {
100 m_activeWindPlugin = m_availableWindPlugins[desiredWindPlugin];
101
102 m_log.InfoFormat("[WIND] {0} plugin found, initializing.", desiredWindPlugin);
103
104 if (windConfig != null)
105 {
106 m_activeWindPlugin.Initialise();
107 m_activeWindPlugin.WindConfig(m_scene, windConfig);
108 }
109 }
110
111
112 // if the plug-in wasn't found, default to no wind.
113 if (m_activeWindPlugin == null)
114 {
115 m_log.ErrorFormat("[WIND] Could not find specified wind plug-in: {0}", desiredWindPlugin);
116 m_log.ErrorFormat("[WIND] Defaulting to no wind.");
117 }
72 118
73 scene.EventManager.OnFrame += WindUpdate; 119 // This one puts an entry in the main help screen
74 scene.EventManager.OnMakeChildAgent += MakeChildAgent; 120 m_scene.AddCommand(this, String.Empty, "wind", "Usage: wind <plugin> <param> [value] - Get or Update Wind paramaters", null);
75 scene.EventManager.OnAvatarEnteringNewParcel += AvatarEnteringParcel; 121
76 scene.EventManager.OnClientClosed += ClientLoggedOut; 122 // This one enables the ability to type just the base command without any parameters
77 scene.RegisterModuleInterface<IWindModule>(this); 123 m_scene.AddCommand(this, "wind", "", "", HandleConsoleCommand);
78 124
125 // Get a list of the parameters for each plugin
126 foreach (IWindModelPlugin windPlugin in m_availableWindPlugins.Values)
127 {
128 m_scene.AddCommand(this, String.Format("wind base wind_plugin {0}", windPlugin.Name), String.Format("{0} - {1}", windPlugin.Name, windPlugin.Description), "", HandleConsoleBaseCommand);
129 m_scene.AddCommand(this, String.Format("wind base wind_update_rate"), "Change the wind update rate.", "", HandleConsoleBaseCommand);
130
131 foreach (KeyValuePair<string, string> kvp in windPlugin.WindParams())
132 {
133 m_scene.AddCommand(this, String.Format("wind {0} {1}", windPlugin.Name, kvp.Key), String.Format("{0} : {1} - {2}", windPlugin.Name, kvp.Key, kvp.Value), "", HandleConsoleParamCommand);
134 }
135 }
136
137
138 // Register event handlers for when Avatars enter the region, and frame ticks
139 m_scene.EventManager.OnFrame += WindUpdate;
140 m_scene.EventManager.OnMakeRootAgent += OnAgentEnteredRegion;
141
142 // Register the wind module
143 m_scene.RegisterModuleInterface<IWindModule>(this);
144
145 // Generate initial wind values
79 GenWindPos(); 146 GenWindPos();
80 147
148 // Mark Module Ready for duty
81 m_ready = true; 149 m_ready = true;
82 150
83 } 151 }
@@ -93,12 +161,19 @@ namespace OpenSim.Region.CoreModules
93 if (m_enabled) 161 if (m_enabled)
94 { 162 {
95 m_ready = false; 163 m_ready = false;
164
165 // REVIEW: If a region module is closed, is there a possibility that it'll re-open/initialize ??
166 m_activeWindPlugin = null;
167 foreach (IWindModelPlugin windPlugin in m_availableWindPlugins.Values)
168 {
169 windPlugin.Dispose();
170 }
171
172 m_availableWindPlugins.Clear();
173
96 // Remove our hooks 174 // Remove our hooks
97 m_scene.EventManager.OnFrame -= WindUpdate; 175 m_scene.EventManager.OnFrame -= WindUpdate;
98 // m_scene.EventManager.OnNewClient -= SunToClient; 176 m_scene.EventManager.OnMakeRootAgent -= OnAgentEnteredRegion;
99 m_scene.EventManager.OnMakeChildAgent -= MakeChildAgent;
100 m_scene.EventManager.OnAvatarEnteringNewParcel -= AvatarEnteringParcel;
101 m_scene.EventManager.OnClientClosed -= ClientLoggedOut;
102 } 177 }
103 } 178 }
104 179
@@ -112,144 +187,279 @@ namespace OpenSim.Region.CoreModules
112 get { return false; } 187 get { return false; }
113 } 188 }
114 189
115 /// <summary>
116 /// Retrieve the wind speed at the given region coordinate. This
117 /// implimentation ignores Z.
118 /// </summary>
119 /// <param name="x">0...255</param>
120 /// <param name="y">0...255</param>
121 /// <returns></returns>
122 public Vector3 WindSpeed(int x, int y, int z)
123 {
124 Vector3 windVector = new Vector3(0.0f, 0.0f, 0.0f);
125
126 x /= 16;
127 y /= 16;
128 if (x < 0) x = 0;
129 if (x > 15) x = 15;
130 if (y < 0) y = 0;
131 if (y > 15) y = 15;
132 190
133 if (windSpeeds != null) 191 #endregion
192
193 #region Console Commands
194 private void ValidateConsole()
195 {
196 if (m_scene.ConsoleScene() == null)
134 { 197 {
135 windVector.X = windSpeeds[y * 16 + x].X; 198 // FIXME: If console region is root then this will be printed by every module. Currently, there is no
136 windVector.Y = windSpeeds[y * 16 + x].Y; 199 // way to prevent this, short of making the entire module shared (which is complete overkill).
200 // One possibility is to return a bool to signal whether the module has completely handled the command
201 m_log.InfoFormat("[WIND]: Please change to a specific region in order to set Sun parameters.");
202 return;
137 } 203 }
138 204
205 if (m_scene.ConsoleScene() != m_scene)
206 {
207 m_log.InfoFormat("[WIND]: Console Scene is not my scene.");
208 return;
209 }
210 }
139 211
140 return windVector; 212 /// <summary>
213 /// Base console command handler, only used if a person specifies the base command with now options
214 /// </summary>
215 private void HandleConsoleCommand(string module, string[] cmdparams)
216 {
217 ValidateConsole();
218 m_log.Info("[WIND] The wind command can be used to change the currently active wind model plugin and update the parameters for wind plugins.");
141 } 219 }
142 220
143 public void WindToClient(IClientAPI client) 221 /// <summary>
222 /// Called to change the active wind model plugin
223 /// </summary>
224 private void HandleConsoleBaseCommand(string module, string[] cmdparams)
144 { 225 {
145 if (m_ready) 226 ValidateConsole();
227
228 if( (cmdparams.Length != 4)
229 || !cmdparams[1].Equals("base")
230 )
146 { 231 {
147 //if (!sunFixed) 232 m_log.Info("[WIND] Invalid parameters to change parameters for Wind module base, usage: wind base <parameter> <value>");
148 //GenWindPos(); // Generate shared values once 233 return;
149 client.SendWindData(windSpeeds);
150 } 234 }
235
236 switch (cmdparams[2])
237 {
238 case "wind_update_rate":
239 int newRate = 1;
240
241 if (int.TryParse(cmdparams[3], out newRate))
242 {
243 m_frameUpdateRate = newRate;
244 }
245 else
246 {
247 m_log.InfoFormat("[WIND] Invalid value {0} specified for {1}", cmdparams[3], cmdparams[2]);
248 return;
249 }
250
251 break;
252 case "wind_plugin":
253 string desiredPlugin = cmdparams[3];
254
255 if (desiredPlugin.Equals(m_activeWindPlugin.Name))
256 {
257 m_log.InfoFormat("[WIND] Wind model plugin {0} is already active", cmdparams[3]);
258 return;
259 }
260
261 if (m_availableWindPlugins.ContainsKey(desiredPlugin))
262 {
263 m_activeWindPlugin = m_availableWindPlugins[cmdparams[3]];
264 m_log.InfoFormat("[WIND] {0} wind model plugin now active", m_activeWindPlugin.Name);
265 }
266 else
267 {
268 m_log.InfoFormat("[WIND] Could not find wind model plugin {0}", desiredPlugin);
269 }
270 break;
271 }
272
151 } 273 }
152 274
153 public void WindUpdate() 275 /// <summary>
276 /// Called to change plugin parameters.
277 /// </summary>
278 private void HandleConsoleParamCommand(string module, string[] cmdparams)
154 { 279 {
155 if (((m_frame++ % m_frame_mod) != 0) || !m_ready) 280 ValidateConsole();
281
282 // wind <plugin> <param> [value]
283 if ((cmdparams.Length != 4)
284 && (cmdparams.Length != 3))
156 { 285 {
286 m_log.Info("[WIND] Usage: wind <plugin> <param> [value]");
157 return; 287 return;
158 } 288 }
159 //m_log.Debug("[WIND]:Regenerating...");
160 GenWindPos(); // Generate shared values once
161 289
162 //int spotxp = 0; 290 string plugin = cmdparams[1];
163 //int spotyp = 0; 291 string param = cmdparams[2];
164 //int spotxm = 0; 292 float value = 0f;
165 //int spotym = 0; 293 if (cmdparams.Length == 4)
166 List<ScenePresence> avatars = m_scene.GetAvatars();
167 foreach (ScenePresence avatar in avatars)
168 { 294 {
169 if (!avatar.IsChildAgent) 295 if (!float.TryParse(cmdparams[3], out value))
170 { 296 {
171 avatar.ControllingClient.SendWindData(windSpeeds); 297 m_log.InfoFormat("[WIND] Invalid value {0}", cmdparams[3]);
172 } 298 }
173 }
174 299
175 // set estate settings for region access to sun position 300 try
176 //m_scene.RegionInfo.RegionSettings.SunVector = Position; 301 {
177 //m_scene.RegionInfo.EstateSettings.sunHour = GetLindenEstateHourFromCurrentTime(); 302 WindParamSet(plugin, param, value);
178 } 303 }
179 304 catch (Exception e)
180 public void ForceWindUpdateToAllClients() 305 {
181 { 306 m_log.InfoFormat("[WIND] {0}", e.Message);
182 GenWindPos(); // Generate shared values once 307 }
183 308 }
184 List<ScenePresence> avatars = m_scene.GetAvatars(); 309 else
185 foreach (ScenePresence avatar in avatars)
186 { 310 {
187 if (!avatar.IsChildAgent) 311 try
188 avatar.ControllingClient.SendWindData(windSpeeds); 312 {
313 value = WindParamGet(plugin, param);
314 m_log.InfoFormat("[WIND] {0} : {1}", param, value);
315 }
316 catch (Exception e)
317 {
318 m_log.InfoFormat("[WIND] {0}", e.Message);
319 }
189 } 320 }
190 321
191 // set estate settings for region access to sun position
192 //m_scene.RegionInfo.RegionSettings.SunVector = Position;
193 //m_scene.RegionInfo.RegionSettings.SunPosition = GetLindenEstateHourFromCurrentTime();
194 } 322 }
323 #endregion
324
325
326 #region IWindModule Methods
327
195 /// <summary> 328 /// <summary>
196 /// Calculate the sun's orbital position and its velocity. 329 /// Retrieve the wind speed at the given region coordinate. This
330 /// implimentation ignores Z.
197 /// </summary> 331 /// </summary>
332 /// <param name="x">0...255</param>
333 /// <param name="y">0...255</param>
334 public Vector3 WindSpeed(int x, int y, int z)
335 {
336 if (m_activeWindPlugin != null)
337 {
338 return m_activeWindPlugin.WindSpeed(x, y, z);
339 }
340 else
341 {
342 return new Vector3(0.0f, 0.0f, 0.0f);
343 }
344 }
198 345
199 private void GenWindPos() 346 public void WindParamSet(string plugin, string param, float value)
200 { 347 {
201 for (int y = 0; y < 16; y++) 348 if (m_availableWindPlugins.ContainsKey(plugin))
202 { 349 {
203 for (int x = 0; x < 16; x++) 350 IWindModelPlugin windPlugin = m_availableWindPlugins[plugin];
204 { 351 windPlugin.WindParamSet(param, value);
205 windSpeeds[y * 16 + x].X = (float)(m_rndnums.NextDouble() * 2d - 1d); // -1 to 1 352 m_log.InfoFormat("[WIND] {0} set to {1}", param, value);
206 windSpeeds[y * 16 + x].Y = (float)(m_rndnums.NextDouble() * 2d - 1d); // -1 to 1 353 }
207 windSpeeds[y * 16 + x].X *= m_strength; 354 else
208 windSpeeds[y * 16 + x].Y *= m_strength; 355 {
209 } 356 throw new Exception(String.Format("Could not find plugin {0}", plugin));
210 } 357 }
358
211 } 359 }
212 360
213 private void ClientLoggedOut(UUID AgentId) 361 public float WindParamGet(string plugin, string param)
214 { 362 {
215 lock (m_rootAgents) 363 if (m_availableWindPlugins.ContainsKey(plugin))
216 { 364 {
217 if (m_rootAgents.ContainsKey(AgentId)) 365 IWindModelPlugin windPlugin = m_availableWindPlugins[plugin];
218 { 366 return windPlugin.WindParamGet(param);
219 m_rootAgents.Remove(AgentId); 367 }
220 } 368 else
369 {
370 throw new Exception(String.Format("Could not find plugin {0}", plugin));
221 } 371 }
222 } 372 }
223 373
224 private void AvatarEnteringParcel(ScenePresence avatar, int localLandID, UUID regionID) 374 public string WindActiveModelPluginName
225 { 375 {
226 lock (m_rootAgents) 376 get
227 { 377 {
228 if (m_rootAgents.ContainsKey(avatar.UUID)) 378 if (m_activeWindPlugin != null)
229 { 379 {
230 m_rootAgents[avatar.UUID] = avatar.RegionHandle; 380 return m_activeWindPlugin.Name;
231 } 381 }
232 else 382 else
233 { 383 {
234 m_rootAgents.Add(avatar.UUID, avatar.RegionHandle); 384 return String.Empty;
235 WindToClient(avatar.ControllingClient);
236 } 385 }
237 } 386 }
238 //m_log.Info("[FRIEND]: " + avatar.Name + " status:" + (!avatar.IsChildAgent).ToString());
239 } 387 }
240 388
241 private void MakeChildAgent(ScenePresence avatar) 389 #endregion
390
391 /// <summary>
392 /// Called on each frame update. Updates the wind model and clients as necessary.
393 /// </summary>
394 public void WindUpdate()
395 {
396 if (((m_frame++ % m_frameUpdateRate) != 0) || !m_ready)
397 {
398 return;
399 }
400
401 GenWindPos();
402
403 SendWindAllClients();
404 }
405
406 public void OnAgentEnteredRegion(ScenePresence avatar)
407 {
408 if (m_ready)
409 {
410 if (m_activeWindPlugin != null)
411 {
412 // Ask wind plugin to generate a LL wind array to be cached locally
413 // Try not to update this too often, as it may involve array copies
414 if (m_frame >= (m_frameLastUpdateClientArray + m_frameUpdateRate))
415 {
416 windSpeeds = m_activeWindPlugin.WindLLClientArray();
417 m_frameLastUpdateClientArray = m_frame;
418 }
419 }
420
421 avatar.ControllingClient.SendWindData(windSpeeds);
422 }
423 }
424
425 private void SendWindAllClients()
242 { 426 {
243 lock (m_rootAgents) 427 if (m_ready)
244 { 428 {
245 if (m_rootAgents.ContainsKey(avatar.UUID)) 429 List<ScenePresence> avatars = m_scene.GetAvatars();
430
431 if (avatars.Count > 0)
246 { 432 {
247 if (m_rootAgents[avatar.UUID] == avatar.RegionHandle) 433 // Ask wind plugin to generate a LL wind array to be cached locally
434 // Try not to update this too often, as it may involve array copies
435 if (m_frame >= (m_frameLastUpdateClientArray + m_frameUpdateRate))
436 {
437 windSpeeds = m_activeWindPlugin.WindLLClientArray();
438 m_frameLastUpdateClientArray = m_frame;
439 }
440
441 foreach (ScenePresence avatar in avatars)
248 { 442 {
249 m_rootAgents.Remove(avatar.UUID); 443 if (!avatar.IsChildAgent)
444 avatar.ControllingClient.SendWindData(windSpeeds);
250 } 445 }
251 } 446 }
252 } 447 }
253 } 448 }
449 /// <summary>
450 /// Calculate the sun's orbital position and its velocity.
451 /// </summary>
452
453 private void GenWindPos()
454 {
455 if( m_activeWindPlugin != null )
456 {
457 // Tell Wind Plugin to update it's wind data
458 m_activeWindPlugin.WindUpdate(m_frame);
459 }
460 }
461
462
463
254 } 464 }
255} 465}