aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region
diff options
context:
space:
mode:
authorMelanie2012-03-04 16:23:46 +0000
committerMelanie2012-03-04 16:23:46 +0000
commit182f5efbe94881c22af82bc71566c49dd02ed8f8 (patch)
tree2b26c2657cfb91464008d8e305566500bc3cdd9e /OpenSim/Region
parentMerge branch 'master' into careminster (diff)
parentZero velocity when drag-copying (diff)
downloadopensim-SC_OLD-182f5efbe94881c22af82bc71566c49dd02ed8f8.zip
opensim-SC_OLD-182f5efbe94881c22af82bc71566c49dd02ed8f8.tar.gz
opensim-SC_OLD-182f5efbe94881c22af82bc71566c49dd02ed8f8.tar.bz2
opensim-SC_OLD-182f5efbe94881c22af82bc71566c49dd02ed8f8.tar.xz
Merge branch 'master' of ssh://melanie@3dhosting.de/var/git/careminster into careminster
Diffstat (limited to 'OpenSim/Region')
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs4
-rw-r--r--OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs17
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs6
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs6
-rw-r--r--OpenSim/Region/Framework/Scenes/KeyframeMotion.cs422
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs6
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneGraph.cs11
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs44
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs115
-rw-r--r--OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs34
-rw-r--r--OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs5
-rw-r--r--OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs163
-rw-r--r--OpenSim/Region/Physics/ChOdePlugin/OdePlugin.cs28
-rw-r--r--OpenSim/Region/Physics/UbitOdePlugin/ODEDynamics.cs110
-rw-r--r--OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs321
-rw-r--r--OpenSim/Region/Physics/UbitOdePlugin/OdeApi.cs1
-rw-r--r--OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs514
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs164
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs13
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs12
22 files changed, 1305 insertions, 695 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
index 2e86315..f835e56 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
@@ -4845,7 +4845,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4845 if (part != null && part != part.ParentGroup.RootPart) 4845 if (part != null && part != part.ParentGroup.RootPart)
4846 { 4846 {
4847 position = part.OffsetPosition + presence.OffsetPosition * part.RotationOffset; 4847 position = part.OffsetPosition + presence.OffsetPosition * part.RotationOffset;
4848 rotation = presence.Rotation * part.RotationOffset; 4848 rotation = part.RotationOffset * presence.Rotation;
4849 } 4849 }
4850 } 4850 }
4851 4851
@@ -4974,7 +4974,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4974 if (part != null && part != part.ParentGroup.RootPart) 4974 if (part != null && part != part.ParentGroup.RootPart)
4975 { 4975 {
4976 offsetPosition = part.OffsetPosition + data.OffsetPosition * part.RotationOffset; 4976 offsetPosition = part.OffsetPosition + data.OffsetPosition * part.RotationOffset;
4977 rotation = data.Rotation * part.RotationOffset; 4977 rotation = part.RotationOffset * data.Rotation;
4978 parentID = part.ParentGroup.RootPart.LocalId; 4978 parentID = part.ParentGroup.RootPart.LocalId;
4979 } 4979 }
4980 } 4980 }
diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
index b0cee03..2bebd30 100644
--- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
@@ -551,12 +551,17 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
551 /// <param name="client"></param> 551 /// <param name="client"></param>
552 private void Client_OnRequestWearables(IClientAPI client) 552 private void Client_OnRequestWearables(IClientAPI client)
553 { 553 {
554 // m_log.DebugFormat("[AVFACTORY]: Client_OnRequestWearables called for {0} ({1})", client.Name, client.AgentId); 554 Util.FireAndForget(delegate(object x)
555 ScenePresence sp = m_scene.GetScenePresence(client.AgentId); 555 {
556 if (sp != null) 556 Thread.Sleep(4000);
557 client.SendWearables(sp.Appearance.Wearables, sp.Appearance.Serial++); 557
558 else 558 // m_log.DebugFormat("[AVFACTORY]: Client_OnRequestWearables called for {0} ({1})", client.Name, client.AgentId);
559 m_log.WarnFormat("[AVFACTORY]: Client_OnRequestWearables unable to find presence for {0}", client.AgentId); 559 ScenePresence sp = m_scene.GetScenePresence(client.AgentId);
560 if (sp != null)
561 client.SendWearables(sp.Appearance.Wearables, sp.Appearance.Serial++);
562 else
563 m_log.WarnFormat("[AVFACTORY]: Client_OnRequestWearables unable to find presence for {0}", client.AgentId);
564 });
560 } 565 }
561 566
562 /// <summary> 567 /// <summary>
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
index 2498705..60a8f86 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
@@ -1746,6 +1746,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1746 if (grp.RootPart.PhysActor != null) 1746 if (grp.RootPart.PhysActor != null)
1747 { 1747 {
1748 grp.RootPart.PhysActor.CrossingFailure(); 1748 grp.RootPart.PhysActor.CrossingFailure();
1749 if (grp.RootPart.KeyframeMotion != null)
1750 {
1751 grp.RootPart.Velocity = Vector3.Zero;
1752 grp.RootPart.KeyframeMotion.CrossingFailure();
1753 grp.SendGroupRootTerseUpdate();
1754 }
1749 } 1755 }
1750 } 1756 }
1751 1757
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
index 6c4c63f..192d55f 100644
--- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
@@ -355,6 +355,12 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
355 355
356 foreach (SceneObjectGroup objectGroup in objlist) 356 foreach (SceneObjectGroup objectGroup in objlist)
357 { 357 {
358 if (objectGroup.RootPart.KeyframeMotion != null)
359 objectGroup.RootPart.KeyframeMotion.Stop();
360 objectGroup.RootPart.SetForce(Vector3.Zero);
361 objectGroup.RootPart.SetAngularImpulse(Vector3.Zero, false);
362 objectGroup.RootPart.KeyframeMotion = null;
363
358 Vector3 inventoryStoredPosition = new Vector3 364 Vector3 inventoryStoredPosition = new Vector3
359 (((objectGroup.AbsolutePosition.X > (int)Constants.RegionSize) 365 (((objectGroup.AbsolutePosition.X > (int)Constants.RegionSize)
360 ? 250 366 ? 250
diff --git a/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs b/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs
new file mode 100644
index 0000000..b7b0d27
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs
@@ -0,0 +1,422 @@
1// Proprietary code of Avination Virtual Limited
2// (c) 2012 Melanie Thielker
3//
4
5using System;
6using System.Timers;
7using System.Collections;
8using System.Collections.Generic;
9using System.IO;
10using System.Diagnostics;
11using System.Reflection;
12using System.Threading;
13using OpenMetaverse;
14using OpenSim.Framework;
15using OpenSim.Region.Framework.Interfaces;
16using OpenSim.Region.Physics.Manager;
17using OpenSim.Region.Framework.Scenes.Serialization;
18using System.Runtime.Serialization.Formatters.Binary;
19using System.Runtime.Serialization;
20using Timer = System.Timers.Timer;
21using log4net;
22
23namespace OpenSim.Region.Framework.Scenes
24{
25 [Serializable]
26 public class KeyframeMotion
27 {
28 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
29
30 public enum PlayMode : int
31 {
32 Forward = 0,
33 Reverse = 1,
34 Loop = 2,
35 PingPong = 3
36 };
37
38 [Flags]
39 public enum DataFormat : int
40 {
41 Translation = 1,
42 Rotation = 2
43 }
44
45 [Serializable]
46 public struct Keyframe
47 {
48 public Vector3? Position;
49 public Quaternion? Rotation;
50 public Quaternion StartRotation;
51 public int TimeMS;
52 public int TimeTotal;
53 public Vector3 AngularVelocity;
54 };
55
56 private Vector3 m_basePosition;
57 private Quaternion m_baseRotation;
58 private Vector3 m_serializedPosition;
59
60 private Keyframe m_currentFrame;
61 private List<Keyframe> m_frames = new List<Keyframe>();
62
63 private Keyframe[] m_keyframes;
64
65 [NonSerialized()]
66 protected Timer m_timer = new Timer();
67
68 [NonSerialized()]
69 private SceneObjectGroup m_group;
70
71 private PlayMode m_mode = PlayMode.Forward;
72 private DataFormat m_data = DataFormat.Translation | DataFormat.Rotation;
73
74 private bool m_running = false;
75 [NonSerialized()]
76 private bool m_selected = false;
77
78 private int m_iterations = 0;
79
80 private const double timerInterval = 50.0;
81
82 public DataFormat Data
83 {
84 get { return m_data; }
85 }
86
87 public bool Selected
88 {
89 set
90 {
91 if (value)
92 {
93 // Once we're let go, recompute positions
94 if (m_selected)
95 UpdateSceneObject(m_group);
96 }
97 else
98 {
99 // Save selection position in case we get moved
100 if (!m_selected)
101 m_serializedPosition = m_group.AbsolutePosition;
102 }
103 m_selected = value; }
104 }
105
106 public static KeyframeMotion FromData(SceneObjectGroup grp, Byte[] data)
107 {
108 MemoryStream ms = new MemoryStream(data);
109
110 BinaryFormatter fmt = new BinaryFormatter();
111
112 KeyframeMotion newMotion = (KeyframeMotion)fmt.Deserialize(ms);
113
114 // This will be started when position is updated
115 newMotion.m_timer = new Timer();
116 newMotion.m_timer.Interval = (int)timerInterval;
117 newMotion.m_timer.AutoReset = true;
118 newMotion.m_timer.Elapsed += newMotion.OnTimer;
119
120 return newMotion;
121 }
122
123 public void UpdateSceneObject(SceneObjectGroup grp)
124 {
125 m_group = grp;
126 Vector3 offset = grp.AbsolutePosition - m_serializedPosition;
127
128 m_basePosition += offset;
129 m_currentFrame.Position += offset;
130 for (int i = 0 ; i < m_frames.Count ; i++)
131 {
132 Keyframe k = m_frames[i];
133 k.Position += offset;
134 m_frames[i] = k;
135 }
136
137 if (m_running)
138 Start();
139 }
140
141 public KeyframeMotion(SceneObjectGroup grp, PlayMode mode, DataFormat data)
142 {
143 m_mode = mode;
144 m_data = data;
145
146 m_group = grp;
147 m_basePosition = grp.AbsolutePosition;
148 m_baseRotation = grp.GroupRotation;
149
150 m_timer.Interval = (int)timerInterval;
151 m_timer.AutoReset = true;
152 m_timer.Elapsed += OnTimer;
153 }
154
155 public void SetKeyframes(Keyframe[] frames)
156 {
157 m_keyframes = frames;
158 }
159
160 public void Start()
161 {
162 if (m_keyframes.Length > 0)
163 m_timer.Start();
164 m_running = true;
165 }
166
167 public void Stop()
168 {
169 // Failed object creation
170 if (m_timer == null)
171 return;
172 m_timer.Stop();
173
174 m_basePosition = m_group.AbsolutePosition;
175 m_baseRotation = m_group.GroupRotation;
176
177 m_group.RootPart.Velocity = Vector3.Zero;
178 m_group.RootPart.UpdateAngularVelocity(Vector3.Zero);
179 m_group.SendGroupRootTerseUpdate();
180
181 m_frames.Clear();
182 m_running = false;
183 }
184
185 public void Pause()
186 {
187 m_group.RootPart.Velocity = Vector3.Zero;
188 m_group.RootPart.UpdateAngularVelocity(Vector3.Zero);
189 m_group.SendGroupRootTerseUpdate();
190
191 m_timer.Stop();
192 m_running = false;
193 }
194
195 private void GetNextList()
196 {
197 m_frames.Clear();
198 Vector3 pos = m_basePosition;
199 Quaternion rot = m_baseRotation;
200
201 if (m_mode == PlayMode.Loop || m_mode == PlayMode.PingPong || m_iterations == 0)
202 {
203 int direction = 1;
204 if (m_mode == PlayMode.Reverse || ((m_mode == PlayMode.PingPong) && ((m_iterations & 1) != 0)))
205 direction = -1;
206
207 int start = 0;
208 int end = m_keyframes.Length;
209// if (m_mode == PlayMode.PingPong && m_keyframes.Length > 1)
210// end = m_keyframes.Length - 1;
211
212 if (direction < 0)
213 {
214 start = m_keyframes.Length - 1;
215 end = -1;
216// if (m_mode == PlayMode.PingPong && m_keyframes.Length > 1)
217// end = 0;
218 }
219
220 for (int i = start; i != end ; i += direction)
221 {
222 Keyframe k = m_keyframes[i];
223
224 if (k.Position.HasValue)
225 k.Position = (k.Position * direction) + pos;
226 else
227 k.Position = pos;
228
229 k.StartRotation = rot;
230 if (k.Rotation.HasValue)
231 {
232 if (direction == -1)
233 k.Rotation = Quaternion.Conjugate((Quaternion)k.Rotation);
234 k.Rotation = rot * k.Rotation;
235 }
236 else
237 {
238 k.Rotation = rot;
239 }
240
241 float angle = 0;
242
243 float aa = k.StartRotation.X * k.StartRotation.X + k.StartRotation.Y * k.StartRotation.Y + k.StartRotation.Z * k.StartRotation.Z + k.StartRotation.W * k.StartRotation.W;
244 float bb = ((Quaternion)k.Rotation).X * ((Quaternion)k.Rotation).X + ((Quaternion)k.Rotation).Y * ((Quaternion)k.Rotation).Y + ((Quaternion)k.Rotation).Z * ((Quaternion)k.Rotation).Z + ((Quaternion)k.Rotation).W * ((Quaternion)k.Rotation).W;
245 float aa_bb = aa * bb;
246
247 if (aa_bb == 0)
248 {
249 angle = 0;
250 }
251 else
252 {
253 float ab = k.StartRotation.X * ((Quaternion)k.Rotation).X +
254 k.StartRotation.Y * ((Quaternion)k.Rotation).Y +
255 k.StartRotation.Z * ((Quaternion)k.Rotation).Z +
256 k.StartRotation.W * ((Quaternion)k.Rotation).W;
257 float q = (ab * ab) / aa_bb;
258
259 if (q > 1.0f)
260 {
261 angle = 0;
262 }
263 else
264 {
265 angle = (float)Math.Acos(2 * q - 1);
266 }
267 }
268
269 k.AngularVelocity = (new Vector3(0, 0, 1) * (Quaternion)k.Rotation) * (angle / (k.TimeMS / 1000));
270 k.TimeTotal = k.TimeMS;
271
272 m_frames.Add(k);
273
274 pos = (Vector3)k.Position;
275 rot = (Quaternion)k.Rotation;
276 }
277
278 m_basePosition = pos;
279 m_baseRotation = rot;
280
281 m_iterations++;
282 }
283 }
284
285 protected void OnTimer(object sender, ElapsedEventArgs e)
286 {
287 if (m_frames.Count == 0)
288 {
289 GetNextList();
290
291 if (m_frames.Count == 0)
292 {
293 Stop();
294 return;
295 }
296
297 m_currentFrame = m_frames[0];
298 }
299
300 if (m_selected)
301 {
302 if (m_group.RootPart.Velocity != Vector3.Zero)
303 {
304 m_group.RootPart.Velocity = Vector3.Zero;
305 m_group.SendGroupRootTerseUpdate();
306 }
307 return;
308 }
309
310 // Do the frame processing
311 double steps = (double)m_currentFrame.TimeMS / timerInterval;
312 float complete = ((float)m_currentFrame.TimeTotal - (float)m_currentFrame.TimeMS) / (float)m_currentFrame.TimeTotal;
313
314 if (steps <= 1.0)
315 {
316 m_currentFrame.TimeMS = 0;
317
318 m_group.AbsolutePosition = (Vector3)m_currentFrame.Position;
319 m_group.UpdateGroupRotationR((Quaternion)m_currentFrame.Rotation);
320 }
321 else
322 {
323 Vector3 v = (Vector3)m_currentFrame.Position - m_group.AbsolutePosition;
324 Vector3 motionThisFrame = v / (float)steps;
325 v = v * 1000 / m_currentFrame.TimeMS;
326
327 bool update = false;
328
329 if (Vector3.Mag(motionThisFrame) >= 0.05f)
330 {
331 m_group.AbsolutePosition += motionThisFrame;
332 m_group.RootPart.Velocity = v;
333 update = true;
334 }
335
336 if ((Quaternion)m_currentFrame.Rotation != m_group.GroupRotation)
337 {
338 Quaternion current = m_group.GroupRotation;
339
340 Quaternion step = Quaternion.Slerp(m_currentFrame.StartRotation, (Quaternion)m_currentFrame.Rotation, complete);
341
342 float angle = 0;
343
344 float aa = current.X * current.X + current.Y * current.Y + current.Z * current.Z + current.W * current.W;
345 float bb = step.X * step.X + step.Y * step.Y + step.Z * step.Z + step.W * step.W;
346 float aa_bb = aa * bb;
347
348 if (aa_bb == 0)
349 {
350 angle = 0;
351 }
352 else
353 {
354 float ab = current.X * step.X +
355 current.Y * step.Y +
356 current.Z * step.Z +
357 current.W * step.W;
358 float q = (ab * ab) / aa_bb;
359
360 if (q > 1.0f)
361 {
362 angle = 0;
363 }
364 else
365 {
366 angle = (float)Math.Acos(2 * q - 1);
367 }
368 }
369
370 if (angle > 0.01f)
371 {
372 m_group.UpdateGroupRotationR(step);
373 //m_group.RootPart.UpdateAngularVelocity(m_currentFrame.AngularVelocity / 2);
374 update = true;
375 }
376 }
377
378 if (update)
379 m_group.SendGroupRootTerseUpdate();
380 }
381
382 m_currentFrame.TimeMS -= (int)timerInterval;
383
384 if (m_currentFrame.TimeMS <= 0)
385 {
386 m_group.RootPart.Velocity = Vector3.Zero;
387 m_group.RootPart.UpdateAngularVelocity(Vector3.Zero);
388 m_group.SendGroupRootTerseUpdate();
389
390 m_frames.RemoveAt(0);
391 if (m_frames.Count > 0)
392 m_currentFrame = m_frames[0];
393 }
394 }
395
396 public Byte[] Serialize()
397 {
398 MemoryStream ms = new MemoryStream();
399 m_timer.Stop();
400
401 BinaryFormatter fmt = new BinaryFormatter();
402 SceneObjectGroup tmp = m_group;
403 m_group = null;
404 m_serializedPosition = tmp.AbsolutePosition;
405 fmt.Serialize(ms, this);
406 m_group = tmp;
407 return ms.ToArray();
408 }
409
410 public void CrossingFailure()
411 {
412 // The serialization has stopped the timer, so let's wait a moment
413 // then retry the crossing. We'll get back here if it fails.
414 Util.FireAndForget(delegate (object x)
415 {
416 Thread.Sleep(60000);
417 if (m_running)
418 m_timer.Start();
419 });
420 }
421 }
422}
diff --git a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
index bf2e775..b006045 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
@@ -138,12 +138,12 @@ namespace OpenSim.Region.Framework.Scenes
138 { 138 {
139 SceneObjectGroup sog = part.ParentGroup; 139 SceneObjectGroup sog = part.ParentGroup;
140 sog.SendPropertiesToClient(remoteClient); 140 sog.SendPropertiesToClient(remoteClient);
141 sog.IsSelected = true;
142 141
143 // A prim is only tainted if it's allowed to be edited by the person clicking it. 142 // A prim is only tainted if it's allowed to be edited by the person clicking it.
144 if (Permissions.CanEditObject(sog.UUID, remoteClient.AgentId) 143 if (Permissions.CanEditObject(sog.UUID, remoteClient.AgentId)
145 || Permissions.CanMoveObject(sog.UUID, remoteClient.AgentId)) 144 || Permissions.CanMoveObject(sog.UUID, remoteClient.AgentId))
146 { 145 {
146 sog.IsSelected = true;
147 EventManager.TriggerParcelPrimCountTainted(); 147 EventManager.TriggerParcelPrimCountTainted();
148 } 148 }
149 } 149 }
@@ -215,7 +215,9 @@ namespace OpenSim.Region.Framework.Scenes
215 // handled by group, but by prim. Legacy cruft. 215 // handled by group, but by prim. Legacy cruft.
216 // TODO: Make selection flagging per prim! 216 // TODO: Make selection flagging per prim!
217 // 217 //
218 part.ParentGroup.IsSelected = false; 218 if (Permissions.CanEditObject(part.ParentGroup.UUID, remoteClient.AgentId)
219 || Permissions.CanMoveObject(part.ParentGroup.UUID, remoteClient.AgentId))
220 part.ParentGroup.IsSelected = false;
219 221
220 if (part.ParentGroup.IsAttachment) 222 if (part.ParentGroup.IsAttachment)
221 isAttachment = true; 223 isAttachment = true;
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 4324cc0..e675c73 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -2411,6 +2411,8 @@ namespace OpenSim.Region.Framework.Scenes
2411 2411
2412 if (newPosition != Vector3.Zero) 2412 if (newPosition != Vector3.Zero)
2413 newObject.RootPart.GroupPosition = newPosition; 2413 newObject.RootPart.GroupPosition = newPosition;
2414 if (newObject.RootPart.KeyframeMotion != null)
2415 newObject.RootPart.KeyframeMotion.UpdateSceneObject(newObject);
2414 2416
2415 if (!AddSceneObject(newObject)) 2417 if (!AddSceneObject(newObject))
2416 { 2418 {
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index 5a7f124..a320601 100644
--- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
@@ -1731,6 +1731,12 @@ namespace OpenSim.Region.Framework.Scenes
1731 /// <param name="childPrims"></param> 1731 /// <param name="childPrims"></param>
1732 protected internal void LinkObjects(SceneObjectPart root, List<SceneObjectPart> children) 1732 protected internal void LinkObjects(SceneObjectPart root, List<SceneObjectPart> children)
1733 { 1733 {
1734 if (root.KeyframeMotion != null)
1735 {
1736 root.KeyframeMotion.Stop();
1737 root.KeyframeMotion = null;
1738 }
1739
1734 SceneObjectGroup parentGroup = root.ParentGroup; 1740 SceneObjectGroup parentGroup = root.ParentGroup;
1735 if (parentGroup == null) return; 1741 if (parentGroup == null) return;
1736 1742
@@ -1823,6 +1829,11 @@ namespace OpenSim.Region.Framework.Scenes
1823 { 1829 {
1824 if (part != null) 1830 if (part != null)
1825 { 1831 {
1832 if (part.KeyframeMotion != null)
1833 {
1834 part.KeyframeMotion.Stop();
1835 part.KeyframeMotion = null;
1836 }
1826 if (part.ParentGroup.PrimCount != 1) // Skip single 1837 if (part.ParentGroup.PrimCount != 1) // Skip single
1827 { 1838 {
1828 if (part.LinkNum < 2) // Root 1839 if (part.LinkNum < 2) // Root
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index cf8637f..c9ea8e4 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -582,7 +582,7 @@ namespace OpenSim.Region.Framework.Scenes
582 foreach (ScenePresence av in m_linkedAvatars) 582 foreach (ScenePresence av in m_linkedAvatars)
583 { 583 {
584 SceneObjectPart p = m_scene.GetSceneObjectPart(av.ParentID); 584 SceneObjectPart p = m_scene.GetSceneObjectPart(av.ParentID);
585 if (m_parts.TryGetValue(p.UUID, out p)) 585 if (p != null && m_parts.TryGetValue(p.UUID, out p))
586 { 586 {
587 Vector3 offset = p.GetWorldPosition() - av.ParentPosition; 587 Vector3 offset = p.GetWorldPosition() - av.ParentPosition;
588 av.AbsolutePosition += offset; 588 av.AbsolutePosition += offset;
@@ -720,6 +720,8 @@ namespace OpenSim.Region.Framework.Scenes
720 child.PhysActor.Selected = value; 720 child.PhysActor.Selected = value;
721 } 721 }
722 } 722 }
723 if (RootPart.KeyframeMotion != null)
724 RootPart.KeyframeMotion.Selected = value;
723 } 725 }
724 } 726 }
725 727
@@ -890,6 +892,10 @@ namespace OpenSim.Region.Framework.Scenes
890 ApplyPhysics(); 892 ApplyPhysics();
891 893
892 if (RootPart.PhysActor != null) 894 if (RootPart.PhysActor != null)
895 RootPart.Force = RootPart.Force;
896 if (RootPart.PhysActor != null)
897 RootPart.Torque = RootPart.Torque;
898 if (RootPart.PhysActor != null)
893 RootPart.Buoyancy = RootPart.Buoyancy; 899 RootPart.Buoyancy = RootPart.Buoyancy;
894 900
895 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled 901 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled
@@ -1829,6 +1835,11 @@ namespace OpenSim.Region.Framework.Scenes
1829 1835
1830 backup_group.ForEachPart(delegate(SceneObjectPart part) 1836 backup_group.ForEachPart(delegate(SceneObjectPart part)
1831 { 1837 {
1838 if (part.KeyframeMotion != null)
1839 {
1840 part.KeyframeMotion = KeyframeMotion.FromData(backup_group, part.KeyframeMotion.Serialize());
1841 part.KeyframeMotion.UpdateSceneObject(this);
1842 }
1832 part.Inventory.ProcessInventoryBackup(datastore); 1843 part.Inventory.ProcessInventoryBackup(datastore);
1833 }); 1844 });
1834 1845
@@ -1978,10 +1989,18 @@ namespace OpenSim.Region.Framework.Scenes
1978 public void CopyRootPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) 1989 public void CopyRootPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed)
1979 { 1990 {
1980 SetRootPart(part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, 0, userExposed)); 1991 SetRootPart(part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, 0, userExposed));
1992 if (userExposed)
1993 RootPart.Velocity = Vector3.Zero; // In case source is moving
1981 } 1994 }
1982 1995
1983 public void ScriptSetPhysicsStatus(bool usePhysics) 1996 public void ScriptSetPhysicsStatus(bool usePhysics)
1984 { 1997 {
1998 if (usePhysics)
1999 {
2000 if (RootPart.KeyframeMotion != null)
2001 RootPart.KeyframeMotion.Stop();
2002 RootPart.KeyframeMotion = null;
2003 }
1985 UpdatePrimFlags(RootPart.LocalId, usePhysics, IsTemporary, IsPhantom, IsVolumeDetect); 2004 UpdatePrimFlags(RootPart.LocalId, usePhysics, IsTemporary, IsPhantom, IsVolumeDetect);
1986 } 2005 }
1987 2006
@@ -2045,30 +2064,9 @@ namespace OpenSim.Region.Framework.Scenes
2045 } 2064 }
2046 } 2065 }
2047 2066
2048 public void setAngularImpulse(Vector3 impulse)
2049 {
2050 if (RootPart.PhysActor != null)
2051 {
2052 if (!IsAttachment)
2053 {
2054 RootPart.PhysActor.Torque = impulse;
2055 m_scene.PhysicsScene.AddPhysicsActorTaint(RootPart.PhysActor);
2056 }
2057 }
2058 }
2059
2060 public Vector3 GetTorque() 2067 public Vector3 GetTorque()
2061 { 2068 {
2062 if (RootPart.PhysActor != null) 2069 return RootPart.Torque;
2063 {
2064 if (!IsAttachment)
2065 {
2066 Vector3 torque = RootPart.PhysActor.Torque;
2067 return torque;
2068 }
2069 }
2070
2071 return Vector3.Zero;
2072 } 2070 }
2073 2071
2074 // This is used by both Double-Click Auto-Pilot and llMoveToTarget() in an attached object 2072 // This is used by both Double-Click Auto-Pilot and llMoveToTarget() in an attached object
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index dd9431b..1c72b10 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -294,6 +294,8 @@ namespace OpenSim.Region.Framework.Scenes
294 protected Vector3 m_lastAngularVelocity; 294 protected Vector3 m_lastAngularVelocity;
295 protected int m_lastTerseSent; 295 protected int m_lastTerseSent;
296 protected float m_buoyancy = 0.0f; 296 protected float m_buoyancy = 0.0f;
297 protected Vector3 m_force;
298 protected Vector3 m_torque;
297 299
298 /// <summary> 300 /// <summary>
299 /// Stores media texture data 301 /// Stores media texture data
@@ -313,6 +315,14 @@ namespace OpenSim.Region.Framework.Scenes
313 315
314 private SOPVehicle m_vehicle = null; 316 private SOPVehicle m_vehicle = null;
315 317
318 private KeyframeMotion m_keyframeMotion = null;
319
320 public KeyframeMotion KeyframeMotion
321 {
322 get; set;
323 }
324
325
316 #endregion Fields 326 #endregion Fields
317 327
318// ~SceneObjectPart() 328// ~SceneObjectPart()
@@ -906,7 +916,7 @@ namespace OpenSim.Region.Framework.Scenes
906 get 916 get
907 { 917 {
908 PhysicsActor actor = PhysActor; 918 PhysicsActor actor = PhysActor;
909 if ((actor != null) && actor.IsPhysical) 919 if ((actor != null) && actor.IsPhysical && ParentGroup.RootPart == this)
910 { 920 {
911 m_angularVelocity = actor.RotationalVelocity; 921 m_angularVelocity = actor.RotationalVelocity;
912 } 922 }
@@ -1302,14 +1312,69 @@ namespace OpenSim.Region.Framework.Scenes
1302 1312
1303 public float Buoyancy 1313 public float Buoyancy
1304 { 1314 {
1305 get { return m_buoyancy; } 1315 get
1316 {
1317 if (ParentGroup.RootPart == this)
1318 return m_buoyancy;
1319
1320 return ParentGroup.RootPart.Buoyancy;
1321 }
1306 set 1322 set
1307 { 1323 {
1324 if (ParentGroup != null && ParentGroup.RootPart != null && ParentGroup.RootPart != this)
1325 {
1326 ParentGroup.RootPart.Buoyancy = value;
1327 return;
1328 }
1308 m_buoyancy = value; 1329 m_buoyancy = value;
1309 if (PhysActor != null) 1330 if (PhysActor != null)
1310 {
1311 PhysActor.Buoyancy = value; 1331 PhysActor.Buoyancy = value;
1332 }
1333 }
1334
1335 public Vector3 Force
1336 {
1337 get
1338 {
1339 if (ParentGroup.RootPart == this)
1340 return m_force;
1341
1342 return ParentGroup.RootPart.Force;
1343 }
1344
1345 set
1346 {
1347 if (ParentGroup != null && ParentGroup.RootPart != null && ParentGroup.RootPart != this)
1348 {
1349 ParentGroup.RootPart.Force = value;
1350 return;
1351 }
1352 m_force = value;
1353 if (PhysActor != null)
1354 PhysActor.Force = value;
1355 }
1356 }
1357
1358 public Vector3 Torque
1359 {
1360 get
1361 {
1362 if (ParentGroup.RootPart == this)
1363 return m_torque;
1364
1365 return ParentGroup.RootPart.Torque;
1366 }
1367
1368 set
1369 {
1370 if (ParentGroup != null && ParentGroup.RootPart != null && ParentGroup.RootPart != this)
1371 {
1372 ParentGroup.RootPart.Torque = value;
1373 return;
1312 } 1374 }
1375 m_torque = value;
1376 if (PhysActor != null)
1377 PhysActor.Torque = value;
1313 } 1378 }
1314 } 1379 }
1315 1380
@@ -1488,20 +1553,24 @@ namespace OpenSim.Region.Framework.Scenes
1488 /// </summary> 1553 /// </summary>
1489 /// <param name="impulsei">Vector force</param> 1554 /// <param name="impulsei">Vector force</param>
1490 /// <param name="localGlobalTF">true for the local frame, false for the global frame</param> 1555 /// <param name="localGlobalTF">true for the local frame, false for the global frame</param>
1491 public void SetAngularImpulse(Vector3 impulsei, bool localGlobalTF) 1556
1557 // this is actualy Set Torque.. keeping naming so not to edit lslapi also
1558 public void SetAngularImpulse(Vector3 torquei, bool localGlobalTF)
1492 { 1559 {
1493 Vector3 impulse = impulsei; 1560 Vector3 torque = torquei;
1494 1561
1495 if (localGlobalTF) 1562 if (localGlobalTF)
1496 { 1563 {
1564/*
1497 Quaternion grot = GetWorldRotation(); 1565 Quaternion grot = GetWorldRotation();
1498 Quaternion AXgrot = grot; 1566 Quaternion AXgrot = grot;
1499 Vector3 AXimpulsei = impulsei; 1567 Vector3 AXimpulsei = impulsei;
1500 Vector3 newimpulse = AXimpulsei * AXgrot; 1568 Vector3 newimpulse = AXimpulsei * AXgrot;
1501 impulse = newimpulse; 1569 */
1570 torque *= GetWorldRotation();
1502 } 1571 }
1503 1572
1504 ParentGroup.setAngularImpulse(impulse); 1573 Torque = torque;
1505 } 1574 }
1506 1575
1507 /// <summary> 1576 /// <summary>
@@ -1571,14 +1640,22 @@ namespace OpenSim.Region.Framework.Scenes
1571 1640
1572 DoPhysicsPropertyUpdate(RigidBody, true); 1641 DoPhysicsPropertyUpdate(RigidBody, true);
1573 PhysActor.SetVolumeDetect(VolumeDetectActive ? 1 : 0); 1642 PhysActor.SetVolumeDetect(VolumeDetectActive ? 1 : 0);
1643
1644 if (!building)
1645 PhysActor.Building = false;
1574 1646
1575 Velocity = velocity; 1647 Velocity = velocity;
1576 AngularVelocity = rotationalVelocity; 1648 AngularVelocity = rotationalVelocity;
1577 PhysActor.Velocity = velocity; 1649 PhysActor.Velocity = velocity;
1578 PhysActor.RotationalVelocity = rotationalVelocity; 1650 PhysActor.RotationalVelocity = rotationalVelocity;
1579 1651
1580 if (!building) 1652 // if not vehicle and root part apply force and torque
1581 PhysActor.Building = false; 1653 if ((m_vehicle == null || m_vehicle.Type == Vehicle.TYPE_NONE)
1654 && LocalId == ParentGroup.RootPart.LocalId)
1655 {
1656 PhysActor.Force = Force;
1657 PhysActor.Torque = Torque;
1658 }
1582 } 1659 }
1583 } 1660 }
1584 } 1661 }
@@ -1816,7 +1893,8 @@ namespace OpenSim.Region.Framework.Scenes
1816 1893
1817 Velocity = new Vector3(0, 0, 0); 1894 Velocity = new Vector3(0, 0, 0);
1818 Acceleration = new Vector3(0, 0, 0); 1895 Acceleration = new Vector3(0, 0, 0);
1819 AngularVelocity = new Vector3(0, 0, 0); 1896 if (ParentGroup.RootPart == this)
1897 AngularVelocity = new Vector3(0, 0, 0);
1820 1898
1821 PhysActor.OnRequestTerseUpdate -= PhysicsRequestingTerseUpdate; 1899 PhysActor.OnRequestTerseUpdate -= PhysicsRequestingTerseUpdate;
1822 PhysActor.OnOutOfBounds -= PhysicsOutOfBounds; 1900 PhysActor.OnOutOfBounds -= PhysicsOutOfBounds;
@@ -1840,7 +1918,8 @@ namespace OpenSim.Region.Framework.Scenes
1840 // velocity-vector. 1918 // velocity-vector.
1841 Velocity = new Vector3(0, 0, 0); 1919 Velocity = new Vector3(0, 0, 0);
1842 Acceleration = new Vector3(0, 0, 0); 1920 Acceleration = new Vector3(0, 0, 0);
1843 AngularVelocity = new Vector3(0, 0, 0); 1921 if (ParentGroup.RootPart == this)
1922 AngularVelocity = new Vector3(0, 0, 0);
1844 //RotationalVelocity = new Vector3(0, 0, 0); 1923 //RotationalVelocity = new Vector3(0, 0, 0);
1845 } 1924 }
1846 1925
@@ -1855,6 +1934,9 @@ namespace OpenSim.Region.Framework.Scenes
1855 { 1934 {
1856 if (UsePhysics) 1935 if (UsePhysics)
1857 { 1936 {
1937 if (ParentGroup.RootPart.KeyframeMotion != null)
1938 ParentGroup.RootPart.KeyframeMotion.Stop();
1939 ParentGroup.RootPart.KeyframeMotion = null;
1858 ParentGroup.Scene.AddPhysicalPrim(1); 1940 ParentGroup.Scene.AddPhysicalPrim(1);
1859 1941
1860 PhysActor.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate; 1942 PhysActor.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate;
@@ -2002,10 +2084,7 @@ namespace OpenSim.Region.Framework.Scenes
2002 2084
2003 public Vector3 GetForce() 2085 public Vector3 GetForce()
2004 { 2086 {
2005 if (PhysActor != null) 2087 return Force;
2006 return PhysActor.Force;
2007 else
2008 return Vector3.Zero;
2009 } 2088 }
2010 2089
2011 /// <summary> 2090 /// <summary>
@@ -3150,10 +3229,13 @@ namespace OpenSim.Region.Framework.Scenes
3150 3229
3151 public void SetBuoyancy(float fvalue) 3230 public void SetBuoyancy(float fvalue)
3152 { 3231 {
3232 Buoyancy = fvalue;
3233/*
3153 if (PhysActor != null) 3234 if (PhysActor != null)
3154 { 3235 {
3155 PhysActor.Buoyancy = fvalue; 3236 PhysActor.Buoyancy = fvalue;
3156 } 3237 }
3238 */
3157 } 3239 }
3158 3240
3159 public void SetDieAtEdge(bool p) 3241 public void SetDieAtEdge(bool p)
@@ -3181,10 +3263,13 @@ namespace OpenSim.Region.Framework.Scenes
3181 3263
3182 public void SetForce(Vector3 force) 3264 public void SetForce(Vector3 force)
3183 { 3265 {
3266 Force = force;
3267/*
3184 if (PhysActor != null) 3268 if (PhysActor != null)
3185 { 3269 {
3186 PhysActor.Force = force; 3270 PhysActor.Force = force;
3187 } 3271 }
3272 */
3188 } 3273 }
3189 3274
3190 public SOPVehicle sopVehicle 3275 public SOPVehicle sopVehicle
diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
index 72a0ec3..51a3320 100644
--- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
+++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
@@ -244,6 +244,12 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
244 sr.Close(); 244 sr.Close();
245 } 245 }
246 246
247 XmlNodeList keymotion = doc.GetElementsByTagName("KeyframeMotion");
248 if (keymotion.Count > 0)
249 sceneObject.RootPart.KeyframeMotion = KeyframeMotion.FromData(sceneObject, Convert.FromBase64String(keymotion[0].InnerText));
250 else
251 sceneObject.RootPart.KeyframeMotion = null;
252
247 // Script state may, or may not, exist. Not having any, is NOT 253 // Script state may, or may not, exist. Not having any, is NOT
248 // ever a problem. 254 // ever a problem.
249 sceneObject.LoadScriptState(doc); 255 sceneObject.LoadScriptState(doc);
@@ -349,6 +355,8 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
349 m_SOPXmlProcessors.Add("PayPrice4", ProcessPayPrice4); 355 m_SOPXmlProcessors.Add("PayPrice4", ProcessPayPrice4);
350 356
351 m_SOPXmlProcessors.Add("Buoyancy", ProcessBuoyancy); 357 m_SOPXmlProcessors.Add("Buoyancy", ProcessBuoyancy);
358 m_SOPXmlProcessors.Add("Force", ProcessForce);
359 m_SOPXmlProcessors.Add("Torque", ProcessTorque);
352 m_SOPXmlProcessors.Add("VolumeDetectActive", ProcessVolumeDetectActive); 360 m_SOPXmlProcessors.Add("VolumeDetectActive", ProcessVolumeDetectActive);
353 361
354 //Ubit comented until proper testing 362 //Ubit comented until proper testing
@@ -595,7 +603,6 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
595 obj.sopVehicle = _vehicle; 603 obj.sopVehicle = _vehicle;
596 } 604 }
597 605
598
599 private static void ProcessShape(SceneObjectPart obj, XmlTextReader reader) 606 private static void ProcessShape(SceneObjectPart obj, XmlTextReader reader)
600 { 607 {
601 List<string> errorNodeNames; 608 List<string> errorNodeNames;
@@ -762,7 +769,16 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
762 769
763 private static void ProcessBuoyancy(SceneObjectPart obj, XmlTextReader reader) 770 private static void ProcessBuoyancy(SceneObjectPart obj, XmlTextReader reader)
764 { 771 {
765 obj.Buoyancy = (int)reader.ReadElementContentAsFloat("Buoyancy", String.Empty); 772 obj.Buoyancy = (float)reader.ReadElementContentAsFloat("Buoyancy", String.Empty);
773 }
774
775 private static void ProcessForce(SceneObjectPart obj, XmlTextReader reader)
776 {
777 obj.Force = Util.ReadVector(reader, "Force");
778 }
779 private static void ProcessTorque(SceneObjectPart obj, XmlTextReader reader)
780 {
781 obj.Torque = Util.ReadVector(reader, "Torque");
766 } 782 }
767 783
768 private static void ProcessVolumeDetectActive(SceneObjectPart obj, XmlTextReader reader) 784 private static void ProcessVolumeDetectActive(SceneObjectPart obj, XmlTextReader reader)
@@ -1157,6 +1173,16 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1157 }); 1173 });
1158 1174
1159 writer.WriteEndElement(); 1175 writer.WriteEndElement();
1176
1177 if (sog.RootPart.KeyframeMotion != null)
1178 {
1179 Byte[] data = sog.RootPart.KeyframeMotion.Serialize();
1180
1181 writer.WriteStartElement(String.Empty, "KeyframeMotion", String.Empty);
1182 writer.WriteBase64(data, 0, data.Length);
1183 writer.WriteEndElement();
1184 }
1185
1160 writer.WriteEndElement(); 1186 writer.WriteEndElement();
1161 } 1187 }
1162 1188
@@ -1256,6 +1282,10 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1256 writer.WriteElementString("PayPrice4", sop.PayPrice[4].ToString()); 1282 writer.WriteElementString("PayPrice4", sop.PayPrice[4].ToString());
1257 1283
1258 writer.WriteElementString("Buoyancy", sop.Buoyancy.ToString()); 1284 writer.WriteElementString("Buoyancy", sop.Buoyancy.ToString());
1285
1286 WriteVector(writer, "Force", sop.Force);
1287 WriteVector(writer, "Torque", sop.Torque);
1288
1259 writer.WriteElementString("VolumeDetectActive", sop.VolumeDetectActive.ToString().ToLower()); 1289 writer.WriteElementString("VolumeDetectActive", sop.VolumeDetectActive.ToString().ToLower());
1260 1290
1261 //Ubit comented until proper testing 1291 //Ubit comented until proper testing
diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs
index ae46c97..78e9b29 100644
--- a/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs
+++ b/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs
@@ -99,8 +99,11 @@ namespace OpenSim.Region.OptionalModules.World.NPC
99 // Delete existing sp attachments 99 // Delete existing sp attachments
100 scene.AttachmentsModule.DeleteAttachmentsFromScene(sp, false); 100 scene.AttachmentsModule.DeleteAttachmentsFromScene(sp, false);
101 101
102 AvatarAppearance app = new AvatarAppearance(appearance, true);
103 sp.Appearance = app;
104
102 // Set new sp appearance. Also sends to clients. 105 // Set new sp appearance. Also sends to clients.
103 scene.RequestModuleInterface<IAvatarFactoryModule>().SetAppearance(sp, new AvatarAppearance(appearance, true)); 106 scene.RequestModuleInterface<IAvatarFactoryModule>().SetAppearance(sp, app);
104 107
105 // Rez needed sp attachments 108 // Rez needed sp attachments
106 scene.AttachmentsModule.RezAttachments(sp); 109 scene.AttachmentsModule.RezAttachments(sp);
diff --git a/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs
index 80c1277..0a4ebe4 100644
--- a/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs
+++ b/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs
@@ -704,6 +704,8 @@ namespace OpenSim.Region.Physics.OdePlugin
704 if (m_isphysical) 704 if (m_isphysical)
705 m_targetSpace = _parent_scene.space; 705 m_targetSpace = _parent_scene.space;
706 706
707 _triMeshData = IntPtr.Zero;
708
707 m_primName = primName; 709 m_primName = primName;
708 m_taintserial = null; 710 m_taintserial = null;
709 m_taintadd = true; 711 m_taintadd = true;
@@ -773,6 +775,8 @@ namespace OpenSim.Region.Physics.OdePlugin
773 m_targetSpace = _parent_scene.space; 775 m_targetSpace = _parent_scene.space;
774 } 776 }
775 777
778 _triMeshData = IntPtr.Zero;
779
776 m_taintserial = null; 780 m_taintserial = null;
777 m_primName = primName; 781 m_primName = primName;
778 m_taintadd = true; 782 m_taintadd = true;
@@ -1762,7 +1766,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1762 1766
1763 private static Dictionary<IMesh, IntPtr> m_MeshToTriMeshMap = new Dictionary<IMesh, IntPtr>(); 1767 private static Dictionary<IMesh, IntPtr> m_MeshToTriMeshMap = new Dictionary<IMesh, IntPtr>();
1764 1768
1765 public void setMesh(OdeScene parent_scene, IMesh mesh) 1769 public bool setMesh(OdeScene parent_scene, IMesh mesh)
1766 { 1770 {
1767 // This sleeper is there to moderate how long it takes between 1771 // This sleeper is there to moderate how long it takes between
1768 // setting up the mesh and pre-processing it when we get rapid fire mesh requests on a single object 1772 // setting up the mesh and pre-processing it when we get rapid fire mesh requests on a single object
@@ -1785,24 +1789,48 @@ namespace OpenSim.Region.Physics.OdePlugin
1785 disableBody(); 1789 disableBody();
1786 } 1790 }
1787 } 1791 }
1792
1793// do it on caller instead
1794/*
1795 if (_triMeshData != IntPtr.Zero)
1796 {
1797 d.GeomTriMeshDataDestroy(_triMeshData);
1798 _triMeshData = IntPtr.Zero;
1799 }
1800*/
1788 IntPtr vertices, indices; 1801 IntPtr vertices, indices;
1789 int vertexCount, indexCount; 1802 int vertexCount, indexCount;
1790 int vertexStride, triStride; 1803 int vertexStride, triStride;
1791 mesh.getVertexListAsPtrToFloatArray(out vertices, out vertexStride, out vertexCount); // Note, that vertices are fixed in unmanaged heap 1804 mesh.getVertexListAsPtrToFloatArray(out vertices, out vertexStride, out vertexCount); // Note, that vertices are fixed in unmanaged heap
1792 mesh.getIndexListAsPtrToIntArray(out indices, out triStride, out indexCount); // Also fixed, needs release after usage 1805 mesh.getIndexListAsPtrToIntArray(out indices, out triStride, out indexCount); // Also fixed, needs release after usage
1793 1806
1807 // warning this destroys the mesh for eventual future use. Only pinned float arrays stay valid
1794 mesh.releaseSourceMeshData(); // free up the original mesh data to save memory 1808 mesh.releaseSourceMeshData(); // free up the original mesh data to save memory
1809
1810 if (vertexCount == 0 || indexCount == 0)
1811 {
1812 m_log.WarnFormat("[PHYSICS]: Got invalid mesh on prim {0} at <{1},{2},{3}>. It can be a sculp with alpha channel in map. Replacing it by a small box.", Name, _position.X, _position.Y, _position.Z);
1813 _size.X = 0.05f;
1814 _size.Y = 0.05f;
1815 _size.Z = 0.05f;
1816 return false;
1817 }
1818
1819/*
1795 if (m_MeshToTriMeshMap.ContainsKey(mesh)) 1820 if (m_MeshToTriMeshMap.ContainsKey(mesh))
1796 { 1821 {
1797 _triMeshData = m_MeshToTriMeshMap[mesh]; 1822 _triMeshData = m_MeshToTriMeshMap[mesh];
1798 } 1823 }
1799 else 1824 else
1825*/
1826
1827
1800 { 1828 {
1801 _triMeshData = d.GeomTriMeshDataCreate(); 1829 _triMeshData = d.GeomTriMeshDataCreate();
1802 1830
1803 d.GeomTriMeshDataBuildSimple(_triMeshData, vertices, vertexStride, vertexCount, indices, indexCount, triStride); 1831 d.GeomTriMeshDataBuildSimple(_triMeshData, vertices, vertexStride, vertexCount, indices, indexCount, triStride);
1804 d.GeomTriMeshDataPreprocess(_triMeshData); 1832 d.GeomTriMeshDataPreprocess(_triMeshData);
1805 m_MeshToTriMeshMap[mesh] = _triMeshData; 1833// m_MeshToTriMeshMap[mesh] = _triMeshData;
1806 } 1834 }
1807 1835
1808 _parent_scene.waitForSpaceUnlock(m_targetSpace); 1836 _parent_scene.waitForSpaceUnlock(m_targetSpace);
@@ -1810,13 +1838,23 @@ namespace OpenSim.Region.Physics.OdePlugin
1810 { 1838 {
1811 // if (prim_geom == IntPtr.Zero) // setGeom takes care of phys engine recreate and prim_geom pointer 1839 // if (prim_geom == IntPtr.Zero) // setGeom takes care of phys engine recreate and prim_geom pointer
1812 // { 1840 // {
1813 SetGeom(d.CreateTriMesh(m_targetSpace, _triMeshData, parent_scene.triCallback, null, null)); 1841 // SetGeom(d.CreateTriMesh(m_targetSpace, _triMeshData, parent_scene.triCallback, null, null));
1842 SetGeom(d.CreateTriMesh(m_targetSpace, _triMeshData, null, null, null));
1814 // } 1843 // }
1815 } 1844 }
1816 catch (AccessViolationException) 1845 catch (Exception e)
1817 { 1846 {
1818 m_log.Error("[PHYSICS]: MESH LOCKED"); 1847 m_log.ErrorFormat("[PHYSICS]: Create trimesh failed on prim {0} : {1}",Name,e.Message);
1819 return; 1848
1849 if (_triMeshData != IntPtr.Zero)
1850 {
1851 d.GeomTriMeshDataDestroy(_triMeshData);
1852 _triMeshData = IntPtr.Zero;
1853 }
1854 _size.X = 0.05f;
1855 _size.Y = 0.05f;
1856 _size.Z = 0.05f;
1857 return false;
1820 } 1858 }
1821 1859
1822 1860
@@ -1828,6 +1866,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1828 1866
1829 // enableBody(); 1867 // enableBody();
1830 // } 1868 // }
1869 return true;
1831 } 1870 }
1832 1871
1833 public void ProcessTaints(float timestep) //============================================================================= 1872 public void ProcessTaints(float timestep) //=============================================================================
@@ -1837,6 +1876,9 @@ namespace OpenSim.Region.Physics.OdePlugin
1837 changeadd(timestep); 1876 changeadd(timestep);
1838 } 1877 }
1839 1878
1879 if (m_taintremove)
1880 return;
1881
1840 if (prim_geom != IntPtr.Zero) 1882 if (prim_geom != IntPtr.Zero)
1841 { 1883 {
1842 if (!_position.ApproxEquals(m_taintposition, 0f)) 1884 if (!_position.ApproxEquals(m_taintposition, 0f))
@@ -2286,75 +2328,62 @@ namespace OpenSim.Region.Physics.OdePlugin
2286 2328
2287 public void CreateGeom(IntPtr m_targetSpace, IMesh _mesh) 2329 public void CreateGeom(IntPtr m_targetSpace, IMesh _mesh)
2288 { 2330 {
2331 bool gottrimesh = false;
2332
2333 if (_triMeshData != IntPtr.Zero)
2334 {
2335 d.GeomTriMeshDataDestroy(_triMeshData);
2336 _triMeshData = IntPtr.Zero;
2337 }
2338
2289 if (_mesh != null) // Special - make mesh 2339 if (_mesh != null) // Special - make mesh
2290 { 2340 {
2291 setMesh(_parent_scene, _mesh); 2341 gottrimesh = setMesh(_parent_scene, _mesh);
2292 } 2342 }
2293 else // not a mesh 2343
2344 if (!gottrimesh) // not a mesh
2294 { 2345 {
2295 if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1) // special profile?? 2346 IntPtr geo = IntPtr.Zero;
2347
2348 if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1
2349 && _size.X == _size.Y && _size.X == _size.Z)
2296 { 2350 {
2297 if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z) // Equi-size 2351 // its a sphere
2352 _parent_scene.waitForSpaceUnlock(m_targetSpace);
2353 try
2298 { 2354 {
2299 if (((_size.X / 2f) > 0f)) // Has size 2355 geo = d.CreateSphere(m_targetSpace, _size.X * 0.5f);
2300 {
2301 _parent_scene.waitForSpaceUnlock(m_targetSpace);
2302 try
2303 {
2304 SetGeom(d.CreateSphere(m_targetSpace, _size.X / 2));
2305 }
2306 catch (AccessViolationException)
2307 {
2308 m_log.Warn("[PHYSICS]: Unable to create physics proxy for object");
2309 ode.dunlock(_parent_scene.world);
2310 return;
2311 }
2312 }
2313 else
2314 {
2315 _parent_scene.waitForSpaceUnlock(m_targetSpace);
2316 try
2317 {
2318 SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
2319 }
2320 catch (AccessViolationException)
2321 {
2322 m_log.Warn("[PHYSICS]: Unable to create physics proxy for object");
2323 ode.dunlock(_parent_scene.world);
2324 return;
2325 }
2326 }
2327 } 2356 }
2328 else // not equi-size 2357 catch (Exception e)
2329 { 2358 {
2330 _parent_scene.waitForSpaceUnlock(m_targetSpace); 2359 m_log.WarnFormat("[PHYSICS]: Unable to create basic sphere for object {0}", e.Message);
2331 try 2360 geo = IntPtr.Zero;
2332 { 2361 ode.dunlock(_parent_scene.world);
2333 SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
2334 }
2335 catch (AccessViolationException)
2336 {
2337 m_log.Warn("[PHYSICS]: Unable to create physics proxy for object");
2338 ode.dunlock(_parent_scene.world);
2339 return;
2340 }
2341 } 2362 }
2342 } 2363 }
2343 2364 else // make it a box
2344 else // not special profile
2345 { 2365 {
2346 _parent_scene.waitForSpaceUnlock(m_targetSpace); 2366 _parent_scene.waitForSpaceUnlock(m_targetSpace);
2347 try 2367 try
2348 { 2368 {
2349 SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z)); 2369 geo = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z);
2350 } 2370 }
2351 catch (AccessViolationException) 2371 catch (Exception e)
2352 { 2372 {
2353 m_log.Warn("[PHYSICS]: Unable to create physics proxy for object"); 2373 m_log.WarnFormat("[PHYSICS]: Unable to create basic sphere for object {0}", e.Message);
2374 geo = IntPtr.Zero;
2354 ode.dunlock(_parent_scene.world); 2375 ode.dunlock(_parent_scene.world);
2355 return;
2356 } 2376 }
2357 } 2377 }
2378
2379 if (geo == IntPtr.Zero)
2380 {
2381 m_taintremove = true;
2382 _parent_scene.AddPhysicsActorTaint(this);
2383 return;
2384 }
2385
2386 SetGeom(geo);
2358 } 2387 }
2359 } 2388 }
2360 2389
@@ -2372,18 +2401,17 @@ namespace OpenSim.Region.Physics.OdePlugin
2372 { 2401 {
2373 if (_parent_scene.needsMeshing(_pbs)) 2402 if (_parent_scene.needsMeshing(_pbs))
2374 { 2403 {
2375 // Don't need to re-enable body.. it's done in SetMesh
2376 try 2404 try
2377 { 2405 {
2378 _mesh = _parent_scene.mesher.CreateMesh(m_primName, _pbs, _size, _parent_scene.meshSculptLOD, IsPhysical); 2406 _mesh = _parent_scene.mesher.CreateMesh(m_primName, _pbs, _size, (int)LevelOfDetail.High, true);
2379 } 2407 }
2380 catch 2408 catch
2381 { 2409 {
2382 //Don't continuously try to mesh prims when meshing has failed 2410 //Don't continuously try to mesh prims when meshing has failed
2383 m_meshfailed = true; 2411 m_meshfailed = true;
2412 _mesh = null;
2413 m_log.WarnFormat("[PHYSICS]: changeAdd CreateMesh fail on prim {0} at <{1},{2},{3}>", Name, _position.X, _position.Y, _position.Z);
2384 } 2414 }
2385 // createmesh returns null when it's a shape that isn't a cube.
2386 // m_log.Debug(m_localID);
2387 } 2415 }
2388 } 2416 }
2389 2417
@@ -2630,17 +2658,17 @@ namespace OpenSim.Region.Physics.OdePlugin
2630 try 2658 try
2631 { 2659 {
2632 if (_parent_scene.needsMeshing(_pbs)) 2660 if (_parent_scene.needsMeshing(_pbs))
2633 mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size, meshlod, IsPhysical); 2661 mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size, (int)LevelOfDetail.High, true);
2634 } 2662 }
2635 catch 2663 catch
2636 { 2664 {
2637 m_meshfailed = true; 2665 m_meshfailed = true;
2666 mesh = null;
2667 m_log.WarnFormat("[PHYSICS]: changeSize CreateMesh fail on prim {0} at <{1},{2},{3}>", Name, _position.X, _position.Y, _position.Z);
2638 } 2668 }
2639 2669
2640 //IMesh mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size, meshlod, IsPhysical); 2670 //IMesh mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size, meshlod, IsPhysical);
2641 CreateGeom(m_targetSpace, mesh); 2671 CreateGeom(m_targetSpace, mesh);
2642
2643
2644 } 2672 }
2645 else 2673 else
2646 { 2674 {
@@ -2732,18 +2760,23 @@ namespace OpenSim.Region.Physics.OdePlugin
2732 { 2760 {
2733 // Don't need to re-enable body.. it's done in SetMesh 2761 // Don't need to re-enable body.. it's done in SetMesh
2734 float meshlod = _parent_scene.meshSculptLOD; 2762 float meshlod = _parent_scene.meshSculptLOD;
2763 IMesh mesh;
2735 2764
2736 if (IsPhysical) 2765 if (IsPhysical)
2737 meshlod = _parent_scene.MeshSculptphysicalLOD; 2766 meshlod = _parent_scene.MeshSculptphysicalLOD;
2738 try 2767 try
2739 { 2768 {
2740 IMesh mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size, meshlod, IsPhysical); 2769 mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size, (int)LevelOfDetail.High, true);
2741 CreateGeom(m_targetSpace, mesh);
2742 } 2770 }
2743 catch 2771 catch
2744 { 2772 {
2773 mesh = null;
2745 m_meshfailed = true; 2774 m_meshfailed = true;
2775 m_log.WarnFormat("[PHYSICS]: changeAdd CreateMesh fail on prim {0} at <{1},{2},{3}>", Name, _position.X, _position.Y, _position.Z);
2746 } 2776 }
2777
2778 CreateGeom(m_targetSpace, mesh);
2779
2747 // createmesh returns null when it doesn't mesh. 2780 // createmesh returns null when it doesn't mesh.
2748 } 2781 }
2749 else 2782 else
diff --git a/OpenSim/Region/Physics/ChOdePlugin/OdePlugin.cs b/OpenSim/Region/Physics/ChOdePlugin/OdePlugin.cs
index 61fb2d0..7a1e671 100644
--- a/OpenSim/Region/Physics/ChOdePlugin/OdePlugin.cs
+++ b/OpenSim/Region/Physics/ChOdePlugin/OdePlugin.cs
@@ -1772,7 +1772,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1772 IMesh mesh = null; 1772 IMesh mesh = null;
1773 1773
1774 if (needsMeshing(pbs)) 1774 if (needsMeshing(pbs))
1775 mesh = mesher.CreateMesh(primName, pbs, size, 32f, isPhysical); 1775 mesh = mesher.CreateMesh(primName, pbs, size, (int)LevelOfDetail.High, true);
1776 1776
1777 result = AddPrim(primName, position, size, rotation, mesh, pbs, isPhysical, localid); 1777 result = AddPrim(primName, position, size, rotation, mesh, pbs, isPhysical, localid);
1778 1778
@@ -2174,6 +2174,16 @@ namespace OpenSim.Region.Physics.OdePlugin
2174 { 2174 {
2175 prim.ResetTaints(); 2175 prim.ResetTaints();
2176 2176
2177 try
2178 {
2179 if (prim._triMeshData != IntPtr.Zero)
2180 {
2181 d.GeomTriMeshDataDestroy(prim._triMeshData);
2182 prim._triMeshData = IntPtr.Zero;
2183 }
2184 }
2185 catch { };
2186
2177 if (prim.IsPhysical) 2187 if (prim.IsPhysical)
2178 { 2188 {
2179 prim.disableBody(); 2189 prim.disableBody();
@@ -2185,7 +2195,6 @@ namespace OpenSim.Region.Physics.OdePlugin
2185 prim.IsPhysical = false; 2195 prim.IsPhysical = false;
2186 } 2196 }
2187 2197
2188
2189 } 2198 }
2190 // we don't want to remove the main space 2199 // we don't want to remove the main space
2191 2200
@@ -2505,7 +2514,7 @@ namespace OpenSim.Region.Physics.OdePlugin
2505 } 2514 }
2506 2515
2507 // if it's a standard box or sphere with no cuts, hollows, twist or top shear, return false since ODE can use an internal representation for the prim 2516 // if it's a standard box or sphere with no cuts, hollows, twist or top shear, return false since ODE can use an internal representation for the prim
2508 if (!forceSimplePrimMeshing) 2517 if (!forceSimplePrimMeshing && !pbs.SculptEntry)
2509 { 2518 {
2510 if ((pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight) 2519 if ((pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight)
2511 || (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1 2520 || (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1
@@ -2528,6 +2537,9 @@ namespace OpenSim.Region.Physics.OdePlugin
2528 } 2537 }
2529 } 2538 }
2530 2539
2540 if (forceSimplePrimMeshing)
2541 return true;
2542
2531 if (pbs.ProfileHollow != 0) 2543 if (pbs.ProfileHollow != 0)
2532 iPropertiesNotSupportedDefault++; 2544 iPropertiesNotSupportedDefault++;
2533 2545
@@ -2592,6 +2604,8 @@ namespace OpenSim.Region.Physics.OdePlugin
2592 } 2604 }
2593 } 2605 }
2594 2606
2607 if (pbs.SculptEntry && meshSculptedPrim)
2608 iPropertiesNotSupportedDefault++;
2595 2609
2596 if (iPropertiesNotSupportedDefault == 0) 2610 if (iPropertiesNotSupportedDefault == 0)
2597 { 2611 {
@@ -3443,8 +3457,8 @@ namespace OpenSim.Region.Physics.OdePlugin
3443 int heightmapWidth = regionsize + 2; // ODE map size 257 x 257 (Meters) (1 extra 3457 int heightmapWidth = regionsize + 2; // ODE map size 257 x 257 (Meters) (1 extra
3444 int heightmapHeight = regionsize + 2; 3458 int heightmapHeight = regionsize + 2;
3445 3459
3446 int heightmapWidthSamples = (int)regionsize + 3; // Sample file size, 258 x 258 samples 3460 int heightmapWidthSamples = (int)regionsize + 2; // Sample file size, 258 x 258 samples
3447 int heightmapHeightSamples = (int)regionsize + 3; 3461 int heightmapHeightSamples = (int)regionsize + 2;
3448 3462
3449 // Array of height samples for ODE 3463 // Array of height samples for ODE
3450 float[] _heightmap; 3464 float[] _heightmap;
@@ -3481,7 +3495,7 @@ namespace OpenSim.Region.Physics.OdePlugin
3481 // Output x = 0 1 2 3 ..... 255 256 257 258 total out 3495 // Output x = 0 1 2 3 ..... 255 256 257 258 total out
3482 float val= heightMap[(yy * regionsize) + xx]; // input from heightMap, <0-255 * 256> <0-255> 3496 float val= heightMap[(yy * regionsize) + xx]; // input from heightMap, <0-255 * 256> <0-255>
3483 if (val < minele) val = minele; 3497 if (val < minele) val = minele;
3484 _heightmap[x * (heightmapHeightSamples) + y] = val; // samples output to _heightmap, <0-257 * 258> <0-257> 3498 _heightmap[x * (regionsize + 2) + y] = val; // samples output to _heightmap, <0-257 * 258> <0-257>
3485 hfmin = (val < hfmin) ? val : hfmin; 3499 hfmin = (val < hfmin) ? val : hfmin;
3486 hfmax = (val > hfmax) ? val : hfmax; 3500 hfmax = (val > hfmax) ? val : hfmax;
3487 } 3501 }
@@ -3531,8 +3545,6 @@ namespace OpenSim.Region.Physics.OdePlugin
3531 d.RFromAxisAndAngle(out R, v3.X, v3.Y, v3.Z, angle); 3545 d.RFromAxisAndAngle(out R, v3.X, v3.Y, v3.Z, angle);
3532 d.GeomSetRotation(GroundGeom, ref R); 3546 d.GeomSetRotation(GroundGeom, ref R);
3533 d.GeomSetPosition(GroundGeom, (pOffset.X + (regionsize * 0.5f)) - 0.5f, (pOffset.Y + (regionsize * 0.5f)) - 0.5f, 0); 3547 d.GeomSetPosition(GroundGeom, (pOffset.X + (regionsize * 0.5f)) - 0.5f, (pOffset.Y + (regionsize * 0.5f)) - 0.5f, 0);
3534 // having nsamples = size + 1 center is actually at size/2
3535 d.GeomSetPosition(GroundGeom, (pOffset.X + (regionsize * 0.5f)), (pOffset.Y + (regionsize * 0.5f)), 0);
3536 IntPtr testGround = IntPtr.Zero; 3548 IntPtr testGround = IntPtr.Zero;
3537 if (RegionTerrain.TryGetValue(pOffset, out testGround)) 3549 if (RegionTerrain.TryGetValue(pOffset, out testGround))
3538 { 3550 {
diff --git a/OpenSim/Region/Physics/UbitOdePlugin/ODEDynamics.cs b/OpenSim/Region/Physics/UbitOdePlugin/ODEDynamics.cs
index 80218e7..c9d0909 100644
--- a/OpenSim/Region/Physics/UbitOdePlugin/ODEDynamics.cs
+++ b/OpenSim/Region/Physics/UbitOdePlugin/ODEDynamics.cs
@@ -83,7 +83,6 @@ namespace OpenSim.Region.Physics.OdePlugin
83 private Vector3 m_linearFrictionTimescale = new Vector3(1000, 1000, 1000); 83 private Vector3 m_linearFrictionTimescale = new Vector3(1000, 1000, 1000);
84 private float m_linearMotorDecayTimescale = 120; 84 private float m_linearMotorDecayTimescale = 120;
85 private float m_linearMotorTimescale = 1000; 85 private float m_linearMotorTimescale = 1000;
86 private Vector3 m_lastLinearVelocityVector = Vector3.Zero;
87 private Vector3 m_linearMotorOffset = Vector3.Zero; 86 private Vector3 m_linearMotorOffset = Vector3.Zero;
88 87
89 //Angular properties 88 //Angular properties
@@ -91,7 +90,6 @@ namespace OpenSim.Region.Physics.OdePlugin
91 private float m_angularMotorTimescale = 1000; // motor angular velocity ramp up rate 90 private float m_angularMotorTimescale = 1000; // motor angular velocity ramp up rate
92 private float m_angularMotorDecayTimescale = 120; // motor angular velocity decay rate 91 private float m_angularMotorDecayTimescale = 120; // motor angular velocity decay rate
93 private Vector3 m_angularFrictionTimescale = new Vector3(1000, 1000, 1000); // body angular velocity decay rate 92 private Vector3 m_angularFrictionTimescale = new Vector3(1000, 1000, 1000); // body angular velocity decay rate
94 private Vector3 m_lastAngularVelocity = Vector3.Zero; // what was last applied to body
95 93
96 //Deflection properties 94 //Deflection properties
97 private float m_angularDeflectionEfficiency = 0; 95 private float m_angularDeflectionEfficiency = 0;
@@ -102,7 +100,7 @@ namespace OpenSim.Region.Physics.OdePlugin
102 //Banking properties 100 //Banking properties
103 private float m_bankingEfficiency = 0; 101 private float m_bankingEfficiency = 0;
104 private float m_bankingMix = 0; 102 private float m_bankingMix = 0;
105 private float m_bankingTimescale = 0; 103 private float m_bankingTimescale = 1000;
106 104
107 //Hover and Buoyancy properties 105 //Hover and Buoyancy properties
108 private float m_VhoverHeight = 0f; 106 private float m_VhoverHeight = 0f;
@@ -117,9 +115,8 @@ namespace OpenSim.Region.Physics.OdePlugin
117 private float m_verticalAttractionEfficiency = 1.0f; // damped 115 private float m_verticalAttractionEfficiency = 1.0f; // damped
118 private float m_verticalAttractionTimescale = 1000f; // Timescale > 300 means no vert attractor. 116 private float m_verticalAttractionTimescale = 1000f; // Timescale > 300 means no vert attractor.
119 117
120 // auxiliar
121 private Vector3 m_dir = Vector3.Zero; // velocity applied to body
122 118
119 // auxiliar
123 private float m_lmEfect = 0; // current linear motor eficiency 120 private float m_lmEfect = 0; // current linear motor eficiency
124 private float m_amEfect = 0; // current angular motor eficiency 121 private float m_amEfect = 0; // current angular motor eficiency
125 122
@@ -130,6 +127,82 @@ namespace OpenSim.Region.Physics.OdePlugin
130 _pParentScene = rootPrim._parent_scene; 127 _pParentScene = rootPrim._parent_scene;
131 } 128 }
132 129
130
131 public void DoSetVehicle(VehicleData vd)
132 {
133
134 float timestep = _pParentScene.ODE_STEPSIZE;
135 float invtimestep = 1.0f / timestep;
136
137 m_type = vd.m_type;
138 m_flags = vd.m_flags;
139
140 // Linear properties
141 m_linearMotorDirection = vd.m_linearMotorDirection;
142
143 m_linearFrictionTimescale = vd.m_linearFrictionTimescale;
144 if (m_linearFrictionTimescale.X < timestep) m_linearFrictionTimescale.X = timestep;
145 if (m_linearFrictionTimescale.Y < timestep) m_linearFrictionTimescale.Y = timestep;
146 if (m_linearFrictionTimescale.Z < timestep) m_linearFrictionTimescale.Z = timestep;
147
148 m_linearMotorDecayTimescale = vd.m_linearMotorDecayTimescale;
149 if (m_linearMotorDecayTimescale < 0.5f) m_linearMotorDecayTimescale = 0.5f;
150 m_linearMotorDecayTimescale *= invtimestep;
151
152 m_linearMotorTimescale = vd.m_linearMotorTimescale;
153 if (m_linearMotorTimescale < timestep) m_linearMotorTimescale = timestep;
154
155 m_linearMotorOffset = vd.m_linearMotorOffset;
156
157 //Angular properties
158 m_angularMotorDirection = vd.m_angularMotorDirection;
159 m_angularMotorTimescale = vd.m_angularMotorTimescale;
160 if (m_angularMotorTimescale < timestep) m_angularMotorTimescale = timestep;
161
162 m_angularMotorDecayTimescale = vd.m_angularMotorDecayTimescale;
163 if (m_angularMotorDecayTimescale < 0.5f) m_angularMotorDecayTimescale = 0.5f;
164 m_angularMotorDecayTimescale *= invtimestep;
165
166 m_angularFrictionTimescale = vd.m_angularFrictionTimescale;
167 if (m_angularFrictionTimescale.X < timestep) m_angularFrictionTimescale.X = timestep;
168 if (m_angularFrictionTimescale.Y < timestep) m_angularFrictionTimescale.Y = timestep;
169 if (m_angularFrictionTimescale.Z < timestep) m_angularFrictionTimescale.Z = timestep;
170
171 //Deflection properties
172 m_angularDeflectionEfficiency = vd.m_angularDeflectionEfficiency;
173 m_angularDeflectionTimescale = vd.m_angularDeflectionTimescale;
174 if (m_angularDeflectionTimescale < timestep) m_angularDeflectionTimescale = timestep;
175
176 m_linearDeflectionEfficiency = vd.m_linearDeflectionEfficiency;
177 m_linearDeflectionTimescale = vd.m_linearDeflectionTimescale;
178 if (m_linearDeflectionTimescale < timestep) m_linearDeflectionTimescale = timestep;
179
180 //Banking properties
181 m_bankingEfficiency = vd.m_bankingEfficiency;
182 m_bankingMix = vd.m_bankingMix;
183 m_bankingTimescale = vd.m_bankingTimescale;
184 if (m_bankingTimescale < timestep) m_bankingTimescale = timestep;
185
186 //Hover and Buoyancy properties
187 m_VhoverHeight = vd.m_VhoverHeight;
188 m_VhoverEfficiency = vd.m_VhoverEfficiency;
189 m_VhoverTimescale = vd.m_VhoverTimescale;
190 if (m_VhoverTimescale < timestep) m_VhoverTimescale = timestep;
191
192 m_VehicleBuoyancy = vd.m_VehicleBuoyancy;
193
194 //Attractor properties
195 m_verticalAttractionEfficiency = vd.m_verticalAttractionEfficiency;
196 m_verticalAttractionTimescale = vd.m_verticalAttractionTimescale;
197 if (m_verticalAttractionTimescale < timestep) m_verticalAttractionTimescale = timestep;
198
199 // Axis
200 m_referenceFrame = vd.m_referenceFrame;
201
202 m_lmEfect = 0;
203 m_amEfect = 0;
204 }
205
133 internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue) 206 internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue)
134 { 207 {
135 float len; 208 float len;
@@ -231,6 +304,9 @@ namespace OpenSim.Region.Physics.OdePlugin
231 if (len > 12.566f) 304 if (len > 12.566f)
232 m_angularMotorDirection *= (12.566f / len); 305 m_angularMotorDirection *= (12.566f / len);
233 m_amEfect = 1.0f; // turn it on 306 m_amEfect = 1.0f; // turn it on
307 if (rootPrim.Body != IntPtr.Zero && !d.BodyIsEnabled(rootPrim.Body)
308 && !rootPrim.m_isSelected && !rootPrim.m_disabled)
309 d.BodyEnable(rootPrim.Body);
234 break; 310 break;
235 case Vehicle.LINEAR_FRICTION_TIMESCALE: 311 case Vehicle.LINEAR_FRICTION_TIMESCALE:
236 if (pValue < timestep) pValue = timestep; 312 if (pValue < timestep) pValue = timestep;
@@ -242,6 +318,9 @@ namespace OpenSim.Region.Physics.OdePlugin
242 if (len > 30.0f) 318 if (len > 30.0f)
243 m_linearMotorDirection *= (30.0f / len); 319 m_linearMotorDirection *= (30.0f / len);
244 m_lmEfect = 1.0f; // turn it on 320 m_lmEfect = 1.0f; // turn it on
321 if (rootPrim.Body != IntPtr.Zero && !d.BodyIsEnabled(rootPrim.Body)
322 && !rootPrim.m_isSelected && !rootPrim.m_disabled)
323 d.BodyEnable(rootPrim.Body);
245 break; 324 break;
246 case Vehicle.LINEAR_MOTOR_OFFSET: 325 case Vehicle.LINEAR_MOTOR_OFFSET:
247 m_linearMotorOffset = new Vector3(pValue, pValue, pValue); 326 m_linearMotorOffset = new Vector3(pValue, pValue, pValue);
@@ -273,6 +352,9 @@ namespace OpenSim.Region.Physics.OdePlugin
273 if (len > 12.566f) 352 if (len > 12.566f)
274 m_angularMotorDirection *= (12.566f / len); 353 m_angularMotorDirection *= (12.566f / len);
275 m_amEfect = 1.0f; // turn it on 354 m_amEfect = 1.0f; // turn it on
355 if (rootPrim.Body != IntPtr.Zero && !d.BodyIsEnabled(rootPrim.Body)
356 && !rootPrim.m_isSelected && !rootPrim.m_disabled)
357 d.BodyEnable(rootPrim.Body);
276 break; 358 break;
277 case Vehicle.LINEAR_FRICTION_TIMESCALE: 359 case Vehicle.LINEAR_FRICTION_TIMESCALE:
278 if (pValue.X < timestep) pValue.X = timestep; 360 if (pValue.X < timestep) pValue.X = timestep;
@@ -286,6 +368,9 @@ namespace OpenSim.Region.Physics.OdePlugin
286 if (len > 30.0f) 368 if (len > 30.0f)
287 m_linearMotorDirection *= (30.0f / len); 369 m_linearMotorDirection *= (30.0f / len);
288 m_lmEfect = 1.0f; // turn it on 370 m_lmEfect = 1.0f; // turn it on
371 if (rootPrim.Body != IntPtr.Zero && !d.BodyIsEnabled(rootPrim.Body)
372 && !rootPrim.m_isSelected && !rootPrim.m_disabled)
373 d.BodyEnable(rootPrim.Body);
289 break; 374 break;
290 case Vehicle.LINEAR_MOTOR_OFFSET: 375 case Vehicle.LINEAR_MOTOR_OFFSET:
291 m_linearMotorOffset = new Vector3(pValue.X, pValue.Y, pValue.Z); 376 m_linearMotorOffset = new Vector3(pValue.X, pValue.Y, pValue.Z);
@@ -347,12 +432,23 @@ namespace OpenSim.Region.Physics.OdePlugin
347 m_linearFrictionTimescale = new Vector3(1000, 1000, 1000); 432 m_linearFrictionTimescale = new Vector3(1000, 1000, 1000);
348 m_angularFrictionTimescale = new Vector3(1000, 1000, 1000); 433 m_angularFrictionTimescale = new Vector3(1000, 1000, 1000);
349 m_linearMotorTimescale = 1000; 434 m_linearMotorTimescale = 1000;
350 m_linearMotorDecayTimescale = 120 * invtimestep; 435 m_linearMotorDecayTimescale = 120;
351 m_angularMotorTimescale = 1000; 436 m_angularMotorTimescale = 1000;
352 m_angularMotorDecayTimescale = 1000 * invtimestep; 437 m_angularMotorDecayTimescale = 1000;
353 m_VhoverHeight = 0; 438 m_VhoverHeight = 0;
439 m_VhoverEfficiency = 1;
354 m_VhoverTimescale = 1000; 440 m_VhoverTimescale = 1000;
355 m_VehicleBuoyancy = 0; 441 m_VehicleBuoyancy = 0;
442 m_linearDeflectionEfficiency = 0;
443 m_linearDeflectionTimescale = 1000;
444 m_angularDeflectionEfficiency = 0;
445 m_angularDeflectionTimescale = 1000;
446 m_bankingEfficiency = 0;
447 m_bankingMix = 1;
448 m_bankingTimescale = 1000;
449 m_verticalAttractionEfficiency = 0;
450 m_verticalAttractionTimescale = 1000;
451
356 m_flags = (VehicleFlag)0; 452 m_flags = (VehicleFlag)0;
357 break; 453 break;
358 454
diff --git a/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs
index 3b7f562..0ccdbc0 100644
--- a/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs
+++ b/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs
@@ -111,7 +111,7 @@ namespace OpenSim.Region.Physics.OdePlugin
111 | CollisionCategories.Body 111 | CollisionCategories.Body
112 | CollisionCategories.Character 112 | CollisionCategories.Character
113 ); 113 );
114 private bool m_collidesLand = true; 114// private bool m_collidesLand = true;
115 private bool m_collidesWater; 115 private bool m_collidesWater;
116 public bool m_returnCollisions; 116 public bool m_returnCollisions;
117 117
@@ -122,7 +122,7 @@ namespace OpenSim.Region.Physics.OdePlugin
122 private CollisionCategories m_collisionFlags = m_default_collisionFlags; 122 private CollisionCategories m_collisionFlags = m_default_collisionFlags;
123 123
124 public bool m_disabled; 124 public bool m_disabled;
125 public bool m_taintselected; 125
126 126
127 public uint m_localID; 127 public uint m_localID;
128 128
@@ -142,20 +142,19 @@ namespace OpenSim.Region.Physics.OdePlugin
142 private List<OdePrim> childrenPrim = new List<OdePrim>(); 142 private List<OdePrim> childrenPrim = new List<OdePrim>();
143 143
144 private bool m_iscolliding; 144 private bool m_iscolliding;
145 private bool m_wascolliding; 145
146 private bool m_isSelected; 146 public bool m_isSelected;
147 private bool m_delaySelect;
148 private bool m_lastdoneSelected;
149 public bool m_outbounds;
147 150
148 internal bool m_isVolumeDetect; // If true, this prim only detects collisions but doesn't collide actively 151 internal bool m_isVolumeDetect; // If true, this prim only detects collisions but doesn't collide actively
149 152
150 private bool m_throttleUpdates; 153 private bool m_throttleUpdates;
151 private int throttleCounter; 154 private int throttleCounter;
152 public int m_interpenetrationcount;
153 public float m_collisionscore; 155 public float m_collisionscore;
154 int m_colliderfilter = 0; 156 int m_colliderfilter = 0;
155 public int m_roundsUnderMotionThreshold;
156 private int m_crossingfailures;
157 157
158 public bool outofBounds;
159 private float m_density = 10.000006836f; // Aluminum g/cm3; 158 private float m_density = 10.000006836f; // Aluminum g/cm3;
160 159
161 public bool _zeroFlag; 160 public bool _zeroFlag;
@@ -166,12 +165,11 @@ namespace OpenSim.Region.Physics.OdePlugin
166 private Vector3 _target_velocity; 165 private Vector3 _target_velocity;
167 166
168 public Vector3 primOOBsize; // prim real dimensions from mesh 167 public Vector3 primOOBsize; // prim real dimensions from mesh
169 public Vector3 primOOBoffset; // is centroid out of mesh or rest aabb 168 public Vector3 primOOBoffset; // its centroid out of mesh or rest aabb
170 public float primOOBradiusSQ; 169 public float primOOBradiusSQ;
171 public d.Mass primdMass; // prim inertia information on it's own referencial 170 public d.Mass primdMass; // prim inertia information on it's own referencial
172 float primMass; // prim own mass 171 float primMass; // prim own mass
173 float _mass; // object mass acording to case 172 float _mass; // object mass acording to case
174 public d.Mass objectpMass; // object last computed inertia
175 private bool hasOOBoffsetFromMesh = false; // if true we did compute it form mesh centroid, else from aabb 173 private bool hasOOBoffsetFromMesh = false; // if true we did compute it form mesh centroid, else from aabb
176 174
177 public int givefakepos = 0; 175 public int givefakepos = 0;
@@ -182,9 +180,6 @@ namespace OpenSim.Region.Physics.OdePlugin
182 public int m_eventsubscription; 180 public int m_eventsubscription;
183 private CollisionEventUpdate CollisionEventsThisFrame = new CollisionEventUpdate(); 181 private CollisionEventUpdate CollisionEventsThisFrame = new CollisionEventUpdate();
184 182
185 private IntPtr m_linkJoint = IntPtr.Zero;
186 private IntPtr _linkJointGroup = IntPtr.Zero;
187
188 public volatile bool childPrim; 183 public volatile bool childPrim;
189 184
190 public ODEDynamics m_vehicle; 185 public ODEDynamics m_vehicle;
@@ -264,7 +259,7 @@ namespace OpenSim.Region.Physics.OdePlugin
264 set 259 set
265 { 260 {
266 if (value) 261 if (value)
267 m_isSelected = value; 262 m_isSelected = value; // if true set imediatly to stop moves etc
268 AddChange(changes.Selected, value); 263 AddChange(changes.Selected, value);
269 } 264 }
270 } 265 }
@@ -298,13 +293,6 @@ namespace OpenSim.Region.Physics.OdePlugin
298 m_iscolliding = false; 293 m_iscolliding = false;
299 else 294 else
300 m_iscolliding = true; 295 m_iscolliding = true;
301
302 if (m_wascolliding != m_iscolliding)
303 {
304 if (m_wascolliding && !m_isSelected && Body != IntPtr.Zero)
305 d.BodyEnable(Body);
306 m_wascolliding = m_iscolliding;
307 }
308 } 296 }
309 } 297 }
310 298
@@ -665,19 +653,21 @@ namespace OpenSim.Region.Physics.OdePlugin
665 strVehicleQuatParam fp = new strVehicleQuatParam(); 653 strVehicleQuatParam fp = new strVehicleQuatParam();
666 fp.param = param; 654 fp.param = param;
667 fp.value = value; 655 fp.value = value;
668 AddChange(changes.VehicleVectorParam, fp); 656 AddChange(changes.VehicleRotationParam, fp);
669 } 657 }
670 658
671 public override void VehicleFlags(int param, bool value) 659 public override void VehicleFlags(int param, bool value)
672 { 660 {
673 if (m_vehicle == null)
674 return;
675 strVehicleBoolParam bp = new strVehicleBoolParam(); 661 strVehicleBoolParam bp = new strVehicleBoolParam();
676 bp.param = param; 662 bp.param = param;
677 bp.value = value; 663 bp.value = value;
678 AddChange(changes.VehicleFlags, bp); 664 AddChange(changes.VehicleFlags, bp);
679 } 665 }
680 666
667 public override void SetVehicle(object vdata)
668 {
669 AddChange(changes.SetVehicle, vdata);
670 }
681 public void SetAcceleration(Vector3 accel) 671 public void SetAcceleration(Vector3 accel)
682 { 672 {
683 _acceleration = accel; 673 _acceleration = accel;
@@ -710,8 +700,30 @@ namespace OpenSim.Region.Physics.OdePlugin
710 700
711 public override void CrossingFailure() 701 public override void CrossingFailure()
712 { 702 {
713 m_crossingfailures++; 703 if (m_outbounds)
714 changeDisable(false); 704 {
705 _position.X = Util.Clip(_position.X, 0.5f, _parent_scene.WorldExtents.X - 0.5f);
706 _position.Y = Util.Clip(_position.Y, 0.5f, _parent_scene.WorldExtents.Y - 0.5f);
707 _position.Z = Util.Clip(_position.Z + 0.2f, -100f, 50000f);
708
709 m_lastposition = _position;
710 _velocity.X = 0;
711 _velocity.Y = 0;
712 _velocity.Z = 0;
713
714 m_lastVelocity = _velocity;
715 if (m_vehicle != null && m_vehicle.Type != Vehicle.TYPE_NONE)
716 m_vehicle.Stop();
717
718 if(Body != IntPtr.Zero)
719 d.BodySetLinearVel(Body, 0, 0, 0); // stop it
720 if (prim_geom != IntPtr.Zero)
721 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
722
723 m_outbounds = false;
724 changeDisable(false);
725 base.RequestPhysicsterseUpdate();
726 }
715 } 727 }
716 728
717 public override void SetMomentum(Vector3 momentum) 729 public override void SetMomentum(Vector3 momentum)
@@ -865,12 +877,14 @@ namespace OpenSim.Region.Physics.OdePlugin
865 m_force = Vector3.Zero; 877 m_force = Vector3.Zero;
866 878
867 m_iscolliding = false; 879 m_iscolliding = false;
868 m_wascolliding = false;
869 m_colliderfilter = 0; 880 m_colliderfilter = 0;
870 881
871 hasOOBoffsetFromMesh = false; 882 hasOOBoffsetFromMesh = false;
872 _triMeshData = IntPtr.Zero; 883 _triMeshData = IntPtr.Zero;
873 884
885 m_lastdoneSelected = false;
886 m_isSelected = false;
887 m_delaySelect = false;
874 888
875 primContactData.mu = parent_scene.m_materialContactsData[(int)Material.Wood].mu; 889 primContactData.mu = parent_scene.m_materialContactsData[(int)Material.Wood].mu;
876 primContactData.bounce = parent_scene.m_materialContactsData[(int)Material.Wood].bounce; 890 primContactData.bounce = parent_scene.m_materialContactsData[(int)Material.Wood].bounce;
@@ -885,8 +899,6 @@ namespace OpenSim.Region.Physics.OdePlugin
885 private void resetCollisionAccounting() 899 private void resetCollisionAccounting()
886 { 900 {
887 m_collisionscore = 0; 901 m_collisionscore = 0;
888 m_interpenetrationcount = 0;
889 m_disabled = false;
890 } 902 }
891 903
892 private void createAMotor(Vector3 axis) 904 private void createAMotor(Vector3 axis)
@@ -926,9 +938,6 @@ namespace OpenSim.Region.Physics.OdePlugin
926 curr.W = dcur.W; 938 curr.W = dcur.W;
927 Vector3 ax; 939 Vector3 ax;
928 940
929 const int StopERP = 7;
930 const int StopCFM = 8;
931
932 int i = 0; 941 int i = 0;
933 int j = 0; 942 int j = 0;
934 if (axis.X == 0) 943 if (axis.X == 0)
@@ -943,10 +952,10 @@ namespace OpenSim.Region.Physics.OdePlugin
943 d.JointSetAMotorParam(Amotor, (int)d.JointParam.FudgeFactor, 0.0001f); 952 d.JointSetAMotorParam(Amotor, (int)d.JointParam.FudgeFactor, 0.0001f);
944 d.JointSetAMotorParam(Amotor, (int)d.JointParam.Bounce, 0f); 953 d.JointSetAMotorParam(Amotor, (int)d.JointParam.Bounce, 0f);
945 d.JointSetAMotorParam(Amotor, (int)d.JointParam.FMax, 5e8f); 954 d.JointSetAMotorParam(Amotor, (int)d.JointParam.FMax, 5e8f);
946 d.JointSetAMotorParam(Amotor, (int)StopCFM, 0f); 955 d.JointSetAMotorParam(Amotor, (int)d.JointParam.StopCFM, 0f);
947 d.JointSetAMotorParam(Amotor, (int)StopERP, 0.8f); 956 d.JointSetAMotorParam(Amotor, (int)d.JointParam.StopERP, 0.8f);
948 i++; 957 i++;
949 j = 256; // odeplugin.cs doesn't have all parameters so this moves to next axis set 958 j = 256; // move to next axis set
950 } 959 }
951 960
952 if (axis.Y == 0) 961 if (axis.Y == 0)
@@ -960,8 +969,8 @@ namespace OpenSim.Region.Physics.OdePlugin
960 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.FudgeFactor, 0.0001f); 969 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.FudgeFactor, 0.0001f);
961 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.Bounce, 0f); 970 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.Bounce, 0f);
962 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.FMax, 5e8f); 971 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.FMax, 5e8f);
963 d.JointSetAMotorParam(Amotor, j + (int)StopCFM, 0f); 972 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.StopCFM, 0f);
964 d.JointSetAMotorParam(Amotor, j + (int)StopERP, 0.8f); 973 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.StopERP, 0.8f);
965 i++; 974 i++;
966 j += 256; 975 j += 256;
967 } 976 }
@@ -977,8 +986,8 @@ namespace OpenSim.Region.Physics.OdePlugin
977 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.FudgeFactor, 0.0001f); 986 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.FudgeFactor, 0.0001f);
978 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.Bounce, 0f); 987 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.Bounce, 0f);
979 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.FMax, 5e8f); 988 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.FMax, 5e8f);
980 d.JointSetAMotorParam(Amotor, j + (int)StopCFM, 0f); 989 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.StopCFM, 0f);
981 d.JointSetAMotorParam(Amotor, j + (int)StopERP, 0.8f); 990 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.StopERP, 0.8f);
982 } 991 }
983 } 992 }
984 993
@@ -1186,24 +1195,10 @@ namespace OpenSim.Region.Physics.OdePlugin
1186 1195
1187 public void enableBodySoft() 1196 public void enableBodySoft()
1188 { 1197 {
1189 if (!childPrim) 1198 if (!childPrim && !m_isSelected)
1190 { 1199 {
1191 if (m_isphysical && Body != IntPtr.Zero && prim_geom != IntPtr.Zero) 1200 if (m_isphysical && Body != IntPtr.Zero && prim_geom != IntPtr.Zero)
1192 { 1201 {
1193 if (m_targetSpace != _parent_scene.ActiveSpace)
1194 {
1195 m_targetSpace = _parent_scene.ActiveSpace;
1196
1197 foreach (OdePrim prm in childrenPrim)
1198 {
1199 if (prm.prim_geom != IntPtr.Zero)
1200 {
1201 d.SpaceAdd(m_targetSpace, prm.prim_geom);
1202 prm.m_targetSpace = m_targetSpace;
1203 }
1204 }
1205 d.SpaceAdd(m_targetSpace, prim_geom);
1206 }
1207 d.GeomEnable(prim_geom); 1202 d.GeomEnable(prim_geom);
1208 foreach (OdePrim prm in childrenPrim) 1203 foreach (OdePrim prm in childrenPrim)
1209 d.GeomEnable(prm.prim_geom); 1204 d.GeomEnable(prm.prim_geom);
@@ -1211,6 +1206,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1211 d.BodyEnable(Body); 1206 d.BodyEnable(Body);
1212 } 1207 }
1213 } 1208 }
1209 m_disabled = false;
1214 resetCollisionAccounting(); // this sets m_disable to false 1210 resetCollisionAccounting(); // this sets m_disable to false
1215 } 1211 }
1216 1212
@@ -1221,19 +1217,6 @@ namespace OpenSim.Region.Physics.OdePlugin
1221 { 1217 {
1222 if (m_isphysical && Body != IntPtr.Zero && prim_geom != IntPtr.Zero) 1218 if (m_isphysical && Body != IntPtr.Zero && prim_geom != IntPtr.Zero)
1223 { 1219 {
1224 if (m_targetSpace == _parent_scene.ActiveSpace)
1225 {
1226 foreach (OdePrim prm in childrenPrim)
1227 {
1228 if (prm.m_targetSpace != IntPtr.Zero && prm.prim_geom != IntPtr.Zero)
1229 {
1230 d.SpaceRemove(prm.m_targetSpace, prm.prim_geom);
1231 prm.m_targetSpace = IntPtr.Zero;
1232 }
1233 }
1234 d.SpaceRemove(m_targetSpace, prim_geom);
1235 m_targetSpace = IntPtr.Zero;
1236 }
1237 d.GeomDisable(prim_geom); 1220 d.GeomDisable(prim_geom);
1238 foreach (OdePrim prm in childrenPrim) 1221 foreach (OdePrim prm in childrenPrim)
1239 d.GeomDisable(prm.prim_geom); 1222 d.GeomDisable(prm.prim_geom);
@@ -1369,9 +1352,6 @@ namespace OpenSim.Region.Physics.OdePlugin
1369 d.BodySetMass(Body, ref objdmass); 1352 d.BodySetMass(Body, ref objdmass);
1370 _mass = objdmass.mass; 1353 _mass = objdmass.mass;
1371 1354
1372 m_collisionCategories |= CollisionCategories.Body;
1373 m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind);
1374
1375 // disconnect from world gravity so we can apply buoyancy 1355 // disconnect from world gravity so we can apply buoyancy
1376 d.BodySetGravityMode(Body, false); 1356 d.BodySetGravityMode(Body, false);
1377 1357
@@ -1379,16 +1359,14 @@ namespace OpenSim.Region.Physics.OdePlugin
1379 d.BodySetAutoDisableSteps(Body, body_autodisable_frames); 1359 d.BodySetAutoDisableSteps(Body, body_autodisable_frames);
1380 // d.BodySetLinearDampingThreshold(Body, 0.01f); 1360 // d.BodySetLinearDampingThreshold(Body, 0.01f);
1381 // d.BodySetAngularDampingThreshold(Body, 0.001f); 1361 // d.BodySetAngularDampingThreshold(Body, 0.001f);
1382 d.BodySetDamping(Body, .001f, .0002f); 1362 d.BodySetDamping(Body, .002f, .002f);
1383 1363
1364 m_collisionCategories |= CollisionCategories.Body;
1365 m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind);
1384 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); 1366 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
1385 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); 1367 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
1386
1387 m_interpenetrationcount = 0;
1388 m_collisionscore = 0; 1368 m_collisionscore = 0;
1389 1369
1390 m_disabled = false;
1391
1392 if (m_targetSpace != _parent_scene.ActiveSpace) 1370 if (m_targetSpace != _parent_scene.ActiveSpace)
1393 { 1371 {
1394 if (m_targetSpace != IntPtr.Zero) 1372 if (m_targetSpace != IntPtr.Zero)
@@ -1416,6 +1394,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1416 prm.m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind); 1394 prm.m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind);
1417 d.GeomSetCategoryBits(prm.prim_geom, (int)prm.m_collisionCategories); 1395 d.GeomSetCategoryBits(prm.prim_geom, (int)prm.m_collisionCategories);
1418 d.GeomSetCollideBits(prm.prim_geom, (int)prm.m_collisionFlags); 1396 d.GeomSetCollideBits(prm.prim_geom, (int)prm.m_collisionFlags);
1397 prm.m_collisionscore = 0;
1419 1398
1420 if (prm.m_targetSpace != _parent_scene.ActiveSpace) 1399 if (prm.m_targetSpace != _parent_scene.ActiveSpace)
1421 { 1400 {
@@ -1428,10 +1407,11 @@ namespace OpenSim.Region.Physics.OdePlugin
1428 prm.m_targetSpace = _parent_scene.ActiveSpace; 1407 prm.m_targetSpace = _parent_scene.ActiveSpace;
1429 d.SpaceAdd(m_targetSpace, prm.prim_geom); 1408 d.SpaceAdd(m_targetSpace, prm.prim_geom);
1430 } 1409 }
1431 d.GeomEnable(prm.prim_geom); 1410
1411 if (m_isSelected || m_disabled)
1412 d.GeomDisable(prm.prim_geom);
1413
1432 prm.m_disabled = false; 1414 prm.m_disabled = false;
1433 prm.m_interpenetrationcount = 0;
1434 prm.m_collisionscore = 0;
1435 _parent_scene.addActivePrim(prm); 1415 _parent_scene.addActivePrim(prm);
1436 } 1416 }
1437 } 1417 }
@@ -1442,8 +1422,12 @@ namespace OpenSim.Region.Physics.OdePlugin
1442 createAMotor(m_angularlock); 1422 createAMotor(m_angularlock);
1443 } 1423 }
1444 1424
1445 d.GeomEnable(prim_geom); 1425 if (m_isSelected || m_disabled)
1446 m_disabled = false; 1426 {
1427 d.GeomDisable(prim_geom);
1428 d.BodyDisable(Body);
1429 }
1430
1447 _parent_scene.addActivePrim(this); 1431 _parent_scene.addActivePrim(this);
1448 } 1432 }
1449 1433
@@ -1484,12 +1468,16 @@ namespace OpenSim.Region.Physics.OdePlugin
1484 prm.m_collisionscore = 0; 1468 prm.m_collisionscore = 0;
1485 } 1469 }
1486 } 1470 }
1471 if (Amotor != IntPtr.Zero)
1472 {
1473 d.JointDestroy(Amotor);
1474 Amotor = IntPtr.Zero;
1475 }
1487 d.BodyDestroy(Body); 1476 d.BodyDestroy(Body);
1488 } 1477 }
1489 Body = IntPtr.Zero; 1478 Body = IntPtr.Zero;
1490 } 1479 }
1491 _mass = primMass; 1480 _mass = primMass;
1492 m_disabled = true;
1493 m_collisionscore = 0; 1481 m_collisionscore = 0;
1494 } 1482 }
1495 1483
@@ -2115,49 +2103,72 @@ namespace OpenSim.Region.Physics.OdePlugin
2115 d.BodySetTorque(Body, 0f, 0f, 0f); 2103 d.BodySetTorque(Body, 0f, 0f, 0f);
2116 d.BodySetLinearVel(Body, 0f, 0f, 0f); 2104 d.BodySetLinearVel(Body, 0f, 0f, 0f);
2117 d.BodySetAngularVel(Body, 0f, 0f, 0f); 2105 d.BodySetAngularVel(Body, 0f, 0f, 0f);
2118
2119 } 2106 }
2120 } 2107 }
2121 2108
2122 private void changeSelectedStatus(bool newval) 2109 private void changeSelectedStatus(bool newval)
2123 { 2110 {
2111 if (m_lastdoneSelected == newval)
2112 return;
2113
2114 m_lastdoneSelected = newval;
2115 DoSelectedStatus(newval);
2116 }
2117
2118 private void CheckDelaySelect()
2119 {
2120 if (m_delaySelect)
2121 {
2122 DoSelectedStatus(m_isSelected);
2123 }
2124 }
2125
2126 private void DoSelectedStatus(bool newval)
2127 {
2124 m_isSelected = newval; 2128 m_isSelected = newval;
2125 Stop(); 2129 Stop();
2126 2130
2127 if (newval) 2131 if (newval)
2128 { 2132 {
2129 m_collisionCategories = CollisionCategories.Selected; 2133 if (!childPrim && Body != IntPtr.Zero)
2130 m_collisionFlags = (CollisionCategories.Sensor | CollisionCategories.Space); 2134 d.BodyDisable(Body);
2131 2135
2132 if (prim_geom != IntPtr.Zero) 2136 if (m_delaySelect)
2133 { 2137 {
2134 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); 2138 if (!childPrim)
2135 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); 2139 {
2140 foreach (OdePrim prm in childrenPrim)
2141 {
2142 d.GeomDisable(prm.prim_geom);
2143 prm.m_delaySelect = false;
2144 }
2145 }
2146 d.GeomDisable(prim_geom);
2147 m_delaySelect = false;
2148 }
2149 else
2150 {
2151 m_delaySelect = true;
2136 } 2152 }
2137
2138 disableBodySoft();
2139 } 2153 }
2140 else 2154 else
2141 { 2155 {
2142 m_collisionCategories = CollisionCategories.Geom; 2156 if (!childPrim && Body != IntPtr.Zero && !m_disabled)
2143 2157 d.BodyEnable(Body);
2144 if (m_isphysical)
2145 m_collisionCategories |= CollisionCategories.Body;
2146
2147 m_collisionFlags = m_default_collisionFlags;
2148
2149 if (m_collidesLand)
2150 m_collisionFlags |= CollisionCategories.Land;
2151 if (m_collidesWater)
2152 m_collisionFlags |= CollisionCategories.Water;
2153 2158
2154 if (prim_geom != IntPtr.Zero) 2159 if (!childPrim)
2155 { 2160 {
2156 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); 2161 foreach (OdePrim prm in childrenPrim)
2157 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); 2162 {
2163 if(!prm.m_disabled)
2164 d.GeomEnable(prm.prim_geom);
2165 prm.m_delaySelect = false;
2166 }
2158 } 2167 }
2168 if(!m_disabled)
2169 d.GeomEnable(prim_geom);
2159 2170
2160 enableBodySoft(); 2171 m_delaySelect = false;
2161 } 2172 }
2162 2173
2163 resetCollisionAccounting(); 2174 resetCollisionAccounting();
@@ -2165,6 +2176,7 @@ namespace OpenSim.Region.Physics.OdePlugin
2165 2176
2166 private void changePosition(Vector3 newPos) 2177 private void changePosition(Vector3 newPos)
2167 { 2178 {
2179 CheckDelaySelect();
2168 if (m_isphysical) 2180 if (m_isphysical)
2169 { 2181 {
2170 if (childPrim) // inertia is messed, must rebuild 2182 if (childPrim) // inertia is messed, must rebuild
@@ -2207,6 +2219,7 @@ namespace OpenSim.Region.Physics.OdePlugin
2207 2219
2208 private void changeOrientation(Quaternion newOri) 2220 private void changeOrientation(Quaternion newOri)
2209 { 2221 {
2222 CheckDelaySelect();
2210 if (m_isphysical) 2223 if (m_isphysical)
2211 { 2224 {
2212 if (childPrim) // inertia is messed, must rebuild 2225 if (childPrim) // inertia is messed, must rebuild
@@ -2258,6 +2271,7 @@ namespace OpenSim.Region.Physics.OdePlugin
2258 2271
2259 private void changePositionAndOrientation(Vector3 newPos, Quaternion newOri) 2272 private void changePositionAndOrientation(Vector3 newPos, Quaternion newOri)
2260 { 2273 {
2274 CheckDelaySelect();
2261 if (m_isphysical) 2275 if (m_isphysical)
2262 { 2276 {
2263 if (childPrim && m_building) // inertia is messed, must rebuild 2277 if (childPrim && m_building) // inertia is messed, must rebuild
@@ -2342,6 +2356,8 @@ namespace OpenSim.Region.Physics.OdePlugin
2342 2356
2343 private void changePhysicsStatus(bool NewStatus) 2357 private void changePhysicsStatus(bool NewStatus)
2344 { 2358 {
2359 CheckDelaySelect();
2360
2345 m_isphysical = NewStatus; 2361 m_isphysical = NewStatus;
2346 2362
2347 if (!childPrim) 2363 if (!childPrim)
@@ -2384,6 +2400,8 @@ namespace OpenSim.Region.Physics.OdePlugin
2384 2400
2385 private void changeprimsizeshape() 2401 private void changeprimsizeshape()
2386 { 2402 {
2403 CheckDelaySelect();
2404
2387 OdePrim parent = (OdePrim)_parent; 2405 OdePrim parent = (OdePrim)_parent;
2388 2406
2389 bool chp = childPrim; 2407 bool chp = childPrim;
@@ -2508,7 +2526,6 @@ namespace OpenSim.Region.Physics.OdePlugin
2508 } 2526 }
2509 2527
2510 m_collisionscore = 0; 2528 m_collisionscore = 0;
2511 m_interpenetrationcount = 0;
2512 } 2529 }
2513 } 2530 }
2514 2531
@@ -2528,7 +2545,6 @@ namespace OpenSim.Region.Physics.OdePlugin
2528 } 2545 }
2529 } 2546 }
2530 m_collisionscore = 0; 2547 m_collisionscore = 0;
2531 m_interpenetrationcount = 0;
2532 } 2548 }
2533 } 2549 }
2534 2550
@@ -2565,6 +2581,7 @@ namespace OpenSim.Region.Physics.OdePlugin
2565 else 2581 else
2566 { 2582 {
2567 m_building = false; 2583 m_building = false;
2584 CheckDelaySelect();
2568 if (!childPrim) 2585 if (!childPrim)
2569 MakeBody(); 2586 MakeBody();
2570 } 2587 }
@@ -2575,18 +2592,26 @@ namespace OpenSim.Region.Physics.OdePlugin
2575 } 2592 }
2576 } 2593 }
2577 2594
2578 private void changeVehicleType(int value) 2595 public void changeSetVehicle(VehicleData vdata)
2579 { 2596 {
2580 if (m_vehicle == null) 2597 if (m_vehicle == null)
2598 m_vehicle = new ODEDynamics(this);
2599 m_vehicle.DoSetVehicle(vdata);
2600 }
2601 private void changeVehicleType(int value)
2602 {
2603 if (value == (int)Vehicle.TYPE_NONE)
2581 { 2604 {
2582 if (value != (int)Vehicle.TYPE_NONE) 2605 if (m_vehicle != null)
2583 { 2606 m_vehicle = null;
2584 m_vehicle = new ODEDynamics(this);
2585 m_vehicle.ProcessTypeChange((Vehicle)value);
2586 }
2587 } 2607 }
2588 else 2608 else
2609 {
2610 if (m_vehicle == null)
2611 m_vehicle = new ODEDynamics(this);
2612
2589 m_vehicle.ProcessTypeChange((Vehicle)value); 2613 m_vehicle.ProcessTypeChange((Vehicle)value);
2614 }
2590 } 2615 }
2591 2616
2592 private void changeVehicleFloatParam(strVehicleFloatParam fp) 2617 private void changeVehicleFloatParam(strVehicleFloatParam fp)
@@ -2595,8 +2620,6 @@ namespace OpenSim.Region.Physics.OdePlugin
2595 return; 2620 return;
2596 2621
2597 m_vehicle.ProcessFloatVehicleParam((Vehicle)fp.param, fp.value); 2622 m_vehicle.ProcessFloatVehicleParam((Vehicle)fp.param, fp.value);
2598 if (Body != IntPtr.Zero && !d.BodyIsEnabled(Body))
2599 d.BodyEnable(Body);
2600 } 2623 }
2601 2624
2602 private void changeVehicleVectorParam(strVehicleVectorParam vp) 2625 private void changeVehicleVectorParam(strVehicleVectorParam vp)
@@ -2604,8 +2627,6 @@ namespace OpenSim.Region.Physics.OdePlugin
2604 if (m_vehicle == null) 2627 if (m_vehicle == null)
2605 return; 2628 return;
2606 m_vehicle.ProcessVectorVehicleParam((Vehicle)vp.param, vp.value); 2629 m_vehicle.ProcessVectorVehicleParam((Vehicle)vp.param, vp.value);
2607 if (Body != IntPtr.Zero && !d.BodyIsEnabled(Body))
2608 d.BodyEnable(Body);
2609 } 2630 }
2610 2631
2611 private void changeVehicleRotationParam(strVehicleQuatParam qp) 2632 private void changeVehicleRotationParam(strVehicleQuatParam qp)
@@ -2613,8 +2634,6 @@ namespace OpenSim.Region.Physics.OdePlugin
2613 if (m_vehicle == null) 2634 if (m_vehicle == null)
2614 return; 2635 return;
2615 m_vehicle.ProcessRotationVehicleParam((Vehicle)qp.param, qp.value); 2636 m_vehicle.ProcessRotationVehicleParam((Vehicle)qp.param, qp.value);
2616 if (Body != IntPtr.Zero && !d.BodyIsEnabled(Body))
2617 d.BodyEnable(Body);
2618 } 2637 }
2619 2638
2620 private void changeVehicleFlags(strVehicleBoolParam bp) 2639 private void changeVehicleFlags(strVehicleBoolParam bp)
@@ -2622,8 +2641,6 @@ namespace OpenSim.Region.Physics.OdePlugin
2622 if (m_vehicle == null) 2641 if (m_vehicle == null)
2623 return; 2642 return;
2624 m_vehicle.ProcessVehicleFlags(bp.param, bp.value); 2643 m_vehicle.ProcessVehicleFlags(bp.param, bp.value);
2625 if (Body != IntPtr.Zero && !d.BodyIsEnabled(Body))
2626 d.BodyEnable(Body);
2627 } 2644 }
2628 2645
2629 #endregion 2646 #endregion
@@ -2849,41 +2866,6 @@ namespace OpenSim.Region.Physics.OdePlugin
2849 { 2866 {
2850 if (Body != IntPtr.Zero) 2867 if (Body != IntPtr.Zero)
2851 { 2868 {
2852 if (m_crossingfailures != 0 && m_crossingfailures < 5)
2853 {
2854 _position.X = Util.Clip(_position.X, 0.4f, _parent_scene.WorldExtents.X - 0.4f);
2855 _position.Y = Util.Clip(_position.Y, 0.4f, _parent_scene.WorldExtents.Y - 0.4f);
2856 _position.Z = Util.Clip(_position.Z + 0.2f, -100f, 50000f);
2857
2858 float tmp = _parent_scene.GetTerrainHeightAtXY(_position.X, _position.Y);
2859 if (_position.Z < tmp)
2860 _position.Z = tmp + 0.2f;
2861
2862 m_lastposition = _position;
2863 m_lastorientation = _orientation;
2864 _velocity.X = 0;
2865 _velocity.Y = 0;
2866 _velocity.Z = 0;
2867
2868 m_lastVelocity = _velocity;
2869 m_rotationalVelocity = _velocity;
2870 if (m_vehicle != null && m_vehicle.Type != Vehicle.TYPE_NONE)
2871 m_vehicle.Stop();
2872
2873 m_crossingfailures = 0; // do this only once
2874 d.BodySetLinearVel(Body, 0, 0, 0); // stop it
2875 d.BodySetAngularVel(Body, 0, 0, 0);
2876 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
2877 enableBodySoft();
2878 base.RequestPhysicsterseUpdate();
2879 return;
2880 }
2881
2882 else if (m_crossingfailures != 0)
2883 {
2884 return;
2885 }
2886
2887 Vector3 pv = Vector3.Zero; 2869 Vector3 pv = Vector3.Zero;
2888 bool lastZeroFlag = _zeroFlag; 2870 bool lastZeroFlag = _zeroFlag;
2889 2871
@@ -2899,24 +2881,21 @@ namespace OpenSim.Region.Physics.OdePlugin
2899 // we can't let it keeping moving and having colisions 2881 // we can't let it keeping moving and having colisions
2900 // since it can be stucked between something like terrain and edge 2882 // since it can be stucked between something like terrain and edge
2901 // so lets stop and disable it until something else kicks it 2883 // so lets stop and disable it until something else kicks it
2902 if (m_crossingfailures == 0)
2903 {
2904 2884
2905 _position.X = Util.Clip(lpos.X, -0.5f, _parent_scene.WorldExtents.X + 0.5f); 2885 _position.X = Util.Clip(lpos.X, -0.2f, _parent_scene.WorldExtents.X + 0.2f);
2906 _position.Y = Util.Clip(lpos.Y, -0.5f, _parent_scene.WorldExtents.Y + 0.5f); 2886 _position.Y = Util.Clip(lpos.Y, -0.2f, _parent_scene.WorldExtents.Y + 0.2f);
2907 _position.Z = Util.Clip(lpos.Z, -100f, 50000f); 2887 _position.Z = Util.Clip(lpos.Z, -100f, 50000f);
2908 2888
2909 m_lastposition = _position; 2889 m_lastposition = _position;
2910 m_lastorientation = _orientation; 2890// m_lastorientation = _orientation;
2911 2891
2912 d.BodySetLinearVel(Body, 0, 0, 0); // stop it 2892 d.BodySetLinearVel(Body, 0, 0, 0); // stop it
2913 d.BodySetAngularVel(Body, 0, 0, 0); 2893// d.BodySetAngularVel(Body, 0, 0, 0);
2914 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z); 2894 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
2915 disableBodySoft(); // stop collisions 2895 disableBodySoft(); // stop collisions
2916 m_crossingfailures++; // do this only once 2896 m_outbounds = true;
2917 base.RequestPhysicsterseUpdate(); 2897 base.RequestPhysicsterseUpdate();
2918 return; 2898 return;
2919 }
2920 } 2899 }
2921 2900
2922 if (lpos.Z < -100 || lpos.Z > 100000f) 2901 if (lpos.Z < -100 || lpos.Z > 100000f)
@@ -3159,6 +3138,7 @@ namespace OpenSim.Region.Physics.OdePlugin
3159 else 3138 else
3160 ChildRemove(this, false); 3139 ChildRemove(this, false);
3161 3140
3141 m_vehicle = null;
3162 RemoveGeom(); 3142 RemoveGeom();
3163 m_targetSpace = IntPtr.Zero; 3143 m_targetSpace = IntPtr.Zero;
3164 if (m_eventsubscription > 0) 3144 if (m_eventsubscription > 0)
@@ -3273,6 +3253,9 @@ namespace OpenSim.Region.Physics.OdePlugin
3273 changeVehicleRotationParam((strVehicleQuatParam) arg); 3253 changeVehicleRotationParam((strVehicleQuatParam) arg);
3274 break; 3254 break;
3275 3255
3256 case changes.SetVehicle:
3257 changeSetVehicle((VehicleData) arg);
3258 break;
3276 case changes.Null: 3259 case changes.Null:
3277 donullchange(); 3260 donullchange();
3278 break; 3261 break;
diff --git a/OpenSim/Region/Physics/UbitOdePlugin/OdeApi.cs b/OpenSim/Region/Physics/UbitOdePlugin/OdeApi.cs
index e62746e..2b6bc59 100644
--- a/OpenSim/Region/Physics/UbitOdePlugin/OdeApi.cs
+++ b/OpenSim/Region/Physics/UbitOdePlugin/OdeApi.cs
@@ -1,4 +1,3 @@
1
2/* 1/*
3 * based on: 2 * based on:
4 * Ode.NET - .NET bindings for ODE 3 * Ode.NET - .NET bindings for ODE
diff --git a/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs b/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs
index 56f3786..6e4c373 100644
--- a/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs
+++ b/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs
@@ -137,6 +137,7 @@ namespace OpenSim.Region.Physics.OdePlugin
137 VehicleVectorParam, 137 VehicleVectorParam,
138 VehicleRotationParam, 138 VehicleRotationParam,
139 VehicleFlags, 139 VehicleFlags,
140 SetVehicle,
140 141
141 Null //keep this last used do dim the methods array. does nothing but pulsing the prim 142 Null //keep this last used do dim the methods array. does nothing but pulsing the prim
142 } 143 }
@@ -166,8 +167,8 @@ namespace OpenSim.Region.Physics.OdePlugin
166 167
167 float frictionMovementMult = 0.3f; 168 float frictionMovementMult = 0.3f;
168 169
169 float TerrainBounce = 0.3f; 170 float TerrainBounce = 0.1f;
170 float TerrainFriction = 0.3f; 171 float TerrainFriction = 0.1f;
171 172
172 public float AvatarBounce = 0.3f; 173 public float AvatarBounce = 0.3f;
173 public float AvatarFriction = 0;// 0.9f * 0.5f; 174 public float AvatarFriction = 0;// 0.9f * 0.5f;
@@ -989,145 +990,62 @@ namespace OpenSim.Region.Physics.OdePlugin
989 /// <param name="timeStep"></param> 990 /// <param name="timeStep"></param>
990 private void collision_optimized() 991 private void collision_optimized()
991 { 992 {
992// _perloopContact.Clear();
993// clear characts IsColliding until we do it some other way
994
995 lock (_characters) 993 lock (_characters)
996 { 994 {
997 foreach (OdeCharacter chr in _characters) 995 try
996 {
997 foreach (OdeCharacter chr in _characters)
998 { 998 {
999 // this are odd checks if they are needed something is wrong elsewhere 999 if (chr == null || chr.Shell == IntPtr.Zero || chr.Body == IntPtr.Zero)
1000 // keep for now 1000 continue;
1001 if (chr == null) 1001
1002 continue; 1002 chr.IsColliding = false;
1003 1003 // chr.CollidingGround = false; not done here
1004 if (chr.Shell == IntPtr.Zero || chr.Body == IntPtr.Zero) 1004 chr.CollidingObj = false;
1005 continue; 1005 // do colisions with static space
1006 1006 d.SpaceCollide2(StaticSpace, chr.Shell, IntPtr.Zero, nearCallback);
1007 chr.IsColliding = false;
1008 // chr.CollidingGround = false; not done here
1009 chr.CollidingObj = false;
1010 } 1007 }
1011 } 1008 }
1012 1009 catch (AccessViolationException)
1013 // now let ode do its job
1014 // colide active things amoung them
1015
1016 int st = Util.EnvironmentTickCount();
1017 int ta;
1018 int ts;
1019 try
1020 {
1021 d.SpaceCollide(ActiveSpace, IntPtr.Zero, nearCallback);
1022 }
1023 catch (AccessViolationException)
1024 { 1010 {
1025 m_log.Warn("[PHYSICS]: Unable to Active space collide"); 1011 m_log.Warn("[PHYSICS]: Unable to collide Character to static space");
1026 } 1012 }
1027 ta = Util.EnvironmentTickCountSubtract(st); 1013
1028 // then active things with static enviroment 1014 }
1029 try 1015
1016 // collide active prims with static enviroment
1017 lock (_activeprims)
1018 {
1019 try
1030 { 1020 {
1031 d.SpaceCollide2(ActiveSpace,StaticSpace, IntPtr.Zero, nearCallback); 1021 foreach (OdePrim prm in _activeprims)
1022 {
1023 if (d.BodyIsEnabled(prm.Body))
1024 d.SpaceCollide2(StaticSpace, prm.prim_geom, IntPtr.Zero, nearCallback);
1025 }
1032 } 1026 }
1033 catch (AccessViolationException) 1027 catch (AccessViolationException)
1034 { 1028 {
1035 m_log.Warn("[PHYSICS]: Unable to Active to static space collide"); 1029 m_log.Warn("[PHYSICS]: Unable to collide Active prim to static space");
1036 } 1030 }
1037 ts = Util.EnvironmentTickCountSubtract(st);
1038// _perloopContact.Clear();
1039 }
1040
1041 #endregion
1042
1043
1044 public float GetTerrainHeightAtXY(float x, float y)
1045 {
1046 // assumes 1m size grid and constante size square regions
1047 // region offset in mega position
1048
1049 int offsetX = ((int)(x / (int)Constants.RegionSize)) * (int)Constants.RegionSize;
1050 int offsetY = ((int)(y / (int)Constants.RegionSize)) * (int)Constants.RegionSize;
1051
1052 IntPtr heightFieldGeom = IntPtr.Zero;
1053
1054 // get region map
1055 if (!RegionTerrain.TryGetValue(new Vector3(offsetX, offsetY, 0), out heightFieldGeom))
1056 return 0f;
1057
1058 if (heightFieldGeom == IntPtr.Zero)
1059 return 0f;
1060
1061 if (!TerrainHeightFieldHeights.ContainsKey(heightFieldGeom))
1062 return 0f;
1063
1064 // TerrainHeightField for ODE as offset 1m
1065 x += 1f - offsetX;
1066 y += 1f - offsetY;
1067
1068 // make position fit into array
1069 if (x < 0)
1070 x = 0;
1071 if (y < 0)
1072 y = 0;
1073
1074 // integer indexs
1075 int ix;
1076 int iy;
1077 // interpolators offset
1078 float dx;
1079 float dy;
1080
1081 int regsize = (int)Constants.RegionSize + 2; // map size see setterrain
1082
1083 // we still have square fixed size regions
1084 // also flip x and y because of how map is done for ODE fliped axis
1085 // so ix,iy,dx and dy are inter exchanged
1086 if (x < regsize - 1)
1087 {
1088 iy = (int)x;
1089 dy = x - (float)iy;
1090 }
1091 else // out world use external height
1092 {
1093 iy = regsize - 1;
1094 dy = 0;
1095 } 1031 }
1096 if (y < regsize - 1) 1032
1033 // finally colide active things amoung them
1034 try
1097 { 1035 {
1098 ix = (int)y; 1036 d.SpaceCollide(ActiveSpace, IntPtr.Zero, nearCallback);
1099 dx = y - (float)ix;
1100 } 1037 }
1101 else 1038 catch (AccessViolationException)
1102 { 1039 {
1103 ix = regsize - 1; 1040 m_log.Warn("[PHYSICS]: Unable to collide in Active space");
1104 dx = 0;
1105 } 1041 }
1106 1042
1107 float h0; 1043// _perloopContact.Clear();
1108 float h1; 1044 }
1109 float h2;
1110
1111 iy *= regsize;
1112 iy += ix; // all indexes have iy + ix
1113 1045
1114 float[] heights = TerrainHeightFieldHeights[heightFieldGeom]; 1046 #endregion
1115 1047
1116 if ((dx + dy) <= 1.0f)
1117 {
1118 h0 = ((float)heights[iy]); // 0,0 vertice
1119 h1 = (((float)heights[iy + 1]) - h0) * dx; // 1,0 vertice minus 0,0
1120 h2 = (((float)heights[iy + regsize]) - h0) * dy; // 0,1 vertice minus 0,0
1121 }
1122 else
1123 {
1124 h0 = ((float)heights[iy + regsize + 1]); // 1,1 vertice
1125 h1 = (((float)heights[iy + 1]) - h0) * (1 - dy); // 1,1 vertice minus 1,0
1126 h2 = (((float)heights[iy + regsize]) - h0) * (1 - dx); // 1,1 vertice minus 0,1
1127 }
1128 1048
1129 return h0 + h1 + h2;
1130 }
1131 1049
1132 /// <summary> 1050 /// <summary>
1133 /// Add actor to the list that should receive collision events in the simulate loop. 1051 /// Add actor to the list that should receive collision events in the simulate loop.
@@ -1835,273 +1753,94 @@ namespace OpenSim.Region.Physics.OdePlugin
1835 get { return (false); } 1753 get { return (false); }
1836 } 1754 }
1837 1755
1838 #region ODE Specific Terrain Fixes 1756 public float GetTerrainHeightAtXY(float x, float y)
1839 public float[] ResizeTerrain512NearestNeighbour(float[] heightMap)
1840 { 1757 {
1841 float[] returnarr = new float[262144]; 1758 // assumes 1m size grid and constante size square regions
1842 float[,] resultarr = new float[(int)WorldExtents.X, (int)WorldExtents.Y]; 1759 // needs to know about sims around in future
1760 // region offset in mega position
1843 1761
1844 // Filling out the array into its multi-dimensional components 1762 int offsetX = ((int)(x / (int)Constants.RegionSize)) * (int)Constants.RegionSize;
1845 for (int y = 0; y < WorldExtents.Y; y++) 1763 int offsetY = ((int)(y / (int)Constants.RegionSize)) * (int)Constants.RegionSize;
1846 {
1847 for (int x = 0; x < WorldExtents.X; x++)
1848 {
1849 resultarr[y, x] = heightMap[y * (int)WorldExtents.Y + x];
1850 }
1851 }
1852 1764
1853 // Resize using Nearest Neighbour 1765 IntPtr heightFieldGeom = IntPtr.Zero;
1854
1855 // This particular way is quick but it only works on a multiple of the original
1856
1857 // The idea behind this method can be described with the following diagrams
1858 // second pass and third pass happen in the same loop really.. just separated
1859 // them to show what this does.
1860
1861 // First Pass
1862 // ResultArr:
1863 // 1,1,1,1,1,1
1864 // 1,1,1,1,1,1
1865 // 1,1,1,1,1,1
1866 // 1,1,1,1,1,1
1867 // 1,1,1,1,1,1
1868 // 1,1,1,1,1,1
1869
1870 // Second Pass
1871 // ResultArr2:
1872 // 1,,1,,1,,1,,1,,1,
1873 // ,,,,,,,,,,
1874 // 1,,1,,1,,1,,1,,1,
1875 // ,,,,,,,,,,
1876 // 1,,1,,1,,1,,1,,1,
1877 // ,,,,,,,,,,
1878 // 1,,1,,1,,1,,1,,1,
1879 // ,,,,,,,,,,
1880 // 1,,1,,1,,1,,1,,1,
1881 // ,,,,,,,,,,
1882 // 1,,1,,1,,1,,1,,1,
1883
1884 // Third pass fills in the blanks
1885 // ResultArr2:
1886 // 1,1,1,1,1,1,1,1,1,1,1,1
1887 // 1,1,1,1,1,1,1,1,1,1,1,1
1888 // 1,1,1,1,1,1,1,1,1,1,1,1
1889 // 1,1,1,1,1,1,1,1,1,1,1,1
1890 // 1,1,1,1,1,1,1,1,1,1,1,1
1891 // 1,1,1,1,1,1,1,1,1,1,1,1
1892 // 1,1,1,1,1,1,1,1,1,1,1,1
1893 // 1,1,1,1,1,1,1,1,1,1,1,1
1894 // 1,1,1,1,1,1,1,1,1,1,1,1
1895 // 1,1,1,1,1,1,1,1,1,1,1,1
1896 // 1,1,1,1,1,1,1,1,1,1,1,1
1897
1898 // X,Y = .
1899 // X+1,y = ^
1900 // X,Y+1 = *
1901 // X+1,Y+1 = #
1902
1903 // Filling in like this;
1904 // .*
1905 // ^#
1906 // 1st .
1907 // 2nd *
1908 // 3rd ^
1909 // 4th #
1910 // on single loop.
1911
1912 float[,] resultarr2 = new float[512, 512];
1913 for (int y = 0; y < WorldExtents.Y; y++)
1914 {
1915 for (int x = 0; x < WorldExtents.X; x++)
1916 {
1917 resultarr2[y * 2, x * 2] = resultarr[y, x];
1918 1766
1919 if (y < WorldExtents.Y) 1767 // get region map
1920 { 1768 if (!RegionTerrain.TryGetValue(new Vector3(offsetX, offsetY, 0), out heightFieldGeom))
1921 resultarr2[(y * 2) + 1, x * 2] = resultarr[y, x]; 1769 return 0f;
1922 }
1923 if (x < WorldExtents.X)
1924 {
1925 resultarr2[y * 2, (x * 2) + 1] = resultarr[y, x];
1926 }
1927 if (x < WorldExtents.X && y < WorldExtents.Y)
1928 {
1929 resultarr2[(y * 2) + 1, (x * 2) + 1] = resultarr[y, x];
1930 }
1931 }
1932 }
1933 1770
1934 //Flatten out the array 1771 if (heightFieldGeom == IntPtr.Zero)
1935 int i = 0; 1772 return 0f;
1936 for (int y = 0; y < 512; y++)
1937 {
1938 for (int x = 0; x < 512; x++)
1939 {
1940 if (resultarr2[y, x] <= 0)
1941 returnarr[i] = 0.0000001f;
1942 else
1943 returnarr[i] = resultarr2[y, x];
1944 1773
1945 i++; 1774 if (!TerrainHeightFieldHeights.ContainsKey(heightFieldGeom))
1946 } 1775 return 0f;
1947 }
1948 1776
1949 return returnarr; 1777 // TerrainHeightField for ODE as offset 1m
1950 } 1778 x += 1f - offsetX;
1779 y += 1f - offsetY;
1951 1780
1952 public float[] ResizeTerrain512Interpolation(float[] heightMap) 1781 // make position fit into array
1953 { 1782 if (x < 0)
1954 float[] returnarr = new float[262144]; 1783 x = 0;
1955 float[,] resultarr = new float[512,512]; 1784 if (y < 0)
1785 y = 0;
1786
1787 // integer indexs
1788 int ix;
1789 int iy;
1790 // interpolators offset
1791 float dx;
1792 float dy;
1793
1794 int regsize = (int)Constants.RegionSize + 3; // map size see setterrain number of samples
1956 1795
1957 // Filling out the array into its multi-dimensional components 1796 // we still have square fixed size regions
1958 for (int y = 0; y < 256; y++) 1797 // also flip x and y because of how map is done for ODE fliped axis
1798 // so ix,iy,dx and dy are inter exchanged
1799 if (x < regsize - 1)
1959 { 1800 {
1960 for (int x = 0; x < 256; x++) 1801 iy = (int)x;
1961 { 1802 dy = x - (float)iy;
1962 resultarr[y, x] = heightMap[y * 256 + x];
1963 }
1964 } 1803 }
1965 1804 else // out world use external height
1966 // Resize using interpolation
1967
1968 // This particular way is quick but it only works on a multiple of the original
1969
1970 // The idea behind this method can be described with the following diagrams
1971 // second pass and third pass happen in the same loop really.. just separated
1972 // them to show what this does.
1973
1974 // First Pass
1975 // ResultArr:
1976 // 1,1,1,1,1,1
1977 // 1,1,1,1,1,1
1978 // 1,1,1,1,1,1
1979 // 1,1,1,1,1,1
1980 // 1,1,1,1,1,1
1981 // 1,1,1,1,1,1
1982
1983 // Second Pass
1984 // ResultArr2:
1985 // 1,,1,,1,,1,,1,,1,
1986 // ,,,,,,,,,,
1987 // 1,,1,,1,,1,,1,,1,
1988 // ,,,,,,,,,,
1989 // 1,,1,,1,,1,,1,,1,
1990 // ,,,,,,,,,,
1991 // 1,,1,,1,,1,,1,,1,
1992 // ,,,,,,,,,,
1993 // 1,,1,,1,,1,,1,,1,
1994 // ,,,,,,,,,,
1995 // 1,,1,,1,,1,,1,,1,
1996
1997 // Third pass fills in the blanks
1998 // ResultArr2:
1999 // 1,1,1,1,1,1,1,1,1,1,1,1
2000 // 1,1,1,1,1,1,1,1,1,1,1,1
2001 // 1,1,1,1,1,1,1,1,1,1,1,1
2002 // 1,1,1,1,1,1,1,1,1,1,1,1
2003 // 1,1,1,1,1,1,1,1,1,1,1,1
2004 // 1,1,1,1,1,1,1,1,1,1,1,1
2005 // 1,1,1,1,1,1,1,1,1,1,1,1
2006 // 1,1,1,1,1,1,1,1,1,1,1,1
2007 // 1,1,1,1,1,1,1,1,1,1,1,1
2008 // 1,1,1,1,1,1,1,1,1,1,1,1
2009 // 1,1,1,1,1,1,1,1,1,1,1,1
2010
2011 // X,Y = .
2012 // X+1,y = ^
2013 // X,Y+1 = *
2014 // X+1,Y+1 = #
2015
2016 // Filling in like this;
2017 // .*
2018 // ^#
2019 // 1st .
2020 // 2nd *
2021 // 3rd ^
2022 // 4th #
2023 // on single loop.
2024
2025 float[,] resultarr2 = new float[512,512];
2026 for (int y = 0; y < (int)Constants.RegionSize; y++)
2027 { 1805 {
2028 for (int x = 0; x < (int)Constants.RegionSize; x++) 1806 iy = regsize - 1;
2029 { 1807 dy = 0;
2030 resultarr2[y*2, x*2] = resultarr[y, x];
2031
2032 if (y < (int)Constants.RegionSize)
2033 {
2034 if (y + 1 < (int)Constants.RegionSize)
2035 {
2036 if (x + 1 < (int)Constants.RegionSize)
2037 {
2038 resultarr2[(y*2) + 1, x*2] = ((resultarr[y, x] + resultarr[y + 1, x] +
2039 resultarr[y, x + 1] + resultarr[y + 1, x + 1])/4);
2040 }
2041 else
2042 {
2043 resultarr2[(y*2) + 1, x*2] = ((resultarr[y, x] + resultarr[y + 1, x])/2);
2044 }
2045 }
2046 else
2047 {
2048 resultarr2[(y*2) + 1, x*2] = resultarr[y, x];
2049 }
2050 }
2051 if (x < (int)Constants.RegionSize)
2052 {
2053 if (x + 1 < (int)Constants.RegionSize)
2054 {
2055 if (y + 1 < (int)Constants.RegionSize)
2056 {
2057 resultarr2[y*2, (x*2) + 1] = ((resultarr[y, x] + resultarr[y + 1, x] +
2058 resultarr[y, x + 1] + resultarr[y + 1, x + 1])/4);
2059 }
2060 else
2061 {
2062 resultarr2[y*2, (x*2) + 1] = ((resultarr[y, x] + resultarr[y, x + 1])/2);
2063 }
2064 }
2065 else
2066 {
2067 resultarr2[y*2, (x*2) + 1] = resultarr[y, x];
2068 }
2069 }
2070 if (x < (int)Constants.RegionSize && y < (int)Constants.RegionSize)
2071 {
2072 if ((x + 1 < (int)Constants.RegionSize) && (y + 1 < (int)Constants.RegionSize))
2073 {
2074 resultarr2[(y*2) + 1, (x*2) + 1] = ((resultarr[y, x] + resultarr[y + 1, x] +
2075 resultarr[y, x + 1] + resultarr[y + 1, x + 1])/4);
2076 }
2077 else
2078 {
2079 resultarr2[(y*2) + 1, (x*2) + 1] = resultarr[y, x];
2080 }
2081 }
2082 }
2083 } 1808 }
2084 //Flatten out the array 1809 if (y < regsize - 1)
2085 int i = 0;
2086 for (int y = 0; y < 512; y++)
2087 { 1810 {
2088 for (int x = 0; x < 512; x++) 1811 ix = (int)y;
2089 { 1812 dx = y - (float)ix;
2090 if (Single.IsNaN(resultarr2[y, x]) || Single.IsInfinity(resultarr2[y, x])) 1813 }
2091 { 1814 else
2092 m_log.Warn("[PHYSICS]: Non finite heightfield element detected. Setting it to 0"); 1815 {
2093 resultarr2[y, x] = 0; 1816 ix = regsize - 1;
2094 } 1817 dx = 0;
2095 returnarr[i] = resultarr2[y, x];
2096 i++;
2097 }
2098 } 1818 }
2099 1819
2100 return returnarr; 1820 float h0;
2101 } 1821 float h1;
1822 float h2;
2102 1823
2103 #endregion 1824 iy *= regsize;
1825 iy += ix; // all indexes have iy + ix
2104 1826
1827 float[] heights = TerrainHeightFieldHeights[heightFieldGeom];
1828
1829 if ((dx + dy) <= 1.0f)
1830 {
1831 h0 = ((float)heights[iy]); // 0,0 vertice
1832 h1 = (((float)heights[iy + 1]) - h0) * dx; // 1,0 vertice minus 0,0
1833 h2 = (((float)heights[iy + regsize]) - h0) * dy; // 0,1 vertice minus 0,0
1834 }
1835 else
1836 {
1837 h0 = ((float)heights[iy + regsize + 1]); // 1,1 vertice
1838 h1 = (((float)heights[iy + 1]) - h0) * (1 - dy); // 1,1 vertice minus 1,0
1839 h2 = (((float)heights[iy + regsize]) - h0) * (1 - dx); // 1,1 vertice minus 0,1
1840 }
1841
1842 return h0 + h1 + h2;
1843 }
2105 public override void SetTerrain(float[] heightMap) 1844 public override void SetTerrain(float[] heightMap)
2106 { 1845 {
2107 if (m_worldOffset != Vector3.Zero && m_parentScene != null) 1846 if (m_worldOffset != Vector3.Zero && m_parentScene != null)
@@ -2124,48 +1863,47 @@ namespace OpenSim.Region.Physics.OdePlugin
2124 1863
2125 public void SetTerrain(float[] heightMap, Vector3 pOffset) 1864 public void SetTerrain(float[] heightMap, Vector3 pOffset)
2126 { 1865 {
1866 // assumes 1m size grid and constante size square regions
1867 // needs to know about sims around in future
2127 1868
2128 float[] _heightmap; 1869 float[] _heightmap;
2129 _heightmap = new float[(((int)Constants.RegionSize + 2) * ((int)Constants.RegionSize + 2))];
2130 1870
2131 uint heightmapWidth = Constants.RegionSize + 2; 1871 uint heightmapWidth = Constants.RegionSize + 2;
2132 uint heightmapHeight = Constants.RegionSize + 2; 1872 uint heightmapHeight = Constants.RegionSize + 2;
2133 1873
2134 uint heightmapWidthSamples; 1874 uint heightmapWidthSamples = heightmapWidth + 1;
1875 uint heightmapHeightSamples = heightmapHeight + 1;
2135 1876
2136 uint heightmapHeightSamples; 1877 _heightmap = new float[heightmapWidthSamples * heightmapHeightSamples];
2137
2138 heightmapWidthSamples = (uint)Constants.RegionSize + 2;
2139 heightmapHeightSamples = (uint)Constants.RegionSize + 2;
2140 1878
2141 const float scale = 1.0f; 1879 const float scale = 1.0f;
2142 const float offset = 0.0f; 1880 const float offset = 0.0f;
2143 const float thickness = 10f; 1881 const float thickness = 10f;
2144 const int wrap = 0; 1882 const int wrap = 0;
2145 1883
2146 int regionsize = (int) Constants.RegionSize + 2; 1884 uint regionsize = Constants.RegionSize;
2147 1885
2148 float hfmin = float.MaxValue; 1886 float hfmin = float.MaxValue;
2149 float hfmax = float.MinValue; 1887 float hfmax = float.MinValue;
2150 float val; 1888 float val;
2151 int xx; 1889 uint xx;
2152 int yy; 1890 uint yy;
2153 1891
2154 int maxXXYY = regionsize - 3; 1892 uint maxXXYY = regionsize - 1;
2155 // flipping map adding one margin all around so things don't fall in edges 1893 // flipping map adding one margin all around so things don't fall in edges
2156 1894
2157 int xt = 0; 1895 uint xt = 0;
2158 xx = 0; 1896 xx = 0;
2159 1897
2160 for (int x = 0; x < heightmapWidthSamples; x++) 1898 for (uint x = 0; x < heightmapWidthSamples; x++)
2161 { 1899 {
2162 if (x > 1 && xx < maxXXYY) 1900 if (x > 1 && xx < maxXXYY)
2163 xx++; 1901 xx++;
2164 yy = 0; 1902 yy = 0;
2165 for (int y = 0; y < heightmapHeightSamples; y++) 1903 for (uint y = 0; y < heightmapHeightSamples; y++)
2166 { 1904 {
2167 if (y > 1 && y < maxXXYY) 1905 if (y > 1 && y < maxXXYY)
2168 yy += (int)Constants.RegionSize; 1906 yy += regionsize;
2169 1907
2170 val = heightMap[yy + xx]; 1908 val = heightMap[yy + xx];
2171 _heightmap[xt + y] = val; 1909 _heightmap[xt + y] = val;
@@ -2176,8 +1914,7 @@ namespace OpenSim.Region.Physics.OdePlugin
2176 hfmax = val; 1914 hfmax = val;
2177 1915
2178 } 1916 }
2179 1917 xt += heightmapHeightSamples;
2180 xt += regionsize;
2181 } 1918 }
2182 lock (OdeLock) 1919 lock (OdeLock)
2183 { 1920 {
@@ -2230,11 +1967,6 @@ namespace OpenSim.Region.Physics.OdePlugin
2230 d.RFromAxisAndAngle(out R, v3.X, v3.Y, v3.Z, angle); 1967 d.RFromAxisAndAngle(out R, v3.X, v3.Y, v3.Z, angle);
2231 d.GeomSetRotation(GroundGeom, ref R); 1968 d.GeomSetRotation(GroundGeom, ref R);
2232 d.GeomSetPosition(GroundGeom, pOffset.X + (float)Constants.RegionSize * 0.5f - 0.5f, pOffset.Y + (float)Constants.RegionSize * 0.5f - 0.5f, 0); 1969 d.GeomSetPosition(GroundGeom, pOffset.X + (float)Constants.RegionSize * 0.5f - 0.5f, pOffset.Y + (float)Constants.RegionSize * 0.5f - 0.5f, 0);
2233 IntPtr testGround = IntPtr.Zero;
2234 if (RegionTerrain.TryGetValue(pOffset, out testGround))
2235 {
2236 RegionTerrain.Remove(pOffset);
2237 }
2238 RegionTerrain.Add(pOffset, GroundGeom, GroundGeom); 1970 RegionTerrain.Add(pOffset, GroundGeom, GroundGeom);
2239// TerrainHeightFieldHeights.Add(GroundGeom, ODElandMap); 1971// TerrainHeightFieldHeights.Add(GroundGeom, ODElandMap);
2240 TerrainHeightFieldHeights.Add(GroundGeom, _heightmap); 1972 TerrainHeightFieldHeights.Add(GroundGeom, _heightmap);
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index 8708b99..4366626 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -2484,13 +2484,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2484 public void llApplyRotationalImpulse(LSL_Vector force, int local) 2484 public void llApplyRotationalImpulse(LSL_Vector force, int local)
2485 { 2485 {
2486 m_host.AddScriptLPS(1); 2486 m_host.AddScriptLPS(1);
2487 m_host.ApplyAngularImpulse(new Vector3((float)force.x, (float)force.y, (float)force.z), local != 0); 2487 m_host.ParentGroup.RootPart.ApplyAngularImpulse(new Vector3((float)force.x, (float)force.y, (float)force.z), local != 0);
2488 } 2488 }
2489 2489
2490 public void llSetTorque(LSL_Vector torque, int local) 2490 public void llSetTorque(LSL_Vector torque, int local)
2491 { 2491 {
2492 m_host.AddScriptLPS(1); 2492 m_host.AddScriptLPS(1);
2493 m_host.SetAngularImpulse(new Vector3((float)torque.x, (float)torque.y, (float)torque.z), local != 0); 2493 m_host.ParentGroup.RootPart.SetAngularImpulse(new Vector3((float)torque.x, (float)torque.y, (float)torque.z), local != 0);
2494 } 2494 }
2495 2495
2496 public LSL_Vector llGetTorque() 2496 public LSL_Vector llGetTorque()
@@ -4657,6 +4657,28 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4657 ScriptSleep(5000); 4657 ScriptSleep(5000);
4658 } 4658 }
4659 4659
4660 public void llTeleportAgent(string agent, string simname, LSL_Vector pos, LSL_Vector lookAt)
4661 {
4662 m_host.AddScriptLPS(1);
4663 UUID agentId = new UUID();
4664 if (UUID.TryParse(agent, out agentId))
4665 {
4666 ScenePresence presence = World.GetScenePresence(agentId);
4667 if (presence != null)
4668 {
4669 // agent must not be a god
4670 if (presence.UserLevel >= 200) return;
4671
4672 // agent must be over the owners land
4673 if (m_host.OwnerID == World.LandChannel.GetLandObject(
4674 presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID)
4675 {
4676 World.RequestTeleportLocation(presence.ControllingClient, simname, new Vector3((float)pos.x, (float)pos.y, (float)pos.z), new Vector3((float)lookAt.x, (float)lookAt.y, (float)lookAt.z), (uint)TeleportFlags.ViaLocation);
4677 }
4678 }
4679 }
4680 }
4681
4660 public void llTextBox(string agent, string message, int chatChannel) 4682 public void llTextBox(string agent, string message, int chatChannel)
4661 { 4683 {
4662 IDialogModule dm = World.RequestModuleInterface<IDialogModule>(); 4684 IDialogModule dm = World.RequestModuleInterface<IDialogModule>();
@@ -11980,6 +12002,144 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11980 } 12002 }
11981 12003
11982 #endregion 12004 #endregion
12005
12006 public void llSetKeyframedMotion(LSL_List frames, LSL_List options)
12007 {
12008 SceneObjectGroup group = m_host.ParentGroup;
12009
12010 if (group.RootPart.PhysActor != null && group.RootPart.PhysActor.IsPhysical)
12011 return;
12012 if (group.IsAttachment)
12013 return;
12014
12015 if (frames.Data.Length > 0) // We are getting a new motion
12016 {
12017 if (group.RootPart.KeyframeMotion != null)
12018 group.RootPart.KeyframeMotion.Stop();
12019 group.RootPart.KeyframeMotion = null;
12020
12021 int idx = 0;
12022
12023 KeyframeMotion.PlayMode mode = KeyframeMotion.PlayMode.Forward;
12024 KeyframeMotion.DataFormat data = KeyframeMotion.DataFormat.Translation | KeyframeMotion.DataFormat.Rotation;
12025
12026 while (idx < options.Data.Length)
12027 {
12028 int option = (int)options.GetLSLIntegerItem(idx++);
12029 int remain = options.Data.Length - idx;
12030
12031 switch (option)
12032 {
12033 case ScriptBaseClass.KFM_MODE:
12034 if (remain < 1)
12035 break;
12036 int modeval = (int)options.GetLSLIntegerItem(idx++);
12037 switch(modeval)
12038 {
12039 case ScriptBaseClass.KFM_FORWARD:
12040 mode = KeyframeMotion.PlayMode.Forward;
12041 break;
12042 case ScriptBaseClass.KFM_REVERSE:
12043 mode = KeyframeMotion.PlayMode.Reverse;
12044 break;
12045 case ScriptBaseClass.KFM_LOOP:
12046 mode = KeyframeMotion.PlayMode.Loop;
12047 break;
12048 case ScriptBaseClass.KFM_PING_PONG:
12049 mode = KeyframeMotion.PlayMode.PingPong;
12050 break;
12051 }
12052 break;
12053 case ScriptBaseClass.KFM_DATA:
12054 if (remain < 1)
12055 break;
12056 int dataval = (int)options.GetLSLIntegerItem(idx++);
12057 data = (KeyframeMotion.DataFormat)dataval;
12058 break;
12059 }
12060 }
12061
12062 group.RootPart.KeyframeMotion = new KeyframeMotion(group, mode, data);
12063
12064 idx = 0;
12065
12066 int elemLength = 2;
12067 if (data == (KeyframeMotion.DataFormat.Translation | KeyframeMotion.DataFormat.Rotation))
12068 elemLength = 3;
12069
12070 List<KeyframeMotion.Keyframe> keyframes = new List<KeyframeMotion.Keyframe>();
12071 while (idx < frames.Data.Length)
12072 {
12073 int remain = frames.Data.Length - idx;
12074
12075 if (remain < elemLength)
12076 break;
12077
12078 KeyframeMotion.Keyframe frame = new KeyframeMotion.Keyframe();
12079 frame.Position = null;
12080 frame.Rotation = null;
12081
12082 if ((data & KeyframeMotion.DataFormat.Translation) != 0)
12083 {
12084 LSL_Types.Vector3 tempv = frames.GetVector3Item(idx++);
12085 frame.Position = new Vector3((float)tempv.x, (float)tempv.y, (float)tempv.z);
12086 }
12087 if ((data & KeyframeMotion.DataFormat.Rotation) != 0)
12088 {
12089 LSL_Types.Quaternion tempq = frames.GetQuaternionItem(idx++);
12090 frame.Rotation = new Quaternion((float)tempq.x, (float)tempq.y, (float)tempq.z, (float)tempq.s);
12091 }
12092
12093 float tempf = (float)frames.GetLSLFloatItem(idx++);
12094 frame.TimeMS = (int)(tempf * 1000.0f);
12095
12096 keyframes.Add(frame);
12097 }
12098
12099 group.RootPart.KeyframeMotion.SetKeyframes(keyframes.ToArray());
12100 group.RootPart.KeyframeMotion.Start();
12101 }
12102 else
12103 {
12104 if (group.RootPart.KeyframeMotion == null)
12105 return;
12106
12107 if (options.Data.Length == 0)
12108 {
12109 group.RootPart.KeyframeMotion.Stop();
12110 return;
12111 }
12112
12113 int code = (int)options.GetLSLIntegerItem(0);
12114
12115 int idx = 0;
12116
12117 while (idx < options.Data.Length)
12118 {
12119 int option = (int)options.GetLSLIntegerItem(idx++);
12120 int remain = options.Data.Length - idx;
12121
12122 switch (option)
12123 {
12124 case ScriptBaseClass.KFM_COMMAND:
12125 int cmd = (int)options.GetLSLIntegerItem(idx++);
12126 switch (cmd)
12127 {
12128 case ScriptBaseClass.KFM_CMD_PLAY:
12129 group.RootPart.KeyframeMotion.Start();
12130 break;
12131 case ScriptBaseClass.KFM_CMD_STOP:
12132 group.RootPart.KeyframeMotion.Stop();
12133 break;
12134 case ScriptBaseClass.KFM_CMD_PAUSE:
12135 group.RootPart.KeyframeMotion.Pause();
12136 break;
12137 }
12138 break;
12139 }
12140 }
12141 }
12142 }
11983 } 12143 }
11984 12144
11985 public class NotecardCache 12145 public class NotecardCache
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs
index 55444dc..8d97a7c 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs
@@ -399,6 +399,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
399 void llTargetOmega(LSL_Vector axis, double spinrate, double gain); 399 void llTargetOmega(LSL_Vector axis, double spinrate, double gain);
400 void llTargetRemove(int number); 400 void llTargetRemove(int number);
401 void llTeleportAgentHome(string agent); 401 void llTeleportAgentHome(string agent);
402 void llTeleportAgent(string agent, string simname, LSL_Vector pos, LSL_Vector lookAt);
402 void llTextBox(string avatar, string message, int chat_channel); 403 void llTextBox(string avatar, string message, int chat_channel);
403 LSL_String llToLower(string source); 404 LSL_String llToLower(string source);
404 LSL_String llToUpper(string source); 405 LSL_String llToUpper(string source);
@@ -419,5 +420,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
419 420
420 void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules); 421 void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules);
421 LSL_List GetLinkPrimitiveParamsEx(LSL_Key prim, LSL_List rules); 422 LSL_List GetLinkPrimitiveParamsEx(LSL_Key prim, LSL_List rules);
423 void llSetKeyframedMotion(LSL_List frames, LSL_List options);
422 } 424 }
423} 425}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
index 3d0e5cb..a5e160d 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
@@ -641,5 +641,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
641 public static readonly LSLInteger RCERR_UNKNOWN = -1; 641 public static readonly LSLInteger RCERR_UNKNOWN = -1;
642 public static readonly LSLInteger RCERR_SIM_PERF_LOW = -2; 642 public static readonly LSLInteger RCERR_SIM_PERF_LOW = -2;
643 public static readonly LSLInteger RCERR_CAST_TIME_EXCEEDED = 3; 643 public static readonly LSLInteger RCERR_CAST_TIME_EXCEEDED = 3;
644
645 public const int KFM_MODE = 1;
646 public const int KFM_LOOP = 1;
647 public const int KFM_REVERSE = 3;
648 public const int KFM_FORWARD = 0;
649 public const int KFM_PING_PONG = 2;
650 public const int KFM_DATA = 2;
651 public const int KFM_TRANSLATION = 2;
652 public const int KFM_ROTATION = 1;
653 public const int KFM_COMMAND = 0;
654 public const int KFM_CMD_PLAY = 0;
655 public const int KFM_CMD_STOP = 1;
656 public const int KFM_CMD_PAUSE = 2;
644 } 657 }
645} 658}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs
index 5f9f0b9..a8d1ddb 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs
@@ -1820,6 +1820,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
1820 m_LSL_Functions.llTargetRemove(number); 1820 m_LSL_Functions.llTargetRemove(number);
1821 } 1821 }
1822 1822
1823 public void llTeleportAgent(string agent, string simname, LSL_Vector pos, LSL_Vector lookAt)
1824 {
1825 m_LSL_Functions.llTeleportAgent(agent, simname, pos, lookAt);
1826 }
1827
1823 public void llTeleportAgentHome(string agent) 1828 public void llTeleportAgentHome(string agent)
1824 { 1829 {
1825 m_LSL_Functions.llTeleportAgentHome(agent); 1830 m_LSL_Functions.llTeleportAgentHome(agent);
@@ -1937,7 +1942,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
1937 1942
1938 public LSL_Integer llGetLinkNumberOfSides(LSL_Integer link) 1943 public LSL_Integer llGetLinkNumberOfSides(LSL_Integer link)
1939 { 1944 {
1940 return m_LSL_Functions.llGetLinkNumberOfSides(link); 1945 return m_LSL_Functions.llGetLinkNumberOfSides(link);
1946 }
1947
1948 public void llSetKeyframedMotion(LSL_List frames, LSL_List options)
1949 {
1950 m_LSL_Functions.llSetKeyframedMotion(frames, options);
1941 } 1951 }
1942 } 1952 }
1943} 1953}