aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/OdePlugin
diff options
context:
space:
mode:
authorTom2011-09-04 07:06:36 -0700
committerTom2011-09-04 07:06:36 -0700
commit66dec3b8742eff04fbbcc6e3249fe4ba87986500 (patch)
tree76cc708a821d35fac5cdbbce2de304b47064e732 /OpenSim/Region/Physics/OdePlugin
parentGuard another nullref (diff)
parentFixed BulletSim config files for Linux *.so libraries. (diff)
downloadopensim-SC_OLD-66dec3b8742eff04fbbcc6e3249fe4ba87986500.zip
opensim-SC_OLD-66dec3b8742eff04fbbcc6e3249fe4ba87986500.tar.gz
opensim-SC_OLD-66dec3b8742eff04fbbcc6e3249fe4ba87986500.tar.bz2
opensim-SC_OLD-66dec3b8742eff04fbbcc6e3249fe4ba87986500.tar.xz
Resolve merge commits, stage 1
Diffstat (limited to 'OpenSim/Region/Physics/OdePlugin')
-rw-r--r--OpenSim/Region/Physics/OdePlugin/ODECharacter.cs18
-rw-r--r--OpenSim/Region/Physics/OdePlugin/ODEPrim.cs303
-rw-r--r--OpenSim/Region/Physics/OdePlugin/ODERayCastRequestManager.cs92
-rw-r--r--OpenSim/Region/Physics/OdePlugin/OdeScene.cs834
-rw-r--r--OpenSim/Region/Physics/OdePlugin/Tests/ODETestClass.cs5
5 files changed, 683 insertions, 569 deletions
diff --git a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs
index 0e7dd81..c165a41 100644
--- a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs
+++ b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs
@@ -258,7 +258,11 @@ namespace OpenSim.Region.Physics.OdePlugin
258 public override bool Flying 258 public override bool Flying
259 { 259 {
260 get { return flying; } 260 get { return flying; }
261 set { flying = value; } 261 set
262 {
263 flying = value;
264// m_log.DebugFormat("[PHYSICS]: Set OdeCharacter Flying to {0}", flying);
265 }
262 } 266 }
263 267
264 /// <summary> 268 /// <summary>
@@ -305,10 +309,12 @@ namespace OpenSim.Region.Physics.OdePlugin
305 { 309 {
306 m_iscolliding = true; 310 m_iscolliding = true;
307 } 311 }
312
308 if (m_wascolliding != m_iscolliding) 313 if (m_wascolliding != m_iscolliding)
309 { 314 {
310 //base.SendCollisionUpdate(new CollisionEventUpdate()); 315 //base.SendCollisionUpdate(new CollisionEventUpdate());
311 } 316 }
317
312 m_wascolliding = m_iscolliding; 318 m_wascolliding = m_iscolliding;
313 } 319 }
314 } 320 }
@@ -1219,18 +1225,23 @@ namespace OpenSim.Region.Physics.OdePlugin
1219 { 1225 {
1220 m_requestedUpdateFrequency = ms; 1226 m_requestedUpdateFrequency = ms;
1221 m_eventsubscription = ms; 1227 m_eventsubscription = ms;
1222 _parent_scene.addCollisionEventReporting(this); 1228 _parent_scene.AddCollisionEventReporting(this);
1223 } 1229 }
1230
1224 public override void UnSubscribeEvents() 1231 public override void UnSubscribeEvents()
1225 { 1232 {
1226 _parent_scene.remCollisionEventReporting(this); 1233 _parent_scene.RemoveCollisionEventReporting(this);
1227 m_requestedUpdateFrequency = 0; 1234 m_requestedUpdateFrequency = 0;
1228 m_eventsubscription = 0; 1235 m_eventsubscription = 0;
1229 } 1236 }
1237
1230 public void AddCollisionEvent(uint CollidedWith, ContactPoint contact) 1238 public void AddCollisionEvent(uint CollidedWith, ContactPoint contact)
1231 { 1239 {
1232 if (m_eventsubscription > 0) 1240 if (m_eventsubscription > 0)
1233 { 1241 {
1242// m_log.DebugFormat(
1243// "[PHYSICS]: Adding collision event for {0}, collidedWith {1}, contact {2}", "", CollidedWith, contact);
1244
1234 CollisionEventsThisFrame.addCollider(CollidedWith, contact); 1245 CollisionEventsThisFrame.addCollider(CollidedWith, contact);
1235 } 1246 }
1236 } 1247 }
@@ -1247,6 +1258,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1247 m_eventsubscription = 0; 1258 m_eventsubscription = 0;
1248 } 1259 }
1249 } 1260 }
1261
1250 public override bool SubscribedEvents() 1262 public override bool SubscribedEvents()
1251 { 1263 {
1252 if (m_eventsubscription > 0) 1264 if (m_eventsubscription > 0)
diff --git a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
index 5fe0775..0a4fc51 100644
--- a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
+++ b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
@@ -61,6 +61,22 @@ namespace OpenSim.Region.Physics.OdePlugin
61 { 61 {
62 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 62 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
63 63
64 private bool m_isphysical;
65
66 /// <summary>
67 /// Is this prim subject to physics? Even if not, it's still solid for collision purposes.
68 /// </summary>
69 public override bool IsPhysical
70 {
71 get { return m_isphysical; }
72 set
73 {
74 m_isphysical = value;
75 if (!m_isphysical) // Zero the remembered last velocity
76 m_lastVelocity = Vector3.Zero;
77 }
78 }
79
64 private Vector3 _position; 80 private Vector3 _position;
65 private Vector3 _velocity; 81 private Vector3 _velocity;
66 private Vector3 _torque; 82 private Vector3 _torque;
@@ -138,12 +154,15 @@ namespace OpenSim.Region.Physics.OdePlugin
138 private List<Vector3> m_forcelist = new List<Vector3>(); 154 private List<Vector3> m_forcelist = new List<Vector3>();
139 private List<Vector3> m_angularforcelist = new List<Vector3>(); 155 private List<Vector3> m_angularforcelist = new List<Vector3>();
140 156
141 private IMesh _mesh;
142 private PrimitiveBaseShape _pbs; 157 private PrimitiveBaseShape _pbs;
143 private OdeScene _parent_scene; 158 private OdeScene _parent_scene;
159
160 /// <summary>
161 /// The physics space which contains prim geometries
162 /// </summary>
144 public IntPtr m_targetSpace = IntPtr.Zero; 163 public IntPtr m_targetSpace = IntPtr.Zero;
164
145 public IntPtr prim_geom; 165 public IntPtr prim_geom;
146 public IntPtr prev_geom;
147 public IntPtr _triMeshData; 166 public IntPtr _triMeshData;
148 167
149 private IntPtr _linkJointGroup = IntPtr.Zero; 168 private IntPtr _linkJointGroup = IntPtr.Zero;
@@ -153,7 +172,6 @@ namespace OpenSim.Region.Physics.OdePlugin
153 private List<OdePrim> childrenPrim = new List<OdePrim>(); 172 private List<OdePrim> childrenPrim = new List<OdePrim>();
154 173
155 private bool iscolliding; 174 private bool iscolliding;
156 private bool m_isphysical;
157 private bool m_isSelected; 175 private bool m_isSelected;
158 176
159 internal bool m_isVolumeDetect; // If true, this prim only detects collisions but doesn't collide actively 177 internal bool m_isVolumeDetect; // If true, this prim only detects collisions but doesn't collide actively
@@ -188,7 +206,7 @@ namespace OpenSim.Region.Physics.OdePlugin
188 internal int m_material = (int)Material.Wood; 206 internal int m_material = (int)Material.Wood;
189 207
190 public OdePrim(String primName, OdeScene parent_scene, Vector3 pos, Vector3 size, 208 public OdePrim(String primName, OdeScene parent_scene, Vector3 pos, Vector3 size,
191 Quaternion rotation, IMesh mesh, PrimitiveBaseShape pbs, bool pisPhysical, CollisionLocker dode) 209 Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical, CollisionLocker dode)
192 { 210 {
193 Name = primName; 211 Name = primName;
194 m_vehicle = new ODEDynamics(); 212 m_vehicle = new ODEDynamics();
@@ -208,9 +226,7 @@ namespace OpenSim.Region.Physics.OdePlugin
208 // m_tensor = parent_scene.bodyMotorJointMaxforceTensor; 226 // m_tensor = parent_scene.bodyMotorJointMaxforceTensor;
209 body_autodisable_frames = parent_scene.bodyFramesAutoDisable; 227 body_autodisable_frames = parent_scene.bodyFramesAutoDisable;
210 228
211
212 prim_geom = IntPtr.Zero; 229 prim_geom = IntPtr.Zero;
213 prev_geom = IntPtr.Zero;
214 230
215 if (!pos.IsFinite()) 231 if (!pos.IsFinite())
216 { 232 {
@@ -233,20 +249,21 @@ namespace OpenSim.Region.Physics.OdePlugin
233 249
234 _orientation = rotation; 250 _orientation = rotation;
235 m_taintrot = _orientation; 251 m_taintrot = _orientation;
236 _mesh = mesh;
237 _pbs = pbs; 252 _pbs = pbs;
238 253
239 _parent_scene = parent_scene; 254 _parent_scene = parent_scene;
240 m_targetSpace = (IntPtr)0; 255 m_targetSpace = (IntPtr)0;
241 256
242 if (pos.Z < 0) 257 if (pos.Z < 0)
243 m_isphysical = false; 258 {
259 IsPhysical = false;
260 }
244 else 261 else
245 { 262 {
246 m_isphysical = pisPhysical; 263 IsPhysical = pisPhysical;
247 // If we're physical, we need to be in the master space for now. 264 // If we're physical, we need to be in the master space for now.
248 // linksets *should* be in a space together.. but are not currently 265 // linksets *should* be in a space together.. but are not currently
249 if (m_isphysical) 266 if (IsPhysical)
250 m_targetSpace = _parent_scene.space; 267 m_targetSpace = _parent_scene.space;
251 } 268 }
252 269
@@ -289,7 +306,7 @@ namespace OpenSim.Region.Physics.OdePlugin
289 // through it while it's selected 306 // through it while it's selected
290 m_collisionscore = 0; 307 m_collisionscore = 0;
291 308
292 if ((m_isphysical && !_zeroFlag) || !value) 309 if ((IsPhysical && !_zeroFlag) || !value)
293 { 310 {
294 m_taintselected = value; 311 m_taintselected = value;
295 _parent_scene.AddPhysicsActorTaint(this); 312 _parent_scene.AddPhysicsActorTaint(this);
@@ -305,15 +322,21 @@ namespace OpenSim.Region.Physics.OdePlugin
305 } 322 }
306 } 323 }
307 324
325 /// <summary>
326 /// Set a new geometry for this prim.
327 /// </summary>
328 /// <param name="geom"></param>
308 public void SetGeom(IntPtr geom) 329 public void SetGeom(IntPtr geom)
309 { 330 {
310 prev_geom = prim_geom;
311 prim_geom = geom; 331 prim_geom = geom;
312//Console.WriteLine("SetGeom to " + prim_geom + " for " + Name); 332//Console.WriteLine("SetGeom to " + prim_geom + " for " + Name);
313 if (prim_geom != IntPtr.Zero) 333 if (prim_geom != IntPtr.Zero)
314 { 334 {
315 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); 335 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
316 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); 336 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
337
338 _parent_scene.geom_name_map[prim_geom] = Name;
339 _parent_scene.actor_name_map[prim_geom] = this;
317 } 340 }
318 341
319 if (childPrim) 342 if (childPrim)
@@ -332,7 +355,7 @@ namespace OpenSim.Region.Physics.OdePlugin
332 { 355 {
333 if (!childPrim) 356 if (!childPrim)
334 { 357 {
335 if (m_isphysical && Body != IntPtr.Zero) 358 if (IsPhysical && Body != IntPtr.Zero)
336 { 359 {
337 d.BodyEnable(Body); 360 d.BodyEnable(Body);
338 if (m_vehicle.Type != Vehicle.TYPE_NONE) 361 if (m_vehicle.Type != Vehicle.TYPE_NONE)
@@ -347,12 +370,15 @@ namespace OpenSim.Region.Physics.OdePlugin
347 { 370 {
348 m_disabled = true; 371 m_disabled = true;
349 372
350 if (m_isphysical && Body != IntPtr.Zero) 373 if (IsPhysical && Body != IntPtr.Zero)
351 { 374 {
352 d.BodyDisable(Body); 375 d.BodyDisable(Body);
353 } 376 }
354 } 377 }
355 378
379 /// <summary>
380 /// Make a prim subject to physics.
381 /// </summary>
356 public void enableBody() 382 public void enableBody()
357 { 383 {
358 // Don't enable this body if we're a child prim 384 // Don't enable this body if we're a child prim
@@ -638,7 +664,7 @@ namespace OpenSim.Region.Physics.OdePlugin
638 float profileEnd; 664 float profileEnd;
639 665
640 if (_pbs.PathCurve == (byte)Extrusion.Straight || _pbs.PathCurve == (byte)Extrusion.Flexible) 666 if (_pbs.PathCurve == (byte)Extrusion.Straight || _pbs.PathCurve == (byte)Extrusion.Flexible)
641 { 667 {
642 taperX1 = _pbs.PathScaleX * 0.01f; 668 taperX1 = _pbs.PathScaleX * 0.01f;
643 if (taperX1 > 1.0f) 669 if (taperX1 > 1.0f)
644 taperX1 = 2.0f - taperX1; 670 taperX1 = 2.0f - taperX1;
@@ -648,9 +674,9 @@ namespace OpenSim.Region.Physics.OdePlugin
648 if (taperY1 > 1.0f) 674 if (taperY1 > 1.0f)
649 taperY1 = 2.0f - taperY1; 675 taperY1 = 2.0f - taperY1;
650 taperY = 1.0f - taperY1; 676 taperY = 1.0f - taperY1;
651 } 677 }
652 else 678 else
653 { 679 {
654 taperX = _pbs.PathTaperX * 0.01f; 680 taperX = _pbs.PathTaperX * 0.01f;
655 if (taperX < 0.0f) 681 if (taperX < 0.0f)
656 taperX = -taperX; 682 taperX = -taperX;
@@ -660,9 +686,7 @@ namespace OpenSim.Region.Physics.OdePlugin
660 if (taperY < 0.0f) 686 if (taperY < 0.0f)
661 taperY = -taperY; 687 taperY = -taperY;
662 taperY1 = 1.0f - taperY; 688 taperY1 = 1.0f - taperY;
663 689 }
664 }
665
666 690
667 volume *= (taperX1 * taperY1 + 0.5f * (taperX1 * taperY + taperX * taperY1) + 0.3333333333f * taperX * taperY); 691 volume *= (taperX1 * taperY1 + 0.5f * (taperX1 * taperY + taperX * taperY1) + 0.3333333333f * taperX * taperY);
668 692
@@ -730,6 +754,9 @@ namespace OpenSim.Region.Physics.OdePlugin
730 } 754 }
731 } 755 }
732 756
757 /// <summary>
758 /// Stop a prim from being subject to physics.
759 /// </summary>
733 public void disableBody() 760 public void disableBody()
734 { 761 {
735 //this kills the body so things like 'mesh' can re-create it. 762 //this kills the body so things like 'mesh' can re-create it.
@@ -780,6 +807,7 @@ namespace OpenSim.Region.Physics.OdePlugin
780 Body = IntPtr.Zero; 807 Body = IntPtr.Zero;
781 } 808 }
782 } 809 }
810
783 m_disabled = true; 811 m_disabled = true;
784 m_collisionscore = 0; 812 m_collisionscore = 0;
785 } 813 }
@@ -846,7 +874,6 @@ namespace OpenSim.Region.Physics.OdePlugin
846 return; 874 return;
847 } 875 }
848 876
849
850 // if (IsPhysical && Body == (IntPtr) 0) 877 // if (IsPhysical && Body == (IntPtr) 0)
851 // { 878 // {
852 // Recreate the body 879 // Recreate the body
@@ -859,7 +886,9 @@ namespace OpenSim.Region.Physics.OdePlugin
859 886
860 public void ProcessTaints(float timestep) 887 public void ProcessTaints(float timestep)
861 { 888 {
862Console.WriteLine("ProcessTaints for " + Name); 889#if SPAM
890Console.WriteLine("ZProcessTaints for " + Name);
891#endif
863 if (m_taintadd) 892 if (m_taintadd)
864 { 893 {
865 changeadd(timestep); 894 changeadd(timestep);
@@ -887,7 +916,7 @@ Console.WriteLine("ProcessTaints for " + Name);
887 } 916 }
888 } 917 }
889 918
890 if (m_taintPhysics != m_isphysical && !(m_taintparent != _parent)) 919 if (m_taintPhysics != IsPhysical && !(m_taintparent != _parent))
891 changePhysicsStatus(timestep); 920 changePhysicsStatus(timestep);
892 921
893 if (!_size.ApproxEquals(m_taintsize, 0f)) 922 if (!_size.ApproxEquals(m_taintsize, 0f))
@@ -969,7 +998,7 @@ Console.WriteLine("ProcessTaints for " + Name);
969 OdePrim obj = (OdePrim)m_taintparent; 998 OdePrim obj = (OdePrim)m_taintparent;
970 //obj.disableBody(); 999 //obj.disableBody();
971//Console.WriteLine("changelink calls ParentPrim"); 1000//Console.WriteLine("changelink calls ParentPrim");
972 obj.ParentPrim(this); 1001 obj.AddChildPrim(this);
973 1002
974 /* 1003 /*
975 if (obj.Body != (IntPtr)0 && Body != (IntPtr)0 && obj.Body != Body) 1004 if (obj.Body != (IntPtr)0 && Body != (IntPtr)0 && obj.Body != Body)
@@ -1006,14 +1035,16 @@ Console.WriteLine("ProcessTaints for " + Name);
1006 } 1035 }
1007 1036
1008 _parent = m_taintparent; 1037 _parent = m_taintparent;
1009 m_taintPhysics = m_isphysical; 1038 m_taintPhysics = IsPhysical;
1010 } 1039 }
1011 1040
1012 // I'm the parent 1041 /// <summary>
1013 // prim is the child 1042 /// Add a child prim to this parent prim.
1014 public void ParentPrim(OdePrim prim) 1043 /// </summary>
1044 /// <param name="prim">Child prim</param>
1045 public void AddChildPrim(OdePrim prim)
1015 { 1046 {
1016//Console.WriteLine("ParentPrim " + Name); 1047//Console.WriteLine("AddChildPrim " + Name);
1017 if (this.m_localID != prim.m_localID) 1048 if (this.m_localID != prim.m_localID)
1018 { 1049 {
1019 if (Body == IntPtr.Zero) 1050 if (Body == IntPtr.Zero)
@@ -1036,7 +1067,6 @@ Console.WriteLine("ProcessTaints for " + Name);
1036 d.MassSetZero(out m2); 1067 d.MassSetZero(out m2);
1037 d.MassSetBoxTotal(out m2, prim.CalculateMass(), prm._size.X, prm._size.Y, prm._size.Z); 1068 d.MassSetBoxTotal(out m2, prim.CalculateMass(), prm._size.X, prm._size.Y, prm._size.Z);
1038 1069
1039
1040 d.Quaternion quat = new d.Quaternion(); 1070 d.Quaternion quat = new d.Quaternion();
1041 quat.W = prm._orientation.W; 1071 quat.W = prm._orientation.W;
1042 quat.X = prm._orientation.X; 1072 quat.X = prm._orientation.X;
@@ -1106,6 +1136,7 @@ Console.WriteLine("ProcessTaints for " + Name);
1106 prm.Body = Body; 1136 prm.Body = Body;
1107 _parent_scene.addActivePrim(prm); 1137 _parent_scene.addActivePrim(prm);
1108 } 1138 }
1139
1109 m_collisionCategories |= CollisionCategories.Body; 1140 m_collisionCategories |= CollisionCategories.Body;
1110 m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind); 1141 m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind);
1111 1142
@@ -1114,7 +1145,6 @@ Console.WriteLine("ProcessTaints for " + Name);
1114//Console.WriteLine(" Post GeomSetCategoryBits 2"); 1145//Console.WriteLine(" Post GeomSetCategoryBits 2");
1115 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); 1146 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
1116 1147
1117
1118 d.Quaternion quat2 = new d.Quaternion(); 1148 d.Quaternion quat2 = new d.Quaternion();
1119 quat2.W = _orientation.W; 1149 quat2.W = _orientation.W;
1120 quat2.X = _orientation.X; 1150 quat2.X = _orientation.X;
@@ -1136,7 +1166,6 @@ Console.WriteLine("ProcessTaints for " + Name);
1136 d.BodySetAutoDisableFlag(Body, true); 1166 d.BodySetAutoDisableFlag(Body, true);
1137 d.BodySetAutoDisableSteps(Body, body_autodisable_frames); 1167 d.BodySetAutoDisableSteps(Body, body_autodisable_frames);
1138 1168
1139
1140 m_interpenetrationcount = 0; 1169 m_interpenetrationcount = 0;
1141 m_collisionscore = 0; 1170 m_collisionscore = 0;
1142 m_disabled = false; 1171 m_disabled = false;
@@ -1147,7 +1176,9 @@ Console.WriteLine("ProcessTaints for " + Name);
1147 createAMotor(m_angularlock); 1176 createAMotor(m_angularlock);
1148 } 1177 }
1149 d.BodySetPosition(Body, Position.X, Position.Y, Position.Z); 1178 d.BodySetPosition(Body, Position.X, Position.Y, Position.Z);
1150 if (m_vehicle.Type != Vehicle.TYPE_NONE) m_vehicle.Enable(Body, _parent_scene); 1179 if (m_vehicle.Type != Vehicle.TYPE_NONE)
1180 m_vehicle.Enable(Body, _parent_scene);
1181
1151 _parent_scene.addActivePrim(this); 1182 _parent_scene.addActivePrim(this);
1152 } 1183 }
1153 } 1184 }
@@ -1157,7 +1188,7 @@ Console.WriteLine("ProcessTaints for " + Name);
1157 1188
1158 private void ChildSetGeom(OdePrim odePrim) 1189 private void ChildSetGeom(OdePrim odePrim)
1159 { 1190 {
1160 //if (m_isphysical && Body != IntPtr.Zero) 1191 //if (IsPhysical && Body != IntPtr.Zero)
1161 lock (childrenPrim) 1192 lock (childrenPrim)
1162 { 1193 {
1163 foreach (OdePrim prm in childrenPrim) 1194 foreach (OdePrim prm in childrenPrim)
@@ -1173,7 +1204,6 @@ Console.WriteLine("ProcessTaints for " + Name);
1173 } 1204 }
1174 disableBody(); 1205 disableBody();
1175 1206
1176
1177 if (Body != IntPtr.Zero) 1207 if (Body != IntPtr.Zero)
1178 { 1208 {
1179 _parent_scene.remActivePrim(this); 1209 _parent_scene.remActivePrim(this);
@@ -1184,10 +1214,9 @@ Console.WriteLine("ProcessTaints for " + Name);
1184 foreach (OdePrim prm in childrenPrim) 1214 foreach (OdePrim prm in childrenPrim)
1185 { 1215 {
1186//Console.WriteLine("ChildSetGeom calls ParentPrim"); 1216//Console.WriteLine("ChildSetGeom calls ParentPrim");
1187 ParentPrim(prm); 1217 AddChildPrim(prm);
1188 } 1218 }
1189 } 1219 }
1190
1191 } 1220 }
1192 1221
1193 private void ChildDelink(OdePrim odePrim) 1222 private void ChildDelink(OdePrim odePrim)
@@ -1224,7 +1253,7 @@ Console.WriteLine("ProcessTaints for " + Name);
1224 foreach (OdePrim prm in childrenPrim) 1253 foreach (OdePrim prm in childrenPrim)
1225 { 1254 {
1226//Console.WriteLine("ChildDelink calls ParentPrim"); 1255//Console.WriteLine("ChildDelink calls ParentPrim");
1227 ParentPrim(prm); 1256 AddChildPrim(prm);
1228 } 1257 }
1229 } 1258 }
1230 } 1259 }
@@ -1258,7 +1287,7 @@ Console.WriteLine("ProcessTaints for " + Name);
1258 // first 50 again. then the last 50 are disabled. then the first 50, which were just woken 1287 // first 50 again. then the last 50 are disabled. then the first 50, which were just woken
1259 // up, start simulating again, which in turn wakes up the last 50. 1288 // up, start simulating again, which in turn wakes up the last 50.
1260 1289
1261 if (m_isphysical) 1290 if (IsPhysical)
1262 { 1291 {
1263 disableBodySoft(); 1292 disableBodySoft();
1264 } 1293 }
@@ -1269,7 +1298,7 @@ Console.WriteLine("ProcessTaints for " + Name);
1269 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); 1298 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
1270 } 1299 }
1271 1300
1272 if (m_isphysical) 1301 if (IsPhysical)
1273 { 1302 {
1274 disableBodySoft(); 1303 disableBodySoft();
1275 } 1304 }
@@ -1278,7 +1307,7 @@ Console.WriteLine("ProcessTaints for " + Name);
1278 { 1307 {
1279 m_collisionCategories = CollisionCategories.Geom; 1308 m_collisionCategories = CollisionCategories.Geom;
1280 1309
1281 if (m_isphysical) 1310 if (IsPhysical)
1282 m_collisionCategories |= CollisionCategories.Body; 1311 m_collisionCategories |= CollisionCategories.Body;
1283 1312
1284 m_collisionFlags = m_default_collisionFlags; 1313 m_collisionFlags = m_default_collisionFlags;
@@ -1293,7 +1322,8 @@ Console.WriteLine("ProcessTaints for " + Name);
1293 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); 1322 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
1294 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); 1323 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
1295 } 1324 }
1296 if (m_isphysical) 1325
1326 if (IsPhysical)
1297 { 1327 {
1298 if (Body != IntPtr.Zero) 1328 if (Body != IntPtr.Zero)
1299 { 1329 {
@@ -1312,7 +1342,7 @@ Console.WriteLine("ProcessTaints for " + Name);
1312 { 1342 {
1313 m_taintposition = _position; 1343 m_taintposition = _position;
1314 m_taintrot = _orientation; 1344 m_taintrot = _orientation;
1315 m_taintPhysics = m_isphysical; 1345 m_taintPhysics = IsPhysical;
1316 m_taintselected = m_isSelected; 1346 m_taintselected = m_isSelected;
1317 m_taintsize = _size; 1347 m_taintsize = _size;
1318 m_taintshape = false; 1348 m_taintshape = false;
@@ -1321,12 +1351,19 @@ Console.WriteLine("ProcessTaints for " + Name);
1321 m_taintVelocity = Vector3.Zero; 1351 m_taintVelocity = Vector3.Zero;
1322 } 1352 }
1323 1353
1324 public void CreateGeom(IntPtr m_targetSpace, IMesh _mesh) 1354 /// <summary>
1355 /// Create a geometry for the given mesh in the given target space.
1356 /// </summary>
1357 /// <param name="m_targetSpace"></param>
1358 /// <param name="mesh">If null, then a mesh is used that is based on the profile shape data.</param>
1359 public void CreateGeom(IntPtr m_targetSpace, IMesh mesh)
1325 { 1360 {
1326//Console.WriteLine("CreateGeom:"); 1361#if SPAM
1327 if (_mesh != null) 1362Console.WriteLine("CreateGeom:");
1363#endif
1364 if (mesh != null)
1328 { 1365 {
1329 setMesh(_parent_scene, _mesh); 1366 setMesh(_parent_scene, mesh);
1330 } 1367 }
1331 else 1368 else
1332 { 1369 {
@@ -1399,6 +1436,39 @@ Console.WriteLine("ProcessTaints for " + Name);
1399 } 1436 }
1400 } 1437 }
1401 1438
1439 /// <summary>
1440 /// Remove the existing geom from this prim.
1441 /// </summary>
1442 /// <param name="m_targetSpace"></param>
1443 /// <param name="mesh">If null, then a mesh is used that is based on the profile shape data.</param>
1444 /// <returns>true if the geom was successfully removed, false if it was already gone or the remove failed.</returns>
1445 public bool RemoveGeom()
1446 {
1447 if (prim_geom != IntPtr.Zero)
1448 {
1449 try
1450 {
1451 _parent_scene.geom_name_map.Remove(prim_geom);
1452 _parent_scene.actor_name_map.Remove(prim_geom);
1453 d.GeomDestroy(prim_geom);
1454 prim_geom = IntPtr.Zero;
1455 }
1456 catch (System.AccessViolationException)
1457 {
1458 prim_geom = IntPtr.Zero;
1459 m_log.ErrorFormat("[PHYSICS]: PrimGeom dead for {0}", Name);
1460
1461 return false;
1462 }
1463
1464 return true;
1465 }
1466 else
1467 {
1468 return false;
1469 }
1470 }
1471
1402 public void changeadd(float timestep) 1472 public void changeadd(float timestep)
1403 { 1473 {
1404 int[] iprimspaceArrItem = _parent_scene.calculateSpaceArrayItemFromPos(_position); 1474 int[] iprimspaceArrItem = _parent_scene.calculateSpaceArrayItemFromPos(_position);
@@ -1409,15 +1479,14 @@ Console.WriteLine("ProcessTaints for " + Name);
1409 1479
1410 m_targetSpace = targetspace; 1480 m_targetSpace = targetspace;
1411 1481
1412 if (_mesh == null) 1482 IMesh mesh = null;
1483
1484 if (_parent_scene.needsMeshing(_pbs))
1413 { 1485 {
1414 if (_parent_scene.needsMeshing(_pbs)) 1486 // Don't need to re-enable body.. it's done in SetMesh
1415 { 1487 mesh = _parent_scene.mesher.CreateMesh(Name, _pbs, _size, _parent_scene.meshSculptLOD, IsPhysical);
1416 // Don't need to re-enable body.. it's done in SetMesh 1488 // createmesh returns null when it's a shape that isn't a cube.
1417 _mesh = _parent_scene.mesher.CreateMesh(Name, _pbs, _size, _parent_scene.meshSculptLOD, IsPhysical); 1489 // m_log.Debug(m_localID);
1418 // createmesh returns null when it's a shape that isn't a cube.
1419 // m_log.Debug(m_localID);
1420 }
1421 } 1490 }
1422 1491
1423 lock (_parent_scene.OdeLock) 1492 lock (_parent_scene.OdeLock)
@@ -1425,7 +1494,7 @@ Console.WriteLine("ProcessTaints for " + Name);
1425#if SPAM 1494#if SPAM
1426Console.WriteLine("changeadd 1"); 1495Console.WriteLine("changeadd 1");
1427#endif 1496#endif
1428 CreateGeom(m_targetSpace, _mesh); 1497 CreateGeom(m_targetSpace, mesh);
1429 1498
1430 if (prim_geom != IntPtr.Zero) 1499 if (prim_geom != IntPtr.Zero)
1431 { 1500 {
@@ -1438,15 +1507,12 @@ Console.WriteLine("changeadd 1");
1438 d.GeomSetQuaternion(prim_geom, ref myrot); 1507 d.GeomSetQuaternion(prim_geom, ref myrot);
1439 } 1508 }
1440 1509
1441 if (m_isphysical && Body == IntPtr.Zero) 1510 if (IsPhysical && Body == IntPtr.Zero)
1442 { 1511 {
1443 enableBody(); 1512 enableBody();
1444 } 1513 }
1445 } 1514 }
1446 1515
1447 _parent_scene.geom_name_map[prim_geom] = this.Name;
1448 _parent_scene.actor_name_map[prim_geom] = (PhysicsActor)this;
1449
1450 changeSelectedStatus(timestep); 1516 changeSelectedStatus(timestep);
1451 1517
1452 m_taintadd = false; 1518 m_taintadd = false;
@@ -1454,9 +1520,8 @@ Console.WriteLine("changeadd 1");
1454 1520
1455 public void changemove(float timestep) 1521 public void changemove(float timestep)
1456 { 1522 {
1457 if (m_isphysical) 1523 if (IsPhysical)
1458 { 1524 {
1459
1460 if (!m_disabled && !m_taintremove && !childPrim) 1525 if (!m_disabled && !m_taintremove && !childPrim)
1461 { 1526 {
1462 if (Body == IntPtr.Zero) 1527 if (Body == IntPtr.Zero)
@@ -1788,7 +1853,7 @@ Console.WriteLine(" JointCreateFixed");
1788 { 1853 {
1789 // KF: If this is a root prim do BodySet 1854 // KF: If this is a root prim do BodySet
1790 d.BodySetQuaternion(Body, ref myrot); 1855 d.BodySetQuaternion(Body, ref myrot);
1791 if (m_isphysical) 1856 if (IsPhysical)
1792 { 1857 {
1793 if (!m_angularlock.ApproxEquals(Vector3.One, 0f)) 1858 if (!m_angularlock.ApproxEquals(Vector3.One, 0f))
1794 createAMotor(m_angularlock); 1859 createAMotor(m_angularlock);
@@ -1825,7 +1890,7 @@ Console.WriteLine(" JointCreateFixed");
1825 1890
1826 public void changePhysicsStatus(float timestep) 1891 public void changePhysicsStatus(float timestep)
1827 { 1892 {
1828 if (m_isphysical == true) 1893 if (IsPhysical)
1829 { 1894 {
1830 if (Body == IntPtr.Zero) 1895 if (Body == IntPtr.Zero)
1831 { 1896 {
@@ -1845,25 +1910,12 @@ Console.WriteLine(" JointCreateFixed");
1845 { 1910 {
1846 if (_pbs.SculptEntry && _parent_scene.meshSculptedPrim) 1911 if (_pbs.SculptEntry && _parent_scene.meshSculptedPrim)
1847 { 1912 {
1848 1913 RemoveGeom();
1849 1914
1850 if (prim_geom != IntPtr.Zero)
1851 {
1852 try
1853 {
1854 d.GeomDestroy(prim_geom);
1855 prim_geom = IntPtr.Zero;
1856 _mesh = null;
1857 }
1858 catch (System.AccessViolationException)
1859 {
1860 prim_geom = IntPtr.Zero;
1861 m_log.ErrorFormat("[PHYSICS]: PrimGeom dead for {0}", Name);
1862 }
1863 }
1864//Console.WriteLine("changePhysicsStatus for " + Name); 1915//Console.WriteLine("changePhysicsStatus for " + Name);
1865 changeadd(2f); 1916 changeadd(2f);
1866 } 1917 }
1918
1867 if (childPrim) 1919 if (childPrim)
1868 { 1920 {
1869 if (_parent != null) 1921 if (_parent != null)
@@ -1882,7 +1934,7 @@ Console.WriteLine(" JointCreateFixed");
1882 changeSelectedStatus(timestep); 1934 changeSelectedStatus(timestep);
1883 1935
1884 resetCollisionAccounting(); 1936 resetCollisionAccounting();
1885 m_taintPhysics = m_isphysical; 1937 m_taintPhysics = IsPhysical;
1886 } 1938 }
1887 1939
1888 public void changesize(float timestamp) 1940 public void changesize(float timestamp)
@@ -1891,18 +1943,10 @@ Console.WriteLine(" JointCreateFixed");
1891 m_log.DebugFormat("[ODE PRIM]: Called changesize"); 1943 m_log.DebugFormat("[ODE PRIM]: Called changesize");
1892#endif 1944#endif
1893 1945
1894 string oldname = _parent_scene.geom_name_map[prim_geom];
1895
1896 if (_size.X <= 0) _size.X = 0.01f; 1946 if (_size.X <= 0) _size.X = 0.01f;
1897 if (_size.Y <= 0) _size.Y = 0.01f; 1947 if (_size.Y <= 0) _size.Y = 0.01f;
1898 if (_size.Z <= 0) _size.Z = 0.01f; 1948 if (_size.Z <= 0) _size.Z = 0.01f;
1899 1949
1900 // Cleanup of old prim geometry
1901 if (_mesh != null)
1902 {
1903 // TODO: Cleanup meshing here
1904 }
1905
1906 //kill body to rebuild 1950 //kill body to rebuild
1907 if (IsPhysical && Body != IntPtr.Zero) 1951 if (IsPhysical && Body != IntPtr.Zero)
1908 { 1952 {
@@ -1926,10 +1970,12 @@ Console.WriteLine(" JointCreateFixed");
1926 d.SpaceRemove(m_targetSpace, prim_geom); 1970 d.SpaceRemove(m_targetSpace, prim_geom);
1927 } 1971 }
1928 1972
1929 d.GeomDestroy(prim_geom); 1973 RemoveGeom();
1930 prim_geom = IntPtr.Zero; 1974
1931 // we don't need to do space calculation because the client sends a position update also. 1975 // we don't need to do space calculation because the client sends a position update also.
1932 1976
1977 IMesh mesh = null;
1978
1933 // Construction of new prim 1979 // Construction of new prim
1934 if (_parent_scene.needsMeshing(_pbs)) 1980 if (_parent_scene.needsMeshing(_pbs))
1935 { 1981 {
@@ -1939,28 +1985,11 @@ Console.WriteLine(" JointCreateFixed");
1939 meshlod = _parent_scene.MeshSculptphysicalLOD; 1985 meshlod = _parent_scene.MeshSculptphysicalLOD;
1940 // Don't need to re-enable body.. it's done in SetMesh 1986 // Don't need to re-enable body.. it's done in SetMesh
1941 1987
1942 IMesh mesh = null;
1943
1944 if (_parent_scene.needsMeshing(_pbs)) 1988 if (_parent_scene.needsMeshing(_pbs))
1945 mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size, meshlod, IsPhysical); 1989 mesh = _parent_scene.mesher.CreateMesh(Name, _pbs, _size, meshlod, IsPhysical);
1946
1947 //IMesh mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size, meshlod, IsPhysical);
1948#if SPAM
1949Console.WriteLine("changesize 1");
1950#endif
1951 CreateGeom(m_targetSpace, mesh);
1952 }
1953 else
1954 {
1955 _mesh = null;
1956
1957#if SPAM
1958Console.WriteLine("changesize 2");
1959#endif
1960
1961 CreateGeom(m_targetSpace, _mesh);
1962 } 1990 }
1963 1991
1992 CreateGeom(m_targetSpace, mesh);
1964 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z); 1993 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
1965 d.Quaternion myrot = new d.Quaternion(); 1994 d.Quaternion myrot = new d.Quaternion();
1966 myrot.X = _orientation.X; 1995 myrot.X = _orientation.X;
@@ -1978,8 +2007,6 @@ Console.WriteLine("changesize 2");
1978 d.BodyEnable(Body); 2007 d.BodyEnable(Body);
1979 } 2008 }
1980 2009
1981 _parent_scene.geom_name_map[prim_geom] = oldname;
1982
1983 changeSelectedStatus(timestamp); 2010 changeSelectedStatus(timestamp);
1984 if (childPrim) 2011 if (childPrim)
1985 { 2012 {
@@ -2013,8 +2040,6 @@ Console.WriteLine("changesize 2");
2013 2040
2014 public void changeshape(float timestamp) 2041 public void changeshape(float timestamp)
2015 { 2042 {
2016 string oldname = _parent_scene.geom_name_map[prim_geom];
2017
2018 // Cleanup of old prim geometry and Bodies 2043 // Cleanup of old prim geometry and Bodies
2019 if (IsPhysical && Body != IntPtr.Zero) 2044 if (IsPhysical && Body != IntPtr.Zero)
2020 { 2045 {
@@ -2031,23 +2056,17 @@ Console.WriteLine("changesize 2");
2031 disableBody(); 2056 disableBody();
2032 } 2057 }
2033 } 2058 }
2034 try
2035 {
2036 d.GeomDestroy(prim_geom);
2037 }
2038 catch (System.AccessViolationException)
2039 {
2040 prim_geom = IntPtr.Zero;
2041 m_log.ErrorFormat("[PHYSICS]: PrimGeom dead for {0}", Name);
2042 }
2043 2059
2044 prim_geom = IntPtr.Zero; 2060 RemoveGeom();
2061
2045 // we don't need to do space calculation because the client sends a position update also. 2062 // we don't need to do space calculation because the client sends a position update also.
2046 if (_size.X <= 0) _size.X = 0.01f; 2063 if (_size.X <= 0) _size.X = 0.01f;
2047 if (_size.Y <= 0) _size.Y = 0.01f; 2064 if (_size.Y <= 0) _size.Y = 0.01f;
2048 if (_size.Z <= 0) _size.Z = 0.01f; 2065 if (_size.Z <= 0) _size.Z = 0.01f;
2049 // Construction of new prim 2066 // Construction of new prim
2050 2067
2068 IMesh mesh = null;
2069
2051 if (_parent_scene.needsMeshing(_pbs)) 2070 if (_parent_scene.needsMeshing(_pbs))
2052 { 2071 {
2053 // Don't need to re-enable body.. it's done in CreateMesh 2072 // Don't need to re-enable body.. it's done in CreateMesh
@@ -2056,23 +2075,11 @@ Console.WriteLine("changesize 2");
2056 if (IsPhysical) 2075 if (IsPhysical)
2057 meshlod = _parent_scene.MeshSculptphysicalLOD; 2076 meshlod = _parent_scene.MeshSculptphysicalLOD;
2058 2077
2059 IMesh mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size, meshlod, IsPhysical);
2060 // createmesh returns null when it doesn't mesh. 2078 // createmesh returns null when it doesn't mesh.
2061#if SPAM 2079 mesh = _parent_scene.mesher.CreateMesh(Name, _pbs, _size, meshlod, IsPhysical);
2062Console.WriteLine("changeshape needed meshing");
2063#endif
2064 CreateGeom(m_targetSpace, mesh);
2065 }
2066 else
2067 {
2068 _mesh = null;
2069
2070#if SPAM
2071Console.WriteLine("changeshape not need meshing");
2072#endif
2073 CreateGeom(m_targetSpace, null);
2074 } 2080 }
2075 2081
2082 CreateGeom(m_targetSpace, mesh);
2076 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z); 2083 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
2077 d.Quaternion myrot = new d.Quaternion(); 2084 d.Quaternion myrot = new d.Quaternion();
2078 //myrot.W = _orientation.w; 2085 //myrot.W = _orientation.w;
@@ -2093,7 +2100,6 @@ Console.WriteLine("changeshape not need meshing");
2093 d.BodyEnable(Body); 2100 d.BodyEnable(Body);
2094 } 2101 }
2095 } 2102 }
2096 _parent_scene.geom_name_map[prim_geom] = oldname;
2097 2103
2098 changeSelectedStatus(timestamp); 2104 changeSelectedStatus(timestamp);
2099 if (childPrim) 2105 if (childPrim)
@@ -2104,6 +2110,7 @@ Console.WriteLine("changeshape not need meshing");
2104 parent.ChildSetGeom(this); 2110 parent.ChildSetGeom(this);
2105 } 2111 }
2106 } 2112 }
2113
2107 resetCollisionAccounting(); 2114 resetCollisionAccounting();
2108 m_taintshape = false; 2115 m_taintshape = false;
2109 } 2116 }
@@ -2215,16 +2222,6 @@ Console.WriteLine("changeshape not need meshing");
2215 m_taintVelocity = Vector3.Zero; 2222 m_taintVelocity = Vector3.Zero;
2216 } 2223 }
2217 2224
2218 public override bool IsPhysical
2219 {
2220 get { return m_isphysical; }
2221 set {
2222 m_isphysical = value;
2223 if (!m_isphysical) // Zero the remembered last velocity
2224 m_lastVelocity = Vector3.Zero;
2225 }
2226 }
2227
2228 public void setPrimForRemoval() 2225 public void setPrimForRemoval()
2229 { 2226 {
2230 m_taintremove = true; 2227 m_taintremove = true;
@@ -2283,6 +2280,7 @@ Console.WriteLine("changeshape not need meshing");
2283 if (value.IsFinite()) 2280 if (value.IsFinite())
2284 { 2281 {
2285 _size = value; 2282 _size = value;
2283// m_log.DebugFormat("[PHYSICS]: Set size on {0} to {1}", Name, value);
2286 } 2284 }
2287 else 2285 else
2288 { 2286 {
@@ -2343,7 +2341,7 @@ Console.WriteLine("changeshape not need meshing");
2343 { 2341 {
2344 lock (_parent_scene.OdeLock) 2342 lock (_parent_scene.OdeLock)
2345 { 2343 {
2346 m_isVolumeDetect = (param!=0); 2344 m_isVolumeDetect = (param != 0);
2347 } 2345 }
2348 } 2346 }
2349 2347
@@ -2402,7 +2400,7 @@ Console.WriteLine("changeshape not need meshing");
2402 { 2400 {
2403 get 2401 get
2404 { 2402 {
2405 if (!m_isphysical || Body == IntPtr.Zero) 2403 if (!IsPhysical || Body == IntPtr.Zero)
2406 return Vector3.Zero; 2404 return Vector3.Zero;
2407 2405
2408 return _torque; 2406 return _torque;
@@ -2984,12 +2982,12 @@ Console.WriteLine("changeshape not need meshing");
2984 public override void SubscribeEvents(int ms) 2982 public override void SubscribeEvents(int ms)
2985 { 2983 {
2986 m_eventsubscription = ms; 2984 m_eventsubscription = ms;
2987 _parent_scene.addCollisionEventReporting(this); 2985 _parent_scene.AddCollisionEventReporting(this);
2988 } 2986 }
2989 2987
2990 public override void UnSubscribeEvents() 2988 public override void UnSubscribeEvents()
2991 { 2989 {
2992 _parent_scene.remCollisionEventReporting(this); 2990 _parent_scene.RemoveCollisionEventReporting(this);
2993 m_eventsubscription = 0; 2991 m_eventsubscription = 0;
2994 } 2992 }
2995 2993
@@ -2997,6 +2995,7 @@ Console.WriteLine("changeshape not need meshing");
2997 { 2995 {
2998 if (CollisionEventsThisFrame == null) 2996 if (CollisionEventsThisFrame == null)
2999 CollisionEventsThisFrame = new CollisionEventUpdate(); 2997 CollisionEventsThisFrame = new CollisionEventUpdate();
2998
3000 CollisionEventsThisFrame.addCollider(CollidedWith, contact); 2999 CollisionEventsThisFrame.addCollider(CollidedWith, contact);
3001 } 3000 }
3002 3001
diff --git a/OpenSim/Region/Physics/OdePlugin/ODERayCastRequestManager.cs b/OpenSim/Region/Physics/OdePlugin/ODERayCastRequestManager.cs
index 15ccddc..9d7aa94 100644
--- a/OpenSim/Region/Physics/OdePlugin/ODERayCastRequestManager.cs
+++ b/OpenSim/Region/Physics/OdePlugin/ODERayCastRequestManager.cs
@@ -45,11 +45,16 @@ namespace OpenSim.Region.Physics.OdePlugin
45 public class ODERayCastRequestManager 45 public class ODERayCastRequestManager
46 { 46 {
47 /// <summary> 47 /// <summary>
48 /// Pending Raycast Requests 48 /// Pending raycast requests
49 /// </summary> 49 /// </summary>
50 protected List<ODERayCastRequest> m_PendingRequests = new List<ODERayCastRequest>(); 50 protected List<ODERayCastRequest> m_PendingRequests = new List<ODERayCastRequest>();
51 51
52 /// <summary> 52 /// <summary>
53 /// Pending ray requests
54 /// </summary>
55 protected List<ODERayRequest> m_PendingRayRequests = new List<ODERayRequest>();
56
57 /// <summary>
53 /// Scene that created this object. 58 /// Scene that created this object.
54 /// </summary> 59 /// </summary>
55 private OdeScene m_scene; 60 private OdeScene m_scene;
@@ -96,6 +101,29 @@ namespace OpenSim.Region.Physics.OdePlugin
96 } 101 }
97 102
98 /// <summary> 103 /// <summary>
104 /// Queues a raycast
105 /// </summary>
106 /// <param name="position">Origin of Ray</param>
107 /// <param name="direction">Ray normal</param>
108 /// <param name="length">Ray length</param>
109 /// <param name="count"></param>
110 /// <param name="retMethod">Return method to send the results</param>
111 public void QueueRequest(Vector3 position, Vector3 direction, float length, int count, RayCallback retMethod)
112 {
113 lock (m_PendingRequests)
114 {
115 ODERayRequest req = new ODERayRequest();
116 req.callbackMethod = retMethod;
117 req.length = length;
118 req.Normal = direction;
119 req.Origin = position;
120 req.Count = count;
121
122 m_PendingRayRequests.Add(req);
123 }
124 }
125
126 /// <summary>
99 /// Process all queued raycast requests 127 /// Process all queued raycast requests
100 /// </summary> 128 /// </summary>
101 /// <returns>Time in MS the raycasts took to process.</returns> 129 /// <returns>Time in MS the raycasts took to process.</returns>
@@ -119,15 +147,23 @@ namespace OpenSim.Region.Physics.OdePlugin
119 //Fail silently 147 //Fail silently
120 } 148 }
121 } 149 }
122 /* 150
123 foreach (ODERayCastRequest req in m_PendingRequests) 151 m_PendingRequests.Clear();
152 }
153 }
154
155 lock (m_PendingRayRequests)
156 {
157 if (m_PendingRayRequests.Count > 0)
158 {
159 ODERayRequest[] reqs = m_PendingRayRequests.ToArray();
160 for (int i = 0; i < reqs.Length; i++)
124 { 161 {
125 if (req.callbackMethod != null) // quick optimization here, don't raycast 162 if (reqs[i].callbackMethod != null) // quick optimization here, don't raycast
126 RayCast(req); // if there isn't anyone to send results to 163 RayCast(reqs[i]); // if there isn't anyone to send results
127
128 } 164 }
129 */ 165
130 m_PendingRequests.Clear(); 166 m_PendingRayRequests.Clear();
131 } 167 }
132 } 168 }
133 169
@@ -153,7 +189,6 @@ namespace OpenSim.Region.Physics.OdePlugin
153 // Remove Ray 189 // Remove Ray
154 d.GeomDestroy(ray); 190 d.GeomDestroy(ray);
155 191
156
157 // Define default results 192 // Define default results
158 bool hitYN = false; 193 bool hitYN = false;
159 uint hitConsumerID = 0; 194 uint hitConsumerID = 0;
@@ -184,6 +219,31 @@ namespace OpenSim.Region.Physics.OdePlugin
184 req.callbackMethod(hitYN, closestcontact, hitConsumerID, distance, snormal); 219 req.callbackMethod(hitYN, closestcontact, hitConsumerID, distance, snormal);
185 } 220 }
186 221
222 /// <summary>
223 /// Method that actually initiates the raycast
224 /// </summary>
225 /// <param name="req"></param>
226 private void RayCast(ODERayRequest req)
227 {
228 // Create the ray
229 IntPtr ray = d.CreateRay(m_scene.space, req.length);
230 d.GeomRaySet(ray, req.Origin.X, req.Origin.Y, req.Origin.Z, req.Normal.X, req.Normal.Y, req.Normal.Z);
231
232 // Collide test
233 d.SpaceCollide2(m_scene.space, ray, IntPtr.Zero, nearCallback);
234
235 // Remove Ray
236 d.GeomDestroy(ray);
237
238 // Find closest contact and object.
239 lock (m_contactResults)
240 {
241 // Return results
242 if (req.callbackMethod != null)
243 req.callbackMethod(m_contactResults);
244 }
245 }
246
187 // This is the standard Near. Uses space AABBs to speed up detection. 247 // This is the standard Near. Uses space AABBs to speed up detection.
188 private void near(IntPtr space, IntPtr g1, IntPtr g2) 248 private void near(IntPtr space, IntPtr g1, IntPtr g2)
189 { 249 {
@@ -349,10 +409,7 @@ namespace OpenSim.Region.Physics.OdePlugin
349 m_contactResults.Add(collisionresult); 409 m_contactResults.Add(collisionresult);
350 } 410 }
351 } 411 }
352
353
354 } 412 }
355
356 } 413 }
357 414
358 /// <summary> 415 /// <summary>
@@ -372,11 +429,12 @@ namespace OpenSim.Region.Physics.OdePlugin
372 public RaycastCallback callbackMethod; 429 public RaycastCallback callbackMethod;
373 } 430 }
374 431
375 public struct ContactResult 432 public struct ODERayRequest
376 { 433 {
377 public Vector3 Pos; 434 public Vector3 Origin;
378 public float Depth;
379 public uint ConsumerID;
380 public Vector3 Normal; 435 public Vector3 Normal;
436 public int Count;
437 public float length;
438 public RayCallback callbackMethod;
381 } 439 }
382} 440} \ No newline at end of file
diff --git a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs
index 88902b0..6e603e8 100644
--- a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs
+++ b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs
@@ -26,7 +26,7 @@
26 */ 26 */
27 27
28//#define USE_DRAWSTUFF 28//#define USE_DRAWSTUFF
29#define SPAM 29//#define SPAM
30 30
31using System; 31using System;
32using System.Collections.Generic; 32using System.Collections.Generic;
@@ -100,7 +100,7 @@ namespace OpenSim.Region.Physics.OdePlugin
100 Rubber = 6 100 Rubber = 6
101 } 101 }
102 102
103 public sealed class OdeScene : PhysicsScene 103 public class OdeScene : PhysicsScene
104 { 104 {
105 private readonly ILog m_log; 105 private readonly ILog m_log;
106 // private Dictionary<string, sCollisionData> m_storedCollisions = new Dictionary<string, sCollisionData>(); 106 // private Dictionary<string, sCollisionData> m_storedCollisions = new Dictionary<string, sCollisionData>();
@@ -198,7 +198,12 @@ namespace OpenSim.Region.Physics.OdePlugin
198 private readonly List<OdePrim> _taintedPrimL = new List<OdePrim>(); 198 private readonly List<OdePrim> _taintedPrimL = new List<OdePrim>();
199 private readonly HashSet<OdeCharacter> _taintedActors = new HashSet<OdeCharacter>(); 199 private readonly HashSet<OdeCharacter> _taintedActors = new HashSet<OdeCharacter>();
200 private readonly List<d.ContactGeom> _perloopContact = new List<d.ContactGeom>(); 200 private readonly List<d.ContactGeom> _perloopContact = new List<d.ContactGeom>();
201
202 /// <summary>
203 /// A list of actors that should receive collision events.
204 /// </summary>
201 private readonly List<PhysicsActor> _collisionEventPrim = new List<PhysicsActor>(); 205 private readonly List<PhysicsActor> _collisionEventPrim = new List<PhysicsActor>();
206
202 private readonly HashSet<OdeCharacter> _badCharacter = new HashSet<OdeCharacter>(); 207 private readonly HashSet<OdeCharacter> _badCharacter = new HashSet<OdeCharacter>();
203 public Dictionary<IntPtr, String> geom_name_map = new Dictionary<IntPtr, String>(); 208 public Dictionary<IntPtr, String> geom_name_map = new Dictionary<IntPtr, String>();
204 public Dictionary<IntPtr, PhysicsActor> actor_name_map = new Dictionary<IntPtr, PhysicsActor>(); 209 public Dictionary<IntPtr, PhysicsActor> actor_name_map = new Dictionary<IntPtr, PhysicsActor>();
@@ -299,7 +304,6 @@ namespace OpenSim.Region.Physics.OdePlugin
299 // Create the world and the first space 304 // Create the world and the first space
300 world = d.WorldCreate(); 305 world = d.WorldCreate();
301 space = d.HashSpaceCreate(IntPtr.Zero); 306 space = d.HashSpaceCreate(IntPtr.Zero);
302
303 307
304 contactgroup = d.JointGroupCreate(0); 308 contactgroup = d.JointGroupCreate(0);
305 //contactgroup 309 //contactgroup
@@ -952,7 +956,6 @@ namespace OpenSim.Region.Physics.OdePlugin
952 character.SetPidStatus(true); 956 character.SetPidStatus(true);
953 } 957 }
954 } 958 }
955
956 959
957 if (p1.PhysicsActorType == (int) ActorTypes.Agent) 960 if (p1.PhysicsActorType == (int) ActorTypes.Agent)
958 { 961 {
@@ -1053,9 +1056,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1053 { 1056 {
1054 joint = d.JointCreateContact(world, contactgroup, ref m_materialContacts[material, movintYN]); 1057 joint = d.JointCreateContact(world, contactgroup, ref m_materialContacts[material, movintYN]);
1055 m_global_contactcount++; 1058 m_global_contactcount++;
1056
1057 } 1059 }
1058
1059 } 1060 }
1060 else 1061 else
1061 { 1062 {
@@ -1078,7 +1079,6 @@ namespace OpenSim.Region.Physics.OdePlugin
1078 { 1079 {
1079 joint = d.JointCreateContact(world, contactgroup, ref m_materialContacts[material, movintYN]); 1080 joint = d.JointCreateContact(world, contactgroup, ref m_materialContacts[material, movintYN]);
1080 m_global_contactcount++; 1081 m_global_contactcount++;
1081
1082 } 1082 }
1083 } 1083 }
1084 } 1084 }
@@ -1290,6 +1290,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1290 1290
1291 //returncollisions = true; 1291 //returncollisions = true;
1292 break; 1292 break;
1293
1293 case ActorTypes.Prim: 1294 case ActorTypes.Prim:
1294 if (p1 is OdePrim) 1295 if (p1 is OdePrim)
1295 { 1296 {
@@ -1317,6 +1318,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1317 1318
1318 cc2.AddCollisionEvent(obj2LocalID, contact); 1319 cc2.AddCollisionEvent(obj2LocalID, contact);
1319 break; 1320 break;
1321
1320 case ActorTypes.Prim: 1322 case ActorTypes.Prim:
1321 1323
1322 if (p2 is OdePrim) 1324 if (p2 is OdePrim)
@@ -1421,18 +1423,18 @@ namespace OpenSim.Region.Physics.OdePlugin
1421 1423
1422 public int TriCallback(IntPtr trimesh, IntPtr refObject, int triangleIndex) 1424 public int TriCallback(IntPtr trimesh, IntPtr refObject, int triangleIndex)
1423 { 1425 {
1424 String name1 = null; 1426// String name1 = null;
1425 String name2 = null; 1427// String name2 = null;
1426 1428//
1427 if (!geom_name_map.TryGetValue(trimesh, out name1)) 1429// if (!geom_name_map.TryGetValue(trimesh, out name1))
1428 { 1430// {
1429 name1 = "null"; 1431// name1 = "null";
1430 } 1432// }
1431 1433//
1432 if (!geom_name_map.TryGetValue(refObject, out name2)) 1434// if (!geom_name_map.TryGetValue(refObject, out name2))
1433 { 1435// {
1434 name2 = "null"; 1436// name2 = "null";
1435 } 1437// }
1436 1438
1437 // m_log.InfoFormat("TriCallback: A collision was detected between {1} and {2}. Index was {3}", 0, name1, name2, triangleIndex); 1439 // m_log.InfoFormat("TriCallback: A collision was detected between {1} and {2}. Index was {3}", 0, name1, name2, triangleIndex);
1438 1440
@@ -1604,7 +1606,11 @@ namespace OpenSim.Region.Physics.OdePlugin
1604 } 1606 }
1605// End recovered. Kitto Flora 1607// End recovered. Kitto Flora
1606 1608
1607 public void addCollisionEventReporting(PhysicsActor obj) 1609 /// <summary>
1610 /// Add actor to the list that should receive collision events in the simulate loop.
1611 /// </summary>
1612 /// <param name="obj"></param>
1613 public void AddCollisionEventReporting(PhysicsActor obj)
1608 { 1614 {
1609 lock (_collisionEventPrim) 1615 lock (_collisionEventPrim)
1610 { 1616 {
@@ -1613,7 +1619,11 @@ namespace OpenSim.Region.Physics.OdePlugin
1613 } 1619 }
1614 } 1620 }
1615 1621
1616 public void remCollisionEventReporting(PhysicsActor obj) 1622 /// <summary>
1623 /// Remove actor from the list that should receive collision events in the simulate loop.
1624 /// </summary>
1625 /// <param name="obj"></param>
1626 public void RemoveCollisionEventReporting(PhysicsActor obj)
1617 { 1627 {
1618 lock (_collisionEventPrim) 1628 lock (_collisionEventPrim)
1619 { 1629 {
@@ -1677,7 +1687,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1677 } 1687 }
1678 1688
1679 private PhysicsActor AddPrim(String name, Vector3 position, Vector3 size, Quaternion rotation, 1689 private PhysicsActor AddPrim(String name, Vector3 position, Vector3 size, Quaternion rotation,
1680 IMesh mesh, PrimitiveBaseShape pbs, bool isphysical) 1690 PrimitiveBaseShape pbs, bool isphysical, uint localID)
1681 { 1691 {
1682 Vector3 pos = position; 1692 Vector3 pos = position;
1683 Vector3 siz = size; 1693 Vector3 siz = size;
@@ -1686,12 +1696,12 @@ namespace OpenSim.Region.Physics.OdePlugin
1686 OdePrim newPrim; 1696 OdePrim newPrim;
1687 lock (OdeLock) 1697 lock (OdeLock)
1688 { 1698 {
1689 newPrim = new OdePrim(name, this, pos, siz, rot, mesh, pbs, isphysical, ode); 1699 newPrim = new OdePrim(name, this, pos, siz, rot, pbs, isphysical, ode);
1690 1700
1691 lock (_prims) 1701 lock (_prims)
1692 _prims.Add(newPrim); 1702 _prims.Add(newPrim);
1693 } 1703 }
1694 1704 newPrim.LocalID = localID;
1695 return newPrim; 1705 return newPrim;
1696 } 1706 }
1697 1707
@@ -1714,27 +1724,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1714 m_log.DebugFormat("[PHYSICS]: Adding physics actor to {0}", primName); 1724 m_log.DebugFormat("[PHYSICS]: Adding physics actor to {0}", primName);
1715#endif 1725#endif
1716 1726
1717 PhysicsActor result; 1727 return AddPrim(primName, position, size, rotation, pbs, isPhysical, localid);
1718 IMesh mesh = null;
1719
1720 if (needsMeshing(pbs))
1721 {
1722 try
1723 {
1724 mesh = mesher.CreateMesh(primName, pbs, size, 32f, isPhysical);
1725 }
1726 catch(Exception e)
1727 {
1728 m_log.ErrorFormat("[PHYSICS]: Exception while meshing prim {0}.", primName);
1729 m_log.Debug(e.ToString());
1730 mesh = null;
1731 return null;
1732 }
1733 }
1734
1735 result = AddPrim(primName, position, size, rotation, mesh, pbs, isPhysical);
1736
1737 return result;
1738 } 1728 }
1739 1729
1740 public override float TimeDilation 1730 public override float TimeDilation
@@ -2104,6 +2094,8 @@ namespace OpenSim.Region.Physics.OdePlugin
2104 2094
2105 public override void RemovePrim(PhysicsActor prim) 2095 public override void RemovePrim(PhysicsActor prim)
2106 { 2096 {
2097 // As with all ODE physics operations, we don't remove the prim immediately but signal that it should be
2098 // removed in the next physics simulate pass.
2107 if (prim is OdePrim) 2099 if (prim is OdePrim)
2108 { 2100 {
2109 lock (OdeLock) 2101 lock (OdeLock)
@@ -2120,6 +2112,9 @@ namespace OpenSim.Region.Physics.OdePlugin
2120 /// <summary> 2112 /// <summary>
2121 /// This is called from within simulate but outside the locked portion 2113 /// This is called from within simulate but outside the locked portion
2122 /// We need to do our own locking here 2114 /// We need to do our own locking here
2115 /// (Note: As of 20110801 this no longer appears to be true - this is being called within lock (odeLock) in
2116 /// Simulate() -- justincc).
2117 ///
2123 /// Essentially, we need to remove the prim from our space segment, whatever segment it's in. 2118 /// Essentially, we need to remove the prim from our space segment, whatever segment it's in.
2124 /// 2119 ///
2125 /// If there are no more prim in the segment, we need to empty (spacedestroy)the segment and reclaim memory 2120 /// If there are no more prim in the segment, we need to empty (spacedestroy)the segment and reclaim memory
@@ -2131,7 +2126,7 @@ namespace OpenSim.Region.Physics.OdePlugin
2131//Console.WriteLine("RemovePrimThreadLocked " + prim.m_primName); 2126//Console.WriteLine("RemovePrimThreadLocked " + prim.m_primName);
2132 lock (prim) 2127 lock (prim)
2133 { 2128 {
2134 remCollisionEventReporting(prim); 2129 RemoveCollisionEventReporting(prim);
2135 lock (ode) 2130 lock (ode)
2136 { 2131 {
2137 if (prim.prim_geom != IntPtr.Zero) 2132 if (prim.prim_geom != IntPtr.Zero)
@@ -2176,24 +2171,12 @@ namespace OpenSim.Region.Physics.OdePlugin
2176 //} 2171 //}
2177 //} 2172 //}
2178 //m_log.Warn(prim.prim_geom); 2173 //m_log.Warn(prim.prim_geom);
2179 try 2174
2180 { 2175 if (!prim.RemoveGeom())
2181 if (prim.prim_geom != IntPtr.Zero) 2176 m_log.Warn("[PHYSICS]: Unable to remove prim from physics scene");
2182 { 2177
2183 d.GeomDestroy(prim.prim_geom);
2184 prim.prim_geom = IntPtr.Zero;
2185 }
2186 else
2187 {
2188 m_log.Warn("[PHYSICS]: Unable to remove prim from physics scene");
2189 }
2190 }
2191 catch (AccessViolationException)
2192 {
2193 m_log.Info("[PHYSICS]: Couldn't remove prim from physics scene, it was already be removed.");
2194 }
2195 lock (_prims) 2178 lock (_prims)
2196 _prims.Remove(prim); 2179 _prims.Remove(prim);
2197 2180
2198 //If there are no more geometries in the sub-space, we don't need it in the main space anymore 2181 //If there are no more geometries in the sub-space, we don't need it in the main space anymore
2199 //if (d.SpaceGetNumGeoms(prim.m_targetSpace) == 0) 2182 //if (d.SpaceGetNumGeoms(prim.m_targetSpace) == 0)
@@ -2584,7 +2567,9 @@ namespace OpenSim.Region.Physics.OdePlugin
2584 { 2567 {
2585 if (!(_taintedPrimH.Contains(taintedprim))) 2568 if (!(_taintedPrimH.Contains(taintedprim)))
2586 { 2569 {
2587//Console.WriteLine("AddPhysicsActorTaint to " + taintedprim.m_primName); 2570#if SPAM
2571Console.WriteLine("AddPhysicsActorTaint to " + taintedprim.Name);
2572#endif
2588 _taintedPrimH.Add(taintedprim); // HashSet for searching 2573 _taintedPrimH.Add(taintedprim); // HashSet for searching
2589 _taintedPrimL.Add(taintedprim); // List for ordered readout 2574 _taintedPrimL.Add(taintedprim); // List for ordered readout
2590 } 2575 }
@@ -2684,320 +2669,148 @@ namespace OpenSim.Region.Physics.OdePlugin
2684 //if (!ode.lockquery()) 2669 //if (!ode.lockquery())
2685 //{ 2670 //{
2686 // ode.dlock(world); 2671 // ode.dlock(world);
2687 try
2688 {
2689 // Insert, remove Characters
2690 bool processedtaints = false;
2691 2672
2692 lock (_taintedActors) 2673 try
2693 { 2674 {
2694 if (_taintedActors.Count > 0) 2675 // Insert, remove Characters
2695 { 2676 bool processedtaints = false;
2696 foreach (OdeCharacter character in _taintedActors)
2697 {
2698 character.ProcessTaints(timeStep);
2699 2677
2700 processedtaints = true; 2678 lock (_taintedActors)
2701 //character.m_collisionscore = 0; 2679 {
2702 } 2680 if (_taintedActors.Count > 0)
2681 {
2682 foreach (OdeCharacter character in _taintedActors)
2683 {
2684 character.ProcessTaints(timeStep);
2703 2685
2704 if (processedtaints) 2686 processedtaints = true;
2705 _taintedActors.Clear(); 2687 //character.m_collisionscore = 0;
2706 }
2707 } 2688 }
2708 2689
2709 // Modify other objects in the scene. 2690 if (processedtaints)
2710 processedtaints = false; 2691 _taintedActors.Clear();
2692 }
2693 }
2694
2695 // Modify other objects in the scene.
2696 processedtaints = false;
2711 2697
2712 lock (_taintedPrimLock) 2698 lock (_taintedPrimLock)
2699 {
2700 foreach (OdePrim prim in _taintedPrimL)
2701 {
2702 if (prim.m_taintremove)
2713 { 2703 {
2714 foreach (OdePrim prim in _taintedPrimL) 2704// Console.WriteLine("Simulate calls RemovePrimThreadLocked for {0}", prim.Name);
2715 { 2705 RemovePrimThreadLocked(prim);
2716 if (prim.m_taintremove) 2706 }
2717 { 2707 else
2718 //Console.WriteLine("Simulate calls RemovePrimThreadLocked"); 2708 {
2719 RemovePrimThreadLocked(prim); 2709// Console.WriteLine("Simulate calls ProcessTaints for {0}", prim.Name);
2720 } 2710 prim.ProcessTaints(timeStep);
2721 else 2711 }
2722 {
2723 //Console.WriteLine("Simulate calls ProcessTaints");
2724 prim.ProcessTaints(timeStep);
2725 }
2726 processedtaints = true;
2727 prim.m_collisionscore = 0;
2728
2729 // This loop can block up the Heartbeat for a very long time on large regions.
2730 // We need to let the Watchdog know that the Heartbeat is not dead
2731 // NOTE: This is currently commented out, but if things like OAR loading are
2732 // timing the heartbeat out we will need to uncomment it
2733 //Watchdog.UpdateThread();
2734 }
2735 2712
2736 if (SupportsNINJAJoints) 2713 processedtaints = true;
2737 { 2714 prim.m_collisionscore = 0;
2738 // Create pending joints, if possible
2739 2715
2740 // joints can only be processed after ALL bodies are processed (and exist in ODE), since creating 2716 // This loop can block up the Heartbeat for a very long time on large regions.
2741 // a joint requires specifying the body id of both involved bodies 2717 // We need to let the Watchdog know that the Heartbeat is not dead
2742 if (pendingJoints.Count > 0) 2718 // NOTE: This is currently commented out, but if things like OAR loading are
2743 { 2719 // timing the heartbeat out we will need to uncomment it
2744 List<PhysicsJoint> successfullyProcessedPendingJoints = new List<PhysicsJoint>(); 2720 //Watchdog.UpdateThread();
2745 //DoJointErrorMessage(joints_connecting_actor, "taint: " + pendingJoints.Count + " pending joints"); 2721 }
2746 foreach (PhysicsJoint joint in pendingJoints) 2722
2747 { 2723 if (SupportsNINJAJoints)
2748 //DoJointErrorMessage(joint, "taint: time to create joint with parms: " + joint.RawParams); 2724 SimulatePendingNINJAJoints();
2749 string[] jointParams = joint.RawParams.Split(" ".ToCharArray(), System.StringSplitOptions.RemoveEmptyEntries);
2750 List<IntPtr> jointBodies = new List<IntPtr>();
2751 bool allJointBodiesAreReady = true;
2752 foreach (string jointParam in jointParams)
2753 {
2754 if (jointParam == "NULL")
2755 {
2756 //DoJointErrorMessage(joint, "attaching NULL joint to world");
2757 jointBodies.Add(IntPtr.Zero);
2758 }
2759 else
2760 {
2761 //DoJointErrorMessage(joint, "looking for prim name: " + jointParam);
2762 bool foundPrim = false;
2763 lock (_prims)
2764 {
2765 foreach (OdePrim prim in _prims) // FIXME: inefficient
2766 {
2767 if (prim.SOPName == jointParam)
2768 {
2769 //DoJointErrorMessage(joint, "found for prim name: " + jointParam);
2770 if (prim.IsPhysical && prim.Body != IntPtr.Zero)
2771 {
2772 jointBodies.Add(prim.Body);
2773 foundPrim = true;
2774 break;
2775 }
2776 else
2777 {
2778 DoJointErrorMessage(joint, "prim name " + jointParam +
2779 " exists but is not (yet) physical; deferring joint creation. " +
2780 "IsPhysical property is " + prim.IsPhysical +
2781 " and body is " + prim.Body);
2782 foundPrim = false;
2783 break;
2784 }
2785 }
2786 }
2787 }
2788 if (foundPrim)
2789 {
2790 // all is fine
2791 }
2792 else
2793 {
2794 allJointBodiesAreReady = false;
2795 break;
2796 }
2797 }
2798 }
2799 if (allJointBodiesAreReady)
2800 {
2801 //DoJointErrorMessage(joint, "allJointBodiesAreReady for " + joint.ObjectNameInScene + " with parms " + joint.RawParams);
2802 if (jointBodies[0] == jointBodies[1])
2803 {
2804 DoJointErrorMessage(joint, "ERROR: joint cannot be created; the joint bodies are the same, body1==body2. Raw body is " + jointBodies[0] + ". raw parms: " + joint.RawParams);
2805 }
2806 else
2807 {
2808 switch (joint.Type)
2809 {
2810 case PhysicsJointType.Ball:
2811 {
2812 IntPtr odeJoint;
2813 //DoJointErrorMessage(joint, "ODE creating ball joint ");
2814 odeJoint = d.JointCreateBall(world, IntPtr.Zero);
2815 //DoJointErrorMessage(joint, "ODE attaching ball joint: " + odeJoint + " with b1:" + jointBodies[0] + " b2:" + jointBodies[1]);
2816 d.JointAttach(odeJoint, jointBodies[0], jointBodies[1]);
2817 //DoJointErrorMessage(joint, "ODE setting ball anchor: " + odeJoint + " to vec:" + joint.Position);
2818 d.JointSetBallAnchor(odeJoint,
2819 joint.Position.X,
2820 joint.Position.Y,
2821 joint.Position.Z);
2822 //DoJointErrorMessage(joint, "ODE joint setting OK");
2823 //DoJointErrorMessage(joint, "The ball joint's bodies are here: b0: ");
2824 //DoJointErrorMessage(joint, "" + (jointBodies[0] != IntPtr.Zero ? "" + d.BodyGetPosition(jointBodies[0]) : "fixed environment"));
2825 //DoJointErrorMessage(joint, "The ball joint's bodies are here: b1: ");
2826 //DoJointErrorMessage(joint, "" + (jointBodies[1] != IntPtr.Zero ? "" + d.BodyGetPosition(jointBodies[1]) : "fixed environment"));
2827
2828 if (joint is OdePhysicsJoint)
2829 {
2830 ((OdePhysicsJoint)joint).jointID = odeJoint;
2831 }
2832 else
2833 {
2834 DoJointErrorMessage(joint, "WARNING: non-ode joint in ODE!");
2835 }
2836 }
2837 break;
2838 case PhysicsJointType.Hinge:
2839 {
2840 IntPtr odeJoint;
2841 //DoJointErrorMessage(joint, "ODE creating hinge joint ");
2842 odeJoint = d.JointCreateHinge(world, IntPtr.Zero);
2843 //DoJointErrorMessage(joint, "ODE attaching hinge joint: " + odeJoint + " with b1:" + jointBodies[0] + " b2:" + jointBodies[1]);
2844 d.JointAttach(odeJoint, jointBodies[0], jointBodies[1]);
2845 //DoJointErrorMessage(joint, "ODE setting hinge anchor: " + odeJoint + " to vec:" + joint.Position);
2846 d.JointSetHingeAnchor(odeJoint,
2847 joint.Position.X,
2848 joint.Position.Y,
2849 joint.Position.Z);
2850 // We use the orientation of the x-axis of the joint's coordinate frame
2851 // as the axis for the hinge.
2852
2853 // Therefore, we must get the joint's coordinate frame based on the
2854 // joint.Rotation field, which originates from the orientation of the
2855 // joint's proxy object in the scene.
2856
2857 // The joint's coordinate frame is defined as the transformation matrix
2858 // that converts a vector from joint-local coordinates into world coordinates.
2859 // World coordinates are defined as the XYZ coordinate system of the sim,
2860 // as shown in the top status-bar of the viewer.
2861
2862 // Once we have the joint's coordinate frame, we extract its X axis (AtAxis)
2863 // and use that as the hinge axis.
2864
2865 //joint.Rotation.Normalize();
2866 Matrix4 proxyFrame = Matrix4.CreateFromQuaternion(joint.Rotation);
2867
2868 // Now extract the X axis of the joint's coordinate frame.
2869
2870 // Do not try to use proxyFrame.AtAxis or you will become mired in the
2871 // tar pit of transposed, inverted, and generally messed-up orientations.
2872 // (In other words, Matrix4.AtAxis() is borked.)
2873 // Vector3 jointAxis = proxyFrame.AtAxis; <--- this path leadeth to madness
2874
2875 // Instead, compute the X axis of the coordinate frame by transforming
2876 // the (1,0,0) vector. At least that works.
2877
2878 //m_log.Debug("PHY: making axis: complete matrix is " + proxyFrame);
2879 Vector3 jointAxis = Vector3.Transform(Vector3.UnitX, proxyFrame);
2880 //m_log.Debug("PHY: making axis: hinge joint axis is " + jointAxis);
2881 //DoJointErrorMessage(joint, "ODE setting hinge axis: " + odeJoint + " to vec:" + jointAxis);
2882 d.JointSetHingeAxis(odeJoint,
2883 jointAxis.X,
2884 jointAxis.Y,
2885 jointAxis.Z);
2886 //d.JointSetHingeParam(odeJoint, (int)dParam.CFM, 0.1f);
2887 if (joint is OdePhysicsJoint)
2888 {
2889 ((OdePhysicsJoint)joint).jointID = odeJoint;
2890 }
2891 else
2892 {
2893 DoJointErrorMessage(joint, "WARNING: non-ode joint in ODE!");
2894 }
2895 }
2896 break;
2897 }
2898 successfullyProcessedPendingJoints.Add(joint);
2899 }
2900 }
2901 else
2902 {
2903 DoJointErrorMessage(joint, "joint could not yet be created; still pending");
2904 }
2905 }
2906 foreach (PhysicsJoint successfullyProcessedJoint in successfullyProcessedPendingJoints)
2907 {
2908 //DoJointErrorMessage(successfullyProcessedJoint, "finalizing succesfully procsssed joint " + successfullyProcessedJoint.ObjectNameInScene + " parms " + successfullyProcessedJoint.RawParams);
2909 //DoJointErrorMessage(successfullyProcessedJoint, "removing from pending");
2910 InternalRemovePendingJoint(successfullyProcessedJoint);
2911 //DoJointErrorMessage(successfullyProcessedJoint, "adding to active");
2912 InternalAddActiveJoint(successfullyProcessedJoint);
2913 //DoJointErrorMessage(successfullyProcessedJoint, "done");
2914 }
2915 }
2916 }
2917 2725
2918 if (processedtaints) 2726 if (processedtaints)
2727 {
2919//Console.WriteLine("Simulate calls Clear of _taintedPrim list"); 2728//Console.WriteLine("Simulate calls Clear of _taintedPrim list");
2920 _taintedPrimH.Clear(); 2729 _taintedPrimH.Clear();
2921 _taintedPrimL.Clear(); 2730 _taintedPrimL.Clear();
2922 } 2731 }
2732 }
2923 2733
2924 // Move characters 2734 // Move characters
2925 lock (_characters) 2735 lock (_characters)
2736 {
2737 List<OdeCharacter> defects = new List<OdeCharacter>();
2738 foreach (OdeCharacter actor in _characters)
2739 {
2740 if (actor != null)
2741 actor.Move(timeStep, defects);
2742 }
2743 if (0 != defects.Count)
2744 {
2745 foreach (OdeCharacter defect in defects)
2926 { 2746 {
2927 List<OdeCharacter> defects = new List<OdeCharacter>(); 2747 RemoveCharacter(defect);
2928 foreach (OdeCharacter actor in _characters)
2929 {
2930 if (actor != null)
2931 actor.Move(timeStep, defects);
2932 }
2933 if (0 != defects.Count)
2934 {
2935 foreach (OdeCharacter defect in defects)
2936 {
2937 RemoveCharacter(defect);
2938 }
2939 }
2940 } 2748 }
2749 }
2750 }
2941 2751
2942 // Move other active objects 2752 // Move other active objects
2943 lock (_activeprims) 2753 lock (_activeprims)
2944 { 2754 {
2945 foreach (OdePrim prim in _activeprims) 2755 foreach (OdePrim prim in _activeprims)
2946 { 2756 {
2947 prim.m_collisionscore = 0; 2757 prim.m_collisionscore = 0;
2948 prim.Move(timeStep); 2758 prim.Move(timeStep);
2949 } 2759 }
2950 } 2760 }
2951 2761
2952 //if ((framecount % m_randomizeWater) == 0) 2762 //if ((framecount % m_randomizeWater) == 0)
2953 // randomizeWater(waterlevel); 2763 // randomizeWater(waterlevel);
2954 2764
2955 //int RayCastTimeMS = m_rayCastManager.ProcessQueuedRequests(); 2765 //int RayCastTimeMS = m_rayCastManager.ProcessQueuedRequests();
2956 m_rayCastManager.ProcessQueuedRequests(); 2766 m_rayCastManager.ProcessQueuedRequests();
2767
2768 collision_optimized(timeStep);
2769
2770 lock (_collisionEventPrim)
2771 {
2772 foreach (PhysicsActor obj in _collisionEventPrim)
2773 {
2774 if (obj == null)
2775 continue;
2957 2776
2958 collision_optimized(timeStep); 2777// m_log.DebugFormat("[PHYSICS]: Assessing {0} for collision events", obj.SOPName);
2959 2778
2960 lock (_collisionEventPrim) 2779 switch ((ActorTypes)obj.PhysicsActorType)
2961 { 2780 {
2962 foreach (PhysicsActor obj in _collisionEventPrim) 2781 case ActorTypes.Agent:
2963 { 2782 OdeCharacter cobj = (OdeCharacter)obj;
2964 if (obj == null) 2783 cobj.AddCollisionFrameTime(100);
2965 continue; 2784 cobj.SendCollisions();
2785 break;
2966 2786
2967 switch ((ActorTypes)obj.PhysicsActorType) 2787 case ActorTypes.Prim:
2968 { 2788 OdePrim pobj = (OdePrim)obj;
2969 case ActorTypes.Agent: 2789 pobj.SendCollisions();
2970 OdeCharacter cobj = (OdeCharacter)obj; 2790 break;
2971 cobj.AddCollisionFrameTime(100);
2972 cobj.SendCollisions();
2973 break;
2974 case ActorTypes.Prim:
2975 OdePrim pobj = (OdePrim)obj;
2976 pobj.SendCollisions();
2977 break;
2978 }
2979 }
2980 } 2791 }
2792 }
2793 }
2981 2794
2982 //if (m_global_contactcount > 5) 2795 //if (m_global_contactcount > 5)
2983 //{ 2796 //{
2984 // m_log.DebugFormat("[PHYSICS]: Contacts:{0}", m_global_contactcount); 2797 // m_log.DebugFormat("[PHYSICS]: Contacts:{0}", m_global_contactcount);
2985 //} 2798 //}
2986 2799
2987 m_global_contactcount = 0; 2800 m_global_contactcount = 0;
2988 2801
2989 d.WorldQuickStep(world, ODE_STEPSIZE); 2802 d.WorldQuickStep(world, ODE_STEPSIZE);
2990 d.JointGroupEmpty(contactgroup); 2803 d.JointGroupEmpty(contactgroup);
2991 //ode.dunlock(world); 2804 //ode.dunlock(world);
2992 } 2805 }
2993 catch (Exception e) 2806 catch (Exception e)
2994 { 2807 {
2995 m_log.ErrorFormat("[PHYSICS]: {0}, {1}, {2}", e.Message, e.TargetSite, e); 2808 m_log.ErrorFormat("[PHYSICS]: {0}, {1}, {2}", e.Message, e.TargetSite, e);
2996 ode.dunlock(world); 2809 ode.dunlock(world);
2997 } 2810 }
2998 2811
2999 step_time -= ODE_STEPSIZE; 2812 step_time -= ODE_STEPSIZE;
3000 i++; 2813 i++;
3001 //} 2814 //}
3002 //else 2815 //else
3003 //{ 2816 //{
@@ -3014,6 +2827,7 @@ namespace OpenSim.Region.Physics.OdePlugin
3014 { 2827 {
3015 if (actor.bad) 2828 if (actor.bad)
3016 m_log.WarnFormat("[PHYSICS]: BAD Actor {0} in _characters list was not removed?", actor.m_uuid); 2829 m_log.WarnFormat("[PHYSICS]: BAD Actor {0} in _characters list was not removed?", actor.m_uuid);
2830
3017 actor.UpdatePositionAndVelocity(); 2831 actor.UpdatePositionAndVelocity();
3018 } 2832 }
3019 } 2833 }
@@ -3027,6 +2841,7 @@ namespace OpenSim.Region.Physics.OdePlugin
3027 { 2841 {
3028 RemoveCharacter(chr); 2842 RemoveCharacter(chr);
3029 } 2843 }
2844
3030 _badCharacter.Clear(); 2845 _badCharacter.Clear();
3031 } 2846 }
3032 } 2847 }
@@ -3042,30 +2857,7 @@ namespace OpenSim.Region.Physics.OdePlugin
3042 actor.UpdatePositionAndVelocity(); 2857 actor.UpdatePositionAndVelocity();
3043 2858
3044 if (SupportsNINJAJoints) 2859 if (SupportsNINJAJoints)
3045 { 2860 SimulateActorPendingJoints(actor);
3046 // If an actor moved, move its joint proxy objects as well.
3047 // There seems to be an event PhysicsActor.OnPositionUpdate that could be used
3048 // for this purpose but it is never called! So we just do the joint
3049 // movement code here.
3050
3051 if (actor.SOPName != null &&
3052 joints_connecting_actor.ContainsKey(actor.SOPName) &&
3053 joints_connecting_actor[actor.SOPName] != null &&
3054 joints_connecting_actor[actor.SOPName].Count > 0)
3055 {
3056 foreach (PhysicsJoint affectedJoint in joints_connecting_actor[actor.SOPName])
3057 {
3058 if (affectedJoint.IsInPhysicsEngine)
3059 {
3060 DoJointMoved(affectedJoint);
3061 }
3062 else
3063 {
3064 DoJointErrorMessage(affectedJoint, "a body connected to a joint was moved, but the joint doesn't exist yet! this will lead to joint error. joint was: " + affectedJoint.ObjectNameInScene + " parms:" + affectedJoint.RawParams);
3065 }
3066 }
3067 }
3068 }
3069 } 2861 }
3070 } 2862 }
3071 } 2863 }
@@ -3076,7 +2868,7 @@ namespace OpenSim.Region.Physics.OdePlugin
3076 // Finished with all sim stepping. If requested, dump world state to file for debugging. 2868 // Finished with all sim stepping. If requested, dump world state to file for debugging.
3077 // TODO: This call to the export function is already inside lock (OdeLock) - but is an extra lock needed? 2869 // TODO: This call to the export function is already inside lock (OdeLock) - but is an extra lock needed?
3078 // TODO: This overwrites all dump files in-place. Should this be a growing logfile, or separate snapshots? 2870 // TODO: This overwrites all dump files in-place. Should this be a growing logfile, or separate snapshots?
3079 if (physics_logging && (physics_logging_interval>0) && (framecount % physics_logging_interval == 0)) 2871 if (physics_logging && (physics_logging_interval > 0) && (framecount % physics_logging_interval == 0))
3080 { 2872 {
3081 string fname = "state-" + world.ToString() + ".DIF"; // give each physics world a separate filename 2873 string fname = "state-" + world.ToString() + ".DIF"; // give each physics world a separate filename
3082 string prefix = "world" + world.ToString(); // prefix for variable names in exported .DIF file 2874 string prefix = "world" + world.ToString(); // prefix for variable names in exported .DIF file
@@ -3088,8 +2880,10 @@ namespace OpenSim.Region.Physics.OdePlugin
3088 fwriter.WriteLine(header); 2880 fwriter.WriteLine(header);
3089 fwriter.Close(); 2881 fwriter.Close();
3090 } 2882 }
2883
3091 d.WorldExportDIF(world, fname, physics_logging_append_existing_logfile, prefix); 2884 d.WorldExportDIF(world, fname, physics_logging_append_existing_logfile, prefix);
3092 } 2885 }
2886
3093 latertickcount = Util.EnvironmentTickCount() - tickCountFrameRun; 2887 latertickcount = Util.EnvironmentTickCount() - tickCountFrameRun;
3094 2888
3095 // OpenSimulator above does 10 fps. 10 fps = means that the main thread loop and physics 2889 // OpenSimulator above does 10 fps. 10 fps = means that the main thread loop and physics
@@ -3098,7 +2892,9 @@ namespace OpenSim.Region.Physics.OdePlugin
3098 // If Physics stalls, it takes longer which makes the tick count ms larger. 2892 // If Physics stalls, it takes longer which makes the tick count ms larger.
3099 2893
3100 if (latertickcount < 100) 2894 if (latertickcount < 100)
2895 {
3101 m_timeDilation = 1.0f; 2896 m_timeDilation = 1.0f;
2897 }
3102 else 2898 else
3103 { 2899 {
3104 m_timeDilation = 100f / latertickcount; 2900 m_timeDilation = 100f / latertickcount;
@@ -3111,6 +2907,229 @@ namespace OpenSim.Region.Physics.OdePlugin
3111 return fps; 2907 return fps;
3112 } 2908 }
3113 2909
2910 /// <summary>
2911 /// Simulate pending NINJA joints.
2912 /// </summary>
2913 /// <remarks>
2914 /// Called by the main Simulate() loop if NINJA joints are active. Should not be called from anywhere else.
2915 /// </remarks>
2916 protected void SimulatePendingNINJAJoints()
2917 {
2918 // Create pending joints, if possible
2919
2920 // joints can only be processed after ALL bodies are processed (and exist in ODE), since creating
2921 // a joint requires specifying the body id of both involved bodies
2922 if (pendingJoints.Count > 0)
2923 {
2924 List<PhysicsJoint> successfullyProcessedPendingJoints = new List<PhysicsJoint>();
2925 //DoJointErrorMessage(joints_connecting_actor, "taint: " + pendingJoints.Count + " pending joints");
2926 foreach (PhysicsJoint joint in pendingJoints)
2927 {
2928 //DoJointErrorMessage(joint, "taint: time to create joint with parms: " + joint.RawParams);
2929 string[] jointParams = joint.RawParams.Split(" ".ToCharArray(), System.StringSplitOptions.RemoveEmptyEntries);
2930 List<IntPtr> jointBodies = new List<IntPtr>();
2931 bool allJointBodiesAreReady = true;
2932 foreach (string jointParam in jointParams)
2933 {
2934 if (jointParam == "NULL")
2935 {
2936 //DoJointErrorMessage(joint, "attaching NULL joint to world");
2937 jointBodies.Add(IntPtr.Zero);
2938 }
2939 else
2940 {
2941 //DoJointErrorMessage(joint, "looking for prim name: " + jointParam);
2942 bool foundPrim = false;
2943 lock (_prims)
2944 {
2945 foreach (OdePrim prim in _prims) // FIXME: inefficient
2946 {
2947 if (prim.SOPName == jointParam)
2948 {
2949 //DoJointErrorMessage(joint, "found for prim name: " + jointParam);
2950 if (prim.IsPhysical && prim.Body != IntPtr.Zero)
2951 {
2952 jointBodies.Add(prim.Body);
2953 foundPrim = true;
2954 break;
2955 }
2956 else
2957 {
2958 DoJointErrorMessage(joint, "prim name " + jointParam +
2959 " exists but is not (yet) physical; deferring joint creation. " +
2960 "IsPhysical property is " + prim.IsPhysical +
2961 " and body is " + prim.Body);
2962 foundPrim = false;
2963 break;
2964 }
2965 }
2966 }
2967 }
2968 if (foundPrim)
2969 {
2970 // all is fine
2971 }
2972 else
2973 {
2974 allJointBodiesAreReady = false;
2975 break;
2976 }
2977 }
2978 }
2979
2980 if (allJointBodiesAreReady)
2981 {
2982 //DoJointErrorMessage(joint, "allJointBodiesAreReady for " + joint.ObjectNameInScene + " with parms " + joint.RawParams);
2983 if (jointBodies[0] == jointBodies[1])
2984 {
2985 DoJointErrorMessage(joint, "ERROR: joint cannot be created; the joint bodies are the same, body1==body2. Raw body is " + jointBodies[0] + ". raw parms: " + joint.RawParams);
2986 }
2987 else
2988 {
2989 switch (joint.Type)
2990 {
2991 case PhysicsJointType.Ball:
2992 {
2993 IntPtr odeJoint;
2994 //DoJointErrorMessage(joint, "ODE creating ball joint ");
2995 odeJoint = d.JointCreateBall(world, IntPtr.Zero);
2996 //DoJointErrorMessage(joint, "ODE attaching ball joint: " + odeJoint + " with b1:" + jointBodies[0] + " b2:" + jointBodies[1]);
2997 d.JointAttach(odeJoint, jointBodies[0], jointBodies[1]);
2998 //DoJointErrorMessage(joint, "ODE setting ball anchor: " + odeJoint + " to vec:" + joint.Position);
2999 d.JointSetBallAnchor(odeJoint,
3000 joint.Position.X,
3001 joint.Position.Y,
3002 joint.Position.Z);
3003 //DoJointErrorMessage(joint, "ODE joint setting OK");
3004 //DoJointErrorMessage(joint, "The ball joint's bodies are here: b0: ");
3005 //DoJointErrorMessage(joint, "" + (jointBodies[0] != IntPtr.Zero ? "" + d.BodyGetPosition(jointBodies[0]) : "fixed environment"));
3006 //DoJointErrorMessage(joint, "The ball joint's bodies are here: b1: ");
3007 //DoJointErrorMessage(joint, "" + (jointBodies[1] != IntPtr.Zero ? "" + d.BodyGetPosition(jointBodies[1]) : "fixed environment"));
3008
3009 if (joint is OdePhysicsJoint)
3010 {
3011 ((OdePhysicsJoint)joint).jointID = odeJoint;
3012 }
3013 else
3014 {
3015 DoJointErrorMessage(joint, "WARNING: non-ode joint in ODE!");
3016 }
3017 }
3018 break;
3019 case PhysicsJointType.Hinge:
3020 {
3021 IntPtr odeJoint;
3022 //DoJointErrorMessage(joint, "ODE creating hinge joint ");
3023 odeJoint = d.JointCreateHinge(world, IntPtr.Zero);
3024 //DoJointErrorMessage(joint, "ODE attaching hinge joint: " + odeJoint + " with b1:" + jointBodies[0] + " b2:" + jointBodies[1]);
3025 d.JointAttach(odeJoint, jointBodies[0], jointBodies[1]);
3026 //DoJointErrorMessage(joint, "ODE setting hinge anchor: " + odeJoint + " to vec:" + joint.Position);
3027 d.JointSetHingeAnchor(odeJoint,
3028 joint.Position.X,
3029 joint.Position.Y,
3030 joint.Position.Z);
3031 // We use the orientation of the x-axis of the joint's coordinate frame
3032 // as the axis for the hinge.
3033
3034 // Therefore, we must get the joint's coordinate frame based on the
3035 // joint.Rotation field, which originates from the orientation of the
3036 // joint's proxy object in the scene.
3037
3038 // The joint's coordinate frame is defined as the transformation matrix
3039 // that converts a vector from joint-local coordinates into world coordinates.
3040 // World coordinates are defined as the XYZ coordinate system of the sim,
3041 // as shown in the top status-bar of the viewer.
3042
3043 // Once we have the joint's coordinate frame, we extract its X axis (AtAxis)
3044 // and use that as the hinge axis.
3045
3046 //joint.Rotation.Normalize();
3047 Matrix4 proxyFrame = Matrix4.CreateFromQuaternion(joint.Rotation);
3048
3049 // Now extract the X axis of the joint's coordinate frame.
3050
3051 // Do not try to use proxyFrame.AtAxis or you will become mired in the
3052 // tar pit of transposed, inverted, and generally messed-up orientations.
3053 // (In other words, Matrix4.AtAxis() is borked.)
3054 // Vector3 jointAxis = proxyFrame.AtAxis; <--- this path leadeth to madness
3055
3056 // Instead, compute the X axis of the coordinate frame by transforming
3057 // the (1,0,0) vector. At least that works.
3058
3059 //m_log.Debug("PHY: making axis: complete matrix is " + proxyFrame);
3060 Vector3 jointAxis = Vector3.Transform(Vector3.UnitX, proxyFrame);
3061 //m_log.Debug("PHY: making axis: hinge joint axis is " + jointAxis);
3062 //DoJointErrorMessage(joint, "ODE setting hinge axis: " + odeJoint + " to vec:" + jointAxis);
3063 d.JointSetHingeAxis(odeJoint,
3064 jointAxis.X,
3065 jointAxis.Y,
3066 jointAxis.Z);
3067 //d.JointSetHingeParam(odeJoint, (int)dParam.CFM, 0.1f);
3068 if (joint is OdePhysicsJoint)
3069 {
3070 ((OdePhysicsJoint)joint).jointID = odeJoint;
3071 }
3072 else
3073 {
3074 DoJointErrorMessage(joint, "WARNING: non-ode joint in ODE!");
3075 }
3076 }
3077 break;
3078 }
3079 successfullyProcessedPendingJoints.Add(joint);
3080 }
3081 }
3082 else
3083 {
3084 DoJointErrorMessage(joint, "joint could not yet be created; still pending");
3085 }
3086 }
3087
3088 foreach (PhysicsJoint successfullyProcessedJoint in successfullyProcessedPendingJoints)
3089 {
3090 //DoJointErrorMessage(successfullyProcessedJoint, "finalizing succesfully procsssed joint " + successfullyProcessedJoint.ObjectNameInScene + " parms " + successfullyProcessedJoint.RawParams);
3091 //DoJointErrorMessage(successfullyProcessedJoint, "removing from pending");
3092 InternalRemovePendingJoint(successfullyProcessedJoint);
3093 //DoJointErrorMessage(successfullyProcessedJoint, "adding to active");
3094 InternalAddActiveJoint(successfullyProcessedJoint);
3095 //DoJointErrorMessage(successfullyProcessedJoint, "done");
3096 }
3097 }
3098 }
3099
3100 /// <summary>
3101 /// Simulate the joint proxies of a NINJA actor.
3102 /// </summary>
3103 /// <remarks>
3104 /// Called as part of the Simulate() loop if NINJA physics is active. Must only be called from there.
3105 /// </remarks>
3106 /// <param name="actor"></param>
3107 protected void SimulateActorPendingJoints(OdePrim actor)
3108 {
3109 // If an actor moved, move its joint proxy objects as well.
3110 // There seems to be an event PhysicsActor.OnPositionUpdate that could be used
3111 // for this purpose but it is never called! So we just do the joint
3112 // movement code here.
3113
3114 if (actor.SOPName != null &&
3115 joints_connecting_actor.ContainsKey(actor.SOPName) &&
3116 joints_connecting_actor[actor.SOPName] != null &&
3117 joints_connecting_actor[actor.SOPName].Count > 0)
3118 {
3119 foreach (PhysicsJoint affectedJoint in joints_connecting_actor[actor.SOPName])
3120 {
3121 if (affectedJoint.IsInPhysicsEngine)
3122 {
3123 DoJointMoved(affectedJoint);
3124 }
3125 else
3126 {
3127 DoJointErrorMessage(affectedJoint, "a body connected to a joint was moved, but the joint doesn't exist yet! this will lead to joint error. joint was: " + affectedJoint.ObjectNameInScene + " parms:" + affectedJoint.RawParams);
3128 }
3129 }
3130 }
3131 }
3132
3114 public override void GetResults() 3133 public override void GetResults()
3115 { 3134 {
3116 } 3135 }
@@ -3456,24 +3475,21 @@ namespace OpenSim.Region.Physics.OdePlugin
3456 float hfmin = 2000; 3475 float hfmin = 2000;
3457 float hfmax = -2000; 3476 float hfmax = -2000;
3458 3477
3459 for (int x = 0; x < heightmapWidthSamples; x++) 3478 for (int x = 0; x < heightmapWidthSamples; x++)
3479 {
3480 for (int y = 0; y < heightmapHeightSamples; y++)
3460 { 3481 {
3461 for (int y = 0; y < heightmapHeightSamples; y++) 3482 int xx = Util.Clip(x - 1, 0, regionsize - 1);
3462 { 3483 int yy = Util.Clip(y - 1, 0, regionsize - 1);
3463 int xx = Util.Clip(x - 1, 0, regionsize - 1); 3484
3464 int yy = Util.Clip(y - 1, 0, regionsize - 1); 3485
3465 3486 float val= heightMap[yy * (int)Constants.RegionSize + xx];
3466 3487 _heightmap[x * ((int)Constants.RegionSize + 2) + y] = val;
3467 float val= heightMap[yy * (int)Constants.RegionSize + xx]; 3488
3468 _heightmap[x * ((int)Constants.RegionSize + 2) + y] = val; 3489 hfmin = (val < hfmin) ? val : hfmin;
3469 3490 hfmax = (val > hfmax) ? val : hfmax;
3470 hfmin = (val < hfmin) ? val : hfmin;
3471 hfmax = (val > hfmax) ? val : hfmax;
3472 }
3473 } 3491 }
3474 3492 }
3475
3476
3477 3493
3478 lock (OdeLock) 3494 lock (OdeLock)
3479 { 3495 {
@@ -3528,7 +3544,6 @@ namespace OpenSim.Region.Physics.OdePlugin
3528 } 3544 }
3529 RegionTerrain.Add(pOffset, GroundGeom, GroundGeom); 3545 RegionTerrain.Add(pOffset, GroundGeom, GroundGeom);
3530 TerrainHeightFieldHeights.Add(GroundGeom,_heightmap); 3546 TerrainHeightFieldHeights.Add(GroundGeom,_heightmap);
3531
3532 } 3547 }
3533 } 3548 }
3534 3549
@@ -3691,6 +3706,7 @@ namespace OpenSim.Region.Physics.OdePlugin
3691 //d.CloseODE(); 3706 //d.CloseODE();
3692 } 3707 }
3693 } 3708 }
3709
3694 public override Dictionary<uint, float> GetTopColliders() 3710 public override Dictionary<uint, float> GetTopColliders()
3695 { 3711 {
3696 Dictionary<uint, float> returncolliders = new Dictionary<uint, float>(); 3712 Dictionary<uint, float> returncolliders = new Dictionary<uint, float>();
@@ -3727,6 +3743,34 @@ namespace OpenSim.Region.Physics.OdePlugin
3727 } 3743 }
3728 } 3744 }
3729 3745
3746 public override void RaycastWorld(Vector3 position, Vector3 direction, float length, int Count, RayCallback retMethod)
3747 {
3748 if (retMethod != null)
3749 {
3750 m_rayCastManager.QueueRequest(position, direction, length, Count, retMethod);
3751 }
3752 }
3753
3754 public override List<ContactResult> RaycastWorld(Vector3 position, Vector3 direction, float length, int Count)
3755 {
3756 ContactResult[] ourResults = null;
3757 RayCallback retMethod = delegate(List<ContactResult> results)
3758 {
3759 ourResults = new ContactResult[results.Count];
3760 results.CopyTo(ourResults, 0);
3761 };
3762 int waitTime = 0;
3763 m_rayCastManager.QueueRequest(position, direction, length, Count, retMethod);
3764 while (ourResults == null && waitTime < 1000)
3765 {
3766 Thread.Sleep(1);
3767 waitTime++;
3768 }
3769 if (ourResults == null)
3770 return new List<ContactResult> ();
3771 return new List<ContactResult>(ourResults);
3772 }
3773
3730#if USE_DRAWSTUFF 3774#if USE_DRAWSTUFF
3731 // Keyboard callback 3775 // Keyboard callback
3732 public void command(int cmd) 3776 public void command(int cmd)
diff --git a/OpenSim/Region/Physics/OdePlugin/Tests/ODETestClass.cs b/OpenSim/Region/Physics/OdePlugin/Tests/ODETestClass.cs
index 5dcd6f5..2ea810f 100644
--- a/OpenSim/Region/Physics/OdePlugin/Tests/ODETestClass.cs
+++ b/OpenSim/Region/Physics/OdePlugin/Tests/ODETestClass.cs
@@ -31,17 +31,18 @@ using NUnit.Framework;
31using OpenMetaverse; 31using OpenMetaverse;
32using OpenSim.Framework; 32using OpenSim.Framework;
33using OpenSim.Region.Physics.Manager; 33using OpenSim.Region.Physics.Manager;
34using OpenSim.Region.Physics.OdePlugin;
34using log4net; 35using log4net;
35using System.Reflection; 36using System.Reflection;
36 37
37namespace OpenSim.Region.Physics.OdePlugin 38namespace OpenSim.Region.Physics.OdePlugin.Tests
38{ 39{
39 [TestFixture] 40 [TestFixture]
40 public class ODETestClass 41 public class ODETestClass
41 { 42 {
42 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 43 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
43 44
44 private OdePlugin cbt; 45 private OpenSim.Region.Physics.OdePlugin.OdePlugin cbt;
45 private PhysicsScene ps; 46 private PhysicsScene ps;
46 private IMeshingPlugin imp; 47 private IMeshingPlugin imp;
47 48