aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/OdePlugin
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Physics/OdePlugin')
-rw-r--r--OpenSim/Region/Physics/OdePlugin/ODECharacter.cs10
-rw-r--r--OpenSim/Region/Physics/OdePlugin/ODEPrim.cs472
-rw-r--r--OpenSim/Region/Physics/OdePlugin/OdeScene.cs452
3 files changed, 619 insertions, 315 deletions
diff --git a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs
index 8397eb4..f3b0630 100644
--- a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs
+++ b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs
@@ -1261,14 +1261,20 @@ namespace OpenSim.Region.Physics.OdePlugin
1261 { 1261 {
1262 m_requestedUpdateFrequency = ms; 1262 m_requestedUpdateFrequency = ms;
1263 m_eventsubscription = ms; 1263 m_eventsubscription = ms;
1264 CollisionEventsThisFrame.Clear(); 1264
1265 // Don't clear collision event reporting here. This is called directly from scene code and so can lead
1266 // to a race condition with the simulate loop
1267
1265 _parent_scene.AddCollisionEventReporting(this); 1268 _parent_scene.AddCollisionEventReporting(this);
1266 } 1269 }
1267 1270
1268 public override void UnSubscribeEvents() 1271 public override void UnSubscribeEvents()
1269 { 1272 {
1270 CollisionEventsThisFrame.Clear();
1271 _parent_scene.RemoveCollisionEventReporting(this); 1273 _parent_scene.RemoveCollisionEventReporting(this);
1274
1275 // Don't clear collision event reporting here. This is called directly from scene code and so can lead
1276 // to a race condition with the simulate loop
1277
1272 m_requestedUpdateFrequency = 0; 1278 m_requestedUpdateFrequency = 0;
1273 m_eventsubscription = 0; 1279 m_eventsubscription = 0;
1274 } 1280 }
diff --git a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
index 6f37347..a41c856 100644
--- a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
+++ b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
@@ -156,7 +156,15 @@ namespace OpenSim.Region.Physics.OdePlugin
156 /// </summary> 156 /// </summary>
157 public IntPtr m_targetSpace = IntPtr.Zero; 157 public IntPtr m_targetSpace = IntPtr.Zero;
158 158
159 /// <summary>
160 /// The prim geometry, used for collision detection.
161 /// </summary>
162 /// <remarks>
163 /// This is never null except for a brief period when the geometry needs to be replaced (due to resizing or
164 /// mesh change) or when the physical prim is being removed from the scene.
165 /// </remarks>
159 public IntPtr prim_geom { get; private set; } 166 public IntPtr prim_geom { get; private set; }
167
160 public IntPtr _triMeshData { get; private set; } 168 public IntPtr _triMeshData { get; private set; }
161 169
162 private IntPtr _linkJointGroup = IntPtr.Zero; 170 private IntPtr _linkJointGroup = IntPtr.Zero;
@@ -325,14 +333,12 @@ namespace OpenSim.Region.Physics.OdePlugin
325 { 333 {
326 prim_geom = geom; 334 prim_geom = geom;
327//Console.WriteLine("SetGeom to " + prim_geom + " for " + Name); 335//Console.WriteLine("SetGeom to " + prim_geom + " for " + Name);
328 if (prim_geom != IntPtr.Zero)
329 {
330 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
331 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
332 336
333 _parent_scene.geom_name_map[prim_geom] = Name; 337 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
334 _parent_scene.actor_name_map[prim_geom] = this; 338 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
335 } 339
340 _parent_scene.geom_name_map[prim_geom] = Name;
341 _parent_scene.actor_name_map[prim_geom] = this;
336 342
337 if (childPrim) 343 if (childPrim)
338 { 344 {
@@ -765,11 +771,8 @@ namespace OpenSim.Region.Physics.OdePlugin
765 m_collisionCategories &= ~CollisionCategories.Body; 771 m_collisionCategories &= ~CollisionCategories.Body;
766 m_collisionFlags &= ~(CollisionCategories.Wind | CollisionCategories.Land); 772 m_collisionFlags &= ~(CollisionCategories.Wind | CollisionCategories.Land);
767 773
768 if (prim_geom != IntPtr.Zero) 774 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
769 { 775 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
770 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
771 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
772 }
773 776
774 d.BodyDestroy(Body); 777 d.BodyDestroy(Body);
775 lock (childrenPrim) 778 lock (childrenPrim)
@@ -793,11 +796,8 @@ namespace OpenSim.Region.Physics.OdePlugin
793 m_collisionCategories &= ~CollisionCategories.Body; 796 m_collisionCategories &= ~CollisionCategories.Body;
794 m_collisionFlags &= ~(CollisionCategories.Wind | CollisionCategories.Land); 797 m_collisionFlags &= ~(CollisionCategories.Wind | CollisionCategories.Land);
795 798
796 if (prim_geom != IntPtr.Zero) 799 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
797 { 800 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
798 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
799 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
800 }
801 801
802 Body = IntPtr.Zero; 802 Body = IntPtr.Zero;
803 } 803 }
@@ -864,10 +864,7 @@ namespace OpenSim.Region.Physics.OdePlugin
864// _parent_scene.waitForSpaceUnlock(m_targetSpace); 864// _parent_scene.waitForSpaceUnlock(m_targetSpace);
865 try 865 try
866 { 866 {
867 if (prim_geom == IntPtr.Zero) 867 SetGeom(d.CreateTriMesh(m_targetSpace, _triMeshData, parent_scene.triCallback, null, null));
868 {
869 SetGeom(d.CreateTriMesh(m_targetSpace, _triMeshData, parent_scene.triCallback, null, null));
870 }
871 } 868 }
872 catch (AccessViolationException) 869 catch (AccessViolationException)
873 { 870 {
@@ -890,73 +887,67 @@ namespace OpenSim.Region.Physics.OdePlugin
890#if SPAM 887#if SPAM
891Console.WriteLine("ZProcessTaints for " + Name); 888Console.WriteLine("ZProcessTaints for " + Name);
892#endif 889#endif
890
891 // This must be processed as the very first taint so that later operations have a prim_geom to work with
892 // if this is a new prim.
893 if (m_taintadd) 893 if (m_taintadd)
894 {
895 changeadd(); 894 changeadd();
896 }
897
898 if (prim_geom != IntPtr.Zero)
899 {
900 if (!_position.ApproxEquals(m_taintposition, 0f))
901 changemove();
902 895
903 if (m_taintrot != _orientation) 896 if (!_position.ApproxEquals(m_taintposition, 0f))
904 { 897 changemove();
905 if (childPrim && IsPhysical) // For physical child prim... 898
906 { 899 if (m_taintrot != _orientation)
907 rotate(); 900 {
908 // KF: ODE will also rotate the parent prim! 901 if (childPrim && IsPhysical) // For physical child prim...
909 // so rotate the root back to where it was 902 {
910 OdePrim parent = (OdePrim)_parent; 903 rotate();
911 parent.rotate(); 904 // KF: ODE will also rotate the parent prim!
912 } 905 // so rotate the root back to where it was
913 else 906 OdePrim parent = (OdePrim)_parent;
914 { 907 parent.rotate();
915 //Just rotate the prim
916 rotate();
917 }
918 } 908 }
919 909 else
920 if (m_taintPhysics != IsPhysical && !(m_taintparent != _parent)) 910 {
921 changePhysicsStatus(); 911 //Just rotate the prim
912 rotate();
913 }
914 }
915
916 if (m_taintPhysics != IsPhysical && !(m_taintparent != _parent))
917 changePhysicsStatus();
922 918
923 if (!_size.ApproxEquals(m_taintsize, 0f)) 919 if (!_size.ApproxEquals(m_taintsize, 0f))
924 changesize(); 920 changesize();
925 921
926 if (m_taintshape) 922 if (m_taintshape)
927 changeshape(); 923 changeshape();
928 924
929 if (m_taintforce) 925 if (m_taintforce)
930 changeAddForce(); 926 changeAddForce();
931 927
932 if (m_taintaddangularforce) 928 if (m_taintaddangularforce)
933 changeAddAngularForce(); 929 changeAddAngularForce();
934 930
935 if (!m_taintTorque.ApproxEquals(Vector3.Zero, 0.001f)) 931 if (!m_taintTorque.ApproxEquals(Vector3.Zero, 0.001f))
936 changeSetTorque(); 932 changeSetTorque();
937 933
938 if (m_taintdisable) 934 if (m_taintdisable)
939 changedisable(); 935 changedisable();
940 936
941 if (m_taintselected != m_isSelected) 937 if (m_taintselected != m_isSelected)
942 changeSelectedStatus(); 938 changeSelectedStatus();
943 939
944 if (!m_taintVelocity.ApproxEquals(Vector3.Zero, 0.001f)) 940 if (!m_taintVelocity.ApproxEquals(Vector3.Zero, 0.001f))
945 changevelocity(); 941 changevelocity();
946 942
947 if (m_taintparent != _parent) 943 if (m_taintparent != _parent)
948 changelink(); 944 changelink();
949 945
950 if (m_taintCollidesWater != m_collidesWater) 946 if (m_taintCollidesWater != m_collidesWater)
951 changefloatonwater(); 947 changefloatonwater();
952 948
953 if (!m_angularlock.ApproxEquals(m_taintAngularLock,0f)) 949 if (!m_angularlock.ApproxEquals(m_taintAngularLock,0f))
954 changeAngularLock(); 950 changeAngularLock();
955 }
956 else
957 {
958 m_log.ErrorFormat("[PHYSICS]: The scene reused a disposed PhysActor for {0}! *waves finger*, Don't be evil. A couple of things can cause this. An improper prim breakdown(be sure to set prim_geom to zero after d.GeomDestroy! An improper buildup (creating the geom failed). Or, the Scene Reused a physics actor after disposing it.)", Name);
959 }
960 } 951 }
961 952
962 /// <summary> 953 /// <summary>
@@ -1052,150 +1043,146 @@ Console.WriteLine("ZProcessTaints for " + Name);
1052 /// <param name="prim">Child prim</param> 1043 /// <param name="prim">Child prim</param>
1053 private void AddChildPrim(OdePrim prim) 1044 private void AddChildPrim(OdePrim prim)
1054 { 1045 {
1055//Console.WriteLine("AddChildPrim " + Name); 1046 if (LocalID == prim.LocalID)
1056 if (LocalID != prim.LocalID) 1047 return;
1048
1049 if (Body == IntPtr.Zero)
1057 { 1050 {
1058 if (Body == IntPtr.Zero) 1051 Body = d.BodyCreate(_parent_scene.world);
1052 setMass();
1053 }
1054
1055 lock (childrenPrim)
1056 {
1057 if (childrenPrim.Contains(prim))
1058 return;
1059
1060// m_log.DebugFormat(
1061// "[ODE PRIM]: Linking prim {0} {1} to {2} {3}", prim.Name, prim.LocalID, Name, LocalID);
1062
1063 childrenPrim.Add(prim);
1064
1065 foreach (OdePrim prm in childrenPrim)
1059 { 1066 {
1060 Body = d.BodyCreate(_parent_scene.world); 1067 d.Mass m2;
1061 setMass(); 1068 d.MassSetZero(out m2);
1069 d.MassSetBoxTotal(out m2, prim.CalculateMass(), prm._size.X, prm._size.Y, prm._size.Z);
1070
1071 d.Quaternion quat = new d.Quaternion();
1072 quat.W = prm._orientation.W;
1073 quat.X = prm._orientation.X;
1074 quat.Y = prm._orientation.Y;
1075 quat.Z = prm._orientation.Z;
1076
1077 d.Matrix3 mat = new d.Matrix3();
1078 d.RfromQ(out mat, ref quat);
1079 d.MassRotate(ref m2, ref mat);
1080 d.MassTranslate(ref m2, Position.X - prm.Position.X, Position.Y - prm.Position.Y, Position.Z - prm.Position.Z);
1081 d.MassAdd(ref pMass, ref m2);
1062 } 1082 }
1063 if (Body != IntPtr.Zero) 1083
1084 foreach (OdePrim prm in childrenPrim)
1064 { 1085 {
1065 lock (childrenPrim) 1086 prm.m_collisionCategories |= CollisionCategories.Body;
1066 { 1087 prm.m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind);
1067 if (!childrenPrim.Contains(prim))
1068 {
1069//Console.WriteLine("childrenPrim.Add " + prim);
1070 childrenPrim.Add(prim);
1071
1072 foreach (OdePrim prm in childrenPrim)
1073 {
1074 d.Mass m2;
1075 d.MassSetZero(out m2);
1076 d.MassSetBoxTotal(out m2, prim.CalculateMass(), prm._size.X, prm._size.Y, prm._size.Z);
1077
1078 d.Quaternion quat = new d.Quaternion();
1079 quat.W = prm._orientation.W;
1080 quat.X = prm._orientation.X;
1081 quat.Y = prm._orientation.Y;
1082 quat.Z = prm._orientation.Z;
1083
1084 d.Matrix3 mat = new d.Matrix3();
1085 d.RfromQ(out mat, ref quat);
1086 d.MassRotate(ref m2, ref mat);
1087 d.MassTranslate(ref m2, Position.X - prm.Position.X, Position.Y - prm.Position.Y, Position.Z - prm.Position.Z);
1088 d.MassAdd(ref pMass, ref m2);
1089 }
1090
1091 foreach (OdePrim prm in childrenPrim)
1092 {
1093 prm.m_collisionCategories |= CollisionCategories.Body;
1094 prm.m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind);
1095 1088
1096 if (prm.prim_geom == IntPtr.Zero)
1097 {
1098 m_log.WarnFormat(
1099 "[PHYSICS]: Unable to link one of the linkset elements {0} for parent {1}. No geom yet",
1100 prm.Name, prim.Name);
1101 continue;
1102 }
1103//Console.WriteLine(" GeomSetCategoryBits 1: " + prm.prim_geom + " - " + (int)prm.m_collisionCategories + " for " + Name); 1089//Console.WriteLine(" GeomSetCategoryBits 1: " + prm.prim_geom + " - " + (int)prm.m_collisionCategories + " for " + Name);
1104 d.GeomSetCategoryBits(prm.prim_geom, (int)prm.m_collisionCategories); 1090 d.GeomSetCategoryBits(prm.prim_geom, (int)prm.m_collisionCategories);
1105 d.GeomSetCollideBits(prm.prim_geom, (int)prm.m_collisionFlags); 1091 d.GeomSetCollideBits(prm.prim_geom, (int)prm.m_collisionFlags);
1106
1107 1092
1108 d.Quaternion quat = new d.Quaternion(); 1093 d.Quaternion quat = new d.Quaternion();
1109 quat.W = prm._orientation.W; 1094 quat.W = prm._orientation.W;
1110 quat.X = prm._orientation.X; 1095 quat.X = prm._orientation.X;
1111 quat.Y = prm._orientation.Y; 1096 quat.Y = prm._orientation.Y;
1112 quat.Z = prm._orientation.Z; 1097 quat.Z = prm._orientation.Z;
1113 1098
1114 d.Matrix3 mat = new d.Matrix3(); 1099 d.Matrix3 mat = new d.Matrix3();
1115 d.RfromQ(out mat, ref quat); 1100 d.RfromQ(out mat, ref quat);
1116 if (Body != IntPtr.Zero) 1101 if (Body != IntPtr.Zero)
1117 { 1102 {
1118 d.GeomSetBody(prm.prim_geom, Body); 1103 d.GeomSetBody(prm.prim_geom, Body);
1119 prm.childPrim = true; 1104 prm.childPrim = true;
1120 d.GeomSetOffsetWorldPosition(prm.prim_geom, prm.Position.X , prm.Position.Y, prm.Position.Z); 1105 d.GeomSetOffsetWorldPosition(prm.prim_geom, prm.Position.X , prm.Position.Y, prm.Position.Z);
1121 //d.GeomSetOffsetPosition(prim.prim_geom, 1106 //d.GeomSetOffsetPosition(prim.prim_geom,
1122 // (Position.X - prm.Position.X) - pMass.c.X, 1107 // (Position.X - prm.Position.X) - pMass.c.X,
1123 // (Position.Y - prm.Position.Y) - pMass.c.Y, 1108 // (Position.Y - prm.Position.Y) - pMass.c.Y,
1124 // (Position.Z - prm.Position.Z) - pMass.c.Z); 1109 // (Position.Z - prm.Position.Z) - pMass.c.Z);
1125 d.GeomSetOffsetWorldRotation(prm.prim_geom, ref mat); 1110 d.GeomSetOffsetWorldRotation(prm.prim_geom, ref mat);
1126 //d.GeomSetOffsetRotation(prm.prim_geom, ref mat); 1111 //d.GeomSetOffsetRotation(prm.prim_geom, ref mat);
1127 d.MassTranslate(ref pMass, -pMass.c.X, -pMass.c.Y, -pMass.c.Z); 1112 d.MassTranslate(ref pMass, -pMass.c.X, -pMass.c.Y, -pMass.c.Z);
1128 d.BodySetMass(Body, ref pMass); 1113 d.BodySetMass(Body, ref pMass);
1129 } 1114 }
1130 else 1115 else
1131 { 1116 {
1132 m_log.DebugFormat("[PHYSICS]: {0} ain't got no boooooooooddy, no body", Name); 1117 m_log.DebugFormat("[PHYSICS]: {0} ain't got no boooooooooddy, no body", Name);
1133 } 1118 }
1134 1119
1135 prm.m_interpenetrationcount = 0; 1120 prm.m_interpenetrationcount = 0;
1136 prm.m_collisionscore = 0; 1121 prm.m_collisionscore = 0;
1137 prm.m_disabled = false; 1122 prm.m_disabled = false;
1138 1123
1139 // The body doesn't already have a finite rotation mode set here 1124 // The body doesn't already have a finite rotation mode set here
1140 if ((!m_angularlock.ApproxEquals(Vector3.Zero, 0f)) && _parent == null) 1125 if ((!m_angularlock.ApproxEquals(Vector3.Zero, 0f)) && _parent == null)
1141 { 1126 {
1142 prm.createAMotor(m_angularlock); 1127 prm.createAMotor(m_angularlock);
1143 } 1128 }
1144 prm.Body = Body; 1129 prm.Body = Body;
1145 _parent_scene.ActivatePrim(prm); 1130 _parent_scene.ActivatePrim(prm);
1146 } 1131 }
1147 1132
1148 m_collisionCategories |= CollisionCategories.Body; 1133 m_collisionCategories |= CollisionCategories.Body;
1149 m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind); 1134 m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind);
1150 1135
1151//Console.WriteLine("GeomSetCategoryBits 2: " + prim_geom + " - " + (int)m_collisionCategories + " for " + Name); 1136//Console.WriteLine("GeomSetCategoryBits 2: " + prim_geom + " - " + (int)m_collisionCategories + " for " + Name);
1152 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); 1137 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
1153//Console.WriteLine(" Post GeomSetCategoryBits 2"); 1138//Console.WriteLine(" Post GeomSetCategoryBits 2");
1154 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); 1139 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
1155
1156 d.Quaternion quat2 = new d.Quaternion();
1157 quat2.W = _orientation.W;
1158 quat2.X = _orientation.X;
1159 quat2.Y = _orientation.Y;
1160 quat2.Z = _orientation.Z;
1161
1162 d.Matrix3 mat2 = new d.Matrix3();
1163 d.RfromQ(out mat2, ref quat2);
1164 d.GeomSetBody(prim_geom, Body);
1165 d.GeomSetOffsetWorldPosition(prim_geom, Position.X - pMass.c.X, Position.Y - pMass.c.Y, Position.Z - pMass.c.Z);
1166 //d.GeomSetOffsetPosition(prim.prim_geom,
1167 // (Position.X - prm.Position.X) - pMass.c.X,
1168 // (Position.Y - prm.Position.Y) - pMass.c.Y,
1169 // (Position.Z - prm.Position.Z) - pMass.c.Z);
1170 //d.GeomSetOffsetRotation(prim_geom, ref mat2);
1171 d.MassTranslate(ref pMass, -pMass.c.X, -pMass.c.Y, -pMass.c.Z);
1172 d.BodySetMass(Body, ref pMass);
1173
1174 d.BodySetAutoDisableFlag(Body, true);
1175 d.BodySetAutoDisableSteps(Body, body_autodisable_frames);
1176 1140
1177 m_interpenetrationcount = 0; 1141 d.Quaternion quat2 = new d.Quaternion();
1178 m_collisionscore = 0; 1142 quat2.W = _orientation.W;
1179 m_disabled = false; 1143 quat2.X = _orientation.X;
1144 quat2.Y = _orientation.Y;
1145 quat2.Z = _orientation.Z;
1180 1146
1181 // The body doesn't already have a finite rotation mode set here 1147 d.Matrix3 mat2 = new d.Matrix3();
1182 if ((!m_angularlock.ApproxEquals(Vector3.Zero, 0f)) && _parent == null) 1148 d.RfromQ(out mat2, ref quat2);
1183 { 1149 d.GeomSetBody(prim_geom, Body);
1184 createAMotor(m_angularlock); 1150 d.GeomSetOffsetWorldPosition(prim_geom, Position.X - pMass.c.X, Position.Y - pMass.c.Y, Position.Z - pMass.c.Z);
1185 } 1151 //d.GeomSetOffsetPosition(prim.prim_geom,
1186 d.BodySetPosition(Body, Position.X, Position.Y, Position.Z); 1152 // (Position.X - prm.Position.X) - pMass.c.X,
1187 if (m_vehicle.Type != Vehicle.TYPE_NONE) 1153 // (Position.Y - prm.Position.Y) - pMass.c.Y,
1188 m_vehicle.Enable(Body, _parent_scene); 1154 // (Position.Z - prm.Position.Z) - pMass.c.Z);
1155 //d.GeomSetOffsetRotation(prim_geom, ref mat2);
1156 d.MassTranslate(ref pMass, -pMass.c.X, -pMass.c.Y, -pMass.c.Z);
1157 d.BodySetMass(Body, ref pMass);
1189 1158
1190 _parent_scene.ActivatePrim(this); 1159 d.BodySetAutoDisableFlag(Body, true);
1191 } 1160 d.BodySetAutoDisableSteps(Body, body_autodisable_frames);
1192 } 1161
1162 m_interpenetrationcount = 0;
1163 m_collisionscore = 0;
1164 m_disabled = false;
1165
1166 // The body doesn't already have a finite rotation mode set here
1167 if ((!m_angularlock.ApproxEquals(Vector3.Zero, 0f)) && _parent == null)
1168 {
1169 createAMotor(m_angularlock);
1193 } 1170 }
1171
1172 d.BodySetPosition(Body, Position.X, Position.Y, Position.Z);
1173
1174 if (m_vehicle.Type != Vehicle.TYPE_NONE)
1175 m_vehicle.Enable(Body, _parent_scene);
1176
1177 _parent_scene.ActivatePrim(this);
1194 } 1178 }
1195 } 1179 }
1196 1180
1197 private void ChildSetGeom(OdePrim odePrim) 1181 private void ChildSetGeom(OdePrim odePrim)
1198 { 1182 {
1183// m_log.DebugFormat(
1184// "[ODE PRIM]: ChildSetGeom {0} {1} for {2} {3}", odePrim.Name, odePrim.LocalID, Name, LocalID);
1185
1199 //if (IsPhysical && Body != IntPtr.Zero) 1186 //if (IsPhysical && Body != IntPtr.Zero)
1200 lock (childrenPrim) 1187 lock (childrenPrim)
1201 { 1188 {
@@ -1210,12 +1197,14 @@ Console.WriteLine("ZProcessTaints for " + Name);
1210 //prm.childPrim = false; 1197 //prm.childPrim = false;
1211 } 1198 }
1212 } 1199 }
1200
1213 disableBody(); 1201 disableBody();
1214 1202
1215 if (Body != IntPtr.Zero) 1203 // Spurious - Body == IntPtr.Zero after disableBody()
1216 { 1204// if (Body != IntPtr.Zero)
1217 _parent_scene.DeactivatePrim(this); 1205// {
1218 } 1206// _parent_scene.DeactivatePrim(this);
1207// }
1219 1208
1220 lock (childrenPrim) 1209 lock (childrenPrim)
1221 { 1210 {
@@ -1229,6 +1218,9 @@ Console.WriteLine("ZProcessTaints for " + Name);
1229 1218
1230 private void ChildDelink(OdePrim odePrim) 1219 private void ChildDelink(OdePrim odePrim)
1231 { 1220 {
1221// m_log.DebugFormat(
1222// "[ODE PRIM]: Delinking prim {0} {1} from {2} {3}", odePrim.Name, odePrim.LocalID, Name, LocalID);
1223
1232 // Okay, we have a delinked child.. need to rebuild the body. 1224 // Okay, we have a delinked child.. need to rebuild the body.
1233 lock (childrenPrim) 1225 lock (childrenPrim)
1234 { 1226 {
@@ -1243,6 +1235,7 @@ Console.WriteLine("ZProcessTaints for " + Name);
1243 //prm.childPrim = false; 1235 //prm.childPrim = false;
1244 } 1236 }
1245 } 1237 }
1238
1246 disableBody(); 1239 disableBody();
1247 1240
1248 lock (childrenPrim) 1241 lock (childrenPrim)
@@ -1251,10 +1244,11 @@ Console.WriteLine("ZProcessTaints for " + Name);
1251 childrenPrim.Remove(odePrim); 1244 childrenPrim.Remove(odePrim);
1252 } 1245 }
1253 1246
1254 if (Body != IntPtr.Zero) 1247 // Spurious - Body == IntPtr.Zero after disableBody()
1255 { 1248// if (Body != IntPtr.Zero)
1256 _parent_scene.DeactivatePrim(this); 1249// {
1257 } 1250// _parent_scene.DeactivatePrim(this);
1251// }
1258 1252
1259 lock (childrenPrim) 1253 lock (childrenPrim)
1260 { 1254 {
@@ -1303,11 +1297,8 @@ Console.WriteLine("ZProcessTaints for " + Name);
1303 disableBodySoft(); 1297 disableBodySoft();
1304 } 1298 }
1305 1299
1306 if (prim_geom != IntPtr.Zero) 1300 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
1307 { 1301 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
1308 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
1309 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
1310 }
1311 1302
1312 if (IsPhysical) 1303 if (IsPhysical)
1313 { 1304 {
@@ -1328,11 +1319,8 @@ Console.WriteLine("ZProcessTaints for " + Name);
1328 if (m_collidesWater) 1319 if (m_collidesWater)
1329 m_collisionFlags |= CollisionCategories.Water; 1320 m_collisionFlags |= CollisionCategories.Water;
1330 1321
1331 if (prim_geom != IntPtr.Zero) 1322 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
1332 { 1323 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
1333 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
1334 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
1335 }
1336 1324
1337 if (IsPhysical) 1325 if (IsPhysical)
1338 { 1326 {
@@ -1472,6 +1460,9 @@ Console.WriteLine("CreateGeom:");
1472 } 1460 }
1473 else 1461 else
1474 { 1462 {
1463 m_log.WarnFormat(
1464 "[ODE PRIM]: Called RemoveGeom() on {0} {1} where geometry was already null.", Name, LocalID);
1465
1475 return false; 1466 return false;
1476 } 1467 }
1477 } 1468 }
@@ -1505,16 +1496,13 @@ Console.WriteLine("changeadd 1");
1505#endif 1496#endif
1506 CreateGeom(m_targetSpace, mesh); 1497 CreateGeom(m_targetSpace, mesh);
1507 1498
1508 if (prim_geom != IntPtr.Zero) 1499 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
1509 { 1500 d.Quaternion myrot = new d.Quaternion();
1510 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z); 1501 myrot.X = _orientation.X;
1511 d.Quaternion myrot = new d.Quaternion(); 1502 myrot.Y = _orientation.Y;
1512 myrot.X = _orientation.X; 1503 myrot.Z = _orientation.Z;
1513 myrot.Y = _orientation.Y; 1504 myrot.W = _orientation.W;
1514 myrot.Z = _orientation.Z; 1505 d.GeomSetQuaternion(prim_geom, ref myrot);
1515 myrot.W = _orientation.W;
1516 d.GeomSetQuaternion(prim_geom, ref myrot);
1517 }
1518 1506
1519 if (IsPhysical && Body == IntPtr.Zero) 1507 if (IsPhysical && Body == IntPtr.Zero)
1520 enableBody(); 1508 enableBody();
@@ -1579,24 +1567,20 @@ Console.WriteLine(" JointCreateFixed");
1579 //m_log.Debug("[BUG]: race!"); 1567 //m_log.Debug("[BUG]: race!");
1580 //} 1568 //}
1581 } 1569 }
1582 else
1583 {
1584 // string primScenAvatarIn = _parent_scene.whichspaceamIin(_position);
1585 // int[] arrayitem = _parent_scene.calculateSpaceArrayItemFromPos(_position);
1586// _parent_scene.waitForSpaceUnlock(m_targetSpace);
1587 1570
1588 IntPtr tempspace = _parent_scene.recalculateSpaceForGeom(prim_geom, _position, m_targetSpace); 1571 // string primScenAvatarIn = _parent_scene.whichspaceamIin(_position);
1589 m_targetSpace = tempspace; 1572 // int[] arrayitem = _parent_scene.calculateSpaceArrayItemFromPos(_position);
1573// _parent_scene.waitForSpaceUnlock(m_targetSpace);
1574
1575 IntPtr tempspace = _parent_scene.recalculateSpaceForGeom(prim_geom, _position, m_targetSpace);
1576 m_targetSpace = tempspace;
1590 1577
1591// _parent_scene.waitForSpaceUnlock(m_targetSpace); 1578// _parent_scene.waitForSpaceUnlock(m_targetSpace);
1592 if (prim_geom != IntPtr.Zero) 1579
1593 { 1580 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
1594 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
1595 1581
1596// _parent_scene.waitForSpaceUnlock(m_targetSpace); 1582// _parent_scene.waitForSpaceUnlock(m_targetSpace);
1597 d.SpaceAdd(m_targetSpace, prim_geom); 1583 d.SpaceAdd(m_targetSpace, prim_geom);
1598 }
1599 }
1600 1584
1601 changeSelectedStatus(); 1585 changeSelectedStatus();
1602 1586
@@ -2047,18 +2031,16 @@ Console.WriteLine(" JointCreateFixed");
2047 { 2031 {
2048 m_collidesWater = m_taintCollidesWater; 2032 m_collidesWater = m_taintCollidesWater;
2049 2033
2050 if (prim_geom != IntPtr.Zero) 2034 if (m_collidesWater)
2051 { 2035 {
2052 if (m_collidesWater) 2036 m_collisionFlags |= CollisionCategories.Water;
2053 {
2054 m_collisionFlags |= CollisionCategories.Water;
2055 }
2056 else
2057 {
2058 m_collisionFlags &= ~CollisionCategories.Water;
2059 }
2060 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
2061 } 2037 }
2038 else
2039 {
2040 m_collisionFlags &= ~CollisionCategories.Water;
2041 }
2042
2043 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
2062 } 2044 }
2063 2045
2064 /// <summary> 2046 /// <summary>
diff --git a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs
index 842ff91..32e81e2 100644
--- a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs
+++ b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs
@@ -30,20 +30,21 @@
30 30
31using System; 31using System;
32using System.Collections.Generic; 32using System.Collections.Generic;
33using System.Diagnostics;
34using System.IO;
35using System.Linq;
33using System.Reflection; 36using System.Reflection;
34using System.Runtime.InteropServices; 37using System.Runtime.InteropServices;
35using System.Threading; 38using System.Threading;
36using System.IO;
37using System.Diagnostics;
38using log4net; 39using log4net;
39using Nini.Config; 40using Nini.Config;
40using Ode.NET; 41using Ode.NET;
42using OpenMetaverse;
41#if USE_DRAWSTUFF 43#if USE_DRAWSTUFF
42using Drawstuff.NET; 44using Drawstuff.NET;
43#endif 45#endif
44using OpenSim.Framework; 46using OpenSim.Framework;
45using OpenSim.Region.Physics.Manager; 47using OpenSim.Region.Physics.Manager;
46using OpenMetaverse;
47 48
48namespace OpenSim.Region.Physics.OdePlugin 49namespace OpenSim.Region.Physics.OdePlugin
49{ 50{
@@ -54,15 +55,15 @@ namespace OpenSim.Region.Physics.OdePlugin
54 End = 2 55 End = 2
55 } 56 }
56 57
57 public struct sCollisionData 58// public struct sCollisionData
58 { 59// {
59 public uint ColliderLocalId; 60// public uint ColliderLocalId;
60 public uint CollidedWithLocalId; 61// public uint CollidedWithLocalId;
61 public int NumberOfCollisions; 62// public int NumberOfCollisions;
62 public int CollisionType; 63// public int CollisionType;
63 public int StatusIndicator; 64// public int StatusIndicator;
64 public int lastframe; 65// public int lastframe;
65 } 66// }
66 67
67 [Flags] 68 [Flags]
68 public enum CollisionCategories : int 69 public enum CollisionCategories : int
@@ -131,6 +132,135 @@ namespace OpenSim.Region.Physics.OdePlugin
131 /// </remarks> 132 /// </remarks>
132 internal static Object UniversalColliderSyncObject = new Object(); 133 internal static Object UniversalColliderSyncObject = new Object();
133 134
135 /// <summary>
136 /// Is stats collecting enabled for this ODE scene?
137 /// </summary>
138 public bool CollectStats { get; set; }
139
140 /// <summary>
141 /// Statistics for this scene.
142 /// </summary>
143 private Dictionary<string, float> m_stats = new Dictionary<string, float>();
144
145 /// <summary>
146 /// Stat name for total number of avatars in this ODE scene.
147 /// </summary>
148 public const string ODETotalAvatarsStatName = "ODETotalAvatars";
149
150 /// <summary>
151 /// Stat name for total number of prims in this ODE scene.
152 /// </summary>
153 public const string ODETotalPrimsStatName = "ODETotalPrims";
154
155 /// <summary>
156 /// Stat name for total number of prims with active physics in this ODE scene.
157 /// </summary>
158 public const string ODEActivePrimsStatName = "ODEActivePrims";
159
160 /// <summary>
161 /// Stat name for the total time spent in ODE frame processing.
162 /// </summary>
163 /// <remarks>
164 /// A sanity check for the main scene loop physics time.
165 /// </remarks>
166 public const string ODETotalFrameMsStatName = "ODETotalFrameMS";
167
168 /// <summary>
169 /// Stat name for time spent processing avatar taints per frame
170 /// </summary>
171 public const string ODEAvatarTaintMsStatName = "ODEAvatarTaintFrameMS";
172
173 /// <summary>
174 /// Stat name for time spent processing prim taints per frame
175 /// </summary>
176 public const string ODEPrimTaintMsStatName = "ODEPrimTaintFrameMS";
177
178 /// <summary>
179 /// Stat name for time spent calculating avatar forces per frame.
180 /// </summary>
181 public const string ODEAvatarForcesFrameMsStatName = "ODEAvatarForcesFrameMS";
182
183 /// <summary>
184 /// Stat name for time spent calculating prim forces per frame
185 /// </summary>
186 public const string ODEPrimForcesFrameMsStatName = "ODEPrimForcesFrameMS";
187
188 /// <summary>
189 /// Stat name for time spent fulfilling raycasting requests per frame
190 /// </summary>
191 public const string ODERaycastingFrameMsStatName = "ODERaycastingFrameMS";
192
193 /// <summary>
194 /// Stat name for time spent in native code that actually steps through the simulation.
195 /// </summary>
196 public const string ODENativeStepFrameMsStatName = "ODENativeStepFrameMS";
197
198 /// <summary>
199 /// Stat name for the number of milliseconds that ODE spends in native space collision code.
200 /// </summary>
201 public const string ODENativeSpaceCollisionFrameMsStatName = "ODENativeSpaceCollisionFrameMS";
202
203 /// <summary>
204 /// Stat name for milliseconds that ODE spends in native geom collision code.
205 /// </summary>
206 public const string ODENativeGeomCollisionFrameMsStatName = "ODENativeGeomCollisionFrameMS";
207
208 /// <summary>
209 /// Time spent in collision processing that is not spent in native space or geom collision code.
210 /// </summary>
211 public const string ODEOtherCollisionFrameMsStatName = "ODEOtherCollisionFrameMS";
212
213 /// <summary>
214 /// Stat name for time spent notifying listeners of collisions
215 /// </summary>
216 public const string ODECollisionNotificationFrameMsStatName = "ODECollisionNotificationFrameMS";
217
218 /// <summary>
219 /// Stat name for milliseconds spent updating avatar position and velocity
220 /// </summary>
221 public const string ODEAvatarUpdateFrameMsStatName = "ODEAvatarUpdateFrameMS";
222
223 /// <summary>
224 /// Stat name for the milliseconds spent updating prim position and velocity
225 /// </summary>
226 public const string ODEPrimUpdateFrameMsStatName = "ODEPrimUpdateFrameMS";
227
228 /// <summary>
229 /// Stat name for avatar collisions with another entity.
230 /// </summary>
231 public const string ODEAvatarContactsStatsName = "ODEAvatarContacts";
232
233 /// <summary>
234 /// Stat name for prim collisions with another entity.
235 /// </summary>
236 public const string ODEPrimContactsStatName = "ODEPrimContacts";
237
238 /// <summary>
239 /// Used to hold tick numbers for stat collection purposes.
240 /// </summary>
241 private int m_nativeCollisionStartTick;
242
243 /// <summary>
244 /// A messy way to tell if we need to avoid adding a collision time because this was already done in the callback.
245 /// </summary>
246 private bool m_inCollisionTiming;
247
248 /// <summary>
249 /// A temporary holder for the number of avatar collisions in a frame, so we can work out how many object
250 /// collisions occured using the _perloopcontact if stats collection is enabled.
251 /// </summary>
252 private int m_tempAvatarCollisionsThisFrame;
253
254 /// <summary>
255 /// Used in calculating physics frame time dilation
256 /// </summary>
257 private int tickCountFrameRun;
258
259 /// <summary>
260 /// Used in calculating physics frame time dilation
261 /// </summary>
262 private int latertickcount;
263
134 private Random fluidRandomizer = new Random(Environment.TickCount); 264 private Random fluidRandomizer = new Random(Environment.TickCount);
135 265
136 private const uint m_regionWidth = Constants.RegionSize; 266 private const uint m_regionWidth = Constants.RegionSize;
@@ -257,12 +387,12 @@ namespace OpenSim.Region.Physics.OdePlugin
257 /// <summary> 387 /// <summary>
258 /// A dictionary of actors that should receive collision events. 388 /// A dictionary of actors that should receive collision events.
259 /// </summary> 389 /// </summary>
260 private readonly Dictionary<uint, PhysicsActor> _collisionEventPrim = new Dictionary<uint, PhysicsActor>(); 390 private readonly Dictionary<uint, PhysicsActor> m_collisionEventActors = new Dictionary<uint, PhysicsActor>();
261 391
262 /// <summary> 392 /// <summary>
263 /// A dictionary of collision event changes that are waiting to be processed. 393 /// A dictionary of collision event changes that are waiting to be processed.
264 /// </summary> 394 /// </summary>
265 private readonly Dictionary<uint, PhysicsActor> _collisionEventPrimChanges = new Dictionary<uint, PhysicsActor>(); 395 private readonly Dictionary<uint, PhysicsActor> m_collisionEventActorsChanges = new Dictionary<uint, PhysicsActor>();
266 396
267 /// <summary> 397 /// <summary>
268 /// Maps a unique geometry id (a memory location) to a physics actor name. 398 /// Maps a unique geometry id (a memory location) to a physics actor name.
@@ -345,9 +475,6 @@ namespace OpenSim.Region.Physics.OdePlugin
345 private OdePrim cp1; 475 private OdePrim cp1;
346 private OdeCharacter cc2; 476 private OdeCharacter cc2;
347 private OdePrim cp2; 477 private OdePrim cp2;
348 private int tickCountFrameRun;
349
350 private int latertickcount=0;
351 //private int cStartStop = 0; 478 //private int cStartStop = 0;
352 //private string cDictKey = ""; 479 //private string cDictKey = "";
353 480
@@ -440,6 +567,8 @@ namespace OpenSim.Region.Physics.OdePlugin
440 // Initialize the mesh plugin 567 // Initialize the mesh plugin
441 public override void Initialise(IMesher meshmerizer, IConfigSource config) 568 public override void Initialise(IMesher meshmerizer, IConfigSource config)
442 { 569 {
570 InitializeExtraStats();
571
443 mesher = meshmerizer; 572 mesher = meshmerizer;
444 m_config = config; 573 m_config = config;
445 // Defaults 574 // Defaults
@@ -464,6 +593,8 @@ namespace OpenSim.Region.Physics.OdePlugin
464 IConfig physicsconfig = m_config.Configs["ODEPhysicsSettings"]; 593 IConfig physicsconfig = m_config.Configs["ODEPhysicsSettings"];
465 if (physicsconfig != null) 594 if (physicsconfig != null)
466 { 595 {
596 CollectStats = physicsconfig.GetBoolean("collect_stats", false);
597
467 gravityx = physicsconfig.GetFloat("world_gravityx", 0f); 598 gravityx = physicsconfig.GetFloat("world_gravityx", 0f);
468 gravityy = physicsconfig.GetFloat("world_gravityy", 0f); 599 gravityy = physicsconfig.GetFloat("world_gravityy", 0f);
469 gravityz = physicsconfig.GetFloat("world_gravityz", -9.8f); 600 gravityz = physicsconfig.GetFloat("world_gravityz", -9.8f);
@@ -765,6 +896,62 @@ namespace OpenSim.Region.Physics.OdePlugin
765 #region Collision Detection 896 #region Collision Detection
766 897
767 /// <summary> 898 /// <summary>
899 /// Collides two geometries.
900 /// </summary>
901 /// <returns></returns>
902 /// <param name='geom1'></param>
903 /// <param name='geom2'>/param>
904 /// <param name='maxContacts'></param>
905 /// <param name='contactsArray'></param>
906 /// <param name='contactGeomSize'></param>
907 private int CollideGeoms(
908 IntPtr geom1, IntPtr geom2, int maxContacts, Ode.NET.d.ContactGeom[] contactsArray, int contactGeomSize)
909 {
910 int count;
911
912 lock (OdeScene.UniversalColliderSyncObject)
913 {
914 // We do this inside the lock so that we don't count any delay in acquiring it
915 if (CollectStats)
916 m_nativeCollisionStartTick = Util.EnvironmentTickCount();
917
918 count = d.Collide(geom1, geom2, maxContacts, contactsArray, contactGeomSize);
919 }
920
921 // We do this outside the lock so that any waiting threads aren't held up, though the effect is probably
922 // negligable
923 if (CollectStats)
924 m_stats[ODENativeGeomCollisionFrameMsStatName]
925 += Util.EnvironmentTickCountSubtract(m_nativeCollisionStartTick);
926
927 return count;
928 }
929
930 /// <summary>
931 /// Collide two spaces or a space and a geometry.
932 /// </summary>
933 /// <param name='space1'></param>
934 /// <param name='space2'>/param>
935 /// <param name='data'></param>
936 private void CollideSpaces(IntPtr space1, IntPtr space2, IntPtr data)
937 {
938 if (CollectStats)
939 {
940 m_inCollisionTiming = true;
941 m_nativeCollisionStartTick = Util.EnvironmentTickCount();
942 }
943
944 d.SpaceCollide2(space1, space2, data, nearCallback);
945
946 if (CollectStats && m_inCollisionTiming)
947 {
948 m_stats[ODENativeSpaceCollisionFrameMsStatName]
949 += Util.EnvironmentTickCountSubtract(m_nativeCollisionStartTick);
950 m_inCollisionTiming = false;
951 }
952 }
953
954 /// <summary>
768 /// This is our near callback. A geometry is near a body 955 /// This is our near callback. A geometry is near a body
769 /// </summary> 956 /// </summary>
770 /// <param name="space">The space that contains the geoms. Remember, spaces are also geoms</param> 957 /// <param name="space">The space that contains the geoms. Remember, spaces are also geoms</param>
@@ -772,6 +959,13 @@ namespace OpenSim.Region.Physics.OdePlugin
772 /// <param name="g2">another geometry or space</param> 959 /// <param name="g2">another geometry or space</param>
773 private void near(IntPtr space, IntPtr g1, IntPtr g2) 960 private void near(IntPtr space, IntPtr g1, IntPtr g2)
774 { 961 {
962 if (CollectStats && m_inCollisionTiming)
963 {
964 m_stats[ODENativeSpaceCollisionFrameMsStatName]
965 += Util.EnvironmentTickCountSubtract(m_nativeCollisionStartTick);
966 m_inCollisionTiming = false;
967 }
968
775// m_log.DebugFormat("[PHYSICS]: Colliding {0} and {1} in {2}", g1, g2, space); 969// m_log.DebugFormat("[PHYSICS]: Colliding {0} and {1} in {2}", g1, g2, space);
776 // no lock here! It's invoked from within Simulate(), which is thread-locked 970 // no lock here! It's invoked from within Simulate(), which is thread-locked
777 971
@@ -789,7 +983,7 @@ namespace OpenSim.Region.Physics.OdePlugin
789 // contact points in the space 983 // contact points in the space
790 try 984 try
791 { 985 {
792 d.SpaceCollide2(g1, g2, IntPtr.Zero, nearCallback); 986 CollideSpaces(g1, g2, IntPtr.Zero);
793 } 987 }
794 catch (AccessViolationException) 988 catch (AccessViolationException)
795 { 989 {
@@ -832,6 +1026,7 @@ namespace OpenSim.Region.Physics.OdePlugin
832 1026
833 // Figure out how many contact points we have 1027 // Figure out how many contact points we have
834 int count = 0; 1028 int count = 0;
1029
835 try 1030 try
836 { 1031 {
837 // Colliding Geom To Geom 1032 // Colliding Geom To Geom
@@ -843,8 +1038,11 @@ namespace OpenSim.Region.Physics.OdePlugin
843 if (b1 != IntPtr.Zero && b2 != IntPtr.Zero && d.AreConnectedExcluding(b1, b2, d.JointType.Contact)) 1038 if (b1 != IntPtr.Zero && b2 != IntPtr.Zero && d.AreConnectedExcluding(b1, b2, d.JointType.Contact))
844 return; 1039 return;
845 1040
846 lock (OdeScene.UniversalColliderSyncObject) 1041 count = CollideGeoms(g1, g2, contacts.Length, contacts, d.ContactGeom.SizeOf);
847 count = d.Collide(g1, g2, contacts.Length, contacts, d.ContactGeom.SizeOf); 1042
1043 // All code after this is only relevant if we have any collisions
1044 if (count <= 0)
1045 return;
848 1046
849 if (count > contacts.Length) 1047 if (count > contacts.Length)
850 m_log.Error("[ODE SCENE]: Got " + count + " contacts when we asked for a maximum of " + contacts.Length); 1048 m_log.Error("[ODE SCENE]: Got " + count + " contacts when we asked for a maximum of " + contacts.Length);
@@ -1113,14 +1311,12 @@ namespace OpenSim.Region.Physics.OdePlugin
1113 { 1311 {
1114 _perloopContact.Add(curContact); 1312 _perloopContact.Add(curContact);
1115 1313
1116 // If we're colliding against terrain
1117 if (name1 == "Terrain" || name2 == "Terrain") 1314 if (name1 == "Terrain" || name2 == "Terrain")
1118 { 1315 {
1119 // If we're moving
1120 if ((p2.PhysicsActorType == (int) ActorTypes.Agent) && 1316 if ((p2.PhysicsActorType == (int) ActorTypes.Agent) &&
1121 (Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f)) 1317 (Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f))
1122 { 1318 {
1123 // Use the movement terrain contact 1319 // Avatar is moving on terrain, use the movement terrain contact
1124 AvatarMovementTerrainContact.geom = curContact; 1320 AvatarMovementTerrainContact.geom = curContact;
1125 1321
1126 if (m_global_contactcount < maxContactsbeforedeath) 1322 if (m_global_contactcount < maxContactsbeforedeath)
@@ -1133,7 +1329,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1133 { 1329 {
1134 if (p2.PhysicsActorType == (int)ActorTypes.Agent) 1330 if (p2.PhysicsActorType == (int)ActorTypes.Agent)
1135 { 1331 {
1136 // Use the non moving terrain contact 1332 // Avatar is standing on terrain, use the non moving terrain contact
1137 TerrainContact.geom = curContact; 1333 TerrainContact.geom = curContact;
1138 1334
1139 if (m_global_contactcount < maxContactsbeforedeath) 1335 if (m_global_contactcount < maxContactsbeforedeath)
@@ -1228,13 +1424,11 @@ namespace OpenSim.Region.Physics.OdePlugin
1228 } 1424 }
1229 else 1425 else
1230 { 1426 {
1231 // we're colliding with prim or avatar
1232 // check if we're moving
1233 if ((p2.PhysicsActorType == (int)ActorTypes.Agent)) 1427 if ((p2.PhysicsActorType == (int)ActorTypes.Agent))
1234 { 1428 {
1235 if ((Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f)) 1429 if ((Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f))
1236 { 1430 {
1237 // Use the Movement prim contact 1431 // Avatar is moving on a prim, use the Movement prim contact
1238 AvatarMovementprimContact.geom = curContact; 1432 AvatarMovementprimContact.geom = curContact;
1239 1433
1240 if (m_global_contactcount < maxContactsbeforedeath) 1434 if (m_global_contactcount < maxContactsbeforedeath)
@@ -1245,9 +1439,8 @@ namespace OpenSim.Region.Physics.OdePlugin
1245 } 1439 }
1246 else 1440 else
1247 { 1441 {
1248 // Use the non movement contact 1442 // Avatar is standing still on a prim, use the non movement contact
1249 contact.geom = curContact; 1443 contact.geom = curContact;
1250 _perloopContact.Add(curContact);
1251 1444
1252 if (m_global_contactcount < maxContactsbeforedeath) 1445 if (m_global_contactcount < maxContactsbeforedeath)
1253 { 1446 {
@@ -1355,7 +1548,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1355 break; 1548 break;
1356 } 1549 }
1357 } 1550 }
1358 //m_log.DebugFormat("[Collsion]: Depth {0}", Math.Abs(contact.depth - contactGeom.depth)); 1551 //m_log.DebugFormat("[Collision]: Depth {0}", Math.Abs(contact.depth - contactGeom.depth));
1359 //m_log.DebugFormat("[Collision]: <{0},{1},{2}>", Math.Abs(contactGeom.normal.X - contact.normal.X), Math.Abs(contactGeom.normal.Y - contact.normal.Y), Math.Abs(contactGeom.normal.Z - contact.normal.Z)); 1552 //m_log.DebugFormat("[Collision]: <{0},{1},{2}>", Math.Abs(contactGeom.normal.X - contact.normal.X), Math.Abs(contactGeom.normal.Y - contact.normal.Y), Math.Abs(contactGeom.normal.Z - contact.normal.Z));
1360 } 1553 }
1361 } 1554 }
@@ -1578,7 +1771,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1578 // and we'll run it again on all of them. 1771 // and we'll run it again on all of them.
1579 try 1772 try
1580 { 1773 {
1581 d.SpaceCollide2(space, chr.Shell, IntPtr.Zero, nearCallback); 1774 CollideSpaces(space, chr.Shell, IntPtr.Zero);
1582 } 1775 }
1583 catch (AccessViolationException) 1776 catch (AccessViolationException)
1584 { 1777 {
@@ -1593,6 +1786,12 @@ namespace OpenSim.Region.Physics.OdePlugin
1593 //} 1786 //}
1594 } 1787 }
1595 1788
1789 if (CollectStats)
1790 {
1791 m_tempAvatarCollisionsThisFrame = _perloopContact.Count;
1792 m_stats[ODEAvatarContactsStatsName] += m_tempAvatarCollisionsThisFrame;
1793 }
1794
1596 List<OdePrim> removeprims = null; 1795 List<OdePrim> removeprims = null;
1597 foreach (OdePrim chr in _activeprims) 1796 foreach (OdePrim chr in _activeprims)
1598 { 1797 {
@@ -1604,7 +1803,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1604 { 1803 {
1605 if (space != IntPtr.Zero && chr.prim_geom != IntPtr.Zero && chr.m_taintremove == false) 1804 if (space != IntPtr.Zero && chr.prim_geom != IntPtr.Zero && chr.m_taintremove == false)
1606 { 1805 {
1607 d.SpaceCollide2(space, chr.prim_geom, IntPtr.Zero, nearCallback); 1806 CollideSpaces(space, chr.prim_geom, IntPtr.Zero);
1608 } 1807 }
1609 else 1808 else
1610 { 1809 {
@@ -1625,6 +1824,9 @@ namespace OpenSim.Region.Physics.OdePlugin
1625 } 1824 }
1626 } 1825 }
1627 1826
1827 if (CollectStats)
1828 m_stats[ODEPrimContactsStatName] += _perloopContact.Count - m_tempAvatarCollisionsThisFrame;
1829
1628 if (removeprims != null) 1830 if (removeprims != null)
1629 { 1831 {
1630 foreach (OdePrim chr in removeprims) 1832 foreach (OdePrim chr in removeprims)
@@ -1706,8 +1908,8 @@ namespace OpenSim.Region.Physics.OdePlugin
1706 { 1908 {
1707// m_log.DebugFormat("[PHYSICS]: Adding {0} {1} to collision event reporting", obj.SOPName, obj.LocalID); 1909// m_log.DebugFormat("[PHYSICS]: Adding {0} {1} to collision event reporting", obj.SOPName, obj.LocalID);
1708 1910
1709 lock (_collisionEventPrimChanges) 1911 lock (m_collisionEventActorsChanges)
1710 _collisionEventPrimChanges[obj.LocalID] = obj; 1912 m_collisionEventActorsChanges[obj.LocalID] = obj;
1711 } 1913 }
1712 1914
1713 /// <summary> 1915 /// <summary>
@@ -1718,8 +1920,8 @@ namespace OpenSim.Region.Physics.OdePlugin
1718 { 1920 {
1719// m_log.DebugFormat("[PHYSICS]: Removing {0} {1} from collision event reporting", obj.SOPName, obj.LocalID); 1921// m_log.DebugFormat("[PHYSICS]: Removing {0} {1} from collision event reporting", obj.SOPName, obj.LocalID);
1720 1922
1721 lock (_collisionEventPrimChanges) 1923 lock (m_collisionEventActorsChanges)
1722 _collisionEventPrimChanges[obj.LocalID] = null; 1924 m_collisionEventActorsChanges[obj.LocalID] = null;
1723 } 1925 }
1724 1926
1725 #region Add/Remove Entities 1927 #region Add/Remove Entities
@@ -2226,7 +2428,8 @@ namespace OpenSim.Region.Physics.OdePlugin
2226 /// <param name="prim"></param> 2428 /// <param name="prim"></param>
2227 internal void RemovePrimThreadLocked(OdePrim prim) 2429 internal void RemovePrimThreadLocked(OdePrim prim)
2228 { 2430 {
2229//Console.WriteLine("RemovePrimThreadLocked " + prim.m_primName); 2431// m_log.DebugFormat("[ODE SCENE]: Removing physical prim {0} {1}", prim.Name, prim.LocalID);
2432
2230 lock (prim) 2433 lock (prim)
2231 { 2434 {
2232 RemoveCollisionEventReporting(prim); 2435 RemoveCollisionEventReporting(prim);
@@ -2682,21 +2885,23 @@ namespace OpenSim.Region.Physics.OdePlugin
2682 2885
2683 /// <summary> 2886 /// <summary>
2684 /// This is our main simulate loop 2887 /// This is our main simulate loop
2888 /// </summary>
2889 /// <remarks>
2685 /// It's thread locked by a Mutex in the scene. 2890 /// It's thread locked by a Mutex in the scene.
2686 /// It holds Collisions, it instructs ODE to step through the physical reactions 2891 /// It holds Collisions, it instructs ODE to step through the physical reactions
2687 /// It moves the objects around in memory 2892 /// It moves the objects around in memory
2688 /// It calls the methods that report back to the object owners.. (scenepresence, SceneObjectGroup) 2893 /// It calls the methods that report back to the object owners.. (scenepresence, SceneObjectGroup)
2689 /// </summary> 2894 /// </remarks>
2690 /// <param name="timeStep"></param> 2895 /// <param name="timeStep"></param>
2691 /// <returns></returns> 2896 /// <returns>The number of frames simulated over that period.</returns>
2692 public override float Simulate(float timeStep) 2897 public override float Simulate(float timeStep)
2693 { 2898 {
2899 int startFrameTick = CollectStats ? Util.EnvironmentTickCount() : 0;
2900 int tempTick = 0, tempTick2 = 0;
2901
2694 if (framecount >= int.MaxValue) 2902 if (framecount >= int.MaxValue)
2695 framecount = 0; 2903 framecount = 0;
2696 2904
2697 //if (m_worldOffset != Vector3.Zero)
2698 // return 0;
2699
2700 framecount++; 2905 framecount++;
2701 2906
2702 float fps = 0; 2907 float fps = 0;
@@ -2704,7 +2909,7 @@ namespace OpenSim.Region.Physics.OdePlugin
2704 float timeLeft = timeStep; 2909 float timeLeft = timeStep;
2705 2910
2706 //m_log.Info(timeStep.ToString()); 2911 //m_log.Info(timeStep.ToString());
2707// step_time += timeStep; 2912// step_time += timeSte
2708// 2913//
2709// // If We're loaded down by something else, 2914// // If We're loaded down by something else,
2710// // or debugging with the Visual Studio project on pause 2915// // or debugging with the Visual Studio project on pause
@@ -2725,17 +2930,17 @@ namespace OpenSim.Region.Physics.OdePlugin
2725 // We change _collisionEventPrimChanges to avoid locking _collisionEventPrim itself and causing potential 2930 // We change _collisionEventPrimChanges to avoid locking _collisionEventPrim itself and causing potential
2726 // deadlock if the collision event tries to lock something else later on which is already locked by a 2931 // deadlock if the collision event tries to lock something else later on which is already locked by a
2727 // caller that is adding or removing the collision event. 2932 // caller that is adding or removing the collision event.
2728 lock (_collisionEventPrimChanges) 2933 lock (m_collisionEventActorsChanges)
2729 { 2934 {
2730 foreach (KeyValuePair<uint, PhysicsActor> kvp in _collisionEventPrimChanges) 2935 foreach (KeyValuePair<uint, PhysicsActor> kvp in m_collisionEventActorsChanges)
2731 { 2936 {
2732 if (kvp.Value == null) 2937 if (kvp.Value == null)
2733 _collisionEventPrim.Remove(kvp.Key); 2938 m_collisionEventActors.Remove(kvp.Key);
2734 else 2939 else
2735 _collisionEventPrim[kvp.Key] = kvp.Value; 2940 m_collisionEventActors[kvp.Key] = kvp.Value;
2736 } 2941 }
2737 2942
2738 _collisionEventPrimChanges.Clear(); 2943 m_collisionEventActorsChanges.Clear();
2739 } 2944 }
2740 2945
2741 if (SupportsNINJAJoints) 2946 if (SupportsNINJAJoints)
@@ -2770,6 +2975,9 @@ namespace OpenSim.Region.Physics.OdePlugin
2770 { 2975 {
2771 try 2976 try
2772 { 2977 {
2978 if (CollectStats)
2979 tempTick = Util.EnvironmentTickCount();
2980
2773 lock (_taintedActors) 2981 lock (_taintedActors)
2774 { 2982 {
2775 foreach (OdeCharacter character in _taintedActors) 2983 foreach (OdeCharacter character in _taintedActors)
@@ -2778,6 +2986,13 @@ namespace OpenSim.Region.Physics.OdePlugin
2778 _taintedActors.Clear(); 2986 _taintedActors.Clear();
2779 } 2987 }
2780 2988
2989 if (CollectStats)
2990 {
2991 tempTick2 = Util.EnvironmentTickCount();
2992 m_stats[ODEAvatarTaintMsStatName] += Util.EnvironmentTickCountSubtract(tempTick2, tempTick);
2993 tempTick = tempTick2;
2994 }
2995
2781 lock (_taintedPrims) 2996 lock (_taintedPrims)
2782 { 2997 {
2783 foreach (OdePrim prim in _taintedPrims) 2998 foreach (OdePrim prim in _taintedPrims)
@@ -2808,6 +3023,13 @@ namespace OpenSim.Region.Physics.OdePlugin
2808 _taintedPrims.Clear(); 3023 _taintedPrims.Clear();
2809 } 3024 }
2810 3025
3026 if (CollectStats)
3027 {
3028 tempTick2 = Util.EnvironmentTickCount();
3029 m_stats[ODEPrimTaintMsStatName] += Util.EnvironmentTickCountSubtract(tempTick2, tempTick);
3030 tempTick = tempTick2;
3031 }
3032
2811 // Move characters 3033 // Move characters
2812 foreach (OdeCharacter actor in _characters) 3034 foreach (OdeCharacter actor in _characters)
2813 actor.Move(defects); 3035 actor.Move(defects);
@@ -2827,6 +3049,13 @@ namespace OpenSim.Region.Physics.OdePlugin
2827 defects.Clear(); 3049 defects.Clear();
2828 } 3050 }
2829 3051
3052 if (CollectStats)
3053 {
3054 tempTick2 = Util.EnvironmentTickCount();
3055 m_stats[ODEAvatarForcesFrameMsStatName] += Util.EnvironmentTickCountSubtract(tempTick2, tempTick);
3056 tempTick = tempTick2;
3057 }
3058
2830 // Move other active objects 3059 // Move other active objects
2831 foreach (OdePrim prim in _activeprims) 3060 foreach (OdePrim prim in _activeprims)
2832 { 3061 {
@@ -2834,15 +3063,36 @@ namespace OpenSim.Region.Physics.OdePlugin
2834 prim.Move(timeStep); 3063 prim.Move(timeStep);
2835 } 3064 }
2836 3065
3066 if (CollectStats)
3067 {
3068 tempTick2 = Util.EnvironmentTickCount();
3069 m_stats[ODEPrimForcesFrameMsStatName] += Util.EnvironmentTickCountSubtract(tempTick2, tempTick);
3070 tempTick = tempTick2;
3071 }
3072
2837 //if ((framecount % m_randomizeWater) == 0) 3073 //if ((framecount % m_randomizeWater) == 0)
2838 // randomizeWater(waterlevel); 3074 // randomizeWater(waterlevel);
2839 3075
2840 //int RayCastTimeMS = m_rayCastManager.ProcessQueuedRequests(); 3076 //int RayCastTimeMS = m_rayCastManager.ProcessQueuedRequests();
2841 m_rayCastManager.ProcessQueuedRequests(); 3077 m_rayCastManager.ProcessQueuedRequests();
2842 3078
3079 if (CollectStats)
3080 {
3081 tempTick2 = Util.EnvironmentTickCount();
3082 m_stats[ODERaycastingFrameMsStatName] += Util.EnvironmentTickCountSubtract(tempTick2, tempTick);
3083 tempTick = tempTick2;
3084 }
3085
2843 collision_optimized(); 3086 collision_optimized();
2844 3087
2845 foreach (PhysicsActor obj in _collisionEventPrim.Values) 3088 if (CollectStats)
3089 {
3090 tempTick2 = Util.EnvironmentTickCount();
3091 m_stats[ODEOtherCollisionFrameMsStatName] += Util.EnvironmentTickCountSubtract(tempTick2, tempTick);
3092 tempTick = tempTick2;
3093 }
3094
3095 foreach (PhysicsActor obj in m_collisionEventActors.Values)
2846 { 3096 {
2847// m_log.DebugFormat("[PHYSICS]: Assessing {0} {1} for collision events", obj.SOPName, obj.LocalID); 3097// m_log.DebugFormat("[PHYSICS]: Assessing {0} {1} for collision events", obj.SOPName, obj.LocalID);
2848 3098
@@ -2866,9 +3116,19 @@ namespace OpenSim.Region.Physics.OdePlugin
2866// "[PHYSICS]: Collision contacts to process this frame = {0}", m_global_contactcount); 3116// "[PHYSICS]: Collision contacts to process this frame = {0}", m_global_contactcount);
2867 3117
2868 m_global_contactcount = 0; 3118 m_global_contactcount = 0;
2869 3119
3120 if (CollectStats)
3121 {
3122 tempTick2 = Util.EnvironmentTickCount();
3123 m_stats[ODECollisionNotificationFrameMsStatName] += Util.EnvironmentTickCountSubtract(tempTick2, tempTick);
3124 tempTick = tempTick2;
3125 }
3126
2870 d.WorldQuickStep(world, ODE_STEPSIZE); 3127 d.WorldQuickStep(world, ODE_STEPSIZE);
2871 3128
3129 if (CollectStats)
3130 m_stats[ODENativeStepFrameMsStatName] += Util.EnvironmentTickCountSubtract(tempTick);
3131
2872 d.JointGroupEmpty(contactgroup); 3132 d.JointGroupEmpty(contactgroup);
2873 } 3133 }
2874 catch (Exception e) 3134 catch (Exception e)
@@ -2879,6 +3139,9 @@ namespace OpenSim.Region.Physics.OdePlugin
2879 timeLeft -= ODE_STEPSIZE; 3139 timeLeft -= ODE_STEPSIZE;
2880 } 3140 }
2881 3141
3142 if (CollectStats)
3143 tempTick = Util.EnvironmentTickCount();
3144
2882 foreach (OdeCharacter actor in _characters) 3145 foreach (OdeCharacter actor in _characters)
2883 { 3146 {
2884 if (actor.bad) 3147 if (actor.bad)
@@ -2902,6 +3165,13 @@ namespace OpenSim.Region.Physics.OdePlugin
2902 defects.Clear(); 3165 defects.Clear();
2903 } 3166 }
2904 3167
3168 if (CollectStats)
3169 {
3170 tempTick2 = Util.EnvironmentTickCount();
3171 m_stats[ODEAvatarUpdateFrameMsStatName] += Util.EnvironmentTickCountSubtract(tempTick2, tempTick);
3172 tempTick = tempTick2;
3173 }
3174
2905 //if (timeStep < 0.2f) 3175 //if (timeStep < 0.2f)
2906 3176
2907 foreach (OdePrim prim in _activeprims) 3177 foreach (OdePrim prim in _activeprims)
@@ -2915,6 +3185,9 @@ namespace OpenSim.Region.Physics.OdePlugin
2915 } 3185 }
2916 } 3186 }
2917 3187
3188 if (CollectStats)
3189 m_stats[ODEPrimUpdateFrameMsStatName] += Util.EnvironmentTickCountSubtract(tempTick);
3190
2918 //DumpJointInfo(); 3191 //DumpJointInfo();
2919 3192
2920 // Finished with all sim stepping. If requested, dump world state to file for debugging. 3193 // Finished with all sim stepping. If requested, dump world state to file for debugging.
@@ -2936,7 +3209,7 @@ namespace OpenSim.Region.Physics.OdePlugin
2936 d.WorldExportDIF(world, fname, physics_logging_append_existing_logfile, prefix); 3209 d.WorldExportDIF(world, fname, physics_logging_append_existing_logfile, prefix);
2937 } 3210 }
2938 3211
2939 latertickcount = Util.EnvironmentTickCount() - tickCountFrameRun; 3212 latertickcount = Util.EnvironmentTickCountSubtract(tickCountFrameRun);
2940 3213
2941 // OpenSimulator above does 10 fps. 10 fps = means that the main thread loop and physics 3214 // OpenSimulator above does 10 fps. 10 fps = means that the main thread loop and physics
2942 // has a max of 100 ms to run theoretically. 3215 // has a max of 100 ms to run theoretically.
@@ -2954,6 +3227,9 @@ namespace OpenSim.Region.Physics.OdePlugin
2954 } 3227 }
2955 3228
2956 tickCountFrameRun = Util.EnvironmentTickCount(); 3229 tickCountFrameRun = Util.EnvironmentTickCount();
3230
3231 if (CollectStats)
3232 m_stats[ODETotalFrameMsStatName] += Util.EnvironmentTickCountSubtract(startFrameTick);
2957 } 3233 }
2958 3234
2959 return fps; 3235 return fps;
@@ -3189,7 +3465,7 @@ namespace OpenSim.Region.Physics.OdePlugin
3189 public override bool IsThreaded 3465 public override bool IsThreaded
3190 { 3466 {
3191 // for now we won't be multithreaded 3467 // for now we won't be multithreaded
3192 get { return (false); } 3468 get { return false; }
3193 } 3469 }
3194 3470
3195 #region ODE Specific Terrain Fixes 3471 #region ODE Specific Terrain Fixes
@@ -3765,26 +4041,19 @@ namespace OpenSim.Region.Physics.OdePlugin
3765 4041
3766 public override Dictionary<uint, float> GetTopColliders() 4042 public override Dictionary<uint, float> GetTopColliders()
3767 { 4043 {
3768 Dictionary<uint, float> returncolliders = new Dictionary<uint, float>(); 4044 Dictionary<uint, float> topColliders;
3769 int cnt = 0; 4045
3770 lock (_prims) 4046 lock (_prims)
3771 { 4047 {
3772 foreach (OdePrim prm in _prims) 4048 List<OdePrim> orderedPrims = new List<OdePrim>(_prims);
3773 { 4049 orderedPrims.OrderByDescending(p => p.CollisionScore).Take(25);
3774 if (prm.CollisionScore > 0) 4050 topColliders = orderedPrims.ToDictionary(p => p.LocalID, p => p.CollisionScore);
3775 { 4051
3776 returncolliders.Add(prm.LocalID, prm.CollisionScore); 4052 foreach (OdePrim p in _prims)
3777 cnt++; 4053 p.CollisionScore = 0;
3778 prm.CollisionScore = 0f;
3779 if (cnt > 25)
3780 {
3781 break;
3782 }
3783 }
3784 }
3785 } 4054 }
3786 4055
3787 return returncolliders; 4056 return topColliders;
3788 } 4057 }
3789 4058
3790 public override bool SupportsRayCast() 4059 public override bool SupportsRayCast()
@@ -3954,5 +4223,52 @@ namespace OpenSim.Region.Physics.OdePlugin
3954 ds.SetViewpoint(ref xyz, ref hpr); 4223 ds.SetViewpoint(ref xyz, ref hpr);
3955 } 4224 }
3956#endif 4225#endif
4226
4227 public override Dictionary<string, float> GetStats()
4228 {
4229 if (!CollectStats)
4230 return null;
4231
4232 Dictionary<string, float> returnStats;
4233
4234 lock (OdeLock)
4235 {
4236 returnStats = new Dictionary<string, float>(m_stats);
4237
4238 // FIXME: This is a SUPER DUMB HACK until we can establish stats that aren't subject to a division by
4239 // 3 from the SimStatsReporter.
4240 returnStats[ODETotalAvatarsStatName] = _characters.Count * 3;
4241 returnStats[ODETotalPrimsStatName] = _prims.Count * 3;
4242 returnStats[ODEActivePrimsStatName] = _activeprims.Count * 3;
4243
4244 InitializeExtraStats();
4245 }
4246
4247 returnStats[ODEOtherCollisionFrameMsStatName]
4248 = returnStats[ODEOtherCollisionFrameMsStatName]
4249 - returnStats[ODENativeSpaceCollisionFrameMsStatName]
4250 - returnStats[ODENativeGeomCollisionFrameMsStatName];
4251
4252 return returnStats;
4253 }
4254
4255 private void InitializeExtraStats()
4256 {
4257 m_stats[ODETotalFrameMsStatName] = 0;
4258 m_stats[ODEAvatarTaintMsStatName] = 0;
4259 m_stats[ODEPrimTaintMsStatName] = 0;
4260 m_stats[ODEAvatarForcesFrameMsStatName] = 0;
4261 m_stats[ODEPrimForcesFrameMsStatName] = 0;
4262 m_stats[ODERaycastingFrameMsStatName] = 0;
4263 m_stats[ODENativeStepFrameMsStatName] = 0;
4264 m_stats[ODENativeSpaceCollisionFrameMsStatName] = 0;
4265 m_stats[ODENativeGeomCollisionFrameMsStatName] = 0;
4266 m_stats[ODEOtherCollisionFrameMsStatName] = 0;
4267 m_stats[ODECollisionNotificationFrameMsStatName] = 0;
4268 m_stats[ODEAvatarContactsStatsName] = 0;
4269 m_stats[ODEPrimContactsStatName] = 0;
4270 m_stats[ODEAvatarUpdateFrameMsStatName] = 0;
4271 m_stats[ODEPrimUpdateFrameMsStatName] = 0;
4272 }
3957 } 4273 }
3958} \ No newline at end of file 4274} \ No newline at end of file