OpenSim
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros
POSScene.cs
Go to the documentation of this file.
1 /*
2  * Copyright (c) Contributors, http://opensimulator.org/
3  * See CONTRIBUTORS.TXT for a full list of copyright holders.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  * * Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * * Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * * Neither the name of the OpenSimulator Project nor the
13  * names of its contributors may be used to endorse or promote products
14  * derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 using System;
29 using System.Collections.Generic;
30 using Nini.Config;
31 using OpenMetaverse;
32 using Mono.Addins;
33 using OpenSim.Framework;
34 using OpenSim.Region.PhysicsModules.SharedBase;
35 using OpenSim.Region.Framework.Scenes;
36 using OpenSim.Region.Framework.Interfaces;
37 
38 namespace OpenSim.Region.PhysicsModule.POS
39 {
40  [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "POSPhysicsScene")]
42  {
43  private List<POSCharacter> _characters = new List<POSCharacter>();
44  private List<POSPrim> _prims = new List<POSPrim>();
45  private float[] _heightMap;
46  private const float gravity = -9.8f;
47 
48  private bool m_Enabled = false;
49  //protected internal string sceneIdentifier;
50 
51  #region INonSharedRegionModule
52  public string Name
53  {
54  get { return "POS"; }
55  }
56 
57  public Type ReplaceableInterface
58  {
59  get { return null; }
60  }
61 
62  public void Initialise(IConfigSource source)
63  {
64  // TODO: Move this out of Startup
65  IConfig config = source.Configs["Startup"];
66  if (config != null)
67  {
68  string physics = config.GetString("physics", string.Empty);
69  if (physics == Name)
70  m_Enabled = true;
71  }
72 
73  }
74 
75  public void Close()
76  {
77  }
78 
79  public void AddRegion(Scene scene)
80  {
81  if (!m_Enabled)
82  return;
83 
84  EngineType = Name;
85  PhysicsSceneName = EngineType + "/" + scene.RegionInfo.RegionName;
86 
87  scene.RegisterModuleInterface<PhysicsScene>(this);
88  base.Initialise(scene.PhysicsRequestAsset,
89  (scene.Heightmap != null ? scene.Heightmap.GetFloatsSerialised() : new float[Constants.RegionSize * Constants.RegionSize]),
91 
92  }
93 
94  public void RemoveRegion(Scene scene)
95  {
96  if (!m_Enabled)
97  return;
98  }
99 
100  public void RegionLoaded(Scene scene)
101  {
102  if (!m_Enabled)
103  return;
104  }
105  #endregion
106 
107  public override void Dispose()
108  {
109  }
110 
111  public override PhysicsActor AddAvatar(
112  string avName, Vector3 position, Vector3 velocity, Vector3 size, bool isFlying)
113  {
114  POSCharacter act = new POSCharacter();
115  act.Position = position;
116  act.Flying = isFlying;
117  _characters.Add(act);
118  return act;
119  }
120 
121  public override void RemovePrim(PhysicsActor prim)
122  {
123  POSPrim p = (POSPrim) prim;
124  if (_prims.Contains(p))
125  {
126  _prims.Remove(p);
127  }
128  }
129 
130  public override void RemoveAvatar(PhysicsActor character)
131  {
132  POSCharacter act = (POSCharacter) character;
133  if (_characters.Contains(act))
134  {
135  _characters.Remove(act);
136  }
137  }
138 
139 /*
140  public override PhysicsActor AddPrim(Vector3 position, Vector3 size, Quaternion rotation)
141  {
142  return null;
143  }
144 */
145 
146  public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position,
147  Vector3 size, Quaternion rotation, bool isPhysical, uint localid)
148  {
149  POSPrim prim = new POSPrim();
150  prim.Position = position;
151  prim.Orientation = rotation;
152  prim.Size = size;
153  _prims.Add(prim);
154  return prim;
155  }
156 
157  private bool isColliding(POSCharacter c, POSPrim p)
158  {
159  Vector3 rotatedPos = new Vector3(c.Position.X - p.Position.X, c.Position.Y - p.Position.Y,
160  c.Position.Z - p.Position.Z) * Quaternion.Inverse(p.Orientation);
161  Vector3 avatarSize = new Vector3(c.Size.X, c.Size.Y, c.Size.Z) * Quaternion.Inverse(p.Orientation);
162 
163  return (Math.Abs(rotatedPos.X) < (p.Size.X*0.5 + Math.Abs(avatarSize.X)) &&
164  Math.Abs(rotatedPos.Y) < (p.Size.Y*0.5 + Math.Abs(avatarSize.Y)) &&
165  Math.Abs(rotatedPos.Z) < (p.Size.Z*0.5 + Math.Abs(avatarSize.Z)));
166  }
167 
168  private bool isCollidingWithPrim(POSCharacter c)
169  {
170  foreach (POSPrim p in _prims)
171  {
172  if (isColliding(c, p))
173  {
174  return true;
175  }
176  }
177 
178  return false;
179  }
180 
181  public override void AddPhysicsActorTaint(PhysicsActor prim)
182  {
183  }
184 
185  public override float Simulate(float timeStep)
186  {
187  float fps = 0;
188  for (int i = 0; i < _characters.Count; ++i)
189  {
190  fps++;
191  POSCharacter character = _characters[i];
192 
193  float oldposX = character.Position.X;
194  float oldposY = character.Position.Y;
195  float oldposZ = character.Position.Z;
196 
197  if (!character.Flying)
198  {
199  character._target_velocity.Z += gravity * timeStep;
200  }
201 
202  Vector3 characterPosition = character.Position;
203 
204  characterPosition.X += character._target_velocity.X * timeStep;
205  characterPosition.Y += character._target_velocity.Y * timeStep;
206 
207  characterPosition.X = Util.Clamp(character.Position.X, 0.01f, Constants.RegionSize - 0.01f);
208  characterPosition.Y = Util.Clamp(character.Position.Y, 0.01f, Constants.RegionSize - 0.01f);
209 
210  bool forcedZ = false;
211 
212  float terrainheight = _heightMap[(int)character.Position.Y * Constants.RegionSize + (int)character.Position.X];
213  if (character.Position.Z + (character._target_velocity.Z * timeStep) < terrainheight + 2)
214  {
215  characterPosition.Z = terrainheight + character.Size.Z;
216  forcedZ = true;
217  }
218  else
219  {
220  characterPosition.Z += character._target_velocity.Z*timeStep;
221  }
222 
226 
227  if (isCollidingWithPrim(character))
228  {
229  characterPosition.Z = oldposZ; // first try Z axis
230  if (isCollidingWithPrim(character))
231  {
232  characterPosition.Z = oldposZ + character.Size.Z / 4.4f; // try harder
233  if (isCollidingWithPrim(character))
234  {
235  characterPosition.Z = oldposZ + character.Size.Z / 2.2f; // try very hard
236  if (isCollidingWithPrim(character))
237  {
238  characterPosition.X = oldposX;
239  characterPosition.Y = oldposY;
240  characterPosition.Z = oldposZ;
241 
242  characterPosition.X += character._target_velocity.X * timeStep;
243  if (isCollidingWithPrim(character))
244  {
245  characterPosition.X = oldposX;
246  }
247 
248  characterPosition.Y += character._target_velocity.Y * timeStep;
249  if (isCollidingWithPrim(character))
250  {
251  characterPosition.Y = oldposY;
252  }
253  }
254  else
255  {
256  forcedZ = true;
257  }
258  }
259  else
260  {
261  forcedZ = true;
262  }
263  }
264  else
265  {
266  forcedZ = true;
267  }
268  }
269 
270  characterPosition.X = Util.Clamp(character.Position.X, 0.01f, Constants.RegionSize - 0.01f);
271  characterPosition.Y = Util.Clamp(character.Position.Y, 0.01f, Constants.RegionSize - 0.01f);
272 
273  character.Position = characterPosition;
274 
275  character._velocity.X = (character.Position.X - oldposX)/timeStep;
276  character._velocity.Y = (character.Position.Y - oldposY)/timeStep;
277 
278  if (forcedZ)
279  {
280  character._velocity.Z = 0;
281  character._target_velocity.Z = 0;
282  ((PhysicsActor)character).IsColliding = true;
283  character.RequestPhysicsterseUpdate();
284  }
285  else
286  {
287  ((PhysicsActor)character).IsColliding = false;
288  character._velocity.Z = (character.Position.Z - oldposZ)/timeStep;
289  }
290  }
291  return 1.0f;
292  }
293 
294  public override void GetResults()
295  {
296  }
297 
298  public override bool IsThreaded
299  {
300  // for now we won't be multithreaded
301  get { return (false); }
302  }
303 
304  public override void SetTerrain(float[] heightMap)
305  {
306  _heightMap = heightMap;
307  }
308 
309  public override void DeleteTerrain()
310  {
311  }
312 
313  public override void SetWaterLevel(float baseheight)
314  {
315  }
316 
317  public override Dictionary<uint, float> GetTopColliders()
318  {
319  Dictionary<uint, float> returncolliders = new Dictionary<uint, float>();
320  return returncolliders;
321  }
322  }
323 }
override void SetWaterLevel(float baseheight)
Definition: POSScene.cs:313
override void RemoveAvatar(PhysicsActor character)
Remove an avatar.
Definition: POSScene.cs:130
void Initialise(IConfigSource source)
This is called to initialize the region module. For shared modules, this is called exactly once...
Definition: POSScene.cs:62
override void SetTerrain(float[] heightMap)
Definition: POSScene.cs:304
override Dictionary< uint, float > GetTopColliders()
Definition: POSScene.cs:317
RegionSettings RegionSettings
Definition: RegionInfo.cs:290
void Close()
This is the inverse to Initialise. After a Close(), this instance won't be usable anymore...
Definition: POSScene.cs:75
OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion rotation
Definition: ICM_Api.cs:32
override PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 velocity, Vector3 size, bool isFlying)
Add an avatar
Definition: POSScene.cs:111
override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position, Vector3 size, Quaternion rotation, bool isPhysical, uint localid)
Definition: POSScene.cs:146
void AddRegion(Scene scene)
This is called whenever a Scene is added. For shared modules, this can happen several times...
Definition: POSScene.cs:79
void RemoveRegion(Scene scene)
This is called whenever a Scene is removed. For shared modules, this can happen several times...
Definition: POSScene.cs:94
void RegionLoaded(Scene scene)
This will be called once for every scene loaded. In a shared module this will be multiple times in on...
Definition: POSScene.cs:100
override void RemovePrim(PhysicsActor prim)
Remove a prim.
Definition: POSScene.cs:121
override void AddPhysicsActorTaint(PhysicsActor prim)
Definition: POSScene.cs:181
override float Simulate(float timeStep)
Perform a simulation of the current physics scene over the given timestep.
Definition: POSScene.cs:185