aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsActor.cs42
-rw-r--r--OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsPrim.cs315
-rw-r--r--OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsScene.cs41
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs102
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSPlugin.cs11
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs29
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSScene.cs23
-rw-r--r--OpenSim/Region/Physics/Manager/PhysicsScene.cs14
-rw-r--r--OpenSim/Region/Physics/OdePlugin/ODECharacter.cs10
-rw-r--r--OpenSim/Region/Physics/OdePlugin/ODEPrim.cs472
-rw-r--r--OpenSim/Region/Physics/OdePlugin/OdeScene.cs452
11 files changed, 1084 insertions, 427 deletions
diff --git a/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsActor.cs b/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsActor.cs
index b1a3ff9..e43136a 100644
--- a/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsActor.cs
+++ b/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsActor.cs
@@ -36,13 +36,7 @@ namespace OpenSim.Region.Physics.BasicPhysicsPlugin
36{ 36{
37 public class BasicActor : PhysicsActor 37 public class BasicActor : PhysicsActor
38 { 38 {
39 private Vector3 _position;
40 private Vector3 _velocity;
41 private Vector3 _acceleration;
42 private Vector3 _size; 39 private Vector3 _size;
43 private Vector3 m_rotationalVelocity;
44 private bool flying;
45 private bool iscolliding;
46 40
47 public BasicActor(Vector3 size) 41 public BasicActor(Vector3 size)
48 { 42 {
@@ -55,11 +49,7 @@ namespace OpenSim.Region.Physics.BasicPhysicsPlugin
55 set { return; } 49 set { return; }
56 } 50 }
57 51
58 public override Vector3 RotationalVelocity 52 public override Vector3 RotationalVelocity { get; set; }
59 {
60 get { return m_rotationalVelocity; }
61 set { m_rotationalVelocity = value; }
62 }
63 53
64 public override bool SetAlwaysRun 54 public override bool SetAlwaysRun
65 { 55 {
@@ -105,17 +95,9 @@ namespace OpenSim.Region.Physics.BasicPhysicsPlugin
105 set { return; } 95 set { return; }
106 } 96 }
107 97
108 public override bool Flying 98 public override bool Flying { get; set; }
109 {
110 get { return flying; }
111 set { flying = value; }
112 }
113 99
114 public override bool IsColliding 100 public override bool IsColliding { get; set; }
115 {
116 get { return iscolliding; }
117 set { iscolliding = value; }
118 }
119 101
120 public override bool CollidingGround 102 public override bool CollidingGround
121 { 103 {
@@ -134,11 +116,7 @@ namespace OpenSim.Region.Physics.BasicPhysicsPlugin
134 get { return false; } 116 get { return false; }
135 } 117 }
136 118
137 public override Vector3 Position 119 public override Vector3 Position { get; set; }
138 {
139 get { return _position; }
140 set { _position = value; }
141 }
142 120
143 public override Vector3 Size 121 public override Vector3 Size
144 { 122 {
@@ -206,11 +184,7 @@ namespace OpenSim.Region.Physics.BasicPhysicsPlugin
206 get { return Vector3.Zero; } 184 get { return Vector3.Zero; }
207 } 185 }
208 186
209 public override Vector3 Velocity 187 public override Vector3 Velocity { get; set; }
210 {
211 get { return _velocity; }
212 set { _velocity = value; }
213 }
214 188
215 public override Vector3 Torque 189 public override Vector3 Torque
216 { 190 {
@@ -230,11 +204,7 @@ namespace OpenSim.Region.Physics.BasicPhysicsPlugin
230 set { } 204 set { }
231 } 205 }
232 206
233 public override Vector3 Acceleration 207 public override Vector3 Acceleration { get; set; }
234 {
235 get { return _acceleration; }
236 set { _acceleration = value; }
237 }
238 208
239 public override bool Kinematic 209 public override bool Kinematic
240 { 210 {
diff --git a/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsPrim.cs b/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsPrim.cs
new file mode 100644
index 0000000..47d7df3
--- /dev/null
+++ b/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsPrim.cs
@@ -0,0 +1,315 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using Nini.Config;
31using OpenMetaverse;
32using OpenSim.Framework;
33using OpenSim.Region.Physics.Manager;
34
35namespace OpenSim.Region.Physics.BasicPhysicsPlugin
36{
37 public class BasicPhysicsPrim : PhysicsActor
38 {
39 private Vector3 _size;
40// private PrimitiveBaseShape _shape;
41
42 public BasicPhysicsPrim(
43 string name, uint localId, Vector3 position, Vector3 size, Quaternion orientation, PrimitiveBaseShape shape)
44 {
45 Name = name;
46 LocalID = localId;
47 Position = position;
48 Size = size;
49 Orientation = orientation;
50 Shape = shape;
51 }
52
53 public override int PhysicsActorType
54 {
55 get { return (int) ActorTypes.Agent; }
56 set { return; }
57 }
58
59 public override Vector3 RotationalVelocity { get; set; }
60
61 public override bool SetAlwaysRun
62 {
63 get { return false; }
64 set { return; }
65 }
66
67 public override uint LocalID
68 {
69 set { return; }
70 }
71
72 public override bool Grabbed
73 {
74 set { return; }
75 }
76
77 public override bool Selected
78 {
79 set { return; }
80 }
81
82 public override float Buoyancy
83 {
84 get { return 0f; }
85 set { return; }
86 }
87
88 public override bool FloatOnWater
89 {
90 set { return; }
91 }
92
93 public override bool IsPhysical
94 {
95 get { return false; }
96 set { return; }
97 }
98
99 public override bool ThrottleUpdates
100 {
101 get { return false; }
102 set { return; }
103 }
104
105 public override bool Flying { get; set; }
106
107 public override bool IsColliding { get; set; }
108
109 public override bool CollidingGround
110 {
111 get { return false; }
112 set { return; }
113 }
114
115 public override bool CollidingObj
116 {
117 get { return false; }
118 set { return; }
119 }
120
121 public override bool Stopped
122 {
123 get { return false; }
124 }
125
126 public override Vector3 Position { get; set; }
127
128 public override Vector3 Size
129 {
130 get { return _size; }
131 set {
132 _size = value;
133 _size.Z = _size.Z / 2.0f;
134 }
135 }
136
137 public override PrimitiveBaseShape Shape
138 {
139// set { _shape = value; }
140 set {}
141 }
142
143 public override float Mass
144 {
145 get { return 0f; }
146 }
147
148 public override Vector3 Force
149 {
150 get { return Vector3.Zero; }
151 set { return; }
152 }
153
154 public override int VehicleType
155 {
156 get { return 0; }
157 set { return; }
158 }
159
160 public override void VehicleFloatParam(int param, float value)
161 {
162
163 }
164
165 public override void VehicleVectorParam(int param, Vector3 value)
166 {
167
168 }
169
170 public override void VehicleRotationParam(int param, Quaternion rotation)
171 {
172
173 }
174
175 public override void VehicleFlags(int param, bool remove)
176 {
177
178 }
179
180 public override void SetVolumeDetect(int param)
181 {
182
183 }
184
185 public override Vector3 CenterOfMass
186 {
187 get { return Vector3.Zero; }
188 }
189
190 public override Vector3 GeometricCenter
191 {
192 get { return Vector3.Zero; }
193 }
194
195 public override Vector3 Velocity { get; set; }
196
197 public override Vector3 Torque
198 {
199 get { return Vector3.Zero; }
200 set { return; }
201 }
202
203 public override float CollisionScore
204 {
205 get { return 0f; }
206 set { }
207 }
208
209 public override Quaternion Orientation { get; set; }
210
211 public override Vector3 Acceleration { get; set; }
212
213 public override bool Kinematic
214 {
215 get { return true; }
216 set { }
217 }
218
219 public override void link(PhysicsActor obj)
220 {
221 }
222
223 public override void delink()
224 {
225 }
226
227 public override void LockAngularMotion(Vector3 axis)
228 {
229 }
230
231 public override void AddForce(Vector3 force, bool pushforce)
232 {
233 }
234
235 public override void AddAngularForce(Vector3 force, bool pushforce)
236 {
237 }
238
239 public override void SetMomentum(Vector3 momentum)
240 {
241 }
242
243 public override void CrossingFailure()
244 {
245 }
246
247 public override Vector3 PIDTarget
248 {
249 set { return; }
250 }
251
252 public override bool PIDActive
253 {
254 set { return; }
255 }
256
257 public override float PIDTau
258 {
259 set { return; }
260 }
261
262 public override float PIDHoverHeight
263 {
264 set { return; }
265 }
266
267 public override bool PIDHoverActive
268 {
269 set { return; }
270 }
271
272 public override PIDHoverType PIDHoverType
273 {
274 set { return; }
275 }
276
277 public override float PIDHoverTau
278 {
279 set { return; }
280 }
281
282 public override Quaternion APIDTarget
283 {
284 set { return; }
285 }
286
287 public override bool APIDActive
288 {
289 set { return; }
290 }
291
292 public override float APIDStrength
293 {
294 set { return; }
295 }
296
297 public override float APIDDamping
298 {
299 set { return; }
300 }
301
302 public override void SubscribeEvents(int ms)
303 {
304 }
305
306 public override void UnSubscribeEvents()
307 {
308 }
309
310 public override bool SubscribedEvents()
311 {
312 return false;
313 }
314 }
315}
diff --git a/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsScene.cs b/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsScene.cs
index 2e14216..f5826ed 100644
--- a/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsScene.cs
+++ b/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsScene.cs
@@ -34,9 +34,17 @@ using OpenSim.Region.Physics.Manager;
34 34
35namespace OpenSim.Region.Physics.BasicPhysicsPlugin 35namespace OpenSim.Region.Physics.BasicPhysicsPlugin
36{ 36{
37 /// <summary>
38 /// This is an incomplete extremely basic physics implementation
39 /// </summary>
40 /// <remarks>
41 /// Not useful for anything at the moment apart from some regression testing in other components where some form
42 /// of physics plugin is needed.
43 /// </remarks>
37 public class BasicScene : PhysicsScene 44 public class BasicScene : PhysicsScene
38 { 45 {
39 private List<BasicActor> _actors = new List<BasicActor>(); 46 private List<BasicActor> _actors = new List<BasicActor>();
47 private List<BasicPhysicsPrim> _prims = new List<BasicPhysicsPrim>();
40 private float[] _heightMap; 48 private float[] _heightMap;
41 49
42 //protected internal string sceneIdentifier; 50 //protected internal string sceneIdentifier;
@@ -50,10 +58,19 @@ namespace OpenSim.Region.Physics.BasicPhysicsPlugin
50 { 58 {
51 } 59 }
52 60
53 public override void Dispose() 61 public override void Dispose() {}
62
63 public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position,
64 Vector3 size, Quaternion rotation, bool isPhysical, uint localid)
54 { 65 {
66 BasicPhysicsPrim prim = new BasicPhysicsPrim(primName, localid, position, size, rotation, pbs);
67 prim.IsPhysical = isPhysical;
68
69 _prims.Add(prim);
55 70
71 return prim;
56 } 72 }
73
57 public override PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 size, bool isFlying) 74 public override PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 size, bool isFlying)
58 { 75 {
59 BasicActor act = new BasicActor(size); 76 BasicActor act = new BasicActor(size);
@@ -63,30 +80,18 @@ namespace OpenSim.Region.Physics.BasicPhysicsPlugin
63 return act; 80 return act;
64 } 81 }
65 82
66 public override void RemovePrim(PhysicsActor prim) 83 public override void RemovePrim(PhysicsActor actor)
67 { 84 {
85 BasicPhysicsPrim prim = (BasicPhysicsPrim)actor;
86 if (_prims.Contains(prim))
87 _prims.Remove(prim);
68 } 88 }
69 89
70 public override void RemoveAvatar(PhysicsActor actor) 90 public override void RemoveAvatar(PhysicsActor actor)
71 { 91 {
72 BasicActor act = (BasicActor) actor; 92 BasicActor act = (BasicActor)actor;
73 if (_actors.Contains(act)) 93 if (_actors.Contains(act))
74 {
75 _actors.Remove(act); 94 _actors.Remove(act);
76 }
77 }
78
79/*
80 public override PhysicsActor AddPrim(Vector3 position, Vector3 size, Quaternion rotation)
81 {
82 return null;
83 }
84*/
85
86 public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position,
87 Vector3 size, Quaternion rotation, bool isPhysical, uint localid)
88 {
89 return null;
90 } 95 }
91 96
92 public override void AddPhysicsActorTaint(PhysicsActor prim) 97 public override void AddPhysicsActorTaint(PhysicsActor prim)
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
index b08d5db..dc0c008 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
@@ -74,7 +74,7 @@ public class BSCharacter : PhysicsActor
74 private float _buoyancy; 74 private float _buoyancy;
75 75
76 private int _subscribedEventsMs = 0; 76 private int _subscribedEventsMs = 0;
77 private int _lastCollisionTime = 0; 77 private int _nextCollisionOkTime = 0;
78 78
79 private Vector3 _PIDTarget; 79 private Vector3 _PIDTarget;
80 private bool _usePID; 80 private bool _usePID;
@@ -360,17 +360,22 @@ public class BSCharacter : PhysicsActor
360 } 360 }
361 //m_lastUpdateSent = false; 361 //m_lastUpdateSent = false;
362 } 362 }
363
363 public override void AddAngularForce(Vector3 force, bool pushforce) { 364 public override void AddAngularForce(Vector3 force, bool pushforce) {
364 } 365 }
365 public override void SetMomentum(Vector3 momentum) { 366 public override void SetMomentum(Vector3 momentum) {
366 } 367 }
368
369 // Turn on collision events at a rate no faster than one every the given milliseconds
367 public override void SubscribeEvents(int ms) { 370 public override void SubscribeEvents(int ms) {
368 _subscribedEventsMs = ms; 371 _subscribedEventsMs = ms;
369 _lastCollisionTime = Util.EnvironmentTickCount() - _subscribedEventsMs; // make first collision happen 372 _nextCollisionOkTime = Util.EnvironmentTickCount() - _subscribedEventsMs; // make first collision happen
370 } 373 }
374 // Stop collision events
371 public override void UnSubscribeEvents() { 375 public override void UnSubscribeEvents() {
372 _subscribedEventsMs = 0; 376 _subscribedEventsMs = 0;
373 } 377 }
378 // Return 'true' if someone has subscribed to events
374 public override bool SubscribedEvents() { 379 public override bool SubscribedEvents() {
375 return (_subscribedEventsMs > 0); 380 return (_subscribedEventsMs > 0);
376 } 381 }
@@ -386,47 +391,57 @@ public class BSCharacter : PhysicsActor
386 _mass = _density * _avatarVolume; 391 _mass = _density * _avatarVolume;
387 } 392 }
388 393
394 // Set to 'true' if the individual changed items should be checked
395 // (someday RequestPhysicsTerseUpdate() will take a bitmap of changed properties)
396 const bool SHOULD_CHECK_FOR_INDIVIDUAL_CHANGES = false;
397
389 // The physics engine says that properties have updated. Update same and inform 398 // The physics engine says that properties have updated. Update same and inform
390 // the world that things have changed. 399 // the world that things have changed.
391 public void UpdateProperties(EntityProperties entprop) 400 public void UpdateProperties(EntityProperties entprop)
392 { 401 {
393 bool changed = false; 402 bool changed = false;
394 // we assign to the local variables so the normal set action does not happen 403 if (SHOULD_CHECK_FOR_INDIVIDUAL_CHANGES) {
395 if (_position != entprop.Position) 404 // we assign to the local variables so the normal set action does not happen
396 { 405 if (_position != entprop.Position) {
397 _position = entprop.Position; 406 _position = entprop.Position;
398 changed = true; 407 changed = true;
408 }
409 if (_orientation != entprop.Rotation) {
410 _orientation = entprop.Rotation;
411 changed = true;
412 }
413 if (_velocity != entprop.Velocity) {
414 _velocity = entprop.Velocity;
415 changed = true;
416 }
417 if (_acceleration != entprop.Acceleration) {
418 _acceleration = entprop.Acceleration;
419 changed = true;
420 }
421 if (_rotationalVelocity != entprop.RotationalVelocity) {
422 _rotationalVelocity = entprop.RotationalVelocity;
423 changed = true;
424 }
425 if (changed) {
426 // m_log.DebugFormat("{0}: UpdateProperties: id={1}, c={2}, pos={3}, rot={4}", LogHeader, LocalID, changed, _position, _orientation);
427 // Avatar movement is not done by generating this event. There is code in the heartbeat
428 // loop that updates avatars.
429 // base.RequestPhysicsterseUpdate();
430 }
399 } 431 }
400 if (_orientation != entprop.Rotation) 432 else {
401 { 433 _position = entprop.Position;
402 _orientation = entprop.Rotation; 434 _orientation = entprop.Rotation;
403 changed = true;
404 }
405 if (_velocity != entprop.Velocity)
406 {
407 _velocity = entprop.Velocity; 435 _velocity = entprop.Velocity;
408 changed = true;
409 }
410 if (_acceleration != entprop.Acceleration)
411 {
412 _acceleration = entprop.Acceleration; 436 _acceleration = entprop.Acceleration;
413 changed = true;
414 }
415 if (_rotationalVelocity != entprop.RotationalVelocity)
416 {
417 _rotationalVelocity = entprop.RotationalVelocity; 437 _rotationalVelocity = entprop.RotationalVelocity;
418 changed = true;
419 }
420 if (changed)
421 {
422 // m_log.DebugFormat("{0}: UpdateProperties: id={1}, c={2}, pos={3}, rot={4}", LogHeader, LocalID, changed, _position, _orientation);
423 // Avatar movement is not done by generating this event. There is a system that
424 // checks for avatar updates each heartbeat loop.
425 // base.RequestPhysicsterseUpdate(); 438 // base.RequestPhysicsterseUpdate();
426 } 439 }
427 } 440 }
428 441
429 // Called by the scene when a collision with this object is reported 442 // Called by the scene when a collision with this object is reported
443 // The collision, if it should be reported to the character, is placed in a collection
444 // that will later be sent to the simulator when SendCollisions() is called.
430 CollisionEventUpdate collisionCollection = null; 445 CollisionEventUpdate collisionCollection = null;
431 public void Collide(uint collidingWith, ActorTypes type, Vector3 contactPoint, Vector3 contactNormal, float pentrationDepth) 446 public void Collide(uint collidingWith, ActorTypes type, Vector3 contactPoint, Vector3 contactNormal, float pentrationDepth)
432 { 447 {
@@ -440,29 +455,34 @@ public class BSCharacter : PhysicsActor
440 } 455 }
441 456
442 // throttle collisions to the rate specified in the subscription 457 // throttle collisions to the rate specified in the subscription
443 if (_subscribedEventsMs == 0) return; // don't want collisions 458 if (_subscribedEventsMs != 0) {
444 int nowTime = _scene.SimulationNowTime; 459 int nowTime = _scene.SimulationNowTime;
445 if (nowTime < (_lastCollisionTime + _subscribedEventsMs)) return; 460 if (nowTime >= _nextCollisionOkTime) {
446 _lastCollisionTime = nowTime; 461 _nextCollisionOkTime = nowTime + _subscribedEventsMs;
447 462
448 if (collisionCollection == null) 463 if (collisionCollection == null)
449 collisionCollection = new CollisionEventUpdate(); 464 collisionCollection = new CollisionEventUpdate();
450 collisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth)); 465 collisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth));
466 }
467 }
451 } 468 }
452 469
453 public void SendCollisions() 470 public void SendCollisions()
454 { 471 {
455 // if (collisionCollection != null) 472 /*
456 // { 473 if (collisionCollection != null && collisionCollection.Count > 0)
457 // base.SendCollisionUpdate(collisionCollection); 474 {
458 // collisionCollection = null; 475 base.SendCollisionUpdate(collisionCollection);
459 // } 476 collisionCollection = null;
477 }
478 */
460 // Kludge to make a collision call even if there are no collisions. 479 // Kludge to make a collision call even if there are no collisions.
461 // This causes the avatar animation to get updated. 480 // This causes the avatar animation to get updated.
462 if (collisionCollection == null) 481 if (collisionCollection == null)
463 collisionCollection = new CollisionEventUpdate(); 482 collisionCollection = new CollisionEventUpdate();
464 base.SendCollisionUpdate(collisionCollection); 483 base.SendCollisionUpdate(collisionCollection);
465 collisionCollection = null; 484 collisionCollection.Clear();
485 // End kludge
466 } 486 }
467 487
468} 488}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPlugin.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPlugin.cs
index 0730824..0f027b8 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPlugin.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPlugin.cs
@@ -32,6 +32,14 @@ using OpenMetaverse;
32 32
33namespace OpenSim.Region.Physics.BulletSPlugin 33namespace OpenSim.Region.Physics.BulletSPlugin
34{ 34{
35 /// <summary>
36 /// Entry for a port of Bullet (http://bulletphysics.org/) to OpenSim.
37 /// This module interfaces to an unmanaged C++ library which makes the
38 /// actual calls into the Bullet physics engine.
39 /// The unmanaged library is found in opensim-libs::trunk/unmanaged/BulletSim/.
40 /// The unmanaged library is compiled and linked statically with Bullet
41 /// to create BulletSim.dll and libBulletSim.so (for both 32 and 64 bit).
42 /// </summary>
35public class BSPlugin : IPhysicsPlugin 43public class BSPlugin : IPhysicsPlugin
36{ 44{
37 //private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); 45 //private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
@@ -53,6 +61,9 @@ public class BSPlugin : IPhysicsPlugin
53 { 61 {
54 if (Util.IsWindows()) 62 if (Util.IsWindows())
55 Util.LoadArchSpecificWindowsDll("BulletSim.dll"); 63 Util.LoadArchSpecificWindowsDll("BulletSim.dll");
64 // If not Windows, loading is performed by the
65 // Mono loader as specified in
66 // "bin/Physics/OpenSim.Region.Physics.BulletSPlugin.dll.config".
56 67
57 _mScene = new BSScene(sceneIdentifier); 68 _mScene = new BSScene(sceneIdentifier);
58 } 69 }
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
index 248d1f2..130f1ca 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
@@ -90,7 +90,7 @@ public sealed class BSPrim : PhysicsActor
90 private BSPrim _parentPrim; 90 private BSPrim _parentPrim;
91 91
92 private int _subscribedEventsMs = 0; 92 private int _subscribedEventsMs = 0;
93 private int _lastCollisionTime = 0; 93 private int _nextCollisionOkTime = 0;
94 long _collidingStep; 94 long _collidingStep;
95 long _collidingGroundStep; 95 long _collidingGroundStep;
96 96
@@ -597,7 +597,8 @@ public sealed class BSPrim : PhysicsActor
597 } 597 }
598 public override void SubscribeEvents(int ms) { 598 public override void SubscribeEvents(int ms) {
599 _subscribedEventsMs = ms; 599 _subscribedEventsMs = ms;
600 _lastCollisionTime = Util.EnvironmentTickCount() - _subscribedEventsMs; // make first collision happen 600 // make sure first collision happens
601 _nextCollisionOkTime = Util.EnvironmentTickCount() - _subscribedEventsMs;
601 } 602 }
602 public override void UnSubscribeEvents() { 603 public override void UnSubscribeEvents() {
603 _subscribedEventsMs = 0; 604 _subscribedEventsMs = 0;
@@ -1338,23 +1339,27 @@ public sealed class BSPrim : PhysicsActor
1338 _collidingGroundStep = _scene.SimulationStep; 1339 _collidingGroundStep = _scene.SimulationStep;
1339 } 1340 }
1340 1341
1341 if (_subscribedEventsMs == 0) return; // nothing in the object is waiting for collision events 1342 // if someone is subscribed to collision events....
1342 // throttle the collisions to the number of milliseconds specified in the subscription 1343 if (_subscribedEventsMs != 0) {
1343 int nowTime = _scene.SimulationNowTime; 1344 // throttle the collisions to the number of milliseconds specified in the subscription
1344 if (nowTime < (_lastCollisionTime + _subscribedEventsMs)) return; 1345 int nowTime = _scene.SimulationNowTime;
1345 _lastCollisionTime = nowTime; 1346 if (nowTime >= _nextCollisionOkTime) {
1347 _nextCollisionOkTime = nowTime + _subscribedEventsMs;
1346 1348
1347 if (collisionCollection == null) 1349 if (collisionCollection == null)
1348 collisionCollection = new CollisionEventUpdate(); 1350 collisionCollection = new CollisionEventUpdate();
1349 collisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth)); 1351 collisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth));
1352 }
1353 }
1350 } 1354 }
1351 1355
1356 // The scene is telling us it's time to pass our collected collisions into the simulator
1352 public void SendCollisions() 1357 public void SendCollisions()
1353 { 1358 {
1354 if (collisionCollection != null) 1359 if (collisionCollection != null && collisionCollection.Count > 0)
1355 { 1360 {
1356 base.SendCollisionUpdate(collisionCollection); 1361 base.SendCollisionUpdate(collisionCollection);
1357 collisionCollection = null; 1362 collisionCollection.Clear();
1358 } 1363 }
1359 } 1364 }
1360} 1365}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
index 94a0ccf..417cb5f 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
@@ -52,6 +52,7 @@ using OpenSim.Region.Framework;
52// Should prim.link() and prim.delink() membership checking happen at taint time? 52// Should prim.link() and prim.delink() membership checking happen at taint time?
53// Mesh sharing. Use meshHash to tell if we already have a hull of that shape and only create once 53// Mesh sharing. Use meshHash to tell if we already have a hull of that shape and only create once
54// Do attachments need to be handled separately? Need collision events. Do not collide with VolumeDetect 54// Do attachments need to be handled separately? Need collision events. Do not collide with VolumeDetect
55// Use collision masks for collision with terrain and phantom objects
55// Implement the genCollisions feature in BulletSim::SetObjectProperties (don't pass up unneeded collisions) 56// Implement the genCollisions feature in BulletSim::SetObjectProperties (don't pass up unneeded collisions)
56// Implement LockAngularMotion 57// Implement LockAngularMotion
57// Decide if clearing forces is the right thing to do when setting position (BulletSim::SetObjectTranslation) 58// Decide if clearing forces is the right thing to do when setting position (BulletSim::SetObjectTranslation)
@@ -62,9 +63,6 @@ using OpenSim.Region.Framework;
62// Multiple contact points on collision? 63// Multiple contact points on collision?
63// See code in ode::near... calls to collision_accounting_events() 64// See code in ode::near... calls to collision_accounting_events()
64// (This might not be a problem. ODE collects all the collisions with one object in one tick.) 65// (This might not be a problem. ODE collects all the collisions with one object in one tick.)
65// Use collision masks for collision with terrain and phantom objects
66// Figure out how to not allocate a new Dictionary and List for every collision
67// in BSPrim.Collide() and BSCharacter.Collide(). Can the same ones be reused?
68// Raycast 66// Raycast
69// 67//
70namespace OpenSim.Region.Physics.BulletSPlugin 68namespace OpenSim.Region.Physics.BulletSPlugin
@@ -405,6 +403,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters
405 // prevent simulation until we've been initialized 403 // prevent simulation until we've been initialized
406 if (!m_initialized) return 10.0f; 404 if (!m_initialized) return 10.0f;
407 405
406 long simulateStartTime = Util.EnvironmentTickCount();
407
408 // update the prim states while we know the physics engine is not busy 408 // update the prim states while we know the physics engine is not busy
409 ProcessTaints(); 409 ProcessTaints();
410 410
@@ -437,13 +437,18 @@ public class BSScene : PhysicsScene, IPhysicsParameters
437 } 437 }
438 } 438 }
439 439
440 // The SendCollision's batch up the collisions on the objects. Now push the collisions into the simulator. 440 // The above SendCollision's batch up the collisions on the objects.
441 // Now push the collisions into the simulator.
441 foreach (BSPrim bsp in m_primsWithCollisions) 442 foreach (BSPrim bsp in m_primsWithCollisions)
442 bsp.SendCollisions(); 443 bsp.SendCollisions();
443 m_primsWithCollisions.Clear(); 444 m_primsWithCollisions.Clear();
445
446 // This is a kludge to get avatar movement updated.
447 // Don't send collisions only if there were collisions -- send everytime.
448 // ODE sends collisions even if there are none and this is used to update
449 // avatar animations and stuff.
444 // foreach (BSCharacter bsc in m_avatarsWithCollisions) 450 // foreach (BSCharacter bsc in m_avatarsWithCollisions)
445 // bsc.SendCollisions(); 451 // bsc.SendCollisions();
446 // This is a kludge to get avatar movement updated. ODE sends collisions even if there isn't any
447 foreach (KeyValuePair<uint, BSCharacter> kvp in m_avatars) 452 foreach (KeyValuePair<uint, BSCharacter> kvp in m_avatars)
448 kvp.Value.SendCollisions(); 453 kvp.Value.SendCollisions();
449 m_avatarsWithCollisions.Clear(); 454 m_avatarsWithCollisions.Clear();
@@ -465,10 +470,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters
465 if (m_avatars.TryGetValue(entprop.ID, out actor)) 470 if (m_avatars.TryGetValue(entprop.ID, out actor))
466 { 471 {
467 actor.UpdateProperties(entprop); 472 actor.UpdateProperties(entprop);
473 continue;
468 } 474 }
469 } 475 }
470 } 476 }
471 477
478 // If enabled, call into the physics engine to dump statistics
472 if (m_detailedStatsStep > 0) 479 if (m_detailedStatsStep > 0)
473 { 480 {
474 if ((m_simulationStep % m_detailedStatsStep) == 0) 481 if ((m_simulationStep % m_detailedStatsStep) == 0)
@@ -477,6 +484,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters
477 } 484 }
478 } 485 }
479 486
487 // this is a waste since the outside routine also calcuates the physics simulation
488 // period. TODO: There should be a way of computing physics frames from simulator computation.
489 // long simulateTotalTime = Util.EnvironmentTickCountSubtract(simulateStartTime);
490 // return (timeStep * (float)simulateTotalTime);
491
480 // TODO: FIX THIS: fps calculation wrong. This calculation always returns about 1 in normal operation. 492 // TODO: FIX THIS: fps calculation wrong. This calculation always returns about 1 in normal operation.
481 return timeStep / (numSubSteps * m_fixedTimeStep) * 1000f; 493 return timeStep / (numSubSteps * m_fixedTimeStep) * 1000f;
482 } 494 }
@@ -528,6 +540,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
528 public override void SetWaterLevel(float baseheight) 540 public override void SetWaterLevel(float baseheight)
529 { 541 {
530 m_waterLevel = baseheight; 542 m_waterLevel = baseheight;
543 // TODO: pass to physics engine so things will float?
531 } 544 }
532 public float GetWaterLevel() 545 public float GetWaterLevel()
533 { 546 {
diff --git a/OpenSim/Region/Physics/Manager/PhysicsScene.cs b/OpenSim/Region/Physics/Manager/PhysicsScene.cs
index d10a2aa..cfede55 100644
--- a/OpenSim/Region/Physics/Manager/PhysicsScene.cs
+++ b/OpenSim/Region/Physics/Manager/PhysicsScene.cs
@@ -241,8 +241,22 @@ namespace OpenSim.Region.Physics.Manager
241 241
242 public abstract void AddPhysicsActorTaint(PhysicsActor prim); 242 public abstract void AddPhysicsActorTaint(PhysicsActor prim);
243 243
244 /// <summary>
245 /// Perform a simulation of the current physics scene over the given timestep.
246 /// </summary>
247 /// <param name="timeStep"></param>
248 /// <returns>The number of frames simulated over that period.</returns>
244 public abstract float Simulate(float timeStep); 249 public abstract float Simulate(float timeStep);
245 250
251 /// <summary>
252 /// Get statistics about this scene.
253 /// </summary>
254 /// <remarks>This facility is currently experimental and subject to change.</remarks>
255 /// <returns>
256 /// A dictionary where the key is the statistic name. If no statistics are supplied then returns null.
257 /// </returns>
258 public virtual Dictionary<string, float> GetStats() { return null; }
259
246 public abstract void GetResults(); 260 public abstract void GetResults();
247 261
248 public abstract void SetTerrain(float[] heightMap); 262 public abstract void SetTerrain(float[] heightMap);
diff --git a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs
index 8397eb4..f3b0630 100644
--- a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs
+++ b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs
@@ -1261,14 +1261,20 @@ namespace OpenSim.Region.Physics.OdePlugin
1261 { 1261 {
1262 m_requestedUpdateFrequency = ms; 1262 m_requestedUpdateFrequency = ms;
1263 m_eventsubscription = ms; 1263 m_eventsubscription = ms;
1264 CollisionEventsThisFrame.Clear(); 1264
1265 // Don't clear collision event reporting here. This is called directly from scene code and so can lead
1266 // to a race condition with the simulate loop
1267
1265 _parent_scene.AddCollisionEventReporting(this); 1268 _parent_scene.AddCollisionEventReporting(this);
1266 } 1269 }
1267 1270
1268 public override void UnSubscribeEvents() 1271 public override void UnSubscribeEvents()
1269 { 1272 {
1270 CollisionEventsThisFrame.Clear();
1271 _parent_scene.RemoveCollisionEventReporting(this); 1273 _parent_scene.RemoveCollisionEventReporting(this);
1274
1275 // Don't clear collision event reporting here. This is called directly from scene code and so can lead
1276 // to a race condition with the simulate loop
1277
1272 m_requestedUpdateFrequency = 0; 1278 m_requestedUpdateFrequency = 0;
1273 m_eventsubscription = 0; 1279 m_eventsubscription = 0;
1274 } 1280 }
diff --git a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
index 6f37347..a41c856 100644
--- a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
+++ b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
@@ -156,7 +156,15 @@ namespace OpenSim.Region.Physics.OdePlugin
156 /// </summary> 156 /// </summary>
157 public IntPtr m_targetSpace = IntPtr.Zero; 157 public IntPtr m_targetSpace = IntPtr.Zero;
158 158
159 /// <summary>
160 /// The prim geometry, used for collision detection.
161 /// </summary>
162 /// <remarks>
163 /// This is never null except for a brief period when the geometry needs to be replaced (due to resizing or
164 /// mesh change) or when the physical prim is being removed from the scene.
165 /// </remarks>
159 public IntPtr prim_geom { get; private set; } 166 public IntPtr prim_geom { get; private set; }
167
160 public IntPtr _triMeshData { get; private set; } 168 public IntPtr _triMeshData { get; private set; }
161 169
162 private IntPtr _linkJointGroup = IntPtr.Zero; 170 private IntPtr _linkJointGroup = IntPtr.Zero;
@@ -325,14 +333,12 @@ namespace OpenSim.Region.Physics.OdePlugin
325 { 333 {
326 prim_geom = geom; 334 prim_geom = geom;
327//Console.WriteLine("SetGeom to " + prim_geom + " for " + Name); 335//Console.WriteLine("SetGeom to " + prim_geom + " for " + Name);
328 if (prim_geom != IntPtr.Zero)
329 {
330 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
331 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
332 336
333 _parent_scene.geom_name_map[prim_geom] = Name; 337 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
334 _parent_scene.actor_name_map[prim_geom] = this; 338 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
335 } 339
340 _parent_scene.geom_name_map[prim_geom] = Name;
341 _parent_scene.actor_name_map[prim_geom] = this;
336 342
337 if (childPrim) 343 if (childPrim)
338 { 344 {
@@ -765,11 +771,8 @@ namespace OpenSim.Region.Physics.OdePlugin
765 m_collisionCategories &= ~CollisionCategories.Body; 771 m_collisionCategories &= ~CollisionCategories.Body;
766 m_collisionFlags &= ~(CollisionCategories.Wind | CollisionCategories.Land); 772 m_collisionFlags &= ~(CollisionCategories.Wind | CollisionCategories.Land);
767 773
768 if (prim_geom != IntPtr.Zero) 774 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
769 { 775 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
770 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
771 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
772 }
773 776
774 d.BodyDestroy(Body); 777 d.BodyDestroy(Body);
775 lock (childrenPrim) 778 lock (childrenPrim)
@@ -793,11 +796,8 @@ namespace OpenSim.Region.Physics.OdePlugin
793 m_collisionCategories &= ~CollisionCategories.Body; 796 m_collisionCategories &= ~CollisionCategories.Body;
794 m_collisionFlags &= ~(CollisionCategories.Wind | CollisionCategories.Land); 797 m_collisionFlags &= ~(CollisionCategories.Wind | CollisionCategories.Land);
795 798
796 if (prim_geom != IntPtr.Zero) 799 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
797 { 800 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
798 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
799 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
800 }
801 801
802 Body = IntPtr.Zero; 802 Body = IntPtr.Zero;
803 } 803 }
@@ -864,10 +864,7 @@ namespace OpenSim.Region.Physics.OdePlugin
864// _parent_scene.waitForSpaceUnlock(m_targetSpace); 864// _parent_scene.waitForSpaceUnlock(m_targetSpace);
865 try 865 try
866 { 866 {
867 if (prim_geom == IntPtr.Zero) 867 SetGeom(d.CreateTriMesh(m_targetSpace, _triMeshData, parent_scene.triCallback, null, null));
868 {
869 SetGeom(d.CreateTriMesh(m_targetSpace, _triMeshData, parent_scene.triCallback, null, null));
870 }
871 } 868 }
872 catch (AccessViolationException) 869 catch (AccessViolationException)
873 { 870 {
@@ -890,73 +887,67 @@ namespace OpenSim.Region.Physics.OdePlugin
890#if SPAM 887#if SPAM
891Console.WriteLine("ZProcessTaints for " + Name); 888Console.WriteLine("ZProcessTaints for " + Name);
892#endif 889#endif
890
891 // This must be processed as the very first taint so that later operations have a prim_geom to work with
892 // if this is a new prim.
893 if (m_taintadd) 893 if (m_taintadd)
894 {
895 changeadd(); 894 changeadd();
896 }
897
898 if (prim_geom != IntPtr.Zero)
899 {
900 if (!_position.ApproxEquals(m_taintposition, 0f))
901 changemove();
902 895
903 if (m_taintrot != _orientation) 896 if (!_position.ApproxEquals(m_taintposition, 0f))
904 { 897 changemove();
905 if (childPrim && IsPhysical) // For physical child prim... 898
906 { 899 if (m_taintrot != _orientation)
907 rotate(); 900 {
908 // KF: ODE will also rotate the parent prim! 901 if (childPrim && IsPhysical) // For physical child prim...
909 // so rotate the root back to where it was 902 {
910 OdePrim parent = (OdePrim)_parent; 903 rotate();
911 parent.rotate(); 904 // KF: ODE will also rotate the parent prim!
912 } 905 // so rotate the root back to where it was
913 else 906 OdePrim parent = (OdePrim)_parent;
914 { 907 parent.rotate();
915 //Just rotate the prim
916 rotate();
917 }
918 } 908 }
919 909 else
920 if (m_taintPhysics != IsPhysical && !(m_taintparent != _parent)) 910 {
921 changePhysicsStatus(); 911 //Just rotate the prim
912 rotate();
913 }
914 }
915
916 if (m_taintPhysics != IsPhysical && !(m_taintparent != _parent))
917 changePhysicsStatus();
922 918
923 if (!_size.ApproxEquals(m_taintsize, 0f)) 919 if (!_size.ApproxEquals(m_taintsize, 0f))
924 changesize(); 920 changesize();
925 921
926 if (m_taintshape) 922 if (m_taintshape)
927 changeshape(); 923 changeshape();
928 924
929 if (m_taintforce) 925 if (m_taintforce)
930 changeAddForce(); 926 changeAddForce();
931 927
932 if (m_taintaddangularforce) 928 if (m_taintaddangularforce)
933 changeAddAngularForce(); 929 changeAddAngularForce();
934 930
935 if (!m_taintTorque.ApproxEquals(Vector3.Zero, 0.001f)) 931 if (!m_taintTorque.ApproxEquals(Vector3.Zero, 0.001f))
936 changeSetTorque(); 932 changeSetTorque();
937 933
938 if (m_taintdisable) 934 if (m_taintdisable)
939 changedisable(); 935 changedisable();
940 936
941 if (m_taintselected != m_isSelected) 937 if (m_taintselected != m_isSelected)
942 changeSelectedStatus(); 938 changeSelectedStatus();
943 939
944 if (!m_taintVelocity.ApproxEquals(Vector3.Zero, 0.001f)) 940 if (!m_taintVelocity.ApproxEquals(Vector3.Zero, 0.001f))
945 changevelocity(); 941 changevelocity();
946 942
947 if (m_taintparent != _parent) 943 if (m_taintparent != _parent)
948 changelink(); 944 changelink();
949 945
950 if (m_taintCollidesWater != m_collidesWater) 946 if (m_taintCollidesWater != m_collidesWater)
951 changefloatonwater(); 947 changefloatonwater();
952 948
953 if (!m_angularlock.ApproxEquals(m_taintAngularLock,0f)) 949 if (!m_angularlock.ApproxEquals(m_taintAngularLock,0f))
954 changeAngularLock(); 950 changeAngularLock();
955 }
956 else
957 {
958 m_log.ErrorFormat("[PHYSICS]: The scene reused a disposed PhysActor for {0}! *waves finger*, Don't be evil. A couple of things can cause this. An improper prim breakdown(be sure to set prim_geom to zero after d.GeomDestroy! An improper buildup (creating the geom failed). Or, the Scene Reused a physics actor after disposing it.)", Name);
959 }
960 } 951 }
961 952
962 /// <summary> 953 /// <summary>
@@ -1052,150 +1043,146 @@ Console.WriteLine("ZProcessTaints for " + Name);
1052 /// <param name="prim">Child prim</param> 1043 /// <param name="prim">Child prim</param>
1053 private void AddChildPrim(OdePrim prim) 1044 private void AddChildPrim(OdePrim prim)
1054 { 1045 {
1055//Console.WriteLine("AddChildPrim " + Name); 1046 if (LocalID == prim.LocalID)
1056 if (LocalID != prim.LocalID) 1047 return;
1048
1049 if (Body == IntPtr.Zero)
1057 { 1050 {
1058 if (Body == IntPtr.Zero) 1051 Body = d.BodyCreate(_parent_scene.world);
1052 setMass();
1053 }
1054
1055 lock (childrenPrim)
1056 {
1057 if (childrenPrim.Contains(prim))
1058 return;
1059
1060// m_log.DebugFormat(
1061// "[ODE PRIM]: Linking prim {0} {1} to {2} {3}", prim.Name, prim.LocalID, Name, LocalID);
1062
1063 childrenPrim.Add(prim);
1064
1065 foreach (OdePrim prm in childrenPrim)
1059 { 1066 {
1060 Body = d.BodyCreate(_parent_scene.world); 1067 d.Mass m2;
1061 setMass(); 1068 d.MassSetZero(out m2);
1069 d.MassSetBoxTotal(out m2, prim.CalculateMass(), prm._size.X, prm._size.Y, prm._size.Z);
1070
1071 d.Quaternion quat = new d.Quaternion();
1072 quat.W = prm._orientation.W;
1073 quat.X = prm._orientation.X;
1074 quat.Y = prm._orientation.Y;
1075 quat.Z = prm._orientation.Z;
1076
1077 d.Matrix3 mat = new d.Matrix3();
1078 d.RfromQ(out mat, ref quat);
1079 d.MassRotate(ref m2, ref mat);
1080 d.MassTranslate(ref m2, Position.X - prm.Position.X, Position.Y - prm.Position.Y, Position.Z - prm.Position.Z);
1081 d.MassAdd(ref pMass, ref m2);
1062 } 1082 }
1063 if (Body != IntPtr.Zero) 1083
1084 foreach (OdePrim prm in childrenPrim)
1064 { 1085 {
1065 lock (childrenPrim) 1086 prm.m_collisionCategories |= CollisionCategories.Body;
1066 { 1087 prm.m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind);
1067 if (!childrenPrim.Contains(prim))
1068 {
1069//Console.WriteLine("childrenPrim.Add " + prim);
1070 childrenPrim.Add(prim);
1071
1072 foreach (OdePrim prm in childrenPrim)
1073 {
1074 d.Mass m2;
1075 d.MassSetZero(out m2);
1076 d.MassSetBoxTotal(out m2, prim.CalculateMass(), prm._size.X, prm._size.Y, prm._size.Z);
1077
1078 d.Quaternion quat = new d.Quaternion();
1079 quat.W = prm._orientation.W;
1080 quat.X = prm._orientation.X;
1081 quat.Y = prm._orientation.Y;
1082 quat.Z = prm._orientation.Z;
1083
1084 d.Matrix3 mat = new d.Matrix3();
1085 d.RfromQ(out mat, ref quat);
1086 d.MassRotate(ref m2, ref mat);
1087 d.MassTranslate(ref m2, Position.X - prm.Position.X, Position.Y - prm.Position.Y, Position.Z - prm.Position.Z);
1088 d.MassAdd(ref pMass, ref m2);
1089 }
1090
1091 foreach (OdePrim prm in childrenPrim)
1092 {
1093 prm.m_collisionCategories |= CollisionCategories.Body;
1094 prm.m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind);
1095 1088
1096 if (prm.prim_geom == IntPtr.Zero)
1097 {
1098 m_log.WarnFormat(
1099 "[PHYSICS]: Unable to link one of the linkset elements {0} for parent {1}. No geom yet",
1100 prm.Name, prim.Name);
1101 continue;
1102 }
1103//Console.WriteLine(" GeomSetCategoryBits 1: " + prm.prim_geom + " - " + (int)prm.m_collisionCategories + " for " + Name); 1089//Console.WriteLine(" GeomSetCategoryBits 1: " + prm.prim_geom + " - " + (int)prm.m_collisionCategories + " for " + Name);
1104 d.GeomSetCategoryBits(prm.prim_geom, (int)prm.m_collisionCategories); 1090 d.GeomSetCategoryBits(prm.prim_geom, (int)prm.m_collisionCategories);
1105 d.GeomSetCollideBits(prm.prim_geom, (int)prm.m_collisionFlags); 1091 d.GeomSetCollideBits(prm.prim_geom, (int)prm.m_collisionFlags);
1106
1107 1092
1108 d.Quaternion quat = new d.Quaternion(); 1093 d.Quaternion quat = new d.Quaternion();
1109 quat.W = prm._orientation.W; 1094 quat.W = prm._orientation.W;
1110 quat.X = prm._orientation.X; 1095 quat.X = prm._orientation.X;
1111 quat.Y = prm._orientation.Y; 1096 quat.Y = prm._orientation.Y;
1112 quat.Z = prm._orientation.Z; 1097 quat.Z = prm._orientation.Z;
1113 1098
1114 d.Matrix3 mat = new d.Matrix3(); 1099 d.Matrix3 mat = new d.Matrix3();
1115 d.RfromQ(out mat, ref quat); 1100 d.RfromQ(out mat, ref quat);
1116 if (Body != IntPtr.Zero) 1101 if (Body != IntPtr.Zero)
1117 { 1102 {
1118 d.GeomSetBody(prm.prim_geom, Body); 1103 d.GeomSetBody(prm.prim_geom, Body);
1119 prm.childPrim = true; 1104 prm.childPrim = true;
1120 d.GeomSetOffsetWorldPosition(prm.prim_geom, prm.Position.X , prm.Position.Y, prm.Position.Z); 1105 d.GeomSetOffsetWorldPosition(prm.prim_geom, prm.Position.X , prm.Position.Y, prm.Position.Z);
1121 //d.GeomSetOffsetPosition(prim.prim_geom, 1106 //d.GeomSetOffsetPosition(prim.prim_geom,
1122 // (Position.X - prm.Position.X) - pMass.c.X, 1107 // (Position.X - prm.Position.X) - pMass.c.X,
1123 // (Position.Y - prm.Position.Y) - pMass.c.Y, 1108 // (Position.Y - prm.Position.Y) - pMass.c.Y,
1124 // (Position.Z - prm.Position.Z) - pMass.c.Z); 1109 // (Position.Z - prm.Position.Z) - pMass.c.Z);
1125 d.GeomSetOffsetWorldRotation(prm.prim_geom, ref mat); 1110 d.GeomSetOffsetWorldRotation(prm.prim_geom, ref mat);
1126 //d.GeomSetOffsetRotation(prm.prim_geom, ref mat); 1111 //d.GeomSetOffsetRotation(prm.prim_geom, ref mat);
1127 d.MassTranslate(ref pMass, -pMass.c.X, -pMass.c.Y, -pMass.c.Z); 1112 d.MassTranslate(ref pMass, -pMass.c.X, -pMass.c.Y, -pMass.c.Z);
1128 d.BodySetMass(Body, ref pMass); 1113 d.BodySetMass(Body, ref pMass);
1129 } 1114 }
1130 else 1115 else
1131 { 1116 {
1132 m_log.DebugFormat("[PHYSICS]: {0} ain't got no boooooooooddy, no body", Name); 1117 m_log.DebugFormat("[PHYSICS]: {0} ain't got no boooooooooddy, no body", Name);
1133 } 1118 }
1134 1119
1135 prm.m_interpenetrationcount = 0; 1120 prm.m_interpenetrationcount = 0;
1136 prm.m_collisionscore = 0; 1121 prm.m_collisionscore = 0;
1137 prm.m_disabled = false; 1122 prm.m_disabled = false;
1138 1123
1139 // The body doesn't already have a finite rotation mode set here 1124 // The body doesn't already have a finite rotation mode set here
1140 if ((!m_angularlock.ApproxEquals(Vector3.Zero, 0f)) && _parent == null) 1125 if ((!m_angularlock.ApproxEquals(Vector3.Zero, 0f)) && _parent == null)
1141 { 1126 {
1142 prm.createAMotor(m_angularlock); 1127 prm.createAMotor(m_angularlock);
1143 } 1128 }
1144 prm.Body = Body; 1129 prm.Body = Body;
1145 _parent_scene.ActivatePrim(prm); 1130 _parent_scene.ActivatePrim(prm);
1146 } 1131 }
1147 1132
1148 m_collisionCategories |= CollisionCategories.Body; 1133 m_collisionCategories |= CollisionCategories.Body;
1149 m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind); 1134 m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind);
1150 1135
1151//Console.WriteLine("GeomSetCategoryBits 2: " + prim_geom + " - " + (int)m_collisionCategories + " for " + Name); 1136//Console.WriteLine("GeomSetCategoryBits 2: " + prim_geom + " - " + (int)m_collisionCategories + " for " + Name);
1152 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); 1137 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
1153//Console.WriteLine(" Post GeomSetCategoryBits 2"); 1138//Console.WriteLine(" Post GeomSetCategoryBits 2");
1154 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); 1139 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
1155
1156 d.Quaternion quat2 = new d.Quaternion();
1157 quat2.W = _orientation.W;
1158 quat2.X = _orientation.X;
1159 quat2.Y = _orientation.Y;
1160 quat2.Z = _orientation.Z;
1161
1162 d.Matrix3 mat2 = new d.Matrix3();
1163 d.RfromQ(out mat2, ref quat2);
1164 d.GeomSetBody(prim_geom, Body);
1165 d.GeomSetOffsetWorldPosition(prim_geom, Position.X - pMass.c.X, Position.Y - pMass.c.Y, Position.Z - pMass.c.Z);
1166 //d.GeomSetOffsetPosition(prim.prim_geom,
1167 // (Position.X - prm.Position.X) - pMass.c.X,
1168 // (Position.Y - prm.Position.Y) - pMass.c.Y,
1169 // (Position.Z - prm.Position.Z) - pMass.c.Z);
1170 //d.GeomSetOffsetRotation(prim_geom, ref mat2);
1171 d.MassTranslate(ref pMass, -pMass.c.X, -pMass.c.Y, -pMass.c.Z);
1172 d.BodySetMass(Body, ref pMass);
1173
1174 d.BodySetAutoDisableFlag(Body, true);
1175 d.BodySetAutoDisableSteps(Body, body_autodisable_frames);
1176 1140
1177 m_interpenetrationcount = 0; 1141 d.Quaternion quat2 = new d.Quaternion();
1178 m_collisionscore = 0; 1142 quat2.W = _orientation.W;
1179 m_disabled = false; 1143 quat2.X = _orientation.X;
1144 quat2.Y = _orientation.Y;
1145 quat2.Z = _orientation.Z;
1180 1146
1181 // The body doesn't already have a finite rotation mode set here 1147 d.Matrix3 mat2 = new d.Matrix3();
1182 if ((!m_angularlock.ApproxEquals(Vector3.Zero, 0f)) && _parent == null) 1148 d.RfromQ(out mat2, ref quat2);
1183 { 1149 d.GeomSetBody(prim_geom, Body);
1184 createAMotor(m_angularlock); 1150 d.GeomSetOffsetWorldPosition(prim_geom, Position.X - pMass.c.X, Position.Y - pMass.c.Y, Position.Z - pMass.c.Z);
1185 } 1151 //d.GeomSetOffsetPosition(prim.prim_geom,
1186 d.BodySetPosition(Body, Position.X, Position.Y, Position.Z); 1152 // (Position.X - prm.Position.X) - pMass.c.X,
1187 if (m_vehicle.Type != Vehicle.TYPE_NONE) 1153 // (Position.Y - prm.Position.Y) - pMass.c.Y,
1188 m_vehicle.Enable(Body, _parent_scene); 1154 // (Position.Z - prm.Position.Z) - pMass.c.Z);
1155 //d.GeomSetOffsetRotation(prim_geom, ref mat2);
1156 d.MassTranslate(ref pMass, -pMass.c.X, -pMass.c.Y, -pMass.c.Z);
1157 d.BodySetMass(Body, ref pMass);
1189 1158
1190 _parent_scene.ActivatePrim(this); 1159 d.BodySetAutoDisableFlag(Body, true);
1191 } 1160 d.BodySetAutoDisableSteps(Body, body_autodisable_frames);
1192 } 1161
1162 m_interpenetrationcount = 0;
1163 m_collisionscore = 0;
1164 m_disabled = false;
1165
1166 // The body doesn't already have a finite rotation mode set here
1167 if ((!m_angularlock.ApproxEquals(Vector3.Zero, 0f)) && _parent == null)
1168 {
1169 createAMotor(m_angularlock);
1193 } 1170 }
1171
1172 d.BodySetPosition(Body, Position.X, Position.Y, Position.Z);
1173
1174 if (m_vehicle.Type != Vehicle.TYPE_NONE)
1175 m_vehicle.Enable(Body, _parent_scene);
1176
1177 _parent_scene.ActivatePrim(this);
1194 } 1178 }
1195 } 1179 }
1196 1180
1197 private void ChildSetGeom(OdePrim odePrim) 1181 private void ChildSetGeom(OdePrim odePrim)
1198 { 1182 {
1183// m_log.DebugFormat(
1184// "[ODE PRIM]: ChildSetGeom {0} {1} for {2} {3}", odePrim.Name, odePrim.LocalID, Name, LocalID);
1185
1199 //if (IsPhysical && Body != IntPtr.Zero) 1186 //if (IsPhysical && Body != IntPtr.Zero)
1200 lock (childrenPrim) 1187 lock (childrenPrim)
1201 { 1188 {
@@ -1210,12 +1197,14 @@ Console.WriteLine("ZProcessTaints for " + Name);
1210 //prm.childPrim = false; 1197 //prm.childPrim = false;
1211 } 1198 }
1212 } 1199 }
1200
1213 disableBody(); 1201 disableBody();
1214 1202
1215 if (Body != IntPtr.Zero) 1203 // Spurious - Body == IntPtr.Zero after disableBody()
1216 { 1204// if (Body != IntPtr.Zero)
1217 _parent_scene.DeactivatePrim(this); 1205// {
1218 } 1206// _parent_scene.DeactivatePrim(this);
1207// }
1219 1208
1220 lock (childrenPrim) 1209 lock (childrenPrim)
1221 { 1210 {
@@ -1229,6 +1218,9 @@ Console.WriteLine("ZProcessTaints for " + Name);
1229 1218
1230 private void ChildDelink(OdePrim odePrim) 1219 private void ChildDelink(OdePrim odePrim)
1231 { 1220 {
1221// m_log.DebugFormat(
1222// "[ODE PRIM]: Delinking prim {0} {1} from {2} {3}", odePrim.Name, odePrim.LocalID, Name, LocalID);
1223
1232 // Okay, we have a delinked child.. need to rebuild the body. 1224 // Okay, we have a delinked child.. need to rebuild the body.
1233 lock (childrenPrim) 1225 lock (childrenPrim)
1234 { 1226 {
@@ -1243,6 +1235,7 @@ Console.WriteLine("ZProcessTaints for " + Name);
1243 //prm.childPrim = false; 1235 //prm.childPrim = false;
1244 } 1236 }
1245 } 1237 }
1238
1246 disableBody(); 1239 disableBody();
1247 1240
1248 lock (childrenPrim) 1241 lock (childrenPrim)
@@ -1251,10 +1244,11 @@ Console.WriteLine("ZProcessTaints for " + Name);
1251 childrenPrim.Remove(odePrim); 1244 childrenPrim.Remove(odePrim);
1252 } 1245 }
1253 1246
1254 if (Body != IntPtr.Zero) 1247 // Spurious - Body == IntPtr.Zero after disableBody()
1255 { 1248// if (Body != IntPtr.Zero)
1256 _parent_scene.DeactivatePrim(this); 1249// {
1257 } 1250// _parent_scene.DeactivatePrim(this);
1251// }
1258 1252
1259 lock (childrenPrim) 1253 lock (childrenPrim)
1260 { 1254 {
@@ -1303,11 +1297,8 @@ Console.WriteLine("ZProcessTaints for " + Name);
1303 disableBodySoft(); 1297 disableBodySoft();
1304 } 1298 }
1305 1299
1306 if (prim_geom != IntPtr.Zero) 1300 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
1307 { 1301 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
1308 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
1309 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
1310 }
1311 1302
1312 if (IsPhysical) 1303 if (IsPhysical)
1313 { 1304 {
@@ -1328,11 +1319,8 @@ Console.WriteLine("ZProcessTaints for " + Name);
1328 if (m_collidesWater) 1319 if (m_collidesWater)
1329 m_collisionFlags |= CollisionCategories.Water; 1320 m_collisionFlags |= CollisionCategories.Water;
1330 1321
1331 if (prim_geom != IntPtr.Zero) 1322 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
1332 { 1323 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
1333 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
1334 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
1335 }
1336 1324
1337 if (IsPhysical) 1325 if (IsPhysical)
1338 { 1326 {
@@ -1472,6 +1460,9 @@ Console.WriteLine("CreateGeom:");
1472 } 1460 }
1473 else 1461 else
1474 { 1462 {
1463 m_log.WarnFormat(
1464 "[ODE PRIM]: Called RemoveGeom() on {0} {1} where geometry was already null.", Name, LocalID);
1465
1475 return false; 1466 return false;
1476 } 1467 }
1477 } 1468 }
@@ -1505,16 +1496,13 @@ Console.WriteLine("changeadd 1");
1505#endif 1496#endif
1506 CreateGeom(m_targetSpace, mesh); 1497 CreateGeom(m_targetSpace, mesh);
1507 1498
1508 if (prim_geom != IntPtr.Zero) 1499 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
1509 { 1500 d.Quaternion myrot = new d.Quaternion();
1510 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z); 1501 myrot.X = _orientation.X;
1511 d.Quaternion myrot = new d.Quaternion(); 1502 myrot.Y = _orientation.Y;
1512 myrot.X = _orientation.X; 1503 myrot.Z = _orientation.Z;
1513 myrot.Y = _orientation.Y; 1504 myrot.W = _orientation.W;
1514 myrot.Z = _orientation.Z; 1505 d.GeomSetQuaternion(prim_geom, ref myrot);
1515 myrot.W = _orientation.W;
1516 d.GeomSetQuaternion(prim_geom, ref myrot);
1517 }
1518 1506
1519 if (IsPhysical && Body == IntPtr.Zero) 1507 if (IsPhysical && Body == IntPtr.Zero)
1520 enableBody(); 1508 enableBody();
@@ -1579,24 +1567,20 @@ Console.WriteLine(" JointCreateFixed");
1579 //m_log.Debug("[BUG]: race!"); 1567 //m_log.Debug("[BUG]: race!");
1580 //} 1568 //}
1581 } 1569 }
1582 else
1583 {
1584 // string primScenAvatarIn = _parent_scene.whichspaceamIin(_position);
1585 // int[] arrayitem = _parent_scene.calculateSpaceArrayItemFromPos(_position);
1586// _parent_scene.waitForSpaceUnlock(m_targetSpace);
1587 1570
1588 IntPtr tempspace = _parent_scene.recalculateSpaceForGeom(prim_geom, _position, m_targetSpace); 1571 // string primScenAvatarIn = _parent_scene.whichspaceamIin(_position);
1589 m_targetSpace = tempspace; 1572 // int[] arrayitem = _parent_scene.calculateSpaceArrayItemFromPos(_position);
1573// _parent_scene.waitForSpaceUnlock(m_targetSpace);
1574
1575 IntPtr tempspace = _parent_scene.recalculateSpaceForGeom(prim_geom, _position, m_targetSpace);
1576 m_targetSpace = tempspace;
1590 1577
1591// _parent_scene.waitForSpaceUnlock(m_targetSpace); 1578// _parent_scene.waitForSpaceUnlock(m_targetSpace);
1592 if (prim_geom != IntPtr.Zero) 1579
1593 { 1580 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
1594 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
1595 1581
1596// _parent_scene.waitForSpaceUnlock(m_targetSpace); 1582// _parent_scene.waitForSpaceUnlock(m_targetSpace);
1597 d.SpaceAdd(m_targetSpace, prim_geom); 1583 d.SpaceAdd(m_targetSpace, prim_geom);
1598 }
1599 }
1600 1584
1601 changeSelectedStatus(); 1585 changeSelectedStatus();
1602 1586
@@ -2047,18 +2031,16 @@ Console.WriteLine(" JointCreateFixed");
2047 { 2031 {
2048 m_collidesWater = m_taintCollidesWater; 2032 m_collidesWater = m_taintCollidesWater;
2049 2033
2050 if (prim_geom != IntPtr.Zero) 2034 if (m_collidesWater)
2051 { 2035 {
2052 if (m_collidesWater) 2036 m_collisionFlags |= CollisionCategories.Water;
2053 {
2054 m_collisionFlags |= CollisionCategories.Water;
2055 }
2056 else
2057 {
2058 m_collisionFlags &= ~CollisionCategories.Water;
2059 }
2060 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
2061 } 2037 }
2038 else
2039 {
2040 m_collisionFlags &= ~CollisionCategories.Water;
2041 }
2042
2043 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
2062 } 2044 }
2063 2045
2064 /// <summary> 2046 /// <summary>
diff --git a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs
index 842ff91..32e81e2 100644
--- a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs
+++ b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs
@@ -30,20 +30,21 @@
30 30
31using System; 31using System;
32using System.Collections.Generic; 32using System.Collections.Generic;
33using System.Diagnostics;
34using System.IO;
35using System.Linq;
33using System.Reflection; 36using System.Reflection;
34using System.Runtime.InteropServices; 37using System.Runtime.InteropServices;
35using System.Threading; 38using System.Threading;
36using System.IO;
37using System.Diagnostics;
38using log4net; 39using log4net;
39using Nini.Config; 40using Nini.Config;
40using Ode.NET; 41using Ode.NET;
42using OpenMetaverse;
41#if USE_DRAWSTUFF 43#if USE_DRAWSTUFF
42using Drawstuff.NET; 44using Drawstuff.NET;
43#endif 45#endif
44using OpenSim.Framework; 46using OpenSim.Framework;
45using OpenSim.Region.Physics.Manager; 47using OpenSim.Region.Physics.Manager;
46using OpenMetaverse;
47 48
48namespace OpenSim.Region.Physics.OdePlugin 49namespace OpenSim.Region.Physics.OdePlugin
49{ 50{
@@ -54,15 +55,15 @@ namespace OpenSim.Region.Physics.OdePlugin
54 End = 2 55 End = 2
55 } 56 }
56 57
57 public struct sCollisionData 58// public struct sCollisionData
58 { 59// {
59 public uint ColliderLocalId; 60// public uint ColliderLocalId;
60 public uint CollidedWithLocalId; 61// public uint CollidedWithLocalId;
61 public int NumberOfCollisions; 62// public int NumberOfCollisions;
62 public int CollisionType; 63// public int CollisionType;
63 public int StatusIndicator; 64// public int StatusIndicator;
64 public int lastframe; 65// public int lastframe;
65 } 66// }
66 67
67 [Flags] 68 [Flags]
68 public enum CollisionCategories : int 69 public enum CollisionCategories : int
@@ -131,6 +132,135 @@ namespace OpenSim.Region.Physics.OdePlugin
131 /// </remarks> 132 /// </remarks>
132 internal static Object UniversalColliderSyncObject = new Object(); 133 internal static Object UniversalColliderSyncObject = new Object();
133 134
135 /// <summary>
136 /// Is stats collecting enabled for this ODE scene?
137 /// </summary>
138 public bool CollectStats { get; set; }
139
140 /// <summary>
141 /// Statistics for this scene.
142 /// </summary>
143 private Dictionary<string, float> m_stats = new Dictionary<string, float>();
144
145 /// <summary>
146 /// Stat name for total number of avatars in this ODE scene.
147 /// </summary>
148 public const string ODETotalAvatarsStatName = "ODETotalAvatars";
149
150 /// <summary>
151 /// Stat name for total number of prims in this ODE scene.
152 /// </summary>
153 public const string ODETotalPrimsStatName = "ODETotalPrims";
154
155 /// <summary>
156 /// Stat name for total number of prims with active physics in this ODE scene.
157 /// </summary>
158 public const string ODEActivePrimsStatName = "ODEActivePrims";
159
160 /// <summary>
161 /// Stat name for the total time spent in ODE frame processing.
162 /// </summary>
163 /// <remarks>
164 /// A sanity check for the main scene loop physics time.
165 /// </remarks>
166 public const string ODETotalFrameMsStatName = "ODETotalFrameMS";
167
168 /// <summary>
169 /// Stat name for time spent processing avatar taints per frame
170 /// </summary>
171 public const string ODEAvatarTaintMsStatName = "ODEAvatarTaintFrameMS";
172
173 /// <summary>
174 /// Stat name for time spent processing prim taints per frame
175 /// </summary>
176 public const string ODEPrimTaintMsStatName = "ODEPrimTaintFrameMS";
177
178 /// <summary>
179 /// Stat name for time spent calculating avatar forces per frame.
180 /// </summary>
181 public const string ODEAvatarForcesFrameMsStatName = "ODEAvatarForcesFrameMS";
182
183 /// <summary>
184 /// Stat name for time spent calculating prim forces per frame
185 /// </summary>
186 public const string ODEPrimForcesFrameMsStatName = "ODEPrimForcesFrameMS";
187
188 /// <summary>
189 /// Stat name for time spent fulfilling raycasting requests per frame
190 /// </summary>
191 public const string ODERaycastingFrameMsStatName = "ODERaycastingFrameMS";
192
193 /// <summary>
194 /// Stat name for time spent in native code that actually steps through the simulation.
195 /// </summary>
196 public const string ODENativeStepFrameMsStatName = "ODENativeStepFrameMS";
197
198 /// <summary>
199 /// Stat name for the number of milliseconds that ODE spends in native space collision code.
200 /// </summary>
201 public const string ODENativeSpaceCollisionFrameMsStatName = "ODENativeSpaceCollisionFrameMS";
202
203 /// <summary>
204 /// Stat name for milliseconds that ODE spends in native geom collision code.
205 /// </summary>
206 public const string ODENativeGeomCollisionFrameMsStatName = "ODENativeGeomCollisionFrameMS";
207
208 /// <summary>
209 /// Time spent in collision processing that is not spent in native space or geom collision code.
210 /// </summary>
211 public const string ODEOtherCollisionFrameMsStatName = "ODEOtherCollisionFrameMS";
212
213 /// <summary>
214 /// Stat name for time spent notifying listeners of collisions
215 /// </summary>
216 public const string ODECollisionNotificationFrameMsStatName = "ODECollisionNotificationFrameMS";
217
218 /// <summary>
219 /// Stat name for milliseconds spent updating avatar position and velocity
220 /// </summary>
221 public const string ODEAvatarUpdateFrameMsStatName = "ODEAvatarUpdateFrameMS";
222
223 /// <summary>
224 /// Stat name for the milliseconds spent updating prim position and velocity
225 /// </summary>
226 public const string ODEPrimUpdateFrameMsStatName = "ODEPrimUpdateFrameMS";
227
228 /// <summary>
229 /// Stat name for avatar collisions with another entity.
230 /// </summary>
231 public const string ODEAvatarContactsStatsName = "ODEAvatarContacts";
232
233 /// <summary>
234 /// Stat name for prim collisions with another entity.
235 /// </summary>
236 public const string ODEPrimContactsStatName = "ODEPrimContacts";
237
238 /// <summary>
239 /// Used to hold tick numbers for stat collection purposes.
240 /// </summary>
241 private int m_nativeCollisionStartTick;
242
243 /// <summary>
244 /// A messy way to tell if we need to avoid adding a collision time because this was already done in the callback.
245 /// </summary>
246 private bool m_inCollisionTiming;
247
248 /// <summary>
249 /// A temporary holder for the number of avatar collisions in a frame, so we can work out how many object
250 /// collisions occured using the _perloopcontact if stats collection is enabled.
251 /// </summary>
252 private int m_tempAvatarCollisionsThisFrame;
253
254 /// <summary>
255 /// Used in calculating physics frame time dilation
256 /// </summary>
257 private int tickCountFrameRun;
258
259 /// <summary>
260 /// Used in calculating physics frame time dilation
261 /// </summary>
262 private int latertickcount;
263
134 private Random fluidRandomizer = new Random(Environment.TickCount); 264 private Random fluidRandomizer = new Random(Environment.TickCount);
135 265
136 private const uint m_regionWidth = Constants.RegionSize; 266 private const uint m_regionWidth = Constants.RegionSize;
@@ -257,12 +387,12 @@ namespace OpenSim.Region.Physics.OdePlugin
257 /// <summary> 387 /// <summary>
258 /// A dictionary of actors that should receive collision events. 388 /// A dictionary of actors that should receive collision events.
259 /// </summary> 389 /// </summary>
260 private readonly Dictionary<uint, PhysicsActor> _collisionEventPrim = new Dictionary<uint, PhysicsActor>(); 390 private readonly Dictionary<uint, PhysicsActor> m_collisionEventActors = new Dictionary<uint, PhysicsActor>();
261 391
262 /// <summary> 392 /// <summary>
263 /// A dictionary of collision event changes that are waiting to be processed. 393 /// A dictionary of collision event changes that are waiting to be processed.
264 /// </summary> 394 /// </summary>
265 private readonly Dictionary<uint, PhysicsActor> _collisionEventPrimChanges = new Dictionary<uint, PhysicsActor>(); 395 private readonly Dictionary<uint, PhysicsActor> m_collisionEventActorsChanges = new Dictionary<uint, PhysicsActor>();
266 396
267 /// <summary> 397 /// <summary>
268 /// Maps a unique geometry id (a memory location) to a physics actor name. 398 /// Maps a unique geometry id (a memory location) to a physics actor name.
@@ -345,9 +475,6 @@ namespace OpenSim.Region.Physics.OdePlugin
345 private OdePrim cp1; 475 private OdePrim cp1;
346 private OdeCharacter cc2; 476 private OdeCharacter cc2;
347 private OdePrim cp2; 477 private OdePrim cp2;
348 private int tickCountFrameRun;
349
350 private int latertickcount=0;
351 //private int cStartStop = 0; 478 //private int cStartStop = 0;
352 //private string cDictKey = ""; 479 //private string cDictKey = "";
353 480
@@ -440,6 +567,8 @@ namespace OpenSim.Region.Physics.OdePlugin
440 // Initialize the mesh plugin 567 // Initialize the mesh plugin
441 public override void Initialise(IMesher meshmerizer, IConfigSource config) 568 public override void Initialise(IMesher meshmerizer, IConfigSource config)
442 { 569 {
570 InitializeExtraStats();
571
443 mesher = meshmerizer; 572 mesher = meshmerizer;
444 m_config = config; 573 m_config = config;
445 // Defaults 574 // Defaults
@@ -464,6 +593,8 @@ namespace OpenSim.Region.Physics.OdePlugin
464 IConfig physicsconfig = m_config.Configs["ODEPhysicsSettings"]; 593 IConfig physicsconfig = m_config.Configs["ODEPhysicsSettings"];
465 if (physicsconfig != null) 594 if (physicsconfig != null)
466 { 595 {
596 CollectStats = physicsconfig.GetBoolean("collect_stats", false);
597
467 gravityx = physicsconfig.GetFloat("world_gravityx", 0f); 598 gravityx = physicsconfig.GetFloat("world_gravityx", 0f);
468 gravityy = physicsconfig.GetFloat("world_gravityy", 0f); 599 gravityy = physicsconfig.GetFloat("world_gravityy", 0f);
469 gravityz = physicsconfig.GetFloat("world_gravityz", -9.8f); 600 gravityz = physicsconfig.GetFloat("world_gravityz", -9.8f);
@@ -765,6 +896,62 @@ namespace OpenSim.Region.Physics.OdePlugin
765 #region Collision Detection 896 #region Collision Detection
766 897
767 /// <summary> 898 /// <summary>
899 /// Collides two geometries.
900 /// </summary>
901 /// <returns></returns>
902 /// <param name='geom1'></param>
903 /// <param name='geom2'>/param>
904 /// <param name='maxContacts'></param>
905 /// <param name='contactsArray'></param>
906 /// <param name='contactGeomSize'></param>
907 private int CollideGeoms(
908 IntPtr geom1, IntPtr geom2, int maxContacts, Ode.NET.d.ContactGeom[] contactsArray, int contactGeomSize)
909 {
910 int count;
911
912 lock (OdeScene.UniversalColliderSyncObject)
913 {
914 // We do this inside the lock so that we don't count any delay in acquiring it
915 if (CollectStats)
916 m_nativeCollisionStartTick = Util.EnvironmentTickCount();
917
918 count = d.Collide(geom1, geom2, maxContacts, contactsArray, contactGeomSize);
919 }
920
921 // We do this outside the lock so that any waiting threads aren't held up, though the effect is probably
922 // negligable
923 if (CollectStats)
924 m_stats[ODENativeGeomCollisionFrameMsStatName]
925 += Util.EnvironmentTickCountSubtract(m_nativeCollisionStartTick);
926
927 return count;
928 }
929
930 /// <summary>
931 /// Collide two spaces or a space and a geometry.
932 /// </summary>
933 /// <param name='space1'></param>
934 /// <param name='space2'>/param>
935 /// <param name='data'></param>
936 private void CollideSpaces(IntPtr space1, IntPtr space2, IntPtr data)
937 {
938 if (CollectStats)
939 {
940 m_inCollisionTiming = true;
941 m_nativeCollisionStartTick = Util.EnvironmentTickCount();
942 }
943
944 d.SpaceCollide2(space1, space2, data, nearCallback);
945
946 if (CollectStats && m_inCollisionTiming)
947 {
948 m_stats[ODENativeSpaceCollisionFrameMsStatName]
949 += Util.EnvironmentTickCountSubtract(m_nativeCollisionStartTick);
950 m_inCollisionTiming = false;
951 }
952 }
953
954 /// <summary>
768 /// This is our near callback. A geometry is near a body 955 /// This is our near callback. A geometry is near a body
769 /// </summary> 956 /// </summary>
770 /// <param name="space">The space that contains the geoms. Remember, spaces are also geoms</param> 957 /// <param name="space">The space that contains the geoms. Remember, spaces are also geoms</param>
@@ -772,6 +959,13 @@ namespace OpenSim.Region.Physics.OdePlugin
772 /// <param name="g2">another geometry or space</param> 959 /// <param name="g2">another geometry or space</param>
773 private void near(IntPtr space, IntPtr g1, IntPtr g2) 960 private void near(IntPtr space, IntPtr g1, IntPtr g2)
774 { 961 {
962 if (CollectStats && m_inCollisionTiming)
963 {
964 m_stats[ODENativeSpaceCollisionFrameMsStatName]
965 += Util.EnvironmentTickCountSubtract(m_nativeCollisionStartTick);
966 m_inCollisionTiming = false;
967 }
968
775// m_log.DebugFormat("[PHYSICS]: Colliding {0} and {1} in {2}", g1, g2, space); 969// m_log.DebugFormat("[PHYSICS]: Colliding {0} and {1} in {2}", g1, g2, space);
776 // no lock here! It's invoked from within Simulate(), which is thread-locked 970 // no lock here! It's invoked from within Simulate(), which is thread-locked
777 971
@@ -789,7 +983,7 @@ namespace OpenSim.Region.Physics.OdePlugin
789 // contact points in the space 983 // contact points in the space
790 try 984 try
791 { 985 {
792 d.SpaceCollide2(g1, g2, IntPtr.Zero, nearCallback); 986 CollideSpaces(g1, g2, IntPtr.Zero);
793 } 987 }
794 catch (AccessViolationException) 988 catch (AccessViolationException)
795 { 989 {
@@ -832,6 +1026,7 @@ namespace OpenSim.Region.Physics.OdePlugin
832 1026
833 // Figure out how many contact points we have 1027 // Figure out how many contact points we have
834 int count = 0; 1028 int count = 0;
1029
835 try 1030 try
836 { 1031 {
837 // Colliding Geom To Geom 1032 // Colliding Geom To Geom
@@ -843,8 +1038,11 @@ namespace OpenSim.Region.Physics.OdePlugin
843 if (b1 != IntPtr.Zero && b2 != IntPtr.Zero && d.AreConnectedExcluding(b1, b2, d.JointType.Contact)) 1038 if (b1 != IntPtr.Zero && b2 != IntPtr.Zero && d.AreConnectedExcluding(b1, b2, d.JointType.Contact))
844 return; 1039 return;
845 1040
846 lock (OdeScene.UniversalColliderSyncObject) 1041 count = CollideGeoms(g1, g2, contacts.Length, contacts, d.ContactGeom.SizeOf);
847 count = d.Collide(g1, g2, contacts.Length, contacts, d.ContactGeom.SizeOf); 1042
1043 // All code after this is only relevant if we have any collisions
1044 if (count <= 0)
1045 return;
848 1046
849 if (count > contacts.Length) 1047 if (count > contacts.Length)
850 m_log.Error("[ODE SCENE]: Got " + count + " contacts when we asked for a maximum of " + contacts.Length); 1048 m_log.Error("[ODE SCENE]: Got " + count + " contacts when we asked for a maximum of " + contacts.Length);
@@ -1113,14 +1311,12 @@ namespace OpenSim.Region.Physics.OdePlugin
1113 { 1311 {
1114 _perloopContact.Add(curContact); 1312 _perloopContact.Add(curContact);
1115 1313
1116 // If we're colliding against terrain
1117 if (name1 == "Terrain" || name2 == "Terrain") 1314 if (name1 == "Terrain" || name2 == "Terrain")
1118 { 1315 {
1119 // If we're moving
1120 if ((p2.PhysicsActorType == (int) ActorTypes.Agent) && 1316 if ((p2.PhysicsActorType == (int) ActorTypes.Agent) &&
1121 (Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f)) 1317 (Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f))
1122 { 1318 {
1123 // Use the movement terrain contact 1319 // Avatar is moving on terrain, use the movement terrain contact
1124 AvatarMovementTerrainContact.geom = curContact; 1320 AvatarMovementTerrainContact.geom = curContact;
1125 1321
1126 if (m_global_contactcount < maxContactsbeforedeath) 1322 if (m_global_contactcount < maxContactsbeforedeath)
@@ -1133,7 +1329,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1133 { 1329 {
1134 if (p2.PhysicsActorType == (int)ActorTypes.Agent) 1330 if (p2.PhysicsActorType == (int)ActorTypes.Agent)
1135 { 1331 {
1136 // Use the non moving terrain contact 1332 // Avatar is standing on terrain, use the non moving terrain contact
1137 TerrainContact.geom = curContact; 1333 TerrainContact.geom = curContact;
1138 1334
1139 if (m_global_contactcount < maxContactsbeforedeath) 1335 if (m_global_contactcount < maxContactsbeforedeath)
@@ -1228,13 +1424,11 @@ namespace OpenSim.Region.Physics.OdePlugin
1228 } 1424 }
1229 else 1425 else
1230 { 1426 {
1231 // we're colliding with prim or avatar
1232 // check if we're moving
1233 if ((p2.PhysicsActorType == (int)ActorTypes.Agent)) 1427 if ((p2.PhysicsActorType == (int)ActorTypes.Agent))
1234 { 1428 {
1235 if ((Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f)) 1429 if ((Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f))
1236 { 1430 {
1237 // Use the Movement prim contact 1431 // Avatar is moving on a prim, use the Movement prim contact
1238 AvatarMovementprimContact.geom = curContact; 1432 AvatarMovementprimContact.geom = curContact;
1239 1433
1240 if (m_global_contactcount < maxContactsbeforedeath) 1434 if (m_global_contactcount < maxContactsbeforedeath)
@@ -1245,9 +1439,8 @@ namespace OpenSim.Region.Physics.OdePlugin
1245 } 1439 }
1246 else 1440 else
1247 { 1441 {
1248 // Use the non movement contact 1442 // Avatar is standing still on a prim, use the non movement contact
1249 contact.geom = curContact; 1443 contact.geom = curContact;
1250 _perloopContact.Add(curContact);
1251 1444
1252 if (m_global_contactcount < maxContactsbeforedeath) 1445 if (m_global_contactcount < maxContactsbeforedeath)
1253 { 1446 {
@@ -1355,7 +1548,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1355 break; 1548 break;
1356 } 1549 }
1357 } 1550 }
1358 //m_log.DebugFormat("[Collsion]: Depth {0}", Math.Abs(contact.depth - contactGeom.depth)); 1551 //m_log.DebugFormat("[Collision]: Depth {0}", Math.Abs(contact.depth - contactGeom.depth));
1359 //m_log.DebugFormat("[Collision]: <{0},{1},{2}>", Math.Abs(contactGeom.normal.X - contact.normal.X), Math.Abs(contactGeom.normal.Y - contact.normal.Y), Math.Abs(contactGeom.normal.Z - contact.normal.Z)); 1552 //m_log.DebugFormat("[Collision]: <{0},{1},{2}>", Math.Abs(contactGeom.normal.X - contact.normal.X), Math.Abs(contactGeom.normal.Y - contact.normal.Y), Math.Abs(contactGeom.normal.Z - contact.normal.Z));
1360 } 1553 }
1361 } 1554 }
@@ -1578,7 +1771,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1578 // and we'll run it again on all of them. 1771 // and we'll run it again on all of them.
1579 try 1772 try
1580 { 1773 {
1581 d.SpaceCollide2(space, chr.Shell, IntPtr.Zero, nearCallback); 1774 CollideSpaces(space, chr.Shell, IntPtr.Zero);
1582 } 1775 }
1583 catch (AccessViolationException) 1776 catch (AccessViolationException)
1584 { 1777 {
@@ -1593,6 +1786,12 @@ namespace OpenSim.Region.Physics.OdePlugin
1593 //} 1786 //}
1594 } 1787 }
1595 1788
1789 if (CollectStats)
1790 {
1791 m_tempAvatarCollisionsThisFrame = _perloopContact.Count;
1792 m_stats[ODEAvatarContactsStatsName] += m_tempAvatarCollisionsThisFrame;
1793 }
1794
1596 List<OdePrim> removeprims = null; 1795 List<OdePrim> removeprims = null;
1597 foreach (OdePrim chr in _activeprims) 1796 foreach (OdePrim chr in _activeprims)
1598 { 1797 {
@@ -1604,7 +1803,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1604 { 1803 {
1605 if (space != IntPtr.Zero && chr.prim_geom != IntPtr.Zero && chr.m_taintremove == false) 1804 if (space != IntPtr.Zero && chr.prim_geom != IntPtr.Zero && chr.m_taintremove == false)
1606 { 1805 {
1607 d.SpaceCollide2(space, chr.prim_geom, IntPtr.Zero, nearCallback); 1806 CollideSpaces(space, chr.prim_geom, IntPtr.Zero);
1608 } 1807 }
1609 else 1808 else
1610 { 1809 {
@@ -1625,6 +1824,9 @@ namespace OpenSim.Region.Physics.OdePlugin
1625 } 1824 }
1626 } 1825 }
1627 1826
1827 if (CollectStats)
1828 m_stats[ODEPrimContactsStatName] += _perloopContact.Count - m_tempAvatarCollisionsThisFrame;
1829
1628 if (removeprims != null) 1830 if (removeprims != null)
1629 { 1831 {
1630 foreach (OdePrim chr in removeprims) 1832 foreach (OdePrim chr in removeprims)
@@ -1706,8 +1908,8 @@ namespace OpenSim.Region.Physics.OdePlugin
1706 { 1908 {
1707// m_log.DebugFormat("[PHYSICS]: Adding {0} {1} to collision event reporting", obj.SOPName, obj.LocalID); 1909// m_log.DebugFormat("[PHYSICS]: Adding {0} {1} to collision event reporting", obj.SOPName, obj.LocalID);
1708 1910
1709 lock (_collisionEventPrimChanges) 1911 lock (m_collisionEventActorsChanges)
1710 _collisionEventPrimChanges[obj.LocalID] = obj; 1912 m_collisionEventActorsChanges[obj.LocalID] = obj;
1711 } 1913 }
1712 1914
1713 /// <summary> 1915 /// <summary>
@@ -1718,8 +1920,8 @@ namespace OpenSim.Region.Physics.OdePlugin
1718 { 1920 {
1719// m_log.DebugFormat("[PHYSICS]: Removing {0} {1} from collision event reporting", obj.SOPName, obj.LocalID); 1921// m_log.DebugFormat("[PHYSICS]: Removing {0} {1} from collision event reporting", obj.SOPName, obj.LocalID);
1720 1922
1721 lock (_collisionEventPrimChanges) 1923 lock (m_collisionEventActorsChanges)
1722 _collisionEventPrimChanges[obj.LocalID] = null; 1924 m_collisionEventActorsChanges[obj.LocalID] = null;
1723 } 1925 }
1724 1926
1725 #region Add/Remove Entities 1927 #region Add/Remove Entities
@@ -2226,7 +2428,8 @@ namespace OpenSim.Region.Physics.OdePlugin
2226 /// <param name="prim"></param> 2428 /// <param name="prim"></param>
2227 internal void RemovePrimThreadLocked(OdePrim prim) 2429 internal void RemovePrimThreadLocked(OdePrim prim)
2228 { 2430 {
2229//Console.WriteLine("RemovePrimThreadLocked " + prim.m_primName); 2431// m_log.DebugFormat("[ODE SCENE]: Removing physical prim {0} {1}", prim.Name, prim.LocalID);
2432
2230 lock (prim) 2433 lock (prim)
2231 { 2434 {
2232 RemoveCollisionEventReporting(prim); 2435 RemoveCollisionEventReporting(prim);
@@ -2682,21 +2885,23 @@ namespace OpenSim.Region.Physics.OdePlugin
2682 2885
2683 /// <summary> 2886 /// <summary>
2684 /// This is our main simulate loop 2887 /// This is our main simulate loop
2888 /// </summary>
2889 /// <remarks>
2685 /// It's thread locked by a Mutex in the scene. 2890 /// It's thread locked by a Mutex in the scene.
2686 /// It holds Collisions, it instructs ODE to step through the physical reactions 2891 /// It holds Collisions, it instructs ODE to step through the physical reactions
2687 /// It moves the objects around in memory 2892 /// It moves the objects around in memory
2688 /// It calls the methods that report back to the object owners.. (scenepresence, SceneObjectGroup) 2893 /// It calls the methods that report back to the object owners.. (scenepresence, SceneObjectGroup)
2689 /// </summary> 2894 /// </remarks>
2690 /// <param name="timeStep"></param> 2895 /// <param name="timeStep"></param>
2691 /// <returns></returns> 2896 /// <returns>The number of frames simulated over that period.</returns>
2692 public override float Simulate(float timeStep) 2897 public override float Simulate(float timeStep)
2693 { 2898 {
2899 int startFrameTick = CollectStats ? Util.EnvironmentTickCount() : 0;
2900 int tempTick = 0, tempTick2 = 0;
2901
2694 if (framecount >= int.MaxValue) 2902 if (framecount >= int.MaxValue)
2695 framecount = 0; 2903 framecount = 0;
2696 2904
2697 //if (m_worldOffset != Vector3.Zero)
2698 // return 0;
2699
2700 framecount++; 2905 framecount++;
2701 2906
2702 float fps = 0; 2907 float fps = 0;
@@ -2704,7 +2909,7 @@ namespace OpenSim.Region.Physics.OdePlugin
2704 float timeLeft = timeStep; 2909 float timeLeft = timeStep;
2705 2910
2706 //m_log.Info(timeStep.ToString()); 2911 //m_log.Info(timeStep.ToString());
2707// step_time += timeStep; 2912// step_time += timeSte
2708// 2913//
2709// // If We're loaded down by something else, 2914// // If We're loaded down by something else,
2710// // or debugging with the Visual Studio project on pause 2915// // or debugging with the Visual Studio project on pause
@@ -2725,17 +2930,17 @@ namespace OpenSim.Region.Physics.OdePlugin
2725 // We change _collisionEventPrimChanges to avoid locking _collisionEventPrim itself and causing potential 2930 // We change _collisionEventPrimChanges to avoid locking _collisionEventPrim itself and causing potential
2726 // deadlock if the collision event tries to lock something else later on which is already locked by a 2931 // deadlock if the collision event tries to lock something else later on which is already locked by a
2727 // caller that is adding or removing the collision event. 2932 // caller that is adding or removing the collision event.
2728 lock (_collisionEventPrimChanges) 2933 lock (m_collisionEventActorsChanges)
2729 { 2934 {
2730 foreach (KeyValuePair<uint, PhysicsActor> kvp in _collisionEventPrimChanges) 2935 foreach (KeyValuePair<uint, PhysicsActor> kvp in m_collisionEventActorsChanges)
2731 { 2936 {
2732 if (kvp.Value == null) 2937 if (kvp.Value == null)
2733 _collisionEventPrim.Remove(kvp.Key); 2938 m_collisionEventActors.Remove(kvp.Key);
2734 else 2939 else
2735 _collisionEventPrim[kvp.Key] = kvp.Value; 2940 m_collisionEventActors[kvp.Key] = kvp.Value;
2736 } 2941 }
2737 2942
2738 _collisionEventPrimChanges.Clear(); 2943 m_collisionEventActorsChanges.Clear();
2739 } 2944 }
2740 2945
2741 if (SupportsNINJAJoints) 2946 if (SupportsNINJAJoints)
@@ -2770,6 +2975,9 @@ namespace OpenSim.Region.Physics.OdePlugin
2770 { 2975 {
2771 try 2976 try
2772 { 2977 {
2978 if (CollectStats)
2979 tempTick = Util.EnvironmentTickCount();
2980
2773 lock (_taintedActors) 2981 lock (_taintedActors)
2774 { 2982 {
2775 foreach (OdeCharacter character in _taintedActors) 2983 foreach (OdeCharacter character in _taintedActors)
@@ -2778,6 +2986,13 @@ namespace OpenSim.Region.Physics.OdePlugin
2778 _taintedActors.Clear(); 2986 _taintedActors.Clear();
2779 } 2987 }
2780 2988
2989 if (CollectStats)
2990 {
2991 tempTick2 = Util.EnvironmentTickCount();
2992 m_stats[ODEAvatarTaintMsStatName] += Util.EnvironmentTickCountSubtract(tempTick2, tempTick);
2993 tempTick = tempTick2;
2994 }
2995
2781 lock (_taintedPrims) 2996 lock (_taintedPrims)
2782 { 2997 {
2783 foreach (OdePrim prim in _taintedPrims) 2998 foreach (OdePrim prim in _taintedPrims)
@@ -2808,6 +3023,13 @@ namespace OpenSim.Region.Physics.OdePlugin
2808 _taintedPrims.Clear(); 3023 _taintedPrims.Clear();
2809 } 3024 }
2810 3025
3026 if (CollectStats)
3027 {
3028 tempTick2 = Util.EnvironmentTickCount();
3029 m_stats[ODEPrimTaintMsStatName] += Util.EnvironmentTickCountSubtract(tempTick2, tempTick);
3030 tempTick = tempTick2;
3031 }
3032
2811 // Move characters 3033 // Move characters
2812 foreach (OdeCharacter actor in _characters) 3034 foreach (OdeCharacter actor in _characters)
2813 actor.Move(defects); 3035 actor.Move(defects);
@@ -2827,6 +3049,13 @@ namespace OpenSim.Region.Physics.OdePlugin
2827 defects.Clear(); 3049 defects.Clear();
2828 } 3050 }
2829 3051
3052 if (CollectStats)
3053 {
3054 tempTick2 = Util.EnvironmentTickCount();
3055 m_stats[ODEAvatarForcesFrameMsStatName] += Util.EnvironmentTickCountSubtract(tempTick2, tempTick);
3056 tempTick = tempTick2;
3057 }
3058
2830 // Move other active objects 3059 // Move other active objects
2831 foreach (OdePrim prim in _activeprims) 3060 foreach (OdePrim prim in _activeprims)
2832 { 3061 {
@@ -2834,15 +3063,36 @@ namespace OpenSim.Region.Physics.OdePlugin
2834 prim.Move(timeStep); 3063 prim.Move(timeStep);
2835 } 3064 }
2836 3065
3066 if (CollectStats)
3067 {
3068 tempTick2 = Util.EnvironmentTickCount();
3069 m_stats[ODEPrimForcesFrameMsStatName] += Util.EnvironmentTickCountSubtract(tempTick2, tempTick);
3070 tempTick = tempTick2;
3071 }
3072
2837 //if ((framecount % m_randomizeWater) == 0) 3073 //if ((framecount % m_randomizeWater) == 0)
2838 // randomizeWater(waterlevel); 3074 // randomizeWater(waterlevel);
2839 3075
2840 //int RayCastTimeMS = m_rayCastManager.ProcessQueuedRequests(); 3076 //int RayCastTimeMS = m_rayCastManager.ProcessQueuedRequests();
2841 m_rayCastManager.ProcessQueuedRequests(); 3077 m_rayCastManager.ProcessQueuedRequests();
2842 3078
3079 if (CollectStats)
3080 {
3081 tempTick2 = Util.EnvironmentTickCount();
3082 m_stats[ODERaycastingFrameMsStatName] += Util.EnvironmentTickCountSubtract(tempTick2, tempTick);
3083 tempTick = tempTick2;
3084 }
3085
2843 collision_optimized(); 3086 collision_optimized();
2844 3087
2845 foreach (PhysicsActor obj in _collisionEventPrim.Values) 3088 if (CollectStats)
3089 {
3090 tempTick2 = Util.EnvironmentTickCount();
3091 m_stats[ODEOtherCollisionFrameMsStatName] += Util.EnvironmentTickCountSubtract(tempTick2, tempTick);
3092 tempTick = tempTick2;
3093 }
3094
3095 foreach (PhysicsActor obj in m_collisionEventActors.Values)
2846 { 3096 {
2847// m_log.DebugFormat("[PHYSICS]: Assessing {0} {1} for collision events", obj.SOPName, obj.LocalID); 3097// m_log.DebugFormat("[PHYSICS]: Assessing {0} {1} for collision events", obj.SOPName, obj.LocalID);
2848 3098
@@ -2866,9 +3116,19 @@ namespace OpenSim.Region.Physics.OdePlugin
2866// "[PHYSICS]: Collision contacts to process this frame = {0}", m_global_contactcount); 3116// "[PHYSICS]: Collision contacts to process this frame = {0}", m_global_contactcount);
2867 3117
2868 m_global_contactcount = 0; 3118 m_global_contactcount = 0;
2869 3119
3120 if (CollectStats)
3121 {
3122 tempTick2 = Util.EnvironmentTickCount();
3123 m_stats[ODECollisionNotificationFrameMsStatName] += Util.EnvironmentTickCountSubtract(tempTick2, tempTick);
3124 tempTick = tempTick2;
3125 }
3126
2870 d.WorldQuickStep(world, ODE_STEPSIZE); 3127 d.WorldQuickStep(world, ODE_STEPSIZE);
2871 3128
3129 if (CollectStats)
3130 m_stats[ODENativeStepFrameMsStatName] += Util.EnvironmentTickCountSubtract(tempTick);
3131
2872 d.JointGroupEmpty(contactgroup); 3132 d.JointGroupEmpty(contactgroup);
2873 } 3133 }
2874 catch (Exception e) 3134 catch (Exception e)
@@ -2879,6 +3139,9 @@ namespace OpenSim.Region.Physics.OdePlugin
2879 timeLeft -= ODE_STEPSIZE; 3139 timeLeft -= ODE_STEPSIZE;
2880 } 3140 }
2881 3141
3142 if (CollectStats)
3143 tempTick = Util.EnvironmentTickCount();
3144
2882 foreach (OdeCharacter actor in _characters) 3145 foreach (OdeCharacter actor in _characters)
2883 { 3146 {
2884 if (actor.bad) 3147 if (actor.bad)
@@ -2902,6 +3165,13 @@ namespace OpenSim.Region.Physics.OdePlugin
2902 defects.Clear(); 3165 defects.Clear();
2903 } 3166 }
2904 3167
3168 if (CollectStats)
3169 {
3170 tempTick2 = Util.EnvironmentTickCount();
3171 m_stats[ODEAvatarUpdateFrameMsStatName] += Util.EnvironmentTickCountSubtract(tempTick2, tempTick);
3172 tempTick = tempTick2;
3173 }
3174
2905 //if (timeStep < 0.2f) 3175 //if (timeStep < 0.2f)
2906 3176
2907 foreach (OdePrim prim in _activeprims) 3177 foreach (OdePrim prim in _activeprims)
@@ -2915,6 +3185,9 @@ namespace OpenSim.Region.Physics.OdePlugin
2915 } 3185 }
2916 } 3186 }
2917 3187
3188 if (CollectStats)
3189 m_stats[ODEPrimUpdateFrameMsStatName] += Util.EnvironmentTickCountSubtract(tempTick);
3190
2918 //DumpJointInfo(); 3191 //DumpJointInfo();
2919 3192
2920 // Finished with all sim stepping. If requested, dump world state to file for debugging. 3193 // Finished with all sim stepping. If requested, dump world state to file for debugging.
@@ -2936,7 +3209,7 @@ namespace OpenSim.Region.Physics.OdePlugin
2936 d.WorldExportDIF(world, fname, physics_logging_append_existing_logfile, prefix); 3209 d.WorldExportDIF(world, fname, physics_logging_append_existing_logfile, prefix);
2937 } 3210 }
2938 3211
2939 latertickcount = Util.EnvironmentTickCount() - tickCountFrameRun; 3212 latertickcount = Util.EnvironmentTickCountSubtract(tickCountFrameRun);
2940 3213
2941 // OpenSimulator above does 10 fps. 10 fps = means that the main thread loop and physics 3214 // OpenSimulator above does 10 fps. 10 fps = means that the main thread loop and physics
2942 // has a max of 100 ms to run theoretically. 3215 // has a max of 100 ms to run theoretically.
@@ -2954,6 +3227,9 @@ namespace OpenSim.Region.Physics.OdePlugin
2954 } 3227 }
2955 3228
2956 tickCountFrameRun = Util.EnvironmentTickCount(); 3229 tickCountFrameRun = Util.EnvironmentTickCount();
3230
3231 if (CollectStats)
3232 m_stats[ODETotalFrameMsStatName] += Util.EnvironmentTickCountSubtract(startFrameTick);
2957 } 3233 }
2958 3234
2959 return fps; 3235 return fps;
@@ -3189,7 +3465,7 @@ namespace OpenSim.Region.Physics.OdePlugin
3189 public override bool IsThreaded 3465 public override bool IsThreaded
3190 { 3466 {
3191 // for now we won't be multithreaded 3467 // for now we won't be multithreaded
3192 get { return (false); } 3468 get { return false; }
3193 } 3469 }
3194 3470
3195 #region ODE Specific Terrain Fixes 3471 #region ODE Specific Terrain Fixes
@@ -3765,26 +4041,19 @@ namespace OpenSim.Region.Physics.OdePlugin
3765 4041
3766 public override Dictionary<uint, float> GetTopColliders() 4042 public override Dictionary<uint, float> GetTopColliders()
3767 { 4043 {
3768 Dictionary<uint, float> returncolliders = new Dictionary<uint, float>(); 4044 Dictionary<uint, float> topColliders;
3769 int cnt = 0; 4045
3770 lock (_prims) 4046 lock (_prims)
3771 { 4047 {
3772 foreach (OdePrim prm in _prims) 4048 List<OdePrim> orderedPrims = new List<OdePrim>(_prims);
3773 { 4049 orderedPrims.OrderByDescending(p => p.CollisionScore).Take(25);
3774 if (prm.CollisionScore > 0) 4050 topColliders = orderedPrims.ToDictionary(p => p.LocalID, p => p.CollisionScore);
3775 { 4051
3776 returncolliders.Add(prm.LocalID, prm.CollisionScore); 4052 foreach (OdePrim p in _prims)
3777 cnt++; 4053 p.CollisionScore = 0;
3778 prm.CollisionScore = 0f;
3779 if (cnt > 25)
3780 {
3781 break;
3782 }
3783 }
3784 }
3785 } 4054 }
3786 4055
3787 return returncolliders; 4056 return topColliders;
3788 } 4057 }
3789 4058
3790 public override bool SupportsRayCast() 4059 public override bool SupportsRayCast()
@@ -3954,5 +4223,52 @@ namespace OpenSim.Region.Physics.OdePlugin
3954 ds.SetViewpoint(ref xyz, ref hpr); 4223 ds.SetViewpoint(ref xyz, ref hpr);
3955 } 4224 }
3956#endif 4225#endif
4226
4227 public override Dictionary<string, float> GetStats()
4228 {
4229 if (!CollectStats)
4230 return null;
4231
4232 Dictionary<string, float> returnStats;
4233
4234 lock (OdeLock)
4235 {
4236 returnStats = new Dictionary<string, float>(m_stats);
4237
4238 // FIXME: This is a SUPER DUMB HACK until we can establish stats that aren't subject to a division by
4239 // 3 from the SimStatsReporter.
4240 returnStats[ODETotalAvatarsStatName] = _characters.Count * 3;
4241 returnStats[ODETotalPrimsStatName] = _prims.Count * 3;
4242 returnStats[ODEActivePrimsStatName] = _activeprims.Count * 3;
4243
4244 InitializeExtraStats();
4245 }
4246
4247 returnStats[ODEOtherCollisionFrameMsStatName]
4248 = returnStats[ODEOtherCollisionFrameMsStatName]
4249 - returnStats[ODENativeSpaceCollisionFrameMsStatName]
4250 - returnStats[ODENativeGeomCollisionFrameMsStatName];
4251
4252 return returnStats;
4253 }
4254
4255 private void InitializeExtraStats()
4256 {
4257 m_stats[ODETotalFrameMsStatName] = 0;
4258 m_stats[ODEAvatarTaintMsStatName] = 0;
4259 m_stats[ODEPrimTaintMsStatName] = 0;
4260 m_stats[ODEAvatarForcesFrameMsStatName] = 0;
4261 m_stats[ODEPrimForcesFrameMsStatName] = 0;
4262 m_stats[ODERaycastingFrameMsStatName] = 0;
4263 m_stats[ODENativeStepFrameMsStatName] = 0;
4264 m_stats[ODENativeSpaceCollisionFrameMsStatName] = 0;
4265 m_stats[ODENativeGeomCollisionFrameMsStatName] = 0;
4266 m_stats[ODEOtherCollisionFrameMsStatName] = 0;
4267 m_stats[ODECollisionNotificationFrameMsStatName] = 0;
4268 m_stats[ODEAvatarContactsStatsName] = 0;
4269 m_stats[ODEPrimContactsStatName] = 0;
4270 m_stats[ODEAvatarUpdateFrameMsStatName] = 0;
4271 m_stats[ODEPrimUpdateFrameMsStatName] = 0;
4272 }
3957 } 4273 }
3958} \ No newline at end of file 4274} \ No newline at end of file