aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/OdePlugin/OdeScene.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Physics/OdePlugin/OdeScene.cs')
-rw-r--r--OpenSim/Region/Physics/OdePlugin/OdeScene.cs834
1 files changed, 439 insertions, 395 deletions
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)