aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/PhysicsModules/POS/POSScene.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/PhysicsModules/POS/POSScene.cs')
-rw-r--r--OpenSim/Region/PhysicsModules/POS/POSScene.cs323
1 files changed, 323 insertions, 0 deletions
diff --git a/OpenSim/Region/PhysicsModules/POS/POSScene.cs b/OpenSim/Region/PhysicsModules/POS/POSScene.cs
new file mode 100644
index 0000000..6375f18
--- /dev/null
+++ b/OpenSim/Region/PhysicsModules/POS/POSScene.cs
@@ -0,0 +1,323 @@
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
28using System;
29using System.Collections.Generic;
30using Nini.Config;
31using OpenMetaverse;
32using Mono.Addins;
33using OpenSim.Framework;
34using OpenSim.Region.PhysicsModules.SharedBase;
35using OpenSim.Region.Framework.Scenes;
36using OpenSim.Region.Framework.Interfaces;
37
38namespace OpenSim.Region.PhysicsModule.POS
39{
40 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "POSPhysicsScene")]
41 public class POSScene : PhysicsScene, INonSharedRegionModule
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]),
90 (float)scene.RegionInfo.RegionSettings.WaterHeight);
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
223 /// this is it -- the magic you've all been waiting for! Ladies and gentlemen --
224 /// Completely Bogus Collision Detection!!!
225 /// better known as the CBCD algorithm
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 fps;
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}