aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/PhysicsModules
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/PhysicsModules')
-rw-r--r--OpenSim/Region/PhysicsModules/BasicPhysics/BasicPhysicsActor.cs3
-rw-r--r--OpenSim/Region/PhysicsModules/BasicPhysics/BasicPhysicsPrim.cs3
-rw-r--r--OpenSim/Region/PhysicsModules/BasicPhysics/BasicPhysicsScene.cs2
-rw-r--r--OpenSim/Region/PhysicsModules/BulletS/BSCharacter.cs2
-rwxr-xr-xOpenSim/Region/PhysicsModules/BulletS/BSPhysObject.cs2
-rw-r--r--OpenSim/Region/PhysicsModules/BulletS/BSPrim.cs69
-rw-r--r--OpenSim/Region/PhysicsModules/BulletS/BSScene.cs5
-rwxr-xr-xOpenSim/Region/PhysicsModules/BulletS/BSShapeCollection.cs1
-rwxr-xr-xOpenSim/Region/PhysicsModules/BulletS/BSShapes.cs10
-rwxr-xr-xOpenSim/Region/PhysicsModules/BulletS/Tests/BulletSimTestsUtil.cs4
-rw-r--r--OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/CTri.cs2
-rw-r--r--OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/Concavity.cs2
-rw-r--r--OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/ConvexBuilder.cs2
-rw-r--r--OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/ConvexDecomposition.cs2
-rw-r--r--OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/ConvexResult.cs2
-rw-r--r--OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/HullClasses.cs2
-rw-r--r--OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/HullTriangle.cs2
-rw-r--r--OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/HullUtils.cs2
-rw-r--r--OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/Plane.cs2
-rw-r--r--OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/PlaneTri.cs2
-rw-r--r--OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/Quaternion.cs2
-rw-r--r--OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/SplitPlane.cs2
-rw-r--r--OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/VertexLookup.cs2
-rw-r--r--OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/float2.cs2
-rw-r--r--OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/float3.cs2
-rw-r--r--OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/float3x3.cs2
-rw-r--r--OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/float4.cs2
-rw-r--r--OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/float4x4.cs2
-rw-r--r--OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/int3.cs2
-rw-r--r--OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/int4.cs2
-rw-r--r--OpenSim/Region/PhysicsModules/Meshing/Meshmerizer/HelperTypes.cs2
-rw-r--r--OpenSim/Region/PhysicsModules/Meshing/Meshmerizer/Mesh.cs81
-rw-r--r--OpenSim/Region/PhysicsModules/Meshing/Meshmerizer/Meshmerizer.cs19
-rw-r--r--OpenSim/Region/PhysicsModules/Meshing/Meshmerizer/SculptMap.cs62
-rw-r--r--OpenSim/Region/PhysicsModules/Meshing/Properties/AssemblyInfo.cs4
-rw-r--r--OpenSim/Region/PhysicsModules/Meshing/ZeroMesher.cs25
-rw-r--r--OpenSim/Region/PhysicsModules/Ode/ODECharacter.cs4
-rw-r--r--OpenSim/Region/PhysicsModules/Ode/ODEModule.cs85
-rw-r--r--OpenSim/Region/PhysicsModules/Ode/ODEPrim.cs571
-rw-r--r--OpenSim/Region/PhysicsModules/Ode/ODERayCastRequestManager.cs11
-rw-r--r--OpenSim/Region/PhysicsModules/Ode/OdeScene.cs390
-rw-r--r--OpenSim/Region/PhysicsModules/Ode/Tests/ODETestClass.cs18
-rw-r--r--OpenSim/Region/PhysicsModules/POS/POSCharacter.cs3
-rw-r--r--OpenSim/Region/PhysicsModules/POS/POSPrim.cs5
-rw-r--r--OpenSim/Region/PhysicsModules/POS/POSScene.cs2
-rw-r--r--OpenSim/Region/PhysicsModules/SharedBase/IMesher.cs29
-rw-r--r--OpenSim/Region/PhysicsModules/SharedBase/PhysicsActor.cs283
-rw-r--r--OpenSim/Region/PhysicsModules/SharedBase/PhysicsScene.cs66
-rw-r--r--OpenSim/Region/PhysicsModules/SharedBase/VehicleConstants.cs45
-rw-r--r--OpenSim/Region/PhysicsModules/ubOde/ODEApi.cs2024
-rw-r--r--OpenSim/Region/PhysicsModules/ubOde/ODECharacter.cs1978
-rw-r--r--OpenSim/Region/PhysicsModules/ubOde/ODEDynamics.cs1096
-rw-r--r--OpenSim/Region/PhysicsModules/ubOde/ODEMeshWorker.cs933
-rw-r--r--OpenSim/Region/PhysicsModules/ubOde/ODEModule.cs97
-rw-r--r--OpenSim/Region/PhysicsModules/ubOde/ODEPrim.cs3962
-rw-r--r--OpenSim/Region/PhysicsModules/ubOde/ODERayCastRequestManager.cs680
-rw-r--r--OpenSim/Region/PhysicsModules/ubOde/ODEScene.cs2830
-rw-r--r--OpenSim/Region/PhysicsModules/ubOde/ODESitAvatar.cs356
-rw-r--r--OpenSim/Region/PhysicsModules/ubOde/Properties/AssemblyInfo.cs61
-rw-r--r--OpenSim/Region/PhysicsModules/ubOdeMeshing/HelperTypes.cs340
-rw-r--r--OpenSim/Region/PhysicsModules/ubOdeMeshing/Mesh.cs633
-rw-r--r--OpenSim/Region/PhysicsModules/ubOdeMeshing/Meshmerizer.cs1465
-rw-r--r--OpenSim/Region/PhysicsModules/ubOdeMeshing/PrimMesher.cs1708
-rw-r--r--OpenSim/Region/PhysicsModules/ubOdeMeshing/Properties/AssemblyInfo.cs36
-rw-r--r--OpenSim/Region/PhysicsModules/ubOdeMeshing/SculptMap.cs244
-rw-r--r--OpenSim/Region/PhysicsModules/ubOdeMeshing/SculptMesh.cs220
66 files changed, 19681 insertions, 828 deletions
diff --git a/OpenSim/Region/PhysicsModules/BasicPhysics/BasicPhysicsActor.cs b/OpenSim/Region/PhysicsModules/BasicPhysics/BasicPhysicsActor.cs
index e7b30ba..3944047 100644
--- a/OpenSim/Region/PhysicsModules/BasicPhysics/BasicPhysicsActor.cs
+++ b/OpenSim/Region/PhysicsModules/BasicPhysics/BasicPhysicsActor.cs
@@ -211,7 +211,7 @@ namespace OpenSim.Region.PhysicsModule.BasicPhysics
211 { 211 {
212 } 212 }
213 213
214 public override void LockAngularMotion(Vector3 axis) 214 public override void LockAngularMotion(byte axislocks)
215 { 215 {
216 } 216 }
217 217
@@ -254,6 +254,7 @@ namespace OpenSim.Region.PhysicsModule.BasicPhysics
254 254
255 public override bool PIDHoverActive 255 public override bool PIDHoverActive
256 { 256 {
257 get { return false; }
257 set { return; } 258 set { return; }
258 } 259 }
259 260
diff --git a/OpenSim/Region/PhysicsModules/BasicPhysics/BasicPhysicsPrim.cs b/OpenSim/Region/PhysicsModules/BasicPhysics/BasicPhysicsPrim.cs
index 5383f1b..d2cd028 100644
--- a/OpenSim/Region/PhysicsModules/BasicPhysics/BasicPhysicsPrim.cs
+++ b/OpenSim/Region/PhysicsModules/BasicPhysics/BasicPhysicsPrim.cs
@@ -224,7 +224,7 @@ namespace OpenSim.Region.PhysicsModule.BasicPhysics
224 { 224 {
225 } 225 }
226 226
227 public override void LockAngularMotion(Vector3 axis) 227 public override void LockAngularMotion(byte axislocks)
228 { 228 {
229 } 229 }
230 230
@@ -267,6 +267,7 @@ namespace OpenSim.Region.PhysicsModule.BasicPhysics
267 267
268 public override bool PIDHoverActive 268 public override bool PIDHoverActive
269 { 269 {
270 get { return false; }
270 set { return; } 271 set { return; }
271 } 272 }
272 273
diff --git a/OpenSim/Region/PhysicsModules/BasicPhysics/BasicPhysicsScene.cs b/OpenSim/Region/PhysicsModules/BasicPhysics/BasicPhysicsScene.cs
index 20b337a..ac2c1f3 100644
--- a/OpenSim/Region/PhysicsModules/BasicPhysics/BasicPhysicsScene.cs
+++ b/OpenSim/Region/PhysicsModules/BasicPhysics/BasicPhysicsScene.cs
@@ -220,7 +220,7 @@ namespace OpenSim.Region.PhysicsModule.BasicPhysics
220 actor.Velocity = actorVelocity; 220 actor.Velocity = actorVelocity;
221 } 221 }
222 222
223 return fps; 223 return 1.0f;
224 } 224 }
225 225
226 public override void GetResults() 226 public override void GetResults()
diff --git a/OpenSim/Region/PhysicsModules/BulletS/BSCharacter.cs b/OpenSim/Region/PhysicsModules/BulletS/BSCharacter.cs
index 83fc3a6..989b339 100644
--- a/OpenSim/Region/PhysicsModules/BulletS/BSCharacter.cs
+++ b/OpenSim/Region/PhysicsModules/BulletS/BSCharacter.cs
@@ -300,7 +300,7 @@ public sealed class BSCharacter : BSPhysObject
300 } 300 }
301 301
302 302
303 public override void LockAngularMotion(OMV.Vector3 axis) { return; } 303 public override void LockAngularMotion(byte axislocks) { return; }
304 304
305 public override OMV.Vector3 Position { 305 public override OMV.Vector3 Position {
306 get { 306 get {
diff --git a/OpenSim/Region/PhysicsModules/BulletS/BSPhysObject.cs b/OpenSim/Region/PhysicsModules/BulletS/BSPhysObject.cs
index da3fc18..c3eb776 100755
--- a/OpenSim/Region/PhysicsModules/BulletS/BSPhysObject.cs
+++ b/OpenSim/Region/PhysicsModules/BulletS/BSPhysObject.cs
@@ -268,7 +268,7 @@ public abstract class BSPhysObject : PhysicsActor
268 public float MoveToTargetTau { get; set; } 268 public float MoveToTargetTau { get; set; }
269 269
270 // Used for llSetHoverHeight and maybe vehicle height. Hover Height will override MoveTo target's Z 270 // Used for llSetHoverHeight and maybe vehicle height. Hover Height will override MoveTo target's Z
271 public override bool PIDHoverActive { set { HoverActive = value; } } 271 public override bool PIDHoverActive {get {return HoverActive;} set { HoverActive = value; } }
272 public override float PIDHoverHeight { set { HoverHeight = value; } } 272 public override float PIDHoverHeight { set { HoverHeight = value; } }
273 public override PIDHoverType PIDHoverType { set { HoverType = value; } } 273 public override PIDHoverType PIDHoverType { set { HoverType = value; } }
274 public override float PIDHoverTau { set { HoverTau = value; } } 274 public override float PIDHoverTau { set { HoverTau = value; } }
diff --git a/OpenSim/Region/PhysicsModules/BulletS/BSPrim.cs b/OpenSim/Region/PhysicsModules/BulletS/BSPrim.cs
index 6f27ac7..1d552eb 100644
--- a/OpenSim/Region/PhysicsModules/BulletS/BSPrim.cs
+++ b/OpenSim/Region/PhysicsModules/BulletS/BSPrim.cs
@@ -33,7 +33,7 @@ using log4net;
33using OMV = OpenMetaverse; 33using OMV = OpenMetaverse;
34using OpenSim.Framework; 34using OpenSim.Framework;
35using OpenSim.Region.PhysicsModules.SharedBase; 35using OpenSim.Region.PhysicsModules.SharedBase;
36using OpenSim.Region.PhysicsModule.ConvexDecompositionDotNet; 36using OpenSim.Region.PhysicsModules.ConvexDecompositionDotNet;
37 37
38namespace OpenSim.Region.PhysicsModule.BulletS 38namespace OpenSim.Region.PhysicsModule.BulletS
39{ 39{
@@ -280,20 +280,20 @@ public class BSPrim : BSPhysObject
280 }); 280 });
281 } 281 }
282 282
283 public override void LockAngularMotion(OMV.Vector3 axis) 283 public override void LockAngularMotion(byte axislocks)
284 { 284 {
285 DetailLog("{0},BSPrim.LockAngularMotion,call,axis={1}", LocalID, axis); 285 DetailLog("{0},BSPrim.LockAngularMotion,call,axis={1}", LocalID, axislocks);
286 286
287 ApplyAxisLimits(ExtendedPhysics.PHYS_AXIS_UNLOCK_ANGULAR, 0f, 0f); 287 ApplyAxisLimits(ExtendedPhysics.PHYS_AXIS_UNLOCK_ANGULAR, 0f, 0f);
288 if (axis.X != 1) 288 if ((axislocks & 0x02) != 0)
289 { 289 {
290 ApplyAxisLimits(ExtendedPhysics.PHYS_AXIS_LOCK_ANGULAR_X, 0f, 0f); 290 ApplyAxisLimits(ExtendedPhysics.PHYS_AXIS_LOCK_ANGULAR_X, 0f, 0f);
291 } 291 }
292 if (axis.Y != 1) 292 if ((axislocks & 0x04) != 0)
293 { 293 {
294 ApplyAxisLimits(ExtendedPhysics.PHYS_AXIS_LOCK_ANGULAR_Y, 0f, 0f); 294 ApplyAxisLimits(ExtendedPhysics.PHYS_AXIS_LOCK_ANGULAR_Y, 0f, 0f);
295 } 295 }
296 if (axis.Z != 1) 296 if ((axislocks & 0x08) != 0)
297 { 297 {
298 ApplyAxisLimits(ExtendedPhysics.PHYS_AXIS_LOCK_ANGULAR_Z, 0f, 0f); 298 ApplyAxisLimits(ExtendedPhysics.PHYS_AXIS_LOCK_ANGULAR_Z, 0f, 0f);
299 } 299 }
@@ -647,6 +647,59 @@ public class BSPrim : BSPhysObject
647 }); 647 });
648 } 648 }
649 649
650 public override void SetVehicle(object pvdata)
651 {
652 PhysScene.TaintedObject(LocalID, "BSPrim.SetVehicle", delegate ()
653 {
654 BSDynamics vehicleActor = GetVehicleActor(true /* createIfNone */);
655 if (vehicleActor != null && (pvdata is VehicleData) )
656 {
657 VehicleData vdata = (VehicleData)pvdata;
658 // vehicleActor.ProcessSetVehicle((VehicleData)vdata);
659
660 vehicleActor.ProcessTypeChange(vdata.m_type);
661 vehicleActor.ProcessVehicleFlags(-1, false);
662 vehicleActor.ProcessVehicleFlags((int)vdata.m_flags, false);
663
664 // Linear properties
665 vehicleActor.ProcessVectorVehicleParam(Vehicle.LINEAR_MOTOR_DIRECTION, vdata.m_linearMotorDirection);
666 vehicleActor.ProcessVectorVehicleParam(Vehicle.LINEAR_FRICTION_TIMESCALE, vdata.m_linearFrictionTimescale);
667 vehicleActor.ProcessFloatVehicleParam(Vehicle.LINEAR_MOTOR_DECAY_TIMESCALE, vdata.m_linearMotorDecayTimescale);
668 vehicleActor.ProcessFloatVehicleParam(Vehicle.LINEAR_MOTOR_TIMESCALE, vdata.m_linearMotorTimescale);
669 vehicleActor.ProcessVectorVehicleParam(Vehicle.LINEAR_MOTOR_OFFSET, vdata.m_linearMotorOffset);
670
671 //Angular properties
672 vehicleActor.ProcessVectorVehicleParam(Vehicle.ANGULAR_MOTOR_DIRECTION, vdata.m_angularMotorDirection);
673 vehicleActor.ProcessFloatVehicleParam(Vehicle.ANGULAR_MOTOR_TIMESCALE, vdata.m_angularMotorTimescale);
674 vehicleActor.ProcessFloatVehicleParam(Vehicle.ANGULAR_MOTOR_DECAY_TIMESCALE, vdata.m_angularMotorDecayTimescale);
675 vehicleActor.ProcessVectorVehicleParam(Vehicle.ANGULAR_FRICTION_TIMESCALE, vdata.m_angularFrictionTimescale);
676
677 //Deflection properties
678 vehicleActor.ProcessFloatVehicleParam(Vehicle.ANGULAR_DEFLECTION_EFFICIENCY, vdata.m_angularDeflectionEfficiency);
679 vehicleActor.ProcessFloatVehicleParam(Vehicle.ANGULAR_DEFLECTION_TIMESCALE, vdata.m_angularDeflectionTimescale);
680 vehicleActor.ProcessFloatVehicleParam(Vehicle.LINEAR_DEFLECTION_EFFICIENCY, vdata.m_linearDeflectionEfficiency);
681 vehicleActor.ProcessFloatVehicleParam(Vehicle.LINEAR_DEFLECTION_TIMESCALE, vdata.m_linearDeflectionTimescale);
682
683 //Banking properties
684 vehicleActor.ProcessFloatVehicleParam(Vehicle.BANKING_EFFICIENCY, vdata.m_bankingEfficiency);
685 vehicleActor.ProcessFloatVehicleParam(Vehicle.BANKING_MIX, vdata.m_bankingMix);
686 vehicleActor.ProcessFloatVehicleParam(Vehicle.BANKING_TIMESCALE, vdata.m_bankingTimescale);
687
688 //Hover and Buoyancy properties
689 vehicleActor.ProcessFloatVehicleParam(Vehicle.HOVER_HEIGHT, vdata.m_VhoverHeight);
690 vehicleActor.ProcessFloatVehicleParam(Vehicle.HOVER_EFFICIENCY, vdata.m_VhoverEfficiency);
691 vehicleActor.ProcessFloatVehicleParam(Vehicle.HOVER_TIMESCALE, vdata.m_VhoverTimescale);
692 vehicleActor.ProcessFloatVehicleParam(Vehicle.BUOYANCY, vdata.m_VehicleBuoyancy);
693
694 //Attractor properties
695 vehicleActor.ProcessFloatVehicleParam(Vehicle.VERTICAL_ATTRACTION_EFFICIENCY, vdata.m_verticalAttractionEfficiency);
696 vehicleActor.ProcessFloatVehicleParam(Vehicle.VERTICAL_ATTRACTION_TIMESCALE, vdata.m_verticalAttractionTimescale);
697
698 vehicleActor.ProcessRotationVehicleParam(Vehicle.REFERENCE_FRAME, vdata.m_referenceFrame);
699 }
700 });
701 }
702
650 // Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more 703 // Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more
651 public override void SetVolumeDetect(int param) { 704 public override void SetVolumeDetect(int param) {
652 bool newValue = (param != 0); 705 bool newValue = (param != 0);
@@ -1173,6 +1226,10 @@ public class BSPrim : BSPhysObject
1173 // Used for llSetHoverHeight and maybe vehicle height 1226 // Used for llSetHoverHeight and maybe vehicle height
1174 // Hover Height will override MoveTo target's Z 1227 // Hover Height will override MoveTo target's Z
1175 public override bool PIDHoverActive { 1228 public override bool PIDHoverActive {
1229 get
1230 {
1231 return base.HoverActive;
1232 }
1176 set { 1233 set {
1177 base.HoverActive = value; 1234 base.HoverActive = value;
1178 EnableActor(HoverActive, HoverActorName, delegate() 1235 EnableActor(HoverActive, HoverActorName, delegate()
diff --git a/OpenSim/Region/PhysicsModules/BulletS/BSScene.cs b/OpenSim/Region/PhysicsModules/BulletS/BSScene.cs
index 452ce55..b2d5e47 100644
--- a/OpenSim/Region/PhysicsModules/BulletS/BSScene.cs
+++ b/OpenSim/Region/PhysicsModules/BulletS/BSScene.cs
@@ -762,7 +762,8 @@ namespace OpenSim.Region.PhysicsModule.BulletS
762 // The physics engine returns the number of milliseconds it simulated this call. 762 // The physics engine returns the number of milliseconds it simulated this call.
763 // These are summed and normalized to one second and divided by 1000 to give the reported physics FPS. 763 // These are summed and normalized to one second and divided by 1000 to give the reported physics FPS.
764 // Multiply by a fixed nominal frame rate to give a rate similar to the simulator (usually 55). 764 // Multiply by a fixed nominal frame rate to give a rate similar to the simulator (usually 55).
765 m_simulatedTime += (float)numSubSteps * m_fixedTimeStep * 1000f * NominalFrameRate; 765// m_simulatedTime += (float)numSubSteps * m_fixedTimeStep * 1000f * NominalFrameRate;
766 m_simulatedTime += (float)numSubSteps * m_fixedTimeStep;
766 } 767 }
767 768
768 // Called by a BSPhysObject to note that it has changed properties and this information 769 // Called by a BSPhysObject to note that it has changed properties and this information
@@ -849,7 +850,7 @@ namespace OpenSim.Region.PhysicsModule.BulletS
849 850
850 // Return the framerate simulated to give the above returned results. 851 // Return the framerate simulated to give the above returned results.
851 // (Race condition here but this is just bookkeeping so rare mistakes do not merit a lock). 852 // (Race condition here but this is just bookkeeping so rare mistakes do not merit a lock).
852 float simTime = m_simulatedTime; 853 float simTime = m_simulatedTime / timeStep;
853 m_simulatedTime = 0f; 854 m_simulatedTime = 0f;
854 return simTime; 855 return simTime;
855 } 856 }
diff --git a/OpenSim/Region/PhysicsModules/BulletS/BSShapeCollection.cs b/OpenSim/Region/PhysicsModules/BulletS/BSShapeCollection.cs
index b100273..4ec6f51 100755
--- a/OpenSim/Region/PhysicsModules/BulletS/BSShapeCollection.cs
+++ b/OpenSim/Region/PhysicsModules/BulletS/BSShapeCollection.cs
@@ -30,7 +30,6 @@ using System.Text;
30using OMV = OpenMetaverse; 30using OMV = OpenMetaverse;
31using OpenSim.Framework; 31using OpenSim.Framework;
32using OpenSim.Region.PhysicsModules.SharedBase; 32using OpenSim.Region.PhysicsModules.SharedBase;
33using OpenSim.Region.PhysicsModule.ConvexDecompositionDotNet;
34 33
35namespace OpenSim.Region.PhysicsModule.BulletS 34namespace OpenSim.Region.PhysicsModule.BulletS
36{ 35{
diff --git a/OpenSim/Region/PhysicsModules/BulletS/BSShapes.cs b/OpenSim/Region/PhysicsModules/BulletS/BSShapes.cs
index 086a412..e791b27 100755
--- a/OpenSim/Region/PhysicsModules/BulletS/BSShapes.cs
+++ b/OpenSim/Region/PhysicsModules/BulletS/BSShapes.cs
@@ -31,8 +31,8 @@ using System.Text;
31 31
32using OpenSim.Framework; 32using OpenSim.Framework;
33using OpenSim.Region.PhysicsModules.SharedBase; 33using OpenSim.Region.PhysicsModules.SharedBase;
34using OpenSim.Region.PhysicsModules.Meshing; 34using OpenSim.Region.PhysicsModule.Meshing;
35using OpenSim.Region.PhysicsModule.ConvexDecompositionDotNet; 35using OpenSim.Region.PhysicsModules.ConvexDecompositionDotNet;
36 36
37using OMV = OpenMetaverse; 37using OMV = OpenMetaverse;
38 38
@@ -555,7 +555,9 @@ public class BSShapeMesh : BSShape
555 { 555 {
556 meshData = physicsScene.mesher.CreateMesh(prim.PhysObjectName, pbs, size, lod, 556 meshData = physicsScene.mesher.CreateMesh(prim.PhysObjectName, pbs, size, lod,
557 false, // say it is not physical so a bounding box is not built 557 false, // say it is not physical so a bounding box is not built
558 false // do not cache the mesh and do not use previously built versions 558 false, // do not cache the mesh and do not use previously built versions
559 false,
560 false
559 ); 561 );
560 } 562 }
561 563
@@ -712,7 +714,7 @@ public class BSShapeHull : BSShape
712 lock (physicsScene.mesher) 714 lock (physicsScene.mesher)
713 { 715 {
714 // Pass true for physicalness as this prevents the creation of bounding box which is not needed 716 // Pass true for physicalness as this prevents the creation of bounding box which is not needed
715 meshData = physicsScene.mesher.CreateMesh(prim.PhysObjectName, pbs, size, lod, true /* isPhysical */, false /* shouldCache */); 717 meshData = physicsScene.mesher.CreateMesh(prim.PhysObjectName, pbs, size, lod, true /* isPhysical */, false /* shouldCache */, false, false);
716 718
717 // If we should use the asset's hull info, fetch it out of the locked mesher 719 // If we should use the asset's hull info, fetch it out of the locked mesher
718 if (meshData != null && BSParam.ShouldUseAssetHulls) 720 if (meshData != null && BSParam.ShouldUseAssetHulls)
diff --git a/OpenSim/Region/PhysicsModules/BulletS/Tests/BulletSimTestsUtil.cs b/OpenSim/Region/PhysicsModules/BulletS/Tests/BulletSimTestsUtil.cs
index 4eeea4d..109e19c 100755
--- a/OpenSim/Region/PhysicsModules/BulletS/Tests/BulletSimTestsUtil.cs
+++ b/OpenSim/Region/PhysicsModules/BulletS/Tests/BulletSimTestsUtil.cs
@@ -34,7 +34,7 @@ using Nini.Config;
34 34
35using OpenSim.Framework; 35using OpenSim.Framework;
36using OpenSim.Region.PhysicsModules.SharedBase; 36using OpenSim.Region.PhysicsModules.SharedBase;
37using OpenSim.Region.PhysicsModules.Meshing; 37using OpenSim.Region.PhysicsModule.Meshing;
38using OpenSim.Region.Framework.Interfaces; 38using OpenSim.Region.Framework.Interfaces;
39 39
40using OpenMetaverse; 40using OpenMetaverse;
@@ -86,7 +86,7 @@ public static class BulletSimTestsUtil
86 info.RegionSizeX = info.RegionSizeY = info.RegionSizeZ = Constants.RegionSize; 86 info.RegionSizeX = info.RegionSizeY = info.RegionSizeZ = Constants.RegionSize;
87 OpenSim.Region.Framework.Scenes.Scene scene = new OpenSim.Region.Framework.Scenes.Scene(info); 87 OpenSim.Region.Framework.Scenes.Scene scene = new OpenSim.Region.Framework.Scenes.Scene(info);
88 88
89 IMesher mesher = new OpenSim.Region.PhysicsModules.Meshing.Meshmerizer(); 89 IMesher mesher = new OpenSim.Region.PhysicsModule.Meshing.Meshmerizer();
90 INonSharedRegionModule mod = mesher as INonSharedRegionModule; 90 INonSharedRegionModule mod = mesher as INonSharedRegionModule;
91 mod.Initialise(openSimINI); 91 mod.Initialise(openSimINI);
92 mod.AddRegion(scene); 92 mod.AddRegion(scene);
diff --git a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/CTri.cs b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/CTri.cs
index 7ad689e..3d81439 100644
--- a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/CTri.cs
+++ b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/CTri.cs
@@ -28,7 +28,7 @@
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30 30
31namespace OpenSim.Region.PhysicsModule.ConvexDecompositionDotNet 31namespace OpenSim.Region.PhysicsModules.ConvexDecompositionDotNet
32{ 32{
33 public class Wpoint 33 public class Wpoint
34 { 34 {
diff --git a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/Concavity.cs b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/Concavity.cs
index 4140d25..6a98535 100644
--- a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/Concavity.cs
+++ b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/Concavity.cs
@@ -29,7 +29,7 @@ using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Text; 30using System.Text;
31 31
32namespace OpenSim.Region.PhysicsModule.ConvexDecompositionDotNet 32namespace OpenSim.Region.PhysicsModules.ConvexDecompositionDotNet
33{ 33{
34 public static class Concavity 34 public static class Concavity
35 { 35 {
diff --git a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/ConvexBuilder.cs b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/ConvexBuilder.cs
index 70c3a2b..4480036 100644
--- a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/ConvexBuilder.cs
+++ b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/ConvexBuilder.cs
@@ -29,7 +29,7 @@ using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Diagnostics; 30using System.Diagnostics;
31 31
32namespace OpenSim.Region.PhysicsModule.ConvexDecompositionDotNet 32namespace OpenSim.Region.PhysicsModules.ConvexDecompositionDotNet
33{ 33{
34 public class DecompDesc 34 public class DecompDesc
35 { 35 {
diff --git a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/ConvexDecomposition.cs b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/ConvexDecomposition.cs
index 5046bce..e6dc98a 100644
--- a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/ConvexDecomposition.cs
+++ b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/ConvexDecomposition.cs
@@ -29,7 +29,7 @@ using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Diagnostics; 30using System.Diagnostics;
31 31
32namespace OpenSim.Region.PhysicsModule.ConvexDecompositionDotNet 32namespace OpenSim.Region.PhysicsModules.ConvexDecompositionDotNet
33{ 33{
34 public delegate void ConvexDecompositionCallback(ConvexResult result); 34 public delegate void ConvexDecompositionCallback(ConvexResult result);
35 35
diff --git a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/ConvexResult.cs b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/ConvexResult.cs
index 44e3e50..09129ed 100644
--- a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/ConvexResult.cs
+++ b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/ConvexResult.cs
@@ -28,7 +28,7 @@
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30 30
31namespace OpenSim.Region.PhysicsModule.ConvexDecompositionDotNet 31namespace OpenSim.Region.PhysicsModules.ConvexDecompositionDotNet
32{ 32{
33 public class ConvexResult 33 public class ConvexResult
34 { 34 {
diff --git a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/HullClasses.cs b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/HullClasses.cs
index 8a0164e..7d342d1 100644
--- a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/HullClasses.cs
+++ b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/HullClasses.cs
@@ -28,7 +28,7 @@
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30 30
31namespace OpenSim.Region.PhysicsModule.ConvexDecompositionDotNet 31namespace OpenSim.Region.PhysicsModules.ConvexDecompositionDotNet
32{ 32{
33 public class HullResult 33 public class HullResult
34 { 34 {
diff --git a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/HullTriangle.cs b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/HullTriangle.cs
index d3f0052..66457ac 100644
--- a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/HullTriangle.cs
+++ b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/HullTriangle.cs
@@ -29,7 +29,7 @@ using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Diagnostics; 30using System.Diagnostics;
31 31
32namespace OpenSim.Region.PhysicsModule.ConvexDecompositionDotNet 32namespace OpenSim.Region.PhysicsModules.ConvexDecompositionDotNet
33{ 33{
34 public class HullTriangle : int3 34 public class HullTriangle : int3
35 { 35 {
diff --git a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/HullUtils.cs b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/HullUtils.cs
index 3903254..b0bbfb9 100644
--- a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/HullUtils.cs
+++ b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/HullUtils.cs
@@ -29,7 +29,7 @@ using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Diagnostics; 30using System.Diagnostics;
31 31
32namespace OpenSim.Region.PhysicsModule.ConvexDecompositionDotNet 32namespace OpenSim.Region.PhysicsModules.ConvexDecompositionDotNet
33{ 33{
34 public static class HullUtils 34 public static class HullUtils
35 { 35 {
diff --git a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/Plane.cs b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/Plane.cs
index da9ae0c..f58cad6 100644
--- a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/Plane.cs
+++ b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/Plane.cs
@@ -27,7 +27,7 @@
27 27
28using System; 28using System;
29 29
30namespace OpenSim.Region.PhysicsModule.ConvexDecompositionDotNet 30namespace OpenSim.Region.PhysicsModules.ConvexDecompositionDotNet
31{ 31{
32 public class Plane 32 public class Plane
33 { 33 {
diff --git a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/PlaneTri.cs b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/PlaneTri.cs
index 42f7a22..8f08ddf 100644
--- a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/PlaneTri.cs
+++ b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/PlaneTri.cs
@@ -29,7 +29,7 @@ using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Diagnostics; 30using System.Diagnostics;
31 31
32namespace OpenSim.Region.PhysicsModule.ConvexDecompositionDotNet 32namespace OpenSim.Region.PhysicsModules.ConvexDecompositionDotNet
33{ 33{
34 public enum PlaneTriResult : int 34 public enum PlaneTriResult : int
35 { 35 {
diff --git a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/Quaternion.cs b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/Quaternion.cs
index 045f620..2d72117 100644
--- a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/Quaternion.cs
+++ b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/Quaternion.cs
@@ -27,7 +27,7 @@
27 27
28using System; 28using System;
29 29
30namespace OpenSim.Region.PhysicsModule.ConvexDecompositionDotNet 30namespace OpenSim.Region.PhysicsModules.ConvexDecompositionDotNet
31{ 31{
32 public class Quaternion : float4 32 public class Quaternion : float4
33 { 33 {
diff --git a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/SplitPlane.cs b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/SplitPlane.cs
index 9f56bc5..cc5f99c 100644
--- a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/SplitPlane.cs
+++ b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/SplitPlane.cs
@@ -28,7 +28,7 @@
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30 30
31namespace OpenSim.Region.PhysicsModule.ConvexDecompositionDotNet 31namespace OpenSim.Region.PhysicsModules.ConvexDecompositionDotNet
32{ 32{
33 public class Rect3d 33 public class Rect3d
34 { 34 {
diff --git a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/VertexLookup.cs b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/VertexLookup.cs
index bfe11e5..da2255e 100644
--- a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/VertexLookup.cs
+++ b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/VertexLookup.cs
@@ -28,7 +28,7 @@
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30 30
31namespace OpenSim.Region.PhysicsModule.ConvexDecompositionDotNet 31namespace OpenSim.Region.PhysicsModules.ConvexDecompositionDotNet
32{ 32{
33 public class VertexPool 33 public class VertexPool
34 { 34 {
diff --git a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/float2.cs b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/float2.cs
index e7358c1..2a58ec4 100644
--- a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/float2.cs
+++ b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/float2.cs
@@ -27,7 +27,7 @@
27 27
28using System; 28using System;
29 29
30namespace OpenSim.Region.PhysicsModule.ConvexDecompositionDotNet 30namespace OpenSim.Region.PhysicsModules.ConvexDecompositionDotNet
31{ 31{
32 public class float2 32 public class float2
33 { 33 {
diff --git a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/float3.cs b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/float3.cs
index fde9b32..64a9ef8 100644
--- a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/float3.cs
+++ b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/float3.cs
@@ -27,7 +27,7 @@
27 27
28using System; 28using System;
29 29
30namespace OpenSim.Region.PhysicsModule.ConvexDecompositionDotNet 30namespace OpenSim.Region.PhysicsModules.ConvexDecompositionDotNet
31{ 31{
32 public class float3 : IEquatable<float3> 32 public class float3 : IEquatable<float3>
33 { 33 {
diff --git a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/float3x3.cs b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/float3x3.cs
index c420fde..266ed0b 100644
--- a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/float3x3.cs
+++ b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/float3x3.cs
@@ -29,7 +29,7 @@ using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Diagnostics; 30using System.Diagnostics;
31 31
32namespace OpenSim.Region.PhysicsModule.ConvexDecompositionDotNet 32namespace OpenSim.Region.PhysicsModules.ConvexDecompositionDotNet
33{ 33{
34 public class float3x3 34 public class float3x3
35 { 35 {
diff --git a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/float4.cs b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/float4.cs
index b2b6fd3..058934d 100644
--- a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/float4.cs
+++ b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/float4.cs
@@ -27,7 +27,7 @@
27 27
28using System; 28using System;
29 29
30namespace OpenSim.Region.PhysicsModule.ConvexDecompositionDotNet 30namespace OpenSim.Region.PhysicsModules.ConvexDecompositionDotNet
31{ 31{
32 public class float4 32 public class float4
33 { 33 {
diff --git a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/float4x4.cs b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/float4x4.cs
index 087eba7..58f4f58 100644
--- a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/float4x4.cs
+++ b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/float4x4.cs
@@ -30,7 +30,7 @@ using System.Collections.Generic;
30using System.Linq; 30using System.Linq;
31using System.Text; 31using System.Text;
32 32
33namespace OpenSim.Region.PhysicsModule.ConvexDecompositionDotNet 33namespace OpenSim.Region.PhysicsModules.ConvexDecompositionDotNet
34{ 34{
35 public class float4x4 35 public class float4x4
36 { 36 {
diff --git a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/int3.cs b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/int3.cs
index 90624eb..b3d4ecb 100644
--- a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/int3.cs
+++ b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/int3.cs
@@ -27,7 +27,7 @@
27 27
28using System; 28using System;
29 29
30namespace OpenSim.Region.PhysicsModule.ConvexDecompositionDotNet 30namespace OpenSim.Region.PhysicsModules.ConvexDecompositionDotNet
31{ 31{
32 public class int3 32 public class int3
33 { 33 {
diff --git a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/int4.cs b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/int4.cs
index e9320c0..41e0912 100644
--- a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/int4.cs
+++ b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/int4.cs
@@ -27,7 +27,7 @@
27 27
28using System; 28using System;
29 29
30namespace OpenSim.Region.PhysicsModule.ConvexDecompositionDotNet 30namespace OpenSim.Region.PhysicsModules.ConvexDecompositionDotNet
31{ 31{
32 public class int4 32 public class int4
33 { 33 {
diff --git a/OpenSim/Region/PhysicsModules/Meshing/Meshmerizer/HelperTypes.cs b/OpenSim/Region/PhysicsModules/Meshing/Meshmerizer/HelperTypes.cs
index 34a925d..a0e3b7f 100644
--- a/OpenSim/Region/PhysicsModules/Meshing/Meshmerizer/HelperTypes.cs
+++ b/OpenSim/Region/PhysicsModules/Meshing/Meshmerizer/HelperTypes.cs
@@ -31,7 +31,7 @@ using System.Diagnostics;
31using System.Globalization; 31using System.Globalization;
32using OpenMetaverse; 32using OpenMetaverse;
33using OpenSim.Region.PhysicsModules.SharedBase; 33using OpenSim.Region.PhysicsModules.SharedBase;
34using OpenSim.Region.PhysicsModules.Meshing; 34using OpenSim.Region.PhysicsModule.Meshing;
35 35
36public class Vertex : IComparable<Vertex> 36public class Vertex : IComparable<Vertex>
37{ 37{
diff --git a/OpenSim/Region/PhysicsModules/Meshing/Meshmerizer/Mesh.cs b/OpenSim/Region/PhysicsModules/Meshing/Meshmerizer/Mesh.cs
index bf397ee..e63ad01 100644
--- a/OpenSim/Region/PhysicsModules/Meshing/Meshmerizer/Mesh.cs
+++ b/OpenSim/Region/PhysicsModules/Meshing/Meshmerizer/Mesh.cs
@@ -33,7 +33,7 @@ using OpenSim.Region.PhysicsModules.SharedBase;
33using PrimMesher; 33using PrimMesher;
34using OpenMetaverse; 34using OpenMetaverse;
35 35
36namespace OpenSim.Region.PhysicsModules.Meshing 36namespace OpenSim.Region.PhysicsModule.Meshing
37{ 37{
38 public class Mesh : IMesh 38 public class Mesh : IMesh
39 { 39 {
@@ -46,11 +46,36 @@ namespace OpenSim.Region.PhysicsModules.Meshing
46 IntPtr m_indicesPtr = IntPtr.Zero; 46 IntPtr m_indicesPtr = IntPtr.Zero;
47 int m_indexCount = 0; 47 int m_indexCount = 0;
48 public float[] m_normals; 48 public float[] m_normals;
49 Vector3 _centroid;
50 int _centroidDiv;
51
52 private class vertexcomp : IEqualityComparer<Vertex>
53 {
54 public bool Equals(Vertex v1, Vertex v2)
55 {
56 if (v1.X == v2.X && v1.Y == v2.Y && v1.Z == v2.Z)
57 return true;
58 else
59 return false;
60 }
61 public int GetHashCode(Vertex v)
62 {
63 int a = v.X.GetHashCode();
64 int b = v.Y.GetHashCode();
65 int c = v.Z.GetHashCode();
66 return (a << 16) ^ (b << 8) ^ c;
67 }
68
69 }
49 70
50 public Mesh() 71 public Mesh()
51 { 72 {
52 m_vertices = new Dictionary<Vertex, int>(); 73 vertexcomp vcomp = new vertexcomp();
74
75 m_vertices = new Dictionary<Vertex, int>(vcomp);
53 m_triangles = new List<Triangle>(); 76 m_triangles = new List<Triangle>();
77 _centroid = Vector3.Zero;
78 _centroidDiv = 0;
54 } 79 }
55 80
56 public Mesh Clone() 81 public Mesh Clone()
@@ -61,7 +86,8 @@ namespace OpenSim.Region.PhysicsModules.Meshing
61 { 86 {
62 result.Add(new Triangle(t.v1.Clone(), t.v2.Clone(), t.v3.Clone())); 87 result.Add(new Triangle(t.v1.Clone(), t.v2.Clone(), t.v3.Clone()));
63 } 88 }
64 89 result._centroid = _centroid;
90 result._centroidDiv = _centroidDiv;
65 return result; 91 return result;
66 } 92 }
67 93
@@ -71,15 +97,63 @@ namespace OpenSim.Region.PhysicsModules.Meshing
71 throw new NotSupportedException("Attempt to Add to a pinned Mesh"); 97 throw new NotSupportedException("Attempt to Add to a pinned Mesh");
72 // If a vertex of the triangle is not yet in the vertices list, 98 // If a vertex of the triangle is not yet in the vertices list,
73 // add it and set its index to the current index count 99 // add it and set its index to the current index count
100 // vertex == seems broken
101 // skip colapsed triangles
102 if ((triangle.v1.X == triangle.v2.X && triangle.v1.Y == triangle.v2.Y && triangle.v1.Z == triangle.v2.Z)
103 || (triangle.v1.X == triangle.v3.X && triangle.v1.Y == triangle.v3.Y && triangle.v1.Z == triangle.v3.Z)
104 || (triangle.v2.X == triangle.v3.X && triangle.v2.Y == triangle.v3.Y && triangle.v2.Z == triangle.v3.Z)
105 )
106 {
107 return;
108 }
109
110 if (m_vertices.Count == 0)
111 {
112 _centroidDiv = 0;
113 _centroid = Vector3.Zero;
114 }
115
74 if (!m_vertices.ContainsKey(triangle.v1)) 116 if (!m_vertices.ContainsKey(triangle.v1))
117 {
75 m_vertices[triangle.v1] = m_vertices.Count; 118 m_vertices[triangle.v1] = m_vertices.Count;
119 _centroid.X += triangle.v1.X;
120 _centroid.Y += triangle.v1.Y;
121 _centroid.Z += triangle.v1.Z;
122 _centroidDiv++;
123 }
76 if (!m_vertices.ContainsKey(triangle.v2)) 124 if (!m_vertices.ContainsKey(triangle.v2))
125 {
77 m_vertices[triangle.v2] = m_vertices.Count; 126 m_vertices[triangle.v2] = m_vertices.Count;
127 _centroid.X += triangle.v2.X;
128 _centroid.Y += triangle.v2.Y;
129 _centroid.Z += triangle.v2.Z;
130 _centroidDiv++;
131 }
78 if (!m_vertices.ContainsKey(triangle.v3)) 132 if (!m_vertices.ContainsKey(triangle.v3))
133 {
79 m_vertices[triangle.v3] = m_vertices.Count; 134 m_vertices[triangle.v3] = m_vertices.Count;
135 _centroid.X += triangle.v3.X;
136 _centroid.Y += triangle.v3.Y;
137 _centroid.Z += triangle.v3.Z;
138 _centroidDiv++;
139 }
80 m_triangles.Add(triangle); 140 m_triangles.Add(triangle);
81 } 141 }
82 142
143 public Vector3 GetCentroid()
144 {
145 if (_centroidDiv > 0)
146 return new Vector3(_centroid.X / _centroidDiv, _centroid.Y / _centroidDiv, _centroid.Z / _centroidDiv);
147 else
148 return Vector3.Zero;
149 }
150
151 // not functional
152 public Vector3 GetOBB()
153 {
154 return new Vector3(0.5f, 0.5f, 0.5f);
155 }
156
83 public void CalcNormals() 157 public void CalcNormals()
84 { 158 {
85 int iTriangles = m_triangles.Count; 159 int iTriangles = m_triangles.Count;
@@ -185,6 +259,7 @@ namespace OpenSim.Region.PhysicsModules.Meshing
185 public void getVertexListAsPtrToFloatArray(out IntPtr vertices, out int vertexStride, out int vertexCount) 259 public void getVertexListAsPtrToFloatArray(out IntPtr vertices, out int vertexStride, out int vertexCount)
186 { 260 {
187 // A vertex is 3 floats 261 // A vertex is 3 floats
262
188 vertexStride = 3 * sizeof(float); 263 vertexStride = 3 * sizeof(float);
189 264
190 // If there isn't an unmanaged array allocated yet, do it now 265 // If there isn't an unmanaged array allocated yet, do it now
diff --git a/OpenSim/Region/PhysicsModules/Meshing/Meshmerizer/Meshmerizer.cs b/OpenSim/Region/PhysicsModules/Meshing/Meshmerizer/Meshmerizer.cs
index 4d25bf3..0d22e96 100644
--- a/OpenSim/Region/PhysicsModules/Meshing/Meshmerizer/Meshmerizer.cs
+++ b/OpenSim/Region/PhysicsModules/Meshing/Meshmerizer/Meshmerizer.cs
@@ -44,7 +44,7 @@ using log4net;
44using Nini.Config; 44using Nini.Config;
45using Mono.Addins; 45using Mono.Addins;
46 46
47namespace OpenSim.Region.PhysicsModules.Meshing 47namespace OpenSim.Region.PhysicsModule.Meshing
48{ 48{
49 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "Meshmerizer")] 49 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "Meshmerizer")]
50 public class Meshmerizer : IMesher, INonSharedRegionModule 50 public class Meshmerizer : IMesher, INonSharedRegionModule
@@ -947,11 +947,21 @@ namespace OpenSim.Region.PhysicsModules.Meshing
947 return CreateMesh(primName, primShape, size, lod, false, true); 947 return CreateMesh(primName, primShape, size, lod, false, true);
948 } 948 }
949 949
950 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool shouldCache, bool convex, bool forOde)
951 {
952 return CreateMesh(primName, primShape, size, lod, false);
953 }
954
950 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical) 955 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical)
951 { 956 {
952 return CreateMesh(primName, primShape, size, lod, isPhysical, true); 957 return CreateMesh(primName, primShape, size, lod, isPhysical, true);
953 } 958 }
954 959
960 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex, bool forOde)
961 {
962 return CreateMesh(primName, primShape, size, lod, isPhysical, true);
963 }
964
955 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool shouldCache) 965 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool shouldCache)
956 { 966 {
957#if SPAM 967#if SPAM
@@ -1005,6 +1015,13 @@ namespace OpenSim.Region.PhysicsModules.Meshing
1005 1015
1006 return mesh; 1016 return mesh;
1007 } 1017 }
1018 public IMesh GetMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex)
1019 {
1020 return null;
1021 }
1008 1022
1023 public void ReleaseMesh(IMesh imesh) { }
1024 public void ExpireReleaseMeshs() { }
1025 public void ExpireFileCache() { }
1009 } 1026 }
1010} 1027}
diff --git a/OpenSim/Region/PhysicsModules/Meshing/Meshmerizer/SculptMap.cs b/OpenSim/Region/PhysicsModules/Meshing/Meshmerizer/SculptMap.cs
index 740424e..b3d9cb6 100644
--- a/OpenSim/Region/PhysicsModules/Meshing/Meshmerizer/SculptMap.cs
+++ b/OpenSim/Region/PhysicsModules/Meshing/Meshmerizer/SculptMap.cs
@@ -58,28 +58,24 @@ namespace PrimMesher
58 if (bmW == 0 || bmH == 0) 58 if (bmW == 0 || bmH == 0)
59 throw new Exception("SculptMap: bitmap has no data"); 59 throw new Exception("SculptMap: bitmap has no data");
60 60
61 int numLodPixels = lod * 2 * lod * 2; // (32 * 2)^2 = 64^2 pixels for default sculpt map image 61 int numLodPixels = lod * lod; // (32 * 2)^2 = 64^2 pixels for default sculpt map image
62 62
63 bool smallMap = bmW * bmH <= numLodPixels;
63 bool needsScaling = false; 64 bool needsScaling = false;
64 65
65 bool smallMap = bmW * bmH <= lod * lod;
66
67 width = bmW; 66 width = bmW;
68 height = bmH; 67 height = bmH;
69 while (width * height > numLodPixels) 68 while (width * height > numLodPixels * 4)
70 { 69 {
71 width >>= 1; 70 width >>= 1;
72 height >>= 1; 71 height >>= 1;
73 needsScaling = true; 72 needsScaling = true;
74 } 73 }
75 74
76
77
78 try 75 try
79 { 76 {
80 if (needsScaling) 77 if (needsScaling)
81 bm = ScaleImage(bm, width, height, 78 bm = ScaleImage(bm, width, height);
82 System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor);
83 } 79 }
84 80
85 catch (Exception e) 81 catch (Exception e)
@@ -87,7 +83,7 @@ namespace PrimMesher
87 throw new Exception("Exception in ScaleImage(): e: " + e.ToString()); 83 throw new Exception("Exception in ScaleImage(): e: " + e.ToString());
88 } 84 }
89 85
90 if (width * height > lod * lod) 86 if (width * height > numLodPixels)
91 { 87 {
92 width >>= 1; 88 width >>= 1;
93 height >>= 1; 89 height >>= 1;
@@ -144,15 +140,17 @@ namespace PrimMesher
144 int rowNdx, colNdx; 140 int rowNdx, colNdx;
145 int smNdx = 0; 141 int smNdx = 0;
146 142
143
147 for (rowNdx = 0; rowNdx < numRows; rowNdx++) 144 for (rowNdx = 0; rowNdx < numRows; rowNdx++)
148 { 145 {
149 List<Coord> row = new List<Coord>(numCols); 146 List<Coord> row = new List<Coord>(numCols);
150 for (colNdx = 0; colNdx < numCols; colNdx++) 147 for (colNdx = 0; colNdx < numCols; colNdx++)
151 { 148 {
149
152 if (mirror) 150 if (mirror)
153 row.Add(new Coord(-(redBytes[smNdx] * pixScale - 0.5f), (greenBytes[smNdx] * pixScale - 0.5f), blueBytes[smNdx] * pixScale - 0.5f)); 151 row.Add(new Coord(-((float)redBytes[smNdx] * pixScale - 0.5f), ((float)greenBytes[smNdx] * pixScale - 0.5f), (float)blueBytes[smNdx] * pixScale - 0.5f));
154 else 152 else
155 row.Add(new Coord(redBytes[smNdx] * pixScale - 0.5f, greenBytes[smNdx] * pixScale - 0.5f, blueBytes[smNdx] * pixScale - 0.5f)); 153 row.Add(new Coord((float)redBytes[smNdx] * pixScale - 0.5f, (float)greenBytes[smNdx] * pixScale - 0.5f, (float)blueBytes[smNdx] * pixScale - 0.5f));
156 154
157 ++smNdx; 155 ++smNdx;
158 } 156 }
@@ -161,23 +159,39 @@ namespace PrimMesher
161 return rows; 159 return rows;
162 } 160 }
163 161
164 private Bitmap ScaleImage(Bitmap srcImage, int destWidth, int destHeight, 162 private Bitmap ScaleImage(Bitmap srcImage, int destWidth, int destHeight)
165 System.Drawing.Drawing2D.InterpolationMode interpMode)
166 { 163 {
167 Bitmap scaledImage = new Bitmap(srcImage, destWidth, destHeight);
168 scaledImage.SetResolution(96.0f, 96.0f);
169
170 Graphics grPhoto = Graphics.FromImage(scaledImage);
171 grPhoto.InterpolationMode = interpMode;
172 164
173 grPhoto.DrawImage(srcImage, 165 Bitmap scaledImage = new Bitmap(destWidth, destHeight, PixelFormat.Format24bppRgb);
174 new Rectangle(0, 0, destWidth, destHeight), 166
175 new Rectangle(0, 0, srcImage.Width, srcImage.Height), 167 Color c;
176 GraphicsUnit.Pixel); 168 float xscale = srcImage.Width / destWidth;
169 float yscale = srcImage.Height / destHeight;
170
171 float sy = 0.5f;
172 for (int y = 0; y < destHeight; y++)
173 {
174 float sx = 0.5f;
175 for (int x = 0; x < destWidth; x++)
176 {
177 try
178 {
179 c = srcImage.GetPixel((int)(sx), (int)(sy));
180 scaledImage.SetPixel(x, y, Color.FromArgb(c.R, c.G, c.B));
181 }
182 catch (IndexOutOfRangeException)
183 {
184 }
177 185
178 grPhoto.Dispose(); 186 sx += xscale;
187 }
188 sy += yscale;
189 }
190 srcImage.Dispose();
179 return scaledImage; 191 return scaledImage;
180 } 192 }
193
194 }
195
181 } 196 }
182}
183#endif 197#endif
diff --git a/OpenSim/Region/PhysicsModules/Meshing/Properties/AssemblyInfo.cs b/OpenSim/Region/PhysicsModules/Meshing/Properties/AssemblyInfo.cs
index b4bdb5a..3e17990 100644
--- a/OpenSim/Region/PhysicsModules/Meshing/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/PhysicsModules/Meshing/Properties/AssemblyInfo.cs
@@ -6,7 +6,7 @@ using Mono.Addins;
6// General Information about an assembly is controlled through the following 6// General Information about an assembly is controlled through the following
7// set of attributes. Change these attribute values to modify the information 7// set of attributes. Change these attribute values to modify the information
8// associated with an assembly. 8// associated with an assembly.
9[assembly: AssemblyTitle("OpenSim.Region.PhysicsModules.Meshing")] 9[assembly: AssemblyTitle("OpenSim.Region.PhysicsModule.Meshing")]
10[assembly: AssemblyDescription("")] 10[assembly: AssemblyDescription("")]
11[assembly: AssemblyConfiguration("")] 11[assembly: AssemblyConfiguration("")]
12[assembly: AssemblyCompany("http://opensimulator.org")] 12[assembly: AssemblyCompany("http://opensimulator.org")]
@@ -32,5 +32,5 @@ using Mono.Addins;
32// 32//
33[assembly: AssemblyVersion("0.8.3.*")] 33[assembly: AssemblyVersion("0.8.3.*")]
34 34
35[assembly: Addin("OpenSim.Region.PhysicsModules.Meshing", OpenSim.VersionInfo.VersionNumber)] 35[assembly: Addin("OpenSim.Region.PhysicsModule.Meshing", OpenSim.VersionInfo.VersionNumber)]
36[assembly: AddinDependency("OpenSim.Region.Framework", OpenSim.VersionInfo.VersionNumber)] 36[assembly: AddinDependency("OpenSim.Region.Framework", OpenSim.VersionInfo.VersionNumber)]
diff --git a/OpenSim/Region/PhysicsModules/Meshing/ZeroMesher.cs b/OpenSim/Region/PhysicsModules/Meshing/ZeroMesher.cs
index 0a3b3a4..dbf4f7e 100644
--- a/OpenSim/Region/PhysicsModules/Meshing/ZeroMesher.cs
+++ b/OpenSim/Region/PhysicsModules/Meshing/ZeroMesher.cs
@@ -47,7 +47,7 @@ using log4net;
47 * it's always availabe and thus the default in case of configuration errors 47 * it's always availabe and thus the default in case of configuration errors
48*/ 48*/
49 49
50namespace OpenSim.Region.PhysicsModules.Meshing 50namespace OpenSim.Region.PhysicsModule.Meshing
51{ 51{
52 52
53 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "ZeroMesher")] 53 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "ZeroMesher")]
@@ -110,23 +110,36 @@ namespace OpenSim.Region.PhysicsModules.Meshing
110 #region IMesher 110 #region IMesher
111 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod) 111 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod)
112 { 112 {
113 return CreateMesh(primName, primShape, size, lod, false, false); 113 return CreateMesh(primName, primShape, size, lod, false);
114 } 114 }
115 115
116 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical) 116 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool shouldCache, bool convex, bool forOde)
117 {
118 return CreateMesh(primName, primShape, size, lod, false);
119 }
120
121 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex,bool forOde)
117 { 122 {
118 return CreateMesh(primName, primShape, size, lod, false, false); 123 return CreateMesh(primName, primShape, size, lod, false);
119 } 124 }
120 125
121 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool shouldCache) 126 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical)
122 { 127 {
123 // Remove the reference to the encoded JPEG2000 data so it can be GCed 128 // Remove the reference to the encoded JPEG2000 data so it can be GCed
124 primShape.SculptData = OpenMetaverse.Utils.EmptyBytes; 129 primShape.SculptData = OpenMetaverse.Utils.EmptyBytes;
125 130
126 return null; 131 return null;
127 } 132 }
128 #endregion
129 133
134 public IMesh GetMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex)
135 {
136 return null;
137 }
130 138
139 public void ReleaseMesh(IMesh mesh) { }
140 public void ExpireReleaseMeshs() { }
141 public void ExpireFileCache() { }
142
143 #endregion
131 } 144 }
132} 145}
diff --git a/OpenSim/Region/PhysicsModules/Ode/ODECharacter.cs b/OpenSim/Region/PhysicsModules/Ode/ODECharacter.cs
index b35c299..c1afe13 100644
--- a/OpenSim/Region/PhysicsModules/Ode/ODECharacter.cs
+++ b/OpenSim/Region/PhysicsModules/Ode/ODECharacter.cs
@@ -595,7 +595,7 @@ namespace OpenSim.Region.PhysicsModule.ODE
595 595
596 public override void delink() {} 596 public override void delink() {}
597 597
598 public override void LockAngularMotion(Vector3 axis) {} 598 public override void LockAngularMotion(byte axislocks) {}
599 599
600// This code is very useful. Written by DanX0r. We're just not using it right now. 600// This code is very useful. Written by DanX0r. We're just not using it right now.
601// Commented out to prevent a warning. 601// Commented out to prevent a warning.
@@ -1257,7 +1257,7 @@ namespace OpenSim.Region.PhysicsModule.ODE
1257 public override float PIDTau { set { return; } } 1257 public override float PIDTau { set { return; } }
1258 1258
1259 public override float PIDHoverHeight { set { return; } } 1259 public override float PIDHoverHeight { set { return; } }
1260 public override bool PIDHoverActive { set { return; } } 1260 public override bool PIDHoverActive {get {return false;} set { return; } }
1261 public override PIDHoverType PIDHoverType { set { return; } } 1261 public override PIDHoverType PIDHoverType { set { return; } }
1262 public override float PIDHoverTau { set { return; } } 1262 public override float PIDHoverTau { set { return; } }
1263 1263
diff --git a/OpenSim/Region/PhysicsModules/Ode/ODEModule.cs b/OpenSim/Region/PhysicsModules/Ode/ODEModule.cs
new file mode 100644
index 0000000..101e8b0
--- /dev/null
+++ b/OpenSim/Region/PhysicsModules/Ode/ODEModule.cs
@@ -0,0 +1,85 @@
1using System;
2using System.Reflection;
3using log4net;
4using Nini.Config;
5using Mono.Addins;
6using OpenSim.Framework;
7using OpenSim.Region.Framework.Scenes;
8using OpenSim.Region.Framework.Interfaces;
9using Ode.NET;
10
11namespace OpenSim.Region.PhysicsModule.ODE
12{
13 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "ODEPhysicsScene")]
14 public class OdeModule : INonSharedRegionModule
15 {
16 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
17
18 private bool m_Enabled = false;
19 private IConfigSource m_config;
20 private OdeScene m_scene;
21
22 #region INonSharedRegionModule
23
24 public string Name
25 {
26 get { return "OpenDynamicsEngine"; }
27 }
28
29 public Type ReplaceableInterface
30 {
31 get { return null; }
32 }
33
34 public void Initialise(IConfigSource source)
35 {
36 IConfig config = source.Configs["Startup"];
37 if (config != null)
38 {
39 string physics = config.GetString("physics", string.Empty);
40 if (physics == Name)
41 {
42 m_config = source;
43 m_Enabled = true;
44 }
45 }
46 }
47
48 public void Close()
49 {
50 }
51
52 public void AddRegion(Scene scene)
53 {
54 if (!m_Enabled)
55 return;
56
57 if (Util.IsWindows())
58 Util.LoadArchSpecificWindowsDll("ode.dll");
59
60 // Initializing ODE only when a scene is created allows alternative ODE plugins to co-habit (according to
61 // http://opensimulator.org/mantis/view.php?id=2750).
62 d.InitODE();
63
64 m_scene = new OdeScene(scene, m_config, Name);
65 }
66
67 public void RemoveRegion(Scene scene)
68 {
69 if (!m_Enabled || m_scene == null)
70 return;
71
72 m_scene.Dispose();
73 m_scene = null;
74 }
75
76 public void RegionLoaded(Scene scene)
77 {
78 if (!m_Enabled || m_scene == null)
79 return;
80
81 m_scene.RegionLoaded();
82 }
83 #endregion
84 }
85}
diff --git a/OpenSim/Region/PhysicsModules/Ode/ODEPrim.cs b/OpenSim/Region/PhysicsModules/Ode/ODEPrim.cs
index 0b9c45f..908b266 100644
--- a/OpenSim/Region/PhysicsModules/Ode/ODEPrim.cs
+++ b/OpenSim/Region/PhysicsModules/Ode/ODEPrim.cs
@@ -83,8 +83,15 @@ namespace OpenSim.Region.PhysicsModule.ODE
83 set 83 set
84 { 84 {
85 m_isphysical = value; 85 m_isphysical = value;
86 if (!m_isphysical) // Zero the remembered last velocity 86 if (!m_isphysical)
87 {
88 _zeroFlag = true; // Zero the remembered last velocity
87 m_lastVelocity = Vector3.Zero; 89 m_lastVelocity = Vector3.Zero;
90 _acceleration = Vector3.Zero;
91 _velocity = Vector3.Zero;
92 m_taintVelocity = Vector3.Zero;
93 m_rotationalVelocity = Vector3.Zero;
94 }
88 } 95 }
89 } 96 }
90 97
@@ -104,10 +111,12 @@ namespace OpenSim.Region.PhysicsModule.ODE
104 private Vector3 m_taintVelocity; 111 private Vector3 m_taintVelocity;
105 private Vector3 m_taintTorque; 112 private Vector3 m_taintTorque;
106 private Quaternion m_taintrot; 113 private Quaternion m_taintrot;
107 private Vector3 m_angularlock = Vector3.One; 114
108 private Vector3 m_taintAngularLock = Vector3.One;
109 private IntPtr Amotor = IntPtr.Zero; 115 private IntPtr Amotor = IntPtr.Zero;
110 116
117 private byte m_taintAngularLock = 0;
118 private byte m_angularlock = 0;
119
111 private bool m_assetFailed = false; 120 private bool m_assetFailed = false;
112 121
113 private Vector3 m_PIDTarget; 122 private Vector3 m_PIDTarget;
@@ -445,7 +454,7 @@ namespace OpenSim.Region.PhysicsModule.ODE
445 m_disabled = false; 454 m_disabled = false;
446 455
447 // The body doesn't already have a finite rotation mode set here 456 // The body doesn't already have a finite rotation mode set here
448 if ((!m_angularlock.ApproxEquals(Vector3.One, 0.0f)) && _parent == null) 457 if (m_angularlock != 0 && _parent == null)
449 { 458 {
450 createAMotor(m_angularlock); 459 createAMotor(m_angularlock);
451 } 460 }
@@ -919,7 +928,7 @@ namespace OpenSim.Region.PhysicsModule.ODE
919// _parent_scene.waitForSpaceUnlock(m_targetSpace); 928// _parent_scene.waitForSpaceUnlock(m_targetSpace);
920 try 929 try
921 { 930 {
922 SetGeom(d.CreateTriMesh(m_targetSpace, _triMeshData, parent_scene.triCallback, null, null)); 931 SetGeom(d.CreateTriMesh(m_targetSpace, _triMeshData, null, null, null));
923 } 932 }
924 catch (AccessViolationException) 933 catch (AccessViolationException)
925 { 934 {
@@ -1001,7 +1010,7 @@ Console.WriteLine("ZProcessTaints for " + Name);
1001 if (m_taintCollidesWater != m_collidesWater) 1010 if (m_taintCollidesWater != m_collidesWater)
1002 changefloatonwater(); 1011 changefloatonwater();
1003 1012
1004 if (!m_angularlock.ApproxEquals(m_taintAngularLock,0f)) 1013 if (m_taintAngularLock != m_angularlock)
1005 changeAngularLock(); 1014 changeAngularLock();
1006 } 1015 }
1007 1016
@@ -1017,10 +1026,8 @@ Console.WriteLine("ZProcessTaints for " + Name);
1017 //If we have a parent then we're not authorative here 1026 //If we have a parent then we're not authorative here
1018 if (_parent == null) 1027 if (_parent == null)
1019 { 1028 {
1020 if (!m_taintAngularLock.ApproxEquals(Vector3.One, 0f)) 1029 if (m_taintAngularLock != 0)
1021 { 1030 {
1022 //d.BodySetFiniteRotationMode(Body, 0);
1023 //d.BodySetFiniteRotationAxis(Body,m_taintAngularLock.X,m_taintAngularLock.Y,m_taintAngularLock.Z);
1024 createAMotor(m_taintAngularLock); 1031 createAMotor(m_taintAngularLock);
1025 } 1032 }
1026 else 1033 else
@@ -1034,7 +1041,6 @@ Console.WriteLine("ZProcessTaints for " + Name);
1034 } 1041 }
1035 } 1042 }
1036 1043
1037 // Store this for later in case we get turned into a separate body
1038 m_angularlock = m_taintAngularLock; 1044 m_angularlock = m_taintAngularLock;
1039 } 1045 }
1040 1046
@@ -1230,7 +1236,8 @@ Console.WriteLine("ZProcessTaints for " + Name);
1230 m_disabled = false; 1236 m_disabled = false;
1231 1237
1232 // The body doesn't already have a finite rotation mode set here 1238 // The body doesn't already have a finite rotation mode set here
1233 if ((!m_angularlock.ApproxEquals(Vector3.One, 0f)) && _parent == null) 1239 // or remove
1240 if (_parent == null)
1234 { 1241 {
1235 createAMotor(m_angularlock); 1242 createAMotor(m_angularlock);
1236 } 1243 }
@@ -1686,6 +1693,9 @@ Console.WriteLine(" JointCreateFixed");
1686 float fy = 0; 1693 float fy = 0;
1687 float fz = 0; 1694 float fz = 0;
1688 1695
1696 if (outofBounds)
1697 return;
1698
1689 if (IsPhysical && (Body != IntPtr.Zero) && !m_isSelected && !childPrim) // KF: Only move root prims. 1699 if (IsPhysical && (Body != IntPtr.Zero) && !m_isSelected && !childPrim) // KF: Only move root prims.
1690 { 1700 {
1691 if (m_vehicle.Type != Vehicle.TYPE_NONE) 1701 if (m_vehicle.Type != Vehicle.TYPE_NONE)
@@ -1697,21 +1707,6 @@ Console.WriteLine(" JointCreateFixed");
1697 { 1707 {
1698//Console.WriteLine("Move " + Name); 1708//Console.WriteLine("Move " + Name);
1699 if (!d.BodyIsEnabled (Body)) d.BodyEnable (Body); // KF add 161009 1709 if (!d.BodyIsEnabled (Body)) d.BodyEnable (Body); // KF add 161009
1700 // NON-'VEHICLES' are dealt with here
1701// if (d.BodyIsEnabled(Body) && !m_angularlock.ApproxEquals(Vector3.Zero, 0.003f))
1702// {
1703// d.Vector3 avel2 = d.BodyGetAngularVel(Body);
1704// /*
1705// if (m_angularlock.X == 1)
1706// avel2.X = 0;
1707// if (m_angularlock.Y == 1)
1708// avel2.Y = 0;
1709// if (m_angularlock.Z == 1)
1710// avel2.Z = 0;
1711// d.BodySetAngularVel(Body, avel2.X, avel2.Y, avel2.Z);
1712// */
1713// }
1714 //float PID_P = 900.0f;
1715 1710
1716 float m_mass = CalculateMass(); 1711 float m_mass = CalculateMass();
1717 1712
@@ -1940,8 +1935,8 @@ Console.WriteLine(" JointCreateFixed");
1940 d.BodySetQuaternion(Body, ref myrot); 1935 d.BodySetQuaternion(Body, ref myrot);
1941 if (IsPhysical) 1936 if (IsPhysical)
1942 { 1937 {
1943 if (!m_angularlock.ApproxEquals(Vector3.One, 0f)) 1938 // create or remove locks
1944 createAMotor(m_angularlock); 1939 createAMotor(m_angularlock);
1945 } 1940 }
1946 } 1941 }
1947 else 1942 else
@@ -2659,16 +2654,38 @@ Console.WriteLine(" JointCreateFixed");
2659 2654
2660 public override void CrossingFailure() 2655 public override void CrossingFailure()
2661 { 2656 {
2662 m_crossingfailures++; 2657 /*
2663 if (m_crossingfailures > _parent_scene.geomCrossingFailuresBeforeOutofbounds) 2658 m_crossingfailures++;
2664 { 2659 if (m_crossingfailures > _parent_scene.geomCrossingFailuresBeforeOutofbounds)
2665 base.RaiseOutOfBounds(_position); 2660 {
2666 return; 2661 base.RaiseOutOfBounds(_position);
2667 } 2662 return;
2668 else if (m_crossingfailures == _parent_scene.geomCrossingFailuresBeforeOutofbounds) 2663 }
2664 else if (m_crossingfailures == _parent_scene.geomCrossingFailuresBeforeOutofbounds)
2665 {
2666 m_log.Warn("[PHYSICS]: Too many crossing failures for: " + Name);
2667 }
2668 */
2669 _position.X = Util.Clip(_position.X, 0.5f, _parent_scene.WorldExtents.X - 0.5f);
2670 _position.Y = Util.Clip(_position.Y, 0.5f, _parent_scene.WorldExtents.Y - 0.5f);
2671 _position.Z = Util.Clip(_position.Z + 0.2f, -100f, 50000f);
2672
2673 m_lastposition = _position;
2674 _velocity.X = 0;
2675 _velocity.Y = 0;
2676 _velocity.Z = 0;
2677
2678 m_lastVelocity = _velocity;
2679
2680 if (Body != IntPtr.Zero)
2669 { 2681 {
2670 m_log.Warn("[PHYSICS]: Too many crossing failures for: " + Name); 2682 d.BodySetLinearVel(Body, 0, 0, 0); // stop it
2683 d.BodySetPosition(Body, _position.X, _position.Y, _position.Z);
2671 } 2684 }
2685
2686 outofBounds = false;
2687 base.RequestPhysicsterseUpdate();
2688
2672 } 2689 }
2673 2690
2674 public override float Buoyancy 2691 public override float Buoyancy
@@ -2687,32 +2704,23 @@ Console.WriteLine(" JointCreateFixed");
2687 m_taintparent = null; 2704 m_taintparent = null;
2688 } 2705 }
2689 2706
2690 public override void LockAngularMotion(Vector3 axis) 2707 public override void LockAngularMotion(byte axislocks)
2691 { 2708 {
2692 // reverse the zero/non zero values for ODE. 2709 // m_log.DebugFormat("[axislocks]: {0}", axislocks);
2693 if (axis.IsFinite()) 2710 m_taintAngularLock = axislocks;
2694 {
2695 axis.X = (axis.X > 0) ? 1f : 0f;
2696 axis.Y = (axis.Y > 0) ? 1f : 0f;
2697 axis.Z = (axis.Z > 0) ? 1f : 0f;
2698 m_log.DebugFormat("[axislock]: <{0},{1},{2}>", axis.X, axis.Y, axis.Z);
2699 m_taintAngularLock = axis;
2700 }
2701 else
2702 {
2703 m_log.WarnFormat("[PHYSICS]: Got NaN locking axis from Scene on Object {0}", Name);
2704 }
2705 } 2711 }
2706 2712
2707 internal void UpdatePositionAndVelocity() 2713 internal void UpdatePositionAndVelocity()
2708 { 2714 {
2709 // no lock; called from Simulate() -- if you call this from elsewhere, gotta lock or do Monitor.Enter/Exit! 2715 // no lock; called from Simulate() -- if you call this from elsewhere, gotta lock or do Monitor.Enter/Exit!
2716 if (outofBounds)
2717 return;
2710 if (_parent == null) 2718 if (_parent == null)
2711 { 2719 {
2712 Vector3 pv = Vector3.Zero; 2720 Vector3 pv = Vector3.Zero;
2713 bool lastZeroFlag = _zeroFlag; 2721 bool lastZeroFlag = _zeroFlag;
2714 float m_minvelocity = 0; 2722 float m_minvelocity = 0;
2715 if (Body != (IntPtr)0) // FIXME -> or if it is a joint 2723 if (Body != IntPtr.Zero) // FIXME -> or if it is a joint
2716 { 2724 {
2717 d.Vector3 vec = d.BodyGetPosition(Body); 2725 d.Vector3 vec = d.BodyGetPosition(Body);
2718 d.Quaternion ori = d.BodyGetQuaternion(Body); 2726 d.Quaternion ori = d.BodyGetQuaternion(Body);
@@ -2723,12 +2731,6 @@ Console.WriteLine(" JointCreateFixed");
2723 Vector3 l_position = Vector3.Zero; 2731 Vector3 l_position = Vector3.Zero;
2724 Quaternion l_orientation = Quaternion.Identity; 2732 Quaternion l_orientation = Quaternion.Identity;
2725 2733
2726 // kluge to keep things in bounds. ODE lets dead avatars drift away (they should be removed!)
2727 //if (vec.X < 0.0f) { vec.X = 0.0f; if (Body != (IntPtr)0) d.BodySetAngularVel(Body, 0, 0, 0); }
2728 //if (vec.Y < 0.0f) { vec.Y = 0.0f; if (Body != (IntPtr)0) d.BodySetAngularVel(Body, 0, 0, 0); }
2729 //if (vec.X > 255.95f) { vec.X = 255.95f; if (Body != (IntPtr)0) d.BodySetAngularVel(Body, 0, 0, 0); }
2730 //if (vec.Y > 255.95f) { vec.Y = 255.95f; if (Body != (IntPtr)0) d.BodySetAngularVel(Body, 0, 0, 0); }
2731
2732 m_lastposition = _position; 2734 m_lastposition = _position;
2733 m_lastorientation = _orientation; 2735 m_lastorientation = _orientation;
2734 2736
@@ -2740,26 +2742,6 @@ Console.WriteLine(" JointCreateFixed");
2740 l_orientation.Z = ori.Z; 2742 l_orientation.Z = ori.Z;
2741 l_orientation.W = ori.W; 2743 l_orientation.W = ori.W;
2742 2744
2743 if (l_position.X > ((int)_parent_scene.WorldExtents.X - 0.05f) || l_position.X < 0f || l_position.Y > ((int)_parent_scene.WorldExtents.Y - 0.05f) || l_position.Y < 0f)
2744 {
2745 //base.RaiseOutOfBounds(l_position);
2746
2747 if (m_crossingfailures < _parent_scene.geomCrossingFailuresBeforeOutofbounds)
2748 {
2749 _position = l_position;
2750 //_parent_scene.remActivePrim(this);
2751 if (_parent == null)
2752 base.RequestPhysicsterseUpdate();
2753 return;
2754 }
2755 else
2756 {
2757 if (_parent == null)
2758 base.RaiseOutOfBounds(l_position);
2759 return;
2760 }
2761 }
2762
2763 if (l_position.Z < 0) 2745 if (l_position.Z < 0)
2764 { 2746 {
2765 // This is so prim that get lost underground don't fall forever and suck up 2747 // This is so prim that get lost underground don't fall forever and suck up
@@ -2769,8 +2751,6 @@ Console.WriteLine(" JointCreateFixed");
2769 // It's a hack and will generate a console message if it fails. 2751 // It's a hack and will generate a console message if it fails.
2770 2752
2771 //IsPhysical = false; 2753 //IsPhysical = false;
2772 if (_parent == null)
2773 base.RaiseOutOfBounds(_position);
2774 2754
2775 _acceleration.X = 0; 2755 _acceleration.X = 0;
2776 _acceleration.Y = 0; 2756 _acceleration.Y = 0;
@@ -2784,16 +2764,64 @@ Console.WriteLine(" JointCreateFixed");
2784 m_rotationalVelocity.Z = 0; 2764 m_rotationalVelocity.Z = 0;
2785 2765
2786 if (_parent == null) 2766 if (_parent == null)
2767 base.RaiseOutOfBounds(_position);
2768
2769 if (_parent == null)
2787 base.RequestPhysicsterseUpdate(); 2770 base.RequestPhysicsterseUpdate();
2788 2771
2789 m_throttleUpdates = false; 2772 m_throttleUpdates = false;
2790 throttleCounter = 0; 2773 throttleCounter = 0;
2791 _zeroFlag = true; 2774 _zeroFlag = true;
2792 //outofBounds = true; 2775 //outofBounds = true;
2776 return;
2777 }
2778
2779 if (l_position.X > ((int)_parent_scene.WorldExtents.X - 0.05f) || l_position.X < 0f || l_position.Y > ((int)_parent_scene.WorldExtents.Y - 0.05f) || l_position.Y < 0f)
2780 {
2781 //base.RaiseOutOfBounds(l_position);
2782 /*
2783 if (m_crossingfailures < _parent_scene.geomCrossingFailuresBeforeOutofbounds)
2784 {
2785 _position = l_position;
2786 //_parent_scene.remActivePrim(this);
2787 if (_parent == null)
2788 base.RequestPhysicsterseUpdate();
2789 return;
2790 }
2791 else
2792 {
2793 if (_parent == null)
2794 base.RaiseOutOfBounds(l_position);
2795 return;
2796 }
2797 */
2798 outofBounds = true;
2799 // part near the border on outside
2800 if (l_position.X < 0)
2801 Util.Clamp(l_position.X, -0.1f, -2f);
2802 else
2803 Util.Clamp(l_position.X, _parent_scene.WorldExtents.X + 0.1f, _parent_scene.WorldExtents.X + 2f);
2804 if (l_position.Y < 0)
2805 Util.Clamp(l_position.Y, -0.1f, -2f);
2806 else
2807 Util.Clamp(l_position.Y, _parent_scene.WorldExtents.Y + 0.1f, _parent_scene.WorldExtents.Y + 2f);
2808
2809 d.BodySetPosition(Body, l_position.X, l_position.Y, l_position.Z);
2810
2811 // stop it
2812 d.BodySetAngularVel(Body, 0, 0, 0);
2813 d.BodySetLinearVel(Body, 0, 0, 0);
2814 disableBodySoft();
2815
2816 // tell framework to fix it
2817 if (_parent == null)
2818 base.RequestPhysicsterseUpdate();
2819 return;
2793 } 2820 }
2794 2821
2822
2795 //float Adiff = 1.0f - Math.Abs(Quaternion.Dot(m_lastorientation, l_orientation)); 2823 //float Adiff = 1.0f - Math.Abs(Quaternion.Dot(m_lastorientation, l_orientation));
2796//Console.WriteLine("Adiff " + Name + " = " + Adiff); 2824 //Console.WriteLine("Adiff " + Name + " = " + Adiff);
2797 if ((Math.Abs(m_lastposition.X - l_position.X) < 0.02) 2825 if ((Math.Abs(m_lastposition.X - l_position.X) < 0.02)
2798 && (Math.Abs(m_lastposition.Y - l_position.Y) < 0.02) 2826 && (Math.Abs(m_lastposition.Y - l_position.Y) < 0.02)
2799 && (Math.Abs(m_lastposition.Z - l_position.Z) < 0.02) 2827 && (Math.Abs(m_lastposition.Z - l_position.Z) < 0.02)
@@ -2950,11 +2978,12 @@ Console.WriteLine(" JointCreateFixed");
2950 m_log.WarnFormat("[PHYSICS]: Got NaN PIDTarget from Scene on Object {0}", Name); 2978 m_log.WarnFormat("[PHYSICS]: Got NaN PIDTarget from Scene on Object {0}", Name);
2951 } 2979 }
2952 } 2980 }
2981
2953 public override bool PIDActive { get; set; } 2982 public override bool PIDActive { get; set; }
2954 public override float PIDTau { set { m_PIDTau = value; } } 2983 public override float PIDTau { set { m_PIDTau = value; } }
2955 2984
2956 public override float PIDHoverHeight { set { m_PIDHoverHeight = value; ; } } 2985 public override float PIDHoverHeight { set { m_PIDHoverHeight = value; ; } }
2957 public override bool PIDHoverActive { set { m_useHoverPID = value; } } 2986 public override bool PIDHoverActive { get { return m_useHoverPID;} set { m_useHoverPID = value; } }
2958 public override PIDHoverType PIDHoverType { set { m_PIDHoverType = value; } } 2987 public override PIDHoverType PIDHoverType { set { m_PIDHoverType = value; } }
2959 public override float PIDHoverTau { set { m_PIDHoverTau = value; } } 2988 public override float PIDHoverTau { set { m_PIDHoverTau = value; } }
2960 2989
@@ -2966,7 +2995,7 @@ Console.WriteLine(" JointCreateFixed");
2966 2995
2967 public override float APIDDamping{ set { return; } } 2996 public override float APIDDamping{ set { return; } }
2968 2997
2969 private void createAMotor(Vector3 axis) 2998 private void createAMotor(byte axislock)
2970 { 2999 {
2971 if (Body == IntPtr.Zero) 3000 if (Body == IntPtr.Zero)
2972 return; 3001 return;
@@ -2977,150 +3006,105 @@ Console.WriteLine(" JointCreateFixed");
2977 Amotor = IntPtr.Zero; 3006 Amotor = IntPtr.Zero;
2978 } 3007 }
2979 3008
2980 float axisnum = 3; 3009 if(axislock == 0)
2981 3010 return;
2982 axisnum = (axisnum - (axis.X + axis.Y + axis.Z));
2983
2984 // PhysicsVector totalSize = new PhysicsVector(_size.X, _size.Y, _size.Z);
2985
2986
2987 // Inverse Inertia Matrix, set the X, Y, and/r Z inertia to 0 then invert it again.
2988 d.Mass objMass;
2989 d.MassSetZero(out objMass);
2990 DMassCopy(ref pMass, ref objMass);
2991
2992 //m_log.DebugFormat("1-{0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}, ", objMass.I.M00, objMass.I.M01, objMass.I.M02, objMass.I.M10, objMass.I.M11, objMass.I.M12, objMass.I.M20, objMass.I.M21, objMass.I.M22);
2993
2994 Matrix4 dMassMat = FromDMass(objMass);
2995
2996 Matrix4 mathmat = Inverse(dMassMat);
2997
2998 /*
2999 //m_log.DebugFormat("2-{0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}, ", mathmat[0, 0], mathmat[0, 1], mathmat[0, 2], mathmat[1, 0], mathmat[1, 1], mathmat[1, 2], mathmat[2, 0], mathmat[2, 1], mathmat[2, 2]);
3000
3001 mathmat = Inverse(mathmat);
3002
3003
3004 objMass = FromMatrix4(mathmat, ref objMass);
3005 //m_log.DebugFormat("3-{0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}, ", objMass.I.M00, objMass.I.M01, objMass.I.M02, objMass.I.M10, objMass.I.M11, objMass.I.M12, objMass.I.M20, objMass.I.M21, objMass.I.M22);
3006
3007 mathmat = Inverse(mathmat);
3008 */
3009 if (axis.X == 0)
3010 {
3011 mathmat.M33 = 50.0000001f;
3012 //objMass.I.M22 = 0;
3013 }
3014 if (axis.Y == 0)
3015 {
3016 mathmat.M22 = 50.0000001f;
3017 //objMass.I.M11 = 0;
3018 }
3019 if (axis.Z == 0)
3020 {
3021 mathmat.M11 = 50.0000001f;
3022 //objMass.I.M00 = 0;
3023 }
3024
3025
3026 3011
3027 mathmat = Inverse(mathmat); 3012 int axisnum = 0;
3028 objMass = FromMatrix4(mathmat, ref objMass); 3013 bool axisX = false;
3029 //m_log.DebugFormat("4-{0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}, ", objMass.I.M00, objMass.I.M01, objMass.I.M02, objMass.I.M10, objMass.I.M11, objMass.I.M12, objMass.I.M20, objMass.I.M21, objMass.I.M22); 3014 bool axisY = false;
3030 3015 bool axisZ = false;
3031 //return; 3016 if((axislock & 0x02) != 0)
3032 if (d.MassCheck(ref objMass)) 3017 {
3033 { 3018 axisnum++;
3034 d.BodySetMass(Body, ref objMass); 3019 axisX = true;
3035 } 3020 }
3036 else 3021 if((axislock & 0x04) != 0)
3037 { 3022 {
3038 //m_log.Debug("[PHYSICS]: Mass invalid, ignoring"); 3023 axisnum++;
3039 } 3024 axisY = true;
3025 }
3026 if((axislock & 0x08) != 0)
3027 {
3028 axisnum++;
3029 axisZ = true;
3030 }
3040 3031
3041 if (axisnum <= 0) 3032 if(axisnum == 0)
3042 return; 3033 return;
3043 // int dAMotorEuler = 1; 3034 // stop it
3035 d.BodySetTorque(Body, 0, 0, 0);
3036 d.BodySetAngularVel(Body, 0, 0, 0);
3044 3037
3045 Amotor = d.JointCreateAMotor(_parent_scene.world, IntPtr.Zero); 3038 Amotor = d.JointCreateAMotor(_parent_scene.world, IntPtr.Zero);
3046 d.JointAttach(Amotor, Body, IntPtr.Zero); 3039 d.JointAttach(Amotor, Body, IntPtr.Zero);
3040
3047 d.JointSetAMotorMode(Amotor, 0); 3041 d.JointSetAMotorMode(Amotor, 0);
3048 3042
3049 d.JointSetAMotorNumAxes(Amotor,(int)axisnum); 3043 d.JointSetAMotorNumAxes(Amotor, axisnum);
3050 int i = 0;
3051 3044
3052 if (axis.X == 0) 3045 // get current orientation to lock
3053 {
3054 d.JointSetAMotorAxis(Amotor, i, 0, 1, 0, 0);
3055 i++;
3056 }
3057 3046
3058 if (axis.Y == 0) 3047 d.Quaternion dcur = d.BodyGetQuaternion(Body);
3059 { 3048 Quaternion curr; // crap convertion between identical things
3060 d.JointSetAMotorAxis(Amotor, i, 0, 0, 1, 0); 3049 curr.X = dcur.X;
3061 i++; 3050 curr.Y = dcur.Y;
3062 } 3051 curr.Z = dcur.Z;
3052 curr.W = dcur.W;
3053 Vector3 ax;
3063 3054
3064 if (axis.Z == 0) 3055 int i = 0;
3065 { 3056 int j = 0;
3066 d.JointSetAMotorAxis(Amotor, i, 0, 0, 0, 1); 3057 if (axisX)
3058 {
3059 ax = (new Vector3(1, 0, 0)) * curr; // rotate world X to current local X
3060 d.JointSetAMotorAxis(Amotor, 0, 0, ax.X, ax.Y, ax.Z);
3061 d.JointSetAMotorAngle(Amotor, 0, 0);
3062 d.JointSetAMotorParam(Amotor, (int)d.JointParam.LoStop, 0f);
3063 d.JointSetAMotorParam(Amotor, (int)d.JointParam.HiStop, 0f);
3064 d.JointSetAMotorParam(Amotor, (int)d.JointParam.Vel, 0);
3065 d.JointSetAMotorParam(Amotor, (int)d.JointParam.FudgeFactor, 0.0001f);
3066 d.JointSetAMotorParam(Amotor, (int)d.JointParam.Bounce, 0f);
3067 d.JointSetAMotorParam(Amotor, (int)d.JointParam.CFM, 0f);
3068 d.JointSetAMotorParam(Amotor, (int)d.JointParam.FMax, 5e8f);
3069 d.JointSetAMotorParam(Amotor, (int)d.JointParam.StopCFM, 0f);
3070 d.JointSetAMotorParam(Amotor, (int)d.JointParam.StopERP, 0.8f);
3071 i++;
3072 j = 256; // move to next axis set
3073 }
3074
3075 if (axisY)
3076 {
3077 ax = (new Vector3(0, 1, 0)) * curr;
3078 d.JointSetAMotorAxis(Amotor, i, 0, ax.X, ax.Y, ax.Z);
3079 d.JointSetAMotorAngle(Amotor, i, 0);
3080 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.LoStop, 0f);
3081 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.HiStop, 0f);
3082 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.Vel, 0);
3083 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.FudgeFactor, 0.0001f);
3084 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.Bounce, 0f);
3085 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.CFM, 0f);
3086 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.FMax, 5e8f);
3087 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.StopCFM, 0f);
3088 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.StopERP, 0.8f);
3067 i++; 3089 i++;
3090 j += 256;
3068 } 3091 }
3069 3092
3070 for (int j = 0; j < (int)axisnum; j++) 3093 if (axisZ)
3071 { 3094 {
3072 //d.JointSetAMotorAngle(Amotor, j, 0); 3095 ax = (new Vector3(0, 0, 1)) * curr;
3096 d.JointSetAMotorAxis(Amotor, i, 0, ax.X, ax.Y, ax.Z);
3097 d.JointSetAMotorAngle(Amotor, i, 0);
3098 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.LoStop, 0f);
3099 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.HiStop, 0f);
3100 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.Vel, 0);
3101 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.FudgeFactor, 0.0001f);
3102 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.Bounce, 0f);
3103 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.CFM, 0f);
3104 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.FMax, 5e8f);
3105 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.StopCFM, 0f);
3106 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.StopERP, 0.8f);
3073 } 3107 }
3074
3075 //d.JointSetAMotorAngle(Amotor, 1, 0);
3076 //d.JointSetAMotorAngle(Amotor, 2, 0);
3077
3078 // These lowstops and high stops are effectively (no wiggle room)
3079 d.JointSetAMotorParam(Amotor, (int)dParam.LowStop, -0f);
3080 d.JointSetAMotorParam(Amotor, (int)dParam.LoStop3, -0f);
3081 d.JointSetAMotorParam(Amotor, (int)dParam.LoStop2, -0f);
3082 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop, 0f);
3083 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop3, 0f);
3084 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop2, 0f);
3085 //d.JointSetAMotorParam(Amotor, (int) dParam.Vel, 9000f);
3086 d.JointSetAMotorParam(Amotor, (int)dParam.FudgeFactor, 0f);
3087 d.JointSetAMotorParam(Amotor, (int)dParam.FMax, Mass * 50f);//
3088 }
3089
3090 private Matrix4 FromDMass(d.Mass pMass)
3091 {
3092 Matrix4 obj;
3093 obj.M11 = pMass.I.M00;
3094 obj.M12 = pMass.I.M01;
3095 obj.M13 = pMass.I.M02;
3096 obj.M14 = 0;
3097 obj.M21 = pMass.I.M10;
3098 obj.M22 = pMass.I.M11;
3099 obj.M23 = pMass.I.M12;
3100 obj.M24 = 0;
3101 obj.M31 = pMass.I.M20;
3102 obj.M32 = pMass.I.M21;
3103 obj.M33 = pMass.I.M22;
3104 obj.M34 = 0;
3105 obj.M41 = 0;
3106 obj.M42 = 0;
3107 obj.M43 = 0;
3108 obj.M44 = 1;
3109 return obj;
3110 }
3111
3112 private d.Mass FromMatrix4(Matrix4 pMat, ref d.Mass obj)
3113 {
3114 obj.I.M00 = pMat[0, 0];
3115 obj.I.M01 = pMat[0, 1];
3116 obj.I.M02 = pMat[0, 2];
3117 obj.I.M10 = pMat[1, 0];
3118 obj.I.M11 = pMat[1, 1];
3119 obj.I.M12 = pMat[1, 2];
3120 obj.I.M20 = pMat[2, 0];
3121 obj.I.M21 = pMat[2, 1];
3122 obj.I.M22 = pMat[2, 2];
3123 return obj;
3124 } 3108 }
3125 3109
3126 public override void SubscribeEvents(int ms) 3110 public override void SubscribeEvents(int ms)
@@ -3165,173 +3149,6 @@ Console.WriteLine(" JointCreateFixed");
3165 return false; 3149 return false;
3166 } 3150 }
3167 3151
3168 public static Matrix4 Inverse(Matrix4 pMat)
3169 {
3170 if (determinant3x3(pMat) == 0)
3171 {
3172 return Matrix4.Identity; // should probably throw an error. singluar matrix inverse not possible
3173 }
3174
3175 return (Adjoint(pMat) / determinant3x3(pMat));
3176 }
3177
3178 public static Matrix4 Adjoint(Matrix4 pMat)
3179 {
3180 Matrix4 adjointMatrix = new Matrix4();
3181 for (int i=0; i<4; i++)
3182 {
3183 for (int j=0; j<4; j++)
3184 {
3185 Matrix4SetValue(ref adjointMatrix, i, j, (float)(Math.Pow(-1, i + j) * (determinant3x3(Minor(pMat, i, j)))));
3186 }
3187 }
3188
3189 adjointMatrix = Transpose(adjointMatrix);
3190 return adjointMatrix;
3191 }
3192
3193 public static Matrix4 Minor(Matrix4 matrix, int iRow, int iCol)
3194 {
3195 Matrix4 minor = new Matrix4();
3196 int m = 0, n = 0;
3197 for (int i = 0; i < 4; i++)
3198 {
3199 if (i == iRow)
3200 continue;
3201 n = 0;
3202 for (int j = 0; j < 4; j++)
3203 {
3204 if (j == iCol)
3205 continue;
3206 Matrix4SetValue(ref minor, m,n, matrix[i, j]);
3207 n++;
3208 }
3209 m++;
3210 }
3211
3212 return minor;
3213 }
3214
3215 public static Matrix4 Transpose(Matrix4 pMat)
3216 {
3217 Matrix4 transposeMatrix = new Matrix4();
3218 for (int i = 0; i < 4; i++)
3219 for (int j = 0; j < 4; j++)
3220 Matrix4SetValue(ref transposeMatrix, i, j, pMat[j, i]);
3221 return transposeMatrix;
3222 }
3223
3224 public static void Matrix4SetValue(ref Matrix4 pMat, int r, int c, float val)
3225 {
3226 switch (r)
3227 {
3228 case 0:
3229 switch (c)
3230 {
3231 case 0:
3232 pMat.M11 = val;
3233 break;
3234 case 1:
3235 pMat.M12 = val;
3236 break;
3237 case 2:
3238 pMat.M13 = val;
3239 break;
3240 case 3:
3241 pMat.M14 = val;
3242 break;
3243 }
3244
3245 break;
3246 case 1:
3247 switch (c)
3248 {
3249 case 0:
3250 pMat.M21 = val;
3251 break;
3252 case 1:
3253 pMat.M22 = val;
3254 break;
3255 case 2:
3256 pMat.M23 = val;
3257 break;
3258 case 3:
3259 pMat.M24 = val;
3260 break;
3261 }
3262
3263 break;
3264 case 2:
3265 switch (c)
3266 {
3267 case 0:
3268 pMat.M31 = val;
3269 break;
3270 case 1:
3271 pMat.M32 = val;
3272 break;
3273 case 2:
3274 pMat.M33 = val;
3275 break;
3276 case 3:
3277 pMat.M34 = val;
3278 break;
3279 }
3280
3281 break;
3282 case 3:
3283 switch (c)
3284 {
3285 case 0:
3286 pMat.M41 = val;
3287 break;
3288 case 1:
3289 pMat.M42 = val;
3290 break;
3291 case 2:
3292 pMat.M43 = val;
3293 break;
3294 case 3:
3295 pMat.M44 = val;
3296 break;
3297 }
3298
3299 break;
3300 }
3301 }
3302
3303 private static float determinant3x3(Matrix4 pMat)
3304 {
3305 float det = 0;
3306 float diag1 = pMat[0, 0]*pMat[1, 1]*pMat[2, 2];
3307 float diag2 = pMat[0, 1]*pMat[2, 1]*pMat[2, 0];
3308 float diag3 = pMat[0, 2]*pMat[1, 0]*pMat[2, 1];
3309 float diag4 = pMat[2, 0]*pMat[1, 1]*pMat[0, 2];
3310 float diag5 = pMat[2, 1]*pMat[1, 2]*pMat[0, 0];
3311 float diag6 = pMat[2, 2]*pMat[1, 0]*pMat[0, 1];
3312
3313 det = diag1 + diag2 + diag3 - (diag4 + diag5 + diag6);
3314 return det;
3315 }
3316
3317 private static void DMassCopy(ref d.Mass src, ref d.Mass dst)
3318 {
3319 dst.c.W = src.c.W;
3320 dst.c.X = src.c.X;
3321 dst.c.Y = src.c.Y;
3322 dst.c.Z = src.c.Z;
3323 dst.mass = src.mass;
3324 dst.I.M00 = src.I.M00;
3325 dst.I.M01 = src.I.M01;
3326 dst.I.M02 = src.I.M02;
3327 dst.I.M10 = src.I.M10;
3328 dst.I.M11 = src.I.M11;
3329 dst.I.M12 = src.I.M12;
3330 dst.I.M20 = src.I.M20;
3331 dst.I.M21 = src.I.M21;
3332 dst.I.M22 = src.I.M22;
3333 }
3334
3335 public override void SetMaterial(int pMaterial) 3152 public override void SetMaterial(int pMaterial)
3336 { 3153 {
3337 m_material = pMaterial; 3154 m_material = pMaterial;
diff --git a/OpenSim/Region/PhysicsModules/Ode/ODERayCastRequestManager.cs b/OpenSim/Region/PhysicsModules/Ode/ODERayCastRequestManager.cs
index 8d610f7..6199387 100644
--- a/OpenSim/Region/PhysicsModules/Ode/ODERayCastRequestManager.cs
+++ b/OpenSim/Region/PhysicsModules/Ode/ODERayCastRequestManager.cs
@@ -180,7 +180,7 @@ namespace OpenSim.Region.PhysicsModule.ODE
180 len = 250f; 180 len = 250f;
181 181
182 // Create the ray 182 // Create the ray
183 IntPtr ray = d.CreateRay(m_scene.space, req.length); 183 IntPtr ray = d.CreateRay(m_scene.space, len);
184 d.GeomRaySet(ray, req.Origin.X, req.Origin.Y, req.Origin.Z, req.Normal.X, req.Normal.Y, req.Normal.Z); 184 d.GeomRaySet(ray, req.Origin.X, req.Origin.Y, req.Origin.Z, req.Normal.X, req.Normal.Y, req.Normal.Z);
185 185
186 // Collide test 186 // Collide test
@@ -225,8 +225,13 @@ namespace OpenSim.Region.PhysicsModule.ODE
225 /// <param name="req"></param> 225 /// <param name="req"></param>
226 private void RayCast(ODERayRequest req) 226 private void RayCast(ODERayRequest req)
227 { 227 {
228 // limit ray length or collisions will take all avaiable stack space
229 float len = req.length;
230 if (len > 250f)
231 len = 250f;
232
228 // Create the ray 233 // Create the ray
229 IntPtr ray = d.CreateRay(m_scene.space, req.length); 234 IntPtr ray = d.CreateRay(m_scene.space, len);
230 d.GeomRaySet(ray, req.Origin.X, req.Origin.Y, req.Origin.Z, req.Normal.X, req.Normal.Y, req.Normal.Z); 235 d.GeomRaySet(ray, req.Origin.X, req.Origin.Y, req.Origin.Z, req.Normal.X, req.Normal.Y, req.Normal.Z);
231 236
232 // Collide test 237 // Collide test
@@ -438,4 +443,4 @@ namespace OpenSim.Region.PhysicsModule.ODE
438 public float length; 443 public float length;
439 public RayCallback callbackMethod; 444 public RayCallback callbackMethod;
440 } 445 }
441} \ No newline at end of file 446}
diff --git a/OpenSim/Region/PhysicsModules/Ode/OdeScene.cs b/OpenSim/Region/PhysicsModules/Ode/OdeScene.cs
index 8cc7f28..4e95b7a 100644
--- a/OpenSim/Region/PhysicsModules/Ode/OdeScene.cs
+++ b/OpenSim/Region/PhysicsModules/Ode/OdeScene.cs
@@ -40,6 +40,7 @@ using System.Diagnostics;
40using System.IO; 40using System.IO;
41using System.Linq; 41using System.Linq;
42using System.Reflection; 42using System.Reflection;
43using System.Runtime.ExceptionServices;
43using System.Runtime.InteropServices; 44using System.Runtime.InteropServices;
44using System.Threading; 45using System.Threading;
45using log4net; 46using log4net;
@@ -111,11 +112,9 @@ namespace OpenSim.Region.PhysicsModule.ODE
111 Rubber = 6 112 Rubber = 6
112 } 113 }
113 114
114 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "ODEPhysicsScene")] 115 public class OdeScene : PhysicsScene
115 public class OdeScene : PhysicsScene, INonSharedRegionModule
116 { 116 {
117 private readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType.ToString()); 117 private readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType.ToString());
118 private bool m_Enabled = false;
119 118
120 // private Dictionary<string, sCollisionData> m_storedCollisions = new Dictionary<string, sCollisionData>(); 119 // private Dictionary<string, sCollisionData> m_storedCollisions = new Dictionary<string, sCollisionData>();
121 120
@@ -293,11 +292,8 @@ namespace OpenSim.Region.PhysicsModule.ODE
293 292
294 private float contactsurfacelayer = 0.001f; 293 private float contactsurfacelayer = 0.001f;
295 294
296 private int worldHashspaceLow = -4; 295 private int HashspaceLow = -5;
297 private int worldHashspaceHigh = 128; 296 private int HashspaceHigh = 12;
298
299 private int smallHashspaceLow = -4;
300 private int smallHashspaceHigh = 66;
301 297
302 private float waterlevel = 0f; 298 private float waterlevel = 0f;
303 private int framecount = 0; 299 private int framecount = 0;
@@ -356,10 +352,6 @@ namespace OpenSim.Region.PhysicsModule.ODE
356 public float bodyPIDD = 35f; 352 public float bodyPIDD = 35f;
357 public float bodyPIDG = 25; 353 public float bodyPIDG = 25;
358 354
359 public int geomCrossingFailuresBeforeOutofbounds = 5;
360
361 public float bodyMotorJointMaxforceTensor = 2;
362
363 public int bodyFramesAutoDisable = 20; 355 public int bodyFramesAutoDisable = 20;
364 356
365 private float[] _watermap; 357 private float[] _watermap;
@@ -478,7 +470,7 @@ namespace OpenSim.Region.PhysicsModule.ODE
478 private int m_physicsiterations = 10; 470 private int m_physicsiterations = 10;
479 private const float m_SkipFramesAtms = 0.40f; // Drop frames gracefully at a 400 ms lag 471 private const float m_SkipFramesAtms = 0.40f; // Drop frames gracefully at a 400 ms lag
480 private readonly PhysicsActor PANull = new NullPhysicsActor(); 472 private readonly PhysicsActor PANull = new NullPhysicsActor();
481// private float step_time = 0.0f; 473 private float step_time = 0.0f;
482//Ckrinke: Comment out until used. We declare it, initialize it, but do not use it 474//Ckrinke: Comment out until used. We declare it, initialize it, but do not use it
483//Ckrinke private int ms = 0; 475//Ckrinke private int ms = 0;
484 public IntPtr world; 476 public IntPtr world;
@@ -534,89 +526,37 @@ namespace OpenSim.Region.PhysicsModule.ODE
534 int spaceGridMaxY; 526 int spaceGridMaxY;
535 527
536 private ODERayCastRequestManager m_rayCastManager; 528 private ODERayCastRequestManager m_rayCastManager;
529
530 public Scene m_frameWorkScene = null;
537 531
532 public OdeScene(Scene pscene, IConfigSource psourceconfig, string pname)
533 {
534 m_config = psourceconfig;
535 m_frameWorkScene = pscene;
536
537 EngineType = pname;
538 PhysicsSceneName = EngineType + "/" + pscene.RegionInfo.RegionName;
538 539
539 #region INonSharedRegionModule 540 pscene.RegisterModuleInterface<PhysicsScene>(this);
540 public string Name 541 Vector3 extent = new Vector3(pscene.RegionInfo.RegionSizeX, pscene.RegionInfo.RegionSizeY, pscene.RegionInfo.RegionSizeZ);
541 {
542 get { return "OpenDynamicsEngine"; }
543 }
544
545 public Type ReplaceableInterface
546 {
547 get { return null; }
548 }
549
550 public void Initialise(IConfigSource source)
551 {
552 // TODO: Move this out of Startup
553 IConfig config = source.Configs["Startup"];
554 if (config != null)
555 {
556 string physics = config.GetString("physics", string.Empty);
557 if (physics == Name)
558 {
559 m_Enabled = true;
560 m_config = source;
561
562 // We do this so that OpenSimulator on Windows loads the correct native ODE library depending on whether
563 // it's running as a 32-bit process or a 64-bit one. By invoking LoadLibary here, later DLLImports
564 // will find it already loaded later on.
565 //
566 // This isn't necessary for other platforms (e.g. Mac OSX and Linux) since the DLL used can be
567 // controlled in Ode.NET.dll.config
568 if (Util.IsWindows())
569 Util.LoadArchSpecificWindowsDll("ode.dll");
570
571 // Initializing ODE only when a scene is created allows alternative ODE plugins to co-habit (according to
572 // http://opensimulator.org/mantis/view.php?id=2750).
573 d.InitODE();
574
575 }
576 }
577
578 }
579
580 public void Close()
581 {
582 }
583
584 public void AddRegion(Scene scene)
585 {
586 if (!m_Enabled)
587 return;
588
589 EngineType = Name;
590 PhysicsSceneName = EngineType + "/" + scene.RegionInfo.RegionName;
591
592 scene.RegisterModuleInterface<PhysicsScene>(this);
593 Vector3 extent = new Vector3(scene.RegionInfo.RegionSizeX, scene.RegionInfo.RegionSizeY, scene.RegionInfo.RegionSizeZ);
594 Initialise(extent); 542 Initialise(extent);
595 InitialiseFromConfig(m_config); 543 InitialiseFromConfig(m_config);
596 544
597 // This may not be that good since terrain may not be avaiable at this point 545 // This may not be that good since terrain may not be avaiable at this point
598 base.Initialise(scene.PhysicsRequestAsset, 546 base.Initialise(pscene.PhysicsRequestAsset,
599 (scene.Heightmap != null ? scene.Heightmap.GetFloatsSerialised() : new float[(int)(extent.X * extent.Y)]), 547 (pscene.Heightmap != null ? pscene.Heightmap.GetFloatsSerialised() : new float[(int)(extent.X * extent.Y)]),
600 (float)scene.RegionInfo.RegionSettings.WaterHeight); 548 (float)pscene.RegionInfo.RegionSettings.WaterHeight);
601 549
602 } 550 }
603 551
604 public void RemoveRegion(Scene scene) 552 public void RegionLoaded()
605 { 553 {
606 if (!m_Enabled) 554 mesher = m_frameWorkScene.RequestModuleInterface<IMesher>();
607 return;
608 }
609
610 public void RegionLoaded(Scene scene)
611 {
612 if (!m_Enabled)
613 return;
614
615 mesher = scene.RequestModuleInterface<IMesher>();
616 if (mesher == null) 555 if (mesher == null)
617 m_log.WarnFormat("[ODE SCENE]: No mesher in {0}. Things will not work well.", PhysicsSceneName); 556 m_log.WarnFormat("[ODE SCENE]: No mesher in {0}. Things will not work well.", PhysicsSceneName);
557
558 m_frameWorkScene.PhysicsEnabled = true;
618 } 559 }
619 #endregion
620 560
621 /// <summary> 561 /// <summary>
622 /// Initiailizes the scene 562 /// Initiailizes the scene
@@ -633,8 +573,8 @@ namespace OpenSim.Region.PhysicsModule.ODE
633 m_suportCombine = false; 573 m_suportCombine = false;
634 574
635 nearCallback = near; 575 nearCallback = near;
636 triCallback = TriCallback; 576// triCallback = TriCallback;
637 triArrayCallback = TriArrayCallback; 577// triArrayCallback = TriArrayCallback;
638 m_rayCastManager = new ODERayCastRequestManager(this); 578 m_rayCastManager = new ODERayCastRequestManager(this);
639 579
640 // Create the world and the first space 580 // Create the world and the first space
@@ -679,18 +619,9 @@ namespace OpenSim.Region.PhysicsModule.ODE
679 m_config = config; 619 m_config = config;
680 // Defaults 620 // Defaults
681 621
682 if (Environment.OSVersion.Platform == PlatformID.Unix) 622 avPIDD = 2200.0f;
683 { 623 avPIDP = 900.0f;
684 avPIDD = 3200.0f; 624 avStandupTensor = 550000f;
685 avPIDP = 1400.0f;
686 avStandupTensor = 2000000f;
687 }
688 else
689 {
690 avPIDD = 2200.0f;
691 avPIDP = 900.0f;
692 avStandupTensor = 550000f;
693 }
694 625
695 int contactsPerCollision = 80; 626 int contactsPerCollision = 80;
696 627
@@ -714,12 +645,10 @@ namespace OpenSim.Region.PhysicsModule.ODE
714 avatarTerminalVelocity, AvatarTerminalVelocity); 645 avatarTerminalVelocity, AvatarTerminalVelocity);
715 } 646 }
716 647
717 worldHashspaceLow = physicsconfig.GetInt("world_hashspace_size_low", -4); 648 HashspaceLow = physicsconfig.GetInt("world_hashspace_level_low", -5);
718 worldHashspaceHigh = physicsconfig.GetInt("world_hashspace_size_high", 128); 649 HashspaceHigh = physicsconfig.GetInt("world_hashspace_level_high", 12);
719 650
720 metersInSpace = physicsconfig.GetFloat("meters_in_small_space", 29.9f); 651 metersInSpace = physicsconfig.GetFloat("meters_in_small_space", 29.9f);
721 smallHashspaceLow = physicsconfig.GetInt("small_hashspace_size_low", -4);
722 smallHashspaceHigh = physicsconfig.GetInt("small_hashspace_size_high", 66);
723 652
724 contactsurfacelayer = physicsconfig.GetFloat("world_contact_surface_layer", 0.001f); 653 contactsurfacelayer = physicsconfig.GetFloat("world_contact_surface_layer", 0.001f);
725 654
@@ -738,7 +667,7 @@ namespace OpenSim.Region.PhysicsModule.ODE
738 mAvatarObjectContactBounce = physicsconfig.GetFloat("m_avatarobjectcontact_bounce", 0.1f); 667 mAvatarObjectContactBounce = physicsconfig.GetFloat("m_avatarobjectcontact_bounce", 0.1f);
739 668
740 ODE_STEPSIZE = physicsconfig.GetFloat("world_stepsize", ODE_STEPSIZE); 669 ODE_STEPSIZE = physicsconfig.GetFloat("world_stepsize", ODE_STEPSIZE);
741 m_physicsiterations = physicsconfig.GetInt("world_internal_steps_without_collisions", 10); 670 m_physicsiterations = physicsconfig.GetInt("world_solver_iterations", 10);
742 671
743 avDensity = physicsconfig.GetFloat("av_density", 80f); 672 avDensity = physicsconfig.GetFloat("av_density", 80f);
744// avHeightFudgeFactor = physicsconfig.GetFloat("av_height_fudge_factor", 0.52f); 673// avHeightFudgeFactor = physicsconfig.GetFloat("av_height_fudge_factor", 0.52f);
@@ -754,7 +683,6 @@ namespace OpenSim.Region.PhysicsModule.ODE
754 683
755 geomContactPointsStartthrottle = physicsconfig.GetInt("geom_contactpoints_start_throttling", 5); 684 geomContactPointsStartthrottle = physicsconfig.GetInt("geom_contactpoints_start_throttling", 5);
756 geomUpdatesPerThrottledUpdate = physicsconfig.GetInt("geom_updates_before_throttled_update", 15); 685 geomUpdatesPerThrottledUpdate = physicsconfig.GetInt("geom_updates_before_throttled_update", 15);
757 geomCrossingFailuresBeforeOutofbounds = physicsconfig.GetInt("geom_crossing_failures_before_outofbounds", 5);
758 686
759 geomDefaultDensity = physicsconfig.GetFloat("geometry_default_density", 10.000006836f); 687 geomDefaultDensity = physicsconfig.GetFloat("geometry_default_density", 10.000006836f);
760 bodyFramesAutoDisable = physicsconfig.GetInt("body_frames_auto_disable", 20); 688 bodyFramesAutoDisable = physicsconfig.GetInt("body_frames_auto_disable", 20);
@@ -767,23 +695,10 @@ namespace OpenSim.Region.PhysicsModule.ODE
767 meshSculptLOD = physicsconfig.GetFloat("mesh_lod", 32f); 695 meshSculptLOD = physicsconfig.GetFloat("mesh_lod", 32f);
768 MeshSculptphysicalLOD = physicsconfig.GetFloat("mesh_physical_lod", 16f); 696 MeshSculptphysicalLOD = physicsconfig.GetFloat("mesh_physical_lod", 16f);
769 m_filterCollisions = physicsconfig.GetBoolean("filter_collisions", false); 697 m_filterCollisions = physicsconfig.GetBoolean("filter_collisions", false);
770
771
772 698
773 if (Environment.OSVersion.Platform == PlatformID.Unix) 699 avPIDD = physicsconfig.GetFloat("av_pid_derivative", 2200.0f);
774 { 700 avPIDP = physicsconfig.GetFloat("av_pid_proportional", 900.0f);
775 avPIDD = physicsconfig.GetFloat("av_pid_derivative_linux", 2200.0f); 701 avStandupTensor = physicsconfig.GetFloat("av_capsule_standup_tensor", 550000f);
776 avPIDP = physicsconfig.GetFloat("av_pid_proportional_linux", 900.0f);
777 avStandupTensor = physicsconfig.GetFloat("av_capsule_standup_tensor_linux", 550000f);
778 bodyMotorJointMaxforceTensor = physicsconfig.GetFloat("body_motor_joint_maxforce_tensor_linux", 5f);
779 }
780 else
781 {
782 avPIDD = physicsconfig.GetFloat("av_pid_derivative_win", 2200.0f);
783 avPIDP = physicsconfig.GetFloat("av_pid_proportional_win", 900.0f);
784 avStandupTensor = physicsconfig.GetFloat("av_capsule_standup_tensor_win", 550000f);
785 bodyMotorJointMaxforceTensor = physicsconfig.GetFloat("body_motor_joint_maxforce_tensor_win", 5f);
786 }
787 702
788 physics_logging = physicsconfig.GetBoolean("physics_logging", false); 703 physics_logging = physicsconfig.GetBoolean("physics_logging", false);
789 physics_logging_interval = physicsconfig.GetInt("physics_logging_interval", 0); 704 physics_logging_interval = physicsconfig.GetInt("physics_logging_interval", 0);
@@ -812,7 +727,7 @@ namespace OpenSim.Region.PhysicsModule.ODE
812 if (spaceGridMaxY > 24) 727 if (spaceGridMaxY > 24)
813 { 728 {
814 spaceGridMaxY = 24; 729 spaceGridMaxY = 24;
815 spacesPerMeterY = spaceGridMaxY / WorldExtents.Y ; 730 spacesPerMeterY = spaceGridMaxY / WorldExtents.Y;
816 } 731 }
817 732
818 staticPrimspace = new IntPtr[spaceGridMaxX, spaceGridMaxY]; 733 staticPrimspace = new IntPtr[spaceGridMaxX, spaceGridMaxY];
@@ -984,7 +899,7 @@ namespace OpenSim.Region.PhysicsModule.ODE
984 m_materialContacts[(int)Material.Rubber, 1].surface.soft_cfm = 0.010f; 899 m_materialContacts[(int)Material.Rubber, 1].surface.soft_cfm = 0.010f;
985 m_materialContacts[(int)Material.Rubber, 1].surface.soft_erp = 0.010f; 900 m_materialContacts[(int)Material.Rubber, 1].surface.soft_erp = 0.010f;
986 901
987 d.HashSpaceSetLevels(space, worldHashspaceLow, worldHashspaceHigh); 902 d.HashSpaceSetLevels(space, HashspaceLow, HashspaceHigh);
988 903
989 // Set the gravity,, don't disable things automatically (we set it explicitly on some things) 904 // Set the gravity,, don't disable things automatically (we set it explicitly on some things)
990 905
@@ -1864,10 +1779,10 @@ namespace OpenSim.Region.PhysicsModule.ODE
1864 //} 1779 //}
1865 // } 1780 // }
1866 } 1781 }
1867 1782/*
1868 private int TriArrayCallback(IntPtr trimesh, IntPtr refObject, int[] triangleIndex, int triCount) 1783 private int TriArrayCallback(IntPtr trimesh, IntPtr refObject, int[] triangleIndex, int triCount)
1869 { 1784 {
1870 /* String name1 = null; 1785 String name1 = null;
1871 String name2 = null; 1786 String name2 = null;
1872 1787
1873 if (!geom_name_map.TryGetValue(trimesh, out name1)) 1788 if (!geom_name_map.TryGetValue(trimesh, out name1))
@@ -1880,7 +1795,7 @@ namespace OpenSim.Region.PhysicsModule.ODE
1880 } 1795 }
1881 1796
1882 m_log.InfoFormat("TriArrayCallback: A collision was detected between {1} and {2}", 0, name1, name2); 1797 m_log.InfoFormat("TriArrayCallback: A collision was detected between {1} and {2}", 0, name1, name2);
1883 */ 1798
1884 return 1; 1799 return 1;
1885 } 1800 }
1886 1801
@@ -1910,7 +1825,7 @@ namespace OpenSim.Region.PhysicsModule.ODE
1910 1825
1911 return 1; 1826 return 1;
1912 } 1827 }
1913 1828*/
1914 /// <summary> 1829 /// <summary>
1915 /// This is our collision testing routine in ODE 1830 /// This is our collision testing routine in ODE
1916 /// </summary> 1831 /// </summary>
@@ -2042,7 +1957,8 @@ namespace OpenSim.Region.PhysicsModule.ODE
2042 x = x - offsetX + 1f; 1957 x = x - offsetX + 1f;
2043 y = y - offsetY + 1f; 1958 y = y - offsetY + 1f;
2044 1959
2045 index = (int)((int)x * ((int)m_regionHeight +3) + (int)y); 1960 // map is rotated
1961 index = (int)x * ((int)m_regionHeight + 3) + (int)y;
2046 1962
2047 if (index < TerrainHeightFieldHeights[heightFieldGeom].Length) 1963 if (index < TerrainHeightFieldHeights[heightFieldGeom].Length)
2048 { 1964 {
@@ -2620,59 +2536,13 @@ namespace OpenSim.Region.PhysicsModule.ODE
2620 2536
2621 2537
2622 } 2538 }
2623 // we don't want to remove the main space
2624
2625 // If the geometry is in the targetspace, remove it from the target space
2626 //m_log.Warn(prim.m_targetSpace);
2627
2628 //if (prim.m_targetSpace != IntPtr.Zero)
2629 //{
2630 //if (d.SpaceQuery(prim.m_targetSpace, prim.prim_geom))
2631 //{
2632
2633 //if (d.GeomIsSpace(prim.m_targetSpace))
2634 //{
2635 //waitForSpaceUnlock(prim.m_targetSpace);
2636 //d.SpaceRemove(prim.m_targetSpace, prim.prim_geom);
2637 prim.m_targetSpace = IntPtr.Zero; 2539 prim.m_targetSpace = IntPtr.Zero;
2638 //}
2639 //else
2640 //{
2641 // m_log.Info("[Physics]: Invalid Scene passed to 'removeprim from scene':" +
2642 //((OdePrim)prim).m_targetSpace.ToString());
2643 //}
2644
2645 //}
2646 //}
2647 //m_log.Warn(prim.prim_geom);
2648
2649 if (!prim.RemoveGeom()) 2540 if (!prim.RemoveGeom())
2650 m_log.Warn("[ODE SCENE]: Unable to remove prim from physics scene"); 2541 m_log.Warn("[ODE SCENE]: Unable to remove prim from physics scene");
2651 2542
2652 lock (_prims) 2543 lock (_prims)
2653 _prims.Remove(prim); 2544 _prims.Remove(prim);
2654 2545
2655 //If there are no more geometries in the sub-space, we don't need it in the main space anymore
2656 //if (d.SpaceGetNumGeoms(prim.m_targetSpace) == 0)
2657 //{
2658 //if (prim.m_targetSpace != null)
2659 //{
2660 //if (d.GeomIsSpace(prim.m_targetSpace))
2661 //{
2662 //waitForSpaceUnlock(prim.m_targetSpace);
2663 //d.SpaceRemove(space, prim.m_targetSpace);
2664 // free up memory used by the space.
2665 //d.SpaceDestroy(prim.m_targetSpace);
2666 //int[] xyspace = calculateSpaceArrayItemFromPos(prim.Position);
2667 //resetSpaceArrayItemToZero(xyspace[0], xyspace[1]);
2668 //}
2669 //else
2670 //{
2671 //m_log.Info("[Physics]: Invalid Scene passed to 'removeprim from scene':" +
2672 //((OdePrim) prim).m_targetSpace.ToString());
2673 //}
2674 //}
2675 //}
2676 2546
2677 if (SupportsNINJAJoints) 2547 if (SupportsNINJAJoints)
2678 RemoveAllJointsConnectedToActorThreadLocked(prim); 2548 RemoveAllJointsConnectedToActorThreadLocked(prim);
@@ -2768,12 +2638,9 @@ namespace OpenSim.Region.PhysicsModule.ODE
2768 { 2638 {
2769 if (d.GeomIsSpace(currentspace)) 2639 if (d.GeomIsSpace(currentspace))
2770 { 2640 {
2771// waitForSpaceUnlock(currentspace);
2772// waitForSpaceUnlock(space);
2773 d.SpaceRemove(space, currentspace); 2641 d.SpaceRemove(space, currentspace);
2774 // free up memory used by the space. 2642 // free up memory used by the space.
2775 2643
2776 //d.SpaceDestroy(currentspace);
2777 resetSpaceArrayItemToZero(currentspace); 2644 resetSpaceArrayItemToZero(currentspace);
2778 } 2645 }
2779 else 2646 else
@@ -2831,7 +2698,7 @@ namespace OpenSim.Region.PhysicsModule.ODE
2831 if (newspace == IntPtr.Zero) 2698 if (newspace == IntPtr.Zero)
2832 { 2699 {
2833 newspace = createprimspace(iprimspaceArrItem[0], iprimspaceArrItem[1]); 2700 newspace = createprimspace(iprimspaceArrItem[0], iprimspaceArrItem[1]);
2834 d.HashSpaceSetLevels(newspace, smallHashspaceLow, smallHashspaceHigh); 2701 d.HashSpaceSetLevels(newspace, HashspaceLow, HashspaceHigh);
2835 } 2702 }
2836 2703
2837 return newspace; 2704 return newspace;
@@ -3052,6 +2919,46 @@ namespace OpenSim.Region.PhysicsModule.ODE
3052 } 2919 }
3053 } 2920 }
3054 2921
2922 // does all pending changes generated during region load process
2923 public override void ProcessPreSimulation()
2924 {
2925 lock (OdeLock)
2926 {
2927 if (world == IntPtr.Zero)
2928 {
2929 _taintedPrims.Clear();;
2930 return;
2931 }
2932
2933 int donechanges = 0;
2934 if (_taintedPrims.Count > 0)
2935 {
2936 m_log.InfoFormat("[Ode] start processing pending actor operations");
2937 int tstart = Util.EnvironmentTickCount();
2938
2939 lock (_taintedPrims)
2940 {
2941 foreach (OdePrim prim in _taintedPrims)
2942 {
2943 if (prim.m_taintremove)
2944 RemovePrimThreadLocked(prim);
2945 else
2946 prim.ProcessTaints();
2947
2948 prim.m_collisionscore = 0;
2949 donechanges++;
2950 }
2951 _taintedPrims.Clear();
2952 }
2953
2954 int time = Util.EnvironmentTickCountSubtract(tstart);
2955 m_log.InfoFormat("[Ode] finished {0} operations in {1}ms", donechanges, time);
2956 }
2957 m_log.InfoFormat("[Ode] {0} prim actors loaded",_prims.Count);
2958 }
2959 }
2960
2961
3055 /// <summary> 2962 /// <summary>
3056 /// This is our main simulate loop 2963 /// This is our main simulate loop
3057 /// </summary> 2964 /// </summary>
@@ -3077,26 +2984,12 @@ namespace OpenSim.Region.PhysicsModule.ODE
3077 2984
3078 float fps = 0; 2985 float fps = 0;
3079 2986
3080 float timeLeft = timeStep; 2987 step_time += timeStep;
2988
2989 float HalfOdeStep = ODE_STEPSIZE * 0.5f;
2990 if (step_time < HalfOdeStep)
2991 return 0;
3081 2992
3082 //m_log.Info(timeStep.ToString());
3083// step_time += timeSte
3084//
3085// // If We're loaded down by something else,
3086// // or debugging with the Visual Studio project on pause
3087// // skip a few frames to catch up gracefully.
3088// // without shooting the physicsactors all over the place
3089//
3090// if (step_time >= m_SkipFramesAtms)
3091// {
3092// // Instead of trying to catch up, it'll do 5 physics frames only
3093// step_time = ODE_STEPSIZE;
3094// m_physicsiterations = 5;
3095// }
3096// else
3097// {
3098// m_physicsiterations = 10;
3099// }
3100 2993
3101 // We change _collisionEventPrimChanges to avoid locking _collisionEventPrim itself and causing potential 2994 // We change _collisionEventPrimChanges to avoid locking _collisionEventPrim itself and causing potential
3102 // deadlock if the collision event tries to lock something else later on which is already locked by a 2995 // deadlock if the collision event tries to lock something else later on which is already locked by a
@@ -3138,11 +3031,11 @@ namespace OpenSim.Region.PhysicsModule.ODE
3138 // Figure out the Frames Per Second we're going at. 3031 // Figure out the Frames Per Second we're going at.
3139 //(step_time == 0.004f, there's 250 of those per second. Times the step time/step size 3032 //(step_time == 0.004f, there's 250 of those per second. Times the step time/step size
3140 3033
3141 fps = (timeStep / ODE_STEPSIZE) * 1000; 3034
3142 // HACK: Using a time dilation of 1.0 to debug rubberbanding issues 3035 // HACK: Using a time dilation of 1.0 to debug rubberbanding issues
3143 //m_timeDilation = Math.Min((step_time / ODE_STEPSIZE) / (0.09375f / ODE_STEPSIZE), 1.0f); 3036 //m_timeDilation = Math.Min((step_time / ODE_STEPSIZE) / (0.09375f / ODE_STEPSIZE), 1.0f);
3144 3037
3145 while (timeLeft > 0.0f) 3038 while (step_time > HalfOdeStep)
3146 { 3039 {
3147 try 3040 try
3148 { 3041 {
@@ -3307,7 +3200,8 @@ namespace OpenSim.Region.PhysicsModule.ODE
3307 m_log.ErrorFormat("[ODE SCENE]: {0}, {1}, {2}", e.Message, e.TargetSite, e); 3200 m_log.ErrorFormat("[ODE SCENE]: {0}, {1}, {2}", e.Message, e.TargetSite, e);
3308 } 3201 }
3309 3202
3310 timeLeft -= ODE_STEPSIZE; 3203 step_time -= ODE_STEPSIZE;
3204 fps += ODE_STEPSIZE;
3311 } 3205 }
3312 3206
3313 if (CollectStats) 3207 if (CollectStats)
@@ -3403,6 +3297,7 @@ namespace OpenSim.Region.PhysicsModule.ODE
3403 m_stats[ODETotalFrameMsStatName] += Util.EnvironmentTickCountSubtract(startFrameTick); 3297 m_stats[ODETotalFrameMsStatName] += Util.EnvironmentTickCountSubtract(startFrameTick);
3404 } 3298 }
3405 3299
3300 fps *= 1.0f/timeStep;
3406 return fps; 3301 return fps;
3407 } 3302 }
3408 3303
@@ -3675,7 +3570,6 @@ namespace OpenSim.Region.PhysicsModule.ODE
3675 3570
3676 _heightmap = new float[heightmapWidthSamples * heightmapHeightSamples]; 3571 _heightmap = new float[heightmapWidthSamples * heightmapHeightSamples];
3677 3572
3678
3679 const float scale = 1.0f; 3573 const float scale = 1.0f;
3680 const float offset = 0.0f; 3574 const float offset = 0.0f;
3681 const float thickness = 10f; 3575 const float thickness = 10f;
@@ -3740,7 +3634,8 @@ namespace OpenSim.Region.PhysicsModule.ODE
3740 IntPtr HeightmapData = d.GeomHeightfieldDataCreate(); 3634 IntPtr HeightmapData = d.GeomHeightfieldDataCreate();
3741 d.GeomHeightfieldDataBuildSingle(HeightmapData, _heightmap, 0, 3635 d.GeomHeightfieldDataBuildSingle(HeightmapData, _heightmap, 0,
3742 heightmapWidth, heightmapHeight, 3636 heightmapWidth, heightmapHeight,
3743 (int)heightmapWidthSamples, (int)heightmapHeightSamples, 3637 (int)heightmapWidthSamples,
3638 (int)heightmapHeightSamples,
3744 scale, offset, thickness, wrap); 3639 scale, offset, thickness, wrap);
3745 3640
3746 d.GeomHeightfieldDataSetBounds(HeightmapData, hfmin - 1, hfmax + 1); 3641 d.GeomHeightfieldDataSetBounds(HeightmapData, hfmin - 1, hfmax + 1);
@@ -3765,7 +3660,7 @@ namespace OpenSim.Region.PhysicsModule.ODE
3765 3660
3766 d.RFromAxisAndAngle(out R, v3.X, v3.Y, v3.Z, angle); 3661 d.RFromAxisAndAngle(out R, v3.X, v3.Y, v3.Z, angle);
3767 d.GeomSetRotation(GroundGeom, ref R); 3662 d.GeomSetRotation(GroundGeom, ref R);
3768 d.GeomSetPosition(GroundGeom, pOffset.X + regionsizeX * 0.5f, pOffset.Y + regionsizeY * 0.5f, 0f); 3663 d.GeomSetPosition(GroundGeom, pOffset.X + regionsizeX * 0.5f, pOffset.Y + regionsizeY * 0.5f, 0.0f);
3769 IntPtr testGround = IntPtr.Zero; 3664 IntPtr testGround = IntPtr.Zero;
3770 if (RegionTerrain.TryGetValue(pOffset, out testGround)) 3665 if (RegionTerrain.TryGetValue(pOffset, out testGround))
3771 { 3666 {
@@ -3796,74 +3691,24 @@ namespace OpenSim.Region.PhysicsModule.ODE
3796 public override void SetWaterLevel(float baseheight) 3691 public override void SetWaterLevel(float baseheight)
3797 { 3692 {
3798 waterlevel = baseheight; 3693 waterlevel = baseheight;
3799// randomizeWater(waterlevel);
3800 } 3694 }
3801 3695
3802/* 3696 [HandleProcessCorruptedStateExceptions]
3803 private void randomizeWater(float baseheight) 3697 public override void Dispose()
3804 { 3698 {
3805 uint heightmapWidth = m_regionWidth + 2;
3806 uint heightmapHeight = m_regionHeight + 2;
3807 uint heightmapWidthSamples = m_regionWidth + 2;
3808 uint heightmapHeightSamples = m_regionHeight + 2;
3809 float scale = 1.0f;
3810 float offset = 0.0f;
3811 float thickness = 2.9f;
3812 int wrap = 0;
3813
3814 for (int i = 0; i < (258 * 258); i++)
3815 {
3816 _watermap[i] = (baseheight-0.1f) + ((float)fluidRandomizer.Next(1,9) / 10f);
3817 // m_log.Info((baseheight - 0.1f) + ((float)fluidRandomizer.Next(1, 9) / 10f));
3818 }
3819
3820 lock (OdeLock) 3699 lock (OdeLock)
3821 { 3700 {
3822 if (WaterGeom != IntPtr.Zero) 3701 if(world == IntPtr.Zero)
3823 { 3702 return;
3824 d.SpaceRemove(space, WaterGeom);
3825 }
3826 IntPtr HeightmapData = d.GeomHeightfieldDataCreate();
3827 d.GeomHeightfieldDataBuildSingle(HeightmapData, _watermap, 0, heightmapWidth, heightmapHeight,
3828 (int)heightmapWidthSamples, (int)heightmapHeightSamples, scale,
3829 offset, thickness, wrap);
3830 d.GeomHeightfieldDataSetBounds(HeightmapData, m_regionWidth, m_regionHeight);
3831 WaterGeom = d.CreateHeightfield(space, HeightmapData, 1);
3832 if (WaterGeom != IntPtr.Zero)
3833 {
3834 d.GeomSetCategoryBits(WaterGeom, (int)(CollisionCategories.Water));
3835 d.GeomSetCollideBits(WaterGeom, (int)(CollisionCategories.Space));
3836 }
3837
3838 geom_name_map[WaterGeom] = "Water";
3839
3840 d.Matrix3 R = new d.Matrix3();
3841
3842 Quaternion q1 = Quaternion.CreateFromAxisAngle(new Vector3(1, 0, 0), 1.5707f);
3843 Quaternion q2 = Quaternion.CreateFromAxisAngle(new Vector3(0, 1, 0), 1.5707f);
3844 //Axiom.Math.Quaternion q3 = Axiom.Math.Quaternion.FromAngleAxis(3.14f, new Axiom.Math.Vector3(0, 0, 1));
3845
3846 q1 = q1 * q2;
3847 //q1 = q1 * q3;
3848 Vector3 v3;
3849 float angle;
3850 q1.GetAxisAngle(out v3, out angle);
3851 3703
3852 d.RFromAxisAndAngle(out R, v3.X, v3.Y, v3.Z, angle); 3704 _worldInitialized = false;
3853 d.GeomSetRotation(WaterGeom, ref R);
3854 d.GeomSetPosition(WaterGeom, 128, 128, 0);
3855 }
3856 }
3857*/
3858 public override void Dispose()
3859 {
3860 _worldInitialized = false;
3861 3705
3862 m_rayCastManager.Dispose(); 3706 if (m_rayCastManager != null)
3863 m_rayCastManager = null; 3707 {
3708 m_rayCastManager.Dispose();
3709 m_rayCastManager = null;
3710 }
3864 3711
3865 lock (OdeLock)
3866 {
3867 lock (_prims) 3712 lock (_prims)
3868 { 3713 {
3869 foreach (OdePrim prm in _prims) 3714 foreach (OdePrim prm in _prims)
@@ -3876,10 +3721,29 @@ namespace OpenSim.Region.PhysicsModule.ODE
3876 //{ 3721 //{
3877 //RemoveAvatar(act); 3722 //RemoveAvatar(act);
3878 //} 3723 //}
3879 d.WorldDestroy(world); 3724 IntPtr GroundGeom = IntPtr.Zero;
3725 if (RegionTerrain.TryGetValue(m_worldOffset, out GroundGeom))
3726 {
3727 RegionTerrain.Remove(m_worldOffset);
3728 if (GroundGeom != IntPtr.Zero)
3729 {
3730 if (TerrainHeightFieldHeights.ContainsKey(GroundGeom))
3731 TerrainHeightFieldHeights.Remove(GroundGeom);
3732 d.GeomDestroy(GroundGeom);
3733 }
3734 }
3735
3736 try
3737 {
3738 d.WorldDestroy(world);
3739 world = IntPtr.Zero;
3740 }
3741 catch (AccessViolationException e)
3742 {
3743 m_log.ErrorFormat("[ODE SCENE]: exception {0}", e.Message);
3744 }
3880 //d.CloseODE(); 3745 //d.CloseODE();
3881 } 3746 }
3882
3883 } 3747 }
3884 3748
3885 public override Dictionary<uint, float> GetTopColliders() 3749 public override Dictionary<uint, float> GetTopColliders()
diff --git a/OpenSim/Region/PhysicsModules/Ode/Tests/ODETestClass.cs b/OpenSim/Region/PhysicsModules/Ode/Tests/ODETestClass.cs
index 6dc22bd..2c134e7 100644
--- a/OpenSim/Region/PhysicsModules/Ode/Tests/ODETestClass.cs
+++ b/OpenSim/Region/PhysicsModules/Ode/Tests/ODETestClass.cs
@@ -47,6 +47,8 @@ namespace OpenSim.Region.PhysicsModule.ODE.Tests
47 47
48 //private OpenSim.Region.PhysicsModule.ODE.OdePlugin cbt; 48 //private OpenSim.Region.PhysicsModule.ODE.OdePlugin cbt;
49 private PhysicsScene pScene; 49 private PhysicsScene pScene;
50 private OpenSim.Region.PhysicsModule.ODE.OdeModule odemodule;
51
50 52
51 [SetUp] 53 [SetUp]
52 public void Initialize() 54 public void Initialize()
@@ -65,19 +67,18 @@ namespace OpenSim.Region.PhysicsModule.ODE.Tests
65 info.RegionSizeX = info.RegionSizeY = info.RegionSizeZ = Constants.RegionSize; 67 info.RegionSizeX = info.RegionSizeY = info.RegionSizeZ = Constants.RegionSize;
66 OpenSim.Region.Framework.Scenes.Scene scene = new OpenSim.Region.Framework.Scenes.Scene(info); 68 OpenSim.Region.Framework.Scenes.Scene scene = new OpenSim.Region.Framework.Scenes.Scene(info);
67 69
68 //IMesher mesher = new OpenSim.Region.PhysicsModules.Meshing.Meshmerizer(); 70 //IMesher mesher = new OpenSim.Region.PhysicsModule.Meshing.Meshmerizer();
69 //INonSharedRegionModule mod = mesher as INonSharedRegionModule; 71 //INonSharedRegionModule mod = mesher as INonSharedRegionModule;
70 //mod.Initialise(openSimINI); 72 //mod.Initialise(openSimINI);
71 //mod.AddRegion(scene); 73 //mod.AddRegion(scene);
72 //mod.RegionLoaded(scene); 74 //mod.RegionLoaded(scene);
73 75
74 pScene = new OdeScene(); 76 // pScene = new OdeScene();
75 Console.WriteLine("HERE " + (pScene == null ? "Null" : "Not null")); 77 odemodule = new OpenSim.Region.PhysicsModule.ODE.OdeModule();
76 INonSharedRegionModule mod = (pScene as INonSharedRegionModule); 78 Console.WriteLine("HERE " + (odemodule == null ? "Null" : "Not null"));
77 Console.WriteLine("HERE " + (mod == null ? "Null" : "Not null")); 79 odemodule.Initialise(openSimINI);
78 mod.Initialise(openSimINI); 80 odemodule.AddRegion(scene);
79 mod.AddRegion(scene); 81 odemodule.RegionLoaded(scene);
80 mod.RegionLoaded(scene);
81 82
82 // Loading ODEPlugin 83 // Loading ODEPlugin
83 //cbt = new OdePlugin(); 84 //cbt = new OdePlugin();
@@ -90,6 +91,7 @@ namespace OpenSim.Region.PhysicsModule.ODE.Tests
90 { 91 {
91 _heightmap[i] = 21f; 92 _heightmap[i] = 21f;
92 } 93 }
94 pScene = scene.PhysicsScene;
93 pScene.SetTerrain(_heightmap); 95 pScene.SetTerrain(_heightmap);
94 } 96 }
95 97
diff --git a/OpenSim/Region/PhysicsModules/POS/POSCharacter.cs b/OpenSim/Region/PhysicsModules/POS/POSCharacter.cs
index 32469d9..28d2b53 100644
--- a/OpenSim/Region/PhysicsModules/POS/POSCharacter.cs
+++ b/OpenSim/Region/PhysicsModules/POS/POSCharacter.cs
@@ -248,7 +248,7 @@ namespace OpenSim.Region.PhysicsModule.POS
248 { 248 {
249 } 249 }
250 250
251 public override void LockAngularMotion(Vector3 axis) 251 public override void LockAngularMotion(byte axislocks)
252 { 252 {
253 } 253 }
254 254
@@ -291,6 +291,7 @@ namespace OpenSim.Region.PhysicsModule.POS
291 291
292 public override bool PIDHoverActive 292 public override bool PIDHoverActive
293 { 293 {
294 get { return false; }
294 set { return; } 295 set { return; }
295 } 296 }
296 297
diff --git a/OpenSim/Region/PhysicsModules/POS/POSPrim.cs b/OpenSim/Region/PhysicsModules/POS/POSPrim.cs
index 8aae716..180885d 100644
--- a/OpenSim/Region/PhysicsModules/POS/POSPrim.cs
+++ b/OpenSim/Region/PhysicsModules/POS/POSPrim.cs
@@ -250,7 +250,7 @@ namespace OpenSim.Region.PhysicsModule.POS
250 { 250 {
251 } 251 }
252 252
253 public override void LockAngularMotion(Vector3 axis) 253 public override void LockAngularMotion(byte axislocks)
254 { 254 {
255 } 255 }
256 256
@@ -286,6 +286,7 @@ namespace OpenSim.Region.PhysicsModule.POS
286 286
287 public override bool PIDHoverActive 287 public override bool PIDHoverActive
288 { 288 {
289 get { return false; }
289 set { return; } 290 set { return; }
290 } 291 }
291 292
@@ -298,7 +299,7 @@ namespace OpenSim.Region.PhysicsModule.POS
298 { 299 {
299 set { return; } 300 set { return; }
300 } 301 }
301 302
302 public override Quaternion APIDTarget 303 public override Quaternion APIDTarget
303 { 304 {
304 set { return; } 305 set { return; }
diff --git a/OpenSim/Region/PhysicsModules/POS/POSScene.cs b/OpenSim/Region/PhysicsModules/POS/POSScene.cs
index 6375f18..e6bcbf2 100644
--- a/OpenSim/Region/PhysicsModules/POS/POSScene.cs
+++ b/OpenSim/Region/PhysicsModules/POS/POSScene.cs
@@ -288,7 +288,7 @@ namespace OpenSim.Region.PhysicsModule.POS
288 character._velocity.Z = (character.Position.Z - oldposZ)/timeStep; 288 character._velocity.Z = (character.Position.Z - oldposZ)/timeStep;
289 } 289 }
290 } 290 }
291 return fps; 291 return 1.0f;
292 } 292 }
293 293
294 public override void GetResults() 294 public override void GetResults()
diff --git a/OpenSim/Region/PhysicsModules/SharedBase/IMesher.cs b/OpenSim/Region/PhysicsModules/SharedBase/IMesher.cs
index 5c75307..88169bb 100644
--- a/OpenSim/Region/PhysicsModules/SharedBase/IMesher.cs
+++ b/OpenSim/Region/PhysicsModules/SharedBase/IMesher.cs
@@ -27,6 +27,7 @@
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Runtime.InteropServices;
30using OpenSim.Framework; 31using OpenSim.Framework;
31using OpenMetaverse; 32using OpenMetaverse;
32 33
@@ -36,7 +37,12 @@ namespace OpenSim.Region.PhysicsModules.SharedBase
36 { 37 {
37 IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod); 38 IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod);
38 IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical); 39 IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical);
39 IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool shouldCache); 40 IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex, bool forOde);
41 IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool shouldCache, bool convex, bool forOde);
42 IMesh GetMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex);
43 void ReleaseMesh(IMesh mesh);
44 void ExpireReleaseMeshs();
45 void ExpireFileCache();
40 } 46 }
41 47
42 // Values for level of detail to be passed to the mesher. 48 // Values for level of detail to be passed to the mesher.
@@ -54,6 +60,25 @@ namespace OpenSim.Region.PhysicsModules.SharedBase
54 { 60 {
55 } 61 }
56 62
63 [Serializable()]
64 [StructLayout(LayoutKind.Explicit)]
65 public struct AMeshKey
66 {
67 [FieldOffset(0)]
68 public UUID uuid;
69 [FieldOffset(0)]
70 public ulong hashA;
71 [FieldOffset(8)]
72 public ulong hashB;
73 [FieldOffset(16)]
74 public ulong hashC;
75
76 public override string ToString()
77 {
78 return uuid.ToString() + "-" + hashC.ToString("x") ;
79 }
80 }
81
57 public interface IMesh 82 public interface IMesh
58 { 83 {
59 List<Vector3> getVertexList(); 84 List<Vector3> getVertexList();
@@ -67,5 +92,7 @@ namespace OpenSim.Region.PhysicsModules.SharedBase
67 void releasePinned(); 92 void releasePinned();
68 void Append(IMesh newMesh); 93 void Append(IMesh newMesh);
69 void TransformLinear(float[,] matrix, float[] offset); 94 void TransformLinear(float[,] matrix, float[] offset);
95 Vector3 GetCentroid();
96 Vector3 GetOBB();
70 } 97 }
71} 98}
diff --git a/OpenSim/Region/PhysicsModules/SharedBase/PhysicsActor.cs b/OpenSim/Region/PhysicsModules/SharedBase/PhysicsActor.cs
index c04ff58..ebd2185 100644
--- a/OpenSim/Region/PhysicsModules/SharedBase/PhysicsActor.cs
+++ b/OpenSim/Region/PhysicsModules/SharedBase/PhysicsActor.cs
@@ -43,7 +43,8 @@ namespace OpenSim.Region.PhysicsModules.SharedBase
43 Unknown = 0, 43 Unknown = 0,
44 Agent = 1, 44 Agent = 1,
45 Prim = 2, 45 Prim = 2,
46 Ground = 3 46 Ground = 3,
47 Water = 4
47 } 48 }
48 49
49 public enum PIDHoverType 50 public enum PIDHoverType
@@ -59,15 +60,41 @@ namespace OpenSim.Region.PhysicsModules.SharedBase
59 public Vector3 Position; 60 public Vector3 Position;
60 public Vector3 SurfaceNormal; 61 public Vector3 SurfaceNormal;
61 public float PenetrationDepth; 62 public float PenetrationDepth;
63 public float RelativeSpeed;
64 public bool CharacterFeet;
62 65
63 public ContactPoint(Vector3 position, Vector3 surfaceNormal, float penetrationDepth) 66 public ContactPoint(Vector3 position, Vector3 surfaceNormal, float penetrationDepth)
64 { 67 {
65 Position = position; 68 Position = position;
66 SurfaceNormal = surfaceNormal; 69 SurfaceNormal = surfaceNormal;
67 PenetrationDepth = penetrationDepth; 70 PenetrationDepth = penetrationDepth;
71 RelativeSpeed = 0f; // for now let this one be set explicity
72 CharacterFeet = true; // keep other plugins work as before
73 }
74
75 public ContactPoint(Vector3 position, Vector3 surfaceNormal, float penetrationDepth, bool feet)
76 {
77 Position = position;
78 SurfaceNormal = surfaceNormal;
79 PenetrationDepth = penetrationDepth;
80 RelativeSpeed = 0f; // for now let this one be set explicity
81 CharacterFeet = feet; // keep other plugins work as before
68 } 82 }
69 } 83 }
70 84
85 public struct ContactData
86 {
87 public float mu;
88 public float bounce;
89 public bool softcolide;
90
91 public ContactData(float _mu, float _bounce, bool _softcolide)
92 {
93 mu = _mu;
94 bounce = _bounce;
95 softcolide = _softcolide;
96 }
97 }
71 /// <summary> 98 /// <summary>
72 /// Used to pass collision information to OnCollisionUpdate listeners. 99 /// Used to pass collision information to OnCollisionUpdate listeners.
73 /// </summary> 100 /// </summary>
@@ -99,7 +126,7 @@ namespace OpenSim.Region.PhysicsModules.SharedBase
99 m_objCollisionList.Add(localID, contact); 126 m_objCollisionList.Add(localID, contact);
100 } 127 }
101 else 128 else
102 { 129 {
103 if (m_objCollisionList[localID].PenetrationDepth < contact.PenetrationDepth) 130 if (m_objCollisionList[localID].PenetrationDepth < contact.PenetrationDepth)
104 m_objCollisionList[localID] = contact; 131 m_objCollisionList[localID] = contact;
105 } 132 }
@@ -142,11 +169,32 @@ namespace OpenSim.Region.PhysicsModules.SharedBase
142 { 169 {
143 get { return new NullPhysicsActor(); } 170 get { return new NullPhysicsActor(); }
144 } 171 }
172
173 public virtual bool Building { get; set; }
174
175 public virtual void getContactData(ref ContactData cdata)
176 {
177 cdata.mu = 0;
178 cdata.bounce = 0;
179 }
145 180
146 public abstract bool Stopped { get; } 181 public abstract bool Stopped { get; }
147 182
148 public abstract Vector3 Size { get; set; } 183 public abstract Vector3 Size { get; set; }
149 184
185 public virtual void setAvatarSize(Vector3 size, float feetOffset)
186 {
187 Size = size;
188 }
189
190 public virtual bool Phantom { get; set; }
191
192 public virtual bool IsVolumeDtc
193 {
194 get { return false; }
195 set { return; }
196 }
197
150 public virtual byte PhysicsShapeType { get; set; } 198 public virtual byte PhysicsShapeType { get; set; }
151 199
152 public abstract PrimitiveBaseShape Shape { set; } 200 public abstract PrimitiveBaseShape Shape { set; }
@@ -169,7 +217,7 @@ namespace OpenSim.Region.PhysicsModules.SharedBase
169 /// XXX: Bizarrely, this cannot be "Terrain" or "Water" right now unless it really is simulating terrain or 217 /// XXX: Bizarrely, this cannot be "Terrain" or "Water" right now unless it really is simulating terrain or
170 /// water. This is not a problem due to the formatting of names given by prims and avatars. 218 /// water. This is not a problem due to the formatting of names given by prims and avatars.
171 /// </remarks> 219 /// </remarks>
172 public string Name { get; protected set; } 220 public string Name { get; set; }
173 221
174 /// <summary> 222 /// <summary>
175 /// This is being used by ODE joint code. 223 /// This is being used by ODE joint code.
@@ -182,8 +230,8 @@ namespace OpenSim.Region.PhysicsModules.SharedBase
182 230
183 public abstract void delink(); 231 public abstract void delink();
184 232
185 public abstract void LockAngularMotion(Vector3 axis); 233 public abstract void LockAngularMotion(byte axislocks);
186 234
187 public virtual void RequestPhysicsterseUpdate() 235 public virtual void RequestPhysicsterseUpdate()
188 { 236 {
189 // Make a temporary copy of the event to avoid possibility of 237 // Make a temporary copy of the event to avoid possibility of
@@ -245,6 +293,56 @@ namespace OpenSim.Region.PhysicsModules.SharedBase
245 public abstract void VehicleRotationParam(int param, Quaternion rotation); 293 public abstract void VehicleRotationParam(int param, Quaternion rotation);
246 public abstract void VehicleFlags(int param, bool remove); 294 public abstract void VehicleFlags(int param, bool remove);
247 295
296 // This is an overridable version of SetVehicle() that works for all physics engines.
297 // This is VERY inefficient. It behoves any physics engine to override this and
298 // implement a more efficient setting of all the vehicle parameters.
299 public virtual void SetVehicle(object pvdata)
300 {
301 VehicleData vdata = (VehicleData)pvdata;
302 // vehicleActor.ProcessSetVehicle((VehicleData)vdata);
303
304 this.VehicleType = (int)vdata.m_type;
305 this.VehicleFlags(-1, false); // clears all flags
306 this.VehicleFlags((int)vdata.m_flags, false);
307
308 // Linear properties
309 this.VehicleVectorParam((int)Vehicle.LINEAR_MOTOR_DIRECTION, vdata.m_linearMotorDirection);
310 this.VehicleVectorParam((int)Vehicle.LINEAR_FRICTION_TIMESCALE, vdata.m_linearFrictionTimescale);
311 this.VehicleFloatParam((int)Vehicle.LINEAR_MOTOR_DECAY_TIMESCALE, vdata.m_linearMotorDecayTimescale);
312 this.VehicleFloatParam((int)Vehicle.LINEAR_MOTOR_TIMESCALE, vdata.m_linearMotorTimescale);
313 this.VehicleVectorParam((int)Vehicle.LINEAR_MOTOR_OFFSET, vdata.m_linearMotorOffset);
314
315 //Angular properties
316 this.VehicleVectorParam((int)Vehicle.ANGULAR_MOTOR_DIRECTION, vdata.m_angularMotorDirection);
317 this.VehicleFloatParam((int)Vehicle.ANGULAR_MOTOR_TIMESCALE, vdata.m_angularMotorTimescale);
318 this.VehicleFloatParam((int)Vehicle.ANGULAR_MOTOR_DECAY_TIMESCALE, vdata.m_angularMotorDecayTimescale);
319 this.VehicleVectorParam((int)Vehicle.ANGULAR_FRICTION_TIMESCALE, vdata.m_angularFrictionTimescale);
320
321 //Deflection properties
322 this.VehicleFloatParam((int)Vehicle.ANGULAR_DEFLECTION_EFFICIENCY, vdata.m_angularDeflectionEfficiency);
323 this.VehicleFloatParam((int)Vehicle.ANGULAR_DEFLECTION_TIMESCALE, vdata.m_angularDeflectionTimescale);
324 this.VehicleFloatParam((int)Vehicle.LINEAR_DEFLECTION_EFFICIENCY, vdata.m_linearDeflectionEfficiency);
325 this.VehicleFloatParam((int)Vehicle.LINEAR_DEFLECTION_TIMESCALE, vdata.m_linearDeflectionTimescale);
326
327 //Banking properties
328 this.VehicleFloatParam((int)Vehicle.BANKING_EFFICIENCY, vdata.m_bankingEfficiency);
329 this.VehicleFloatParam((int)Vehicle.BANKING_MIX, vdata.m_bankingMix);
330 this.VehicleFloatParam((int)Vehicle.BANKING_TIMESCALE, vdata.m_bankingTimescale);
331
332 //Hover and Buoyancy properties
333 this.VehicleFloatParam((int)Vehicle.HOVER_HEIGHT, vdata.m_VhoverHeight);
334 this.VehicleFloatParam((int)Vehicle.HOVER_EFFICIENCY, vdata.m_VhoverEfficiency);
335 this.VehicleFloatParam((int)Vehicle.HOVER_TIMESCALE, vdata.m_VhoverTimescale);
336 this.VehicleFloatParam((int)Vehicle.BUOYANCY, vdata.m_VehicleBuoyancy);
337
338 //Attractor properties
339 this.VehicleFloatParam((int)Vehicle.VERTICAL_ATTRACTION_EFFICIENCY, vdata.m_verticalAttractionEfficiency);
340 this.VehicleFloatParam((int)Vehicle.VERTICAL_ATTRACTION_TIMESCALE, vdata.m_verticalAttractionTimescale);
341
342 this.VehicleRotationParam((int)Vehicle.REFERENCE_FRAME, vdata.m_referenceFrame);
343 }
344
345
248 /// <summary> 346 /// <summary>
249 /// Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more 347 /// Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more
250 /// </summary> 348 /// </summary>
@@ -253,6 +351,51 @@ namespace OpenSim.Region.PhysicsModules.SharedBase
253 public abstract Vector3 GeometricCenter { get; } 351 public abstract Vector3 GeometricCenter { get; }
254 public abstract Vector3 CenterOfMass { get; } 352 public abstract Vector3 CenterOfMass { get; }
255 353
354 public virtual Vector3 OOBsize
355 {
356 get
357 {
358 Vector3 s=Size;
359 s.X *=0.5f;
360 s.Y *=0.5f;
361 s.Z *=0.5f;
362 return s;
363 }
364 }
365
366 public virtual Vector3 OOBoffset
367 {
368 get
369 {
370 return Vector3.Zero;
371 }
372 }
373
374 public virtual float OOBRadiusSQ
375 {
376 get
377 {
378 return Size.LengthSquared() * 0.25f; // ((0.5^2)
379 }
380 }
381
382
383 public virtual float PhysicsCost
384 {
385 get
386 {
387 return 0.1f;
388 }
389 }
390
391 public virtual float StreamCost
392 {
393 get
394 {
395 return 1.0f;
396 }
397 }
398
256 /// <summary> 399 /// <summary>
257 /// The desired velocity of this actor. 400 /// The desired velocity of this actor.
258 /// </summary> 401 /// </summary>
@@ -296,7 +439,7 @@ namespace OpenSim.Region.PhysicsModules.SharedBase
296 439
297 // Used for llSetHoverHeight and maybe vehicle height 440 // Used for llSetHoverHeight and maybe vehicle height
298 // Hover Height will override MoveTo target's Z 441 // Hover Height will override MoveTo target's Z
299 public abstract bool PIDHoverActive { set;} 442 public abstract bool PIDHoverActive {get; set;}
300 public abstract float PIDHoverHeight { set;} 443 public abstract float PIDHoverHeight { set;}
301 public abstract PIDHoverType PIDHoverType { set;} 444 public abstract PIDHoverType PIDHoverType { set;}
302 public abstract float PIDHoverTau { set;} 445 public abstract float PIDHoverTau { set;}
@@ -314,6 +457,12 @@ namespace OpenSim.Region.PhysicsModules.SharedBase
314 public abstract void UnSubscribeEvents(); 457 public abstract void UnSubscribeEvents();
315 public abstract bool SubscribedEvents(); 458 public abstract bool SubscribedEvents();
316 459
460 public virtual void AddCollisionEvent(uint CollidedWith, ContactPoint contact) { }
461
462 // Warning in a parent part it returns itself, not null
463 public virtual PhysicsActor ParentActor { get { return this; } }
464
465
317 // Extendable interface for new, physics engine specific operations 466 // Extendable interface for new, physics engine specific operations
318 public virtual object Extension(string pFunct, params object[] pParams) 467 public virtual object Extension(string pFunct, params object[] pParams)
319 { 468 {
@@ -324,9 +473,11 @@ namespace OpenSim.Region.PhysicsModules.SharedBase
324 473
325 public class NullPhysicsActor : PhysicsActor 474 public class NullPhysicsActor : PhysicsActor
326 { 475 {
476 private ActorTypes m_actorType = ActorTypes.Unknown;
477
327 public override bool Stopped 478 public override bool Stopped
328 { 479 {
329 get{ return false; } 480 get{ return true; }
330 } 481 }
331 482
332 public override Vector3 Position 483 public override Vector3 Position
@@ -343,6 +494,7 @@ namespace OpenSim.Region.PhysicsModules.SharedBase
343 494
344 public override uint LocalID 495 public override uint LocalID
345 { 496 {
497 get { return 0; }
346 set { return; } 498 set { return; }
347 } 499 }
348 500
@@ -402,50 +554,17 @@ namespace OpenSim.Region.PhysicsModules.SharedBase
402 set { return; } 554 set { return; }
403 } 555 }
404 556
405 public override void VehicleFloatParam(int param, float value) 557 public override void VehicleFloatParam(int param, float value) {}
406 { 558 public override void VehicleVectorParam(int param, Vector3 value) { }
407 559 public override void VehicleRotationParam(int param, Quaternion rotation) { }
408 } 560 public override void VehicleFlags(int param, bool remove) { }
409 561 public override void SetVolumeDetect(int param) {}
410 public override void VehicleVectorParam(int param, Vector3 value) 562 public override void SetMaterial(int material) {}
411 { 563 public override Vector3 CenterOfMass { get { return Vector3.Zero; }}
412
413 }
414
415 public override void VehicleRotationParam(int param, Quaternion rotation)
416 {
417
418 }
419 564
420 public override void VehicleFlags(int param, bool remove) 565 public override Vector3 GeometricCenter { get { return Vector3.Zero; }}
421 {
422
423 }
424
425 public override void SetVolumeDetect(int param)
426 {
427
428 }
429
430 public override void SetMaterial(int material)
431 {
432
433 }
434
435 public override Vector3 CenterOfMass
436 {
437 get { return Vector3.Zero; }
438 }
439
440 public override Vector3 GeometricCenter
441 {
442 get { return Vector3.Zero; }
443 }
444 566
445 public override PrimitiveBaseShape Shape 567 public override PrimitiveBaseShape Shape { set { return; }}
446 {
447 set { return; }
448 }
449 568
450 public override Vector3 Velocity 569 public override Vector3 Velocity
451 { 570 {
@@ -465,9 +584,7 @@ namespace OpenSim.Region.PhysicsModules.SharedBase
465 set { } 584 set { }
466 } 585 }
467 586
468 public override void CrossingFailure() 587 public override void CrossingFailure() {}
469 {
470 }
471 588
472 public override Quaternion Orientation 589 public override Quaternion Orientation
473 { 590 {
@@ -507,8 +624,20 @@ namespace OpenSim.Region.PhysicsModules.SharedBase
507 624
508 public override int PhysicsActorType 625 public override int PhysicsActorType
509 { 626 {
510 get { return (int) ActorTypes.Unknown; } 627 get { return (int)m_actorType; }
511 set { return; } 628 set {
629 ActorTypes type = (ActorTypes)value;
630 switch (type)
631 {
632 case ActorTypes.Ground:
633 case ActorTypes.Water:
634 m_actorType = type;
635 break;
636 default:
637 m_actorType = ActorTypes.Unknown;
638 break;
639 }
640 }
512 } 641 }
513 642
514 public override bool Kinematic 643 public override bool Kinematic
@@ -517,26 +646,11 @@ namespace OpenSim.Region.PhysicsModules.SharedBase
517 set { return; } 646 set { return; }
518 } 647 }
519 648
520 public override void link(PhysicsActor obj) 649 public override void link(PhysicsActor obj) { }
521 { 650 public override void delink() { }
522 } 651 public override void LockAngularMotion(byte axislocks) { }
523 652 public override void AddForce(Vector3 force, bool pushforce) { }
524 public override void delink() 653 public override void AddAngularForce(Vector3 force, bool pushforce) { }
525 {
526 }
527
528 public override void LockAngularMotion(Vector3 axis)
529 {
530 }
531
532 public override void AddForce(Vector3 force, bool pushforce)
533 {
534 }
535
536 public override void AddAngularForce(Vector3 force, bool pushforce)
537 {
538
539 }
540 654
541 public override Vector3 RotationalVelocity 655 public override Vector3 RotationalVelocity
542 { 656 {
@@ -555,7 +669,7 @@ namespace OpenSim.Region.PhysicsModules.SharedBase
555 public override float PIDTau { set { return; } } 669 public override float PIDTau { set { return; } }
556 670
557 public override float PIDHoverHeight { set { return; } } 671 public override float PIDHoverHeight { set { return; } }
558 public override bool PIDHoverActive { set { return; } } 672 public override bool PIDHoverActive {get {return false;} set { return; } }
559 public override PIDHoverType PIDHoverType { set { return; } } 673 public override PIDHoverType PIDHoverType { set { return; } }
560 public override float PIDHoverTau { set { return; } } 674 public override float PIDHoverTau { set { return; } }
561 675
@@ -564,21 +678,10 @@ namespace OpenSim.Region.PhysicsModules.SharedBase
564 public override float APIDStrength { set { return; } } 678 public override float APIDStrength { set { return; } }
565 public override float APIDDamping { set { return; } } 679 public override float APIDDamping { set { return; } }
566 680
567 public override void SetMomentum(Vector3 momentum) 681 public override void SetMomentum(Vector3 momentum) { }
568 {
569 }
570 682
571 public override void SubscribeEvents(int ms) 683 public override void SubscribeEvents(int ms) { }
572 { 684 public override void UnSubscribeEvents() { }
573 685 public override bool SubscribedEvents() { return false; }
574 }
575 public override void UnSubscribeEvents()
576 {
577
578 }
579 public override bool SubscribedEvents()
580 {
581 return false;
582 }
583 } 686 }
584} 687}
diff --git a/OpenSim/Region/PhysicsModules/SharedBase/PhysicsScene.cs b/OpenSim/Region/PhysicsModules/SharedBase/PhysicsScene.cs
index 32691fc..8623891 100644
--- a/OpenSim/Region/PhysicsModules/SharedBase/PhysicsScene.cs
+++ b/OpenSim/Region/PhysicsModules/SharedBase/PhysicsScene.cs
@@ -41,6 +41,10 @@ namespace OpenSim.Region.PhysicsModules.SharedBase
41 41
42 public delegate void RaycastCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance, Vector3 normal); 42 public delegate void RaycastCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance, Vector3 normal);
43 public delegate void RayCallback(List<ContactResult> list); 43 public delegate void RayCallback(List<ContactResult> list);
44 public delegate void ProbeBoxCallback(List<ContactResult> list);
45 public delegate void ProbeSphereCallback(List<ContactResult> list);
46 public delegate void ProbePlaneCallback(List<ContactResult> list);
47 public delegate void SitAvatarCallback(int status, uint partID, Vector3 offset, Quaternion Orientation);
44 48
45 public delegate void JointMoved(PhysicsJoint joint); 49 public delegate void JointMoved(PhysicsJoint joint);
46 public delegate void JointDeactivated(PhysicsJoint joint); 50 public delegate void JointDeactivated(PhysicsJoint joint);
@@ -89,6 +93,8 @@ namespace OpenSim.Region.PhysicsModules.SharedBase
89 public Vector3 Normal; 93 public Vector3 Normal;
90 } 94 }
91 95
96
97
92 public abstract class PhysicsScene 98 public abstract class PhysicsScene
93 { 99 {
94// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 100// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@@ -143,6 +149,7 @@ namespace OpenSim.Region.PhysicsModules.SharedBase
143 /// <param name="size"></param> 149 /// <param name="size"></param>
144 /// <param name="isFlying"></param> 150 /// <param name="isFlying"></param>
145 /// <returns></returns> 151 /// <returns></returns>
152
146 public abstract PhysicsActor AddAvatar( 153 public abstract PhysicsActor AddAvatar(
147 string avName, Vector3 position, Vector3 velocity, Vector3 size, bool isFlying); 154 string avName, Vector3 position, Vector3 velocity, Vector3 size, bool isFlying);
148 155
@@ -161,12 +168,26 @@ namespace OpenSim.Region.PhysicsModules.SharedBase
161 { 168 {
162 PhysicsActor ret = AddAvatar(avName, position, velocity, size, isFlying); 169 PhysicsActor ret = AddAvatar(avName, position, velocity, size, isFlying);
163 170
164 if (ret != null) 171 if (ret != null)
165 ret.LocalID = localID; 172 ret.LocalID = localID;
166 173
167 return ret; 174 return ret;
168 } 175 }
169 176
177 public virtual PhysicsActor AddAvatar(
178 uint localID, string avName, Vector3 position, Vector3 size, bool isFlying)
179 {
180 PhysicsActor ret = AddAvatar(localID, avName, position, Vector3.Zero, size, isFlying);
181 return ret;
182 }
183
184 public virtual PhysicsActor AddAvatar(
185 uint localID, string avName, Vector3 position, Vector3 size, float feetOffset, bool isFlying)
186 {
187 PhysicsActor ret = AddAvatar(localID, avName, position, Vector3.Zero, size, isFlying);
188 return ret;
189 }
190
170 /// <summary> 191 /// <summary>
171 /// Remove an avatar. 192 /// Remove an avatar.
172 /// </summary> 193 /// </summary>
@@ -182,6 +203,19 @@ namespace OpenSim.Region.PhysicsModules.SharedBase
182 public abstract PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position, 203 public abstract PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position,
183 Vector3 size, Quaternion rotation, bool isPhysical, uint localid); 204 Vector3 size, Quaternion rotation, bool isPhysical, uint localid);
184 205
206 public virtual PhysicsActor AddPrimShape(string primName, PhysicsActor parent, PrimitiveBaseShape pbs, Vector3 position,
207 uint localid, byte[] sdata)
208 {
209 return null;
210 }
211
212 public virtual PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position,
213 Vector3 size, Quaternion rotation, bool isPhysical, bool isPhantom, uint localid)
214 {
215 return AddPrimShape(primName, pbs, position, size, rotation, isPhysical, localid);
216 }
217
218
185 public virtual PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position, 219 public virtual PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position,
186 Vector3 size, Quaternion rotation, bool isPhysical, bool isPhantom, byte shapetype, uint localid) 220 Vector3 size, Quaternion rotation, bool isPhysical, bool isPhantom, byte shapetype, uint localid)
187 { 221 {
@@ -255,6 +289,9 @@ namespace OpenSim.Region.PhysicsModules.SharedBase
255 289
256 public abstract void AddPhysicsActorTaint(PhysicsActor prim); 290 public abstract void AddPhysicsActorTaint(PhysicsActor prim);
257 291
292
293 public virtual void ProcessPreSimulation() { }
294
258 /// <summary> 295 /// <summary>
259 /// Perform a simulation of the current physics scene over the given timestep. 296 /// Perform a simulation of the current physics scene over the given timestep.
260 /// </summary> 297 /// </summary>
@@ -299,7 +336,7 @@ namespace OpenSim.Region.PhysicsModules.SharedBase
299 } 336 }
300 337
301 public virtual void Combine(PhysicsScene pScene, Vector3 offset, Vector3 extents) {} 338 public virtual void Combine(PhysicsScene pScene, Vector3 offset, Vector3 extents) {}
302 339 public virtual void CombineTerrain(float[] heightMap, Vector3 pOffset) {}
303 public virtual void UnCombine(PhysicsScene pScene) {} 340 public virtual void UnCombine(PhysicsScene pScene) {}
304 341
305 /// <summary> 342 /// <summary>
@@ -348,6 +385,31 @@ namespace OpenSim.Region.PhysicsModules.SharedBase
348 return false; 385 return false;
349 } 386 }
350 387
388 public virtual List<ContactResult> RaycastActor(PhysicsActor actor, Vector3 position, Vector3 direction, float length, int Count, RayFilterFlags flags)
389 {
390 return new List<ContactResult>();
391 }
392
393 public virtual List<ContactResult> BoxProbe(Vector3 position, Vector3 size, Quaternion orientation, int Count, RayFilterFlags flags)
394 {
395 return new List<ContactResult>();
396 }
397
398 public virtual List<ContactResult> SphereProbe(Vector3 position, float radius, int Count, RayFilterFlags flags)
399 {
400 return new List<ContactResult>();
401 }
402
403 public virtual List<ContactResult> PlaneProbe(PhysicsActor actor, Vector4 plane, int Count, RayFilterFlags flags)
404 {
405 return new List<ContactResult>();
406 }
407
408 public virtual int SitAvatar(PhysicsActor actor, Vector3 AbsolutePosition, Vector3 CameraPosition, Vector3 offset, Vector3 AvatarSize, SitAvatarCallback PhysicsSitResponse)
409 {
410 return 0;
411 }
412
351 // Extendable interface for new, physics engine specific operations 413 // Extendable interface for new, physics engine specific operations
352 public virtual object Extension(string pFunct, params object[] pParams) 414 public virtual object Extension(string pFunct, params object[] pParams)
353 { 415 {
diff --git a/OpenSim/Region/PhysicsModules/SharedBase/VehicleConstants.cs b/OpenSim/Region/PhysicsModules/SharedBase/VehicleConstants.cs
index 63a8cb8..e850b11 100644
--- a/OpenSim/Region/PhysicsModules/SharedBase/VehicleConstants.cs
+++ b/OpenSim/Region/PhysicsModules/SharedBase/VehicleConstants.cs
@@ -26,6 +26,7 @@
26 */ 26 */
27 27
28using System; 28using System;
29using OpenMetaverse;
29 30
30namespace OpenSim.Region.PhysicsModules.SharedBase 31namespace OpenSim.Region.PhysicsModules.SharedBase
31{ 32{
@@ -117,5 +118,47 @@ namespace OpenSim.Region.PhysicsModules.SharedBase
117 NO_DEFLECTION = 16392, 118 NO_DEFLECTION = 16392,
118 LOCK_ROTATION = 32784 119 LOCK_ROTATION = 32784
119 } 120 }
120 121
122 public struct VehicleData
123 {
124 public Vehicle m_type;
125 public VehicleFlag m_flags;
126
127 // Linear properties
128 public Vector3 m_linearMotorDirection;
129 public Vector3 m_linearFrictionTimescale;
130 public float m_linearMotorDecayTimescale;
131 public float m_linearMotorTimescale;
132 public Vector3 m_linearMotorOffset;
133
134 //Angular properties
135 public Vector3 m_angularMotorDirection;
136 public float m_angularMotorTimescale;
137 public float m_angularMotorDecayTimescale;
138 public Vector3 m_angularFrictionTimescale;
139
140 //Deflection properties
141 public float m_angularDeflectionEfficiency;
142 public float m_angularDeflectionTimescale;
143 public float m_linearDeflectionEfficiency;
144 public float m_linearDeflectionTimescale;
145
146 //Banking properties
147 public float m_bankingEfficiency;
148 public float m_bankingMix;
149 public float m_bankingTimescale;
150
151 //Hover and Buoyancy properties
152 public float m_VhoverHeight;
153 public float m_VhoverEfficiency;
154 public float m_VhoverTimescale;
155 public float m_VehicleBuoyancy;
156
157 //Attractor properties
158 public float m_verticalAttractionEfficiency;
159 public float m_verticalAttractionTimescale;
160
161 // Axis
162 public Quaternion m_referenceFrame;
163 }
121} 164}
diff --git a/OpenSim/Region/PhysicsModules/ubOde/ODEApi.cs b/OpenSim/Region/PhysicsModules/ubOde/ODEApi.cs
new file mode 100644
index 0000000..daf3af1
--- /dev/null
+++ b/OpenSim/Region/PhysicsModules/ubOde/ODEApi.cs
@@ -0,0 +1,2024 @@
1/*
2 * based on:
3 * Ode.NET - .NET bindings for ODE
4 * Jason Perkins (starkos@industriousone.com)
5 * Licensed under the New BSD
6 * Part of the OpenDynamicsEngine
7Open Dynamics Engine
8Copyright (c) 2001-2007, Russell L. Smith.
9All rights reserved.
10
11Redistribution and use in source and binary forms, with or without
12modification, are permitted provided that the following conditions
13are met:
14
15Redistributions of source code must retain the above copyright notice,
16this list of conditions and the following disclaimer.
17
18Redistributions in binary form must reproduce the above copyright notice,
19this list of conditions and the following disclaimer in the documentation
20and/or other materials provided with the distribution.
21
22Neither the names of ODE's copyright owner nor the names of its
23contributors may be used to endorse or promote products derived from
24this software without specific prior written permission.
25
26THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
29FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
30OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
32TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 *
38 * changes by opensim team;
39 * changes by Aurora team http://www.aurora-sim.org/
40 * changes by Ubit Umarov
41 */
42
43using System;
44using System.Runtime.InteropServices;
45using System.Security;
46using OMV = OpenMetaverse;
47namespace OdeAPI
48{
49//#if dDOUBLE
50// don't see much use in double precision with time steps of 20ms and 10 iterations used on opensim
51// at least we save same memory and memory access time, FPU performance on intel usually is similar
52// using dReal = System.Double;
53//#else
54 using dReal = System.Single;
55//#endif
56
57 public static class d
58 {
59 public static dReal Infinity = dReal.MaxValue;
60 public static int NTotalBodies = 0;
61 public static int NTotalGeoms = 0;
62
63 public const uint CONTACTS_UNIMPORTANT = 0x80000000;
64
65 #region Flags and Enumerations
66
67 [Flags]
68 public enum AllocateODEDataFlags : uint
69 {
70 BasicData = 0,
71 CollisionData = 0x00000001,
72 All = ~0u
73 }
74
75 [Flags]
76 public enum IniteODEFlags : uint
77 {
78 dInitFlagManualThreadCleanup = 0x00000001
79 }
80
81 [Flags]
82 public enum ContactFlags : int
83 {
84 Mu2 = 0x001,
85 FDir1 = 0x002,
86 Bounce = 0x004,
87 SoftERP = 0x008,
88 SoftCFM = 0x010,
89 Motion1 = 0x020,
90 Motion2 = 0x040,
91 MotionN = 0x080,
92 Slip1 = 0x100,
93 Slip2 = 0x200,
94 Approx0 = 0x0000,
95 Approx1_1 = 0x1000,
96 Approx1_2 = 0x2000,
97 Approx1 = 0x3000
98 }
99
100 public enum GeomClassID : int
101 {
102 SphereClass,
103 BoxClass,
104 CapsuleClass,
105 CylinderClass,
106 PlaneClass,
107 RayClass,
108 ConvexClass,
109 GeomTransformClass,
110 TriMeshClass,
111 HeightfieldClass,
112 FirstSpaceClass,
113 SimpleSpaceClass = FirstSpaceClass,
114 HashSpaceClass,
115 QuadTreeSpaceClass,
116 LastSpaceClass = QuadTreeSpaceClass,
117 ubtTerrainClass,
118 FirstUserClass,
119 LastUserClass = FirstUserClass + MaxUserClasses - 1,
120 NumClasses,
121 MaxUserClasses = 5
122 }
123
124 public enum JointType : int
125 {
126 None,
127 Ball,
128 Hinge,
129 Slider,
130 Contact,
131 Universal,
132 Hinge2,
133 Fixed,
134 Null,
135 AMotor,
136 LMotor,
137 Plane2D
138 }
139
140 public enum JointParam : int
141 {
142 LoStop,
143 HiStop,
144 Vel,
145 FMax,
146 FudgeFactor,
147 Bounce,
148 CFM,
149 StopERP,
150 StopCFM,
151 SuspensionERP,
152 SuspensionCFM,
153 LoStop2 = 256,
154 HiStop2,
155 Vel2,
156 FMax2,
157 FudgeFactor2,
158 Bounce2,
159 CFM2,
160 StopERP2,
161 StopCFM2,
162 SuspensionERP2,
163 SuspensionCFM2,
164 LoStop3 = 512,
165 HiStop3,
166 Vel3,
167 FMax3,
168 FudgeFactor3,
169 Bounce3,
170 CFM3,
171 StopERP3,
172 StopCFM3,
173 SuspensionERP3,
174 SuspensionCFM3
175 }
176
177 public enum dSweepAndPruneAxis : int
178 {
179 XYZ = ((0)|(1<<2)|(2<<4)),
180 XZY = ((0)|(2<<2)|(1<<4)),
181 YXZ = ((1)|(0<<2)|(2<<4)),
182 YZX = ((1)|(2<<2)|(0<<4)),
183 ZXY = ((2)|(0<<2)|(1<<4)),
184 ZYX = ((2)|(1<<2)|(0<<4))
185 }
186
187 #endregion
188
189 #region Callbacks
190
191 [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
192 public delegate int AABBTestFn(IntPtr o1, IntPtr o2, ref AABB aabb);
193
194 [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
195 public delegate int ColliderFn(IntPtr o1, IntPtr o2, int flags, out ContactGeom contact, int skip);
196
197 [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
198 public delegate void GetAABBFn(IntPtr geom, out AABB aabb);
199
200 [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
201 public delegate ColliderFn GetColliderFnFn(int num);
202
203 [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
204 public delegate void GeomDtorFn(IntPtr o);
205
206 [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
207 public delegate dReal HeightfieldGetHeight(IntPtr p_user_data, int x, int z);
208
209 [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
210 public delegate dReal OSTerrainGetHeight(IntPtr p_user_data, int x, int z);
211
212 [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
213 public delegate void NearCallback(IntPtr data, IntPtr geom1, IntPtr geom2);
214
215 [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
216 public delegate int TriCallback(IntPtr trimesh, IntPtr refObject, int triangleIndex);
217
218 [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
219 public delegate int TriArrayCallback(IntPtr trimesh, IntPtr refObject, int[] triangleIndex, int triCount);
220
221 [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
222 public delegate int TriRayCallback(IntPtr trimesh, IntPtr ray, int triangleIndex, dReal u, dReal v);
223
224 #endregion
225
226 #region Structs
227
228 [StructLayout(LayoutKind.Sequential)]
229 public struct AABB
230 {
231 public dReal MinX, MaxX;
232 public dReal MinY, MaxY;
233 public dReal MinZ, MaxZ;
234 }
235
236
237 [StructLayout(LayoutKind.Sequential)]
238 public struct Contact
239 {
240 public SurfaceParameters surface;
241 public ContactGeom geom;
242 public Vector3 fdir1;
243 public static readonly int unmanagedSizeOf = Marshal.SizeOf(typeof(Contact));
244 }
245
246
247 [StructLayout(LayoutKind.Sequential)]
248 public struct ContactGeom
249 {
250
251 public Vector3 pos;
252 public Vector3 normal;
253 public dReal depth;
254 public IntPtr g1;
255 public IntPtr g2;
256 public int side1;
257 public int side2;
258 public static readonly int unmanagedSizeOf = Marshal.SizeOf(typeof(ContactGeom));
259 }
260
261 [StructLayout(LayoutKind.Sequential)]
262 public struct GeomClass
263 {
264 public int bytes;
265 public GetColliderFnFn collider;
266 public GetAABBFn aabb;
267 public AABBTestFn aabb_test;
268 public GeomDtorFn dtor;
269 }
270
271
272 [StructLayout(LayoutKind.Sequential)]
273 public struct JointFeedback
274 {
275 public Vector3 f1;
276 public Vector3 t1;
277 public Vector3 f2;
278 public Vector3 t2;
279 }
280
281
282 [StructLayout(LayoutKind.Sequential)]
283 public struct Mass
284 {
285 public dReal mass;
286 public Vector4 c;
287 public Matrix3 I;
288 }
289
290
291 [StructLayout(LayoutKind.Sequential)]
292 public struct Matrix3
293 {
294 public Matrix3(dReal m00, dReal m10, dReal m20, dReal m01, dReal m11, dReal m21, dReal m02, dReal m12, dReal m22)
295 {
296 M00 = m00; M10 = m10; M20 = m20; _m30 = 0.0f;
297 M01 = m01; M11 = m11; M21 = m21; _m31 = 0.0f;
298 M02 = m02; M12 = m12; M22 = m22; _m32 = 0.0f;
299 }
300 public dReal M00, M10, M20;
301 private dReal _m30;
302 public dReal M01, M11, M21;
303 private dReal _m31;
304 public dReal M02, M12, M22;
305 private dReal _m32;
306 }
307
308 [StructLayout(LayoutKind.Sequential)]
309 public struct Matrix4
310 {
311 public Matrix4(dReal m00, dReal m10, dReal m20, dReal m30,
312 dReal m01, dReal m11, dReal m21, dReal m31,
313 dReal m02, dReal m12, dReal m22, dReal m32,
314 dReal m03, dReal m13, dReal m23, dReal m33)
315 {
316 M00 = m00; M10 = m10; M20 = m20; M30 = m30;
317 M01 = m01; M11 = m11; M21 = m21; M31 = m31;
318 M02 = m02; M12 = m12; M22 = m22; M32 = m32;
319 M03 = m03; M13 = m13; M23 = m23; M33 = m33;
320 }
321 public dReal M00, M10, M20, M30;
322 public dReal M01, M11, M21, M31;
323 public dReal M02, M12, M22, M32;
324 public dReal M03, M13, M23, M33;
325 }
326
327 [StructLayout(LayoutKind.Sequential)]
328 public struct Quaternion
329 {
330 public dReal W, X, Y, Z;
331 }
332
333
334 [StructLayout(LayoutKind.Sequential)]
335 public struct SurfaceParameters
336 {
337 public ContactFlags mode;
338 public dReal mu;
339 public dReal mu2;
340 public dReal bounce;
341 public dReal bounce_vel;
342 public dReal soft_erp;
343 public dReal soft_cfm;
344 public dReal motion1;
345 public dReal motion2;
346 public dReal motionN;
347 public dReal slip1;
348 public dReal slip2;
349 }
350
351
352 [StructLayout(LayoutKind.Sequential)]
353 public struct Vector3
354 {
355 public Vector3(dReal x, dReal y, dReal z)
356 {
357 X = x; Y = y; Z = z; _w = 0.0f;
358 }
359 public dReal X, Y, Z;
360 private dReal _w;
361 }
362
363
364 [StructLayout(LayoutKind.Sequential)]
365 public struct Vector4
366 {
367 public Vector4(dReal x, dReal y, dReal z, dReal w)
368 {
369 X = x; Y = y; Z = z; W = w;
370 }
371 public dReal X, Y, Z, W;
372 }
373
374 #endregion
375
376 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dAllocateODEDataForThread"), SuppressUnmanagedCodeSecurity]
377 public static extern int AllocateODEDataForThread(uint ODEInitFlags);
378
379 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dAreConnected"), SuppressUnmanagedCodeSecurity]
380 public static extern bool AreConnected(IntPtr b1, IntPtr b2);
381
382 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dAreConnectedExcluding"), SuppressUnmanagedCodeSecurity]
383 public static extern bool AreConnectedExcluding(IntPtr b1, IntPtr b2, JointType joint_type);
384
385 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyAddForce"), SuppressUnmanagedCodeSecurity]
386 public static extern void BodyAddForce(IntPtr body, dReal fx, dReal fy, dReal fz);
387
388 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyAddForceAtPos"), SuppressUnmanagedCodeSecurity]
389 public static extern void BodyAddForceAtPos(IntPtr body, dReal fx, dReal fy, dReal fz, dReal px, dReal py, dReal pz);
390
391 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyAddForceAtRelPos"), SuppressUnmanagedCodeSecurity]
392 public static extern void BodyAddForceAtRelPos(IntPtr body, dReal fx, dReal fy, dReal fz, dReal px, dReal py, dReal pz);
393
394 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyAddRelForce"), SuppressUnmanagedCodeSecurity]
395 public static extern void BodyAddRelForce(IntPtr body, dReal fx, dReal fy, dReal fz);
396
397 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyAddRelForceAtPos"), SuppressUnmanagedCodeSecurity]
398 public static extern void BodyAddRelForceAtPos(IntPtr body, dReal fx, dReal fy, dReal fz, dReal px, dReal py, dReal pz);
399
400 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyAddRelForceAtRelPos"), SuppressUnmanagedCodeSecurity]
401 public static extern void BodyAddRelForceAtRelPos(IntPtr body, dReal fx, dReal fy, dReal fz, dReal px, dReal py, dReal pz);
402
403 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyAddRelTorque"), SuppressUnmanagedCodeSecurity]
404 public static extern void BodyAddRelTorque(IntPtr body, dReal fx, dReal fy, dReal fz);
405
406 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyAddTorque"), SuppressUnmanagedCodeSecurity]
407 public static extern void BodyAddTorque(IntPtr body, dReal fx, dReal fy, dReal fz);
408
409 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyCopyPosition"), SuppressUnmanagedCodeSecurity]
410 public static extern void BodyCopyPosition(IntPtr body, out Vector3 pos);
411
412 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyCopyPosition"), SuppressUnmanagedCodeSecurity]
413 public static extern void BodyCopyPosition(IntPtr body, out dReal X);
414
415 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyCopyQuaternion"), SuppressUnmanagedCodeSecurity]
416 public static extern void BodyCopyQuaternion(IntPtr body, out Quaternion quat);
417
418 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyCopyQuaternion"), SuppressUnmanagedCodeSecurity]
419 public static extern void BodyCopyQuaternion(IntPtr body, out dReal X);
420
421 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyCopyRotation"), SuppressUnmanagedCodeSecurity]
422 public static extern void BodyCopyRotation(IntPtr body, out Matrix3 R);
423
424 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyCopyRotation"), SuppressUnmanagedCodeSecurity]
425 public static extern void BodyCopyRotation(IntPtr body, out dReal M00);
426
427 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyCreate"), SuppressUnmanagedCodeSecurity]
428 public static extern IntPtr BodyiCreate(IntPtr world);
429 public static IntPtr BodyCreate(IntPtr world)
430 {
431 NTotalBodies++;
432 return BodyiCreate(world);
433 }
434
435 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyDestroy"), SuppressUnmanagedCodeSecurity]
436 public static extern void BodyiDestroy(IntPtr body);
437 public static void BodyDestroy(IntPtr body)
438 {
439 NTotalBodies--;
440 BodyiDestroy(body);
441 }
442
443 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyDisable"), SuppressUnmanagedCodeSecurity]
444 public static extern void BodyDisable(IntPtr body);
445
446 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyEnable"), SuppressUnmanagedCodeSecurity]
447 public static extern void BodyEnable(IntPtr body);
448
449 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetAutoDisableAngularThreshold"), SuppressUnmanagedCodeSecurity]
450 public static extern dReal BodyGetAutoDisableAngularThreshold(IntPtr body);
451
452 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetAutoDisableFlag"), SuppressUnmanagedCodeSecurity]
453 public static extern bool BodyGetAutoDisableFlag(IntPtr body);
454
455 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetAutoDisableDefaults"), SuppressUnmanagedCodeSecurity]
456 public static extern void BodyGetAutoDisableDefaults(IntPtr body);
457
458 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetAutoDisableLinearThreshold"), SuppressUnmanagedCodeSecurity]
459 public static extern dReal BodyGetAutoDisableLinearThreshold(IntPtr body);
460
461 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetAutoDisableSteps"), SuppressUnmanagedCodeSecurity]
462 public static extern int BodyGetAutoDisableSteps(IntPtr body);
463
464 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetAutoDisableTime"), SuppressUnmanagedCodeSecurity]
465 public static extern dReal BodyGetAutoDisableTime(IntPtr body);
466
467 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetAngularVel"), SuppressUnmanagedCodeSecurity]
468 public extern unsafe static Vector3* BodyGetAngularVelUnsafe(IntPtr body);
469 public static Vector3 BodyGetAngularVel(IntPtr body)
470 {
471 unsafe { return *(BodyGetAngularVelUnsafe(body)); }
472 }
473
474 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetData"), SuppressUnmanagedCodeSecurity]
475 public static extern IntPtr BodyGetData(IntPtr body);
476
477 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetFiniteRotationMode"), SuppressUnmanagedCodeSecurity]
478 public static extern int BodyGetFiniteRotationMode(IntPtr body);
479
480 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetFiniteRotationAxis"), SuppressUnmanagedCodeSecurity]
481 public static extern void BodyGetFiniteRotationAxis(IntPtr body, out Vector3 result);
482
483 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetForce"), SuppressUnmanagedCodeSecurity]
484 public extern unsafe static Vector3* BodyGetForceUnsafe(IntPtr body);
485 public static Vector3 BodyGetForce(IntPtr body)
486 {
487 unsafe { return *(BodyGetForceUnsafe(body)); }
488 }
489
490 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetGravityMode"), SuppressUnmanagedCodeSecurity]
491 public static extern bool BodyGetGravityMode(IntPtr body);
492
493 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetGyroscopicMode"), SuppressUnmanagedCodeSecurity]
494 public static extern int BodyGetGyroscopicMode(IntPtr body);
495
496 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetJoint"), SuppressUnmanagedCodeSecurity]
497 public static extern IntPtr BodyGetJoint(IntPtr body, int index);
498
499 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetLinearVel"), SuppressUnmanagedCodeSecurity]
500 public extern unsafe static Vector3* BodyGetLinearVelUnsafe(IntPtr body);
501 public static Vector3 BodyGetLinearVel(IntPtr body)
502 {
503 unsafe { return *(BodyGetLinearVelUnsafe(body)); }
504 }
505
506 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetMass"), SuppressUnmanagedCodeSecurity]
507 public static extern void BodyGetMass(IntPtr body, out Mass mass);
508
509 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetNumJoints"), SuppressUnmanagedCodeSecurity]
510 public static extern int BodyGetNumJoints(IntPtr body);
511
512 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetPointVel"), SuppressUnmanagedCodeSecurity]
513 public static extern void BodyGetPointVel(IntPtr body, dReal px, dReal py, dReal pz, out Vector3 result);
514
515 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetPosition"), SuppressUnmanagedCodeSecurity]
516 public extern unsafe static Vector3* BodyGetPositionUnsafe(IntPtr body);
517 public static Vector3 BodyGetPosition(IntPtr body)
518 {
519 unsafe { return *(BodyGetPositionUnsafe(body)); }
520 }
521
522 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetPosRelPoint"), SuppressUnmanagedCodeSecurity]
523 public static extern void BodyGetPosRelPoint(IntPtr body, dReal px, dReal py, dReal pz, out Vector3 result);
524
525 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetQuaternion"), SuppressUnmanagedCodeSecurity]
526 public extern unsafe static Quaternion* BodyGetQuaternionUnsafe(IntPtr body);
527 public static Quaternion BodyGetQuaternion(IntPtr body)
528 {
529 unsafe { return *(BodyGetQuaternionUnsafe(body)); }
530 }
531
532 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetRelPointPos"), SuppressUnmanagedCodeSecurity]
533 public static extern void BodyGetRelPointPos(IntPtr body, dReal px, dReal py, dReal pz, out Vector3 result);
534
535 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetRelPointVel"), SuppressUnmanagedCodeSecurity]
536 public static extern void BodyGetRelPointVel(IntPtr body, dReal px, dReal py, dReal pz, out Vector3 result);
537
538 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetRotation"), SuppressUnmanagedCodeSecurity]
539 public extern unsafe static Matrix3* BodyGetRotationUnsafe(IntPtr body);
540 public static Matrix3 BodyGetRotation(IntPtr body)
541 {
542 unsafe { return *(BodyGetRotationUnsafe(body)); }
543 }
544
545 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetTorque"), SuppressUnmanagedCodeSecurity]
546 public extern unsafe static Vector3* BodyGetTorqueUnsafe(IntPtr body);
547 public static Vector3 BodyGetTorque(IntPtr body)
548 {
549 unsafe { return *(BodyGetTorqueUnsafe(body)); }
550 }
551
552 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetWorld"), SuppressUnmanagedCodeSecurity]
553 public static extern IntPtr BodyGetWorld(IntPtr body);
554
555 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetFirstGeom"), SuppressUnmanagedCodeSecurity]
556 public static extern IntPtr BodyGetFirstGeom(IntPtr body);
557
558 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetNextGeom"), SuppressUnmanagedCodeSecurity]
559 public static extern IntPtr dBodyGetNextGeom(IntPtr Geom);
560
561
562 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyIsEnabled"), SuppressUnmanagedCodeSecurity]
563 public static extern bool BodyIsEnabled(IntPtr body);
564
565 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetAngularVel"), SuppressUnmanagedCodeSecurity]
566 public static extern void BodySetAngularVel(IntPtr body, dReal x, dReal y, dReal z);
567
568 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetAutoDisableAngularThreshold"), SuppressUnmanagedCodeSecurity]
569 public static extern void BodySetAutoDisableAngularThreshold(IntPtr body, dReal angular_threshold);
570
571 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetAutoDisableDefaults"), SuppressUnmanagedCodeSecurity]
572 public static extern void BodySetAutoDisableDefaults(IntPtr body);
573
574 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetAutoDisableFlag"), SuppressUnmanagedCodeSecurity]
575 public static extern void BodySetAutoDisableFlag(IntPtr body, bool do_auto_disable);
576
577 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetAutoDisableLinearThreshold"), SuppressUnmanagedCodeSecurity]
578 public static extern void BodySetAutoDisableLinearThreshold(IntPtr body, dReal linear_threshold);
579
580 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetAutoDisableSteps"), SuppressUnmanagedCodeSecurity]
581 public static extern void BodySetAutoDisableSteps(IntPtr body, int steps);
582
583 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetAutoDisableTime"), SuppressUnmanagedCodeSecurity]
584 public static extern void BodySetAutoDisableTime(IntPtr body, dReal time);
585
586 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetData"), SuppressUnmanagedCodeSecurity]
587 public static extern void BodySetData(IntPtr body, IntPtr data);
588
589 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetFiniteRotationMode"), SuppressUnmanagedCodeSecurity]
590 public static extern void BodySetFiniteRotationMode(IntPtr body, int mode);
591
592 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetFiniteRotationAxis"), SuppressUnmanagedCodeSecurity]
593 public static extern void BodySetFiniteRotationAxis(IntPtr body, dReal x, dReal y, dReal z);
594
595 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetLinearDamping"), SuppressUnmanagedCodeSecurity]
596 public static extern void BodySetLinearDamping(IntPtr body, dReal scale);
597
598 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetAngularDamping"), SuppressUnmanagedCodeSecurity]
599 public static extern void BodySetAngularDamping(IntPtr body, dReal scale);
600
601 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetLinearDamping"), SuppressUnmanagedCodeSecurity]
602 public static extern dReal BodyGetLinearDamping(IntPtr body);
603
604 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetAngularDamping"), SuppressUnmanagedCodeSecurity]
605 public static extern dReal BodyGetAngularDamping(IntPtr body);
606
607 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetAngularDamping"), SuppressUnmanagedCodeSecurity]
608 public static extern void BodySetDamping(IntPtr body, dReal linear_scale, dReal angular_scale);
609
610 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetAngularDampingThreshold"), SuppressUnmanagedCodeSecurity]
611 public static extern void BodySetAngularDampingThreshold(IntPtr body, dReal threshold);
612
613 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetLinearDampingThreshold"), SuppressUnmanagedCodeSecurity]
614 public static extern void BodySetLinearDampingThreshold(IntPtr body, dReal threshold);
615
616 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetLinearDampingThreshold"), SuppressUnmanagedCodeSecurity]
617 public static extern dReal BodyGetLinearDampingThreshold(IntPtr body);
618
619 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetAngularDampingThreshold"), SuppressUnmanagedCodeSecurity]
620 public static extern dReal BodyGetAngularDampingThreshold(IntPtr body);
621
622 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetForce"), SuppressUnmanagedCodeSecurity]
623 public static extern void BodySetForce(IntPtr body, dReal x, dReal y, dReal z);
624
625 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetGravityMode"), SuppressUnmanagedCodeSecurity]
626 public static extern void BodySetGravityMode(IntPtr body, bool mode);
627
628 /// <summary>
629 /// Sets the Gyroscopic term status on the body specified.
630 /// </summary>
631 /// <param name="body">Pointer to body</param>
632 /// <param name="enabled">NonZero enabled, Zero disabled</param>
633 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetGyroscopicMode"), SuppressUnmanagedCodeSecurity]
634 public static extern void dBodySetGyroscopicMode(IntPtr body, int enabled);
635
636 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetLinearVel"), SuppressUnmanagedCodeSecurity]
637 public static extern void BodySetLinearVel(IntPtr body, dReal x, dReal y, dReal z);
638
639 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetMass"), SuppressUnmanagedCodeSecurity]
640 public static extern void BodySetMass(IntPtr body, ref Mass mass);
641
642 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetPosition"), SuppressUnmanagedCodeSecurity]
643 public static extern void BodySetPosition(IntPtr body, dReal x, dReal y, dReal z);
644
645 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetQuaternion"), SuppressUnmanagedCodeSecurity]
646 public static extern void BodySetQuaternion(IntPtr body, ref Quaternion q);
647
648 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetQuaternion"), SuppressUnmanagedCodeSecurity]
649 public static extern void BodySetQuaternion(IntPtr body, ref dReal w);
650
651 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetRotation"), SuppressUnmanagedCodeSecurity]
652 public static extern void BodySetRotation(IntPtr body, ref Matrix3 R);
653
654 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetRotation"), SuppressUnmanagedCodeSecurity]
655 public static extern void BodySetRotation(IntPtr body, ref dReal M00);
656
657 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetTorque"), SuppressUnmanagedCodeSecurity]
658 public static extern void BodySetTorque(IntPtr body, dReal x, dReal y, dReal z);
659
660 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyVectorFromWorld"), SuppressUnmanagedCodeSecurity]
661 public static extern void BodyVectorFromWorld(IntPtr body, dReal px, dReal py, dReal pz, out Vector3 result);
662
663 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyVectorToWorld"), SuppressUnmanagedCodeSecurity]
664 public static extern void BodyVectorToWorld(IntPtr body, dReal px, dReal py, dReal pz, out Vector3 result);
665
666 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBoxBox"), SuppressUnmanagedCodeSecurity]
667 public static extern void BoxBox(ref Vector3 p1, ref Matrix3 R1,
668 ref Vector3 side1, ref Vector3 p2,
669 ref Matrix3 R2, ref Vector3 side2,
670 ref Vector3 normal, out dReal depth, out int return_code,
671 int maxc, out ContactGeom contact, int skip);
672
673 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBoxTouchesBox"), SuppressUnmanagedCodeSecurity]
674 public static extern void BoxTouchesBox(ref Vector3 _p1, ref Matrix3 R1,
675 ref Vector3 side1, ref Vector3 _p2,
676 ref Matrix3 R2, ref Vector3 side2);
677
678 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dCleanupODEAllDataForThread"), SuppressUnmanagedCodeSecurity]
679 public static extern void CleanupODEAllDataForThread();
680
681 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dClosestLineSegmentPoints"), SuppressUnmanagedCodeSecurity]
682 public static extern void ClosestLineSegmentPoints(ref Vector3 a1, ref Vector3 a2,
683 ref Vector3 b1, ref Vector3 b2,
684 ref Vector3 cp1, ref Vector3 cp2);
685
686 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dCloseODE"), SuppressUnmanagedCodeSecurity]
687 public static extern void CloseODE();
688
689 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dCollide"), SuppressUnmanagedCodeSecurity]
690 public static extern int Collide(IntPtr o1, IntPtr o2, int flags, [In, Out] ContactGeom[] contact, int skip);
691 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dCollide"), SuppressUnmanagedCodeSecurity]
692 public static extern int CollidePtr(IntPtr o1, IntPtr o2, int flags, IntPtr contactgeomarray, int skip);
693
694 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dConnectingJoint"), SuppressUnmanagedCodeSecurity]
695 public static extern IntPtr ConnectingJoint(IntPtr j1, IntPtr j2);
696
697 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dCreateBox"), SuppressUnmanagedCodeSecurity]
698 public static extern IntPtr CreateiBox(IntPtr space, dReal lx, dReal ly, dReal lz);
699 public static IntPtr CreateBox(IntPtr space, dReal lx, dReal ly, dReal lz)
700 {
701 NTotalGeoms++;
702 return CreateiBox(space, lx, ly, lz);
703 }
704
705 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dCreateCapsule"), SuppressUnmanagedCodeSecurity]
706 public static extern IntPtr CreateiCapsule(IntPtr space, dReal radius, dReal length);
707 public static IntPtr CreateCapsule(IntPtr space, dReal radius, dReal length)
708 {
709 NTotalGeoms++;
710 return CreateiCapsule(space, radius, length);
711 }
712
713 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dCreateConvex"), SuppressUnmanagedCodeSecurity]
714 public static extern IntPtr CreateiConvex(IntPtr space, dReal[] planes, int planeCount, dReal[] points, int pointCount, int[] polygons);
715 public static IntPtr CreateConvex(IntPtr space, dReal[] planes, int planeCount, dReal[] points, int pointCount, int[] polygons)
716 {
717 NTotalGeoms++;
718 return CreateiConvex(space, planes, planeCount, points, pointCount, polygons);
719 }
720
721 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dCreateCylinder"), SuppressUnmanagedCodeSecurity]
722 public static extern IntPtr CreateiCylinder(IntPtr space, dReal radius, dReal length);
723 public static IntPtr CreateCylinder(IntPtr space, dReal radius, dReal length)
724 {
725 NTotalGeoms++;
726 return CreateiCylinder(space, radius, length);
727 }
728
729 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dCreateHeightfield"), SuppressUnmanagedCodeSecurity]
730 public static extern IntPtr CreateiHeightfield(IntPtr space, IntPtr data, int bPlaceable);
731 public static IntPtr CreateHeightfield(IntPtr space, IntPtr data, int bPlaceable)
732 {
733 NTotalGeoms++;
734 return CreateiHeightfield(space, data, bPlaceable);
735 }
736
737 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dCreateOSTerrain"), SuppressUnmanagedCodeSecurity]
738 public static extern IntPtr CreateiOSTerrain(IntPtr space, IntPtr data, int bPlaceable);
739 public static IntPtr CreateOSTerrain(IntPtr space, IntPtr data, int bPlaceable)
740 {
741 NTotalGeoms++;
742 return CreateiOSTerrain(space, data, bPlaceable);
743 }
744
745
746
747
748
749 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dCreateGeom"), SuppressUnmanagedCodeSecurity]
750 public static extern IntPtr CreateiGeom(int classnum);
751 public static IntPtr CreateGeom(int classnum)
752 {
753 NTotalGeoms++;
754 return CreateiGeom(classnum);
755 }
756
757 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dCreateGeomClass"), SuppressUnmanagedCodeSecurity]
758 public static extern int CreateGeomClass(ref GeomClass classptr);
759
760 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dCreateGeomTransform"), SuppressUnmanagedCodeSecurity]
761 public static extern IntPtr CreateGeomTransform(IntPtr space);
762
763 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dCreatePlane"), SuppressUnmanagedCodeSecurity]
764 public static extern IntPtr CreateiPlane(IntPtr space, dReal a, dReal b, dReal c, dReal d);
765 public static IntPtr CreatePlane(IntPtr space, dReal a, dReal b, dReal c, dReal d)
766 {
767 NTotalGeoms++;
768 return CreateiPlane(space, a, b, c, d);
769 }
770
771 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dCreateRay"), SuppressUnmanagedCodeSecurity]
772 public static extern IntPtr CreateiRay(IntPtr space, dReal length);
773 public static IntPtr CreateRay(IntPtr space, dReal length)
774 {
775 NTotalGeoms++;
776 return CreateiRay(space, length);
777 }
778
779 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dCreateSphere"), SuppressUnmanagedCodeSecurity]
780 public static extern IntPtr CreateiSphere(IntPtr space, dReal radius);
781 public static IntPtr CreateSphere(IntPtr space, dReal radius)
782 {
783 NTotalGeoms++;
784 return CreateiSphere(space, radius);
785 }
786
787 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dCreateTriMesh"), SuppressUnmanagedCodeSecurity]
788 public static extern IntPtr CreateiTriMesh(IntPtr space, IntPtr data,
789 TriCallback callback, TriArrayCallback arrayCallback, TriRayCallback rayCallback);
790 public static IntPtr CreateTriMesh(IntPtr space, IntPtr data,
791 TriCallback callback, TriArrayCallback arrayCallback, TriRayCallback rayCallback)
792 {
793 NTotalGeoms++;
794 return CreateiTriMesh(space, data, callback, arrayCallback, rayCallback);
795 }
796 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dDot"), SuppressUnmanagedCodeSecurity]
797 public static extern dReal Dot(ref dReal X0, ref dReal X1, int n);
798
799 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dDQfromW"), SuppressUnmanagedCodeSecurity]
800 public static extern void DQfromW(dReal[] dq, ref Vector3 w, ref Quaternion q);
801
802 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dFactorCholesky"), SuppressUnmanagedCodeSecurity]
803 public static extern int FactorCholesky(ref dReal A00, int n);
804
805 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dFactorLDLT"), SuppressUnmanagedCodeSecurity]
806 public static extern void FactorLDLT(ref dReal A, out dReal d, int n, int nskip);
807
808 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomBoxGetLengths"), SuppressUnmanagedCodeSecurity]
809 public static extern void GeomBoxGetLengths(IntPtr geom, out Vector3 len);
810
811 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomBoxGetLengths"), SuppressUnmanagedCodeSecurity]
812 public static extern void GeomBoxGetLengths(IntPtr geom, out dReal x);
813
814 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomBoxPointDepth"), SuppressUnmanagedCodeSecurity]
815 public static extern dReal GeomBoxPointDepth(IntPtr geom, dReal x, dReal y, dReal z);
816
817 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomBoxSetLengths"), SuppressUnmanagedCodeSecurity]
818 public static extern void GeomBoxSetLengths(IntPtr geom, dReal x, dReal y, dReal z);
819
820 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomCapsuleGetParams"), SuppressUnmanagedCodeSecurity]
821 public static extern void GeomCapsuleGetParams(IntPtr geom, out dReal radius, out dReal length);
822
823 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomCapsulePointDepth"), SuppressUnmanagedCodeSecurity]
824 public static extern dReal GeomCapsulePointDepth(IntPtr geom, dReal x, dReal y, dReal z);
825
826 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomCapsuleSetParams"), SuppressUnmanagedCodeSecurity]
827 public static extern void GeomCapsuleSetParams(IntPtr geom, dReal radius, dReal length);
828
829 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomClearOffset"), SuppressUnmanagedCodeSecurity]
830 public static extern void GeomClearOffset(IntPtr geom);
831
832 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomCopyOffsetPosition"), SuppressUnmanagedCodeSecurity]
833 public static extern IntPtr GeomCopyOffsetPosition(IntPtr geom, ref Vector3 pos);
834
835 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomCopyOffsetPosition"), SuppressUnmanagedCodeSecurity]
836 public static extern IntPtr GeomCopyOffsetPosition(IntPtr geom, ref dReal X);
837
838 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetOffsetQuaternion"), SuppressUnmanagedCodeSecurity]
839 public static extern void GeomCopyOffsetQuaternion(IntPtr geom, ref Quaternion Q);
840
841 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetOffsetQuaternion"), SuppressUnmanagedCodeSecurity]
842 public static extern void GeomCopyOffsetQuaternion(IntPtr geom, ref dReal X);
843
844 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomCopyOffsetRotation"), SuppressUnmanagedCodeSecurity]
845 public static extern IntPtr GeomCopyOffsetRotation(IntPtr geom, ref Matrix3 R);
846
847 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomCopyOffsetRotation"), SuppressUnmanagedCodeSecurity]
848 public static extern IntPtr GeomCopyOffsetRotation(IntPtr geom, ref dReal M00);
849
850 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomCopyPosition"), SuppressUnmanagedCodeSecurity]
851 public static extern void GeomCopyPosition(IntPtr geom, out Vector3 pos);
852
853 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomCopyPosition"), SuppressUnmanagedCodeSecurity]
854 public static extern void GeomCopyPosition(IntPtr geom, out dReal X);
855
856 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomCopyRotation"), SuppressUnmanagedCodeSecurity]
857 public static extern void GeomCopyRotation(IntPtr geom, out Matrix3 R);
858
859 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomCopyRotation"), SuppressUnmanagedCodeSecurity]
860 public static extern void GeomCopyRotation(IntPtr geom, out dReal M00);
861
862 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomCylinderGetParams"), SuppressUnmanagedCodeSecurity]
863 public static extern void GeomCylinderGetParams(IntPtr geom, out dReal radius, out dReal length);
864
865 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomCylinderSetParams"), SuppressUnmanagedCodeSecurity]
866 public static extern void GeomCylinderSetParams(IntPtr geom, dReal radius, dReal length);
867
868 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomDestroy"), SuppressUnmanagedCodeSecurity]
869 public static extern void GeomiDestroy(IntPtr geom);
870 public static void GeomDestroy(IntPtr geom)
871 {
872 NTotalGeoms--;
873 GeomiDestroy(geom);
874 }
875
876
877 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomDisable"), SuppressUnmanagedCodeSecurity]
878 public static extern void GeomDisable(IntPtr geom);
879
880 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomEnable"), SuppressUnmanagedCodeSecurity]
881 public static extern void GeomEnable(IntPtr geom);
882
883 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetAABB"), SuppressUnmanagedCodeSecurity]
884 public static extern void GeomGetAABB(IntPtr geom, out AABB aabb);
885
886 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetAABB"), SuppressUnmanagedCodeSecurity]
887 public static extern void GeomGetAABB(IntPtr geom, out dReal minX);
888
889 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetBody"), SuppressUnmanagedCodeSecurity]
890 public static extern IntPtr GeomGetBody(IntPtr geom);
891
892 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetCategoryBits"), SuppressUnmanagedCodeSecurity]
893 public static extern uint GeomGetCategoryBits(IntPtr geom);
894
895 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetClassData"), SuppressUnmanagedCodeSecurity]
896 public static extern IntPtr GeomGetClassData(IntPtr geom);
897
898 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetCollideBits"), SuppressUnmanagedCodeSecurity]
899 public static extern uint GeomGetCollideBits(IntPtr geom);
900
901 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetClass"), SuppressUnmanagedCodeSecurity]
902 public static extern GeomClassID GeomGetClass(IntPtr geom);
903
904 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetData"), SuppressUnmanagedCodeSecurity]
905 public static extern IntPtr GeomGetData(IntPtr geom);
906
907 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetOffsetPosition"), SuppressUnmanagedCodeSecurity]
908 public extern unsafe static Vector3* GeomGetOffsetPositionUnsafe(IntPtr geom);
909 public static Vector3 GeomGetOffsetPosition(IntPtr geom)
910 {
911 unsafe { return *(GeomGetOffsetPositionUnsafe(geom)); }
912 }
913
914 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetOffsetRotation"), SuppressUnmanagedCodeSecurity]
915 public extern unsafe static Matrix3* GeomGetOffsetRotationUnsafe(IntPtr geom);
916 public static Matrix3 GeomGetOffsetRotation(IntPtr geom)
917 {
918 unsafe { return *(GeomGetOffsetRotationUnsafe(geom)); }
919 }
920
921 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetPosition"), SuppressUnmanagedCodeSecurity]
922 public extern unsafe static Vector3* GeomGetPositionUnsafe(IntPtr geom);
923 public static Vector3 GeomGetPosition(IntPtr geom)
924 {
925 unsafe { return *(GeomGetPositionUnsafe(geom)); }
926 }
927 public static OMV.Vector3 GeomGetPositionOMV(IntPtr geom)
928 {
929 Vector3 vtmp = GeomGetPosition(geom);
930 return new OMV.Vector3(vtmp.X, vtmp.Y, vtmp.Z);
931 }
932
933 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetQuaternion"), SuppressUnmanagedCodeSecurity]
934 public static extern void GeomCopyQuaternion(IntPtr geom, out Quaternion q);
935 public static OMV.Quaternion GeomGetQuaternionOMV(IntPtr geom)
936 {
937 Quaternion qtmp;
938 GeomCopyQuaternion(geom, out qtmp);
939 return new OMV.Quaternion(qtmp.X, qtmp.Y, qtmp.Z, qtmp.W);
940 }
941
942 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetQuaternion"), SuppressUnmanagedCodeSecurity]
943 public static extern void GeomCopyQuaternion(IntPtr geom, out dReal X);
944
945 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetRotation"), SuppressUnmanagedCodeSecurity]
946 public extern unsafe static Matrix3* GeomGetRotationUnsafe(IntPtr geom);
947 public static Matrix3 GeomGetRotation(IntPtr geom)
948 {
949 unsafe { return *(GeomGetRotationUnsafe(geom)); }
950 }
951
952 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetSpace"), SuppressUnmanagedCodeSecurity]
953 public static extern IntPtr GeomGetSpace(IntPtr geom);
954
955 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomHeightfieldDataBuildByte"), SuppressUnmanagedCodeSecurity]
956 public static extern void GeomHeightfieldDataBuildByte(IntPtr d, byte[] pHeightData, int bCopyHeightData,
957 dReal width, dReal depth, int widthSamples, int depthSamples,
958 dReal scale, dReal offset, dReal thickness, int bWrap);
959
960 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomHeightfieldDataBuildByte"), SuppressUnmanagedCodeSecurity]
961 public static extern void GeomHeightfieldDataBuildByte(IntPtr d, IntPtr pHeightData, int bCopyHeightData,
962 dReal width, dReal depth, int widthSamples, int depthSamples,
963 dReal scale, dReal offset, dReal thickness, int bWrap);
964
965 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomHeightfieldDataBuildCallback"), SuppressUnmanagedCodeSecurity]
966 public static extern void GeomHeightfieldDataBuildCallback(IntPtr d, IntPtr pUserData, HeightfieldGetHeight pCallback,
967 dReal width, dReal depth, int widthSamples, int depthSamples,
968 dReal scale, dReal offset, dReal thickness, int bWrap);
969
970 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomHeightfieldDataBuildShort"), SuppressUnmanagedCodeSecurity]
971 public static extern void GeomHeightfieldDataBuildShort(IntPtr d, ushort[] pHeightData, int bCopyHeightData,
972 dReal width, dReal depth, int widthSamples, int depthSamples,
973 dReal scale, dReal offset, dReal thickness, int bWrap);
974
975 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomHeightfieldDataBuildShort"), SuppressUnmanagedCodeSecurity]
976 public static extern void GeomHeightfieldDataBuildShort(IntPtr d, short[] pHeightData, int bCopyHeightData,
977 dReal width, dReal depth, int widthSamples, int depthSamples,
978 dReal scale, dReal offset, dReal thickness, int bWrap);
979
980 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomHeightfieldDataBuildShort"), SuppressUnmanagedCodeSecurity]
981 public static extern void GeomHeightfieldDataBuildShort(IntPtr d, IntPtr pHeightData, int bCopyHeightData,
982 dReal width, dReal depth, int widthSamples, int depthSamples,
983 dReal scale, dReal offset, dReal thickness, int bWrap);
984
985 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomHeightfieldDataBuildSingle"), SuppressUnmanagedCodeSecurity]
986 public static extern void GeomHeightfieldDataBuildSingle(IntPtr d, float[] pHeightData, int bCopyHeightData,
987 dReal width, dReal depth, int widthSamples, int depthSamples,
988 dReal scale, dReal offset, dReal thickness, int bWrap);
989
990 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomHeightfieldDataBuildSingle"), SuppressUnmanagedCodeSecurity]
991 public static extern void GeomHeightfieldDataBuildSingle(IntPtr d, IntPtr pHeightData, int bCopyHeightData,
992 dReal width, dReal depth, int widthSamples, int depthSamples,
993 dReal scale, dReal offset, dReal thickness, int bWrap);
994
995
996
997 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomHeightfieldDataBuildDouble"), SuppressUnmanagedCodeSecurity]
998 public static extern void GeomHeightfieldDataBuildDouble(IntPtr d, double[] pHeightData, int bCopyHeightData,
999 dReal width, dReal depth, int widthSamples, int depthSamples,
1000 dReal scale, dReal offset, dReal thickness, int bWrap);
1001
1002 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomHeightfieldDataBuildDouble"), SuppressUnmanagedCodeSecurity]
1003 public static extern void GeomHeightfieldDataBuildDouble(IntPtr d, IntPtr pHeightData, int bCopyHeightData,
1004 dReal width, dReal depth, int widthSamples, int depthSamples,
1005 dReal scale, dReal offset, dReal thickness, int bWrap);
1006
1007 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomHeightfieldDataCreate"), SuppressUnmanagedCodeSecurity]
1008 public static extern IntPtr GeomHeightfieldDataCreate();
1009
1010 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomHeightfieldDataDestroy"), SuppressUnmanagedCodeSecurity]
1011 public static extern void GeomHeightfieldDataDestroy(IntPtr d);
1012
1013 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomHeightfieldDataSetBounds"), SuppressUnmanagedCodeSecurity]
1014 public static extern void GeomHeightfieldDataSetBounds(IntPtr d, dReal minHeight, dReal maxHeight);
1015
1016 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomHeightfieldGetHeightfieldData"), SuppressUnmanagedCodeSecurity]
1017 public static extern IntPtr GeomHeightfieldGetHeightfieldData(IntPtr g);
1018
1019 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomHeightfieldSetHeightfieldData"), SuppressUnmanagedCodeSecurity]
1020 public static extern void GeomHeightfieldSetHeightfieldData(IntPtr g, IntPtr d);
1021
1022
1023 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomUbitTerrainDataBuild"), SuppressUnmanagedCodeSecurity]
1024 public static extern void GeomOSTerrainDataBuild(IntPtr d, float[] pHeightData, int bCopyHeightData,
1025 dReal sampleSize, int widthSamples, int depthSamples,
1026 dReal offset, dReal thickness, int bWrap);
1027
1028 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomOSTerrainDataBuild"), SuppressUnmanagedCodeSecurity]
1029 public static extern void GeomOSTerrainDataBuild(IntPtr d, IntPtr pHeightData, int bCopyHeightData,
1030 dReal sampleSize, int widthSamples, int depthSamples,
1031 dReal thickness, int bWrap);
1032
1033 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomOSTerrainDataCreate"), SuppressUnmanagedCodeSecurity]
1034 public static extern IntPtr GeomOSTerrainDataCreate();
1035
1036 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomOSTerrainDataDestroy"), SuppressUnmanagedCodeSecurity]
1037 public static extern void GeomOSTerrainDataDestroy(IntPtr d);
1038
1039 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomOSTerrainDataSetBounds"), SuppressUnmanagedCodeSecurity]
1040 public static extern void GeomOSTerrainDataSetBounds(IntPtr d, dReal minHeight, dReal maxHeight);
1041
1042 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomOSTerrainGetHeightfieldData"), SuppressUnmanagedCodeSecurity]
1043 public static extern IntPtr GeomOSTerrainGetHeightfieldData(IntPtr g);
1044
1045 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomOSTerrainSetHeightfieldData"), SuppressUnmanagedCodeSecurity]
1046 public static extern void GeomOSTerrainSetHeightfieldData(IntPtr g, IntPtr d);
1047
1048
1049 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomIsEnabled"), SuppressUnmanagedCodeSecurity]
1050 public static extern bool GeomIsEnabled(IntPtr geom);
1051
1052 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomIsOffset"), SuppressUnmanagedCodeSecurity]
1053 public static extern bool GeomIsOffset(IntPtr geom);
1054
1055 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomIsSpace"), SuppressUnmanagedCodeSecurity]
1056 public static extern bool GeomIsSpace(IntPtr geom);
1057
1058 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomPlaneGetParams"), SuppressUnmanagedCodeSecurity]
1059 public static extern void GeomPlaneGetParams(IntPtr geom, ref Vector4 result);
1060
1061 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomPlaneGetParams"), SuppressUnmanagedCodeSecurity]
1062 public static extern void GeomPlaneGetParams(IntPtr geom, ref dReal A);
1063
1064 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomPlanePointDepth"), SuppressUnmanagedCodeSecurity]
1065 public static extern dReal GeomPlanePointDepth(IntPtr geom, dReal x, dReal y, dReal z);
1066
1067 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomPlaneSetParams"), SuppressUnmanagedCodeSecurity]
1068 public static extern void GeomPlaneSetParams(IntPtr plane, dReal a, dReal b, dReal c, dReal d);
1069
1070 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomRayGet"), SuppressUnmanagedCodeSecurity]
1071 public static extern void GeomRayGet(IntPtr ray, ref Vector3 start, ref Vector3 dir);
1072
1073 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomRayGet"), SuppressUnmanagedCodeSecurity]
1074 public static extern void GeomRayGet(IntPtr ray, ref dReal startX, ref dReal dirX);
1075
1076 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomRayGetClosestHit"), SuppressUnmanagedCodeSecurity]
1077 public static extern int GeomRayGetClosestHit(IntPtr ray);
1078
1079 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomRayGetLength"), SuppressUnmanagedCodeSecurity]
1080 public static extern dReal GeomRayGetLength(IntPtr ray);
1081
1082 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomRayGetParams"), SuppressUnmanagedCodeSecurity]
1083 public static extern dReal GeomRayGetParams(IntPtr g, out int firstContact, out int backfaceCull);
1084
1085 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomRaySet"), SuppressUnmanagedCodeSecurity]
1086 public static extern void GeomRaySet(IntPtr ray, dReal px, dReal py, dReal pz, dReal dx, dReal dy, dReal dz);
1087
1088 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomRaySetClosestHit"), SuppressUnmanagedCodeSecurity]
1089 public static extern void GeomRaySetClosestHit(IntPtr ray, int closestHit);
1090
1091 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomRaySetLength"), SuppressUnmanagedCodeSecurity]
1092 public static extern void GeomRaySetLength(IntPtr ray, dReal length);
1093
1094 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomRaySetParams"), SuppressUnmanagedCodeSecurity]
1095 public static extern void GeomRaySetParams(IntPtr ray, int firstContact, int backfaceCull);
1096
1097 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetBody"), SuppressUnmanagedCodeSecurity]
1098 public static extern void GeomSetBody(IntPtr geom, IntPtr body);
1099
1100 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetCategoryBits"), SuppressUnmanagedCodeSecurity]
1101 public static extern void GeomSetCategoryBits(IntPtr geom, uint bits);
1102
1103 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetCollideBits"), SuppressUnmanagedCodeSecurity]
1104 public static extern void GeomSetCollideBits(IntPtr geom, uint bits);
1105
1106 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetConvex"), SuppressUnmanagedCodeSecurity]
1107 public static extern IntPtr GeomSetConvex(IntPtr geom, dReal[] planes, int planeCount, dReal[] points, int pointCount, int[] polygons);
1108
1109 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetData"), SuppressUnmanagedCodeSecurity]
1110 public static extern void GeomSetData(IntPtr geom, IntPtr data);
1111
1112 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetOffsetPosition"), SuppressUnmanagedCodeSecurity]
1113 public static extern void GeomSetOffsetPosition(IntPtr geom, dReal x, dReal y, dReal z);
1114
1115 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetOffsetQuaternion"), SuppressUnmanagedCodeSecurity]
1116 public static extern void GeomSetOffsetQuaternion(IntPtr geom, ref Quaternion Q);
1117
1118 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetOffsetQuaternion"), SuppressUnmanagedCodeSecurity]
1119 public static extern void GeomSetOffsetQuaternion(IntPtr geom, ref dReal X);
1120
1121 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetOffsetRotation"), SuppressUnmanagedCodeSecurity]
1122 public static extern void GeomSetOffsetRotation(IntPtr geom, ref Matrix3 R);
1123
1124 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetOffsetRotation"), SuppressUnmanagedCodeSecurity]
1125 public static extern void GeomSetOffsetRotation(IntPtr geom, ref dReal M00);
1126
1127 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetOffsetWorldPosition"), SuppressUnmanagedCodeSecurity]
1128 public static extern void GeomSetOffsetWorldPosition(IntPtr geom, dReal x, dReal y, dReal z);
1129
1130 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetOffsetWorldQuaternion"), SuppressUnmanagedCodeSecurity]
1131 public static extern void GeomSetOffsetWorldQuaternion(IntPtr geom, ref Quaternion Q);
1132
1133 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetOffsetWorldQuaternion"), SuppressUnmanagedCodeSecurity]
1134 public static extern void GeomSetOffsetWorldQuaternion(IntPtr geom, ref dReal X);
1135
1136 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetOffsetWorldRotation"), SuppressUnmanagedCodeSecurity]
1137 public static extern void GeomSetOffsetWorldRotation(IntPtr geom, ref Matrix3 R);
1138
1139 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetOffsetWorldRotation"), SuppressUnmanagedCodeSecurity]
1140 public static extern void GeomSetOffsetWorldRotation(IntPtr geom, ref dReal M00);
1141
1142 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetPosition"), SuppressUnmanagedCodeSecurity]
1143 public static extern void GeomSetPosition(IntPtr geom, dReal x, dReal y, dReal z);
1144
1145 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetQuaternion"), SuppressUnmanagedCodeSecurity]
1146 public static extern void GeomSetQuaternion(IntPtr geom, ref Quaternion quat);
1147
1148 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetQuaternion"), SuppressUnmanagedCodeSecurity]
1149 public static extern void GeomSetQuaternion(IntPtr geom, ref dReal w);
1150
1151 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetRotation"), SuppressUnmanagedCodeSecurity]
1152 public static extern void GeomSetRotation(IntPtr geom, ref Matrix3 R);
1153
1154 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetRotation"), SuppressUnmanagedCodeSecurity]
1155 public static extern void GeomSetRotation(IntPtr geom, ref dReal M00);
1156
1157 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSphereGetRadius"), SuppressUnmanagedCodeSecurity]
1158 public static extern dReal GeomSphereGetRadius(IntPtr geom);
1159
1160 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSpherePointDepth"), SuppressUnmanagedCodeSecurity]
1161 public static extern dReal GeomSpherePointDepth(IntPtr geom, dReal x, dReal y, dReal z);
1162
1163 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSphereSetRadius"), SuppressUnmanagedCodeSecurity]
1164 public static extern void GeomSphereSetRadius(IntPtr geom, dReal radius);
1165
1166 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTransformGetCleanup"), SuppressUnmanagedCodeSecurity]
1167 public static extern int GeomTransformGetCleanup(IntPtr geom);
1168
1169 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTransformGetGeom"), SuppressUnmanagedCodeSecurity]
1170 public static extern IntPtr GeomTransformGetGeom(IntPtr geom);
1171
1172 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTransformGetInfo"), SuppressUnmanagedCodeSecurity]
1173 public static extern int GeomTransformGetInfo(IntPtr geom);
1174
1175 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTransformSetCleanup"), SuppressUnmanagedCodeSecurity]
1176 public static extern void GeomTransformSetCleanup(IntPtr geom, int mode);
1177
1178 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTransformSetGeom"), SuppressUnmanagedCodeSecurity]
1179 public static extern void GeomTransformSetGeom(IntPtr geom, IntPtr obj);
1180
1181 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTransformSetInfo"), SuppressUnmanagedCodeSecurity]
1182 public static extern void GeomTransformSetInfo(IntPtr geom, int info);
1183
1184 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshDataBuildDouble"), SuppressUnmanagedCodeSecurity]
1185 public static extern void GeomTriMeshDataBuildDouble(IntPtr d,
1186 double[] vertices, int vertexStride, int vertexCount,
1187 int[] indices, int indexCount, int triStride);
1188
1189 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshDataBuildDouble"), SuppressUnmanagedCodeSecurity]
1190 public static extern void GeomTriMeshDataBuildDouble(IntPtr d,
1191 IntPtr vertices, int vertexStride, int vertexCount,
1192 IntPtr indices, int indexCount, int triStride);
1193
1194 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshDataBuildDouble1"), SuppressUnmanagedCodeSecurity]
1195 public static extern void GeomTriMeshDataBuildDouble1(IntPtr d,
1196 double[] vertices, int vertexStride, int vertexCount,
1197 int[] indices, int indexCount, int triStride,
1198 double[] normals);
1199
1200 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshDataBuildDouble1"), SuppressUnmanagedCodeSecurity]
1201 public static extern void GeomTriMeshDataBuildDouble(IntPtr d,
1202 IntPtr vertices, int vertexStride, int vertexCount,
1203 IntPtr indices, int indexCount, int triStride,
1204 IntPtr normals);
1205
1206 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshDataBuildSimple"), SuppressUnmanagedCodeSecurity]
1207 public static extern void GeomTriMeshDataBuildSingle(IntPtr d,
1208 dReal[] vertices, int vertexStride, int vertexCount,
1209 int[] indices, int indexCount, int triStride);
1210
1211 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshDataBuildSimple"), SuppressUnmanagedCodeSecurity]
1212 public static extern void GeomTriMeshDataBuildSingle(IntPtr d,
1213 IntPtr vertices, int vertexStride, int vertexCount,
1214 IntPtr indices, int indexCount, int triStride);
1215
1216 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshDataBuildSimple1"), SuppressUnmanagedCodeSecurity]
1217 public static extern void GeomTriMeshDataBuildSingle1(IntPtr d,
1218 dReal[] vertices, int vertexStride, int vertexCount,
1219 int[] indices, int indexCount, int triStride,
1220 dReal[] normals);
1221
1222 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshDataBuildSimple1"), SuppressUnmanagedCodeSecurity]
1223 public static extern void GeomTriMeshDataBuildSingle1(IntPtr d,
1224 IntPtr vertices, int vertexStride, int vertexCount,
1225 IntPtr indices, int indexCount, int triStride,
1226 IntPtr normals);
1227
1228 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshDataBuildSingle"), SuppressUnmanagedCodeSecurity]
1229 public static extern void GeomTriMeshDataBuildSimple(IntPtr d,
1230 float[] vertices, int vertexStride, int vertexCount,
1231 int[] indices, int indexCount, int triStride);
1232
1233 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshDataBuildSingle"), SuppressUnmanagedCodeSecurity]
1234 public static extern void GeomTriMeshDataBuildSimple(IntPtr d,
1235 IntPtr vertices, int vertexStride, int vertexCount,
1236 IntPtr indices, int indexCount, int triStride);
1237
1238 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshDataBuildSingle1"), SuppressUnmanagedCodeSecurity]
1239 public static extern void GeomTriMeshDataBuildSimple1(IntPtr d,
1240 float[] vertices, int vertexStride, int vertexCount,
1241 int[] indices, int indexCount, int triStride,
1242 float[] normals);
1243
1244 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshDataBuildSingle1"), SuppressUnmanagedCodeSecurity]
1245 public static extern void GeomTriMeshDataBuildSimple1(IntPtr d,
1246 IntPtr vertices, int vertexStride, int vertexCount,
1247 IntPtr indices, int indexCount, int triStride,
1248 IntPtr normals);
1249
1250 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshClearTCCache"), SuppressUnmanagedCodeSecurity]
1251 public static extern void GeomTriMeshClearTCCache(IntPtr g);
1252
1253 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshDataCreate"), SuppressUnmanagedCodeSecurity]
1254 public static extern IntPtr GeomTriMeshDataCreate();
1255
1256 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshDataDestroy"), SuppressUnmanagedCodeSecurity]
1257 public static extern void GeomTriMeshDataDestroy(IntPtr d);
1258
1259 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshDataGet"), SuppressUnmanagedCodeSecurity]
1260 public static extern IntPtr GeomTriMeshDataGet(IntPtr d, int data_id);
1261
1262 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshDataPreprocess"), SuppressUnmanagedCodeSecurity]
1263 public static extern void GeomTriMeshDataPreprocess(IntPtr d);
1264
1265 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshDataSet"), SuppressUnmanagedCodeSecurity]
1266 public static extern void GeomTriMeshDataSet(IntPtr d, int data_id, IntPtr in_data);
1267
1268 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshDataUpdate"), SuppressUnmanagedCodeSecurity]
1269 public static extern void GeomTriMeshDataUpdate(IntPtr d);
1270
1271 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshEnableTC"), SuppressUnmanagedCodeSecurity]
1272 public static extern void GeomTriMeshEnableTC(IntPtr g, int geomClass, bool enable);
1273
1274 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshGetArrayCallback"), SuppressUnmanagedCodeSecurity]
1275 public static extern TriArrayCallback GeomTriMeshGetArrayCallback(IntPtr g);
1276
1277 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshGetCallback"), SuppressUnmanagedCodeSecurity]
1278 public static extern TriCallback GeomTriMeshGetCallback(IntPtr g);
1279
1280 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshGetData"), SuppressUnmanagedCodeSecurity]
1281 public static extern IntPtr GeomTriMeshGetData(IntPtr g);
1282
1283 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshGetLastTransform"), SuppressUnmanagedCodeSecurity]
1284 public extern unsafe static Matrix4* GeomTriMeshGetLastTransformUnsafe(IntPtr geom);
1285 public static Matrix4 GeomTriMeshGetLastTransform(IntPtr geom)
1286 {
1287 unsafe { return *(GeomTriMeshGetLastTransformUnsafe(geom)); }
1288 }
1289
1290 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshGetPoint"), SuppressUnmanagedCodeSecurity]
1291 public extern static void GeomTriMeshGetPoint(IntPtr g, int index, dReal u, dReal v, ref Vector3 outVec);
1292
1293 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshGetRayCallback"), SuppressUnmanagedCodeSecurity]
1294 public static extern TriRayCallback GeomTriMeshGetRayCallback(IntPtr g);
1295
1296 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshGetTriangle"), SuppressUnmanagedCodeSecurity]
1297 public extern static void GeomTriMeshGetTriangle(IntPtr g, int index, ref Vector3 v0, ref Vector3 v1, ref Vector3 v2);
1298
1299 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshGetTriangleCount"), SuppressUnmanagedCodeSecurity]
1300 public extern static int GeomTriMeshGetTriangleCount(IntPtr g);
1301
1302 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshGetTriMeshDataID"), SuppressUnmanagedCodeSecurity]
1303 public static extern IntPtr GeomTriMeshGetTriMeshDataID(IntPtr g);
1304
1305 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshIsTCEnabled"), SuppressUnmanagedCodeSecurity]
1306 public static extern bool GeomTriMeshIsTCEnabled(IntPtr g, int geomClass);
1307
1308 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshSetArrayCallback"), SuppressUnmanagedCodeSecurity]
1309 public static extern void GeomTriMeshSetArrayCallback(IntPtr g, TriArrayCallback arrayCallback);
1310
1311 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshSetCallback"), SuppressUnmanagedCodeSecurity]
1312 public static extern void GeomTriMeshSetCallback(IntPtr g, TriCallback callback);
1313
1314 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshSetData"), SuppressUnmanagedCodeSecurity]
1315 public static extern void GeomTriMeshSetData(IntPtr g, IntPtr data);
1316
1317 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshSetLastTransform"), SuppressUnmanagedCodeSecurity]
1318 public static extern void GeomTriMeshSetLastTransform(IntPtr g, ref Matrix4 last_trans);
1319
1320 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshSetLastTransform"), SuppressUnmanagedCodeSecurity]
1321 public static extern void GeomTriMeshSetLastTransform(IntPtr g, ref dReal M00);
1322
1323 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshSetRayCallback"), SuppressUnmanagedCodeSecurity]
1324 public static extern void GeomTriMeshSetRayCallback(IntPtr g, TriRayCallback callback);
1325
1326 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGetConfiguration"), SuppressUnmanagedCodeSecurity]
1327 public static extern IntPtr iGetConfiguration();
1328
1329 public static string GetConfiguration()
1330 {
1331 IntPtr ptr = iGetConfiguration();
1332 string s = Marshal.PtrToStringAnsi(ptr);
1333 return s;
1334 }
1335
1336 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dHashSpaceCreate"), SuppressUnmanagedCodeSecurity]
1337 public static extern IntPtr HashSpaceCreate(IntPtr space);
1338
1339 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dHashSpaceGetLevels"), SuppressUnmanagedCodeSecurity]
1340 public static extern void HashSpaceGetLevels(IntPtr space, out int minlevel, out int maxlevel);
1341
1342 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dHashSpaceSetLevels"), SuppressUnmanagedCodeSecurity]
1343 public static extern void HashSpaceSetLevels(IntPtr space, int minlevel, int maxlevel);
1344
1345 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dInfiniteAABB"), SuppressUnmanagedCodeSecurity]
1346 public static extern void InfiniteAABB(IntPtr geom, out AABB aabb);
1347
1348 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dInitODE"), SuppressUnmanagedCodeSecurity]
1349 public static extern void InitODE();
1350
1351 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dInitODE2"), SuppressUnmanagedCodeSecurity]
1352 public static extern int InitODE2(uint ODEInitFlags);
1353
1354 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dIsPositiveDefinite"), SuppressUnmanagedCodeSecurity]
1355 public static extern int IsPositiveDefinite(ref dReal A, int n);
1356
1357 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dInvertPDMatrix"), SuppressUnmanagedCodeSecurity]
1358 public static extern int InvertPDMatrix(ref dReal A, out dReal Ainv, int n);
1359
1360 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointAddAMotorTorques"), SuppressUnmanagedCodeSecurity]
1361 public static extern void JointAddAMotorTorques(IntPtr joint, dReal torque1, dReal torque2, dReal torque3);
1362
1363 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointAddHingeTorque"), SuppressUnmanagedCodeSecurity]
1364 public static extern void JointAddHingeTorque(IntPtr joint, dReal torque);
1365
1366 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointAddHinge2Torque"), SuppressUnmanagedCodeSecurity]
1367 public static extern void JointAddHinge2Torques(IntPtr joint, dReal torque1, dReal torque2);
1368
1369 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointAddPRTorque"), SuppressUnmanagedCodeSecurity]
1370 public static extern void JointAddPRTorque(IntPtr joint, dReal torque);
1371
1372 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointAddUniversalTorque"), SuppressUnmanagedCodeSecurity]
1373 public static extern void JointAddUniversalTorques(IntPtr joint, dReal torque1, dReal torque2);
1374
1375 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointAddSliderForce"), SuppressUnmanagedCodeSecurity]
1376 public static extern void JointAddSliderForce(IntPtr joint, dReal force);
1377
1378 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointAttach"), SuppressUnmanagedCodeSecurity]
1379 public static extern void JointAttach(IntPtr joint, IntPtr body1, IntPtr body2);
1380
1381 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointCreateAMotor"), SuppressUnmanagedCodeSecurity]
1382 public static extern IntPtr JointCreateAMotor(IntPtr world, IntPtr group);
1383
1384 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointCreateBall"), SuppressUnmanagedCodeSecurity]
1385 public static extern IntPtr JointCreateBall(IntPtr world, IntPtr group);
1386
1387 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointCreateContact"), SuppressUnmanagedCodeSecurity]
1388 public static extern IntPtr JointCreateContact(IntPtr world, IntPtr group, ref Contact contact);
1389 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointCreateContact"), SuppressUnmanagedCodeSecurity]
1390 public static extern IntPtr JointCreateContactPtr(IntPtr world, IntPtr group, IntPtr contact);
1391
1392 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointCreateFixed"), SuppressUnmanagedCodeSecurity]
1393 public static extern IntPtr JointCreateFixed(IntPtr world, IntPtr group);
1394
1395 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointCreateHinge"), SuppressUnmanagedCodeSecurity]
1396 public static extern IntPtr JointCreateHinge(IntPtr world, IntPtr group);
1397
1398 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointCreateHinge2"), SuppressUnmanagedCodeSecurity]
1399 public static extern IntPtr JointCreateHinge2(IntPtr world, IntPtr group);
1400
1401 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointCreateLMotor"), SuppressUnmanagedCodeSecurity]
1402 public static extern IntPtr JointCreateLMotor(IntPtr world, IntPtr group);
1403
1404 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointCreateNull"), SuppressUnmanagedCodeSecurity]
1405 public static extern IntPtr JointCreateNull(IntPtr world, IntPtr group);
1406
1407 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointCreatePR"), SuppressUnmanagedCodeSecurity]
1408 public static extern IntPtr JointCreatePR(IntPtr world, IntPtr group);
1409
1410 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointCreatePlane2D"), SuppressUnmanagedCodeSecurity]
1411 public static extern IntPtr JointCreatePlane2D(IntPtr world, IntPtr group);
1412
1413 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointCreateSlider"), SuppressUnmanagedCodeSecurity]
1414 public static extern IntPtr JointCreateSlider(IntPtr world, IntPtr group);
1415
1416 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointCreateUniversal"), SuppressUnmanagedCodeSecurity]
1417 public static extern IntPtr JointCreateUniversal(IntPtr world, IntPtr group);
1418
1419 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointDestroy"), SuppressUnmanagedCodeSecurity]
1420 public static extern void JointDestroy(IntPtr j);
1421
1422 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetAMotorAngle"), SuppressUnmanagedCodeSecurity]
1423 public static extern dReal JointGetAMotorAngle(IntPtr j, int anum);
1424
1425 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetAMotorAngleRate"), SuppressUnmanagedCodeSecurity]
1426 public static extern dReal JointGetAMotorAngleRate(IntPtr j, int anum);
1427
1428 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetAMotorAxis"), SuppressUnmanagedCodeSecurity]
1429 public static extern void JointGetAMotorAxis(IntPtr j, int anum, out Vector3 result);
1430
1431 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetAMotorAxisRel"), SuppressUnmanagedCodeSecurity]
1432 public static extern int JointGetAMotorAxisRel(IntPtr j, int anum);
1433
1434 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetAMotorMode"), SuppressUnmanagedCodeSecurity]
1435 public static extern int JointGetAMotorMode(IntPtr j);
1436
1437 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetAMotorNumAxes"), SuppressUnmanagedCodeSecurity]
1438 public static extern int JointGetAMotorNumAxes(IntPtr j);
1439
1440 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetAMotorParam"), SuppressUnmanagedCodeSecurity]
1441 public static extern dReal JointGetAMotorParam(IntPtr j, int parameter);
1442
1443 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetBallAnchor"), SuppressUnmanagedCodeSecurity]
1444 public static extern void JointGetBallAnchor(IntPtr j, out Vector3 result);
1445
1446 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetBallAnchor2"), SuppressUnmanagedCodeSecurity]
1447 public static extern void JointGetBallAnchor2(IntPtr j, out Vector3 result);
1448
1449 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetBody"), SuppressUnmanagedCodeSecurity]
1450 public static extern IntPtr JointGetBody(IntPtr j);
1451
1452 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetData"), SuppressUnmanagedCodeSecurity]
1453 public static extern IntPtr JointGetData(IntPtr j);
1454
1455 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetFeedback"), SuppressUnmanagedCodeSecurity]
1456 public extern unsafe static JointFeedback* JointGetFeedbackUnsafe(IntPtr j);
1457 public static JointFeedback JointGetFeedback(IntPtr j)
1458 {
1459 unsafe { return *(JointGetFeedbackUnsafe(j)); }
1460 }
1461
1462 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetHingeAnchor"), SuppressUnmanagedCodeSecurity]
1463 public static extern void JointGetHingeAnchor(IntPtr j, out Vector3 result);
1464
1465 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetHingeAngle"), SuppressUnmanagedCodeSecurity]
1466 public static extern dReal JointGetHingeAngle(IntPtr j);
1467
1468 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetHingeAngleRate"), SuppressUnmanagedCodeSecurity]
1469 public static extern dReal JointGetHingeAngleRate(IntPtr j);
1470
1471 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetHingeAxis"), SuppressUnmanagedCodeSecurity]
1472 public static extern void JointGetHingeAxis(IntPtr j, out Vector3 result);
1473
1474 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetHingeParam"), SuppressUnmanagedCodeSecurity]
1475 public static extern dReal JointGetHingeParam(IntPtr j, int parameter);
1476
1477 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetHinge2Angle1"), SuppressUnmanagedCodeSecurity]
1478 public static extern dReal JointGetHinge2Angle1(IntPtr j);
1479
1480 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetHinge2Angle1Rate"), SuppressUnmanagedCodeSecurity]
1481 public static extern dReal JointGetHinge2Angle1Rate(IntPtr j);
1482
1483 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetHinge2Angle2Rate"), SuppressUnmanagedCodeSecurity]
1484 public static extern dReal JointGetHinge2Angle2Rate(IntPtr j);
1485
1486 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetHingeAnchor2"), SuppressUnmanagedCodeSecurity]
1487 public static extern void JointGetHingeAnchor2(IntPtr j, out Vector3 result);
1488
1489 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetHinge2Anchor"), SuppressUnmanagedCodeSecurity]
1490 public static extern void JointGetHinge2Anchor(IntPtr j, out Vector3 result);
1491
1492 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetHinge2Anchor2"), SuppressUnmanagedCodeSecurity]
1493 public static extern void JointGetHinge2Anchor2(IntPtr j, out Vector3 result);
1494
1495 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetHinge2Axis1"), SuppressUnmanagedCodeSecurity]
1496 public static extern void JointGetHinge2Axis1(IntPtr j, out Vector3 result);
1497
1498 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetHinge2Axis2"), SuppressUnmanagedCodeSecurity]
1499 public static extern void JointGetHinge2Axis2(IntPtr j, out Vector3 result);
1500
1501 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetHinge2Param"), SuppressUnmanagedCodeSecurity]
1502 public static extern dReal JointGetHinge2Param(IntPtr j, int parameter);
1503
1504 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetLMotorAxis"), SuppressUnmanagedCodeSecurity]
1505 public static extern void JointGetLMotorAxis(IntPtr j, int anum, out Vector3 result);
1506
1507 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetLMotorNumAxes"), SuppressUnmanagedCodeSecurity]
1508 public static extern int JointGetLMotorNumAxes(IntPtr j);
1509
1510 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetLMotorParam"), SuppressUnmanagedCodeSecurity]
1511 public static extern dReal JointGetLMotorParam(IntPtr j, int parameter);
1512
1513 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetPRAnchor"), SuppressUnmanagedCodeSecurity]
1514 public static extern void JointGetPRAnchor(IntPtr j, out Vector3 result);
1515
1516 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetPRAxis1"), SuppressUnmanagedCodeSecurity]
1517 public static extern void JointGetPRAxis1(IntPtr j, out Vector3 result);
1518
1519 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetPRAxis2"), SuppressUnmanagedCodeSecurity]
1520 public static extern void JointGetPRAxis2(IntPtr j, out Vector3 result);
1521
1522 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetPRParam"), SuppressUnmanagedCodeSecurity]
1523 public static extern dReal JointGetPRParam(IntPtr j, int parameter);
1524
1525 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetPRPosition"), SuppressUnmanagedCodeSecurity]
1526 public static extern dReal JointGetPRPosition(IntPtr j);
1527
1528 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetPRPositionRate"), SuppressUnmanagedCodeSecurity]
1529 public static extern dReal JointGetPRPositionRate(IntPtr j);
1530
1531 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetSliderAxis"), SuppressUnmanagedCodeSecurity]
1532 public static extern void JointGetSliderAxis(IntPtr j, out Vector3 result);
1533
1534 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetSliderParam"), SuppressUnmanagedCodeSecurity]
1535 public static extern dReal JointGetSliderParam(IntPtr j, int parameter);
1536
1537 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetSliderPosition"), SuppressUnmanagedCodeSecurity]
1538 public static extern dReal JointGetSliderPosition(IntPtr j);
1539
1540 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetSliderPositionRate"), SuppressUnmanagedCodeSecurity]
1541 public static extern dReal JointGetSliderPositionRate(IntPtr j);
1542
1543 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetType"), SuppressUnmanagedCodeSecurity]
1544 public static extern JointType JointGetType(IntPtr j);
1545
1546 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetUniversalAnchor"), SuppressUnmanagedCodeSecurity]
1547 public static extern void JointGetUniversalAnchor(IntPtr j, out Vector3 result);
1548
1549 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetUniversalAnchor2"), SuppressUnmanagedCodeSecurity]
1550 public static extern void JointGetUniversalAnchor2(IntPtr j, out Vector3 result);
1551
1552 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetUniversalAngle1"), SuppressUnmanagedCodeSecurity]
1553 public static extern dReal JointGetUniversalAngle1(IntPtr j);
1554
1555 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetUniversalAngle1Rate"), SuppressUnmanagedCodeSecurity]
1556 public static extern dReal JointGetUniversalAngle1Rate(IntPtr j);
1557
1558 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetUniversalAngle2"), SuppressUnmanagedCodeSecurity]
1559 public static extern dReal JointGetUniversalAngle2(IntPtr j);
1560
1561 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetUniversalAngle2Rate"), SuppressUnmanagedCodeSecurity]
1562 public static extern dReal JointGetUniversalAngle2Rate(IntPtr j);
1563
1564 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetUniversalAngles"), SuppressUnmanagedCodeSecurity]
1565 public static extern void JointGetUniversalAngles(IntPtr j, out dReal angle1, out dReal angle2);
1566
1567 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetUniversalAxis1"), SuppressUnmanagedCodeSecurity]
1568 public static extern void JointGetUniversalAxis1(IntPtr j, out Vector3 result);
1569
1570 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetUniversalAxis2"), SuppressUnmanagedCodeSecurity]
1571 public static extern void JointGetUniversalAxis2(IntPtr j, out Vector3 result);
1572
1573 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetUniversalParam"), SuppressUnmanagedCodeSecurity]
1574 public static extern dReal JointGetUniversalParam(IntPtr j, int parameter);
1575
1576 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGroupCreate"), SuppressUnmanagedCodeSecurity]
1577 public static extern IntPtr JointGroupCreate(int max_size);
1578
1579 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGroupDestroy"), SuppressUnmanagedCodeSecurity]
1580 public static extern void JointGroupDestroy(IntPtr group);
1581
1582 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGroupEmpty"), SuppressUnmanagedCodeSecurity]
1583 public static extern void JointGroupEmpty(IntPtr group);
1584
1585 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetAMotorAngle"), SuppressUnmanagedCodeSecurity]
1586 public static extern void JointSetAMotorAngle(IntPtr j, int anum, dReal angle);
1587
1588 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetAMotorAxis"), SuppressUnmanagedCodeSecurity]
1589 public static extern void JointSetAMotorAxis(IntPtr j, int anum, int rel, dReal x, dReal y, dReal z);
1590
1591 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetAMotorMode"), SuppressUnmanagedCodeSecurity]
1592 public static extern void JointSetAMotorMode(IntPtr j, int mode);
1593
1594 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetAMotorNumAxes"), SuppressUnmanagedCodeSecurity]
1595 public static extern void JointSetAMotorNumAxes(IntPtr group, int num);
1596
1597 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetAMotorParam"), SuppressUnmanagedCodeSecurity]
1598 public static extern void JointSetAMotorParam(IntPtr group, int parameter, dReal value);
1599
1600 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetBallAnchor"), SuppressUnmanagedCodeSecurity]
1601 public static extern void JointSetBallAnchor(IntPtr j, dReal x, dReal y, dReal z);
1602
1603 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetBallAnchor2"), SuppressUnmanagedCodeSecurity]
1604 public static extern void JointSetBallAnchor2(IntPtr j, dReal x, dReal y, dReal z);
1605
1606 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetData"), SuppressUnmanagedCodeSecurity]
1607 public static extern void JointSetData(IntPtr j, IntPtr data);
1608
1609 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetFeedback"), SuppressUnmanagedCodeSecurity]
1610 public static extern void JointSetFeedback(IntPtr j, out JointFeedback feedback);
1611
1612 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetFixed"), SuppressUnmanagedCodeSecurity]
1613 public static extern void JointSetFixed(IntPtr j);
1614
1615 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetHingeAnchor"), SuppressUnmanagedCodeSecurity]
1616 public static extern void JointSetHingeAnchor(IntPtr j, dReal x, dReal y, dReal z);
1617
1618 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetHingeAnchorDelta"), SuppressUnmanagedCodeSecurity]
1619 public static extern void JointSetHingeAnchorDelta(IntPtr j, dReal x, dReal y, dReal z, dReal ax, dReal ay, dReal az);
1620
1621 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetHingeAxis"), SuppressUnmanagedCodeSecurity]
1622 public static extern void JointSetHingeAxis(IntPtr j, dReal x, dReal y, dReal z);
1623
1624 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetHingeParam"), SuppressUnmanagedCodeSecurity]
1625 public static extern void JointSetHingeParam(IntPtr j, int parameter, dReal value);
1626
1627 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetHinge2Anchor"), SuppressUnmanagedCodeSecurity]
1628 public static extern void JointSetHinge2Anchor(IntPtr j, dReal x, dReal y, dReal z);
1629
1630 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetHinge2Axis1"), SuppressUnmanagedCodeSecurity]
1631 public static extern void JointSetHinge2Axis1(IntPtr j, dReal x, dReal y, dReal z);
1632
1633 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetHinge2Axis2"), SuppressUnmanagedCodeSecurity]
1634 public static extern void JointSetHinge2Axis2(IntPtr j, dReal x, dReal y, dReal z);
1635
1636 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetHinge2Param"), SuppressUnmanagedCodeSecurity]
1637 public static extern void JointSetHinge2Param(IntPtr j, int parameter, dReal value);
1638
1639 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetLMotorAxis"), SuppressUnmanagedCodeSecurity]
1640 public static extern void JointSetLMotorAxis(IntPtr j, int anum, int rel, dReal x, dReal y, dReal z);
1641
1642 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetLMotorNumAxes"), SuppressUnmanagedCodeSecurity]
1643 public static extern void JointSetLMotorNumAxes(IntPtr j, int num);
1644
1645 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetLMotorParam"), SuppressUnmanagedCodeSecurity]
1646 public static extern void JointSetLMotorParam(IntPtr j, int parameter, dReal value);
1647
1648 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetPlane2DAngleParam"), SuppressUnmanagedCodeSecurity]
1649 public static extern void JointSetPlane2DAngleParam(IntPtr j, int parameter, dReal value);
1650
1651 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetPlane2DXParam"), SuppressUnmanagedCodeSecurity]
1652 public static extern void JointSetPlane2DXParam(IntPtr j, int parameter, dReal value);
1653
1654 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetPlane2DYParam"), SuppressUnmanagedCodeSecurity]
1655 public static extern void JointSetPlane2DYParam(IntPtr j, int parameter, dReal value);
1656
1657 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetPRAnchor"), SuppressUnmanagedCodeSecurity]
1658 public static extern void JointSetPRAnchor(IntPtr j, dReal x, dReal y, dReal z);
1659
1660 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetPRAxis1"), SuppressUnmanagedCodeSecurity]
1661 public static extern void JointSetPRAxis1(IntPtr j, dReal x, dReal y, dReal z);
1662
1663 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetPRAxis2"), SuppressUnmanagedCodeSecurity]
1664 public static extern void JointSetPRAxis2(IntPtr j, dReal x, dReal y, dReal z);
1665
1666 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetPRParam"), SuppressUnmanagedCodeSecurity]
1667 public static extern void JointSetPRParam(IntPtr j, int parameter, dReal value);
1668
1669 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetSliderAxis"), SuppressUnmanagedCodeSecurity]
1670 public static extern void JointSetSliderAxis(IntPtr j, dReal x, dReal y, dReal z);
1671
1672 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetSliderAxisDelta"), SuppressUnmanagedCodeSecurity]
1673 public static extern void JointSetSliderAxisDelta(IntPtr j, dReal x, dReal y, dReal z, dReal ax, dReal ay, dReal az);
1674
1675 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetSliderParam"), SuppressUnmanagedCodeSecurity]
1676 public static extern void JointSetSliderParam(IntPtr j, int parameter, dReal value);
1677
1678 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetUniversalAnchor"), SuppressUnmanagedCodeSecurity]
1679 public static extern void JointSetUniversalAnchor(IntPtr j, dReal x, dReal y, dReal z);
1680
1681 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetUniversalAxis1"), SuppressUnmanagedCodeSecurity]
1682 public static extern void JointSetUniversalAxis1(IntPtr j, dReal x, dReal y, dReal z);
1683
1684 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetUniversalAxis2"), SuppressUnmanagedCodeSecurity]
1685 public static extern void JointSetUniversalAxis2(IntPtr j, dReal x, dReal y, dReal z);
1686
1687 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetUniversalParam"), SuppressUnmanagedCodeSecurity]
1688 public static extern void JointSetUniversalParam(IntPtr j, int parameter, dReal value);
1689
1690 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dLDLTAddTL"), SuppressUnmanagedCodeSecurity]
1691 public static extern void LDLTAddTL(ref dReal L, ref dReal d, ref dReal a, int n, int nskip);
1692
1693 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMassAdd"), SuppressUnmanagedCodeSecurity]
1694 public static extern void MassAdd(ref Mass a, ref Mass b);
1695
1696 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMassAdjust"), SuppressUnmanagedCodeSecurity]
1697 public static extern void MassAdjust(ref Mass m, dReal newmass);
1698
1699 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMassCheck"), SuppressUnmanagedCodeSecurity]
1700 public static extern bool MassCheck(ref Mass m);
1701
1702 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMassRotate"), SuppressUnmanagedCodeSecurity]
1703 public static extern void MassRotate(ref Mass mass, ref Matrix3 R);
1704
1705 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMassRotate"), SuppressUnmanagedCodeSecurity]
1706 public static extern void MassRotate(ref Mass mass, ref dReal M00);
1707
1708 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMassSetBox"), SuppressUnmanagedCodeSecurity]
1709 public static extern void MassSetBox(out Mass mass, dReal density, dReal lx, dReal ly, dReal lz);
1710
1711 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMassSetBoxTotal"), SuppressUnmanagedCodeSecurity]
1712 public static extern void MassSetBoxTotal(out Mass mass, dReal total_mass, dReal lx, dReal ly, dReal lz);
1713
1714 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMassSetCapsule"), SuppressUnmanagedCodeSecurity]
1715 public static extern void MassSetCapsule(out Mass mass, dReal density, int direction, dReal radius, dReal length);
1716
1717 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMassSetCapsuleTotal"), SuppressUnmanagedCodeSecurity]
1718 public static extern void MassSetCapsuleTotal(out Mass mass, dReal total_mass, int direction, dReal radius, dReal length);
1719
1720 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMassSetCylinder"), SuppressUnmanagedCodeSecurity]
1721 public static extern void MassSetCylinder(out Mass mass, dReal density, int direction, dReal radius, dReal length);
1722
1723 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMassSetCylinderTotal"), SuppressUnmanagedCodeSecurity]
1724 public static extern void MassSetCylinderTotal(out Mass mass, dReal total_mass, int direction, dReal radius, dReal length);
1725
1726 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMassSetParameters"), SuppressUnmanagedCodeSecurity]
1727 public static extern void MassSetParameters(out Mass mass, dReal themass,
1728 dReal cgx, dReal cgy, dReal cgz,
1729 dReal i11, dReal i22, dReal i33,
1730 dReal i12, dReal i13, dReal i23);
1731
1732 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMassSetSphere"), SuppressUnmanagedCodeSecurity]
1733 public static extern void MassSetSphere(out Mass mass, dReal density, dReal radius);
1734
1735 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMassSetSphereTotal"), SuppressUnmanagedCodeSecurity]
1736 public static extern void dMassSetSphereTotal(out Mass mass, dReal total_mass, dReal radius);
1737
1738 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMassSetTrimesh"), SuppressUnmanagedCodeSecurity]
1739 public static extern void MassSetTrimesh(out Mass mass, dReal density, IntPtr g);
1740
1741 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMassSetZero"), SuppressUnmanagedCodeSecurity]
1742 public static extern void MassSetZero(out Mass mass);
1743
1744 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMassTranslate"), SuppressUnmanagedCodeSecurity]
1745 public static extern void MassTranslate(ref Mass mass, dReal x, dReal y, dReal z);
1746
1747 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMultiply0"), SuppressUnmanagedCodeSecurity]
1748 public static extern void Multiply0(out dReal A00, ref dReal B00, ref dReal C00, int p, int q, int r);
1749
1750 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMultiply0"), SuppressUnmanagedCodeSecurity]
1751 private static extern void MultiplyiM3V3(out Vector3 vout, ref Matrix3 matrix, ref Vector3 vect,int p, int q, int r);
1752 public static void MultiplyM3V3(out Vector3 outvector, ref Matrix3 matrix, ref Vector3 invector)
1753 {
1754 MultiplyiM3V3(out outvector, ref matrix, ref invector, 3, 3, 1);
1755 }
1756
1757 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMultiply1"), SuppressUnmanagedCodeSecurity]
1758 public static extern void Multiply1(out dReal A00, ref dReal B00, ref dReal C00, int p, int q, int r);
1759
1760 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMultiply2"), SuppressUnmanagedCodeSecurity]
1761 public static extern void Multiply2(out dReal A00, ref dReal B00, ref dReal C00, int p, int q, int r);
1762
1763 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dQFromAxisAndAngle"), SuppressUnmanagedCodeSecurity]
1764 public static extern void QFromAxisAndAngle(out Quaternion q, dReal ax, dReal ay, dReal az, dReal angle);
1765
1766 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dQfromR"), SuppressUnmanagedCodeSecurity]
1767 public static extern void QfromR(out Quaternion q, ref Matrix3 R);
1768
1769 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dQMultiply0"), SuppressUnmanagedCodeSecurity]
1770 public static extern void QMultiply0(out Quaternion qa, ref Quaternion qb, ref Quaternion qc);
1771
1772 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dQMultiply1"), SuppressUnmanagedCodeSecurity]
1773 public static extern void QMultiply1(out Quaternion qa, ref Quaternion qb, ref Quaternion qc);
1774
1775 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dQMultiply2"), SuppressUnmanagedCodeSecurity]
1776 public static extern void QMultiply2(out Quaternion qa, ref Quaternion qb, ref Quaternion qc);
1777
1778 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dQMultiply3"), SuppressUnmanagedCodeSecurity]
1779 public static extern void QMultiply3(out Quaternion qa, ref Quaternion qb, ref Quaternion qc);
1780
1781 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dQSetIdentity"), SuppressUnmanagedCodeSecurity]
1782 public static extern void QSetIdentity(out Quaternion q);
1783
1784 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dQuadTreeSpaceCreate"), SuppressUnmanagedCodeSecurity]
1785 public static extern IntPtr QuadTreeSpaceCreate(IntPtr space, ref Vector3 center, ref Vector3 extents, int depth);
1786
1787 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dQuadTreeSpaceCreate"), SuppressUnmanagedCodeSecurity]
1788 public static extern IntPtr QuadTreeSpaceCreate(IntPtr space, ref dReal centerX, ref dReal extentsX, int depth);
1789
1790 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dRandReal"), SuppressUnmanagedCodeSecurity]
1791 public static extern dReal RandReal();
1792
1793 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dRFrom2Axes"), SuppressUnmanagedCodeSecurity]
1794 public static extern void RFrom2Axes(out Matrix3 R, dReal ax, dReal ay, dReal az, dReal bx, dReal by, dReal bz);
1795
1796 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dRFromAxisAndAngle"), SuppressUnmanagedCodeSecurity]
1797 public static extern void RFromAxisAndAngle(out Matrix3 R, dReal x, dReal y, dReal z, dReal angle);
1798
1799 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dRFromEulerAngles"), SuppressUnmanagedCodeSecurity]
1800 public static extern void RFromEulerAngles(out Matrix3 R, dReal phi, dReal theta, dReal psi);
1801
1802 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dRfromQ"), SuppressUnmanagedCodeSecurity]
1803 public static extern void RfromQ(out Matrix3 R, ref Quaternion q);
1804
1805 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dRFromZAxis"), SuppressUnmanagedCodeSecurity]
1806 public static extern void RFromZAxis(out Matrix3 R, dReal ax, dReal ay, dReal az);
1807
1808 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dRSetIdentity"), SuppressUnmanagedCodeSecurity]
1809 public static extern void RSetIdentity(out Matrix3 R);
1810
1811 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSetValue"), SuppressUnmanagedCodeSecurity]
1812 public static extern void SetValue(out dReal a, int n);
1813
1814 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSetZero"), SuppressUnmanagedCodeSecurity]
1815 public static extern void SetZero(out dReal a, int n);
1816
1817 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSimpleSpaceCreate"), SuppressUnmanagedCodeSecurity]
1818 public static extern IntPtr SimpleSpaceCreate(IntPtr space);
1819
1820 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSolveCholesky"), SuppressUnmanagedCodeSecurity]
1821 public static extern void SolveCholesky(ref dReal L, out dReal b, int n);
1822
1823 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSolveL1"), SuppressUnmanagedCodeSecurity]
1824 public static extern void SolveL1(ref dReal L, out dReal b, int n, int nskip);
1825
1826 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSolveL1T"), SuppressUnmanagedCodeSecurity]
1827 public static extern void SolveL1T(ref dReal L, out dReal b, int n, int nskip);
1828
1829 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSolveLDLT"), SuppressUnmanagedCodeSecurity]
1830 public static extern void SolveLDLT(ref dReal L, ref dReal d, out dReal b, int n, int nskip);
1831
1832 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSpaceAdd"), SuppressUnmanagedCodeSecurity]
1833 public static extern void SpaceAdd(IntPtr space, IntPtr geom);
1834
1835 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSpaceLockQuery"), SuppressUnmanagedCodeSecurity]
1836 public static extern bool SpaceLockQuery(IntPtr space);
1837
1838 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSpaceClean"), SuppressUnmanagedCodeSecurity]
1839 public static extern void SpaceClean(IntPtr space);
1840
1841 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSpaceCollide"), SuppressUnmanagedCodeSecurity]
1842 public static extern void SpaceCollide(IntPtr space, IntPtr data, NearCallback callback);
1843
1844 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSpaceCollide2"), SuppressUnmanagedCodeSecurity]
1845 public static extern void SpaceCollide2(IntPtr space1, IntPtr space2, IntPtr data, NearCallback callback);
1846
1847 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSpaceDestroy"), SuppressUnmanagedCodeSecurity]
1848 public static extern void SpaceDestroy(IntPtr space);
1849
1850 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSpaceGetCleanup"), SuppressUnmanagedCodeSecurity]
1851 public static extern bool SpaceGetCleanup(IntPtr space);
1852
1853 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSpaceGetNumGeoms"), SuppressUnmanagedCodeSecurity]
1854 public static extern int SpaceGetNumGeoms(IntPtr space);
1855
1856 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSpaceGetGeom"), SuppressUnmanagedCodeSecurity]
1857 public static extern IntPtr SpaceGetGeom(IntPtr space, int i);
1858
1859 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSpaceGetSublevel"), SuppressUnmanagedCodeSecurity]
1860 public static extern int SpaceGetSublevel(IntPtr space);
1861
1862 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSpaceQuery"), SuppressUnmanagedCodeSecurity]
1863 public static extern bool SpaceQuery(IntPtr space, IntPtr geom);
1864
1865 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSpaceRemove"), SuppressUnmanagedCodeSecurity]
1866 public static extern void SpaceRemove(IntPtr space, IntPtr geom);
1867
1868 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSpaceSetCleanup"), SuppressUnmanagedCodeSecurity]
1869 public static extern void SpaceSetCleanup(IntPtr space, bool mode);
1870
1871 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSpaceSetSublevel"), SuppressUnmanagedCodeSecurity]
1872 public static extern void SpaceSetSublevel(IntPtr space, int sublevel);
1873
1874 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSweepAndPruneSpaceCreate"), SuppressUnmanagedCodeSecurity]
1875 public static extern IntPtr SweepAndPruneSpaceCreate(IntPtr space, int AxisOrder);
1876
1877 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dVectorScale"), SuppressUnmanagedCodeSecurity]
1878 public static extern void VectorScale(out dReal a, ref dReal d, int n);
1879
1880 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldCreate"), SuppressUnmanagedCodeSecurity]
1881 public static extern IntPtr WorldCreate();
1882
1883 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldDestroy"), SuppressUnmanagedCodeSecurity]
1884 public static extern void WorldDestroy(IntPtr world);
1885
1886 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetAutoDisableAverageSamplesCount"), SuppressUnmanagedCodeSecurity]
1887 public static extern int WorldGetAutoDisableAverageSamplesCount(IntPtr world);
1888
1889 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetAutoDisableAngularThreshold"), SuppressUnmanagedCodeSecurity]
1890 public static extern dReal WorldGetAutoDisableAngularThreshold(IntPtr world);
1891
1892 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetAutoDisableFlag"), SuppressUnmanagedCodeSecurity]
1893 public static extern bool WorldGetAutoDisableFlag(IntPtr world);
1894
1895 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetAutoDisableLinearThreshold"), SuppressUnmanagedCodeSecurity]
1896 public static extern dReal WorldGetAutoDisableLinearThreshold(IntPtr world);
1897
1898 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetAutoDisableSteps"), SuppressUnmanagedCodeSecurity]
1899 public static extern int WorldGetAutoDisableSteps(IntPtr world);
1900
1901 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetAutoDisableTime"), SuppressUnmanagedCodeSecurity]
1902 public static extern dReal WorldGetAutoDisableTime(IntPtr world);
1903
1904 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetAutoEnableDepthSF1"), SuppressUnmanagedCodeSecurity]
1905 public static extern int WorldGetAutoEnableDepthSF1(IntPtr world);
1906
1907 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetCFM"), SuppressUnmanagedCodeSecurity]
1908 public static extern dReal WorldGetCFM(IntPtr world);
1909
1910 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetERP"), SuppressUnmanagedCodeSecurity]
1911 public static extern dReal WorldGetERP(IntPtr world);
1912
1913 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetGravity"), SuppressUnmanagedCodeSecurity]
1914 public static extern void WorldGetGravity(IntPtr world, out Vector3 gravity);
1915
1916 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetGravity"), SuppressUnmanagedCodeSecurity]
1917 public static extern void WorldGetGravity(IntPtr world, out dReal X);
1918
1919 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetContactMaxCorrectingVel"), SuppressUnmanagedCodeSecurity]
1920 public static extern dReal WorldGetContactMaxCorrectingVel(IntPtr world);
1921
1922 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetContactSurfaceLayer"), SuppressUnmanagedCodeSecurity]
1923 public static extern dReal WorldGetContactSurfaceLayer(IntPtr world);
1924
1925 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetAngularDamping"), SuppressUnmanagedCodeSecurity]
1926 public static extern dReal WorldGetAngularDamping(IntPtr world);
1927
1928 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetAngularDampingThreshold"), SuppressUnmanagedCodeSecurity]
1929 public static extern dReal WorldGetAngularDampingThreshold(IntPtr world);
1930
1931 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetLinearDamping"), SuppressUnmanagedCodeSecurity]
1932 public static extern dReal WorldGetLinearDamping(IntPtr world);
1933
1934 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetLinearDampingThreshold"), SuppressUnmanagedCodeSecurity]
1935 public static extern dReal WorldGetLinearDampingThreshold(IntPtr world);
1936
1937 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetQuickStepNumIterations"), SuppressUnmanagedCodeSecurity]
1938 public static extern int WorldGetQuickStepNumIterations(IntPtr world);
1939
1940 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetQuickStepW"), SuppressUnmanagedCodeSecurity]
1941 public static extern dReal WorldGetQuickStepW(IntPtr world);
1942
1943 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetMaxAngularSpeed"), SuppressUnmanagedCodeSecurity]
1944 public static extern dReal WorldGetMaxAngularSpeed(IntPtr world);
1945
1946 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldImpulseToForce"), SuppressUnmanagedCodeSecurity]
1947 public static extern void WorldImpulseToForce(IntPtr world, dReal stepsize, dReal ix, dReal iy, dReal iz, out Vector3 force);
1948
1949 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldImpulseToForce"), SuppressUnmanagedCodeSecurity]
1950 public static extern void WorldImpulseToForce(IntPtr world, dReal stepsize, dReal ix, dReal iy, dReal iz, out dReal forceX);
1951
1952 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldQuickStep"), SuppressUnmanagedCodeSecurity]
1953 public static extern void WorldQuickStep(IntPtr world, dReal stepsize);
1954
1955 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetAngularDamping"), SuppressUnmanagedCodeSecurity]
1956 public static extern void WorldSetAngularDamping(IntPtr world, dReal scale);
1957
1958 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetAngularDampingThreshold"), SuppressUnmanagedCodeSecurity]
1959 public static extern void WorldSetAngularDampingThreshold(IntPtr world, dReal threshold);
1960
1961 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetAutoDisableAngularThreshold"), SuppressUnmanagedCodeSecurity]
1962 public static extern void WorldSetAutoDisableAngularThreshold(IntPtr world, dReal angular_threshold);
1963
1964 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetAutoDisableAverageSamplesCount"), SuppressUnmanagedCodeSecurity]
1965 public static extern void WorldSetAutoDisableAverageSamplesCount(IntPtr world, int average_samples_count);
1966
1967 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetAutoDisableFlag"), SuppressUnmanagedCodeSecurity]
1968 public static extern void WorldSetAutoDisableFlag(IntPtr world, bool do_auto_disable);
1969
1970 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetAutoDisableLinearThreshold"), SuppressUnmanagedCodeSecurity]
1971 public static extern void WorldSetAutoDisableLinearThreshold(IntPtr world, dReal linear_threshold);
1972
1973 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetAutoDisableSteps"), SuppressUnmanagedCodeSecurity]
1974 public static extern void WorldSetAutoDisableSteps(IntPtr world, int steps);
1975
1976 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetAutoDisableTime"), SuppressUnmanagedCodeSecurity]
1977 public static extern void WorldSetAutoDisableTime(IntPtr world, dReal time);
1978
1979 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetAutoEnableDepthSF1"), SuppressUnmanagedCodeSecurity]
1980 public static extern void WorldSetAutoEnableDepthSF1(IntPtr world, int autoEnableDepth);
1981
1982 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetCFM"), SuppressUnmanagedCodeSecurity]
1983 public static extern void WorldSetCFM(IntPtr world, dReal cfm);
1984
1985 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetContactMaxCorrectingVel"), SuppressUnmanagedCodeSecurity]
1986 public static extern void WorldSetContactMaxCorrectingVel(IntPtr world, dReal vel);
1987
1988 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetContactSurfaceLayer"), SuppressUnmanagedCodeSecurity]
1989 public static extern void WorldSetContactSurfaceLayer(IntPtr world, dReal depth);
1990
1991 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetDamping"), SuppressUnmanagedCodeSecurity]
1992 public static extern void WorldSetDamping(IntPtr world, dReal linear_scale, dReal angular_scale);
1993
1994 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetERP"), SuppressUnmanagedCodeSecurity]
1995 public static extern void WorldSetERP(IntPtr world, dReal erp);
1996
1997 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetGravity"), SuppressUnmanagedCodeSecurity]
1998 public static extern void WorldSetGravity(IntPtr world, dReal x, dReal y, dReal z);
1999
2000 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetLinearDamping"), SuppressUnmanagedCodeSecurity]
2001 public static extern void WorldSetLinearDamping(IntPtr world, dReal scale);
2002
2003 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetLinearDampingThreshold"), SuppressUnmanagedCodeSecurity]
2004 public static extern void WorldSetLinearDampingThreshold(IntPtr world, dReal threshold);
2005
2006 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetQuickStepNumIterations"), SuppressUnmanagedCodeSecurity]
2007 public static extern void WorldSetQuickStepNumIterations(IntPtr world, int num);
2008
2009 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetQuickStepW"), SuppressUnmanagedCodeSecurity]
2010 public static extern void WorldSetQuickStepW(IntPtr world, dReal over_relaxation);
2011
2012 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetMaxAngularSpeed"), SuppressUnmanagedCodeSecurity]
2013 public static extern void WorldSetMaxAngularSpeed(IntPtr world, dReal max_speed);
2014
2015 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldStep"), SuppressUnmanagedCodeSecurity]
2016 public static extern void WorldStep(IntPtr world, dReal stepsize);
2017
2018 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldStepFast1"), SuppressUnmanagedCodeSecurity]
2019 public static extern void WorldStepFast1(IntPtr world, dReal stepsize, int maxiterations);
2020
2021 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldExportDIF"), SuppressUnmanagedCodeSecurity]
2022 public static extern void WorldExportDIF(IntPtr world, string filename, bool append, string prefix);
2023 }
2024}
diff --git a/OpenSim/Region/PhysicsModules/ubOde/ODECharacter.cs b/OpenSim/Region/PhysicsModules/ubOde/ODECharacter.cs
new file mode 100644
index 0000000..55619c0
--- /dev/null
+++ b/OpenSim/Region/PhysicsModules/ubOde/ODECharacter.cs
@@ -0,0 +1,1978 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28
29// Revision by Ubit 2011/12
30
31using System;
32using System.Collections.Generic;
33using System.Reflection;
34using OpenMetaverse;
35using OdeAPI;
36using OpenSim.Framework;
37using OpenSim.Region.PhysicsModules.SharedBase;
38using log4net;
39
40namespace OpenSim.Region.PhysicsModule.ubOde
41{
42 /// <summary>
43 /// Various properties that ODE uses for AMotors but isn't exposed in ODE.NET so we must define them ourselves.
44 /// </summary>
45
46 public enum dParam : int
47 {
48 LowStop = 0,
49 HiStop = 1,
50 Vel = 2,
51 FMax = 3,
52 FudgeFactor = 4,
53 Bounce = 5,
54 CFM = 6,
55 StopERP = 7,
56 StopCFM = 8,
57 LoStop2 = 256,
58 HiStop2 = 257,
59 Vel2 = 258,
60 FMax2 = 259,
61 StopERP2 = 7 + 256,
62 StopCFM2 = 8 + 256,
63 LoStop3 = 512,
64 HiStop3 = 513,
65 Vel3 = 514,
66 FMax3 = 515,
67 StopERP3 = 7 + 512,
68 StopCFM3 = 8 + 512
69 }
70
71 public class OdeCharacter : PhysicsActor
72 {
73 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
74
75 private Vector3 _position;
76 private Vector3 _zeroPosition;
77 private Vector3 _velocity;
78 private Vector3 _target_velocity;
79 private Vector3 _acceleration;
80 private Vector3 m_rotationalVelocity;
81 private Vector3 m_size;
82 private Vector3 m_collideNormal;
83 private Quaternion m_orientation;
84 private Quaternion m_orientation2D;
85 private float m_mass = 80f;
86 public float m_density = 60f;
87 private bool m_pidControllerActive = true;
88
89 const float basePID_D = 0.55f; // scaled for unit mass unit time (2200 /(50*80))
90 const float basePID_P = 0.225f; // scaled for unit mass unit time (900 /(50*80))
91 public float PID_D;
92 public float PID_P;
93
94 private float timeStep;
95 private float invtimeStep;
96
97 private float m_feetOffset = 0;
98 private float feetOff = 0;
99 private float boneOff = 0;
100 private float AvaAvaSizeXsq = 0.3f;
101 private float AvaAvaSizeYsq = 0.2f;
102
103 public float walkDivisor = 1.3f;
104 public float runDivisor = 0.8f;
105 private bool flying = false;
106 private bool m_iscolliding = false;
107 private bool m_iscollidingGround = false;
108 private bool m_iscollidingObj = false;
109 private bool m_alwaysRun = false;
110
111 private bool _zeroFlag = false;
112
113
114 private uint m_localID = 0;
115 public bool m_returnCollisions = false;
116 // taints and their non-tainted counterparts
117 public bool m_isPhysical = false; // the current physical status
118 public float MinimumGroundFlightOffset = 3f;
119
120 private float m_buoyancy = 0f;
121
122 private bool m_freemove = false;
123 // private CollisionLocker ode;
124
125// private string m_name = String.Empty;
126 // other filter control
127 int m_colliderfilter = 0;
128 int m_colliderGroundfilter = 0;
129 int m_colliderObjectfilter = 0;
130
131 // Default we're a Character
132 private CollisionCategories m_collisionCategories = (CollisionCategories.Character);
133
134 // Default, Collide with Other Geometries, spaces, bodies and characters.
135 private CollisionCategories m_collisionFlags = (CollisionCategories.Character
136 | CollisionCategories.Geom
137 | CollisionCategories.VolumeDtc
138 );
139 // we do land collisions not ode | CollisionCategories.Land);
140 public IntPtr Body = IntPtr.Zero;
141 private ODEScene _parent_scene;
142 private IntPtr capsule = IntPtr.Zero;
143 public IntPtr collider = IntPtr.Zero;
144
145 public IntPtr Amotor = IntPtr.Zero;
146
147 public d.Mass ShellMass;
148
149 public int m_eventsubscription = 0;
150 private int m_cureventsubscription = 0;
151 private CollisionEventUpdate CollisionEventsThisFrame = null;
152 private bool SentEmptyCollisionsEvent;
153
154 // unique UUID of this character object
155 public UUID m_uuid;
156 public bool bad = false;
157
158 float mu;
159
160 // HoverHeight control
161 private float m_PIDHoverHeight;
162 private float m_PIDHoverTau;
163 private bool m_useHoverPID;
164 private PIDHoverType m_PIDHoverType;
165 private float m_targetHoverHeight;
166
167
168 public OdeCharacter(uint localID, String avName, ODEScene parent_scene, Vector3 pos, Vector3 pSize, float pfeetOffset, float density, float walk_divisor, float rundivisor)
169 {
170 m_uuid = UUID.Random();
171 m_localID = localID;
172
173 timeStep = parent_scene.ODE_STEPSIZE;
174 invtimeStep = 1 / timeStep;
175
176 if (pos.IsFinite())
177 {
178 if (pos.Z > 99999f)
179 {
180 pos.Z = parent_scene.GetTerrainHeightAtXY(127, 127) + 5;
181 }
182 if (pos.Z < -100f) // shouldn't this be 0 ?
183 {
184 pos.Z = parent_scene.GetTerrainHeightAtXY(127, 127) + 5;
185 }
186 _position = pos;
187 }
188 else
189 {
190 _position = new Vector3(((float)_parent_scene.WorldExtents.X * 0.5f), ((float)_parent_scene.WorldExtents.Y * 0.5f), parent_scene.GetTerrainHeightAtXY(128f, 128f) + 10f);
191 m_log.Warn("[PHYSICS]: Got NaN Position on Character Create");
192 }
193
194 _parent_scene = parent_scene;
195
196
197 m_size.X = pSize.X;
198 m_size.Y = pSize.Y;
199 m_size.Z = pSize.Z;
200
201 if(m_size.X <0.01f)
202 m_size.X = 0.01f;
203 if(m_size.Y <0.01f)
204 m_size.Y = 0.01f;
205 if(m_size.Z <0.01f)
206 m_size.Z = 0.01f;
207
208 m_feetOffset = pfeetOffset;
209 m_orientation = Quaternion.Identity;
210 m_orientation2D = Quaternion.Identity;
211 m_density = density;
212
213 // force lower density for testing
214 m_density = 3.0f;
215
216 mu = parent_scene.AvatarFriction;
217
218 walkDivisor = walk_divisor;
219 runDivisor = rundivisor;
220
221 m_mass = m_density * m_size.X * m_size.Y * m_size.Z; ; // sure we have a default
222
223 PID_D = basePID_D * m_mass * invtimeStep;
224 PID_P = basePID_P * m_mass * invtimeStep;
225
226 m_isPhysical = false; // current status: no ODE information exists
227
228 Name = avName;
229
230 AddChange(changes.Add, null);
231 }
232
233 public override int PhysicsActorType
234 {
235 get { return (int)ActorTypes.Agent; }
236 set { return; }
237 }
238
239 public override void getContactData(ref ContactData cdata)
240 {
241 cdata.mu = mu;
242 cdata.bounce = 0;
243 cdata.softcolide = false;
244 }
245
246 public override bool Building { get; set; }
247
248 /// <summary>
249 /// If this is set, the avatar will move faster
250 /// </summary>
251 public override bool SetAlwaysRun
252 {
253 get { return m_alwaysRun; }
254 set { m_alwaysRun = value; }
255 }
256
257 public override uint LocalID
258 {
259 get { return m_localID; }
260 set { m_localID = value; }
261 }
262
263 public override PhysicsActor ParentActor
264 {
265 get { return (PhysicsActor)this; }
266 }
267
268 public override bool Grabbed
269 {
270 set { return; }
271 }
272
273 public override bool Selected
274 {
275 set { return; }
276 }
277
278 public override float Buoyancy
279 {
280 get { return m_buoyancy; }
281 set { m_buoyancy = value; }
282 }
283
284 public override bool FloatOnWater
285 {
286 set { return; }
287 }
288
289 public override bool IsPhysical
290 {
291 get { return m_isPhysical; }
292 set { return; }
293 }
294
295 public override bool ThrottleUpdates
296 {
297 get { return false; }
298 set { return; }
299 }
300
301 public override bool Flying
302 {
303 get { return flying; }
304 set
305 {
306 flying = value;
307// m_log.DebugFormat("[PHYSICS]: Set OdeCharacter Flying to {0}", flying);
308 }
309 }
310
311 /// <summary>
312 /// Returns if the avatar is colliding in general.
313 /// This includes the ground and objects and avatar.
314 /// </summary>
315 public override bool IsColliding
316 {
317 get { return (m_iscolliding || m_iscollidingGround); }
318 set
319 {
320 if (value)
321 {
322 m_colliderfilter += 3;
323 if (m_colliderfilter > 3)
324 m_colliderfilter = 3;
325 }
326 else
327 {
328 m_colliderfilter--;
329 if (m_colliderfilter < 0)
330 m_colliderfilter = 0;
331 }
332
333 if (m_colliderfilter == 0)
334 m_iscolliding = false;
335 else
336 {
337 m_pidControllerActive = true;
338 m_iscolliding = true;
339 m_freemove = false;
340 }
341 }
342 }
343
344 /// <summary>
345 /// Returns if an avatar is colliding with the ground
346 /// </summary>
347 public override bool CollidingGround
348 {
349 get { return m_iscollidingGround; }
350 set
351 {
352/* we now control this
353 if (value)
354 {
355 m_colliderGroundfilter += 2;
356 if (m_colliderGroundfilter > 2)
357 m_colliderGroundfilter = 2;
358 }
359 else
360 {
361 m_colliderGroundfilter--;
362 if (m_colliderGroundfilter < 0)
363 m_colliderGroundfilter = 0;
364 }
365
366 if (m_colliderGroundfilter == 0)
367 m_iscollidingGround = false;
368 else
369 m_iscollidingGround = true;
370 */
371 }
372
373 }
374
375 /// <summary>
376 /// Returns if the avatar is colliding with an object
377 /// </summary>
378 public override bool CollidingObj
379 {
380 get { return m_iscollidingObj; }
381 set
382 {
383 // Ubit filter this also
384 if (value)
385 {
386 m_colliderObjectfilter += 2;
387 if (m_colliderObjectfilter > 2)
388 m_colliderObjectfilter = 2;
389 }
390 else
391 {
392 m_colliderObjectfilter--;
393 if (m_colliderObjectfilter < 0)
394 m_colliderObjectfilter = 0;
395 }
396
397 if (m_colliderObjectfilter == 0)
398 m_iscollidingObj = false;
399 else
400 m_iscollidingObj = true;
401
402// m_iscollidingObj = value;
403
404 if (m_iscollidingObj)
405 m_pidControllerActive = false;
406 else
407 m_pidControllerActive = true;
408 }
409 }
410
411 /// <summary>
412 /// turn the PID controller on or off.
413 /// The PID Controller will turn on all by itself in many situations
414 /// </summary>
415 /// <param name="status"></param>
416 public void SetPidStatus(bool status)
417 {
418 m_pidControllerActive = status;
419 }
420
421 public override bool Stopped
422 {
423 get { return _zeroFlag; }
424 }
425
426 /// <summary>
427 /// This 'puts' an avatar somewhere in the physics space.
428 /// Not really a good choice unless you 'know' it's a good
429 /// spot otherwise you're likely to orbit the avatar.
430 /// </summary>
431 public override Vector3 Position
432 {
433 get { return _position; }
434 set
435 {
436 if (value.IsFinite())
437 {
438 if (value.Z > 9999999f)
439 {
440 value.Z = _parent_scene.GetTerrainHeightAtXY(127, 127) + 5;
441 }
442 if (value.Z < -100f)
443 {
444 value.Z = _parent_scene.GetTerrainHeightAtXY(127, 127) + 5;
445 }
446 AddChange(changes.Position, value);
447 }
448 else
449 {
450 m_log.Warn("[PHYSICS]: Got a NaN Position from Scene on a Character");
451 }
452 }
453 }
454
455 public override Vector3 RotationalVelocity
456 {
457 get { return m_rotationalVelocity; }
458 set { m_rotationalVelocity = value; }
459 }
460
461 /// <summary>
462 /// This property sets the height of the avatar only. We use the height to make sure the avatar stands up straight
463 /// and use it to offset landings properly
464 /// </summary>
465 public override Vector3 Size
466 {
467 get
468 {
469 return m_size;
470 }
471 set
472 {
473 if (value.IsFinite())
474 {
475 if(value.X <0.01f)
476 value.X = 0.01f;
477 if(value.Y <0.01f)
478 value.Y = 0.01f;
479 if(value.Z <0.01f)
480 value.Z = 0.01f;
481
482 AddChange(changes.Size, value);
483 }
484 else
485 {
486 m_log.Warn("[PHYSICS]: Got a NaN Size from Scene on a Character");
487 }
488 }
489 }
490
491 public override void setAvatarSize(Vector3 size, float feetOffset)
492 {
493 if (size.IsFinite())
494 {
495 if (size.X < 0.01f)
496 size.X = 0.01f;
497 if (size.Y < 0.01f)
498 size.Y = 0.01f;
499 if (size.Z < 0.01f)
500 size.Z = 0.01f;
501
502 strAvatarSize st = new strAvatarSize();
503 st.size = size;
504 st.offset = feetOffset;
505 AddChange(changes.AvatarSize, st);
506 }
507 else
508 {
509 m_log.Warn("[PHYSICS]: Got a NaN AvatarSize from Scene on a Character");
510 }
511
512 }
513 /// <summary>
514 /// This creates the Avatar's physical Surrogate at the position supplied
515 /// </summary>
516 /// <param name="npositionX"></param>
517 /// <param name="npositionY"></param>
518 /// <param name="npositionZ"></param>
519
520 //
521 /// <summary>
522 /// Uses the capped cyllinder volume formula to calculate the avatar's mass.
523 /// This may be used in calculations in the scene/scenepresence
524 /// </summary>
525 public override float Mass
526 {
527 get
528 {
529 return m_mass;
530 }
531 }
532 public override void link(PhysicsActor obj)
533 {
534
535 }
536
537 public override void delink()
538 {
539
540 }
541
542 public override void LockAngularMotion(byte axislocks)
543 {
544
545 }
546
547
548 public override Vector3 Force
549 {
550 get { return _target_velocity; }
551 set { return; }
552 }
553
554 public override int VehicleType
555 {
556 get { return 0; }
557 set { return; }
558 }
559
560 public override void VehicleFloatParam(int param, float value)
561 {
562
563 }
564
565 public override void VehicleVectorParam(int param, Vector3 value)
566 {
567
568 }
569
570 public override void VehicleRotationParam(int param, Quaternion rotation)
571 {
572
573 }
574
575 public override void VehicleFlags(int param, bool remove)
576 {
577
578 }
579
580 public override void SetVolumeDetect(int param)
581 {
582
583 }
584
585 public override Vector3 CenterOfMass
586 {
587 get
588 {
589 Vector3 pos = _position;
590 return pos;
591 }
592 }
593
594 public override Vector3 GeometricCenter
595 {
596 get
597 {
598 Vector3 pos = _position;
599 return pos;
600 }
601 }
602
603 public override PrimitiveBaseShape Shape
604 {
605 set { return; }
606 }
607
608 public override Vector3 Velocity
609 {
610 get
611 {
612 return _velocity;
613 }
614 set
615 {
616 if (value.IsFinite())
617 {
618 AddChange(changes.Velocity, value);
619 }
620 else
621 {
622 m_log.Warn("[PHYSICS]: Got a NaN velocity from Scene in a Character");
623 }
624 }
625 }
626
627 public override Vector3 Torque
628 {
629 get { return Vector3.Zero; }
630 set { return; }
631 }
632
633 public override float CollisionScore
634 {
635 get { return 0f; }
636 set { }
637 }
638
639 public override bool Kinematic
640 {
641 get { return false; }
642 set { }
643 }
644
645 public override Quaternion Orientation
646 {
647 get { return m_orientation; }
648 set
649 {
650// fakeori = value;
651// givefakeori++;
652 value.Normalize();
653 AddChange(changes.Orientation, value);
654 }
655 }
656
657 public override Vector3 Acceleration
658 {
659 get { return _acceleration; }
660 set { }
661 }
662
663 public void SetAcceleration(Vector3 accel)
664 {
665 m_pidControllerActive = true;
666 _acceleration = accel;
667 }
668
669 /// <summary>
670 /// Adds the force supplied to the Target Velocity
671 /// The PID controller takes this target velocity and tries to make it a reality
672 /// </summary>
673 /// <param name="force"></param>
674 public override void AddForce(Vector3 force, bool pushforce)
675 {
676 if (force.IsFinite())
677 {
678 if (pushforce)
679 {
680 AddChange(changes.Force, force * m_density / (_parent_scene.ODE_STEPSIZE * 28f));
681 }
682 else
683 {
684 AddChange(changes.Velocity, force);
685 }
686 }
687 else
688 {
689 m_log.Warn("[PHYSICS]: Got a NaN force applied to a Character");
690 }
691 //m_lastUpdateSent = false;
692 }
693
694 public override void AddAngularForce(Vector3 force, bool pushforce)
695 {
696
697 }
698
699 public override void SetMomentum(Vector3 momentum)
700 {
701 if (momentum.IsFinite())
702 AddChange(changes.Momentum, momentum);
703 }
704
705
706 private void AvatarGeomAndBodyCreation(float npositionX, float npositionY, float npositionZ)
707 {
708 // sizes one day should came from visual parameters
709 float sx = m_size.X;
710 float sy = m_size.Y;
711 float sz = m_size.Z;
712
713 float bot = -sz * 0.5f + m_feetOffset;
714 boneOff = bot + 0.3f;
715
716 float feetsz = sz * 0.45f;
717 if (feetsz > 0.6f)
718 feetsz = 0.6f;
719
720 feetOff = bot + feetsz;
721
722 AvaAvaSizeXsq = 0.4f * sx;
723 AvaAvaSizeXsq *= AvaAvaSizeXsq;
724 AvaAvaSizeYsq = 0.5f * sy;
725 AvaAvaSizeYsq *= AvaAvaSizeYsq;
726
727 _parent_scene.waitForSpaceUnlock(_parent_scene.CharsSpace);
728
729 collider = d.HashSpaceCreate(_parent_scene.CharsSpace);
730 d.HashSpaceSetLevels(collider, -4, 3);
731 d.SpaceSetSublevel(collider, 3);
732 d.SpaceSetCleanup(collider, false);
733 d.GeomSetCategoryBits(collider, (uint)m_collisionCategories);
734 d.GeomSetCollideBits(collider, (uint)m_collisionFlags);
735
736 float r = m_size.X;
737 if (m_size.Y > r)
738 r = m_size.Y;
739 float l = m_size.Z - r;
740 r *= 0.5f;
741
742 capsule = d.CreateCapsule(collider, r, l);
743
744 m_mass = m_density * m_size.X * m_size.Y * m_size.Z; // update mass
745
746 d.MassSetBoxTotal(out ShellMass, m_mass, m_size.X, m_size.Y, m_size.Z);
747
748 PID_D = basePID_D * m_mass / _parent_scene.ODE_STEPSIZE;
749 PID_P = basePID_P * m_mass / _parent_scene.ODE_STEPSIZE;
750
751 Body = d.BodyCreate(_parent_scene.world);
752
753 _zeroFlag = false;
754 m_pidControllerActive = true;
755 m_freemove = false;
756
757 _velocity = Vector3.Zero;
758
759 d.BodySetAutoDisableFlag(Body, false);
760 d.BodySetPosition(Body, npositionX, npositionY, npositionZ);
761
762 _position.X = npositionX;
763 _position.Y = npositionY;
764 _position.Z = npositionZ;
765
766 d.BodySetMass(Body, ref ShellMass);
767 d.GeomSetBody(capsule, Body);
768
769 // The purpose of the AMotor here is to keep the avatar's physical
770 // surrogate from rotating while moving
771 Amotor = d.JointCreateAMotor(_parent_scene.world, IntPtr.Zero);
772 d.JointAttach(Amotor, Body, IntPtr.Zero);
773
774 d.JointSetAMotorMode(Amotor, 0);
775 d.JointSetAMotorNumAxes(Amotor, 3);
776 d.JointSetAMotorAxis(Amotor, 0, 0, 1, 0, 0);
777 d.JointSetAMotorAxis(Amotor, 1, 0, 0, 1, 0);
778 d.JointSetAMotorAxis(Amotor, 2, 0, 0, 0, 1);
779
780 d.JointSetAMotorAngle(Amotor, 0, 0);
781 d.JointSetAMotorAngle(Amotor, 1, 0);
782 d.JointSetAMotorAngle(Amotor, 2, 0);
783
784 d.JointSetAMotorParam(Amotor, (int)dParam.StopCFM, 0f); // make it HARD
785 d.JointSetAMotorParam(Amotor, (int)dParam.StopCFM2, 0f);
786 d.JointSetAMotorParam(Amotor, (int)dParam.StopCFM3, 0f);
787 d.JointSetAMotorParam(Amotor, (int)dParam.StopERP, 0.8f);
788 d.JointSetAMotorParam(Amotor, (int)dParam.StopERP2, 0.8f);
789 d.JointSetAMotorParam(Amotor, (int)dParam.StopERP3, 0.8f);
790
791 // These lowstops and high stops are effectively (no wiggle room)
792 d.JointSetAMotorParam(Amotor, (int)dParam.LowStop, -1e-5f);
793 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop, 1e-5f);
794 d.JointSetAMotorParam(Amotor, (int)dParam.LoStop2, -1e-5f);
795 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop2, 1e-5f);
796 d.JointSetAMotorParam(Amotor, (int)dParam.LoStop3, -1e-5f);
797 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop3, 1e-5f);
798
799 d.JointSetAMotorParam(Amotor, (int)d.JointParam.Vel, 0);
800 d.JointSetAMotorParam(Amotor, (int)d.JointParam.Vel2, 0);
801 d.JointSetAMotorParam(Amotor, (int)d.JointParam.Vel3, 0);
802
803 d.JointSetAMotorParam(Amotor, (int)dParam.FMax, 5e8f);
804 d.JointSetAMotorParam(Amotor, (int)dParam.FMax2, 5e8f);
805 d.JointSetAMotorParam(Amotor, (int)dParam.FMax3, 5e8f);
806 }
807
808 /// <summary>
809 /// Destroys the avatar body and geom
810
811 private void AvatarGeomAndBodyDestroy()
812 {
813 // Kill the Amotor
814 if (Amotor != IntPtr.Zero)
815 {
816 d.JointDestroy(Amotor);
817 Amotor = IntPtr.Zero;
818 }
819
820 if (Body != IntPtr.Zero)
821 {
822 //kill the body
823 d.BodyDestroy(Body);
824 Body = IntPtr.Zero;
825 }
826
827 //kill the Geoms
828 if (capsule != IntPtr.Zero)
829 {
830 _parent_scene.actor_name_map.Remove(capsule);
831 _parent_scene.waitForSpaceUnlock(collider);
832 d.GeomDestroy(capsule);
833 capsule = IntPtr.Zero;
834 }
835
836 if (collider != IntPtr.Zero)
837 {
838 d.SpaceDestroy(collider);
839 collider = IntPtr.Zero;
840 }
841
842 }
843
844 //in place 2D rotation around Z assuming rot is normalised and is a rotation around Z
845 public void RotateXYonZ(ref float x, ref float y, ref Quaternion rot)
846 {
847 float sin = 2.0f * rot.Z * rot.W;
848 float cos = rot.W * rot.W - rot.Z * rot.Z;
849 float tx = x;
850
851 x = tx * cos - y * sin;
852 y = tx * sin + y * cos;
853 }
854 public void RotateXYonZ(ref float x, ref float y, ref float sin, ref float cos)
855 {
856 float tx = x;
857 x = tx * cos - y * sin;
858 y = tx * sin + y * cos;
859 }
860 public void invRotateXYonZ(ref float x, ref float y, ref float sin, ref float cos)
861 {
862 float tx = x;
863 x = tx * cos + y * sin;
864 y = -tx * sin + y * cos;
865 }
866
867 public void invRotateXYonZ(ref float x, ref float y, ref Quaternion rot)
868 {
869 float sin = - 2.0f * rot.Z * rot.W;
870 float cos = rot.W * rot.W - rot.Z * rot.Z;
871 float tx = x;
872
873 x = tx * cos - y * sin;
874 y = tx * sin + y * cos;
875 }
876
877 public bool Collide(IntPtr me, IntPtr other, bool reverse, ref d.ContactGeom contact,
878 ref d.ContactGeom altContact , ref bool useAltcontact, ref bool feetcollision)
879 {
880 feetcollision = false;
881 useAltcontact = false;
882
883 if (me == capsule)
884 {
885 Vector3 offset;
886
887 float h = contact.pos.Z - _position.Z;
888 offset.Z = h - feetOff;
889
890 offset.X = contact.pos.X - _position.X;
891 offset.Y = contact.pos.Y - _position.Y;
892
893 d.GeomClassID gtype = d.GeomGetClass(other);
894 if (gtype == d.GeomClassID.CapsuleClass)
895 {
896 Vector3 roff = offset * Quaternion.Inverse(m_orientation2D);
897 float r = roff.X *roff.X / AvaAvaSizeXsq;
898 r += (roff.Y * roff.Y) / AvaAvaSizeYsq;
899 if (r > 1.0f)
900 return false;
901
902 float dp = 1.0f -(float)Math.Sqrt((double)r);
903 if (dp > 0.05f)
904 dp = 0.05f;
905
906 contact.depth = dp;
907
908 if (offset.Z < 0)
909 {
910 feetcollision = true;
911 if (h < boneOff)
912 {
913 m_collideNormal.X = contact.normal.X;
914 m_collideNormal.Y = contact.normal.Y;
915 m_collideNormal.Z = contact.normal.Z;
916 IsColliding = true;
917 }
918 }
919 return true;
920 }
921/*
922 d.AABB aabb;
923 d.GeomGetAABB(other,out aabb);
924 float othertop = aabb.MaxZ - _position.Z;
925*/
926// if (offset.Z > 0 || othertop > -feetOff || contact.normal.Z > 0.35f)
927 if (offset.Z > 0 || contact.normal.Z > 0.35f)
928 {
929 if (offset.Z <= 0)
930 {
931 feetcollision = true;
932 if (h < boneOff)
933 {
934 m_collideNormal.X = contact.normal.X;
935 m_collideNormal.Y = contact.normal.Y;
936 m_collideNormal.Z = contact.normal.Z;
937 IsColliding = true;
938 }
939 }
940 return true;
941 }
942
943 altContact = contact;
944 useAltcontact = true;
945
946 offset.Z -= 0.2f;
947
948 offset.Normalize();
949
950 if (contact.depth > 0.1f)
951 contact.depth = 0.1f;
952
953 if (reverse)
954 {
955 altContact.normal.X = offset.X;
956 altContact.normal.Y = offset.Y;
957 altContact.normal.Z = offset.Z;
958 }
959 else
960 {
961 altContact.normal.X = -offset.X;
962 altContact.normal.Y = -offset.Y;
963 altContact.normal.Z = -offset.Z;
964 }
965
966 feetcollision = true;
967 if (h < boneOff)
968 {
969 m_collideNormal.X = contact.normal.X;
970 m_collideNormal.Y = contact.normal.Y;
971 m_collideNormal.Z = contact.normal.Z;
972 IsColliding = true;
973 }
974 return true;
975 }
976 return false;
977 }
978
979 /// <summary>
980 /// Called from Simulate
981 /// This is the avatar's movement control + PID Controller
982 /// </summary>
983 /// <param name="timeStep"></param>
984 public void Move(List<OdeCharacter> defects)
985 {
986 if (Body == IntPtr.Zero)
987 return;
988
989 d.Vector3 dtmp = d.BodyGetPosition(Body);
990 Vector3 localpos = new Vector3(dtmp.X, dtmp.Y, dtmp.Z);
991
992 // the Amotor still lets avatar rotation to drift during colisions
993 // so force it back to identity
994
995 d.Quaternion qtmp;
996 qtmp.W = m_orientation2D.W;
997 qtmp.X = m_orientation2D.X;
998 qtmp.Y = m_orientation2D.Y;
999 qtmp.Z = m_orientation2D.Z;
1000 d.BodySetQuaternion(Body, ref qtmp);
1001
1002 if (m_pidControllerActive == false)
1003 {
1004 _zeroPosition = localpos;
1005 }
1006
1007 if (!localpos.IsFinite())
1008 {
1009 m_log.Warn("[PHYSICS]: Avatar Position is non-finite!");
1010 defects.Add(this);
1011 // _parent_scene.RemoveCharacter(this);
1012
1013 // destroy avatar capsule and related ODE data
1014 AvatarGeomAndBodyDestroy();
1015 return;
1016 }
1017
1018 // check outbounds forcing to be in world
1019 bool fixbody = false;
1020 if (localpos.X < 0.0f)
1021 {
1022 fixbody = true;
1023 localpos.X = 0.1f;
1024 }
1025 else if (localpos.X > _parent_scene.WorldExtents.X - 0.1f)
1026 {
1027 fixbody = true;
1028 localpos.X = _parent_scene.WorldExtents.X - 0.1f;
1029 }
1030 if (localpos.Y < 0.0f)
1031 {
1032 fixbody = true;
1033 localpos.Y = 0.1f;
1034 }
1035 else if (localpos.Y > _parent_scene.WorldExtents.Y - 0.1)
1036 {
1037 fixbody = true;
1038 localpos.Y = _parent_scene.WorldExtents.Y - 0.1f;
1039 }
1040 if (fixbody)
1041 {
1042 m_freemove = false;
1043 d.BodySetPosition(Body, localpos.X, localpos.Y, localpos.Z);
1044 }
1045
1046 float breakfactor;
1047
1048 Vector3 vec = Vector3.Zero;
1049 dtmp = d.BodyGetLinearVel(Body);
1050 Vector3 vel = new Vector3(dtmp.X, dtmp.Y, dtmp.Z);
1051 float velLengthSquared = vel.LengthSquared();
1052
1053 Vector3 ctz = _target_velocity;
1054
1055 float movementdivisor = 1f;
1056 //Ubit change divisions into multiplications below
1057 if (!m_alwaysRun)
1058 movementdivisor = 1 / walkDivisor;
1059 else
1060 movementdivisor = 1 / runDivisor;
1061
1062 ctz.X *= movementdivisor;
1063 ctz.Y *= movementdivisor;
1064
1065 //******************************************
1066 // colide with land
1067
1068 d.AABB aabb;
1069// d.GeomGetAABB(feetbox, out aabb);
1070 d.GeomGetAABB(capsule, out aabb);
1071 float chrminZ = aabb.MinZ; // move up a bit
1072 Vector3 posch = localpos;
1073
1074 float ftmp;
1075
1076 if (flying)
1077 {
1078 ftmp = timeStep;
1079 posch.X += vel.X * ftmp;
1080 posch.Y += vel.Y * ftmp;
1081 }
1082
1083 float terrainheight = _parent_scene.GetTerrainHeightAtXY(posch.X, posch.Y);
1084 if (chrminZ < terrainheight)
1085 {
1086 if (ctz.Z < 0)
1087 ctz.Z = 0;
1088
1089 Vector3 n = _parent_scene.GetTerrainNormalAtXY(posch.X, posch.Y);
1090 float depth = terrainheight - chrminZ;
1091
1092 vec.Z = depth * PID_P * 50;
1093
1094 if (!flying)
1095 vec.Z += -vel.Z * PID_D;
1096
1097 if (depth < 0.2f)
1098 {
1099 m_colliderGroundfilter++;
1100 if (m_colliderGroundfilter > 2)
1101 {
1102 m_iscolliding = true;
1103 m_colliderfilter = 2;
1104
1105 if (m_colliderGroundfilter > 10)
1106 {
1107 m_colliderGroundfilter = 10;
1108 m_freemove = false;
1109 }
1110
1111 m_collideNormal.X = n.X;
1112 m_collideNormal.Y = n.Y;
1113 m_collideNormal.Z = n.Z;
1114
1115 m_iscollidingGround = true;
1116
1117
1118 ContactPoint contact = new ContactPoint();
1119 contact.PenetrationDepth = depth;
1120 contact.Position.X = localpos.X;
1121 contact.Position.Y = localpos.Y;
1122 contact.Position.Z = terrainheight;
1123 contact.SurfaceNormal.X = -n.X;
1124 contact.SurfaceNormal.Y = -n.Y;
1125 contact.SurfaceNormal.Z = -n.Z;
1126 contact.RelativeSpeed = -vel.Z;
1127 contact.CharacterFeet = true;
1128 AddCollisionEvent(0, contact);
1129
1130// vec.Z *= 0.5f;
1131 }
1132 }
1133
1134 else
1135 {
1136 m_colliderGroundfilter -= 5;
1137 if (m_colliderGroundfilter <= 0)
1138 {
1139 m_colliderGroundfilter = 0;
1140 m_iscollidingGround = false;
1141 }
1142 }
1143 }
1144 else
1145 {
1146 m_colliderGroundfilter -= 5;
1147 if (m_colliderGroundfilter <= 0)
1148 {
1149 m_colliderGroundfilter = 0;
1150 m_iscollidingGround = false;
1151 }
1152 }
1153
1154 bool hoverPIDActive = false;
1155
1156 if (m_useHoverPID && m_PIDHoverTau != 0 && m_PIDHoverHeight != 0)
1157 {
1158 hoverPIDActive = true;
1159
1160 switch (m_PIDHoverType)
1161 {
1162 case PIDHoverType.Ground:
1163 m_targetHoverHeight = terrainheight + m_PIDHoverHeight;
1164 break;
1165
1166 case PIDHoverType.GroundAndWater:
1167 float waterHeight = _parent_scene.GetWaterLevel();
1168 if (terrainheight > waterHeight)
1169 m_targetHoverHeight = terrainheight + m_PIDHoverHeight;
1170 else
1171 m_targetHoverHeight = waterHeight + m_PIDHoverHeight;
1172 break;
1173 } // end switch (m_PIDHoverType)
1174
1175 // don't go underground
1176 if (m_targetHoverHeight > terrainheight + 0.5f * (aabb.MaxZ - aabb.MinZ))
1177 {
1178 float fz = (m_targetHoverHeight - localpos.Z);
1179
1180 // if error is zero, use position control; otherwise, velocity control
1181 if (Math.Abs(fz) < 0.01f)
1182 {
1183 ctz.Z = 0;
1184 }
1185 else
1186 {
1187 _zeroFlag = false;
1188 fz /= m_PIDHoverTau;
1189
1190 float tmp = Math.Abs(fz);
1191 if (tmp > 50)
1192 fz = 50 * Math.Sign(fz);
1193 else if (tmp < 0.1)
1194 fz = 0.1f * Math.Sign(fz);
1195
1196 ctz.Z = fz;
1197 }
1198 }
1199 }
1200
1201 //******************************************
1202 if (!m_iscolliding)
1203 m_collideNormal.Z = 0;
1204
1205 bool tviszero = (ctz.X == 0.0f && ctz.Y == 0.0f && ctz.Z == 0.0f);
1206
1207 if (!tviszero)
1208 {
1209 m_freemove = false;
1210
1211 // movement relative to surface if moving on it
1212 // dont disturbe vertical movement, ie jumps
1213 if (m_iscolliding && !flying && ctz.Z == 0 && m_collideNormal.Z > 0.2f && m_collideNormal.Z < 0.94f)
1214 {
1215 float p = ctz.X * m_collideNormal.X + ctz.Y * m_collideNormal.Y;
1216 ctz.X *= (float)Math.Sqrt(1 - m_collideNormal.X * m_collideNormal.X);
1217 ctz.Y *= (float)Math.Sqrt(1 - m_collideNormal.Y * m_collideNormal.Y);
1218 ctz.Z -= p;
1219 if (ctz.Z < 0)
1220 ctz.Z *= 2;
1221
1222 }
1223
1224 }
1225
1226 if (!m_freemove)
1227 {
1228
1229 // if velocity is zero, use position control; otherwise, velocity control
1230 if (tviszero && m_iscolliding && !flying)
1231 {
1232 // keep track of where we stopped. No more slippin' & slidin'
1233 if (!_zeroFlag)
1234 {
1235 _zeroFlag = true;
1236 _zeroPosition = localpos;
1237 }
1238 if (m_pidControllerActive)
1239 {
1240 // We only want to deactivate the PID Controller if we think we want to have our surrogate
1241 // react to the physics scene by moving it's position.
1242 // Avatar to Avatar collisions
1243 // Prim to avatar collisions
1244
1245 vec.X = -vel.X * PID_D * 2f + (_zeroPosition.X - localpos.X) * (PID_P * 5);
1246 vec.Y = -vel.Y * PID_D * 2f + (_zeroPosition.Y - localpos.Y) * (PID_P * 5);
1247 if(vel.Z > 0)
1248 vec.Z += -vel.Z * PID_D + (_zeroPosition.Z - localpos.Z) * PID_P;
1249 else
1250 vec.Z += (-vel.Z * PID_D + (_zeroPosition.Z - localpos.Z) * PID_P) * 0.2f;
1251/*
1252 if (flying)
1253 {
1254 vec.Z += -vel.Z * PID_D + (_zeroPosition.Z - localpos.Z) * PID_P;
1255 }
1256*/
1257 }
1258 //PidStatus = true;
1259 }
1260 else
1261 {
1262 m_pidControllerActive = true;
1263 _zeroFlag = false;
1264
1265 if (m_iscolliding)
1266 {
1267 if (!flying)
1268 {
1269 // we are on a surface
1270 if (ctz.Z > 0f)
1271 {
1272 // moving up or JUMPING
1273 vec.Z += (ctz.Z - vel.Z) * PID_D * 2f;
1274 vec.X += (ctz.X - vel.X) * (PID_D);
1275 vec.Y += (ctz.Y - vel.Y) * (PID_D);
1276 }
1277 else
1278 {
1279 // we are moving down on a surface
1280 if (ctz.Z == 0)
1281 {
1282 if (vel.Z > 0)
1283 vec.Z -= vel.Z * PID_D * 2f;
1284 vec.X += (ctz.X - vel.X) * (PID_D);
1285 vec.Y += (ctz.Y - vel.Y) * (PID_D);
1286 }
1287 // intencionally going down
1288 else
1289 {
1290 if (ctz.Z < vel.Z)
1291 vec.Z += (ctz.Z - vel.Z) * PID_D;
1292 else
1293 {
1294 }
1295
1296 if (Math.Abs(ctz.X) > Math.Abs(vel.X))
1297 vec.X += (ctz.X - vel.X) * (PID_D);
1298 if (Math.Abs(ctz.Y) > Math.Abs(vel.Y))
1299 vec.Y += (ctz.Y - vel.Y) * (PID_D);
1300 }
1301 }
1302
1303 // We're standing on something
1304 }
1305 else
1306 {
1307 // We're flying and colliding with something
1308 vec.X += (ctz.X - vel.X) * (PID_D * 0.0625f);
1309 vec.Y += (ctz.Y - vel.Y) * (PID_D * 0.0625f);
1310 vec.Z += (ctz.Z - vel.Z) * (PID_D * 0.0625f);
1311 }
1312 }
1313 else // ie not colliding
1314 {
1315 if (flying || hoverPIDActive) //(!m_iscolliding && flying)
1316 {
1317 // we're in mid air suspended
1318 vec.X += (ctz.X - vel.X) * (PID_D);
1319 vec.Y += (ctz.Y - vel.Y) * (PID_D);
1320 vec.Z += (ctz.Z - vel.Z) * (PID_D);
1321 }
1322
1323 else
1324 {
1325 // we're not colliding and we're not flying so that means we're falling!
1326 // m_iscolliding includes collisions with the ground.
1327
1328 // d.Vector3 pos = d.BodyGetPosition(Body);
1329 vec.X += (ctz.X - vel.X) * PID_D * 0.833f;
1330 vec.Y += (ctz.Y - vel.Y) * PID_D * 0.833f;
1331 // hack for breaking on fall
1332 if (ctz.Z == -9999f)
1333 vec.Z += -vel.Z * PID_D - _parent_scene.gravityz * m_mass;
1334 }
1335 }
1336 }
1337
1338 if (velLengthSquared > 2500.0f) // 50m/s apply breaks
1339 {
1340 breakfactor = 0.16f * m_mass;
1341 vec.X -= breakfactor * vel.X;
1342 vec.Y -= breakfactor * vel.Y;
1343 vec.Z -= breakfactor * vel.Z;
1344 }
1345 }
1346 else
1347 {
1348 breakfactor = m_mass;
1349 vec.X -= breakfactor * vel.X;
1350 vec.Y -= breakfactor * vel.Y;
1351 if (flying)
1352 vec.Z -= 0.5f * breakfactor * vel.Z;
1353 else
1354 vec.Z -= .16f* m_mass * vel.Z;
1355 }
1356
1357 if (flying || hoverPIDActive)
1358 {
1359 vec.Z -= _parent_scene.gravityz * m_mass;
1360
1361 if(!hoverPIDActive)
1362 {
1363 //Added for auto fly height. Kitto Flora
1364 float target_altitude = terrainheight + MinimumGroundFlightOffset;
1365
1366 if (localpos.Z < target_altitude)
1367 {
1368 vec.Z += (target_altitude - localpos.Z) * PID_P * 5.0f;
1369 }
1370 // end add Kitto Flora
1371 }
1372 }
1373
1374 if (vec.IsFinite())
1375 {
1376 if (vec.X != 0 || vec.Y !=0 || vec.Z !=0)
1377 d.BodyAddForce(Body, vec.X, vec.Y, vec.Z);
1378 }
1379 else
1380 {
1381 m_log.Warn("[PHYSICS]: Got a NaN force vector in Move()");
1382 m_log.Warn("[PHYSICS]: Avatar Position is non-finite!");
1383 defects.Add(this);
1384 // _parent_scene.RemoveCharacter(this);
1385 // destroy avatar capsule and related ODE data
1386 AvatarGeomAndBodyDestroy();
1387 return;
1388 }
1389
1390 // update our local ideia of position velocity and aceleration
1391 // _position = localpos;
1392 _position = localpos;
1393
1394 if (_zeroFlag)
1395 {
1396 _velocity = Vector3.Zero;
1397 _acceleration = Vector3.Zero;
1398 m_rotationalVelocity = Vector3.Zero;
1399 }
1400 else
1401 {
1402 Vector3 a =_velocity; // previus velocity
1403 SetSmooth(ref _velocity, ref vel, 2);
1404 a = (_velocity - a) * invtimeStep;
1405 SetSmooth(ref _acceleration, ref a, 2);
1406
1407 dtmp = d.BodyGetAngularVel(Body);
1408 m_rotationalVelocity.X = 0f;
1409 m_rotationalVelocity.Y = 0f;
1410 m_rotationalVelocity.Z = dtmp.Z;
1411 Math.Round(m_rotationalVelocity.Z,3);
1412 }
1413 }
1414
1415 public void round(ref Vector3 v, int digits)
1416 {
1417 v.X = (float)Math.Round(v.X, digits);
1418 v.Y = (float)Math.Round(v.Y, digits);
1419 v.Z = (float)Math.Round(v.Z, digits);
1420 }
1421
1422 public void SetSmooth(ref Vector3 dst, ref Vector3 value)
1423 {
1424 dst.X = 0.1f * dst.X + 0.9f * value.X;
1425 dst.Y = 0.1f * dst.Y + 0.9f * value.Y;
1426 dst.Z = 0.1f * dst.Z + 0.9f * value.Z;
1427 }
1428
1429 public void SetSmooth(ref Vector3 dst, ref Vector3 value, int rounddigits)
1430 {
1431 dst.X = 0.4f * dst.X + 0.6f * value.X;
1432 dst.X = (float)Math.Round(dst.X, rounddigits);
1433
1434 dst.Y = 0.4f * dst.Y + 0.6f * value.Y;
1435 dst.Y = (float)Math.Round(dst.Y, rounddigits);
1436
1437 dst.Z = 0.4f * dst.Z + 0.6f * value.Z;
1438 dst.Z = (float)Math.Round(dst.Z, rounddigits);
1439 }
1440
1441
1442 /// <summary>
1443 /// Updates the reported position and velocity.
1444 /// Used to copy variables from unmanaged space at heartbeat rate and also trigger scene updates acording
1445 /// also outbounds checking
1446 /// copy and outbounds now done in move(..) at ode rate
1447 ///
1448 /// </summary>
1449 public void UpdatePositionAndVelocity()
1450 {
1451 return;
1452
1453// if (Body == IntPtr.Zero)
1454// return;
1455
1456 }
1457
1458 /// <summary>
1459 /// Cleanup the things we use in the scene.
1460 /// </summary>
1461 public void Destroy()
1462 {
1463 AddChange(changes.Remove, null);
1464 }
1465
1466 public override void CrossingFailure()
1467 {
1468 }
1469
1470 public override Vector3 PIDTarget { set { return; } }
1471 public override bool PIDActive {get {return m_pidControllerActive;} set { return; } }
1472 public override float PIDTau { set { return; } }
1473
1474 public override float PIDHoverHeight
1475 {
1476 set
1477 {
1478 AddChange(changes.PIDHoverHeight,value);
1479 }
1480 }
1481 public override bool PIDHoverActive
1482 {
1483 get
1484 {
1485 return m_useHoverPID;
1486 }
1487 set
1488 {
1489 AddChange(changes.PIDHoverActive, value);
1490 }
1491 }
1492
1493 public override PIDHoverType PIDHoverType
1494 {
1495 set
1496 {
1497 AddChange(changes.PIDHoverType,value);
1498 }
1499 }
1500
1501 public override float PIDHoverTau
1502 {
1503 set
1504 {
1505 float tmp =0;
1506 if (value > 0)
1507 {
1508 float mint = (0.05f > timeStep ? 0.05f : timeStep);
1509 if (value < mint)
1510 tmp = mint;
1511 else
1512 tmp = value;
1513 }
1514 AddChange(changes.PIDHoverTau, tmp);
1515 }
1516 }
1517
1518 public override Quaternion APIDTarget { set { return; } }
1519
1520 public override bool APIDActive { set { return; } }
1521
1522 public override float APIDStrength { set { return; } }
1523
1524 public override float APIDDamping { set { return; } }
1525
1526
1527 public override void SubscribeEvents(int ms)
1528 {
1529 m_eventsubscription = ms;
1530 m_cureventsubscription = 0;
1531 if (CollisionEventsThisFrame == null)
1532 CollisionEventsThisFrame = new CollisionEventUpdate();
1533 SentEmptyCollisionsEvent = false;
1534 }
1535
1536 public override void UnSubscribeEvents()
1537 {
1538 if (CollisionEventsThisFrame != null)
1539 {
1540 lock (CollisionEventsThisFrame)
1541 {
1542 CollisionEventsThisFrame.Clear();
1543 CollisionEventsThisFrame = null;
1544 }
1545 }
1546 m_eventsubscription = 0;
1547 }
1548
1549 public override void AddCollisionEvent(uint CollidedWith, ContactPoint contact)
1550 {
1551 if (CollisionEventsThisFrame == null)
1552 CollisionEventsThisFrame = new CollisionEventUpdate();
1553 lock (CollisionEventsThisFrame)
1554 {
1555 CollisionEventsThisFrame.AddCollider(CollidedWith, contact);
1556 _parent_scene.AddCollisionEventReporting(this);
1557 }
1558 }
1559
1560 public void SendCollisions()
1561 {
1562 if (CollisionEventsThisFrame == null)
1563 return;
1564
1565 lock (CollisionEventsThisFrame)
1566 {
1567 if (m_cureventsubscription < m_eventsubscription)
1568 return;
1569
1570 m_cureventsubscription = 0;
1571
1572 int ncolisions = CollisionEventsThisFrame.m_objCollisionList.Count;
1573
1574 if (!SentEmptyCollisionsEvent || ncolisions > 0)
1575 {
1576 base.SendCollisionUpdate(CollisionEventsThisFrame);
1577
1578 if (ncolisions == 0)
1579 {
1580 SentEmptyCollisionsEvent = true;
1581 _parent_scene.RemoveCollisionEventReporting(this);
1582 }
1583 else
1584 {
1585 SentEmptyCollisionsEvent = false;
1586 CollisionEventsThisFrame.Clear();
1587 }
1588 }
1589 }
1590 }
1591
1592 internal void AddCollisionFrameTime(int t)
1593 {
1594 // protect it from overflow crashing
1595 if (m_cureventsubscription < 50000)
1596 m_cureventsubscription += t;
1597 }
1598
1599 public override bool SubscribedEvents()
1600 {
1601 if (m_eventsubscription > 0)
1602 return true;
1603 return false;
1604 }
1605
1606 private void changePhysicsStatus(bool NewStatus)
1607 {
1608 if (NewStatus != m_isPhysical)
1609 {
1610 if (NewStatus)
1611 {
1612 AvatarGeomAndBodyDestroy();
1613
1614 AvatarGeomAndBodyCreation(_position.X, _position.Y, _position.Z);
1615
1616 _parent_scene.actor_name_map[collider] = (PhysicsActor)this;
1617 _parent_scene.actor_name_map[capsule] = (PhysicsActor)this;
1618 _parent_scene.AddCharacter(this);
1619 }
1620 else
1621 {
1622 _parent_scene.RemoveCollisionEventReporting(this);
1623 _parent_scene.RemoveCharacter(this);
1624 // destroy avatar capsule and related ODE data
1625 AvatarGeomAndBodyDestroy();
1626 }
1627 m_freemove = false;
1628 m_isPhysical = NewStatus;
1629 }
1630 }
1631
1632 private void changeAdd()
1633 {
1634 changePhysicsStatus(true);
1635 }
1636
1637 private void changeRemove()
1638 {
1639 changePhysicsStatus(false);
1640 }
1641
1642 private void changeShape(PrimitiveBaseShape arg)
1643 {
1644 }
1645
1646 private void changeAvatarSize(strAvatarSize st)
1647 {
1648 m_feetOffset = st.offset;
1649 changeSize(st.size);
1650 }
1651
1652 private void changeSize(Vector3 pSize)
1653 {
1654 if (pSize.IsFinite())
1655 {
1656 // for now only look to Z changes since viewers also don't change X and Y
1657 if (pSize.Z != m_size.Z)
1658 {
1659 AvatarGeomAndBodyDestroy();
1660
1661
1662 float oldsz = m_size.Z;
1663 m_size = pSize;
1664
1665
1666 AvatarGeomAndBodyCreation(_position.X, _position.Y,
1667 _position.Z + (m_size.Z - oldsz) * 0.5f);
1668
1669 Velocity = Vector3.Zero;
1670
1671
1672 _parent_scene.actor_name_map[collider] = (PhysicsActor)this;
1673 _parent_scene.actor_name_map[capsule] = (PhysicsActor)this;
1674 }
1675 m_freemove = false;
1676 m_pidControllerActive = true;
1677 }
1678 else
1679 {
1680 m_log.Warn("[PHYSICS]: Got a NaN Size from Scene on a Character");
1681 }
1682 }
1683
1684 private void changePosition( Vector3 newPos)
1685 {
1686 if (Body != IntPtr.Zero)
1687 d.BodySetPosition(Body, newPos.X, newPos.Y, newPos.Z);
1688 _position = newPos;
1689 m_freemove = false;
1690 m_pidControllerActive = true;
1691 }
1692
1693 private void changeOrientation(Quaternion newOri)
1694 {
1695 if (m_orientation != newOri)
1696 {
1697 m_orientation = newOri; // keep a copy for core use
1698 // but only use rotations around Z
1699
1700 m_orientation2D.W = newOri.W;
1701 m_orientation2D.Z = newOri.Z;
1702
1703 float t = m_orientation2D.W * m_orientation2D.W + m_orientation2D.Z * m_orientation2D.Z;
1704 if (t > 0)
1705 {
1706 t = 1.0f / (float)Math.Sqrt(t);
1707 m_orientation2D.W *= t;
1708 m_orientation2D.Z *= t;
1709 }
1710 else
1711 {
1712 m_orientation2D.W = 1.0f;
1713 m_orientation2D.Z = 0f;
1714 }
1715 m_orientation2D.Y = 0f;
1716 m_orientation2D.X = 0f;
1717
1718 d.Quaternion myrot = new d.Quaternion();
1719 myrot.X = m_orientation2D.X;
1720 myrot.Y = m_orientation2D.Y;
1721 myrot.Z = m_orientation2D.Z;
1722 myrot.W = m_orientation2D.W;
1723 d.BodySetQuaternion(Body, ref myrot);
1724 }
1725 }
1726
1727 private void changeVelocity(Vector3 newVel)
1728 {
1729 m_pidControllerActive = true;
1730 m_freemove = false;
1731 _target_velocity = newVel;
1732 }
1733
1734 private void changeSetTorque(Vector3 newTorque)
1735 {
1736 }
1737
1738 private void changeAddForce(Vector3 newForce)
1739 {
1740 }
1741
1742 private void changeAddAngularForce(Vector3 arg)
1743 {
1744 }
1745
1746 private void changeAngularLock(byte arg)
1747 {
1748 }
1749
1750 private void changeFloatOnWater(bool arg)
1751 {
1752 }
1753
1754 private void changeVolumedetetion(bool arg)
1755 {
1756 }
1757
1758 private void changeSelectedStatus(bool arg)
1759 {
1760 }
1761
1762 private void changeDisable(bool arg)
1763 {
1764 }
1765
1766 private void changeBuilding(bool arg)
1767 {
1768 }
1769
1770 private void setFreeMove()
1771 {
1772 m_pidControllerActive = true;
1773 _zeroFlag = false;
1774 _target_velocity = Vector3.Zero;
1775 m_freemove = true;
1776 m_colliderfilter = -1;
1777 m_colliderObjectfilter = -1;
1778 m_colliderGroundfilter = -1;
1779
1780 m_iscolliding = false;
1781 m_iscollidingGround = false;
1782 m_iscollidingObj = false;
1783
1784 CollisionEventsThisFrame.Clear();
1785 }
1786
1787 private void changeForce(Vector3 newForce)
1788 {
1789 setFreeMove();
1790
1791 if (Body != IntPtr.Zero)
1792 {
1793 if (newForce.X != 0f || newForce.Y != 0f || newForce.Z != 0)
1794 d.BodyAddForce(Body, newForce.X, newForce.Y, newForce.Z);
1795 }
1796 }
1797
1798 // for now momentum is actually velocity
1799 private void changeMomentum(Vector3 newmomentum)
1800 {
1801 _velocity = newmomentum;
1802 setFreeMove();
1803
1804 if (Body != IntPtr.Zero)
1805 d.BodySetLinearVel(Body, newmomentum.X, newmomentum.Y, newmomentum.Z);
1806 }
1807
1808 private void changePIDHoverHeight(float val)
1809 {
1810 m_PIDHoverHeight = val;
1811 if (val == 0)
1812 m_useHoverPID = false;
1813 }
1814
1815 private void changePIDHoverType(PIDHoverType type)
1816 {
1817 m_PIDHoverType = type;
1818 }
1819
1820 private void changePIDHoverTau(float tau)
1821 {
1822 m_PIDHoverTau = tau;
1823 }
1824
1825 private void changePIDHoverActive(bool active)
1826 {
1827 m_useHoverPID = active;
1828 }
1829
1830 private void donullchange()
1831 {
1832 }
1833
1834 public bool DoAChange(changes what, object arg)
1835 {
1836 if (collider == IntPtr.Zero && what != changes.Add && what != changes.Remove)
1837 {
1838 return false;
1839 }
1840
1841 // nasty switch
1842 switch (what)
1843 {
1844 case changes.Add:
1845 changeAdd();
1846 break;
1847 case changes.Remove:
1848 changeRemove();
1849 break;
1850
1851 case changes.Position:
1852 changePosition((Vector3)arg);
1853 break;
1854
1855 case changes.Orientation:
1856 changeOrientation((Quaternion)arg);
1857 break;
1858
1859 case changes.PosOffset:
1860 donullchange();
1861 break;
1862
1863 case changes.OriOffset:
1864 donullchange();
1865 break;
1866
1867 case changes.Velocity:
1868 changeVelocity((Vector3)arg);
1869 break;
1870
1871 // case changes.Acceleration:
1872 // changeacceleration((Vector3)arg);
1873 // break;
1874 // case changes.AngVelocity:
1875 // changeangvelocity((Vector3)arg);
1876 // break;
1877
1878 case changes.Force:
1879 changeForce((Vector3)arg);
1880 break;
1881
1882 case changes.Torque:
1883 changeSetTorque((Vector3)arg);
1884 break;
1885
1886 case changes.AddForce:
1887 changeAddForce((Vector3)arg);
1888 break;
1889
1890 case changes.AddAngForce:
1891 changeAddAngularForce((Vector3)arg);
1892 break;
1893
1894 case changes.AngLock:
1895 changeAngularLock((byte)arg);
1896 break;
1897
1898 case changes.Size:
1899 changeSize((Vector3)arg);
1900 break;
1901
1902 case changes.AvatarSize:
1903 changeAvatarSize((strAvatarSize)arg);
1904 break;
1905
1906 case changes.Momentum:
1907 changeMomentum((Vector3)arg);
1908 break;
1909
1910 case changes.PIDHoverHeight:
1911 changePIDHoverHeight((float)arg);
1912 break;
1913
1914 case changes.PIDHoverType:
1915 changePIDHoverType((PIDHoverType)arg);
1916 break;
1917
1918 case changes.PIDHoverTau:
1919 changePIDHoverTau((float)arg);
1920 break;
1921
1922 case changes.PIDHoverActive:
1923 changePIDHoverActive((bool)arg);
1924 break;
1925
1926/* not in use for now
1927 case changes.Shape:
1928 changeShape((PrimitiveBaseShape)arg);
1929 break;
1930
1931 case changes.CollidesWater:
1932 changeFloatOnWater((bool)arg);
1933 break;
1934
1935 case changes.VolumeDtc:
1936 changeVolumedetetion((bool)arg);
1937 break;
1938
1939 case changes.Physical:
1940 changePhysicsStatus((bool)arg);
1941 break;
1942
1943 case changes.Selected:
1944 changeSelectedStatus((bool)arg);
1945 break;
1946
1947 case changes.disabled:
1948 changeDisable((bool)arg);
1949 break;
1950
1951 case changes.building:
1952 changeBuilding((bool)arg);
1953 break;
1954*/
1955 case changes.Null:
1956 donullchange();
1957 break;
1958
1959 default:
1960 donullchange();
1961 break;
1962 }
1963 return false;
1964 }
1965
1966 public void AddChange(changes what, object arg)
1967 {
1968 _parent_scene.AddChange((PhysicsActor)this, what, arg);
1969 }
1970
1971 private struct strAvatarSize
1972 {
1973 public Vector3 size;
1974 public float offset;
1975 }
1976
1977 }
1978}
diff --git a/OpenSim/Region/PhysicsModules/ubOde/ODEDynamics.cs b/OpenSim/Region/PhysicsModules/ubOde/ODEDynamics.cs
new file mode 100644
index 0000000..c3b4dd8
--- /dev/null
+++ b/OpenSim/Region/PhysicsModules/ubOde/ODEDynamics.cs
@@ -0,0 +1,1096 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28/* Revised Aug, Sept 2009 by Kitto Flora. ODEDynamics.cs replaces
29 * ODEVehicleSettings.cs. It and ODEPrim.cs are re-organised:
30 * ODEPrim.cs contains methods dealing with Prim editing, Prim
31 * characteristics and Kinetic motion.
32 * ODEDynamics.cs contains methods dealing with Prim Physical motion
33 * (dynamics) and the associated settings. Old Linear and angular
34 * motors for dynamic motion have been replace with MoveLinear()
35 * and MoveAngular(); 'Physical' is used only to switch ODE dynamic
36 * simualtion on/off; VEHICAL_TYPE_NONE/VEHICAL_TYPE_<other> is to
37 * switch between 'VEHICLE' parameter use and general dynamics
38 * settings use.
39 */
40
41// Extensive change Ubit 2012
42
43using System;
44using System.Collections.Generic;
45using System.Reflection;
46using System.Runtime.InteropServices;
47using log4net;
48using OpenMetaverse;
49using OdeAPI;
50using OpenSim.Framework;
51using OpenSim.Region.PhysicsModules.SharedBase;
52
53namespace OpenSim.Region.PhysicsModule.ubOde
54{
55 public class ODEDynamics
56 {
57 public Vehicle Type
58 {
59 get { return m_type; }
60 }
61
62 private OdePrim rootPrim;
63 private ODEScene _pParentScene;
64
65 // Vehicle properties
66 // WARNING this are working copies for internel use
67 // their values may not be the corresponding parameter
68
69 private Quaternion m_referenceFrame = Quaternion.Identity; // Axis modifier
70 private Quaternion m_RollreferenceFrame = Quaternion.Identity; // what hell is this ?
71
72 private Vehicle m_type = Vehicle.TYPE_NONE; // If a 'VEHICLE', and what kind
73
74 private VehicleFlag m_flags = (VehicleFlag) 0; // Boolean settings:
75 // HOVER_TERRAIN_ONLY
76 // HOVER_GLOBAL_HEIGHT
77 // NO_DEFLECTION_UP
78 // HOVER_WATER_ONLY
79 // HOVER_UP_ONLY
80 // LIMIT_MOTOR_UP
81 // LIMIT_ROLL_ONLY
82 private Vector3 m_BlockingEndPoint = Vector3.Zero; // not sl
83
84 // Linear properties
85 private Vector3 m_linearMotorDirection = Vector3.Zero; // velocity requested by LSL, decayed by time
86 private Vector3 m_linearFrictionTimescale = new Vector3(1000, 1000, 1000);
87 private float m_linearMotorDecayTimescale = 120;
88 private float m_linearMotorTimescale = 1000;
89 private Vector3 m_linearMotorOffset = Vector3.Zero;
90
91 //Angular properties
92 private Vector3 m_angularMotorDirection = Vector3.Zero; // angular velocity requested by LSL motor
93 private float m_angularMotorTimescale = 1000; // motor angular velocity ramp up rate
94 private float m_angularMotorDecayTimescale = 120; // motor angular velocity decay rate
95 private Vector3 m_angularFrictionTimescale = new Vector3(1000, 1000, 1000); // body angular velocity decay rate
96
97 //Deflection properties
98 private float m_angularDeflectionEfficiency = 0;
99 private float m_angularDeflectionTimescale = 1000;
100 private float m_linearDeflectionEfficiency = 0;
101 private float m_linearDeflectionTimescale = 1000;
102
103 //Banking properties
104 private float m_bankingEfficiency = 0;
105 private float m_bankingMix = 0;
106 private float m_bankingTimescale = 1000;
107
108 //Hover and Buoyancy properties
109 private float m_VhoverHeight = 0f;
110 private float m_VhoverEfficiency = 0f;
111 private float m_VhoverTimescale = 1000f;
112 private float m_VehicleBuoyancy = 0f; //KF: m_VehicleBuoyancy is set by VEHICLE_BUOYANCY for a vehicle.
113 // Modifies gravity. Slider between -1 (double-gravity) and 1 (full anti-gravity)
114 // KF: So far I have found no good method to combine a script-requested .Z velocity and gravity.
115 // Therefore only m_VehicleBuoyancy=1 (0g) will use the script-requested .Z velocity.
116
117 //Attractor properties
118 private float m_verticalAttractionEfficiency = 1.0f; // damped
119 private float m_verticalAttractionTimescale = 1000f; // Timescale > 300 means no vert attractor.
120
121
122 // auxiliar
123 private float m_lmEfect = 0f; // current linear motor eficiency
124 private float m_lmDecay = 0f; // current linear decay
125
126 private float m_amEfect = 0; // current angular motor eficiency
127 private float m_amDecay = 0f; // current linear decay
128
129 private float m_ffactor = 1.0f;
130
131 private float m_timestep = 0.02f;
132 private float m_invtimestep = 50;
133
134
135 float m_ampwr;
136 float m_amdampX;
137 float m_amdampY;
138 float m_amdampZ;
139
140 float m_gravmod;
141
142 public float FrictionFactor
143 {
144 get
145 {
146 return m_ffactor;
147 }
148 }
149
150 public float GravMod
151 {
152 set
153 {
154 m_gravmod = value;
155 }
156 }
157
158
159 public ODEDynamics(OdePrim rootp)
160 {
161 rootPrim = rootp;
162 _pParentScene = rootPrim._parent_scene;
163 m_timestep = _pParentScene.ODE_STEPSIZE;
164 m_invtimestep = 1.0f / m_timestep;
165 m_gravmod = rootPrim.GravModifier;
166 }
167
168 public void DoSetVehicle(VehicleData vd)
169 {
170 m_type = vd.m_type;
171 m_flags = vd.m_flags;
172
173
174 // Linear properties
175 m_linearMotorDirection = vd.m_linearMotorDirection;
176
177 m_linearFrictionTimescale = vd.m_linearFrictionTimescale;
178 if (m_linearFrictionTimescale.X < m_timestep) m_linearFrictionTimescale.X = m_timestep;
179 if (m_linearFrictionTimescale.Y < m_timestep) m_linearFrictionTimescale.Y = m_timestep;
180 if (m_linearFrictionTimescale.Z < m_timestep) m_linearFrictionTimescale.Z = m_timestep;
181
182 m_linearMotorDecayTimescale = vd.m_linearMotorDecayTimescale;
183 if (m_linearMotorDecayTimescale < m_timestep) m_linearMotorDecayTimescale = m_timestep;
184 m_linearMotorDecayTimescale += 0.2f;
185 m_linearMotorDecayTimescale *= m_invtimestep;
186
187 m_linearMotorTimescale = vd.m_linearMotorTimescale;
188 if (m_linearMotorTimescale < m_timestep) m_linearMotorTimescale = m_timestep;
189
190 m_linearMotorOffset = vd.m_linearMotorOffset;
191
192 //Angular properties
193 m_angularMotorDirection = vd.m_angularMotorDirection;
194 m_angularMotorTimescale = vd.m_angularMotorTimescale;
195 if (m_angularMotorTimescale < m_timestep) m_angularMotorTimescale = m_timestep;
196
197 m_angularMotorDecayTimescale = vd.m_angularMotorDecayTimescale;
198 if (m_angularMotorDecayTimescale < m_timestep) m_angularMotorDecayTimescale = m_timestep;
199 m_angularMotorDecayTimescale *= m_invtimestep;
200
201 m_angularFrictionTimescale = vd.m_angularFrictionTimescale;
202 if (m_angularFrictionTimescale.X < m_timestep) m_angularFrictionTimescale.X = m_timestep;
203 if (m_angularFrictionTimescale.Y < m_timestep) m_angularFrictionTimescale.Y = m_timestep;
204 if (m_angularFrictionTimescale.Z < m_timestep) m_angularFrictionTimescale.Z = m_timestep;
205
206 //Deflection properties
207 m_angularDeflectionEfficiency = vd.m_angularDeflectionEfficiency;
208 m_angularDeflectionTimescale = vd.m_angularDeflectionTimescale;
209 if (m_angularDeflectionTimescale < m_timestep) m_angularDeflectionTimescale = m_timestep;
210
211 m_linearDeflectionEfficiency = vd.m_linearDeflectionEfficiency;
212 m_linearDeflectionTimescale = vd.m_linearDeflectionTimescale;
213 if (m_linearDeflectionTimescale < m_timestep) m_linearDeflectionTimescale = m_timestep;
214
215 //Banking properties
216 m_bankingEfficiency = vd.m_bankingEfficiency;
217 m_bankingMix = vd.m_bankingMix;
218 m_bankingTimescale = vd.m_bankingTimescale;
219 if (m_bankingTimescale < m_timestep) m_bankingTimescale = m_timestep;
220
221 //Hover and Buoyancy properties
222 m_VhoverHeight = vd.m_VhoverHeight;
223 m_VhoverEfficiency = vd.m_VhoverEfficiency;
224 m_VhoverTimescale = vd.m_VhoverTimescale;
225 if (m_VhoverTimescale < m_timestep) m_VhoverTimescale = m_timestep;
226
227 m_VehicleBuoyancy = vd.m_VehicleBuoyancy;
228
229 //Attractor properties
230 m_verticalAttractionEfficiency = vd.m_verticalAttractionEfficiency;
231 m_verticalAttractionTimescale = vd.m_verticalAttractionTimescale;
232 if (m_verticalAttractionTimescale < m_timestep) m_verticalAttractionTimescale = m_timestep;
233
234 // Axis
235 m_referenceFrame = vd.m_referenceFrame;
236
237 m_lmEfect = 0;
238 m_lmDecay = (1.0f - 1.0f / m_linearMotorDecayTimescale);
239 m_amEfect = 0;
240 m_ffactor = 1.0f;
241 }
242
243 internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue)
244 {
245 float len;
246
247 switch (pParam)
248 {
249 case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY:
250 if (pValue < 0f) pValue = 0f;
251 if (pValue > 1f) pValue = 1f;
252 m_angularDeflectionEfficiency = pValue;
253 break;
254 case Vehicle.ANGULAR_DEFLECTION_TIMESCALE:
255 if (pValue < m_timestep) pValue = m_timestep;
256 m_angularDeflectionTimescale = pValue;
257 break;
258 case Vehicle.ANGULAR_MOTOR_DECAY_TIMESCALE:
259 if (pValue < m_timestep) pValue = m_timestep;
260 else if (pValue > 120) pValue = 120;
261 m_angularMotorDecayTimescale = pValue * m_invtimestep;
262 m_amDecay = 1.0f - 1.0f / m_angularMotorDecayTimescale;
263 break;
264 case Vehicle.ANGULAR_MOTOR_TIMESCALE:
265 if (pValue < m_timestep) pValue = m_timestep;
266 m_angularMotorTimescale = pValue;
267 break;
268 case Vehicle.BANKING_EFFICIENCY:
269 if (pValue < -1f) pValue = -1f;
270 if (pValue > 1f) pValue = 1f;
271 m_bankingEfficiency = pValue;
272 break;
273 case Vehicle.BANKING_MIX:
274 if (pValue < 0f) pValue = 0f;
275 if (pValue > 1f) pValue = 1f;
276 m_bankingMix = pValue;
277 break;
278 case Vehicle.BANKING_TIMESCALE:
279 if (pValue < m_timestep) pValue = m_timestep;
280 m_bankingTimescale = pValue;
281 break;
282 case Vehicle.BUOYANCY:
283 if (pValue < -1f) pValue = -1f;
284 if (pValue > 1f) pValue = 1f;
285 m_VehicleBuoyancy = pValue;
286 break;
287 case Vehicle.HOVER_EFFICIENCY:
288 if (pValue < 0f) pValue = 0f;
289 if (pValue > 1f) pValue = 1f;
290 m_VhoverEfficiency = pValue;
291 break;
292 case Vehicle.HOVER_HEIGHT:
293 m_VhoverHeight = pValue;
294 break;
295 case Vehicle.HOVER_TIMESCALE:
296 if (pValue < m_timestep) pValue = m_timestep;
297 m_VhoverTimescale = pValue;
298 break;
299 case Vehicle.LINEAR_DEFLECTION_EFFICIENCY:
300 if (pValue < 0f) pValue = 0f;
301 if (pValue > 1f) pValue = 1f;
302 m_linearDeflectionEfficiency = pValue;
303 break;
304 case Vehicle.LINEAR_DEFLECTION_TIMESCALE:
305 if (pValue < m_timestep) pValue = m_timestep;
306 m_linearDeflectionTimescale = pValue;
307 break;
308 case Vehicle.LINEAR_MOTOR_DECAY_TIMESCALE:
309 if (pValue < m_timestep) pValue = m_timestep;
310 else if (pValue > 120) pValue = 120;
311 m_linearMotorDecayTimescale = (0.2f +pValue) * m_invtimestep;
312 m_lmDecay = (1.0f - 1.0f / m_linearMotorDecayTimescale);
313 break;
314 case Vehicle.LINEAR_MOTOR_TIMESCALE:
315 if (pValue < m_timestep) pValue = m_timestep;
316 m_linearMotorTimescale = pValue;
317 break;
318 case Vehicle.VERTICAL_ATTRACTION_EFFICIENCY:
319 if (pValue < 0f) pValue = 0f;
320 if (pValue > 1f) pValue = 1f;
321 m_verticalAttractionEfficiency = pValue;
322 break;
323 case Vehicle.VERTICAL_ATTRACTION_TIMESCALE:
324 if (pValue < m_timestep) pValue = m_timestep;
325 m_verticalAttractionTimescale = pValue;
326 break;
327
328 // These are vector properties but the engine lets you use a single float value to
329 // set all of the components to the same value
330 case Vehicle.ANGULAR_FRICTION_TIMESCALE:
331 if (pValue < m_timestep) pValue = m_timestep;
332 m_angularFrictionTimescale = new Vector3(pValue, pValue, pValue);
333 break;
334 case Vehicle.ANGULAR_MOTOR_DIRECTION:
335 m_angularMotorDirection = new Vector3(pValue, pValue, pValue);
336 len = m_angularMotorDirection.Length();
337 if (len > 12.566f)
338 m_angularMotorDirection *= (12.566f / len);
339
340 m_amEfect = 1.0f ; // turn it on
341 m_amDecay = 1.0f - 1.0f / m_angularMotorDecayTimescale;
342
343 if (rootPrim.Body != IntPtr.Zero && !d.BodyIsEnabled(rootPrim.Body)
344 && !rootPrim.m_isSelected && !rootPrim.m_disabled)
345 d.BodyEnable(rootPrim.Body);
346 break;
347 case Vehicle.LINEAR_FRICTION_TIMESCALE:
348 if (pValue < m_timestep) pValue = m_timestep;
349 m_linearFrictionTimescale = new Vector3(pValue, pValue, pValue);
350 break;
351 case Vehicle.LINEAR_MOTOR_DIRECTION:
352 m_linearMotorDirection = new Vector3(pValue, pValue, pValue);
353 len = m_linearMotorDirection.Length();
354 if (len > 100.0f)
355 m_linearMotorDirection *= (100.0f / len);
356
357 m_lmDecay = 1.0f - 1.0f / m_linearMotorDecayTimescale;
358 m_lmEfect = 1.0f; // turn it on
359
360 m_ffactor = 0.0f;
361 if (rootPrim.Body != IntPtr.Zero && !d.BodyIsEnabled(rootPrim.Body)
362 && !rootPrim.m_isSelected && !rootPrim.m_disabled)
363 d.BodyEnable(rootPrim.Body);
364 break;
365 case Vehicle.LINEAR_MOTOR_OFFSET:
366 m_linearMotorOffset = new Vector3(pValue, pValue, pValue);
367 len = m_linearMotorOffset.Length();
368 if (len > 100.0f)
369 m_linearMotorOffset *= (100.0f / len);
370 break;
371 }
372 }//end ProcessFloatVehicleParam
373
374 internal void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue)
375 {
376 float len;
377
378 switch (pParam)
379 {
380 case Vehicle.ANGULAR_FRICTION_TIMESCALE:
381 if (pValue.X < m_timestep) pValue.X = m_timestep;
382 if (pValue.Y < m_timestep) pValue.Y = m_timestep;
383 if (pValue.Z < m_timestep) pValue.Z = m_timestep;
384
385 m_angularFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z);
386 break;
387 case Vehicle.ANGULAR_MOTOR_DIRECTION:
388 m_angularMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z);
389 // Limit requested angular speed to 2 rps= 4 pi rads/sec
390 len = m_angularMotorDirection.Length();
391 if (len > 12.566f)
392 m_angularMotorDirection *= (12.566f / len);
393
394 m_amEfect = 1.0f; // turn it on
395 m_amDecay = 1.0f - 1.0f / m_angularMotorDecayTimescale;
396
397 if (rootPrim.Body != IntPtr.Zero && !d.BodyIsEnabled(rootPrim.Body)
398 && !rootPrim.m_isSelected && !rootPrim.m_disabled)
399 d.BodyEnable(rootPrim.Body);
400 break;
401 case Vehicle.LINEAR_FRICTION_TIMESCALE:
402 if (pValue.X < m_timestep) pValue.X = m_timestep;
403 if (pValue.Y < m_timestep) pValue.Y = m_timestep;
404 if (pValue.Z < m_timestep) pValue.Z = m_timestep;
405 m_linearFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z);
406 break;
407 case Vehicle.LINEAR_MOTOR_DIRECTION:
408 m_linearMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z);
409 len = m_linearMotorDirection.Length();
410 if (len > 100.0f)
411 m_linearMotorDirection *= (100.0f / len);
412
413 m_lmEfect = 1.0f; // turn it on
414 m_lmDecay = 1.0f - 1.0f / m_linearMotorDecayTimescale;
415
416 m_ffactor = 0.0f;
417 if (rootPrim.Body != IntPtr.Zero && !d.BodyIsEnabled(rootPrim.Body)
418 && !rootPrim.m_isSelected && !rootPrim.m_disabled)
419 d.BodyEnable(rootPrim.Body);
420 break;
421 case Vehicle.LINEAR_MOTOR_OFFSET:
422 m_linearMotorOffset = new Vector3(pValue.X, pValue.Y, pValue.Z);
423 len = m_linearMotorOffset.Length();
424 if (len > 100.0f)
425 m_linearMotorOffset *= (100.0f / len);
426 break;
427 case Vehicle.BLOCK_EXIT:
428 m_BlockingEndPoint = new Vector3(pValue.X, pValue.Y, pValue.Z);
429 break;
430 }
431 }//end ProcessVectorVehicleParam
432
433 internal void ProcessRotationVehicleParam(Vehicle pParam, Quaternion pValue)
434 {
435 switch (pParam)
436 {
437 case Vehicle.REFERENCE_FRAME:
438 // m_referenceFrame = Quaternion.Inverse(pValue);
439 m_referenceFrame = pValue;
440 break;
441 case Vehicle.ROLL_FRAME:
442 m_RollreferenceFrame = pValue;
443 break;
444 }
445 }//end ProcessRotationVehicleParam
446
447 internal void ProcessVehicleFlags(int pParam, bool remove)
448 {
449 if (remove)
450 {
451 m_flags &= ~((VehicleFlag)pParam);
452 }
453 else
454 {
455 m_flags |= (VehicleFlag)pParam;
456 }
457 }//end ProcessVehicleFlags
458
459 internal void ProcessTypeChange(Vehicle pType)
460 {
461 m_lmEfect = 0;
462
463 m_amEfect = 0;
464 m_ffactor = 1f;
465
466 m_linearMotorDirection = Vector3.Zero;
467 m_angularMotorDirection = Vector3.Zero;
468
469 m_BlockingEndPoint = Vector3.Zero;
470 m_RollreferenceFrame = Quaternion.Identity;
471 m_linearMotorOffset = Vector3.Zero;
472
473 m_referenceFrame = Quaternion.Identity;
474
475 // Set Defaults For Type
476 m_type = pType;
477 switch (pType)
478 {
479 case Vehicle.TYPE_NONE:
480 m_linearFrictionTimescale = new Vector3(1000, 1000, 1000);
481 m_angularFrictionTimescale = new Vector3(1000, 1000, 1000);
482 m_linearMotorTimescale = 1000;
483 m_linearMotorDecayTimescale = 120 * m_invtimestep;
484 m_angularMotorTimescale = 1000;
485 m_angularMotorDecayTimescale = 1000 * m_invtimestep;
486 m_VhoverHeight = 0;
487 m_VhoverEfficiency = 1;
488 m_VhoverTimescale = 1000;
489 m_VehicleBuoyancy = 0;
490 m_linearDeflectionEfficiency = 0;
491 m_linearDeflectionTimescale = 1000;
492 m_angularDeflectionEfficiency = 0;
493 m_angularDeflectionTimescale = 1000;
494 m_bankingEfficiency = 0;
495 m_bankingMix = 1;
496 m_bankingTimescale = 1000;
497 m_verticalAttractionEfficiency = 0;
498 m_verticalAttractionTimescale = 1000;
499
500 m_flags = (VehicleFlag)0;
501 break;
502
503 case Vehicle.TYPE_SLED:
504 m_linearFrictionTimescale = new Vector3(30, 1, 1000);
505 m_angularFrictionTimescale = new Vector3(1000, 1000, 1000);
506 m_linearMotorTimescale = 1000;
507 m_linearMotorDecayTimescale = 120 * m_invtimestep;
508 m_angularMotorTimescale = 1000;
509 m_angularMotorDecayTimescale = 120 * m_invtimestep;
510 m_VhoverHeight = 0;
511 m_VhoverEfficiency = 1;
512 m_VhoverTimescale = 10;
513 m_VehicleBuoyancy = 0;
514 m_linearDeflectionEfficiency = 1;
515 m_linearDeflectionTimescale = 1;
516 m_angularDeflectionEfficiency = 0;
517 m_angularDeflectionTimescale = 10;
518 m_verticalAttractionEfficiency = 1;
519 m_verticalAttractionTimescale = 1000;
520 m_bankingEfficiency = 0;
521 m_bankingMix = 1;
522 m_bankingTimescale = 10;
523 m_flags &=
524 ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY |
525 VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY);
526 m_flags |= (VehicleFlag.NO_DEFLECTION_UP |
527 VehicleFlag.LIMIT_ROLL_ONLY |
528 VehicleFlag.LIMIT_MOTOR_UP);
529 break;
530
531 case Vehicle.TYPE_CAR:
532 m_linearFrictionTimescale = new Vector3(100, 2, 1000);
533 m_angularFrictionTimescale = new Vector3(1000, 1000, 1000);
534 m_linearMotorTimescale = 1;
535 m_linearMotorDecayTimescale = 60 * m_invtimestep;
536 m_angularMotorTimescale = 1;
537 m_angularMotorDecayTimescale = 0.8f * m_invtimestep;
538 m_VhoverHeight = 0;
539 m_VhoverEfficiency = 0;
540 m_VhoverTimescale = 1000;
541 m_VehicleBuoyancy = 0;
542 m_linearDeflectionEfficiency = 1;
543 m_linearDeflectionTimescale = 2;
544 m_angularDeflectionEfficiency = 0;
545 m_angularDeflectionTimescale = 10;
546 m_verticalAttractionEfficiency = 1f;
547 m_verticalAttractionTimescale = 10f;
548 m_bankingEfficiency = -0.2f;
549 m_bankingMix = 1;
550 m_bankingTimescale = 1;
551 m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY |
552 VehicleFlag.HOVER_TERRAIN_ONLY |
553 VehicleFlag.HOVER_GLOBAL_HEIGHT);
554 m_flags |= (VehicleFlag.NO_DEFLECTION_UP |
555 VehicleFlag.LIMIT_ROLL_ONLY |
556 VehicleFlag.LIMIT_MOTOR_UP |
557 VehicleFlag.HOVER_UP_ONLY);
558 break;
559 case Vehicle.TYPE_BOAT:
560 m_linearFrictionTimescale = new Vector3(10, 3, 2);
561 m_angularFrictionTimescale = new Vector3(10, 10, 10);
562 m_linearMotorTimescale = 5;
563 m_linearMotorDecayTimescale = 60 * m_invtimestep;
564 m_angularMotorTimescale = 4;
565 m_angularMotorDecayTimescale = 4 * m_invtimestep;
566 m_VhoverHeight = 0;
567 m_VhoverEfficiency = 0.5f;
568 m_VhoverTimescale = 2;
569 m_VehicleBuoyancy = 1;
570 m_linearDeflectionEfficiency = 0.5f;
571 m_linearDeflectionTimescale = 3;
572 m_angularDeflectionEfficiency = 0.5f;
573 m_angularDeflectionTimescale = 5;
574 m_verticalAttractionEfficiency = 0.5f;
575 m_verticalAttractionTimescale = 5f;
576 m_bankingEfficiency = -0.3f;
577 m_bankingMix = 0.8f;
578 m_bankingTimescale = 1;
579 m_flags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY |
580 VehicleFlag.HOVER_GLOBAL_HEIGHT |
581 VehicleFlag.HOVER_UP_ONLY); // |
582// VehicleFlag.LIMIT_ROLL_ONLY);
583 m_flags |= (VehicleFlag.NO_DEFLECTION_UP |
584 VehicleFlag.LIMIT_MOTOR_UP |
585 VehicleFlag.HOVER_UP_ONLY | // new sl
586 VehicleFlag.HOVER_WATER_ONLY);
587 break;
588
589 case Vehicle.TYPE_AIRPLANE:
590 m_linearFrictionTimescale = new Vector3(200, 10, 5);
591 m_angularFrictionTimescale = new Vector3(20, 20, 20);
592 m_linearMotorTimescale = 2;
593 m_linearMotorDecayTimescale = 60 * m_invtimestep;
594 m_angularMotorTimescale = 4;
595 m_angularMotorDecayTimescale = 8 * m_invtimestep;
596 m_VhoverHeight = 0;
597 m_VhoverEfficiency = 0.5f;
598 m_VhoverTimescale = 1000;
599 m_VehicleBuoyancy = 0;
600 m_linearDeflectionEfficiency = 0.5f;
601 m_linearDeflectionTimescale = 0.5f;
602 m_angularDeflectionEfficiency = 1;
603 m_angularDeflectionTimescale = 2;
604 m_verticalAttractionEfficiency = 0.9f;
605 m_verticalAttractionTimescale = 2f;
606 m_bankingEfficiency = 1;
607 m_bankingMix = 0.7f;
608 m_bankingTimescale = 2;
609 m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY |
610 VehicleFlag.HOVER_TERRAIN_ONLY |
611 VehicleFlag.HOVER_GLOBAL_HEIGHT |
612 VehicleFlag.HOVER_UP_ONLY |
613 VehicleFlag.NO_DEFLECTION_UP |
614 VehicleFlag.LIMIT_MOTOR_UP);
615 m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY);
616 break;
617
618 case Vehicle.TYPE_BALLOON:
619 m_linearFrictionTimescale = new Vector3(5, 5, 5);
620 m_angularFrictionTimescale = new Vector3(10, 10, 10);
621 m_linearMotorTimescale = 5;
622 m_linearMotorDecayTimescale = 60 * m_invtimestep;
623 m_angularMotorTimescale = 6;
624 m_angularMotorDecayTimescale = 10 * m_invtimestep;
625 m_VhoverHeight = 5;
626 m_VhoverEfficiency = 0.8f;
627 m_VhoverTimescale = 10;
628 m_VehicleBuoyancy = 1;
629 m_linearDeflectionEfficiency = 0;
630 m_linearDeflectionTimescale = 5 * m_invtimestep;
631 m_angularDeflectionEfficiency = 0;
632 m_angularDeflectionTimescale = 5;
633 m_verticalAttractionEfficiency = 1f;
634 m_verticalAttractionTimescale = 1000f;
635 m_bankingEfficiency = 0;
636 m_bankingMix = 0.7f;
637 m_bankingTimescale = 5;
638 m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY |
639 VehicleFlag.HOVER_TERRAIN_ONLY |
640 VehicleFlag.HOVER_UP_ONLY |
641 VehicleFlag.NO_DEFLECTION_UP |
642 VehicleFlag.LIMIT_MOTOR_UP | //);
643 VehicleFlag.LIMIT_ROLL_ONLY | // new sl
644 VehicleFlag.HOVER_GLOBAL_HEIGHT); // new sl
645
646// m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY |
647// VehicleFlag.HOVER_GLOBAL_HEIGHT);
648 break;
649
650 }
651
652 m_lmDecay = (1.0f - 1.0f / m_linearMotorDecayTimescale);
653 m_amDecay = 1.0f - 1.0f / m_angularMotorDecayTimescale;
654
655 }//end SetDefaultsForType
656
657 internal void Stop()
658 {
659 m_lmEfect = 0;
660 m_lmDecay = 0f;
661 m_amEfect = 0;
662 m_amDecay = 0;
663 m_ffactor = 1f;
664 }
665
666 public static Vector3 Xrot(Quaternion rot)
667 {
668 Vector3 vec;
669 rot.Normalize(); // just in case
670 vec.X = 2 * (rot.X * rot.X + rot.W * rot.W) - 1;
671 vec.Y = 2 * (rot.X * rot.Y + rot.Z * rot.W);
672 vec.Z = 2 * (rot.X * rot.Z - rot.Y * rot.W);
673 return vec;
674 }
675
676 public static Vector3 Zrot(Quaternion rot)
677 {
678 Vector3 vec;
679 rot.Normalize(); // just in case
680 vec.X = 2 * (rot.X * rot.Z + rot.Y * rot.W);
681 vec.Y = 2 * (rot.Y * rot.Z - rot.X * rot.W);
682 vec.Z = 2 * (rot.Z * rot.Z + rot.W * rot.W) - 1;
683
684 return vec;
685 }
686
687 private const float pi = (float)Math.PI;
688 private const float halfpi = 0.5f * (float)Math.PI;
689 private const float twopi = 2.0f * pi;
690
691 public static Vector3 ubRot2Euler(Quaternion rot)
692 {
693 // returns roll in X
694 // pitch in Y
695 // yaw in Z
696 Vector3 vec;
697
698 // assuming rot is normalised
699 // rot.Normalize();
700
701 float zX = rot.X * rot.Z + rot.Y * rot.W;
702
703 if (zX < -0.49999f)
704 {
705 vec.X = 0;
706 vec.Y = -halfpi;
707 vec.Z = (float)(-2d * Math.Atan(rot.X / rot.W));
708 }
709 else if (zX > 0.49999f)
710 {
711 vec.X = 0;
712 vec.Y = halfpi;
713 vec.Z = (float)(2d * Math.Atan(rot.X / rot.W));
714 }
715 else
716 {
717 vec.Y = (float)Math.Asin(2 * zX);
718
719 float sqw = rot.W * rot.W;
720
721 float minuszY = rot.X * rot.W - rot.Y * rot.Z;
722 float zZ = rot.Z * rot.Z + sqw - 0.5f;
723
724 vec.X = (float)Math.Atan2(minuszY, zZ);
725
726 float yX = rot.Z * rot.W - rot.X * rot.Y; //( have negative ?)
727 float yY = rot.X * rot.X + sqw - 0.5f;
728 vec.Z = (float)Math.Atan2(yX, yY);
729 }
730 return vec;
731 }
732
733 public static void GetRollPitch(Quaternion rot, out float roll, out float pitch)
734 {
735 // assuming rot is normalised
736 // rot.Normalize();
737
738 float zX = rot.X * rot.Z + rot.Y * rot.W;
739
740 if (zX < -0.49999f)
741 {
742 roll = 0;
743 pitch = -halfpi;
744 }
745 else if (zX > 0.49999f)
746 {
747 roll = 0;
748 pitch = halfpi;
749 }
750 else
751 {
752 pitch = (float)Math.Asin(2 * zX);
753
754 float minuszY = rot.X * rot.W - rot.Y * rot.Z;
755 float zZ = rot.Z * rot.Z + rot.W * rot.W - 0.5f;
756
757 roll = (float)Math.Atan2(minuszY, zZ);
758 }
759 return ;
760 }
761
762 internal void Step()
763 {
764 IntPtr Body = rootPrim.Body;
765
766 d.Mass dmass;
767 d.BodyGetMass(Body, out dmass);
768
769 d.Quaternion rot = d.BodyGetQuaternion(Body);
770 Quaternion objrotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W); // rotq = rotation of object
771 Quaternion rotq = objrotq; // rotq = rotation of object
772 rotq *= m_referenceFrame; // rotq is now rotation in vehicle reference frame
773 Quaternion irotq = Quaternion.Inverse(rotq);
774
775 d.Vector3 dvtmp;
776 Vector3 tmpV;
777 Vector3 curVel; // velocity in world
778 Vector3 curAngVel; // angular velocity in world
779 Vector3 force = Vector3.Zero; // actually linear aceleration until mult by mass in world frame
780 Vector3 torque = Vector3.Zero;// actually angular aceleration until mult by Inertia in vehicle frame
781 d.Vector3 dtorque = new d.Vector3();
782
783 dvtmp = d.BodyGetLinearVel(Body);
784 curVel.X = dvtmp.X;
785 curVel.Y = dvtmp.Y;
786 curVel.Z = dvtmp.Z;
787 Vector3 curLocalVel = curVel * irotq; // current velocity in local
788
789 dvtmp = d.BodyGetAngularVel(Body);
790 curAngVel.X = dvtmp.X;
791 curAngVel.Y = dvtmp.Y;
792 curAngVel.Z = dvtmp.Z;
793 Vector3 curLocalAngVel = curAngVel * irotq; // current angular velocity in local
794
795 float ldampZ = 0;
796
797 // linear motor
798 if (m_lmEfect > 0.01 && m_linearMotorTimescale < 1000)
799 {
800 tmpV = m_linearMotorDirection - curLocalVel; // velocity error
801 tmpV *= m_lmEfect / m_linearMotorTimescale; // error to correct in this timestep
802 tmpV *= rotq; // to world
803
804 if ((m_flags & VehicleFlag.LIMIT_MOTOR_UP) != 0)
805 tmpV.Z = 0;
806
807 if (m_linearMotorOffset.X != 0 || m_linearMotorOffset.Y != 0 || m_linearMotorOffset.Z != 0)
808 {
809 // have offset, do it now
810 tmpV *= dmass.mass;
811 d.BodyAddForceAtRelPos(Body, tmpV.X, tmpV.Y, tmpV.Z, m_linearMotorOffset.X, m_linearMotorOffset.Y, m_linearMotorOffset.Z);
812 }
813 else
814 {
815 force.X += tmpV.X;
816 force.Y += tmpV.Y;
817 force.Z += tmpV.Z;
818 }
819
820 m_lmEfect *= m_lmDecay;
821// m_ffactor = 0.01f + 1e-4f * curVel.LengthSquared();
822 m_ffactor = 0.0f;
823 }
824 else
825 {
826 m_lmEfect = 0;
827 m_ffactor = 1f;
828 }
829
830 // hover
831 if (m_VhoverTimescale < 300 && rootPrim.prim_geom != IntPtr.Zero)
832 {
833 // d.Vector3 pos = d.BodyGetPosition(Body);
834 d.Vector3 pos = d.GeomGetPosition(rootPrim.prim_geom);
835 pos.Z -= 0.21f; // minor offset that seems to be always there in sl
836
837 float t = _pParentScene.GetTerrainHeightAtXY(pos.X, pos.Y);
838 float perr;
839
840 // default to global but don't go underground
841 perr = m_VhoverHeight - pos.Z;
842
843 if ((m_flags & VehicleFlag.HOVER_GLOBAL_HEIGHT) == 0)
844 {
845 if ((m_flags & VehicleFlag.HOVER_WATER_ONLY) != 0)
846 {
847 perr += _pParentScene.GetWaterLevel();
848 }
849 else if ((m_flags & VehicleFlag.HOVER_TERRAIN_ONLY) != 0)
850 {
851 perr += t;
852 }
853 else
854 {
855 float w = _pParentScene.GetWaterLevel();
856 if (t > w)
857 perr += t;
858 else
859 perr += w;
860 }
861 }
862 else if (t > m_VhoverHeight)
863 perr = t - pos.Z; ;
864
865 if ((m_flags & VehicleFlag.HOVER_UP_ONLY) == 0 || perr > -0.1)
866 {
867 ldampZ = m_VhoverEfficiency * m_invtimestep;
868
869 perr *= (1.0f + ldampZ) / m_VhoverTimescale;
870
871 // force.Z += perr - curVel.Z * tmp;
872 force.Z += perr;
873 ldampZ *= -curVel.Z;
874
875 force.Z += _pParentScene.gravityz * m_gravmod * (1f - m_VehicleBuoyancy);
876 }
877 else // no buoyancy
878 force.Z += _pParentScene.gravityz;
879 }
880 else
881 {
882 // default gravity and Buoyancy
883 force.Z += _pParentScene.gravityz * m_gravmod * (1f - m_VehicleBuoyancy);
884 }
885
886 // linear deflection
887 if (m_linearDeflectionEfficiency > 0)
888 {
889 float len = curVel.Length();
890 if (len > 0.01) // if moving
891 {
892 Vector3 atAxis;
893 atAxis = Xrot(rotq); // where are we pointing to
894 atAxis *= len; // make it same size as world velocity vector
895
896 tmpV = -atAxis; // oposite direction
897 atAxis -= curVel; // error to one direction
898 len = atAxis.LengthSquared();
899
900 tmpV -= curVel; // error to oposite
901 float lens = tmpV.LengthSquared();
902
903 if (len > 0.01 || lens > 0.01) // do nothing if close enougth
904 {
905 if (len < lens)
906 tmpV = atAxis;
907
908 tmpV *= (m_linearDeflectionEfficiency / m_linearDeflectionTimescale); // error to correct in this timestep
909 force.X += tmpV.X;
910 force.Y += tmpV.Y;
911 if ((m_flags & VehicleFlag.NO_DEFLECTION_UP) == 0)
912 force.Z += tmpV.Z;
913 }
914 }
915 }
916
917 // linear friction/damping
918 if (curLocalVel.X != 0 || curLocalVel.Y != 0 || curLocalVel.Z != 0)
919 {
920 tmpV.X = -curLocalVel.X / m_linearFrictionTimescale.X;
921 tmpV.Y = -curLocalVel.Y / m_linearFrictionTimescale.Y;
922 tmpV.Z = -curLocalVel.Z / m_linearFrictionTimescale.Z;
923 tmpV *= rotq; // to world
924
925 if(ldampZ != 0 && Math.Abs(ldampZ) > Math.Abs(tmpV.Z))
926 tmpV.Z = ldampZ;
927 force.X += tmpV.X;
928 force.Y += tmpV.Y;
929 force.Z += tmpV.Z;
930 }
931
932 // vertical atractor
933 if (m_verticalAttractionTimescale < 300)
934 {
935 float roll;
936 float pitch;
937
938
939
940 float ftmp = m_invtimestep / m_verticalAttractionTimescale / m_verticalAttractionTimescale;
941
942 float ftmp2;
943 ftmp2 = 0.5f * m_verticalAttractionEfficiency * m_invtimestep;
944 m_amdampX = ftmp2;
945
946 m_ampwr = 1.0f - 0.8f * m_verticalAttractionEfficiency;
947
948 GetRollPitch(irotq, out roll, out pitch);
949
950 if (roll > halfpi)
951 roll = pi - roll;
952 else if (roll < -halfpi)
953 roll = -pi - roll;
954
955 float effroll = pitch / halfpi;
956 effroll *= effroll;
957 effroll = 1 - effroll;
958 effroll *= roll;
959
960
961 torque.X += effroll * ftmp;
962
963 if ((m_flags & VehicleFlag.LIMIT_ROLL_ONLY) == 0)
964 {
965 float effpitch = roll / halfpi;
966 effpitch *= effpitch;
967 effpitch = 1 - effpitch;
968 effpitch *= pitch;
969
970 torque.Y += effpitch * ftmp;
971 }
972
973 if (m_bankingEfficiency != 0 && Math.Abs(effroll) > 0.01)
974 {
975
976 float broll = effroll;
977 /*
978 if (broll > halfpi)
979 broll = pi - broll;
980 else if (broll < -halfpi)
981 broll = -pi - broll;
982 */
983 broll *= m_bankingEfficiency;
984 if (m_bankingMix != 0)
985 {
986 float vfact = Math.Abs(curLocalVel.X) / 10.0f;
987 if (vfact > 1.0f) vfact = 1.0f;
988
989 if (curLocalVel.X >= 0)
990 broll *= (1 + (vfact - 1) * m_bankingMix);
991 else
992 broll *= -(1 + (vfact - 1) * m_bankingMix);
993 }
994 // make z rot be in world Z not local as seems to be in sl
995
996 broll = broll / m_bankingTimescale;
997
998
999 tmpV = Zrot(irotq);
1000 tmpV *= broll;
1001
1002 torque.X += tmpV.X;
1003 torque.Y += tmpV.Y;
1004 torque.Z += tmpV.Z;
1005
1006 m_amdampZ = Math.Abs(m_bankingEfficiency) / m_bankingTimescale;
1007 m_amdampY = m_amdampZ;
1008
1009 }
1010 else
1011 {
1012 m_amdampZ = 1 / m_angularFrictionTimescale.Z;
1013 m_amdampY = m_amdampX;
1014 }
1015 }
1016 else
1017 {
1018 m_ampwr = 1.0f;
1019 m_amdampX = 1 / m_angularFrictionTimescale.X;
1020 m_amdampY = 1 / m_angularFrictionTimescale.Y;
1021 m_amdampZ = 1 / m_angularFrictionTimescale.Z;
1022 }
1023
1024 // angular motor
1025 if (m_amEfect > 0.01 && m_angularMotorTimescale < 1000)
1026 {
1027 tmpV = m_angularMotorDirection - curLocalAngVel; // velocity error
1028 tmpV *= m_amEfect / m_angularMotorTimescale; // error to correct in this timestep
1029 torque.X += tmpV.X * m_ampwr;
1030 torque.Y += tmpV.Y * m_ampwr;
1031 torque.Z += tmpV.Z;
1032
1033 m_amEfect *= m_amDecay;
1034 }
1035 else
1036 m_amEfect = 0;
1037
1038 // angular deflection
1039 if (m_angularDeflectionEfficiency > 0)
1040 {
1041 Vector3 dirv;
1042
1043 if (curLocalVel.X > 0.01f)
1044 dirv = curLocalVel;
1045 else if (curLocalVel.X < -0.01f)
1046 // use oposite
1047 dirv = -curLocalVel;
1048 else
1049 {
1050 // make it fall into small positive x case
1051 dirv.X = 0.01f;
1052 dirv.Y = curLocalVel.Y;
1053 dirv.Z = curLocalVel.Z;
1054 }
1055
1056 float ftmp = m_angularDeflectionEfficiency / m_angularDeflectionTimescale;
1057
1058 if (Math.Abs(dirv.Z) > 0.01)
1059 {
1060 torque.Y += - (float)Math.Atan2(dirv.Z, dirv.X) * ftmp;
1061 }
1062
1063 if (Math.Abs(dirv.Y) > 0.01)
1064 {
1065 torque.Z += (float)Math.Atan2(dirv.Y, dirv.X) * ftmp;
1066 }
1067 }
1068
1069 // angular friction
1070 if (curLocalAngVel.X != 0 || curLocalAngVel.Y != 0 || curLocalAngVel.Z != 0)
1071 {
1072 torque.X -= curLocalAngVel.X * m_amdampX;
1073 torque.Y -= curLocalAngVel.Y * m_amdampY;
1074 torque.Z -= curLocalAngVel.Z * m_amdampZ;
1075 }
1076
1077
1078 if (force.X != 0 || force.Y != 0 || force.Z != 0)
1079 {
1080 force *= dmass.mass;
1081 d.BodyAddForce(Body, force.X, force.Y, force.Z);
1082 }
1083
1084 if (torque.X != 0 || torque.Y != 0 || torque.Z != 0)
1085 {
1086 torque *= m_referenceFrame; // to object frame
1087 dtorque.X = torque.X ;
1088 dtorque.Y = torque.Y;
1089 dtorque.Z = torque.Z;
1090
1091 d.MultiplyM3V3(out dvtmp, ref dmass.I, ref dtorque);
1092 d.BodyAddRelTorque(Body, dvtmp.X, dvtmp.Y, dvtmp.Z); // add torque in object frame
1093 }
1094 }
1095 }
1096}
diff --git a/OpenSim/Region/PhysicsModules/ubOde/ODEMeshWorker.cs b/OpenSim/Region/PhysicsModules/ubOde/ODEMeshWorker.cs
new file mode 100644
index 0000000..40b5ef7
--- /dev/null
+++ b/OpenSim/Region/PhysicsModules/ubOde/ODEMeshWorker.cs
@@ -0,0 +1,933 @@
1/*
2 * AJLDuarte 2012
3 */
4
5using System;
6using System.Threading;
7using System.Collections.Generic;
8using System.IO;
9using System.Reflection;
10using System.Runtime.InteropServices;
11using System.Text;
12using OpenSim.Framework;
13using OpenSim.Region.PhysicsModules.SharedBase;
14using OdeAPI;
15using log4net;
16using Nini.Config;
17using OpenMetaverse;
18
19namespace OpenSim.Region.PhysicsModule.ubOde
20{
21 public enum MeshState : byte
22 {
23 noNeed = 0,
24
25 loadingAsset = 1,
26
27 AssetOK = 0x0f, // 00001111
28
29 NeedMask = 0x30, // 00110000
30 needMesh = 0x10, // 00010000
31 needAsset = 0x20, // 00100000
32
33 FailMask = 0xC0, // 11000000
34 AssetFailed = 0x40, // 01000000
35 MeshFailed = 0x80, // 10000000
36
37 MeshNoColide = FailMask | needAsset
38 }
39
40 public enum meshWorkerCmnds : byte
41 {
42 nop = 0,
43 addnew,
44 changefull,
45 changesize,
46 changeshapetype,
47 getmesh,
48 }
49
50 public class ODEPhysRepData
51 {
52 public PhysicsActor actor;
53 public PrimitiveBaseShape pbs;
54 public IMesh mesh;
55
56 public Vector3 size;
57 public Vector3 OBB;
58 public Vector3 OBBOffset;
59
60 public float volume;
61
62 public byte shapetype;
63 public bool hasOBB;
64 public bool hasMeshVolume;
65 public MeshState meshState;
66 public UUID? assetID;
67 public meshWorkerCmnds comand;
68 }
69
70 public class ODEMeshWorker
71 {
72
73 private ILog m_log;
74 private ODEScene m_scene;
75 private IMesher m_mesher;
76
77 public bool meshSculptedPrim = true;
78 public bool forceSimplePrimMeshing = false;
79 public float meshSculptLOD = 32;
80 public float MeshSculptphysicalLOD = 32;
81
82
83 private OpenSim.Framework.BlockingQueue<ODEPhysRepData> createqueue = new OpenSim.Framework.BlockingQueue<ODEPhysRepData>();
84 private bool m_running;
85
86 private Thread m_thread;
87
88 public ODEMeshWorker(ODEScene pScene, ILog pLog, IMesher pMesher, IConfig pConfig)
89 {
90 m_scene = pScene;
91 m_log = pLog;
92 m_mesher = pMesher;
93
94 if (pConfig != null)
95 {
96 forceSimplePrimMeshing = pConfig.GetBoolean("force_simple_prim_meshing", forceSimplePrimMeshing);
97 meshSculptedPrim = pConfig.GetBoolean("mesh_sculpted_prim", meshSculptedPrim);
98 meshSculptLOD = pConfig.GetFloat("mesh_lod", meshSculptLOD);
99 MeshSculptphysicalLOD = pConfig.GetFloat("mesh_physical_lod", MeshSculptphysicalLOD);
100 }
101 m_running = true;
102 m_thread = new Thread(DoWork);
103 m_thread.Name = "OdeMeshWorker";
104 m_thread.Start();
105 }
106
107 private void DoWork()
108 {
109 m_mesher.ExpireFileCache();
110
111 while(m_running)
112 {
113 ODEPhysRepData nextRep = createqueue.Dequeue();
114 if(!m_running)
115 return;
116 if (nextRep == null)
117 continue;
118 if (m_scene.haveActor(nextRep.actor))
119 {
120 switch (nextRep.comand)
121 {
122 case meshWorkerCmnds.changefull:
123 case meshWorkerCmnds.changeshapetype:
124 case meshWorkerCmnds.changesize:
125 GetMesh(nextRep);
126 if (CreateActorPhysRep(nextRep) && m_scene.haveActor(nextRep.actor))
127 m_scene.AddChange(nextRep.actor, changes.PhysRepData, nextRep);
128 break;
129 case meshWorkerCmnds.getmesh:
130 DoRepDataGetMesh(nextRep);
131 break;
132 }
133 }
134 }
135 }
136
137 public void Stop()
138 {
139 try
140 {
141 m_thread.Abort();
142 createqueue.Clear();
143 }
144 catch
145 {
146 }
147 }
148
149 public void ChangeActorPhysRep(PhysicsActor actor, PrimitiveBaseShape pbs,
150 Vector3 size, byte shapetype)
151 {
152 ODEPhysRepData repData = new ODEPhysRepData();
153 repData.actor = actor;
154 repData.pbs = pbs;
155 repData.size = size;
156 repData.shapetype = shapetype;
157
158 CheckMesh(repData);
159 CalcVolumeData(repData);
160 m_scene.AddChange(actor, changes.PhysRepData, repData);
161 return;
162 }
163
164 public ODEPhysRepData NewActorPhysRep(PhysicsActor actor, PrimitiveBaseShape pbs,
165 Vector3 size, byte shapetype)
166 {
167 ODEPhysRepData repData = new ODEPhysRepData();
168 repData.actor = actor;
169 repData.pbs = pbs;
170 repData.size = size;
171 repData.shapetype = shapetype;
172
173 CheckMesh(repData);
174 CalcVolumeData(repData);
175 m_scene.AddChange(actor, changes.AddPhysRep, repData);
176 return repData;
177 }
178
179 public void RequestMesh(ODEPhysRepData repData)
180 {
181 repData.mesh = null;
182
183 if (repData.meshState == MeshState.needAsset)
184 {
185 PrimitiveBaseShape pbs = repData.pbs;
186
187 // check if we got outdated
188
189 if (!pbs.SculptEntry || pbs.SculptTexture == UUID.Zero)
190 {
191 repData.meshState = MeshState.noNeed;
192 return;
193 }
194
195 repData.assetID = pbs.SculptTexture;
196 repData.meshState = MeshState.loadingAsset;
197
198 repData.comand = meshWorkerCmnds.getmesh;
199 createqueue.Enqueue(repData);
200 }
201 }
202
203 // creates and prepares a mesh to use and calls parameters estimation
204 public bool CreateActorPhysRep(ODEPhysRepData repData)
205 {
206 IMesh mesh = repData.mesh;
207
208 if (mesh != null)
209 {
210 IntPtr vertices, indices;
211 int vertexCount, indexCount;
212 int vertexStride, triStride;
213
214 mesh.getVertexListAsPtrToFloatArray(out vertices, out vertexStride, out vertexCount);
215 mesh.getIndexListAsPtrToIntArray(out indices, out triStride, out indexCount);
216
217 if (vertexCount == 0 || indexCount == 0)
218 {
219 m_log.WarnFormat("[PHYSICS]: Invalid mesh data on prim {0} mesh UUID {1}",
220 repData.actor.Name, repData.pbs.SculptTexture.ToString());
221 repData.meshState = MeshState.MeshFailed;
222 repData.hasOBB = false;
223 repData.mesh = null;
224 m_scene.mesher.ReleaseMesh(mesh);
225 }
226 else
227 {
228 repData.OBBOffset = mesh.GetCentroid();
229 repData.OBB = mesh.GetOBB();
230 repData.hasOBB = true;
231 mesh.releaseSourceMeshData();
232 }
233 }
234 CalcVolumeData(repData);
235 return true;
236 }
237
238 public void AssetLoaded(ODEPhysRepData repData)
239 {
240 if (m_scene.haveActor(repData.actor))
241 {
242 if (needsMeshing(repData.pbs)) // no need for pbs now?
243 {
244 repData.comand = meshWorkerCmnds.changefull;
245 createqueue.Enqueue(repData);
246 }
247 }
248 else
249 repData.pbs.SculptData = Utils.EmptyBytes;
250 }
251
252 public void DoRepDataGetMesh(ODEPhysRepData repData)
253 {
254 if (!repData.pbs.SculptEntry)
255 return;
256
257 if (repData.meshState != MeshState.loadingAsset)
258 return;
259
260 if (repData.assetID == null || repData.assetID == UUID.Zero)
261 return;
262
263 if (repData.assetID != repData.pbs.SculptTexture)
264 return;
265
266 // check if it is in cache
267 GetMesh(repData);
268 if (repData.meshState != MeshState.needAsset)
269 {
270 CreateActorPhysRep(repData);
271 m_scene.AddChange(repData.actor, changes.PhysRepData, repData);
272 return;
273 }
274
275 RequestAssetDelegate assetProvider = m_scene.RequestAssetMethod;
276 if (assetProvider == null)
277 return;
278 ODEAssetRequest asr = new ODEAssetRequest(this, assetProvider, repData, m_log);
279 }
280
281
282 /// <summary>
283 /// Routine to figure out if we need to mesh this prim with our mesher
284 /// </summary>
285 /// <param name="pbs"></param>
286 /// <returns></returns>
287 public bool needsMeshing(PrimitiveBaseShape pbs)
288 {
289 // check sculpts or meshs
290 if (pbs.SculptEntry)
291 {
292 if (meshSculptedPrim)
293 return true;
294
295 if (pbs.SculptType == (byte)SculptType.Mesh) // always do meshs
296 return true;
297
298 return false;
299 }
300
301 if (forceSimplePrimMeshing)
302 return true;
303
304 // if it's a standard box or sphere with no cuts, hollows, twist or top shear, return false since ODE can use an internal representation for the prim
305
306 if ((pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight)
307 || (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1
308 && pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z))
309 {
310
311 if (pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0
312 && pbs.ProfileHollow == 0
313 && pbs.PathTwist == 0 && pbs.PathTwistBegin == 0
314 && pbs.PathBegin == 0 && pbs.PathEnd == 0
315 && pbs.PathTaperX == 0 && pbs.PathTaperY == 0
316 && pbs.PathScaleX == 100 && pbs.PathScaleY == 100
317 && pbs.PathShearX == 0 && pbs.PathShearY == 0)
318 {
319 return false;
320 }
321 }
322
323 // following code doesn't give meshs to boxes and spheres ever
324 // and it's odd.. so for now just return true if asked to force meshs
325 // hopefully mesher will fail if doesn't suport so things still get basic boxes
326
327 int iPropertiesNotSupportedDefault = 0;
328
329 if (pbs.ProfileHollow != 0)
330 iPropertiesNotSupportedDefault++;
331
332 if ((pbs.PathBegin != 0) || pbs.PathEnd != 0)
333 iPropertiesNotSupportedDefault++;
334
335 if ((pbs.PathTwistBegin != 0) || (pbs.PathTwist != 0))
336 iPropertiesNotSupportedDefault++;
337
338 if ((pbs.ProfileBegin != 0) || pbs.ProfileEnd != 0)
339 iPropertiesNotSupportedDefault++;
340
341 if ((pbs.PathScaleX != 100) || (pbs.PathScaleY != 100))
342 iPropertiesNotSupportedDefault++;
343
344 if ((pbs.PathShearX != 0) || (pbs.PathShearY != 0))
345 iPropertiesNotSupportedDefault++;
346
347 if (pbs.ProfileShape == ProfileShape.Circle && pbs.PathCurve == (byte)Extrusion.Straight)
348 iPropertiesNotSupportedDefault++;
349
350 if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1 && (pbs.Scale.X != pbs.Scale.Y || pbs.Scale.Y != pbs.Scale.Z || pbs.Scale.Z != pbs.Scale.X))
351 iPropertiesNotSupportedDefault++;
352
353 if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1)
354 iPropertiesNotSupportedDefault++;
355
356 // test for torus
357 if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Square)
358 {
359 if (pbs.PathCurve == (byte)Extrusion.Curve1)
360 {
361 iPropertiesNotSupportedDefault++;
362 }
363 }
364 else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Circle)
365 {
366 if (pbs.PathCurve == (byte)Extrusion.Straight)
367 {
368 iPropertiesNotSupportedDefault++;
369 }
370
371 // ProfileCurve seems to combine hole shape and profile curve so we need to only compare against the lower 3 bits
372 else if (pbs.PathCurve == (byte)Extrusion.Curve1)
373 {
374 iPropertiesNotSupportedDefault++;
375 }
376 }
377 else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle)
378 {
379 if (pbs.PathCurve == (byte)Extrusion.Curve1 || pbs.PathCurve == (byte)Extrusion.Curve2)
380 {
381 iPropertiesNotSupportedDefault++;
382 }
383 }
384 else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle)
385 {
386 if (pbs.PathCurve == (byte)Extrusion.Straight)
387 {
388 iPropertiesNotSupportedDefault++;
389 }
390 else if (pbs.PathCurve == (byte)Extrusion.Curve1)
391 {
392 iPropertiesNotSupportedDefault++;
393 }
394 }
395
396 if (iPropertiesNotSupportedDefault == 0)
397 {
398 return false;
399 }
400 return true;
401 }
402
403 // see if we need a mesh and if so if we have a cached one
404 // called with a new repData
405 public void CheckMesh(ODEPhysRepData repData)
406 {
407 PhysicsActor actor = repData.actor;
408 PrimitiveBaseShape pbs = repData.pbs;
409
410 if (!needsMeshing(pbs))
411 {
412 repData.meshState = MeshState.noNeed;
413 return;
414 }
415
416 IMesh mesh = null;
417
418 Vector3 size = repData.size;
419 byte shapetype = repData.shapetype;
420
421 bool convex;
422
423 int clod = (int)LevelOfDetail.High;
424 if (shapetype == 0)
425 convex = false;
426 else
427 {
428 convex = true;
429 if (pbs.SculptType != (byte)SculptType.Mesh)
430 clod = (int)LevelOfDetail.Low;
431 }
432
433 mesh = m_mesher.GetMesh(actor.Name, pbs, size, clod, true, convex);
434
435 if (mesh == null)
436 {
437 if (pbs.SculptEntry)
438 {
439 if (pbs.SculptTexture != null && pbs.SculptTexture != UUID.Zero)
440 {
441 repData.assetID = pbs.SculptTexture;
442 repData.meshState = MeshState.needAsset;
443 }
444 else
445 repData.meshState = MeshState.MeshFailed;
446
447 return;
448 }
449 else
450 {
451 repData.meshState = MeshState.needMesh;
452 mesh = m_mesher.CreateMesh(actor.Name, pbs, size, clod, true, convex, true);
453 if (mesh == null)
454 {
455 repData.meshState = MeshState.MeshFailed;
456 return;
457 }
458 }
459 }
460
461 repData.meshState = MeshState.AssetOK;
462 repData.mesh = mesh;
463
464 if (pbs.SculptEntry)
465 {
466 repData.assetID = pbs.SculptTexture;
467 }
468
469 pbs.SculptData = Utils.EmptyBytes;
470 return ;
471 }
472
473 public void GetMesh(ODEPhysRepData repData)
474 {
475 PhysicsActor actor = repData.actor;
476
477 PrimitiveBaseShape pbs = repData.pbs;
478
479 repData.mesh = null;
480 repData.hasOBB = false;
481
482 if (!needsMeshing(pbs))
483 {
484 repData.meshState = MeshState.noNeed;
485 return;
486 }
487
488 if (repData.meshState == MeshState.MeshFailed)
489 return;
490
491 if (pbs.SculptEntry)
492 {
493 if (repData.meshState == MeshState.AssetFailed)
494 {
495 if (pbs.SculptTexture == repData.assetID)
496 return;
497 }
498 }
499
500 repData.meshState = MeshState.noNeed;
501
502 IMesh mesh = null;
503 Vector3 size = repData.size;
504 byte shapetype = repData.shapetype;
505
506 bool convex;
507 int clod = (int)LevelOfDetail.High;
508 if (shapetype == 0)
509 convex = false;
510 else
511 {
512 convex = true;
513 if (pbs.SculptType != (byte)SculptType.Mesh)
514 clod = (int)LevelOfDetail.Low;
515 }
516
517 mesh = m_mesher.CreateMesh(actor.Name, pbs, size, clod, true, convex, true);
518
519 if (mesh == null)
520 {
521 if (pbs.SculptEntry)
522 {
523 if (pbs.SculptTexture == UUID.Zero)
524 return;
525
526 repData.assetID = pbs.SculptTexture;
527
528 if (pbs.SculptData == null || pbs.SculptData.Length == 0)
529 {
530 repData.meshState = MeshState.needAsset;
531 return;
532 }
533 }
534 }
535
536 repData.mesh = mesh;
537 repData.pbs.SculptData = Utils.EmptyBytes;
538
539 if (mesh == null)
540 {
541 if (pbs.SculptEntry)
542 repData.meshState = MeshState.AssetFailed;
543 else
544 repData.meshState = MeshState.MeshFailed;
545
546 return;
547 }
548
549 repData.meshState = MeshState.AssetOK;
550
551 return;
552 }
553
554 private void CalculateBasicPrimVolume(ODEPhysRepData repData)
555 {
556 PrimitiveBaseShape _pbs = repData.pbs;
557 Vector3 _size = repData.size;
558
559 float volume = _size.X * _size.Y * _size.Z; // default
560 float tmp;
561
562 float hollowAmount = (float)_pbs.ProfileHollow * 2.0e-5f;
563 float hollowVolume = hollowAmount * hollowAmount;
564
565 switch (_pbs.ProfileShape)
566 {
567 case ProfileShape.Square:
568 // default box
569
570 if (_pbs.PathCurve == (byte)Extrusion.Straight)
571 {
572 if (hollowAmount > 0.0)
573 {
574 switch (_pbs.HollowShape)
575 {
576 case HollowShape.Square:
577 case HollowShape.Same:
578 break;
579
580 case HollowShape.Circle:
581
582 hollowVolume *= 0.78539816339f;
583 break;
584
585 case HollowShape.Triangle:
586
587 hollowVolume *= (0.5f * .5f);
588 break;
589
590 default:
591 hollowVolume = 0;
592 break;
593 }
594 volume *= (1.0f - hollowVolume);
595 }
596 }
597
598 else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
599 {
600 //a tube
601
602 volume *= 0.78539816339e-2f * (float)(200 - _pbs.PathScaleX);
603 tmp = 1.0f - 2.0e-2f * (float)(200 - _pbs.PathScaleY);
604 volume -= volume * tmp * tmp;
605
606 if (hollowAmount > 0.0)
607 {
608 hollowVolume *= hollowAmount;
609
610 switch (_pbs.HollowShape)
611 {
612 case HollowShape.Square:
613 case HollowShape.Same:
614 break;
615
616 case HollowShape.Circle:
617 hollowVolume *= 0.78539816339f;
618 break;
619
620 case HollowShape.Triangle:
621 hollowVolume *= 0.5f * 0.5f;
622 break;
623 default:
624 hollowVolume = 0;
625 break;
626 }
627 volume *= (1.0f - hollowVolume);
628 }
629 }
630
631 break;
632
633 case ProfileShape.Circle:
634
635 if (_pbs.PathCurve == (byte)Extrusion.Straight)
636 {
637 volume *= 0.78539816339f; // elipse base
638
639 if (hollowAmount > 0.0)
640 {
641 switch (_pbs.HollowShape)
642 {
643 case HollowShape.Same:
644 case HollowShape.Circle:
645 break;
646
647 case HollowShape.Square:
648 hollowVolume *= 0.5f * 2.5984480504799f;
649 break;
650
651 case HollowShape.Triangle:
652 hollowVolume *= .5f * 1.27323954473516f;
653 break;
654
655 default:
656 hollowVolume = 0;
657 break;
658 }
659 volume *= (1.0f - hollowVolume);
660 }
661 }
662
663 else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
664 {
665 volume *= 0.61685027506808491367715568749226e-2f * (float)(200 - _pbs.PathScaleX);
666 tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY);
667 volume *= (1.0f - tmp * tmp);
668
669 if (hollowAmount > 0.0)
670 {
671
672 // calculate the hollow volume by it's shape compared to the prim shape
673 hollowVolume *= hollowAmount;
674
675 switch (_pbs.HollowShape)
676 {
677 case HollowShape.Same:
678 case HollowShape.Circle:
679 break;
680
681 case HollowShape.Square:
682 hollowVolume *= 0.5f * 2.5984480504799f;
683 break;
684
685 case HollowShape.Triangle:
686 hollowVolume *= .5f * 1.27323954473516f;
687 break;
688
689 default:
690 hollowVolume = 0;
691 break;
692 }
693 volume *= (1.0f - hollowVolume);
694 }
695 }
696 break;
697
698 case ProfileShape.HalfCircle:
699 if (_pbs.PathCurve == (byte)Extrusion.Curve1)
700 {
701 volume *= 0.5236f;
702
703 if (hollowAmount > 0.0)
704 {
705 hollowVolume *= hollowAmount;
706
707 switch (_pbs.HollowShape)
708 {
709 case HollowShape.Circle:
710 case HollowShape.Triangle: // diference in sl is minor and odd
711 case HollowShape.Same:
712 break;
713
714 case HollowShape.Square:
715 hollowVolume *= 0.909f;
716 break;
717
718 // case HollowShape.Triangle:
719 // hollowVolume *= .827f;
720 // break;
721 default:
722 hollowVolume = 0;
723 break;
724 }
725 volume *= (1.0f - hollowVolume);
726 }
727
728 }
729 break;
730
731 case ProfileShape.EquilateralTriangle:
732
733 if (_pbs.PathCurve == (byte)Extrusion.Straight)
734 {
735 volume *= 0.32475953f;
736
737 if (hollowAmount > 0.0)
738 {
739
740 // calculate the hollow volume by it's shape compared to the prim shape
741 switch (_pbs.HollowShape)
742 {
743 case HollowShape.Same:
744 case HollowShape.Triangle:
745 hollowVolume *= .25f;
746 break;
747
748 case HollowShape.Square:
749 hollowVolume *= 0.499849f * 3.07920140172638f;
750 break;
751
752 case HollowShape.Circle:
753 // Hollow shape is a perfect cyllinder in respect to the cube's scale
754 // Cyllinder hollow volume calculation
755
756 hollowVolume *= 0.1963495f * 3.07920140172638f;
757 break;
758
759 default:
760 hollowVolume = 0;
761 break;
762 }
763 volume *= (1.0f - hollowVolume);
764 }
765 }
766 else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
767 {
768 volume *= 0.32475953f;
769 volume *= 0.01f * (float)(200 - _pbs.PathScaleX);
770 tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY);
771 volume *= (1.0f - tmp * tmp);
772
773 if (hollowAmount > 0.0)
774 {
775
776 hollowVolume *= hollowAmount;
777
778 switch (_pbs.HollowShape)
779 {
780 case HollowShape.Same:
781 case HollowShape.Triangle:
782 hollowVolume *= .25f;
783 break;
784
785 case HollowShape.Square:
786 hollowVolume *= 0.499849f * 3.07920140172638f;
787 break;
788
789 case HollowShape.Circle:
790
791 hollowVolume *= 0.1963495f * 3.07920140172638f;
792 break;
793
794 default:
795 hollowVolume = 0;
796 break;
797 }
798 volume *= (1.0f - hollowVolume);
799 }
800 }
801 break;
802
803 default:
804 break;
805 }
806
807 float taperX1;
808 float taperY1;
809 float taperX;
810 float taperY;
811 float pathBegin;
812 float pathEnd;
813 float profileBegin;
814 float profileEnd;
815
816 if (_pbs.PathCurve == (byte)Extrusion.Straight || _pbs.PathCurve == (byte)Extrusion.Flexible)
817 {
818 taperX1 = _pbs.PathScaleX * 0.01f;
819 if (taperX1 > 1.0f)
820 taperX1 = 2.0f - taperX1;
821 taperX = 1.0f - taperX1;
822
823 taperY1 = _pbs.PathScaleY * 0.01f;
824 if (taperY1 > 1.0f)
825 taperY1 = 2.0f - taperY1;
826 taperY = 1.0f - taperY1;
827 }
828 else
829 {
830 taperX = _pbs.PathTaperX * 0.01f;
831 if (taperX < 0.0f)
832 taperX = -taperX;
833 taperX1 = 1.0f - taperX;
834
835 taperY = _pbs.PathTaperY * 0.01f;
836 if (taperY < 0.0f)
837 taperY = -taperY;
838 taperY1 = 1.0f - taperY;
839 }
840
841 volume *= (taperX1 * taperY1 + 0.5f * (taperX1 * taperY + taperX * taperY1) + 0.3333333333f * taperX * taperY);
842
843 pathBegin = (float)_pbs.PathBegin * 2.0e-5f;
844 pathEnd = 1.0f - (float)_pbs.PathEnd * 2.0e-5f;
845 volume *= (pathEnd - pathBegin);
846
847 // this is crude aproximation
848 profileBegin = (float)_pbs.ProfileBegin * 2.0e-5f;
849 profileEnd = 1.0f - (float)_pbs.ProfileEnd * 2.0e-5f;
850 volume *= (profileEnd - profileBegin);
851
852 repData.volume = volume;
853 }
854
855 private void CalcVolumeData(ODEPhysRepData repData)
856 {
857 if (repData.hasOBB)
858 {
859 Vector3 OBB = repData.OBB;
860 }
861 else
862 {
863 Vector3 OBB = repData.size;
864 OBB.X *= 0.5f;
865 OBB.Y *= 0.5f;
866 OBB.Z *= 0.5f;
867
868 repData.OBB = OBB;
869 repData.OBBOffset = Vector3.Zero;
870 }
871
872 CalculateBasicPrimVolume(repData);
873 }
874 }
875
876 public class ODEAssetRequest
877 {
878 ODEMeshWorker m_worker;
879 private ILog m_log;
880 ODEPhysRepData repData;
881
882 public ODEAssetRequest(ODEMeshWorker pWorker, RequestAssetDelegate provider,
883 ODEPhysRepData pRepData, ILog plog)
884 {
885 m_worker = pWorker;
886 m_log = plog;
887 repData = pRepData;
888
889 repData.meshState = MeshState.AssetFailed;
890 if (provider == null)
891 return;
892
893 if (repData.assetID == null)
894 return;
895
896 UUID assetID = (UUID) repData.assetID;
897 if (assetID == UUID.Zero)
898 return;
899
900 repData.meshState = MeshState.loadingAsset;
901 provider(assetID, ODEassetReceived);
902 }
903
904 void ODEassetReceived(AssetBase asset)
905 {
906 repData.meshState = MeshState.AssetFailed;
907 if (asset != null)
908 {
909 if (asset.Data != null && asset.Data.Length > 0)
910 {
911 repData.meshState = MeshState.noNeed;
912
913 if (!repData.pbs.SculptEntry)
914 return;
915 if (repData.pbs.SculptTexture != repData.assetID)
916 return;
917
918// repData.pbs.SculptData = new byte[asset.Data.Length];
919// asset.Data.CopyTo(repData.pbs.SculptData,0);
920 repData.pbs.SculptData = asset.Data;
921 repData.meshState = MeshState.AssetOK;
922 m_worker.AssetLoaded(repData);
923 }
924 else
925 m_log.WarnFormat("[PHYSICS]: asset provider returned invalid mesh data for prim {0} asset UUID {1}.",
926 repData.actor.Name, asset.ID.ToString());
927 }
928 else
929 m_log.WarnFormat("[PHYSICS]: asset provider returned null asset fo mesh of prim {0}.",
930 repData.actor.Name);
931 }
932 }
933}
diff --git a/OpenSim/Region/PhysicsModules/ubOde/ODEModule.cs b/OpenSim/Region/PhysicsModules/ubOde/ODEModule.cs
new file mode 100644
index 0000000..bd66b4d
--- /dev/null
+++ b/OpenSim/Region/PhysicsModules/ubOde/ODEModule.cs
@@ -0,0 +1,97 @@
1using System;
2using System.Reflection;
3using log4net;
4using Nini.Config;
5using Mono.Addins;
6using OdeAPI;
7using OpenSim.Framework;
8using OpenSim.Region.Framework.Scenes;
9using OpenSim.Region.Framework.Interfaces;
10
11namespace OpenSim.Region.PhysicsModule.ubOde
12{
13 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "ubODEPhysicsScene")]
14 class ubOdeModule : INonSharedRegionModule
15 {
16 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
17
18 private bool m_Enabled = false;
19 private IConfigSource m_config;
20 private ODEScene m_scene;
21 private bool OSOdeLib;
22
23 #region INonSharedRegionModule
24
25 public string Name
26 {
27 get { return "ubODE"; }
28 }
29
30 public Type ReplaceableInterface
31 {
32 get { return null; }
33 }
34
35 public void Initialise(IConfigSource source)
36 {
37 IConfig config = source.Configs["Startup"];
38 if (config != null)
39 {
40 string physics = config.GetString("physics", string.Empty);
41 if (physics == Name)
42 {
43 m_config = source;
44 m_Enabled = true;
45 }
46 }
47 }
48
49 public void Close()
50 {
51 }
52
53 public void AddRegion(Scene scene)
54 {
55 if (!m_Enabled)
56 return;
57
58 if (Util.IsWindows())
59 Util.LoadArchSpecificWindowsDll("ode.dll");
60
61 // Initializing ODE only when a scene is created allows alternative ODE plugins to co-habit (according to
62 // http://opensimulator.org/mantis/view.php?id=2750).
63 d.InitODE();
64
65 string ode_config = d.GetConfiguration();
66 if (ode_config != null && ode_config != "")
67 {
68 m_log.InfoFormat("[ubODE] ode library configuration: {0}", ode_config);
69 // ubODE still not avaiable
70 if (ode_config.Contains("ODE_OPENSIM"))
71 {
72 OSOdeLib = true;
73 }
74 }
75
76 m_scene = new ODEScene(scene, m_config, Name, OSOdeLib);
77 }
78
79 public void RemoveRegion(Scene scene)
80 {
81 if (!m_Enabled || m_scene == null)
82 return;
83
84 m_scene.Dispose();
85 m_scene = null;
86 }
87
88 public void RegionLoaded(Scene scene)
89 {
90 if (!m_Enabled || m_scene == null)
91 return;
92
93 m_scene.RegionLoaded();
94 }
95 #endregion
96 }
97}
diff --git a/OpenSim/Region/PhysicsModules/ubOde/ODEPrim.cs b/OpenSim/Region/PhysicsModules/ubOde/ODEPrim.cs
new file mode 100644
index 0000000..1dbf164
--- /dev/null
+++ b/OpenSim/Region/PhysicsModules/ubOde/ODEPrim.cs
@@ -0,0 +1,3962 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28/*
29 * Revised August 26 2009 by Kitto Flora. ODEDynamics.cs replaces
30 * ODEVehicleSettings.cs. It and ODEPrim.cs are re-organised:
31 * ODEPrim.cs contains methods dealing with Prim editing, Prim
32 * characteristics and Kinetic motion.
33 * ODEDynamics.cs contains methods dealing with Prim Physical motion
34 * (dynamics) and the associated settings. Old Linear and angular
35 * motors for dynamic motion have been replace with MoveLinear()
36 * and MoveAngular(); 'Physical' is used only to switch ODE dynamic
37 * simualtion on/off; VEHICAL_TYPE_NONE/VEHICAL_TYPE_<other> is to
38 * switch between 'VEHICLE' parameter use and general dynamics
39 * settings use.
40 */
41
42//#define SPAM
43
44using System;
45using System.Collections.Generic;
46using System.Reflection;
47using System.Runtime.InteropServices;
48using System.Threading;
49using log4net;
50using OpenMetaverse;
51using OdeAPI;
52using OpenSim.Framework;
53using OpenSim.Region.PhysicsModules.SharedBase;
54
55namespace OpenSim.Region.PhysicsModule.ubOde
56{
57 public class OdePrim : PhysicsActor
58 {
59 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
60
61 private bool m_isphysical;
62 private bool m_fakeisphysical;
63 private bool m_isphantom;
64 private bool m_fakeisphantom;
65 internal bool m_isVolumeDetect; // If true, this prim only detects collisions but doesn't collide actively
66 private bool m_fakeisVolumeDetect; // If true, this prim only detects collisions but doesn't collide actively
67
68 protected bool m_building;
69 protected bool m_forcePosOrRotation;
70 private bool m_iscolliding;
71
72 internal bool m_isSelected;
73 private bool m_delaySelect;
74 private bool m_lastdoneSelected;
75 internal bool m_outbounds;
76
77 private byte m_angularlocks = 0;
78
79 private Quaternion m_lastorientation;
80 private Quaternion _orientation;
81
82 private Vector3 _position;
83 private Vector3 _velocity;
84 private Vector3 m_torque;
85 private Vector3 m_lastVelocity;
86 private Vector3 m_lastposition;
87 private Vector3 m_rotationalVelocity;
88 private Vector3 _size;
89 private Vector3 _acceleration;
90 private IntPtr Amotor;
91
92 private Vector3 m_force;
93 private Vector3 m_forceacc;
94 private Vector3 m_angularForceacc;
95
96 private float m_invTimeStep;
97 private float m_timeStep;
98
99 private Vector3 m_PIDTarget;
100 private float m_PIDTau;
101 private bool m_usePID;
102
103 private float m_PIDHoverHeight;
104 private float m_PIDHoverTau;
105 private bool m_useHoverPID;
106 private PIDHoverType m_PIDHoverType;
107 private float m_targetHoverHeight;
108 private float m_groundHeight;
109 private float m_waterHeight;
110 private float m_buoyancy; //KF: m_buoyancy should be set by llSetBuoyancy() for non-vehicle.
111
112 private int body_autodisable_frames;
113 public int bodydisablecontrol = 0;
114 private float m_gravmod = 1.0f;
115
116 // Default we're a Geometry
117 private CollisionCategories m_collisionCategories = (CollisionCategories.Geom);
118 // Default colide nonphysical don't try to colide with anything
119 private const CollisionCategories m_default_collisionFlagsNotPhysical = 0;
120
121 private const CollisionCategories m_default_collisionFlagsPhysical = (CollisionCategories.Geom |
122 CollisionCategories.Character |
123 CollisionCategories.Land |
124 CollisionCategories.VolumeDtc);
125
126// private bool m_collidesLand = true;
127 private bool m_collidesWater;
128// public bool m_returnCollisions;
129
130 private bool m_NoColide; // for now only for internal use for bad meshs
131
132
133 // Default, Collide with Other Geometries, spaces and Bodies
134 private CollisionCategories m_collisionFlags = m_default_collisionFlagsNotPhysical;
135
136 public bool m_disabled;
137
138 private uint m_localID;
139
140 private IMesh m_mesh;
141 private object m_meshlock = new object();
142 private PrimitiveBaseShape _pbs;
143
144 private UUID? m_assetID;
145 private MeshState m_meshState;
146
147 public ODEScene _parent_scene;
148
149 /// <summary>
150 /// The physics space which contains prim geometry
151 /// </summary>
152 public IntPtr m_targetSpace;
153
154 public IntPtr prim_geom;
155 public IntPtr _triMeshData;
156
157 private PhysicsActor _parent;
158
159 private List<OdePrim> childrenPrim = new List<OdePrim>();
160
161 public float m_collisionscore;
162 private int m_colliderfilter = 0;
163
164 public IntPtr collide_geom; // for objects: geom if single prim space it linkset
165
166 private float m_density;
167 private byte m_shapetype;
168 public bool _zeroFlag;
169 private bool m_lastUpdateSent;
170
171 public IntPtr Body;
172
173 private Vector3 _target_velocity;
174
175 public Vector3 m_OBBOffset;
176 public Vector3 m_OBB;
177 public float primOOBradiusSQ;
178
179 private bool m_hasOBB = true;
180
181 private float m_physCost;
182 private float m_streamCost;
183
184 public d.Mass primdMass; // prim inertia information on it's own referencial
185 float primMass; // prim own mass
186 float primVolume; // prim own volume;
187 float _mass; // object mass acording to case
188
189 public int givefakepos;
190 private Vector3 fakepos;
191 public int givefakeori;
192 private Quaternion fakeori;
193
194 private int m_eventsubscription;
195 private int m_cureventsubscription;
196 private CollisionEventUpdate CollisionEventsThisFrame = null;
197 private bool SentEmptyCollisionsEvent;
198
199 public volatile bool childPrim;
200
201 public ODEDynamics m_vehicle;
202
203 internal int m_material = (int)Material.Wood;
204 private float mu;
205 private float bounce;
206
207 /// <summary>
208 /// Is this prim subject to physics? Even if not, it's still solid for collision purposes.
209 /// </summary>
210 public override bool IsPhysical // this is not reliable for internal use
211 {
212 get { return m_fakeisphysical; }
213 set
214 {
215 m_fakeisphysical = value; // we show imediatly to outside that we changed physical
216 // and also to stop imediatly some updates
217 // but real change will only happen in taintprocessing
218
219 if (!value) // Zero the remembered last velocity
220 m_lastVelocity = Vector3.Zero;
221 AddChange(changes.Physical, value);
222 }
223 }
224
225 public override bool IsVolumeDtc
226 {
227 get { return m_fakeisVolumeDetect; }
228 set
229 {
230 m_fakeisVolumeDetect = value;
231 AddChange(changes.VolumeDtc, value);
232 }
233 }
234
235 public override bool Phantom // this is not reliable for internal use
236 {
237 get { return m_fakeisphantom; }
238 set
239 {
240 m_fakeisphantom = value;
241 AddChange(changes.Phantom, value);
242 }
243 }
244
245 public override bool Building // this is not reliable for internal use
246 {
247 get { return m_building; }
248 set
249 {
250// if (value)
251// m_building = true;
252 AddChange(changes.building, value);
253 }
254 }
255
256 public override void getContactData(ref ContactData cdata)
257 {
258 cdata.mu = mu;
259 cdata.bounce = bounce;
260
261 // cdata.softcolide = m_softcolide;
262 cdata.softcolide = false;
263
264 if (m_isphysical)
265 {
266 ODEDynamics veh;
267 if (_parent != null)
268 veh = ((OdePrim)_parent).m_vehicle;
269 else
270 veh = m_vehicle;
271
272 if (veh != null && veh.Type != Vehicle.TYPE_NONE)
273 cdata.mu *= veh.FrictionFactor;
274// cdata.mu *= 0;
275 }
276 }
277
278 public override float PhysicsCost
279 {
280 get
281 {
282 return m_physCost;
283 }
284 }
285
286 public override float StreamCost
287 {
288 get
289 {
290 return m_streamCost;
291 }
292 }
293
294 public override int PhysicsActorType
295 {
296 get { return (int)ActorTypes.Prim; }
297 set { return; }
298 }
299
300 public override bool SetAlwaysRun
301 {
302 get { return false; }
303 set { return; }
304 }
305
306 public override uint LocalID
307 {
308 get { return m_localID; }
309 set { m_localID = value; }
310 }
311
312 public override PhysicsActor ParentActor
313 {
314 get
315 {
316 if (childPrim)
317 return _parent;
318 else
319 return (PhysicsActor)this;
320 }
321 }
322
323 public override bool Grabbed
324 {
325 set { return; }
326 }
327
328 public override bool Selected
329 {
330 set
331 {
332 if (value)
333 m_isSelected = value; // if true set imediatly to stop moves etc
334 AddChange(changes.Selected, value);
335 }
336 }
337
338 public override bool Flying
339 {
340 // no flying prims for you
341 get { return false; }
342 set { }
343 }
344
345 public override bool IsColliding
346 {
347 get { return m_iscolliding; }
348 set
349 {
350 if (value)
351 {
352 m_colliderfilter += 2;
353 if (m_colliderfilter > 2)
354 m_colliderfilter = 2;
355 }
356 else
357 {
358 m_colliderfilter--;
359 if (m_colliderfilter < 0)
360 m_colliderfilter = 0;
361 }
362
363 if (m_colliderfilter == 0)
364 m_iscolliding = false;
365 else
366 m_iscolliding = true;
367 }
368 }
369
370 public override bool CollidingGround
371 {
372 get { return false; }
373 set { return; }
374 }
375
376 public override bool CollidingObj
377 {
378 get { return false; }
379 set { return; }
380 }
381
382
383 public override bool ThrottleUpdates {get;set;}
384
385 public override bool Stopped
386 {
387 get { return _zeroFlag; }
388 }
389
390 public override Vector3 Position
391 {
392 get
393 {
394 if (givefakepos > 0)
395 return fakepos;
396 else
397 return _position;
398 }
399
400 set
401 {
402 fakepos = value;
403 givefakepos++;
404 AddChange(changes.Position, value);
405 }
406 }
407
408 public override Vector3 Size
409 {
410 get { return _size; }
411 set
412 {
413 if (value.IsFinite())
414 {
415 _parent_scene.m_meshWorker.ChangeActorPhysRep(this, _pbs, value, m_shapetype);
416 }
417 else
418 {
419 m_log.WarnFormat("[PHYSICS]: Got NaN Size on object {0}", Name);
420 }
421 }
422 }
423
424 public override float Mass
425 {
426 get { return primMass; }
427 }
428
429 public override Vector3 Force
430 {
431 get { return m_force; }
432 set
433 {
434 if (value.IsFinite())
435 {
436 AddChange(changes.Force, value);
437 }
438 else
439 {
440 m_log.WarnFormat("[PHYSICS]: NaN in Force Applied to an Object {0}", Name);
441 }
442 }
443 }
444
445 public override void SetVolumeDetect(int param)
446 {
447 m_fakeisVolumeDetect = (param != 0);
448 AddChange(changes.VolumeDtc, m_fakeisVolumeDetect);
449 }
450
451 public override Vector3 GeometricCenter
452 {
453 // this is not real geometric center but a average of positions relative to root prim acording to
454 // http://wiki.secondlife.com/wiki/llGetGeometricCenter
455 // ignoring tortured prims details since sl also seems to ignore
456 // so no real use in doing it on physics
457 get
458 {
459 return Vector3.Zero;
460 }
461 }
462
463 public override Vector3 CenterOfMass
464 {
465 get
466 {
467 lock (_parent_scene.OdeLock)
468 {
469 d.Vector3 dtmp;
470 if (!childPrim && Body != IntPtr.Zero)
471 {
472 dtmp = d.BodyGetPosition(Body);
473 return new Vector3(dtmp.X, dtmp.Y, dtmp.Z);
474 }
475 else if (prim_geom != IntPtr.Zero)
476 {
477 d.Quaternion dq;
478 d.GeomCopyQuaternion(prim_geom, out dq);
479 Quaternion q;
480 q.X = dq.X;
481 q.Y = dq.Y;
482 q.Z = dq.Z;
483 q.W = dq.W;
484
485 Vector3 Ptot = m_OBBOffset * q;
486 dtmp = d.GeomGetPosition(prim_geom);
487 Ptot.X += dtmp.X;
488 Ptot.Y += dtmp.Y;
489 Ptot.Z += dtmp.Z;
490
491 // if(childPrim) we only know about physical linksets
492 return Ptot;
493/*
494 float tmass = _mass;
495 Ptot *= tmass;
496
497 float m;
498
499 foreach (OdePrim prm in childrenPrim)
500 {
501 m = prm._mass;
502 Ptot += prm.CenterOfMass * m;
503 tmass += m;
504 }
505
506 if (tmass == 0)
507 tmass = 0;
508 else
509 tmass = 1.0f / tmass;
510
511 Ptot *= tmass;
512 return Ptot;
513*/
514 }
515 else
516 return _position;
517 }
518 }
519 }
520
521 public override Vector3 OOBsize
522 {
523 get
524 {
525 return m_OBB;
526 }
527 }
528
529 public override Vector3 OOBoffset
530 {
531 get
532 {
533 return m_OBBOffset;
534 }
535 }
536
537 public override float OOBRadiusSQ
538 {
539 get
540 {
541 return primOOBradiusSQ;
542 }
543 }
544
545 public override PrimitiveBaseShape Shape
546 {
547 set
548 {
549// AddChange(changes.Shape, value);
550 _parent_scene.m_meshWorker.ChangeActorPhysRep(this, value, _size, m_shapetype);
551 }
552 }
553
554 public override byte PhysicsShapeType
555 {
556 get
557 {
558 return m_shapetype;
559 }
560 set
561 {
562 m_shapetype = value;
563 _parent_scene.m_meshWorker.ChangeActorPhysRep(this, _pbs, _size, value);
564 }
565 }
566
567 public override Vector3 Velocity
568 {
569 get
570 {
571 if (_zeroFlag)
572 return Vector3.Zero;
573 return _velocity;
574 }
575 set
576 {
577 if (value.IsFinite())
578 {
579 AddChange(changes.Velocity, value);
580 }
581 else
582 {
583 m_log.WarnFormat("[PHYSICS]: Got NaN Velocity in Object {0}", Name);
584 }
585
586 }
587 }
588
589 public override Vector3 Torque
590 {
591 get
592 {
593 if (!IsPhysical || Body == IntPtr.Zero)
594 return Vector3.Zero;
595
596 return m_torque;
597 }
598
599 set
600 {
601 if (value.IsFinite())
602 {
603 AddChange(changes.Torque, value);
604 }
605 else
606 {
607 m_log.WarnFormat("[PHYSICS]: Got NaN Torque in Object {0}", Name);
608 }
609 }
610 }
611
612 public override float CollisionScore
613 {
614 get { return m_collisionscore; }
615 set { m_collisionscore = value; }
616 }
617
618 public override bool Kinematic
619 {
620 get { return false; }
621 set { }
622 }
623
624 public override Quaternion Orientation
625 {
626 get
627 {
628 if (givefakeori > 0)
629 return fakeori;
630 else
631
632 return _orientation;
633 }
634 set
635 {
636 if (QuaternionIsFinite(value))
637 {
638 fakeori = value;
639 givefakeori++;
640
641 value.Normalize();
642
643 AddChange(changes.Orientation, value);
644 }
645 else
646 m_log.WarnFormat("[PHYSICS]: Got NaN quaternion Orientation from Scene in Object {0}", Name);
647
648 }
649 }
650
651 public override Vector3 Acceleration
652 {
653 get { return _acceleration; }
654 set { }
655 }
656
657 public override Vector3 RotationalVelocity
658 {
659 get
660 {
661 Vector3 pv = Vector3.Zero;
662 if (_zeroFlag)
663 return pv;
664
665 if (m_rotationalVelocity.ApproxEquals(pv, 0.0001f))
666 return pv;
667
668 return m_rotationalVelocity;
669 }
670 set
671 {
672 if (value.IsFinite())
673 {
674 AddChange(changes.AngVelocity, value);
675 }
676 else
677 {
678 m_log.WarnFormat("[PHYSICS]: Got NaN RotationalVelocity in Object {0}", Name);
679 }
680 }
681 }
682
683 public override float Buoyancy
684 {
685 get { return m_buoyancy; }
686 set
687 {
688 AddChange(changes.Buoyancy,value);
689 }
690 }
691
692 public override bool FloatOnWater
693 {
694 set
695 {
696 AddChange(changes.CollidesWater, value);
697 }
698 }
699
700 public override Vector3 PIDTarget
701 {
702 set
703 {
704 if (value.IsFinite())
705 {
706 AddChange(changes.PIDTarget,value);
707 }
708 else
709 m_log.WarnFormat("[PHYSICS]: Got NaN PIDTarget from Scene on Object {0}", Name);
710 }
711 }
712
713 public override bool PIDActive
714 {
715 get
716 {
717 return m_usePID;
718 }
719 set
720 {
721 AddChange(changes.PIDActive,value);
722 }
723 }
724
725 public override float PIDTau
726 {
727 set
728 {
729 float tmp = 0;
730 if (value > 0)
731 {
732 float mint = (0.05f > m_timeStep ? 0.05f : m_timeStep);
733 if (value < mint)
734 tmp = mint;
735 else
736 tmp = value;
737 }
738 AddChange(changes.PIDTau,tmp);
739 }
740 }
741
742 public override float PIDHoverHeight
743 {
744 set
745 {
746 AddChange(changes.PIDHoverHeight,value);
747 }
748 }
749 public override bool PIDHoverActive
750 {
751 get
752 {
753 return m_useHoverPID;
754 }
755 set
756 {
757 AddChange(changes.PIDHoverActive, value);
758 }
759 }
760
761 public override PIDHoverType PIDHoverType
762 {
763 set
764 {
765 AddChange(changes.PIDHoverType,value);
766 }
767 }
768
769 public override float PIDHoverTau
770 {
771 set
772 {
773 float tmp =0;
774 if (value > 0)
775 {
776 float mint = (0.05f > m_timeStep ? 0.05f : m_timeStep);
777 if (value < mint)
778 tmp = mint;
779 else
780 tmp = value;
781 }
782 AddChange(changes.PIDHoverTau, tmp);
783 }
784 }
785
786 public override Quaternion APIDTarget { set { return; } }
787
788 public override bool APIDActive { set { return; } }
789
790 public override float APIDStrength { set { return; } }
791
792 public override float APIDDamping { set { return; } }
793
794 public override int VehicleType
795 {
796 // we may need to put a fake on this
797 get
798 {
799 if (m_vehicle == null)
800 return (int)Vehicle.TYPE_NONE;
801 else
802 return (int)m_vehicle.Type;
803 }
804 set
805 {
806 AddChange(changes.VehicleType, value);
807 }
808 }
809
810 public override void VehicleFloatParam(int param, float value)
811 {
812 strVehicleFloatParam fp = new strVehicleFloatParam();
813 fp.param = param;
814 fp.value = value;
815 AddChange(changes.VehicleFloatParam, fp);
816 }
817
818 public override void VehicleVectorParam(int param, Vector3 value)
819 {
820 strVehicleVectorParam fp = new strVehicleVectorParam();
821 fp.param = param;
822 fp.value = value;
823 AddChange(changes.VehicleVectorParam, fp);
824 }
825
826 public override void VehicleRotationParam(int param, Quaternion value)
827 {
828 strVehicleQuatParam fp = new strVehicleQuatParam();
829 fp.param = param;
830 fp.value = value;
831 AddChange(changes.VehicleRotationParam, fp);
832 }
833
834 public override void VehicleFlags(int param, bool value)
835 {
836 strVehicleBoolParam bp = new strVehicleBoolParam();
837 bp.param = param;
838 bp.value = value;
839 AddChange(changes.VehicleFlags, bp);
840 }
841
842 public override void SetVehicle(object vdata)
843 {
844 AddChange(changes.SetVehicle, vdata);
845 }
846 public void SetAcceleration(Vector3 accel)
847 {
848 _acceleration = accel;
849 }
850
851 public override void AddForce(Vector3 force, bool pushforce)
852 {
853 if (force.IsFinite())
854 {
855 if(pushforce)
856 AddChange(changes.AddForce, force);
857 else // a impulse
858 AddChange(changes.AddForce, force * m_invTimeStep);
859 }
860 else
861 {
862 m_log.WarnFormat("[PHYSICS]: Got Invalid linear force vector from Scene in Object {0}", Name);
863 }
864 //m_log.Info("[PHYSICS]: Added Force:" + force.ToString() + " to prim at " + Position.ToString());
865 }
866
867 public override void AddAngularForce(Vector3 force, bool pushforce)
868 {
869 if (force.IsFinite())
870 {
871// if(pushforce) for now applyrotationimpulse seems more happy applied as a force
872 AddChange(changes.AddAngForce, force);
873// else // a impulse
874// AddChange(changes.AddAngForce, force * m_invTimeStep);
875 }
876 else
877 {
878 m_log.WarnFormat("[PHYSICS]: Got Invalid Angular force vector from Scene in Object {0}", Name);
879 }
880 }
881
882 public override void CrossingFailure()
883 {
884 if (m_outbounds)
885 {
886 _position.X = Util.Clip(_position.X, 0.5f, _parent_scene.WorldExtents.X - 0.5f);
887 _position.Y = Util.Clip(_position.Y, 0.5f, _parent_scene.WorldExtents.Y - 0.5f);
888 _position.Z = Util.Clip(_position.Z + 0.2f, -100f, 50000f);
889
890 m_lastposition = _position;
891 _velocity.X = 0;
892 _velocity.Y = 0;
893 _velocity.Z = 0;
894
895 m_lastVelocity = _velocity;
896 if (m_vehicle != null && m_vehicle.Type != Vehicle.TYPE_NONE)
897 m_vehicle.Stop();
898
899 if(Body != IntPtr.Zero)
900 d.BodySetLinearVel(Body, 0, 0, 0); // stop it
901 if (prim_geom != IntPtr.Zero)
902 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
903
904 m_outbounds = false;
905 changeDisable(false);
906 base.RequestPhysicsterseUpdate();
907 }
908 }
909
910 public override void SetMomentum(Vector3 momentum)
911 {
912 }
913
914 public override void SetMaterial(int pMaterial)
915 {
916 m_material = pMaterial;
917 mu = _parent_scene.m_materialContactsData[pMaterial].mu;
918 bounce = _parent_scene.m_materialContactsData[pMaterial].bounce;
919 }
920
921 public override float Density
922 {
923 get
924 {
925 return m_density * 100f;
926 }
927 set
928 {
929 m_density = value / 100f;
930 // for not prim mass is not updated since this implies full rebuild of body inertia TODO
931 }
932 }
933 public override float GravModifier
934 {
935 get
936 {
937 return m_gravmod;
938 }
939 set
940 {
941 m_gravmod = value;
942 if (m_vehicle != null)
943 m_vehicle.GravMod = m_gravmod;
944 }
945 }
946 public override float Friction
947 {
948 get
949 {
950 return mu;
951 }
952 set
953 {
954 mu = value;
955 }
956 }
957
958 public override float Restitution
959 {
960 get
961 {
962 return bounce;
963 }
964 set
965 {
966 bounce = value;
967 }
968 }
969
970 public void setPrimForRemoval()
971 {
972 AddChange(changes.Remove, null);
973 }
974
975 public override void link(PhysicsActor obj)
976 {
977 AddChange(changes.Link, obj);
978 }
979
980 public override void delink()
981 {
982 AddChange(changes.DeLink, null);
983 }
984
985 public override void LockAngularMotion(byte axislock)
986 {
987// m_log.DebugFormat("[axislock]: <{0},{1},{2}>", axis.X, axis.Y, axis.Z);
988 AddChange(changes.AngLock, axislock);
989
990 }
991
992 public override void SubscribeEvents(int ms)
993 {
994 m_eventsubscription = ms;
995 m_cureventsubscription = 0;
996 if (CollisionEventsThisFrame == null)
997 CollisionEventsThisFrame = new CollisionEventUpdate();
998 SentEmptyCollisionsEvent = false;
999 }
1000
1001 public override void UnSubscribeEvents()
1002 {
1003 if (CollisionEventsThisFrame != null)
1004 {
1005 CollisionEventsThisFrame.Clear();
1006 CollisionEventsThisFrame = null;
1007 }
1008 m_eventsubscription = 0;
1009 _parent_scene.RemoveCollisionEventReporting(this);
1010 }
1011
1012 public override void AddCollisionEvent(uint CollidedWith, ContactPoint contact)
1013 {
1014 if (CollisionEventsThisFrame == null)
1015 CollisionEventsThisFrame = new CollisionEventUpdate();
1016// if(CollisionEventsThisFrame.Count < 32)
1017 CollisionEventsThisFrame.AddCollider(CollidedWith, contact);
1018 }
1019
1020 public void SendCollisions()
1021 {
1022 if (CollisionEventsThisFrame == null)
1023 return;
1024
1025 if (m_cureventsubscription < m_eventsubscription)
1026 return;
1027
1028 m_cureventsubscription = 0;
1029
1030 int ncolisions = CollisionEventsThisFrame.m_objCollisionList.Count;
1031
1032 if (!SentEmptyCollisionsEvent || ncolisions > 0)
1033 {
1034 base.SendCollisionUpdate(CollisionEventsThisFrame);
1035
1036 if (ncolisions == 0)
1037 {
1038 SentEmptyCollisionsEvent = true;
1039 _parent_scene.RemoveCollisionEventReporting(this);
1040 }
1041 else
1042 {
1043 SentEmptyCollisionsEvent = false;
1044 CollisionEventsThisFrame.Clear();
1045 }
1046 }
1047 }
1048
1049 internal void AddCollisionFrameTime(int t)
1050 {
1051 if (m_cureventsubscription < 50000)
1052 m_cureventsubscription += t;
1053 }
1054
1055 public override bool SubscribedEvents()
1056 {
1057 if (m_eventsubscription > 0)
1058 return true;
1059 return false;
1060 }
1061
1062 public OdePrim(String primName, ODEScene parent_scene, Vector3 pos, Vector3 size,
1063 Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical,bool pisPhantom,byte _shapeType,uint plocalID)
1064 {
1065 Name = primName;
1066 LocalID = plocalID;
1067
1068 m_vehicle = null;
1069
1070 if (!pos.IsFinite())
1071 {
1072 pos = new Vector3(((float)Constants.RegionSize * 0.5f), ((float)Constants.RegionSize * 0.5f),
1073 parent_scene.GetTerrainHeightAtXY(((float)Constants.RegionSize * 0.5f), ((float)Constants.RegionSize * 0.5f)) + 0.5f);
1074 m_log.WarnFormat("[PHYSICS]: Got nonFinite Object create Position for {0}", Name);
1075 }
1076 _position = pos;
1077 givefakepos = 0;
1078
1079 m_timeStep = parent_scene.ODE_STEPSIZE;
1080 m_invTimeStep = 1f / m_timeStep;
1081
1082 m_density = parent_scene.geomDefaultDensity;
1083 body_autodisable_frames = parent_scene.bodyFramesAutoDisable;
1084
1085 prim_geom = IntPtr.Zero;
1086 collide_geom = IntPtr.Zero;
1087 Body = IntPtr.Zero;
1088
1089 if (!size.IsFinite())
1090 {
1091 size = new Vector3(0.5f, 0.5f, 0.5f);
1092 m_log.WarnFormat("[PHYSICS]: Got nonFinite Object create Size for {0}", Name);
1093 }
1094
1095 if (size.X <= 0) size.X = 0.01f;
1096 if (size.Y <= 0) size.Y = 0.01f;
1097 if (size.Z <= 0) size.Z = 0.01f;
1098
1099 _size = size;
1100
1101 if (!QuaternionIsFinite(rotation))
1102 {
1103 rotation = Quaternion.Identity;
1104 m_log.WarnFormat("[PHYSICS]: Got nonFinite Object create Rotation for {0}", Name);
1105 }
1106
1107 _orientation = rotation;
1108 givefakeori = 0;
1109
1110 _pbs = pbs;
1111
1112 _parent_scene = parent_scene;
1113 m_targetSpace = IntPtr.Zero;
1114
1115 if (pos.Z < 0)
1116 {
1117 m_isphysical = false;
1118 }
1119 else
1120 {
1121 m_isphysical = pisPhysical;
1122 }
1123 m_fakeisphysical = m_isphysical;
1124
1125 m_isVolumeDetect = false;
1126 m_fakeisVolumeDetect = false;
1127
1128 m_force = Vector3.Zero;
1129
1130 m_iscolliding = false;
1131 m_colliderfilter = 0;
1132 m_NoColide = false;
1133
1134 _triMeshData = IntPtr.Zero;
1135
1136 m_shapetype = _shapeType;
1137
1138 m_lastdoneSelected = false;
1139 m_isSelected = false;
1140 m_delaySelect = false;
1141
1142 m_isphantom = pisPhantom;
1143 m_fakeisphantom = pisPhantom;
1144
1145 mu = parent_scene.m_materialContactsData[(int)Material.Wood].mu;
1146 bounce = parent_scene.m_materialContactsData[(int)Material.Wood].bounce;
1147
1148 m_building = true; // control must set this to false when done
1149
1150 // get basic mass parameters
1151 ODEPhysRepData repData = _parent_scene.m_meshWorker.NewActorPhysRep(this, _pbs, _size, m_shapetype);
1152
1153 primVolume = repData.volume;
1154 m_OBB = repData.OBB;
1155 m_OBBOffset = repData.OBBOffset;
1156
1157 UpdatePrimBodyData();
1158 }
1159
1160 private void resetCollisionAccounting()
1161 {
1162 m_collisionscore = 0;
1163 }
1164
1165 private void UpdateCollisionCatFlags()
1166 {
1167 if(m_isphysical && m_disabled)
1168 {
1169 m_collisionCategories = 0;
1170 m_collisionFlags = 0;
1171 }
1172
1173 else if (m_isSelected)
1174 {
1175 m_collisionCategories = CollisionCategories.Selected;
1176 m_collisionFlags = 0;
1177 }
1178
1179 else if (m_isVolumeDetect)
1180 {
1181 m_collisionCategories = CollisionCategories.VolumeDtc;
1182 if (m_isphysical)
1183 m_collisionFlags = CollisionCategories.Geom | CollisionCategories.Character;
1184 else
1185 m_collisionFlags = 0;
1186 }
1187 else if (m_isphantom)
1188 {
1189 m_collisionCategories = CollisionCategories.Phantom;
1190 if (m_isphysical)
1191 m_collisionFlags = CollisionCategories.Land;
1192 else
1193 m_collisionFlags = 0;
1194 }
1195 else
1196 {
1197 m_collisionCategories = CollisionCategories.Geom;
1198 if (m_isphysical)
1199 m_collisionFlags = m_default_collisionFlagsPhysical;
1200 else
1201 m_collisionFlags = m_default_collisionFlagsNotPhysical;
1202 }
1203 }
1204
1205 private void ApplyCollisionCatFlags()
1206 {
1207 if (prim_geom != IntPtr.Zero)
1208 {
1209 if (!childPrim && childrenPrim.Count > 0)
1210 {
1211 foreach (OdePrim prm in childrenPrim)
1212 {
1213 if (m_isphysical && m_disabled)
1214 {
1215 prm.m_collisionCategories = 0;
1216 prm.m_collisionFlags = 0;
1217 }
1218 else
1219 {
1220 // preserve some
1221 if (prm.m_isSelected)
1222 {
1223 prm.m_collisionCategories = CollisionCategories.Selected;
1224 prm.m_collisionFlags = 0;
1225 }
1226 else if (prm.m_isVolumeDetect)
1227 {
1228 prm.m_collisionCategories = CollisionCategories.VolumeDtc;
1229 if (m_isphysical)
1230 prm.m_collisionFlags = CollisionCategories.Geom | CollisionCategories.Character;
1231 else
1232 prm.m_collisionFlags = 0;
1233 }
1234 else if (prm.m_isphantom)
1235 {
1236 prm.m_collisionCategories = CollisionCategories.Phantom;
1237 if (m_isphysical)
1238 prm.m_collisionFlags = CollisionCategories.Land;
1239 else
1240 prm.m_collisionFlags = 0;
1241 }
1242 else
1243 {
1244 prm.m_collisionCategories = m_collisionCategories;
1245 prm.m_collisionFlags = m_collisionFlags;
1246 }
1247 }
1248
1249 if (prm.prim_geom != IntPtr.Zero)
1250 {
1251 if (prm.m_NoColide)
1252 {
1253 d.GeomSetCategoryBits(prm.prim_geom, 0);
1254 if (m_isphysical)
1255 d.GeomSetCollideBits(prm.prim_geom, (int)CollisionCategories.Land);
1256 else
1257 d.GeomSetCollideBits(prm.prim_geom, 0);
1258 }
1259 else
1260 {
1261 d.GeomSetCategoryBits(prm.prim_geom, (uint)prm.m_collisionCategories);
1262 d.GeomSetCollideBits(prm.prim_geom, (uint)prm.m_collisionFlags);
1263 }
1264 }
1265 }
1266 }
1267
1268 if (m_NoColide)
1269 {
1270 d.GeomSetCategoryBits(prim_geom, 0);
1271 d.GeomSetCollideBits(prim_geom, (uint)CollisionCategories.Land);
1272 if (collide_geom != prim_geom && collide_geom != IntPtr.Zero)
1273 {
1274 d.GeomSetCategoryBits(collide_geom, 0);
1275 d.GeomSetCollideBits(collide_geom, (uint)CollisionCategories.Land);
1276 }
1277 }
1278 else
1279 {
1280 d.GeomSetCategoryBits(prim_geom, (uint)m_collisionCategories);
1281 d.GeomSetCollideBits(prim_geom, (uint)m_collisionFlags);
1282 if (collide_geom != prim_geom && collide_geom != IntPtr.Zero)
1283 {
1284 d.GeomSetCategoryBits(collide_geom, (uint)m_collisionCategories);
1285 d.GeomSetCollideBits(collide_geom, (uint)m_collisionFlags);
1286 }
1287 }
1288 }
1289 }
1290
1291 private void createAMotor(byte axislock)
1292 {
1293 if (Body == IntPtr.Zero)
1294 return;
1295
1296 if (Amotor != IntPtr.Zero)
1297 {
1298 d.JointDestroy(Amotor);
1299 Amotor = IntPtr.Zero;
1300 }
1301
1302 int axisnum = 0;
1303 bool axisX = false;
1304 bool axisY = false;
1305 bool axisZ = false;
1306 if((axislock & 0x02) != 0)
1307 {
1308 axisnum++;
1309 axisX = true;
1310 }
1311 if((axislock & 0x04) != 0)
1312 {
1313 axisnum++;
1314 axisY = true;
1315 }
1316 if((axislock & 0x08) != 0)
1317 {
1318 axisnum++;
1319 axisZ = true;
1320 }
1321
1322 if(axisnum == 0)
1323 return;
1324 // stop it
1325 d.BodySetTorque(Body, 0, 0, 0);
1326 d.BodySetAngularVel(Body, 0, 0, 0);
1327
1328 Amotor = d.JointCreateAMotor(_parent_scene.world, IntPtr.Zero);
1329 d.JointAttach(Amotor, Body, IntPtr.Zero);
1330
1331 d.JointSetAMotorMode(Amotor, 0);
1332
1333 d.JointSetAMotorNumAxes(Amotor, axisnum);
1334
1335 // get current orientation to lock
1336
1337 d.Quaternion dcur = d.BodyGetQuaternion(Body);
1338 Quaternion curr; // crap convertion between identical things
1339 curr.X = dcur.X;
1340 curr.Y = dcur.Y;
1341 curr.Z = dcur.Z;
1342 curr.W = dcur.W;
1343 Vector3 ax;
1344
1345 int i = 0;
1346 int j = 0;
1347 if (axisX)
1348 {
1349 ax = (new Vector3(1, 0, 0)) * curr; // rotate world X to current local X
1350 d.JointSetAMotorAxis(Amotor, 0, 0, ax.X, ax.Y, ax.Z);
1351 d.JointSetAMotorAngle(Amotor, 0, 0);
1352 d.JointSetAMotorParam(Amotor, (int)d.JointParam.LoStop, 0f);
1353 d.JointSetAMotorParam(Amotor, (int)d.JointParam.HiStop, 0f);
1354 d.JointSetAMotorParam(Amotor, (int)d.JointParam.Vel, 0);
1355 d.JointSetAMotorParam(Amotor, (int)d.JointParam.FudgeFactor, 0.0001f);
1356 d.JointSetAMotorParam(Amotor, (int)d.JointParam.Bounce, 0f);
1357 d.JointSetAMotorParam(Amotor, (int)d.JointParam.CFM, 0f);
1358 d.JointSetAMotorParam(Amotor, (int)d.JointParam.FMax, 5e8f);
1359 d.JointSetAMotorParam(Amotor, (int)d.JointParam.StopCFM, 0f);
1360 d.JointSetAMotorParam(Amotor, (int)d.JointParam.StopERP, 0.8f);
1361 i++;
1362 j = 256; // move to next axis set
1363 }
1364
1365 if (axisY)
1366 {
1367 ax = (new Vector3(0, 1, 0)) * curr;
1368 d.JointSetAMotorAxis(Amotor, i, 0, ax.X, ax.Y, ax.Z);
1369 d.JointSetAMotorAngle(Amotor, i, 0);
1370 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.LoStop, 0f);
1371 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.HiStop, 0f);
1372 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.Vel, 0);
1373 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.FudgeFactor, 0.0001f);
1374 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.Bounce, 0f);
1375 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.CFM, 0f);
1376 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.FMax, 5e8f);
1377 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.StopCFM, 0f);
1378 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.StopERP, 0.8f);
1379 i++;
1380 j += 256;
1381 }
1382
1383 if (axisZ)
1384 {
1385 ax = (new Vector3(0, 0, 1)) * curr;
1386 d.JointSetAMotorAxis(Amotor, i, 0, ax.X, ax.Y, ax.Z);
1387 d.JointSetAMotorAngle(Amotor, i, 0);
1388 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.LoStop, 0f);
1389 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.HiStop, 0f);
1390 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.Vel, 0);
1391 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.FudgeFactor, 0.0001f);
1392 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.Bounce, 0f);
1393 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.CFM, 0f);
1394 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.FMax, 5e8f);
1395 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.StopCFM, 0f);
1396 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.StopERP, 0.8f);
1397 }
1398 }
1399
1400
1401 private void SetGeom(IntPtr geom)
1402 {
1403 prim_geom = geom;
1404 //Console.WriteLine("SetGeom to " + prim_geom + " for " + Name);
1405 if (prim_geom != IntPtr.Zero)
1406 {
1407
1408 if (m_NoColide)
1409 {
1410 d.GeomSetCategoryBits(prim_geom, 0);
1411 if (m_isphysical)
1412 {
1413 d.GeomSetCollideBits(prim_geom, (uint)CollisionCategories.Land);
1414 }
1415 else
1416 {
1417 d.GeomSetCollideBits(prim_geom, 0);
1418 d.GeomDisable(prim_geom);
1419 }
1420 }
1421 else
1422 {
1423 d.GeomSetCategoryBits(prim_geom, (uint)m_collisionCategories);
1424 d.GeomSetCollideBits(prim_geom, (uint)m_collisionFlags);
1425 }
1426
1427 UpdatePrimBodyData();
1428 _parent_scene.actor_name_map[prim_geom] = this;
1429
1430/*
1431// debug
1432 d.AABB aabb;
1433 d.GeomGetAABB(prim_geom, out aabb);
1434 float x = aabb.MaxX - aabb.MinX;
1435 float y = aabb.MaxY - aabb.MinY;
1436 float z = aabb.MaxZ - aabb.MinZ;
1437 if( x > 60.0f || y > 60.0f || z > 60.0f)
1438 m_log.WarnFormat("[PHYSICS]: large prim geo {0},size {1}, AABBsize <{2},{3},{4}, mesh {5} at {6}",
1439 Name, _size.ToString(), x, y, z, _pbs.SculptEntry ? _pbs.SculptTexture.ToString() : "primMesh", _position.ToString());
1440 else if (x < 0.001f || y < 0.001f || z < 0.001f)
1441 m_log.WarnFormat("[PHYSICS]: small prim geo {0},size {1}, AABBsize <{2},{3},{4}, mesh {5} at {6}",
1442 Name, _size.ToString(), x, y, z, _pbs.SculptEntry ? _pbs.SculptTexture.ToString() : "primMesh", _position.ToString());
1443*/
1444
1445 }
1446 else
1447 m_log.Warn("Setting bad Geom");
1448 }
1449
1450 private bool GetMeshGeom()
1451 {
1452 IntPtr vertices, indices;
1453 int vertexCount, indexCount;
1454 int vertexStride, triStride;
1455
1456 IMesh mesh = m_mesh;
1457
1458 if (mesh == null)
1459 return false;
1460
1461 mesh.getVertexListAsPtrToFloatArray(out vertices, out vertexStride, out vertexCount);
1462 mesh.getIndexListAsPtrToIntArray(out indices, out triStride, out indexCount);
1463
1464 if (vertexCount == 0 || indexCount == 0)
1465 {
1466 m_log.WarnFormat("[PHYSICS]: Invalid mesh data on OdePrim {0}, mesh {1} at {2}",
1467 Name, _pbs.SculptEntry ? _pbs.SculptTexture.ToString() : "primMesh",_position.ToString());
1468
1469 m_hasOBB = false;
1470 m_OBBOffset = Vector3.Zero;
1471 m_OBB = _size * 0.5f;
1472
1473 m_physCost = 0.1f;
1474 m_streamCost = 1.0f;
1475
1476 _parent_scene.mesher.ReleaseMesh(mesh);
1477 m_meshState = MeshState.MeshFailed;
1478 m_mesh = null;
1479 return false;
1480 }
1481
1482 if (vertexCount > 64000 || indexCount > 64000)
1483 {
1484 m_log.WarnFormat("[PHYSICS]: large mesh data on OdePrim {0}, mesh {1} at {2}, {3} vertices, {4} indexes",
1485 Name, _pbs.SculptEntry ? _pbs.SculptTexture.ToString() : "primMesh",
1486 _position.ToString() ,vertexCount , indexCount );
1487 }
1488 IntPtr geo = IntPtr.Zero;
1489
1490 try
1491 {
1492 _triMeshData = d.GeomTriMeshDataCreate();
1493
1494 d.GeomTriMeshDataBuildSimple(_triMeshData, vertices, vertexStride, vertexCount, indices, indexCount, triStride);
1495 d.GeomTriMeshDataPreprocess(_triMeshData);
1496
1497 geo = d.CreateTriMesh(m_targetSpace, _triMeshData, null, null, null);
1498 }
1499
1500 catch (Exception e)
1501 {
1502 m_log.ErrorFormat("[PHYSICS]: SetGeom Mesh failed for {0} exception: {1}", Name, e);
1503 if (_triMeshData != IntPtr.Zero)
1504 {
1505 try
1506 {
1507 d.GeomTriMeshDataDestroy(_triMeshData);
1508 }
1509 catch
1510 {
1511 }
1512 }
1513 _triMeshData = IntPtr.Zero;
1514
1515 m_hasOBB = false;
1516 m_OBBOffset = Vector3.Zero;
1517 m_OBB = _size * 0.5f;
1518 m_physCost = 0.1f;
1519 m_streamCost = 1.0f;
1520
1521 _parent_scene.mesher.ReleaseMesh(mesh);
1522 m_meshState = MeshState.MeshFailed;
1523 m_mesh = null;
1524 return false;
1525 }
1526
1527 m_physCost = 0.0013f * (float)indexCount;
1528 // todo
1529 m_streamCost = 1.0f;
1530
1531 SetGeom(geo);
1532
1533 return true;
1534 }
1535
1536 private void CreateGeom()
1537 {
1538 bool hasMesh = false;
1539
1540 m_NoColide = false;
1541
1542 if ((m_meshState & MeshState.MeshNoColide) != 0)
1543 m_NoColide = true;
1544
1545 else if(m_mesh != null)
1546 {
1547 if (GetMeshGeom())
1548 hasMesh = true;
1549 else
1550 m_NoColide = true;
1551 }
1552
1553
1554 if (!hasMesh)
1555 {
1556 IntPtr geo = IntPtr.Zero;
1557
1558 if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1
1559 && _size.X == _size.Y && _size.Y == _size.Z)
1560 { // it's a sphere
1561 try
1562 {
1563 geo = d.CreateSphere(m_targetSpace, _size.X * 0.5f);
1564 }
1565 catch (Exception e)
1566 {
1567 m_log.WarnFormat("[PHYSICS]: Create sphere failed: {0}", e);
1568 return;
1569 }
1570 }
1571 else
1572 {// do it as a box
1573 try
1574 {
1575 geo = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z);
1576 }
1577 catch (Exception e)
1578 {
1579 m_log.Warn("[PHYSICS]: Create box failed: {0}", e);
1580 return;
1581 }
1582 }
1583 m_physCost = 0.1f;
1584 m_streamCost = 1.0f;
1585 SetGeom(geo);
1586 }
1587 }
1588
1589 private void RemoveGeom()
1590 {
1591 if (prim_geom != IntPtr.Zero)
1592 {
1593 _parent_scene.actor_name_map.Remove(prim_geom);
1594
1595 try
1596 {
1597 d.GeomDestroy(prim_geom);
1598 if (_triMeshData != IntPtr.Zero)
1599 {
1600 d.GeomTriMeshDataDestroy(_triMeshData);
1601 _triMeshData = IntPtr.Zero;
1602 }
1603 }
1604 catch (Exception e)
1605 {
1606 m_log.ErrorFormat("[PHYSICS]: PrimGeom destruction failed for {0} exception {1}", Name, e);
1607 }
1608
1609 prim_geom = IntPtr.Zero;
1610 collide_geom = IntPtr.Zero;
1611 m_targetSpace = IntPtr.Zero;
1612 }
1613 else
1614 {
1615 m_log.ErrorFormat("[PHYSICS]: PrimGeom destruction BAD {0}", Name);
1616 }
1617
1618 lock (m_meshlock)
1619 {
1620 if (m_mesh != null)
1621 {
1622 _parent_scene.mesher.ReleaseMesh(m_mesh);
1623 m_mesh = null;
1624 }
1625 }
1626
1627 Body = IntPtr.Zero;
1628 m_hasOBB = false;
1629 }
1630
1631 //sets non physical prim m_targetSpace to right space in spaces grid for static prims
1632 // should only be called for non physical prims unless they are becoming non physical
1633 private void SetInStaticSpace(OdePrim prim)
1634 {
1635 IntPtr targetSpace = _parent_scene.MoveGeomToStaticSpace(prim.prim_geom, prim._position, prim.m_targetSpace);
1636 prim.m_targetSpace = targetSpace;
1637 collide_geom = IntPtr.Zero;
1638 }
1639
1640 public void enableBodySoft()
1641 {
1642 m_disabled = false;
1643 if (!childPrim && !m_isSelected)
1644 {
1645 if (m_isphysical && Body != IntPtr.Zero)
1646 {
1647 UpdateCollisionCatFlags();
1648 ApplyCollisionCatFlags();
1649
1650 _zeroFlag = true;
1651 d.BodyEnable(Body);
1652
1653 }
1654 }
1655 resetCollisionAccounting();
1656 }
1657
1658 private void disableBodySoft()
1659 {
1660 m_disabled = true;
1661 if (!childPrim)
1662 {
1663 if (m_isphysical && Body != IntPtr.Zero)
1664 {
1665 if (m_isSelected)
1666 m_collisionFlags = CollisionCategories.Selected;
1667 else
1668 m_collisionCategories = 0;
1669 m_collisionFlags = 0;
1670 ApplyCollisionCatFlags();
1671 d.BodyDisable(Body);
1672 }
1673 }
1674 }
1675
1676 private void MakeBody()
1677 {
1678 if (!m_isphysical) // only physical get bodies
1679 return;
1680
1681 if (childPrim) // child prims don't get bodies;
1682 return;
1683
1684 if (m_building)
1685 return;
1686
1687 if (prim_geom == IntPtr.Zero)
1688 {
1689 m_log.Warn("[PHYSICS]: Unable to link the linkset. Root has no geom yet");
1690 return;
1691 }
1692
1693 if (Body != IntPtr.Zero)
1694 {
1695 DestroyBody();
1696 m_log.Warn("[PHYSICS]: MakeBody called having a body");
1697 }
1698
1699 if (d.GeomGetBody(prim_geom) != IntPtr.Zero)
1700 {
1701 d.GeomSetBody(prim_geom, IntPtr.Zero);
1702 m_log.Warn("[PHYSICS]: MakeBody root geom already had a body");
1703 }
1704
1705 d.Matrix3 mymat = new d.Matrix3();
1706 d.Quaternion myrot = new d.Quaternion();
1707 d.Mass objdmass = new d.Mass { };
1708
1709 Body = d.BodyCreate(_parent_scene.world);
1710
1711 objdmass = primdMass;
1712
1713 // rotate inertia
1714 myrot.X = _orientation.X;
1715 myrot.Y = _orientation.Y;
1716 myrot.Z = _orientation.Z;
1717 myrot.W = _orientation.W;
1718
1719 d.RfromQ(out mymat, ref myrot);
1720 d.MassRotate(ref objdmass, ref mymat);
1721
1722 // set the body rotation
1723 d.BodySetRotation(Body, ref mymat);
1724
1725 // recompute full object inertia if needed
1726 if (childrenPrim.Count > 0)
1727 {
1728 d.Matrix3 mat = new d.Matrix3();
1729 d.Quaternion quat = new d.Quaternion();
1730 d.Mass tmpdmass = new d.Mass { };
1731 Vector3 rcm;
1732
1733 rcm.X = _position.X;
1734 rcm.Y = _position.Y;
1735 rcm.Z = _position.Z;
1736
1737 lock (childrenPrim)
1738 {
1739 foreach (OdePrim prm in childrenPrim)
1740 {
1741 if (prm.prim_geom == IntPtr.Zero)
1742 {
1743 m_log.Warn("[PHYSICS]: Unable to link one of the linkset elements, skipping it. No geom yet");
1744 continue;
1745 }
1746
1747 tmpdmass = prm.primdMass;
1748
1749 // apply prim current rotation to inertia
1750 quat.X = prm._orientation.X;
1751 quat.Y = prm._orientation.Y;
1752 quat.Z = prm._orientation.Z;
1753 quat.W = prm._orientation.W;
1754 d.RfromQ(out mat, ref quat);
1755 d.MassRotate(ref tmpdmass, ref mat);
1756
1757 Vector3 ppos = prm._position;
1758 ppos.X -= rcm.X;
1759 ppos.Y -= rcm.Y;
1760 ppos.Z -= rcm.Z;
1761 // refer inertia to root prim center of mass position
1762 d.MassTranslate(ref tmpdmass,
1763 ppos.X,
1764 ppos.Y,
1765 ppos.Z);
1766
1767 d.MassAdd(ref objdmass, ref tmpdmass); // add to total object inertia
1768 // fix prim colision cats
1769
1770 if (d.GeomGetBody(prm.prim_geom) != IntPtr.Zero)
1771 {
1772 d.GeomSetBody(prm.prim_geom, IntPtr.Zero);
1773 m_log.Warn("[PHYSICS]: MakeBody child geom already had a body");
1774 }
1775
1776 d.GeomClearOffset(prm.prim_geom);
1777 d.GeomSetBody(prm.prim_geom, Body);
1778 prm.Body = Body;
1779 d.GeomSetOffsetWorldRotation(prm.prim_geom, ref mat); // set relative rotation
1780 }
1781 }
1782 }
1783
1784 d.GeomClearOffset(prim_geom); // make sure we don't have a hidden offset
1785 // associate root geom with body
1786 d.GeomSetBody(prim_geom, Body);
1787
1788 d.BodySetPosition(Body, _position.X + objdmass.c.X, _position.Y + objdmass.c.Y, _position.Z + objdmass.c.Z);
1789 d.GeomSetOffsetWorldPosition(prim_geom, _position.X, _position.Y, _position.Z);
1790
1791 d.MassTranslate(ref objdmass, -objdmass.c.X, -objdmass.c.Y, -objdmass.c.Z); // ode wants inertia at center of body
1792 myrot.X = -myrot.X;
1793 myrot.Y = -myrot.Y;
1794 myrot.Z = -myrot.Z;
1795
1796 d.RfromQ(out mymat, ref myrot);
1797 d.MassRotate(ref objdmass, ref mymat);
1798
1799 d.BodySetMass(Body, ref objdmass);
1800 _mass = objdmass.mass;
1801
1802 // disconnect from world gravity so we can apply buoyancy
1803 d.BodySetGravityMode(Body, false);
1804
1805 d.BodySetAutoDisableFlag(Body, true);
1806 d.BodySetAutoDisableSteps(Body, body_autodisable_frames);
1807 d.BodySetAutoDisableAngularThreshold(Body, 0.05f);
1808 d.BodySetAutoDisableLinearThreshold(Body, 0.05f);
1809 d.BodySetDamping(Body, .004f, .001f);
1810
1811 if (m_targetSpace != IntPtr.Zero)
1812 {
1813 _parent_scene.waitForSpaceUnlock(m_targetSpace);
1814 if (d.SpaceQuery(m_targetSpace, prim_geom))
1815 d.SpaceRemove(m_targetSpace, prim_geom);
1816 }
1817
1818 if (childrenPrim.Count == 0)
1819 {
1820 collide_geom = prim_geom;
1821 m_targetSpace = _parent_scene.ActiveSpace;
1822 }
1823 else
1824 {
1825 m_targetSpace = d.HashSpaceCreate(_parent_scene.ActiveSpace);
1826 d.HashSpaceSetLevels(m_targetSpace, -2, 8);
1827 d.SpaceSetSublevel(m_targetSpace, 3);
1828 d.SpaceSetCleanup(m_targetSpace, false);
1829
1830 d.GeomSetCategoryBits(m_targetSpace, (uint)(CollisionCategories.Space |
1831 CollisionCategories.Geom |
1832 CollisionCategories.Phantom |
1833 CollisionCategories.VolumeDtc
1834 ));
1835 d.GeomSetCollideBits(m_targetSpace, 0);
1836 collide_geom = m_targetSpace;
1837 }
1838
1839 d.SpaceAdd(m_targetSpace, prim_geom);
1840
1841 if (m_delaySelect)
1842 {
1843 m_isSelected = true;
1844 m_delaySelect = false;
1845 }
1846
1847 m_collisionscore = 0;
1848
1849 UpdateCollisionCatFlags();
1850 ApplyCollisionCatFlags();
1851
1852 _parent_scene.addActivePrim(this);
1853
1854 lock (childrenPrim)
1855 {
1856 foreach (OdePrim prm in childrenPrim)
1857 {
1858 if (prm.prim_geom == IntPtr.Zero)
1859 continue;
1860
1861 Vector3 ppos = prm._position;
1862 d.GeomSetOffsetWorldPosition(prm.prim_geom, ppos.X, ppos.Y, ppos.Z); // set relative position
1863
1864 if (prm.m_targetSpace != m_targetSpace)
1865 {
1866 if (prm.m_targetSpace != IntPtr.Zero)
1867 {
1868 _parent_scene.waitForSpaceUnlock(prm.m_targetSpace);
1869 if (d.SpaceQuery(prm.m_targetSpace, prm.prim_geom))
1870 d.SpaceRemove(prm.m_targetSpace, prm.prim_geom);
1871 }
1872 prm.m_targetSpace = m_targetSpace;
1873 d.SpaceAdd(m_targetSpace, prm.prim_geom);
1874 }
1875
1876 prm.m_collisionscore = 0;
1877
1878 if(!m_disabled)
1879 prm.m_disabled = false;
1880
1881 _parent_scene.addActivePrim(prm);
1882 }
1883 }
1884
1885 // The body doesn't already have a finite rotation mode set here
1886 if (m_angularlocks != 0 && _parent == null)
1887 {
1888 createAMotor(m_angularlocks);
1889 }
1890
1891 if (m_isSelected || m_disabled)
1892 {
1893 d.BodyDisable(Body);
1894 _zeroFlag = true;
1895 }
1896 else
1897 {
1898 d.BodySetAngularVel(Body, m_rotationalVelocity.X, m_rotationalVelocity.Y, m_rotationalVelocity.Z);
1899 d.BodySetLinearVel(Body, _velocity.X, _velocity.Y, _velocity.Z);
1900 _zeroFlag = false;
1901 bodydisablecontrol = 0;
1902 }
1903 _parent_scene.addActiveGroups(this);
1904 }
1905
1906 private void DestroyBody()
1907 {
1908 if (Body != IntPtr.Zero)
1909 {
1910 _parent_scene.remActivePrim(this);
1911
1912 collide_geom = IntPtr.Zero;
1913
1914 if (m_disabled)
1915 m_collisionCategories = 0;
1916 else if (m_isSelected)
1917 m_collisionCategories = CollisionCategories.Selected;
1918 else if (m_isVolumeDetect)
1919 m_collisionCategories = CollisionCategories.VolumeDtc;
1920 else if (m_isphantom)
1921 m_collisionCategories = CollisionCategories.Phantom;
1922 else
1923 m_collisionCategories = CollisionCategories.Geom;
1924
1925 m_collisionFlags = 0;
1926
1927 if (prim_geom != IntPtr.Zero)
1928 {
1929 if (m_NoColide)
1930 {
1931 d.GeomSetCategoryBits(prim_geom, 0);
1932 d.GeomSetCollideBits(prim_geom, 0);
1933 }
1934 else
1935 {
1936 d.GeomSetCategoryBits(prim_geom, (uint)m_collisionCategories);
1937 d.GeomSetCollideBits(prim_geom, (uint)m_collisionFlags);
1938 }
1939 UpdateDataFromGeom();
1940 d.GeomSetBody(prim_geom, IntPtr.Zero);
1941 SetInStaticSpace(this);
1942 }
1943
1944 if (!childPrim)
1945 {
1946 lock (childrenPrim)
1947 {
1948 foreach (OdePrim prm in childrenPrim)
1949 {
1950 _parent_scene.remActivePrim(prm);
1951
1952 if (prm.m_isSelected)
1953 prm.m_collisionCategories = CollisionCategories.Selected;
1954 else if (prm.m_isVolumeDetect)
1955 prm.m_collisionCategories = CollisionCategories.VolumeDtc;
1956 else if (prm.m_isphantom)
1957 prm.m_collisionCategories = CollisionCategories.Phantom;
1958 else
1959 prm.m_collisionCategories = CollisionCategories.Geom;
1960
1961 prm.m_collisionFlags = 0;
1962
1963 if (prm.prim_geom != IntPtr.Zero)
1964 {
1965 if (prm.m_NoColide)
1966 {
1967 d.GeomSetCategoryBits(prm.prim_geom, 0);
1968 d.GeomSetCollideBits(prm.prim_geom, 0);
1969 }
1970 else
1971 {
1972 d.GeomSetCategoryBits(prm.prim_geom, (uint)prm.m_collisionCategories);
1973 d.GeomSetCollideBits(prm.prim_geom, (uint)prm.m_collisionFlags);
1974 }
1975 prm.UpdateDataFromGeom();
1976 SetInStaticSpace(prm);
1977 }
1978 prm.Body = IntPtr.Zero;
1979 prm._mass = prm.primMass;
1980 prm.m_collisionscore = 0;
1981 }
1982 }
1983 if (Amotor != IntPtr.Zero)
1984 {
1985 d.JointDestroy(Amotor);
1986 Amotor = IntPtr.Zero;
1987 }
1988 _parent_scene.remActiveGroup(this);
1989 d.BodyDestroy(Body);
1990 }
1991 Body = IntPtr.Zero;
1992 }
1993 _mass = primMass;
1994 m_collisionscore = 0;
1995 }
1996
1997 private void FixInertia(Vector3 NewPos,Quaternion newrot)
1998 {
1999 d.Matrix3 mat = new d.Matrix3();
2000 d.Quaternion quat = new d.Quaternion();
2001
2002 d.Mass tmpdmass = new d.Mass { };
2003 d.Mass objdmass = new d.Mass { };
2004
2005 d.BodyGetMass(Body, out tmpdmass);
2006 objdmass = tmpdmass;
2007
2008 d.Vector3 dobjpos;
2009 d.Vector3 thispos;
2010
2011 // get current object position and rotation
2012 dobjpos = d.BodyGetPosition(Body);
2013
2014 // get prim own inertia in its local frame
2015 tmpdmass = primdMass;
2016
2017 // transform to object frame
2018 mat = d.GeomGetOffsetRotation(prim_geom);
2019 d.MassRotate(ref tmpdmass, ref mat);
2020
2021 thispos = d.GeomGetOffsetPosition(prim_geom);
2022 d.MassTranslate(ref tmpdmass,
2023 thispos.X,
2024 thispos.Y,
2025 thispos.Z);
2026
2027 // subtract current prim inertia from object
2028 DMassSubPartFromObj(ref tmpdmass, ref objdmass);
2029
2030 // back prim own inertia
2031 tmpdmass = primdMass;
2032
2033 // update to new position and orientation
2034 _position = NewPos;
2035 d.GeomSetOffsetWorldPosition(prim_geom, NewPos.X, NewPos.Y, NewPos.Z);
2036 _orientation = newrot;
2037 quat.X = newrot.X;
2038 quat.Y = newrot.Y;
2039 quat.Z = newrot.Z;
2040 quat.W = newrot.W;
2041 d.GeomSetOffsetWorldQuaternion(prim_geom, ref quat);
2042
2043 mat = d.GeomGetOffsetRotation(prim_geom);
2044 d.MassRotate(ref tmpdmass, ref mat);
2045
2046 thispos = d.GeomGetOffsetPosition(prim_geom);
2047 d.MassTranslate(ref tmpdmass,
2048 thispos.X,
2049 thispos.Y,
2050 thispos.Z);
2051
2052 d.MassAdd(ref objdmass, ref tmpdmass);
2053
2054 // fix all positions
2055 IntPtr g = d.BodyGetFirstGeom(Body);
2056 while (g != IntPtr.Zero)
2057 {
2058 thispos = d.GeomGetOffsetPosition(g);
2059 thispos.X -= objdmass.c.X;
2060 thispos.Y -= objdmass.c.Y;
2061 thispos.Z -= objdmass.c.Z;
2062 d.GeomSetOffsetPosition(g, thispos.X, thispos.Y, thispos.Z);
2063 g = d.dBodyGetNextGeom(g);
2064 }
2065 d.BodyVectorToWorld(Body,objdmass.c.X, objdmass.c.Y, objdmass.c.Z,out thispos);
2066
2067 d.BodySetPosition(Body, dobjpos.X + thispos.X, dobjpos.Y + thispos.Y, dobjpos.Z + thispos.Z);
2068 d.MassTranslate(ref objdmass, -objdmass.c.X, -objdmass.c.Y, -objdmass.c.Z); // ode wants inertia at center of body
2069 d.BodySetMass(Body, ref objdmass);
2070 _mass = objdmass.mass;
2071 }
2072
2073 private void FixInertia(Vector3 NewPos)
2074 {
2075 d.Matrix3 primmat = new d.Matrix3();
2076 d.Mass tmpdmass = new d.Mass { };
2077 d.Mass objdmass = new d.Mass { };
2078 d.Mass primmass = new d.Mass { };
2079
2080 d.Vector3 dobjpos;
2081 d.Vector3 thispos;
2082
2083 d.BodyGetMass(Body, out objdmass);
2084
2085 // get prim own inertia in its local frame
2086 primmass = primdMass;
2087 // transform to object frame
2088 primmat = d.GeomGetOffsetRotation(prim_geom);
2089 d.MassRotate(ref primmass, ref primmat);
2090
2091 tmpdmass = primmass;
2092
2093 thispos = d.GeomGetOffsetPosition(prim_geom);
2094 d.MassTranslate(ref tmpdmass,
2095 thispos.X,
2096 thispos.Y,
2097 thispos.Z);
2098
2099 // subtract current prim inertia from object
2100 DMassSubPartFromObj(ref tmpdmass, ref objdmass);
2101
2102 // update to new position
2103 _position = NewPos;
2104 d.GeomSetOffsetWorldPosition(prim_geom, NewPos.X, NewPos.Y, NewPos.Z);
2105
2106 thispos = d.GeomGetOffsetPosition(prim_geom);
2107 d.MassTranslate(ref primmass,
2108 thispos.X,
2109 thispos.Y,
2110 thispos.Z);
2111
2112 d.MassAdd(ref objdmass, ref primmass);
2113
2114 // fix all positions
2115 IntPtr g = d.BodyGetFirstGeom(Body);
2116 while (g != IntPtr.Zero)
2117 {
2118 thispos = d.GeomGetOffsetPosition(g);
2119 thispos.X -= objdmass.c.X;
2120 thispos.Y -= objdmass.c.Y;
2121 thispos.Z -= objdmass.c.Z;
2122 d.GeomSetOffsetPosition(g, thispos.X, thispos.Y, thispos.Z);
2123 g = d.dBodyGetNextGeom(g);
2124 }
2125
2126 d.BodyVectorToWorld(Body, objdmass.c.X, objdmass.c.Y, objdmass.c.Z, out thispos);
2127
2128 // get current object position and rotation
2129 dobjpos = d.BodyGetPosition(Body);
2130
2131 d.BodySetPosition(Body, dobjpos.X + thispos.X, dobjpos.Y + thispos.Y, dobjpos.Z + thispos.Z);
2132 d.MassTranslate(ref objdmass, -objdmass.c.X, -objdmass.c.Y, -objdmass.c.Z); // ode wants inertia at center of body
2133 d.BodySetMass(Body, ref objdmass);
2134 _mass = objdmass.mass;
2135 }
2136
2137 private void FixInertia(Quaternion newrot)
2138 {
2139 d.Matrix3 mat = new d.Matrix3();
2140 d.Quaternion quat = new d.Quaternion();
2141
2142 d.Mass tmpdmass = new d.Mass { };
2143 d.Mass objdmass = new d.Mass { };
2144 d.Vector3 dobjpos;
2145 d.Vector3 thispos;
2146
2147 d.BodyGetMass(Body, out objdmass);
2148
2149 // get prim own inertia in its local frame
2150 tmpdmass = primdMass;
2151 mat = d.GeomGetOffsetRotation(prim_geom);
2152 d.MassRotate(ref tmpdmass, ref mat);
2153 // transform to object frame
2154 thispos = d.GeomGetOffsetPosition(prim_geom);
2155 d.MassTranslate(ref tmpdmass,
2156 thispos.X,
2157 thispos.Y,
2158 thispos.Z);
2159
2160 // subtract current prim inertia from object
2161 DMassSubPartFromObj(ref tmpdmass, ref objdmass);
2162
2163 // update to new orientation
2164 _orientation = newrot;
2165 quat.X = newrot.X;
2166 quat.Y = newrot.Y;
2167 quat.Z = newrot.Z;
2168 quat.W = newrot.W;
2169 d.GeomSetOffsetWorldQuaternion(prim_geom, ref quat);
2170
2171 tmpdmass = primdMass;
2172 mat = d.GeomGetOffsetRotation(prim_geom);
2173 d.MassRotate(ref tmpdmass, ref mat);
2174 d.MassTranslate(ref tmpdmass,
2175 thispos.X,
2176 thispos.Y,
2177 thispos.Z);
2178
2179 d.MassAdd(ref objdmass, ref tmpdmass);
2180
2181 // fix all positions
2182 IntPtr g = d.BodyGetFirstGeom(Body);
2183 while (g != IntPtr.Zero)
2184 {
2185 thispos = d.GeomGetOffsetPosition(g);
2186 thispos.X -= objdmass.c.X;
2187 thispos.Y -= objdmass.c.Y;
2188 thispos.Z -= objdmass.c.Z;
2189 d.GeomSetOffsetPosition(g, thispos.X, thispos.Y, thispos.Z);
2190 g = d.dBodyGetNextGeom(g);
2191 }
2192
2193 d.BodyVectorToWorld(Body, objdmass.c.X, objdmass.c.Y, objdmass.c.Z, out thispos);
2194 // get current object position and rotation
2195 dobjpos = d.BodyGetPosition(Body);
2196
2197 d.BodySetPosition(Body, dobjpos.X + thispos.X, dobjpos.Y + thispos.Y, dobjpos.Z + thispos.Z);
2198 d.MassTranslate(ref objdmass, -objdmass.c.X, -objdmass.c.Y, -objdmass.c.Z); // ode wants inertia at center of body
2199 d.BodySetMass(Body, ref objdmass);
2200 _mass = objdmass.mass;
2201 }
2202
2203
2204 #region Mass Calculation
2205
2206 private void UpdatePrimBodyData()
2207 {
2208 primMass = m_density * primVolume;
2209
2210 if (primMass <= 0)
2211 primMass = 0.0001f;//ckrinke: Mass must be greater then zero.
2212 if (primMass > _parent_scene.maximumMassObject)
2213 primMass = _parent_scene.maximumMassObject;
2214
2215 _mass = primMass; // just in case
2216
2217 d.MassSetBoxTotal(out primdMass, primMass, 2.0f * m_OBB.X, 2.0f * m_OBB.Y, 2.0f * m_OBB.Z);
2218
2219 d.MassTranslate(ref primdMass,
2220 m_OBBOffset.X,
2221 m_OBBOffset.Y,
2222 m_OBBOffset.Z);
2223
2224 primOOBradiusSQ = m_OBB.LengthSquared();
2225
2226 if (_triMeshData != IntPtr.Zero)
2227 {
2228 float pc = m_physCost;
2229 float psf = primOOBradiusSQ;
2230 psf *= 1.33f * .2f;
2231 pc *= psf;
2232 if (pc < 0.1f)
2233 pc = 0.1f;
2234
2235 m_physCost = pc;
2236 }
2237 else
2238 m_physCost = 0.1f;
2239
2240 m_streamCost = 1.0f;
2241 }
2242
2243 #endregion
2244
2245
2246 /// <summary>
2247 /// Add a child prim to this parent prim.
2248 /// </summary>
2249 /// <param name="prim">Child prim</param>
2250 // I'm the parent
2251 // prim is the child
2252 public void ParentPrim(OdePrim prim)
2253 {
2254 //Console.WriteLine("ParentPrim " + m_primName);
2255 if (this.m_localID != prim.m_localID)
2256 {
2257 DestroyBody(); // for now we need to rebuil entire object on link change
2258
2259 lock (childrenPrim)
2260 {
2261 // adopt the prim
2262 if (!childrenPrim.Contains(prim))
2263 childrenPrim.Add(prim);
2264
2265 // see if this prim has kids and adopt them also
2266 // should not happen for now
2267 foreach (OdePrim prm in prim.childrenPrim)
2268 {
2269 if (!childrenPrim.Contains(prm))
2270 {
2271 if (prm.Body != IntPtr.Zero)
2272 {
2273 if (prm.prim_geom != IntPtr.Zero)
2274 d.GeomSetBody(prm.prim_geom, IntPtr.Zero);
2275 if (prm.Body != prim.Body)
2276 prm.DestroyBody(); // don't loose bodies around
2277 prm.Body = IntPtr.Zero;
2278 }
2279
2280 childrenPrim.Add(prm);
2281 prm._parent = this;
2282 }
2283 }
2284 }
2285 //Remove old children from the prim
2286 prim.childrenPrim.Clear();
2287
2288 if (prim.Body != IntPtr.Zero)
2289 {
2290 if (prim.prim_geom != IntPtr.Zero)
2291 d.GeomSetBody(prim.prim_geom, IntPtr.Zero);
2292 prim.DestroyBody(); // don't loose bodies around
2293 prim.Body = IntPtr.Zero;
2294 }
2295
2296 prim.childPrim = true;
2297 prim._parent = this;
2298
2299 MakeBody(); // full nasty reconstruction
2300 }
2301 }
2302
2303 private void UpdateChildsfromgeom()
2304 {
2305 if (childrenPrim.Count > 0)
2306 {
2307 foreach (OdePrim prm in childrenPrim)
2308 prm.UpdateDataFromGeom();
2309 }
2310 }
2311
2312 private void UpdateDataFromGeom()
2313 {
2314 if (prim_geom != IntPtr.Zero)
2315 {
2316 d.Quaternion qtmp;
2317 d.GeomCopyQuaternion(prim_geom, out qtmp);
2318 _orientation.X = qtmp.X;
2319 _orientation.Y = qtmp.Y;
2320 _orientation.Z = qtmp.Z;
2321 _orientation.W = qtmp.W;
2322/*
2323// Debug
2324 float qlen = _orientation.Length();
2325 if (qlen > 1.01f || qlen < 0.99)
2326 m_log.WarnFormat("[PHYSICS]: Got nonnorm quaternion from geom in Object {0} norm {1}", Name, qlen);
2327//
2328*/
2329 _orientation.Normalize();
2330
2331 d.Vector3 lpos = d.GeomGetPosition(prim_geom);
2332 _position.X = lpos.X;
2333 _position.Y = lpos.Y;
2334 _position.Z = lpos.Z;
2335 }
2336 }
2337
2338 private void ChildDelink(OdePrim odePrim, bool remakebodies)
2339 {
2340 // Okay, we have a delinked child.. destroy all body and remake
2341 if (odePrim != this && !childrenPrim.Contains(odePrim))
2342 return;
2343
2344 DestroyBody();
2345
2346 if (odePrim == this) // delinking the root prim
2347 {
2348 OdePrim newroot = null;
2349 lock (childrenPrim)
2350 {
2351 if (childrenPrim.Count > 0)
2352 {
2353 newroot = childrenPrim[0];
2354 childrenPrim.RemoveAt(0);
2355 foreach (OdePrim prm in childrenPrim)
2356 {
2357 newroot.childrenPrim.Add(prm);
2358 }
2359 childrenPrim.Clear();
2360 }
2361 if (newroot != null)
2362 {
2363 newroot.childPrim = false;
2364 newroot._parent = null;
2365 if (remakebodies)
2366 newroot.MakeBody();
2367 }
2368 }
2369 }
2370
2371 else
2372 {
2373 lock (childrenPrim)
2374 {
2375 childrenPrim.Remove(odePrim);
2376 odePrim.childPrim = false;
2377 odePrim._parent = null;
2378 // odePrim.UpdateDataFromGeom();
2379 if (remakebodies)
2380 odePrim.MakeBody();
2381 }
2382 }
2383 if (remakebodies)
2384 MakeBody();
2385 }
2386
2387 protected void ChildRemove(OdePrim odePrim, bool reMakeBody)
2388 {
2389 // Okay, we have a delinked child.. destroy all body and remake
2390 if (odePrim != this && !childrenPrim.Contains(odePrim))
2391 return;
2392
2393 DestroyBody();
2394
2395 if (odePrim == this)
2396 {
2397 OdePrim newroot = null;
2398 lock (childrenPrim)
2399 {
2400 if (childrenPrim.Count > 0)
2401 {
2402 newroot = childrenPrim[0];
2403 childrenPrim.RemoveAt(0);
2404 foreach (OdePrim prm in childrenPrim)
2405 {
2406 newroot.childrenPrim.Add(prm);
2407 }
2408 childrenPrim.Clear();
2409 }
2410 if (newroot != null)
2411 {
2412 newroot.childPrim = false;
2413 newroot._parent = null;
2414 newroot.MakeBody();
2415 }
2416 }
2417 if (reMakeBody)
2418 MakeBody();
2419 return;
2420 }
2421 else
2422 {
2423 lock (childrenPrim)
2424 {
2425 childrenPrim.Remove(odePrim);
2426 odePrim.childPrim = false;
2427 odePrim._parent = null;
2428 if (reMakeBody)
2429 odePrim.MakeBody();
2430 }
2431 }
2432 MakeBody();
2433 }
2434
2435
2436 #region changes
2437
2438 private void changeadd()
2439 {
2440 }
2441
2442 private void changeAngularLock(byte newLocks)
2443 {
2444 // do we have a Physical object?
2445 if (Body != IntPtr.Zero)
2446 {
2447 //Check that we have a Parent
2448 //If we have a parent then we're not authorative here
2449 if (_parent == null)
2450 {
2451 if (newLocks != 0)
2452 {
2453 createAMotor(newLocks);
2454 }
2455 else
2456 {
2457 if (Amotor != IntPtr.Zero)
2458 {
2459 d.JointDestroy(Amotor);
2460 Amotor = IntPtr.Zero;
2461 }
2462 }
2463 }
2464 }
2465 // Store this for later in case we get turned into a separate body
2466 m_angularlocks = newLocks;
2467 }
2468
2469 private void changeLink(OdePrim NewParent)
2470 {
2471 if (_parent == null && NewParent != null)
2472 {
2473 NewParent.ParentPrim(this);
2474 }
2475 else if (_parent != null)
2476 {
2477 if (_parent is OdePrim)
2478 {
2479 if (NewParent != _parent)
2480 {
2481 (_parent as OdePrim).ChildDelink(this, false); // for now...
2482 childPrim = false;
2483
2484 if (NewParent != null)
2485 {
2486 NewParent.ParentPrim(this);
2487 }
2488 }
2489 }
2490 }
2491 _parent = NewParent;
2492 }
2493
2494
2495 private void Stop()
2496 {
2497 if (!childPrim)
2498 {
2499// m_force = Vector3.Zero;
2500 m_forceacc = Vector3.Zero;
2501 m_angularForceacc = Vector3.Zero;
2502// m_torque = Vector3.Zero;
2503 _velocity = Vector3.Zero;
2504 _acceleration = Vector3.Zero;
2505 m_rotationalVelocity = Vector3.Zero;
2506 _target_velocity = Vector3.Zero;
2507 if (m_vehicle != null && m_vehicle.Type != Vehicle.TYPE_NONE)
2508 m_vehicle.Stop();
2509
2510 _zeroFlag = false;
2511 base.RequestPhysicsterseUpdate();
2512 }
2513
2514 if (Body != IntPtr.Zero)
2515 {
2516 d.BodySetForce(Body, 0f, 0f, 0f);
2517 d.BodySetTorque(Body, 0f, 0f, 0f);
2518 d.BodySetLinearVel(Body, 0f, 0f, 0f);
2519 d.BodySetAngularVel(Body, 0f, 0f, 0f);
2520 }
2521 }
2522
2523 private void changePhantomStatus(bool newval)
2524 {
2525 m_isphantom = newval;
2526
2527 UpdateCollisionCatFlags();
2528 ApplyCollisionCatFlags();
2529 }
2530
2531/* not in use
2532 internal void ChildSelectedChange(bool childSelect)
2533 {
2534 if(childPrim)
2535 return;
2536
2537 if (childSelect == m_isSelected)
2538 return;
2539
2540 if (childSelect)
2541 {
2542 DoSelectedStatus(true);
2543 }
2544
2545 else
2546 {
2547 foreach (OdePrim prm in childrenPrim)
2548 {
2549 if (prm.m_isSelected)
2550 return;
2551 }
2552 DoSelectedStatus(false);
2553 }
2554 }
2555*/
2556 private void changeSelectedStatus(bool newval)
2557 {
2558 if (m_lastdoneSelected == newval)
2559 return;
2560
2561 m_lastdoneSelected = newval;
2562 DoSelectedStatus(newval);
2563 }
2564
2565 private void CheckDelaySelect()
2566 {
2567 if (m_delaySelect)
2568 {
2569 DoSelectedStatus(m_isSelected);
2570 }
2571 }
2572
2573 private void DoSelectedStatus(bool newval)
2574 {
2575 m_isSelected = newval;
2576 Stop();
2577
2578 if (newval)
2579 {
2580 if (!childPrim && Body != IntPtr.Zero)
2581 d.BodyDisable(Body);
2582
2583 if (m_delaySelect || m_isphysical)
2584 {
2585 m_collisionCategories = CollisionCategories.Selected;
2586 m_collisionFlags = 0;
2587
2588 if (!childPrim)
2589 {
2590 foreach (OdePrim prm in childrenPrim)
2591 {
2592 prm.m_collisionCategories = m_collisionCategories;
2593 prm.m_collisionFlags = m_collisionFlags;
2594
2595 if (prm.prim_geom != IntPtr.Zero)
2596 {
2597
2598 if (prm.m_NoColide)
2599 {
2600 d.GeomSetCategoryBits(prm.prim_geom, 0);
2601 d.GeomSetCollideBits(prm.prim_geom, 0);
2602 }
2603 else
2604 {
2605 d.GeomSetCategoryBits(prm.prim_geom, (uint)m_collisionCategories);
2606 d.GeomSetCollideBits(prm.prim_geom, (uint)m_collisionFlags);
2607 }
2608 }
2609 prm.m_delaySelect = false;
2610 }
2611 }
2612// else if (_parent != null)
2613// ((OdePrim)_parent).ChildSelectedChange(true);
2614
2615
2616 if (prim_geom != IntPtr.Zero)
2617 {
2618 if (m_NoColide)
2619 {
2620 d.GeomSetCategoryBits(prim_geom, 0);
2621 d.GeomSetCollideBits(prim_geom, 0);
2622 if (collide_geom != prim_geom && collide_geom != IntPtr.Zero)
2623 {
2624 d.GeomSetCategoryBits(collide_geom, 0);
2625 d.GeomSetCollideBits(collide_geom, 0);
2626 }
2627
2628 }
2629 else
2630 {
2631 d.GeomSetCategoryBits(prim_geom, (uint)m_collisionCategories);
2632 d.GeomSetCollideBits(prim_geom, (uint)m_collisionFlags);
2633 if (collide_geom != prim_geom && collide_geom != IntPtr.Zero)
2634 {
2635 d.GeomSetCategoryBits(collide_geom, (uint)m_collisionCategories);
2636 d.GeomSetCollideBits(collide_geom, (uint)m_collisionFlags);
2637 }
2638 }
2639 }
2640
2641 m_delaySelect = false;
2642 }
2643 else if(!m_isphysical)
2644 {
2645 m_delaySelect = true;
2646 }
2647 }
2648 else
2649 {
2650 if (!childPrim)
2651 {
2652 if (Body != IntPtr.Zero && !m_disabled)
2653 {
2654 _zeroFlag = true;
2655 d.BodyEnable(Body);
2656 }
2657 }
2658// else if (_parent != null)
2659// ((OdePrim)_parent).ChildSelectedChange(false);
2660
2661 UpdateCollisionCatFlags();
2662 ApplyCollisionCatFlags();
2663
2664 m_delaySelect = false;
2665 }
2666
2667 resetCollisionAccounting();
2668 }
2669
2670 private void changePosition(Vector3 newPos)
2671 {
2672 CheckDelaySelect();
2673 if (m_isphysical)
2674 {
2675 if (childPrim) // inertia is messed, must rebuild
2676 {
2677 if (m_building)
2678 {
2679 _position = newPos;
2680 }
2681
2682 else if (m_forcePosOrRotation && _position != newPos && Body != IntPtr.Zero)
2683 {
2684 FixInertia(newPos);
2685 if (!d.BodyIsEnabled(Body))
2686 {
2687 _zeroFlag = true;
2688 d.BodyEnable(Body);
2689 }
2690 }
2691 }
2692 else
2693 {
2694 if (_position != newPos)
2695 {
2696 d.GeomSetPosition(prim_geom, newPos.X, newPos.Y, newPos.Z);
2697 _position = newPos;
2698 }
2699 if (Body != IntPtr.Zero && !d.BodyIsEnabled(Body))
2700 {
2701 _zeroFlag = true;
2702 d.BodyEnable(Body);
2703 }
2704 }
2705 }
2706 else
2707 {
2708 if (prim_geom != IntPtr.Zero)
2709 {
2710 if (newPos != _position)
2711 {
2712 d.GeomSetPosition(prim_geom, newPos.X, newPos.Y, newPos.Z);
2713 _position = newPos;
2714
2715 m_targetSpace = _parent_scene.MoveGeomToStaticSpace(prim_geom, _position, m_targetSpace);
2716 }
2717 }
2718 }
2719 givefakepos--;
2720 if (givefakepos < 0)
2721 givefakepos = 0;
2722// changeSelectedStatus();
2723 resetCollisionAccounting();
2724 }
2725
2726 private void changeOrientation(Quaternion newOri)
2727 {
2728 CheckDelaySelect();
2729 if (m_isphysical)
2730 {
2731 if (childPrim) // inertia is messed, must rebuild
2732 {
2733 if (m_building)
2734 {
2735 _orientation = newOri;
2736 }
2737/*
2738 else if (m_forcePosOrRotation && _orientation != newOri && Body != IntPtr.Zero)
2739 {
2740 FixInertia(_position, newOri);
2741 if (!d.BodyIsEnabled(Body))
2742 d.BodyEnable(Body);
2743 }
2744*/
2745 }
2746 else
2747 {
2748 if (newOri != _orientation)
2749 {
2750 d.Quaternion myrot = new d.Quaternion();
2751 myrot.X = newOri.X;
2752 myrot.Y = newOri.Y;
2753 myrot.Z = newOri.Z;
2754 myrot.W = newOri.W;
2755 d.GeomSetQuaternion(prim_geom, ref myrot);
2756 _orientation = newOri;
2757 if (Body != IntPtr.Zero && m_angularlocks != 0)
2758 createAMotor(m_angularlocks);
2759 }
2760 if (Body != IntPtr.Zero && !d.BodyIsEnabled(Body))
2761 {
2762 _zeroFlag = true;
2763 d.BodyEnable(Body);
2764 }
2765 }
2766 }
2767 else
2768 {
2769 if (prim_geom != IntPtr.Zero)
2770 {
2771 if (newOri != _orientation)
2772 {
2773 d.Quaternion myrot = new d.Quaternion();
2774 myrot.X = newOri.X;
2775 myrot.Y = newOri.Y;
2776 myrot.Z = newOri.Z;
2777 myrot.W = newOri.W;
2778 d.GeomSetQuaternion(prim_geom, ref myrot);
2779 _orientation = newOri;
2780 }
2781 }
2782 }
2783 givefakeori--;
2784 if (givefakeori < 0)
2785 givefakeori = 0;
2786 resetCollisionAccounting();
2787 }
2788
2789 private void changePositionAndOrientation(Vector3 newPos, Quaternion newOri)
2790 {
2791 CheckDelaySelect();
2792 if (m_isphysical)
2793 {
2794 if (childPrim && m_building) // inertia is messed, must rebuild
2795 {
2796 _position = newPos;
2797 _orientation = newOri;
2798 }
2799 else
2800 {
2801 if (newOri != _orientation)
2802 {
2803 d.Quaternion myrot = new d.Quaternion();
2804 myrot.X = newOri.X;
2805 myrot.Y = newOri.Y;
2806 myrot.Z = newOri.Z;
2807 myrot.W = newOri.W;
2808 d.GeomSetQuaternion(prim_geom, ref myrot);
2809 _orientation = newOri;
2810 if (Body != IntPtr.Zero && m_angularlocks != 0)
2811 createAMotor(m_angularlocks);
2812 }
2813 if (_position != newPos)
2814 {
2815 d.GeomSetPosition(prim_geom, newPos.X, newPos.Y, newPos.Z);
2816 _position = newPos;
2817 }
2818 if (Body != IntPtr.Zero && !d.BodyIsEnabled(Body))
2819 {
2820 _zeroFlag = true;
2821 d.BodyEnable(Body);
2822 }
2823 }
2824 }
2825 else
2826 {
2827 // string primScenAvatarIn = _parent_scene.whichspaceamIin(_position);
2828 // int[] arrayitem = _parent_scene.calculateSpaceArrayItemFromPos(_position);
2829
2830 if (prim_geom != IntPtr.Zero)
2831 {
2832 if (newOri != _orientation)
2833 {
2834 d.Quaternion myrot = new d.Quaternion();
2835 myrot.X = newOri.X;
2836 myrot.Y = newOri.Y;
2837 myrot.Z = newOri.Z;
2838 myrot.W = newOri.W;
2839 d.GeomSetQuaternion(prim_geom, ref myrot);
2840 _orientation = newOri;
2841 }
2842
2843 if (newPos != _position)
2844 {
2845 d.GeomSetPosition(prim_geom, newPos.X, newPos.Y, newPos.Z);
2846 _position = newPos;
2847
2848 m_targetSpace = _parent_scene.MoveGeomToStaticSpace(prim_geom, _position, m_targetSpace);
2849 }
2850 }
2851 }
2852 givefakepos--;
2853 if (givefakepos < 0)
2854 givefakepos = 0;
2855 givefakeori--;
2856 if (givefakeori < 0)
2857 givefakeori = 0;
2858 resetCollisionAccounting();
2859 }
2860
2861 private void changeDisable(bool disable)
2862 {
2863 if (disable)
2864 {
2865 if (!m_disabled)
2866 disableBodySoft();
2867 }
2868 else
2869 {
2870 if (m_disabled)
2871 enableBodySoft();
2872 }
2873 }
2874
2875 private void changePhysicsStatus(bool NewStatus)
2876 {
2877 CheckDelaySelect();
2878
2879 m_isphysical = NewStatus;
2880
2881 if (!childPrim)
2882 {
2883 if (NewStatus)
2884 {
2885 if (Body == IntPtr.Zero)
2886 MakeBody();
2887 }
2888 else
2889 {
2890 if (Body != IntPtr.Zero)
2891 {
2892 DestroyBody();
2893 }
2894 Stop();
2895 }
2896 }
2897
2898 resetCollisionAccounting();
2899 }
2900
2901 private void changeSize(Vector3 newSize)
2902 {
2903 }
2904
2905 private void changeShape(PrimitiveBaseShape newShape)
2906 {
2907 }
2908
2909 private void changeAddPhysRep(ODEPhysRepData repData)
2910 {
2911 _size = repData.size; //??
2912 _pbs = repData.pbs;
2913 m_shapetype = repData.shapetype;
2914
2915 m_mesh = repData.mesh;
2916
2917 m_assetID = repData.assetID;
2918 m_meshState = repData.meshState;
2919
2920 m_hasOBB = repData.hasOBB;
2921 m_OBBOffset = repData.OBBOffset;
2922 m_OBB = repData.OBB;
2923
2924 primVolume = repData.volume;
2925
2926 CreateGeom();
2927
2928 if (prim_geom != IntPtr.Zero)
2929 {
2930 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
2931 d.Quaternion myrot = new d.Quaternion();
2932 myrot.X = _orientation.X;
2933 myrot.Y = _orientation.Y;
2934 myrot.Z = _orientation.Z;
2935 myrot.W = _orientation.W;
2936 d.GeomSetQuaternion(prim_geom, ref myrot);
2937 }
2938
2939 if (!m_isphysical)
2940 {
2941 SetInStaticSpace(this);
2942 UpdateCollisionCatFlags();
2943 ApplyCollisionCatFlags();
2944 }
2945 else
2946 MakeBody();
2947
2948 if ((m_meshState & MeshState.NeedMask) != 0)
2949 {
2950 repData.size = _size;
2951 repData.pbs = _pbs;
2952 repData.shapetype = m_shapetype;
2953 _parent_scene.m_meshWorker.RequestMesh(repData);
2954 }
2955 }
2956
2957 private void changePhysRepData(ODEPhysRepData repData)
2958 {
2959 CheckDelaySelect();
2960
2961 OdePrim parent = (OdePrim)_parent;
2962
2963 bool chp = childPrim;
2964
2965 if (chp)
2966 {
2967 if (parent != null)
2968 {
2969 parent.DestroyBody();
2970 }
2971 }
2972 else
2973 {
2974 DestroyBody();
2975 }
2976
2977 RemoveGeom();
2978
2979 _size = repData.size;
2980 _pbs = repData.pbs;
2981 m_shapetype = repData.shapetype;
2982
2983 m_mesh = repData.mesh;
2984
2985 m_assetID = repData.assetID;
2986 m_meshState = repData.meshState;
2987
2988 m_hasOBB = repData.hasOBB;
2989 m_OBBOffset = repData.OBBOffset;
2990 m_OBB = repData.OBB;
2991
2992 primVolume = repData.volume;
2993
2994 CreateGeom();
2995
2996 if (prim_geom != IntPtr.Zero)
2997 {
2998 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
2999 d.Quaternion myrot = new d.Quaternion();
3000 myrot.X = _orientation.X;
3001 myrot.Y = _orientation.Y;
3002 myrot.Z = _orientation.Z;
3003 myrot.W = _orientation.W;
3004 d.GeomSetQuaternion(prim_geom, ref myrot);
3005 }
3006
3007 if (m_isphysical)
3008 {
3009 if (chp)
3010 {
3011 if (parent != null)
3012 {
3013 parent.MakeBody();
3014 }
3015 }
3016 else
3017 MakeBody();
3018 }
3019 else
3020 {
3021 SetInStaticSpace(this);
3022 UpdateCollisionCatFlags();
3023 ApplyCollisionCatFlags();
3024 }
3025
3026 resetCollisionAccounting();
3027
3028 if ((m_meshState & MeshState.NeedMask) != 0)
3029 {
3030 repData.size = _size;
3031 repData.pbs = _pbs;
3032 repData.shapetype = m_shapetype;
3033 _parent_scene.m_meshWorker.RequestMesh(repData);
3034 }
3035 }
3036
3037 private void changeFloatOnWater(bool newval)
3038 {
3039 m_collidesWater = newval;
3040
3041 UpdateCollisionCatFlags();
3042 ApplyCollisionCatFlags();
3043 }
3044
3045 private void changeSetTorque(Vector3 newtorque)
3046 {
3047 if (!m_isSelected)
3048 {
3049 if (m_isphysical && Body != IntPtr.Zero)
3050 {
3051 if (m_disabled)
3052 enableBodySoft();
3053 else if (!d.BodyIsEnabled(Body))
3054 d.BodyEnable(Body);
3055
3056 }
3057 m_torque = newtorque;
3058 }
3059 }
3060
3061 private void changeForce(Vector3 force)
3062 {
3063 m_force = force;
3064 if (Body != IntPtr.Zero && !d.BodyIsEnabled(Body))
3065 d.BodyEnable(Body);
3066 }
3067
3068 private void changeAddForce(Vector3 theforce)
3069 {
3070 m_forceacc += theforce;
3071 if (!m_isSelected)
3072 {
3073 lock (this)
3074 {
3075 //m_log.Info("[PHYSICS]: dequeing forcelist");
3076 if (m_isphysical && Body != IntPtr.Zero)
3077 {
3078 if (m_disabled)
3079 enableBodySoft();
3080 else if (!d.BodyIsEnabled(Body))
3081 d.BodyEnable(Body);
3082 }
3083 }
3084 m_collisionscore = 0;
3085 }
3086 }
3087
3088 // actually angular impulse
3089 private void changeAddAngularImpulse(Vector3 aimpulse)
3090 {
3091 m_angularForceacc += aimpulse * m_invTimeStep;
3092 if (!m_isSelected)
3093 {
3094 lock (this)
3095 {
3096 if (m_isphysical && Body != IntPtr.Zero)
3097 {
3098 if (m_disabled)
3099 enableBodySoft();
3100 else if (!d.BodyIsEnabled(Body))
3101 d.BodyEnable(Body);
3102 }
3103 }
3104 m_collisionscore = 0;
3105 }
3106 }
3107
3108 private void changevelocity(Vector3 newVel)
3109 {
3110 float len = newVel.LengthSquared();
3111 if (len > 100000.0f) // limit to 100m/s
3112 {
3113 len = 100.0f / (float)Math.Sqrt(len);
3114 newVel *= len;
3115 }
3116
3117 if (!m_isSelected)
3118 {
3119 if (Body != IntPtr.Zero)
3120 {
3121 if (m_disabled)
3122 enableBodySoft();
3123 else if (!d.BodyIsEnabled(Body))
3124 d.BodyEnable(Body);
3125
3126 d.BodySetLinearVel(Body, newVel.X, newVel.Y, newVel.Z);
3127 }
3128 //resetCollisionAccounting();
3129 }
3130 _velocity = newVel;
3131 }
3132
3133 private void changeangvelocity(Vector3 newAngVel)
3134 {
3135 float len = newAngVel.LengthSquared();
3136 if (len > _parent_scene.maxAngVelocitySQ)
3137 {
3138 len = _parent_scene.maximumAngularVelocity / (float)Math.Sqrt(len);
3139 newAngVel *= len;
3140 }
3141
3142 if (!m_isSelected)
3143 {
3144 if (Body != IntPtr.Zero)
3145 {
3146 if (m_disabled)
3147 enableBodySoft();
3148 else if (!d.BodyIsEnabled(Body))
3149 d.BodyEnable(Body);
3150
3151
3152 d.BodySetAngularVel(Body, newAngVel.X, newAngVel.Y, newAngVel.Z);
3153 }
3154 //resetCollisionAccounting();
3155 }
3156 m_rotationalVelocity = newAngVel;
3157 }
3158
3159 private void changeVolumedetetion(bool newVolDtc)
3160 {
3161 m_isVolumeDetect = newVolDtc;
3162 m_fakeisVolumeDetect = newVolDtc;
3163 UpdateCollisionCatFlags();
3164 ApplyCollisionCatFlags();
3165 }
3166
3167 protected void changeBuilding(bool newbuilding)
3168 {
3169 // Check if we need to do anything
3170 if (newbuilding == m_building)
3171 return;
3172
3173 if ((bool)newbuilding)
3174 {
3175 m_building = true;
3176 if (!childPrim)
3177 DestroyBody();
3178 }
3179 else
3180 {
3181 m_building = false;
3182 CheckDelaySelect();
3183 if (!childPrim)
3184 MakeBody();
3185 }
3186 if (!childPrim && childrenPrim.Count > 0)
3187 {
3188 foreach (OdePrim prm in childrenPrim)
3189 prm.changeBuilding(m_building); // call directly
3190 }
3191 }
3192
3193 public void changeSetVehicle(VehicleData vdata)
3194 {
3195 if (m_vehicle == null)
3196 m_vehicle = new ODEDynamics(this);
3197 m_vehicle.DoSetVehicle(vdata);
3198 }
3199
3200 private void changeVehicleType(int value)
3201 {
3202 if (value == (int)Vehicle.TYPE_NONE)
3203 {
3204 if (m_vehicle != null)
3205 m_vehicle = null;
3206 }
3207 else
3208 {
3209 if (m_vehicle == null)
3210 m_vehicle = new ODEDynamics(this);
3211
3212 m_vehicle.ProcessTypeChange((Vehicle)value);
3213 }
3214 }
3215
3216 private void changeVehicleFloatParam(strVehicleFloatParam fp)
3217 {
3218 if (m_vehicle == null)
3219 return;
3220
3221 m_vehicle.ProcessFloatVehicleParam((Vehicle)fp.param, fp.value);
3222 }
3223
3224 private void changeVehicleVectorParam(strVehicleVectorParam vp)
3225 {
3226 if (m_vehicle == null)
3227 return;
3228 m_vehicle.ProcessVectorVehicleParam((Vehicle)vp.param, vp.value);
3229 }
3230
3231 private void changeVehicleRotationParam(strVehicleQuatParam qp)
3232 {
3233 if (m_vehicle == null)
3234 return;
3235 m_vehicle.ProcessRotationVehicleParam((Vehicle)qp.param, qp.value);
3236 }
3237
3238 private void changeVehicleFlags(strVehicleBoolParam bp)
3239 {
3240 if (m_vehicle == null)
3241 return;
3242 m_vehicle.ProcessVehicleFlags(bp.param, bp.value);
3243 }
3244
3245 private void changeBuoyancy(float b)
3246 {
3247 m_buoyancy = b;
3248 }
3249
3250 private void changePIDTarget(Vector3 trg)
3251 {
3252 m_PIDTarget = trg;
3253 }
3254
3255 private void changePIDTau(float tau)
3256 {
3257 m_PIDTau = tau;
3258 }
3259
3260 private void changePIDActive(bool val)
3261 {
3262 m_usePID = val;
3263 }
3264
3265 private void changePIDHoverHeight(float val)
3266 {
3267 m_PIDHoverHeight = val;
3268 if (val == 0)
3269 m_useHoverPID = false;
3270 }
3271
3272 private void changePIDHoverType(PIDHoverType type)
3273 {
3274 m_PIDHoverType = type;
3275 }
3276
3277 private void changePIDHoverTau(float tau)
3278 {
3279 m_PIDHoverTau = tau;
3280 }
3281
3282 private void changePIDHoverActive(bool active)
3283 {
3284 m_useHoverPID = active;
3285 }
3286
3287 #endregion
3288
3289 public void Move()
3290 {
3291 if (!childPrim && m_isphysical && Body != IntPtr.Zero &&
3292 !m_disabled && !m_isSelected && !m_building && !m_outbounds)
3293 {
3294 if (!d.BodyIsEnabled(Body))
3295 {
3296 // let vehicles sleep
3297 if (m_vehicle != null && m_vehicle.Type != Vehicle.TYPE_NONE)
3298 return;
3299
3300 if (++bodydisablecontrol < 50)
3301 return;
3302
3303 // clear residuals
3304 d.BodySetAngularVel(Body,0f,0f,0f);
3305 d.BodySetLinearVel(Body,0f,0f,0f);
3306 _zeroFlag = true;
3307 d.BodyEnable(Body);
3308 bodydisablecontrol = -4;
3309 }
3310
3311 if(bodydisablecontrol < 0)
3312 bodydisablecontrol ++;
3313
3314 d.Vector3 lpos = d.GeomGetPosition(prim_geom); // root position that is seem by rest of simulator
3315
3316 if (m_vehicle != null && m_vehicle.Type != Vehicle.TYPE_NONE)
3317 {
3318 // 'VEHICLES' are dealt with in ODEDynamics.cs
3319 m_vehicle.Step();
3320 return;
3321 }
3322
3323 float fx = 0;
3324 float fy = 0;
3325 float fz = 0;
3326
3327 float m_mass = _mass;
3328
3329 if (m_usePID && m_PIDTau > 0)
3330 {
3331 // for now position error
3332 _target_velocity =
3333 new Vector3(
3334 (m_PIDTarget.X - lpos.X),
3335 (m_PIDTarget.Y - lpos.Y),
3336 (m_PIDTarget.Z - lpos.Z)
3337 );
3338
3339 if (_target_velocity.ApproxEquals(Vector3.Zero, 0.02f))
3340 {
3341 d.BodySetPosition(Body, m_PIDTarget.X, m_PIDTarget.Y, m_PIDTarget.Z);
3342 d.BodySetLinearVel(Body, 0, 0, 0);
3343 return;
3344 }
3345 else
3346 {
3347 _zeroFlag = false;
3348
3349 float tmp = 1 / m_PIDTau;
3350 _target_velocity *= tmp;
3351
3352 // apply limits
3353 tmp = _target_velocity.Length();
3354 if (tmp > 50.0f)
3355 {
3356 tmp = 50 / tmp;
3357 _target_velocity *= tmp;
3358 }
3359 else if (tmp < 0.05f)
3360 {
3361 tmp = 0.05f / tmp;
3362 _target_velocity *= tmp;
3363 }
3364
3365 d.Vector3 vel = d.BodyGetLinearVel(Body);
3366 fx = (_target_velocity.X - vel.X) * m_invTimeStep;
3367 fy = (_target_velocity.Y - vel.Y) * m_invTimeStep;
3368 fz = (_target_velocity.Z - vel.Z) * m_invTimeStep;
3369// d.BodySetLinearVel(Body, _target_velocity.X, _target_velocity.Y, _target_velocity.Z);
3370 }
3371 } // end if (m_usePID)
3372
3373 // Hover PID Controller needs to be mutually exlusive to MoveTo PID controller
3374 else if (m_useHoverPID && m_PIDHoverTau != 0 && m_PIDHoverHeight != 0)
3375 {
3376
3377 // Non-Vehicles have a limited set of Hover options.
3378 // determine what our target height really is based on HoverType
3379
3380 m_groundHeight = _parent_scene.GetTerrainHeightAtXY(lpos.X, lpos.Y);
3381
3382 switch (m_PIDHoverType)
3383 {
3384 case PIDHoverType.Ground:
3385 m_targetHoverHeight = m_groundHeight + m_PIDHoverHeight;
3386 break;
3387
3388 case PIDHoverType.GroundAndWater:
3389 m_waterHeight = _parent_scene.GetWaterLevel();
3390 if (m_groundHeight > m_waterHeight)
3391 m_targetHoverHeight = m_groundHeight + m_PIDHoverHeight;
3392 else
3393 m_targetHoverHeight = m_waterHeight + m_PIDHoverHeight;
3394 break;
3395 } // end switch (m_PIDHoverType)
3396
3397 // don't go underground unless volumedetector
3398
3399 if (m_targetHoverHeight > m_groundHeight || m_isVolumeDetect)
3400 {
3401 d.Vector3 vel = d.BodyGetLinearVel(Body);
3402
3403 fz = (m_targetHoverHeight - lpos.Z);
3404
3405 // if error is zero, use position control; otherwise, velocity control
3406 if (Math.Abs(fz) < 0.01f)
3407 {
3408 d.BodySetPosition(Body, lpos.X, lpos.Y, m_targetHoverHeight);
3409 d.BodySetLinearVel(Body, vel.X, vel.Y, 0);
3410 }
3411 else
3412 {
3413 _zeroFlag = false;
3414 fz /= m_PIDHoverTau;
3415
3416 float tmp = Math.Abs(fz);
3417 if (tmp > 50)
3418 fz = 50 * Math.Sign(fz);
3419 else if (tmp < 0.1)
3420 fz = 0.1f * Math.Sign(fz);
3421
3422 fz = ((fz - vel.Z) * m_invTimeStep);
3423 }
3424 }
3425 }
3426 else
3427 {
3428 float b = (1.0f - m_buoyancy) * m_gravmod;
3429 fx = _parent_scene.gravityx * b;
3430 fy = _parent_scene.gravityy * b;
3431 fz = _parent_scene.gravityz * b;
3432 }
3433
3434 fx *= m_mass;
3435 fy *= m_mass;
3436 fz *= m_mass;
3437
3438 // constant force
3439 fx += m_force.X;
3440 fy += m_force.Y;
3441 fz += m_force.Z;
3442
3443 fx += m_forceacc.X;
3444 fy += m_forceacc.Y;
3445 fz += m_forceacc.Z;
3446
3447 m_forceacc = Vector3.Zero;
3448
3449 //m_log.Info("[OBJPID]: X:" + fx.ToString() + " Y:" + fy.ToString() + " Z:" + fz.ToString());
3450 if (fx != 0 || fy != 0 || fz != 0)
3451 {
3452 d.BodyAddForce(Body, fx, fy, fz);
3453 //Console.WriteLine("AddForce " + fx + "," + fy + "," + fz);
3454 }
3455
3456 Vector3 trq;
3457
3458 trq = m_torque;
3459 trq += m_angularForceacc;
3460 m_angularForceacc = Vector3.Zero;
3461 if (trq.X != 0 || trq.Y != 0 || trq.Z != 0)
3462 {
3463 d.BodyAddTorque(Body, trq.X, trq.Y, trq.Z);
3464 }
3465 }
3466 else
3467 { // is not physical, or is not a body or is selected
3468 // _zeroPosition = d.BodyGetPosition(Body);
3469 return;
3470 //Console.WriteLine("Nothing " + Name);
3471
3472 }
3473 }
3474
3475 public void UpdatePositionAndVelocity(int frame)
3476 {
3477 if (_parent == null && !m_disabled && !m_building && !m_outbounds && Body != IntPtr.Zero)
3478 {
3479 bool bodyenabled = d.BodyIsEnabled(Body);
3480
3481 if(bodydisablecontrol < 0)
3482 return;
3483
3484 if (bodyenabled || !_zeroFlag)
3485 {
3486 bool lastZeroFlag = _zeroFlag;
3487
3488 d.Vector3 lpos = d.GeomGetPosition(prim_geom);
3489
3490 // check outside region
3491 if (lpos.Z < -100 || lpos.Z > 100000f)
3492 {
3493 m_outbounds = true;
3494
3495 lpos.Z = Util.Clip(lpos.Z, -100f, 100000f);
3496 _acceleration.X = 0;
3497 _acceleration.Y = 0;
3498 _acceleration.Z = 0;
3499
3500 _velocity.X = 0;
3501 _velocity.Y = 0;
3502 _velocity.Z = 0;
3503 m_rotationalVelocity.X = 0;
3504 m_rotationalVelocity.Y = 0;
3505 m_rotationalVelocity.Z = 0;
3506
3507 d.BodySetLinearVel(Body, 0, 0, 0); // stop it
3508 d.BodySetAngularVel(Body, 0, 0, 0); // stop it
3509 d.BodySetPosition(Body, lpos.X, lpos.Y, lpos.Z); // put it somewhere
3510 m_lastposition = _position;
3511 m_lastorientation = _orientation;
3512
3513 base.RequestPhysicsterseUpdate();
3514
3515// throttleCounter = 0;
3516 _zeroFlag = true;
3517
3518 disableBodySoft(); // disable it and colisions
3519 base.RaiseOutOfBounds(_position);
3520 return;
3521 }
3522
3523 if (lpos.X < 0f)
3524 {
3525 _position.X = Util.Clip(lpos.X, -2f, -0.1f);
3526 m_outbounds = true;
3527 }
3528 else if (lpos.X > _parent_scene.WorldExtents.X)
3529 {
3530 _position.X = Util.Clip(lpos.X, _parent_scene.WorldExtents.X + 0.1f, _parent_scene.WorldExtents.X + 2f);
3531 m_outbounds = true;
3532 }
3533 if (lpos.Y < 0f)
3534 {
3535 _position.Y = Util.Clip(lpos.Y, -2f, -0.1f);
3536 m_outbounds = true;
3537 }
3538 else if (lpos.Y > _parent_scene.WorldExtents.Y)
3539 {
3540 _position.Y = Util.Clip(lpos.Y, _parent_scene.WorldExtents.Y + 0.1f, _parent_scene.WorldExtents.Y + 2f);
3541 m_outbounds = true;
3542 }
3543
3544 if (m_outbounds)
3545 {
3546 m_lastposition = _position;
3547 m_lastorientation = _orientation;
3548
3549 d.Vector3 dtmp = d.BodyGetAngularVel(Body);
3550 m_rotationalVelocity.X = dtmp.X;
3551 m_rotationalVelocity.Y = dtmp.Y;
3552 m_rotationalVelocity.Z = dtmp.Z;
3553
3554 dtmp = d.BodyGetLinearVel(Body);
3555 _velocity.X = dtmp.X;
3556 _velocity.Y = dtmp.Y;
3557 _velocity.Z = dtmp.Z;
3558
3559 d.BodySetLinearVel(Body, 0, 0, 0); // stop it
3560 d.BodySetAngularVel(Body, 0, 0, 0);
3561 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
3562 disableBodySoft(); // stop collisions
3563 UnSubscribeEvents();
3564
3565 base.RequestPhysicsterseUpdate();
3566 return;
3567 }
3568
3569 d.Quaternion ori;
3570 d.GeomCopyQuaternion(prim_geom, out ori);
3571
3572 // decide if moving
3573 // use positions since this are integrated quantities
3574 // tolerance values depende a lot on simulation noise...
3575 // use simple math.abs since we dont need to be exact
3576 if(!bodyenabled)
3577 {
3578 _zeroFlag = true;
3579 }
3580 else
3581 {
3582 float poserror;
3583 float angerror;
3584 if(_zeroFlag)
3585 {
3586 poserror = 0.01f;
3587 angerror = 0.001f;
3588 }
3589 else
3590 {
3591 poserror = 0.005f;
3592 angerror = 0.0005f;
3593 }
3594
3595 if (
3596 (Math.Abs(_position.X - lpos.X) < poserror)
3597 && (Math.Abs(_position.Y - lpos.Y) < poserror)
3598 && (Math.Abs(_position.Z - lpos.Z) < poserror)
3599 && (Math.Abs(_orientation.X - ori.X) < angerror)
3600 && (Math.Abs(_orientation.Y - ori.Y) < angerror)
3601 && (Math.Abs(_orientation.Z - ori.Z) < angerror) // ignore W
3602 )
3603 _zeroFlag = true;
3604 else
3605 _zeroFlag = false;
3606 }
3607
3608 // update position
3609 if (!(_zeroFlag && lastZeroFlag))
3610 {
3611 _position.X = lpos.X;
3612 _position.Y = lpos.Y;
3613 _position.Z = lpos.Z;
3614
3615 _orientation.X = ori.X;
3616 _orientation.Y = ori.Y;
3617 _orientation.Z = ori.Z;
3618 _orientation.W = ori.W;
3619 }
3620
3621 // update velocities and aceleration
3622 if (_zeroFlag || lastZeroFlag)
3623 {
3624 // disable interpolators
3625 _velocity = Vector3.Zero;
3626 _acceleration = Vector3.Zero;
3627 m_rotationalVelocity = Vector3.Zero;
3628 }
3629 else
3630 {
3631 d.Vector3 vel = d.BodyGetLinearVel(Body);
3632
3633 _acceleration = _velocity;
3634
3635 if ((Math.Abs(vel.X) < 0.005f) &&
3636 (Math.Abs(vel.Y) < 0.005f) &&
3637 (Math.Abs(vel.Z) < 0.005f))
3638 {
3639 _velocity = Vector3.Zero;
3640 float t = -m_invTimeStep;
3641 _acceleration = _acceleration * t;
3642 }
3643 else
3644 {
3645 _velocity.X = vel.X;
3646 _velocity.Y = vel.Y;
3647 _velocity.Z = vel.Z;
3648 _acceleration = (_velocity - _acceleration) * m_invTimeStep;
3649 }
3650
3651 if ((Math.Abs(_acceleration.X) < 0.01f) &&
3652 (Math.Abs(_acceleration.Y) < 0.01f) &&
3653 (Math.Abs(_acceleration.Z) < 0.01f))
3654 {
3655 _acceleration = Vector3.Zero;
3656 }
3657
3658 vel = d.BodyGetAngularVel(Body);
3659 if ((Math.Abs(vel.X) < 0.0001) &&
3660 (Math.Abs(vel.Y) < 0.0001) &&
3661 (Math.Abs(vel.Z) < 0.0001)
3662 )
3663 {
3664 m_rotationalVelocity = Vector3.Zero;
3665 }
3666 else
3667 {
3668 m_rotationalVelocity.X = vel.X;
3669 m_rotationalVelocity.Y = vel.Y;
3670 m_rotationalVelocity.Z = vel.Z;
3671 }
3672 }
3673
3674 if (_zeroFlag)
3675 {
3676 if (!m_lastUpdateSent)
3677 {
3678 base.RequestPhysicsterseUpdate();
3679 if (lastZeroFlag)
3680 m_lastUpdateSent = true;
3681 }
3682 return;
3683 }
3684
3685 base.RequestPhysicsterseUpdate();
3686 m_lastUpdateSent = false;
3687 }
3688 }
3689 }
3690
3691 internal static bool QuaternionIsFinite(Quaternion q)
3692 {
3693 if (Single.IsNaN(q.X) || Single.IsInfinity(q.X))
3694 return false;
3695 if (Single.IsNaN(q.Y) || Single.IsInfinity(q.Y))
3696 return false;
3697 if (Single.IsNaN(q.Z) || Single.IsInfinity(q.Z))
3698 return false;
3699 if (Single.IsNaN(q.W) || Single.IsInfinity(q.W))
3700 return false;
3701 return true;
3702 }
3703
3704 internal static void DMassSubPartFromObj(ref d.Mass part, ref d.Mass theobj)
3705 {
3706 // assumes object center of mass is zero
3707 float smass = part.mass;
3708 theobj.mass -= smass;
3709
3710 smass *= 1.0f / (theobj.mass); ;
3711
3712 theobj.c.X -= part.c.X * smass;
3713 theobj.c.Y -= part.c.Y * smass;
3714 theobj.c.Z -= part.c.Z * smass;
3715
3716 theobj.I.M00 -= part.I.M00;
3717 theobj.I.M01 -= part.I.M01;
3718 theobj.I.M02 -= part.I.M02;
3719 theobj.I.M10 -= part.I.M10;
3720 theobj.I.M11 -= part.I.M11;
3721 theobj.I.M12 -= part.I.M12;
3722 theobj.I.M20 -= part.I.M20;
3723 theobj.I.M21 -= part.I.M21;
3724 theobj.I.M22 -= part.I.M22;
3725 }
3726
3727 private void donullchange()
3728 {
3729 }
3730
3731 public bool DoAChange(changes what, object arg)
3732 {
3733 if (prim_geom == IntPtr.Zero && what != changes.Add && what != changes.AddPhysRep && what != changes.Remove)
3734 {
3735 return false;
3736 }
3737
3738 // nasty switch
3739 switch (what)
3740 {
3741 case changes.Add:
3742 changeadd();
3743 break;
3744
3745 case changes.AddPhysRep:
3746 changeAddPhysRep((ODEPhysRepData)arg);
3747 break;
3748
3749 case changes.Remove:
3750 //If its being removed, we don't want to rebuild the physical rep at all, so ignore this stuff...
3751 //When we return true, it destroys all of the prims in the linkset anyway
3752 if (_parent != null)
3753 {
3754 OdePrim parent = (OdePrim)_parent;
3755 parent.ChildRemove(this, false);
3756 }
3757 else
3758 ChildRemove(this, false);
3759
3760 m_vehicle = null;
3761 RemoveGeom();
3762 m_targetSpace = IntPtr.Zero;
3763 UnSubscribeEvents();
3764 return true;
3765
3766 case changes.Link:
3767 OdePrim tmp = (OdePrim)arg;
3768 changeLink(tmp);
3769 break;
3770
3771 case changes.DeLink:
3772 changeLink(null);
3773 break;
3774
3775 case changes.Position:
3776 changePosition((Vector3)arg);
3777 break;
3778
3779 case changes.Orientation:
3780 changeOrientation((Quaternion)arg);
3781 break;
3782
3783 case changes.PosOffset:
3784 donullchange();
3785 break;
3786
3787 case changes.OriOffset:
3788 donullchange();
3789 break;
3790
3791 case changes.Velocity:
3792 changevelocity((Vector3)arg);
3793 break;
3794
3795// case changes.Acceleration:
3796// changeacceleration((Vector3)arg);
3797// break;
3798
3799 case changes.AngVelocity:
3800 changeangvelocity((Vector3)arg);
3801 break;
3802
3803 case changes.Force:
3804 changeForce((Vector3)arg);
3805 break;
3806
3807 case changes.Torque:
3808 changeSetTorque((Vector3)arg);
3809 break;
3810
3811 case changes.AddForce:
3812 changeAddForce((Vector3)arg);
3813 break;
3814
3815 case changes.AddAngForce:
3816 changeAddAngularImpulse((Vector3)arg);
3817 break;
3818
3819 case changes.AngLock:
3820 changeAngularLock((byte)arg);
3821 break;
3822
3823 case changes.Size:
3824 changeSize((Vector3)arg);
3825 break;
3826
3827 case changes.Shape:
3828 changeShape((PrimitiveBaseShape)arg);
3829 break;
3830
3831 case changes.PhysRepData:
3832 changePhysRepData((ODEPhysRepData) arg);
3833 break;
3834
3835 case changes.CollidesWater:
3836 changeFloatOnWater((bool)arg);
3837 break;
3838
3839 case changes.VolumeDtc:
3840 changeVolumedetetion((bool)arg);
3841 break;
3842
3843 case changes.Phantom:
3844 changePhantomStatus((bool)arg);
3845 break;
3846
3847 case changes.Physical:
3848 changePhysicsStatus((bool)arg);
3849 break;
3850
3851 case changes.Selected:
3852 changeSelectedStatus((bool)arg);
3853 break;
3854
3855 case changes.disabled:
3856 changeDisable((bool)arg);
3857 break;
3858
3859 case changes.building:
3860 changeBuilding((bool)arg);
3861 break;
3862
3863 case changes.VehicleType:
3864 changeVehicleType((int)arg);
3865 break;
3866
3867 case changes.VehicleFlags:
3868 changeVehicleFlags((strVehicleBoolParam) arg);
3869 break;
3870
3871 case changes.VehicleFloatParam:
3872 changeVehicleFloatParam((strVehicleFloatParam) arg);
3873 break;
3874
3875 case changes.VehicleVectorParam:
3876 changeVehicleVectorParam((strVehicleVectorParam) arg);
3877 break;
3878
3879 case changes.VehicleRotationParam:
3880 changeVehicleRotationParam((strVehicleQuatParam) arg);
3881 break;
3882
3883 case changes.SetVehicle:
3884 changeSetVehicle((VehicleData) arg);
3885 break;
3886
3887 case changes.Buoyancy:
3888 changeBuoyancy((float)arg);
3889 break;
3890
3891 case changes.PIDTarget:
3892 changePIDTarget((Vector3)arg);
3893 break;
3894
3895 case changes.PIDTau:
3896 changePIDTau((float)arg);
3897 break;
3898
3899 case changes.PIDActive:
3900 changePIDActive((bool)arg);
3901 break;
3902
3903 case changes.PIDHoverHeight:
3904 changePIDHoverHeight((float)arg);
3905 break;
3906
3907 case changes.PIDHoverType:
3908 changePIDHoverType((PIDHoverType)arg);
3909 break;
3910
3911 case changes.PIDHoverTau:
3912 changePIDHoverTau((float)arg);
3913 break;
3914
3915 case changes.PIDHoverActive:
3916 changePIDHoverActive((bool)arg);
3917 break;
3918
3919 case changes.Null:
3920 donullchange();
3921 break;
3922
3923
3924
3925 default:
3926 donullchange();
3927 break;
3928 }
3929 return false;
3930 }
3931
3932 public void AddChange(changes what, object arg)
3933 {
3934 _parent_scene.AddChange((PhysicsActor) this, what, arg);
3935 }
3936
3937
3938 private struct strVehicleBoolParam
3939 {
3940 public int param;
3941 public bool value;
3942 }
3943
3944 private struct strVehicleFloatParam
3945 {
3946 public int param;
3947 public float value;
3948 }
3949
3950 private struct strVehicleQuatParam
3951 {
3952 public int param;
3953 public Quaternion value;
3954 }
3955
3956 private struct strVehicleVectorParam
3957 {
3958 public int param;
3959 public Vector3 value;
3960 }
3961 }
3962}
diff --git a/OpenSim/Region/PhysicsModules/ubOde/ODERayCastRequestManager.cs b/OpenSim/Region/PhysicsModules/ubOde/ODERayCastRequestManager.cs
new file mode 100644
index 0000000..b82d593
--- /dev/null
+++ b/OpenSim/Region/PhysicsModules/ubOde/ODERayCastRequestManager.cs
@@ -0,0 +1,680 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31using System.Runtime.InteropServices;
32using System.Text;
33using OpenSim.Framework;
34using OpenSim.Region.PhysicsModules.SharedBase;
35using OdeAPI;
36using log4net;
37using OpenMetaverse;
38
39namespace OpenSim.Region.PhysicsModule.ubOde
40{
41 /// <summary>
42 /// Processes raycast requests as ODE is in a state to be able to do them.
43 /// This ensures that it's thread safe and there will be no conflicts.
44 /// Requests get returned by a different thread then they were requested by.
45 /// </summary>
46 public class ODERayCastRequestManager
47 {
48 /// <summary>
49 /// Pending ray requests
50 /// </summary>
51 protected OpenSim.Framework.LocklessQueue<ODERayRequest> m_PendingRequests = new OpenSim.Framework.LocklessQueue<ODERayRequest>();
52
53 /// <summary>
54 /// Scene that created this object.
55 /// </summary>
56 private ODEScene m_scene;
57
58 IntPtr ray; // the ray. we only need one for our lifetime
59 IntPtr Sphere;
60 IntPtr Box;
61 IntPtr Plane;
62
63 private int CollisionContactGeomsPerTest = 25;
64 private const int DefaultMaxCount = 25;
65 private const int MaxTimePerCallMS = 30;
66
67 /// <summary>
68 /// ODE near callback delegate
69 /// </summary>
70 private d.NearCallback nearCallback;
71 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
72 private List<ContactResult> m_contactResults = new List<ContactResult>();
73 private RayFilterFlags CurrentRayFilter;
74 private int CurrentMaxCount;
75
76 public ODERayCastRequestManager(ODEScene pScene)
77 {
78 m_scene = pScene;
79 nearCallback = near;
80 ray = d.CreateRay(IntPtr.Zero, 1.0f);
81 d.GeomSetCategoryBits(ray, 0);
82 Box = d.CreateBox(IntPtr.Zero, 1.0f, 1.0f, 1.0f);
83 d.GeomSetCategoryBits(Box, 0);
84 Sphere = d.CreateSphere(IntPtr.Zero,1.0f);
85 d.GeomSetCategoryBits(Sphere, 0);
86 Plane = d.CreatePlane(IntPtr.Zero, 0f,0f,1f,1f);
87 d.GeomSetCategoryBits(Sphere, 0);
88 }
89
90 public void QueueRequest(ODERayRequest req)
91 {
92 if (req.Count == 0)
93 req.Count = DefaultMaxCount;
94
95 m_PendingRequests.Enqueue(req);
96 }
97
98 /// <summary>
99 /// Process all queued raycast requests
100 /// </summary>
101 /// <returns>Time in MS the raycasts took to process.</returns>
102 public int ProcessQueuedRequests()
103 {
104
105 if (m_PendingRequests.Count <= 0)
106 return 0;
107
108 if (m_scene.ContactgeomsArray == IntPtr.Zero || ray == IntPtr.Zero)
109 // oops something got wrong or scene isn't ready still
110 {
111 m_PendingRequests.Clear();
112 return 0;
113 }
114
115 int time = Util.EnvironmentTickCount();
116
117 ODERayRequest req;
118 int closestHit;
119 int backfacecull;
120 CollisionCategories catflags;
121
122 while (m_PendingRequests.Dequeue(out req))
123 {
124 if (req.callbackMethod != null)
125 {
126 IntPtr geom = IntPtr.Zero;
127 if (req.actor != null)
128 {
129 if (m_scene.haveActor(req.actor))
130 {
131 if (req.actor is OdePrim)
132 geom = ((OdePrim)req.actor).prim_geom;
133 else if (req.actor is OdeCharacter)
134 geom = ((OdePrim)req.actor).prim_geom;
135 }
136 if (geom == IntPtr.Zero)
137 {
138 NoContacts(req);
139 continue;
140 }
141 }
142
143 CurrentRayFilter = req.filter;
144 CurrentMaxCount = req.Count;
145
146 CollisionContactGeomsPerTest = req.Count & 0xffff;
147
148 closestHit = ((CurrentRayFilter & RayFilterFlags.ClosestHit) == 0 ? 0 : 1);
149 backfacecull = ((CurrentRayFilter & RayFilterFlags.BackFaceCull) == 0 ? 0 : 1);
150
151 if (req.callbackMethod is ProbeBoxCallback)
152 {
153 if (CollisionContactGeomsPerTest > 80)
154 CollisionContactGeomsPerTest = 80;
155 d.GeomBoxSetLengths(Box, req.Normal.X, req.Normal.Y, req.Normal.Z);
156 d.GeomSetPosition(Box, req.Origin.X, req.Origin.Y, req.Origin.Z);
157 d.Quaternion qtmp;
158 qtmp.X = req.orientation.X;
159 qtmp.Y = req.orientation.Y;
160 qtmp.Z = req.orientation.Z;
161 qtmp.W = req.orientation.W;
162 d.GeomSetQuaternion(Box, ref qtmp);
163 }
164 else if (req.callbackMethod is ProbeSphereCallback)
165 {
166 if (CollisionContactGeomsPerTest > 80)
167 CollisionContactGeomsPerTest = 80;
168
169 d.GeomSphereSetRadius(Sphere, req.length);
170 d.GeomSetPosition(Sphere, req.Origin.X, req.Origin.Y, req.Origin.Z);
171 }
172 else if (req.callbackMethod is ProbePlaneCallback)
173 {
174 if (CollisionContactGeomsPerTest > 80)
175 CollisionContactGeomsPerTest = 80;
176
177 d.GeomPlaneSetParams(Plane, req.Normal.X, req.Normal.Y, req.Normal.Z, req.length);
178 }
179
180 else
181 {
182 if (CollisionContactGeomsPerTest > 25)
183 CollisionContactGeomsPerTest = 25;
184
185 d.GeomRaySetLength(ray, req.length);
186 d.GeomRaySet(ray, req.Origin.X, req.Origin.Y, req.Origin.Z, req.Normal.X, req.Normal.Y, req.Normal.Z);
187 d.GeomRaySetParams(ray, 0, backfacecull);
188
189 if (req.callbackMethod is RaycastCallback)
190 {
191 // if we only want one get only one per Collision pair saving memory
192 CurrentRayFilter |= RayFilterFlags.ClosestHit;
193 d.GeomRaySetClosestHit(ray, 1);
194 }
195 else
196 d.GeomRaySetClosestHit(ray, closestHit);
197 }
198
199 if ((CurrentRayFilter & RayFilterFlags.ContactsUnImportant) != 0)
200 unchecked
201 {
202 CollisionContactGeomsPerTest |= (int)d.CONTACTS_UNIMPORTANT;
203 }
204
205 if (geom == IntPtr.Zero)
206 {
207 // translate ray filter to Collision flags
208 catflags = 0;
209 if ((CurrentRayFilter & RayFilterFlags.volumedtc) != 0)
210 catflags |= CollisionCategories.VolumeDtc;
211 if ((CurrentRayFilter & RayFilterFlags.phantom) != 0)
212 catflags |= CollisionCategories.Phantom;
213 if ((CurrentRayFilter & RayFilterFlags.agent) != 0)
214 catflags |= CollisionCategories.Character;
215 if ((CurrentRayFilter & RayFilterFlags.PrimsNonPhantom) != 0)
216 catflags |= CollisionCategories.Geom;
217 if ((CurrentRayFilter & RayFilterFlags.land) != 0)
218 catflags |= CollisionCategories.Land;
219 if ((CurrentRayFilter & RayFilterFlags.water) != 0)
220 catflags |= CollisionCategories.Water;
221
222 if (catflags != 0)
223 {
224 if (req.callbackMethod is ProbeBoxCallback)
225 {
226 catflags |= CollisionCategories.Space;
227 d.GeomSetCollideBits(Box, (uint)catflags);
228 d.GeomSetCategoryBits(Box, (uint)catflags);
229 doProbe(req, Box);
230 }
231 else if (req.callbackMethod is ProbeSphereCallback)
232 {
233 catflags |= CollisionCategories.Space;
234 d.GeomSetCollideBits(Sphere, (uint)catflags);
235 d.GeomSetCategoryBits(Sphere, (uint)catflags);
236 doProbe(req, Sphere);
237 }
238 else if (req.callbackMethod is ProbePlaneCallback)
239 {
240 catflags |= CollisionCategories.Space;
241 d.GeomSetCollideBits(Plane, (uint)catflags);
242 d.GeomSetCategoryBits(Plane, (uint)catflags);
243 doPlane(req,IntPtr.Zero);
244 }
245 else
246 {
247 d.GeomSetCollideBits(ray, (uint)catflags);
248 doSpaceRay(req);
249 }
250 }
251 }
252 else
253 {
254 // if we select a geom don't use filters
255
256 if (req.callbackMethod is ProbePlaneCallback)
257 {
258 d.GeomSetCollideBits(Plane, (uint)CollisionCategories.All);
259 doPlane(req,geom);
260 }
261 else
262 {
263 d.GeomSetCollideBits(ray, (uint)CollisionCategories.All);
264 doGeomRay(req,geom);
265 }
266 }
267 }
268
269 if (Util.EnvironmentTickCountSubtract(time) > MaxTimePerCallMS)
270 break;
271 }
272
273 lock (m_contactResults)
274 m_contactResults.Clear();
275
276 return Util.EnvironmentTickCountSubtract(time);
277 }
278 /// <summary>
279 /// Method that actually initiates the raycast with spaces
280 /// </summary>
281 /// <param name="req"></param>
282 ///
283
284 private void NoContacts(ODERayRequest req)
285 {
286 if (req.callbackMethod is RaycastCallback)
287 {
288 ((RaycastCallback)req.callbackMethod)(false, Vector3.Zero, 0, 0, Vector3.Zero);
289 return;
290 }
291 List<ContactResult> cresult = new List<ContactResult>();
292
293 if (req.callbackMethod is RayCallback)
294 ((RayCallback)req.callbackMethod)(cresult);
295 else if (req.callbackMethod is ProbeBoxCallback)
296 ((ProbeBoxCallback)req.callbackMethod)(cresult);
297 else if (req.callbackMethod is ProbeSphereCallback)
298 ((ProbeSphereCallback)req.callbackMethod)(cresult);
299 }
300
301 private const RayFilterFlags FilterActiveSpace = RayFilterFlags.agent | RayFilterFlags.physical | RayFilterFlags.LSLPhantom;
302// private const RayFilterFlags FilterStaticSpace = RayFilterFlags.water | RayFilterFlags.land | RayFilterFlags.nonphysical | RayFilterFlags.LSLPhanton;
303 private const RayFilterFlags FilterStaticSpace = RayFilterFlags.water | RayFilterFlags.nonphysical | RayFilterFlags.LSLPhantom;
304
305 private void doSpaceRay(ODERayRequest req)
306 {
307 // Collide tests
308 if ((CurrentRayFilter & FilterActiveSpace) != 0)
309 {
310 d.SpaceCollide2(ray, m_scene.ActiveSpace, IntPtr.Zero, nearCallback);
311 d.SpaceCollide2(ray, m_scene.CharsSpace, IntPtr.Zero, nearCallback);
312 }
313 if ((CurrentRayFilter & FilterStaticSpace) != 0 && (m_contactResults.Count < CurrentMaxCount))
314 d.SpaceCollide2(ray, m_scene.StaticSpace, IntPtr.Zero, nearCallback);
315 if ((CurrentRayFilter & RayFilterFlags.land) != 0 && (m_contactResults.Count < CurrentMaxCount))
316 {
317 // current ode land to ray collisions is very bad
318 // so for now limit its range badly
319 if (req.length > 60.0f)
320 d.GeomRaySetLength(ray, 60.0f);
321
322 d.SpaceCollide2(ray, m_scene.GroundSpace, IntPtr.Zero, nearCallback);
323 }
324
325 if (req.callbackMethod is RaycastCallback)
326 {
327 // Define default results
328 bool hitYN = false;
329 uint hitConsumerID = 0;
330 float distance = float.MaxValue;
331 Vector3 closestcontact = Vector3.Zero;
332 Vector3 snormal = Vector3.Zero;
333
334 // Find closest contact and object.
335 lock (m_contactResults)
336 {
337 foreach (ContactResult cResult in m_contactResults)
338 {
339 if(cResult.Depth < distance)
340 {
341 closestcontact = cResult.Pos;
342 hitConsumerID = cResult.ConsumerID;
343 distance = cResult.Depth;
344 snormal = cResult.Normal;
345 }
346 }
347 m_contactResults.Clear();
348 }
349
350 if (distance > 0 && distance < float.MaxValue)
351 hitYN = true;
352 ((RaycastCallback)req.callbackMethod)(hitYN, closestcontact, hitConsumerID, distance, snormal);
353 }
354 else
355 {
356 List<ContactResult> cresult = new List<ContactResult>(m_contactResults.Count);
357 lock (m_PendingRequests)
358 {
359 cresult.AddRange(m_contactResults);
360 m_contactResults.Clear();
361 }
362 ((RayCallback)req.callbackMethod)(cresult);
363 }
364 }
365
366 private void doProbe(ODERayRequest req, IntPtr probe)
367 {
368 // Collide tests
369 if ((CurrentRayFilter & FilterActiveSpace) != 0)
370 {
371 d.SpaceCollide2(probe, m_scene.ActiveSpace, IntPtr.Zero, nearCallback);
372 d.SpaceCollide2(probe, m_scene.CharsSpace, IntPtr.Zero, nearCallback);
373 }
374 if ((CurrentRayFilter & FilterStaticSpace) != 0 && (m_contactResults.Count < CurrentMaxCount))
375 d.SpaceCollide2(probe, m_scene.StaticSpace, IntPtr.Zero, nearCallback);
376 if ((CurrentRayFilter & RayFilterFlags.land) != 0 && (m_contactResults.Count < CurrentMaxCount))
377 d.SpaceCollide2(probe, m_scene.GroundSpace, IntPtr.Zero, nearCallback);
378
379 List<ContactResult> cresult = new List<ContactResult>(m_contactResults.Count);
380 lock (m_PendingRequests)
381 {
382 cresult.AddRange(m_contactResults);
383 m_contactResults.Clear();
384 }
385 if (req.callbackMethod is ProbeBoxCallback)
386 ((ProbeBoxCallback)req.callbackMethod)(cresult);
387 else if (req.callbackMethod is ProbeSphereCallback)
388 ((ProbeSphereCallback)req.callbackMethod)(cresult);
389 }
390
391 private void doPlane(ODERayRequest req,IntPtr geom)
392 {
393 // Collide tests
394 if (geom == IntPtr.Zero)
395 {
396 if ((CurrentRayFilter & FilterActiveSpace) != 0)
397 {
398 d.SpaceCollide2(Plane, m_scene.ActiveSpace, IntPtr.Zero, nearCallback);
399 d.SpaceCollide2(Plane, m_scene.CharsSpace, IntPtr.Zero, nearCallback);
400 }
401 if ((CurrentRayFilter & FilterStaticSpace) != 0 && (m_contactResults.Count < CurrentMaxCount))
402 d.SpaceCollide2(Plane, m_scene.StaticSpace, IntPtr.Zero, nearCallback);
403 if ((CurrentRayFilter & RayFilterFlags.land) != 0 && (m_contactResults.Count < CurrentMaxCount))
404 d.SpaceCollide2(Plane, m_scene.GroundSpace, IntPtr.Zero, nearCallback);
405 }
406 else
407 {
408 d.SpaceCollide2(Plane, geom, IntPtr.Zero, nearCallback);
409 }
410
411 List<ContactResult> cresult = new List<ContactResult>(m_contactResults.Count);
412 lock (m_PendingRequests)
413 {
414 cresult.AddRange(m_contactResults);
415 m_contactResults.Clear();
416 }
417
418 ((ProbePlaneCallback)req.callbackMethod)(cresult);
419 }
420
421 /// <summary>
422 /// Method that actually initiates the raycast with a geom
423 /// </summary>
424 /// <param name="req"></param>
425 private void doGeomRay(ODERayRequest req, IntPtr geom)
426 {
427 // Collide test
428 d.SpaceCollide2(ray, geom, IntPtr.Zero, nearCallback); // still do this to have full AABB pre test
429
430 if (req.callbackMethod is RaycastCallback)
431 {
432 // Define default results
433 bool hitYN = false;
434 uint hitConsumerID = 0;
435 float distance = float.MaxValue;
436 Vector3 closestcontact = Vector3.Zero;
437 Vector3 snormal = Vector3.Zero;
438
439 // Find closest contact and object.
440 lock (m_contactResults)
441 {
442 foreach (ContactResult cResult in m_contactResults)
443 {
444 if(cResult.Depth < distance )
445 {
446 closestcontact = cResult.Pos;
447 hitConsumerID = cResult.ConsumerID;
448 distance = cResult.Depth;
449 snormal = cResult.Normal;
450 }
451 }
452 m_contactResults.Clear();
453 }
454
455 if (distance > 0 && distance < float.MaxValue)
456 hitYN = true;
457
458 ((RaycastCallback)req.callbackMethod)(hitYN, closestcontact, hitConsumerID, distance, snormal);
459 }
460 else
461 {
462 List<ContactResult> cresult = new List<ContactResult>(m_contactResults.Count);
463 lock (m_PendingRequests)
464 {
465 cresult.AddRange(m_contactResults);
466 m_contactResults.Clear();
467 }
468 ((RayCallback)req.callbackMethod)(cresult);
469 }
470 }
471
472 private bool GetCurContactGeom(int index, ref d.ContactGeom newcontactgeom)
473 {
474 IntPtr ContactgeomsArray = m_scene.ContactgeomsArray;
475 if (ContactgeomsArray == IntPtr.Zero || index >= CollisionContactGeomsPerTest)
476 return false;
477
478 IntPtr contactptr = new IntPtr(ContactgeomsArray.ToInt64() + (Int64)(index * d.ContactGeom.unmanagedSizeOf));
479 newcontactgeom = (d.ContactGeom)Marshal.PtrToStructure(contactptr, typeof(d.ContactGeom));
480 return true;
481 }
482
483 // This is the standard Near. g1 is the ray
484 private void near(IntPtr space, IntPtr g1, IntPtr g2)
485 {
486 if (g2 == IntPtr.Zero || g1 == g2)
487 return;
488
489 if (m_contactResults.Count >= CurrentMaxCount)
490 return;
491
492 if (d.GeomIsSpace(g2))
493 {
494 try
495 {
496 d.SpaceCollide2(g1, g2, IntPtr.Zero, nearCallback);
497 }
498 catch (Exception e)
499 {
500 m_log.WarnFormat("[PHYSICS Ray]: Unable to Space collide test an object: {0}", e.Message);
501 }
502 return;
503 }
504
505 int count = 0;
506 try
507 {
508 count = d.CollidePtr(g1, g2, CollisionContactGeomsPerTest, m_scene.ContactgeomsArray, d.ContactGeom.unmanagedSizeOf);
509 }
510 catch (Exception e)
511 {
512 m_log.WarnFormat("[PHYSICS Ray]: Unable to collide test an object: {0}", e.Message);
513 return;
514 }
515
516 if (count == 0)
517 return;
518/*
519 uint cat1 = d.GeomGetCategoryBits(g1);
520 uint cat2 = d.GeomGetCategoryBits(g2);
521 uint col1 = d.GeomGetCollideBits(g1);
522 uint col2 = d.GeomGetCollideBits(g2);
523*/
524
525 uint ID = 0;
526 PhysicsActor p2 = null;
527
528 m_scene.actor_name_map.TryGetValue(g2, out p2);
529
530 if (p2 == null)
531 return;
532
533 switch (p2.PhysicsActorType)
534 {
535 case (int)ActorTypes.Prim:
536
537 RayFilterFlags thisFlags;
538
539 if (p2.IsPhysical)
540 thisFlags = RayFilterFlags.physical;
541 else
542 thisFlags = RayFilterFlags.nonphysical;
543
544 if (p2.Phantom)
545 thisFlags |= RayFilterFlags.phantom;
546
547 if (p2.IsVolumeDtc)
548 thisFlags |= RayFilterFlags.volumedtc;
549
550 if ((thisFlags & CurrentRayFilter) == 0)
551 return;
552
553 ID = ((OdePrim)p2).LocalID;
554 break;
555
556 case (int)ActorTypes.Agent:
557
558 if ((CurrentRayFilter & RayFilterFlags.agent) == 0)
559 return;
560 else
561 ID = ((OdeCharacter)p2).LocalID;
562 break;
563
564 case (int)ActorTypes.Ground:
565
566 if ((CurrentRayFilter & RayFilterFlags.land) == 0)
567 return;
568 break;
569
570 case (int)ActorTypes.Water:
571
572 if ((CurrentRayFilter & RayFilterFlags.water) == 0)
573 return;
574 break;
575
576 default:
577 break;
578 }
579
580 d.ContactGeom curcontact = new d.ContactGeom();
581
582 // closestHit for now only works for meshs, so must do it for others
583 if ((CurrentRayFilter & RayFilterFlags.ClosestHit) == 0)
584 {
585 // Loop all contacts, build results.
586 for (int i = 0; i < count; i++)
587 {
588 if (!GetCurContactGeom(i, ref curcontact))
589 break;
590
591 ContactResult collisionresult = new ContactResult();
592 collisionresult.ConsumerID = ID;
593 collisionresult.Pos.X = curcontact.pos.X;
594 collisionresult.Pos.Y = curcontact.pos.Y;
595 collisionresult.Pos.Z = curcontact.pos.Z;
596 collisionresult.Depth = curcontact.depth;
597 collisionresult.Normal.X = curcontact.normal.X;
598 collisionresult.Normal.Y = curcontact.normal.Y;
599 collisionresult.Normal.Z = curcontact.normal.Z;
600 lock (m_contactResults)
601 {
602 m_contactResults.Add(collisionresult);
603 if (m_contactResults.Count >= CurrentMaxCount)
604 return;
605 }
606 }
607 }
608 else
609 {
610 // keep only closest contact
611 ContactResult collisionresult = new ContactResult();
612 collisionresult.ConsumerID = ID;
613 collisionresult.Depth = float.MaxValue;
614
615 for (int i = 0; i < count; i++)
616 {
617 if (!GetCurContactGeom(i, ref curcontact))
618 break;
619
620 if (curcontact.depth < collisionresult.Depth)
621 {
622 collisionresult.Pos.X = curcontact.pos.X;
623 collisionresult.Pos.Y = curcontact.pos.Y;
624 collisionresult.Pos.Z = curcontact.pos.Z;
625 collisionresult.Depth = curcontact.depth;
626 collisionresult.Normal.X = curcontact.normal.X;
627 collisionresult.Normal.Y = curcontact.normal.Y;
628 collisionresult.Normal.Z = curcontact.normal.Z;
629 }
630 }
631
632 if (collisionresult.Depth != float.MaxValue)
633 {
634 lock (m_contactResults)
635 m_contactResults.Add(collisionresult);
636 }
637 }
638 }
639
640 /// <summary>
641 /// Dereference the creator scene so that it can be garbage collected if needed.
642 /// </summary>
643 internal void Dispose()
644 {
645 m_scene = null;
646 if (ray != IntPtr.Zero)
647 {
648 d.GeomDestroy(ray);
649 ray = IntPtr.Zero;
650 }
651 if (Box != IntPtr.Zero)
652 {
653 d.GeomDestroy(Box);
654 Box = IntPtr.Zero;
655 }
656 if (Sphere != IntPtr.Zero)
657 {
658 d.GeomDestroy(Sphere);
659 Sphere = IntPtr.Zero;
660 }
661 if (Plane != IntPtr.Zero)
662 {
663 d.GeomDestroy(Plane);
664 Plane = IntPtr.Zero;
665 }
666 }
667 }
668
669 public struct ODERayRequest
670 {
671 public PhysicsActor actor;
672 public Vector3 Origin;
673 public Vector3 Normal;
674 public int Count;
675 public float length;
676 public object callbackMethod;
677 public RayFilterFlags filter;
678 public Quaternion orientation;
679 }
680}
diff --git a/OpenSim/Region/PhysicsModules/ubOde/ODEScene.cs b/OpenSim/Region/PhysicsModules/ubOde/ODEScene.cs
new file mode 100644
index 0000000..61e31a1
--- /dev/null
+++ b/OpenSim/Region/PhysicsModules/ubOde/ODEScene.cs
@@ -0,0 +1,2830 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28// Revision 2011/12/13 by Ubit Umarov
29//#define SPAM
30
31using System;
32using System.Collections.Generic;
33using System.Reflection;
34using System.Runtime.InteropServices;
35using System.Threading;
36using System.IO;
37using System.Diagnostics;
38using log4net;
39using Nini.Config;
40using Mono.Addins;
41using OdeAPI;
42using OpenSim.Framework;
43using OpenSim.Region.Framework.Scenes;
44using OpenSim.Region.Framework.Interfaces;
45using OpenSim.Region.PhysicsModules.SharedBase;
46using OpenMetaverse;
47
48namespace OpenSim.Region.PhysicsModule.ubOde
49{
50 // colision flags of things others can colide with
51 // rays, sensors, probes removed since can't be colided with
52 // The top space where things are placed provided further selection
53 // ie physical are in active space nonphysical in static
54 // this should be exclusive as possible
55
56 [Flags]
57 public enum CollisionCategories : uint
58 {
59 Disabled = 0,
60 //by 'things' types
61 Space = 0x01,
62 Geom = 0x02, // aka prim/part
63 Character = 0x04,
64 Land = 0x08,
65 Water = 0x010,
66
67 // by state
68 Phantom = 0x01000,
69 VolumeDtc = 0x02000,
70 Selected = 0x04000,
71 NoShape = 0x08000,
72
73
74 All = 0xffffffff
75 }
76
77 /// <summary>
78 /// Material type for a primitive
79 /// </summary>
80 public enum Material : int
81 {
82 /// <summary></summary>
83 Stone = 0,
84 /// <summary></summary>
85 Metal = 1,
86 /// <summary></summary>
87 Glass = 2,
88 /// <summary></summary>
89 Wood = 3,
90 /// <summary></summary>
91 Flesh = 4,
92 /// <summary></summary>
93 Plastic = 5,
94 /// <summary></summary>
95 Rubber = 6,
96
97 light = 7 // compatibility with old viewers
98 }
99
100 public enum changes : int
101 {
102 Add = 0, // arg null. finishs the prim creation. should be used internally only ( to remove later ?)
103 Remove,
104 Link, // arg AuroraODEPrim new parent prim or null to delink. Makes the prim part of a object with prim parent as root
105 // or removes from a object if arg is null
106 DeLink,
107 Position, // arg Vector3 new position in world coords. Changes prim position. Prim must know if it is root or child
108 Orientation, // arg Quaternion new orientation in world coords. Changes prim position. Prim must know it it is root or child
109 PosOffset, // not in use
110 // arg Vector3 new position in local coords. Changes prim position in object
111 OriOffset, // not in use
112 // arg Vector3 new position in local coords. Changes prim position in object
113 Velocity,
114 AngVelocity,
115 Acceleration,
116 Force,
117 Torque,
118 Momentum,
119
120 AddForce,
121 AddAngForce,
122 AngLock,
123
124 Buoyancy,
125
126 PIDTarget,
127 PIDTau,
128 PIDActive,
129
130 PIDHoverHeight,
131 PIDHoverType,
132 PIDHoverTau,
133 PIDHoverActive,
134
135 Size,
136 AvatarSize,
137 Shape,
138 PhysRepData,
139 AddPhysRep,
140
141 CollidesWater,
142 VolumeDtc,
143
144 Physical,
145 Phantom,
146 Selected,
147 disabled,
148 building,
149
150 VehicleType,
151 VehicleFloatParam,
152 VehicleVectorParam,
153 VehicleRotationParam,
154 VehicleFlags,
155 SetVehicle,
156
157 Null //keep this last used do dim the methods array. does nothing but pulsing the prim
158 }
159
160 public struct ODEchangeitem
161 {
162 public PhysicsActor actor;
163 public OdeCharacter character;
164 public changes what;
165 public Object arg;
166 }
167
168 public class ODEScene : PhysicsScene
169 {
170 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
171
172 public bool m_OSOdeLib = false;
173 public bool m_suportCombine = false; // mega suport not tested
174 public Scene m_frameWorkScene = null;
175
176// private int threadid = 0;
177
178// const d.ContactFlags comumContactFlags = d.ContactFlags.SoftERP | d.ContactFlags.SoftCFM |d.ContactFlags.Approx1 | d.ContactFlags.Bounce;
179
180 const d.ContactFlags comumContactFlags = d.ContactFlags.Bounce | d.ContactFlags.Approx1 | d.ContactFlags.Slip1 | d.ContactFlags.Slip2;
181 const float comumContactERP = 0.75f;
182 const float comumContactCFM = 0.0001f;
183 const float comumContactSLIP = 0f;
184
185 float frictionMovementMult = 0.8f;
186
187 float TerrainBounce = 0.1f;
188 float TerrainFriction = 0.3f;
189
190 public float AvatarFriction = 0;// 0.9f * 0.5f;
191
192 // this netx dimensions are only relevant for terrain partition (mega regions)
193 // WorldExtents below has the simulation dimensions
194 // they should be identical except on mega regions
195 private uint m_regionWidth = Constants.RegionSize;
196 private uint m_regionHeight = Constants.RegionSize;
197
198 public float ODE_STEPSIZE = 0.020f;
199 public float HalfOdeStep = 0.01f;
200 public int odetimestepMS = 20; // rounded
201 private float metersInSpace = 25.6f;
202 private float m_timeDilation = 1.0f;
203
204 private DateTime m_lastframe;
205 private DateTime m_lastMeshExpire;
206
207 public float gravityx = 0f;
208 public float gravityy = 0f;
209 public float gravityz = -9.8f;
210
211 private float waterlevel = 0f;
212 private int framecount = 0;
213
214 private float avDensity = 80f;
215 private float avMovementDivisorWalk = 1.3f;
216 private float avMovementDivisorRun = 0.8f;
217 private float minimumGroundFlightOffset = 3f;
218 public float maximumMassObject = 10000.01f;
219 public float geomDefaultDensity = 10.0f;
220
221 public float maximumAngularVelocity = 12.0f; // default 12rad/s
222 public float maxAngVelocitySQ = 144f; // squared value
223
224 public float bodyPIDD = 35f;
225 public float bodyPIDG = 25;
226
227 public int bodyFramesAutoDisable = 5;
228
229 private d.NearCallback nearCallback;
230
231 private HashSet<OdeCharacter> _characters = new HashSet<OdeCharacter>();
232 private HashSet<OdePrim> _prims = new HashSet<OdePrim>();
233 private HashSet<OdePrim> _activeprims = new HashSet<OdePrim>();
234 private HashSet<OdePrim> _activegroups = new HashSet<OdePrim>();
235
236 public OpenSim.Framework.LocklessQueue<ODEchangeitem> ChangesQueue = new OpenSim.Framework.LocklessQueue<ODEchangeitem>();
237
238 /// <summary>
239 /// A list of actors that should receive collision events.
240 /// </summary>
241 private List<PhysicsActor> _collisionEventPrim = new List<PhysicsActor>();
242 private List<PhysicsActor> _collisionEventPrimRemove = new List<PhysicsActor>();
243
244 private HashSet<OdeCharacter> _badCharacter = new HashSet<OdeCharacter>();
245 public Dictionary<IntPtr, PhysicsActor> actor_name_map = new Dictionary<IntPtr, PhysicsActor>();
246
247 private float contactsurfacelayer = 0.002f;
248
249 private int contactsPerCollision = 80;
250 internal IntPtr ContactgeomsArray = IntPtr.Zero;
251 private IntPtr GlobalContactsArray = IntPtr.Zero;
252 private d.Contact SharedTmpcontact = new d.Contact();
253
254 const int maxContactsbeforedeath = 6000;
255 private volatile int m_global_contactcount = 0;
256
257 private IntPtr contactgroup;
258
259 public ContactData[] m_materialContactsData = new ContactData[8];
260
261 private Dictionary<Vector3, IntPtr> RegionTerrain = new Dictionary<Vector3, IntPtr>();
262 private Dictionary<IntPtr, float[]> TerrainHeightFieldHeights = new Dictionary<IntPtr, float[]>();
263 private Dictionary<IntPtr, GCHandle> TerrainHeightFieldHeightsHandlers = new Dictionary<IntPtr, GCHandle>();
264
265 private int m_physicsiterations = 15;
266 private const float m_SkipFramesAtms = 0.40f; // Drop frames gracefully at a 400 ms lag
267// private PhysicsActor PANull = new NullPhysicsActor();
268 private float step_time = 0.0f;
269
270 public IntPtr world;
271
272 // split the spaces acording to contents type
273 // ActiveSpace contains characters and active prims
274 // StaticSpace contains land and other that is mostly static in enviroment
275 // this can contain subspaces, like the grid in staticspace
276 // as now space only contains this 2 top spaces
277
278 public IntPtr TopSpace; // the global space
279 public IntPtr ActiveSpace; // space for active prims
280 public IntPtr CharsSpace; // space for active prims
281 public IntPtr StaticSpace; // space for the static things around
282 public IntPtr GroundSpace; // space for ground
283
284 // some speedup variables
285 private int spaceGridMaxX;
286 private int spaceGridMaxY;
287 private float spacesPerMeterX;
288 private float spacesPerMeterY;
289
290 // split static geometry collision into a grid as before
291 private IntPtr[,] staticPrimspace;
292 private IntPtr[] staticPrimspaceOffRegion;
293
294 public Object OdeLock;
295 public static Object SimulationLock;
296
297 public IMesher mesher;
298
299 public IConfigSource m_config;
300
301 public bool physics_logging = false;
302 public int physics_logging_interval = 0;
303 public bool physics_logging_append_existing_logfile = false;
304
305 private Vector3 m_worldOffset = Vector3.Zero;
306 public Vector2 WorldExtents = new Vector2((int)Constants.RegionSize, (int)Constants.RegionSize);
307 private PhysicsScene m_parentScene = null;
308
309 private ODERayCastRequestManager m_rayCastManager;
310 public ODEMeshWorker m_meshWorker;
311
312 /* maybe needed if ode uses tls
313 private void checkThread()
314 {
315
316 int th = Thread.CurrentThread.ManagedThreadId;
317 if(th != threadid)
318 {
319 threadid = th;
320 d.AllocateODEDataForThread(~0U);
321 }
322 }
323 */
324
325 IConfig physicsconfig = null;
326
327 public ODEScene(Scene pscene, IConfigSource psourceconfig, string pname, bool pOSOdeLib)
328 {
329 OdeLock = new Object();
330
331 EngineType = pname;
332 PhysicsSceneName = EngineType + "/" + pscene.RegionInfo.RegionName;
333
334 m_config = psourceconfig;
335 m_OSOdeLib = pOSOdeLib;
336
337// m_OSOdeLib = false; //debug
338
339 m_frameWorkScene = pscene;
340
341 m_frameWorkScene.RegisterModuleInterface<PhysicsScene>(this);
342
343 Initialization();
344
345 base.Initialise(m_frameWorkScene.PhysicsRequestAsset,
346 (m_frameWorkScene.Heightmap != null ? m_frameWorkScene.Heightmap.GetFloatsSerialised() : new float[m_frameWorkScene.RegionInfo.RegionSizeX * m_frameWorkScene.RegionInfo.RegionSizeY]),
347 (float)m_frameWorkScene.RegionInfo.RegionSettings.WaterHeight);
348 }
349
350 public void RegionLoaded()
351 {
352 mesher = m_frameWorkScene.RequestModuleInterface<IMesher>();
353 if (mesher == null)
354 {
355 m_log.ErrorFormat("[ubOde] No mesher. module disabled");
356 return;
357 }
358
359 m_meshWorker = new ODEMeshWorker(this, m_log, mesher, physicsconfig);
360 m_frameWorkScene.PhysicsEnabled = true;
361 }
362 /// <summary>
363 /// Initiailizes the scene
364 /// Sets many properties that ODE requires to be stable
365 /// These settings need to be tweaked 'exactly' right or weird stuff happens.
366 /// </summary>
367 private void Initialization()
368 {
369 // checkThread();
370 SimulationLock = new Object();
371
372 nearCallback = near;
373
374 m_rayCastManager = new ODERayCastRequestManager(this);
375
376 WorldExtents.X = m_frameWorkScene.RegionInfo.RegionSizeX;
377 m_regionWidth = (uint)WorldExtents.X;
378 WorldExtents.Y = m_frameWorkScene.RegionInfo.RegionSizeY;
379 m_regionHeight = (uint)WorldExtents.Y;
380
381 m_suportCombine = false;
382
383 lock (OdeLock)
384 {
385 // Create the world and the first space
386 try
387 {
388 world = d.WorldCreate();
389 TopSpace = d.HashSpaceCreate(IntPtr.Zero);
390
391 // now the major subspaces
392 ActiveSpace = d.HashSpaceCreate(TopSpace);
393 CharsSpace = d.HashSpaceCreate(TopSpace);
394 StaticSpace = d.HashSpaceCreate(TopSpace);
395 GroundSpace = d.HashSpaceCreate(TopSpace);
396 }
397 catch
398 {
399 // i must RtC#FM
400 // i did!
401 }
402
403 d.HashSpaceSetLevels(TopSpace, -5, 12);
404 d.HashSpaceSetLevels(ActiveSpace, -5, 10);
405 d.HashSpaceSetLevels(CharsSpace, -4, 3);
406 d.HashSpaceSetLevels(StaticSpace, -5, 12);
407 d.HashSpaceSetLevels(GroundSpace, 0, 8);
408
409 // demote to second level
410 d.SpaceSetSublevel(ActiveSpace, 1);
411 d.SpaceSetSublevel(CharsSpace, 1);
412 d.SpaceSetSublevel(StaticSpace, 1);
413 d.SpaceSetSublevel(GroundSpace, 1);
414
415 d.GeomSetCategoryBits(ActiveSpace, (uint)(CollisionCategories.Space |
416 CollisionCategories.Geom |
417 CollisionCategories.Character |
418 CollisionCategories.Phantom |
419 CollisionCategories.VolumeDtc
420 ));
421 d.GeomSetCollideBits(ActiveSpace, (uint)(CollisionCategories.Space |
422 CollisionCategories.Geom |
423 CollisionCategories.Character |
424 CollisionCategories.Phantom |
425 CollisionCategories.VolumeDtc
426 ));
427 d.GeomSetCategoryBits(CharsSpace, (uint)(CollisionCategories.Space |
428 CollisionCategories.Geom |
429 CollisionCategories.Character |
430 CollisionCategories.Phantom |
431 CollisionCategories.VolumeDtc
432 ));
433 d.GeomSetCollideBits(CharsSpace, 0);
434
435 d.GeomSetCategoryBits(StaticSpace, (uint)(CollisionCategories.Space |
436 CollisionCategories.Geom |
437 // CollisionCategories.Land |
438 // CollisionCategories.Water |
439 CollisionCategories.Phantom |
440 CollisionCategories.VolumeDtc
441 ));
442 d.GeomSetCollideBits(StaticSpace, 0);
443
444 d.GeomSetCategoryBits(GroundSpace, (uint)(CollisionCategories.Land));
445 d.GeomSetCollideBits(GroundSpace, 0);
446
447 contactgroup = d.JointGroupCreate(maxContactsbeforedeath + 1);
448 //contactgroup
449
450 d.WorldSetAutoDisableFlag(world, false);
451 }
452
453
454 // checkThread();
455
456
457 // Defaults
458
459 int contactsPerCollision = 80;
460
461 physicsconfig = null;
462
463 if (m_config != null)
464 {
465 physicsconfig = m_config.Configs["ODEPhysicsSettings"];
466 if (physicsconfig != null)
467 {
468 gravityx = physicsconfig.GetFloat("world_gravityx", gravityx);
469 gravityy = physicsconfig.GetFloat("world_gravityy", gravityy);
470 gravityz = physicsconfig.GetFloat("world_gravityz", gravityz);
471
472 metersInSpace = physicsconfig.GetFloat("meters_in_small_space", metersInSpace);
473
474 // contactsurfacelayer = physicsconfig.GetFloat("world_contact_surface_layer", contactsurfacelayer);
475
476 ODE_STEPSIZE = physicsconfig.GetFloat("world_stepsize", ODE_STEPSIZE);
477
478 avDensity = physicsconfig.GetFloat("av_density", avDensity);
479 avMovementDivisorWalk = physicsconfig.GetFloat("av_movement_divisor_walk", avMovementDivisorWalk);
480 avMovementDivisorRun = physicsconfig.GetFloat("av_movement_divisor_run", avMovementDivisorRun);
481
482 contactsPerCollision = physicsconfig.GetInt("contacts_per_collision", contactsPerCollision);
483
484 geomDefaultDensity = physicsconfig.GetFloat("geometry_default_density", geomDefaultDensity);
485 bodyFramesAutoDisable = physicsconfig.GetInt("body_frames_auto_disable", bodyFramesAutoDisable);
486
487 physics_logging = physicsconfig.GetBoolean("physics_logging", false);
488 physics_logging_interval = physicsconfig.GetInt("physics_logging_interval", 0);
489 physics_logging_append_existing_logfile = physicsconfig.GetBoolean("physics_logging_append_existing_logfile", false);
490
491 minimumGroundFlightOffset = physicsconfig.GetFloat("minimum_ground_flight_offset", minimumGroundFlightOffset);
492 maximumMassObject = physicsconfig.GetFloat("maximum_mass_object", maximumMassObject);
493
494 avDensity *= 3f / 80f; // scale other engines density option to this
495 }
496 }
497
498 float heartbeat = 1/m_frameWorkScene.FrameTime;
499 maximumAngularVelocity = 0.49f * heartbeat *(float)Math.PI;
500 maxAngVelocitySQ = maximumAngularVelocity * maximumAngularVelocity;
501
502 d.WorldSetCFM(world, comumContactCFM);
503 d.WorldSetERP(world, comumContactERP);
504
505 d.WorldSetGravity(world, gravityx, gravityy, gravityz);
506
507 d.WorldSetLinearDamping(world, 0.002f);
508 d.WorldSetAngularDamping(world, 0.002f);
509 d.WorldSetAngularDampingThreshold(world, 0f);
510 d.WorldSetLinearDampingThreshold(world, 0f);
511 d.WorldSetMaxAngularSpeed(world, maximumAngularVelocity);
512
513 d.WorldSetQuickStepNumIterations(world, m_physicsiterations);
514
515 d.WorldSetContactSurfaceLayer(world, contactsurfacelayer);
516 d.WorldSetContactMaxCorrectingVel(world, 60.0f);
517
518 HalfOdeStep = ODE_STEPSIZE * 0.5f;
519 odetimestepMS = (int)(1000.0f * ODE_STEPSIZE + 0.5f);
520
521 ContactgeomsArray = Marshal.AllocHGlobal(contactsPerCollision * d.ContactGeom.unmanagedSizeOf);
522 GlobalContactsArray = Marshal.AllocHGlobal((maxContactsbeforedeath + 100) * d.Contact.unmanagedSizeOf);
523
524 SharedTmpcontact.geom.g1 = IntPtr.Zero;
525 SharedTmpcontact.geom.g2 = IntPtr.Zero;
526
527 SharedTmpcontact.geom.side1 = -1;
528 SharedTmpcontact.geom.side2 = -1;
529
530 SharedTmpcontact.surface.mode = comumContactFlags;
531 SharedTmpcontact.surface.mu = 0;
532 SharedTmpcontact.surface.bounce = 0;
533 SharedTmpcontact.surface.soft_cfm = comumContactCFM;
534 SharedTmpcontact.surface.soft_erp = comumContactERP;
535 SharedTmpcontact.surface.slip1 = comumContactSLIP;
536 SharedTmpcontact.surface.slip2 = comumContactSLIP;
537
538 m_materialContactsData[(int)Material.Stone].mu = 0.8f;
539 m_materialContactsData[(int)Material.Stone].bounce = 0.4f;
540
541 m_materialContactsData[(int)Material.Metal].mu = 0.3f;
542 m_materialContactsData[(int)Material.Metal].bounce = 0.4f;
543
544 m_materialContactsData[(int)Material.Glass].mu = 0.2f;
545 m_materialContactsData[(int)Material.Glass].bounce = 0.7f;
546
547 m_materialContactsData[(int)Material.Wood].mu = 0.6f;
548 m_materialContactsData[(int)Material.Wood].bounce = 0.5f;
549
550 m_materialContactsData[(int)Material.Flesh].mu = 0.9f;
551 m_materialContactsData[(int)Material.Flesh].bounce = 0.3f;
552
553 m_materialContactsData[(int)Material.Plastic].mu = 0.4f;
554 m_materialContactsData[(int)Material.Plastic].bounce = 0.7f;
555
556 m_materialContactsData[(int)Material.Rubber].mu = 0.9f;
557 m_materialContactsData[(int)Material.Rubber].bounce = 0.95f;
558
559 m_materialContactsData[(int)Material.light].mu = 0.0f;
560 m_materialContactsData[(int)Material.light].bounce = 0.0f;
561
562
563 spacesPerMeterX = 1.0f / metersInSpace;
564 spacesPerMeterY = spacesPerMeterX;
565 spaceGridMaxX = (int)(WorldExtents.X * spacesPerMeterX);
566 spaceGridMaxY = (int)(WorldExtents.Y * spacesPerMeterY);
567
568 if (spaceGridMaxX > 24)
569 {
570 spaceGridMaxX = 24;
571 spacesPerMeterX = spaceGridMaxX / WorldExtents.X;
572 }
573
574 if (spaceGridMaxY > 24)
575 {
576 spaceGridMaxY = 24;
577 spacesPerMeterY = spaceGridMaxY / WorldExtents.Y;
578 }
579
580 staticPrimspace = new IntPtr[spaceGridMaxX, spaceGridMaxY];
581
582 // create all spaces now
583 int i, j;
584 IntPtr newspace;
585
586 for (i = 0; i < spaceGridMaxX; i++)
587 for (j = 0; j < spaceGridMaxY; j++)
588 {
589 newspace = d.HashSpaceCreate(StaticSpace);
590 d.GeomSetCategoryBits(newspace, (int)CollisionCategories.Space);
591 waitForSpaceUnlock(newspace);
592 d.SpaceSetSublevel(newspace, 2);
593 d.HashSpaceSetLevels(newspace, -2, 8);
594 d.GeomSetCategoryBits(newspace, (uint)(CollisionCategories.Space |
595 CollisionCategories.Geom |
596 CollisionCategories.Land |
597 CollisionCategories.Water |
598 CollisionCategories.Phantom |
599 CollisionCategories.VolumeDtc
600 ));
601 d.GeomSetCollideBits(newspace, 0);
602
603 staticPrimspace[i, j] = newspace;
604 }
605
606 // let this now be index limit
607 spaceGridMaxX--;
608 spaceGridMaxY--;
609
610 // create 4 off world spaces (x<0,x>max,y<0,y>max)
611 staticPrimspaceOffRegion = new IntPtr[4];
612
613 for (i = 0; i < 4; i++)
614 {
615 newspace = d.HashSpaceCreate(StaticSpace);
616 d.GeomSetCategoryBits(newspace, (int)CollisionCategories.Space);
617 waitForSpaceUnlock(newspace);
618 d.SpaceSetSublevel(newspace, 2);
619 d.HashSpaceSetLevels(newspace, -2, 8);
620 d.GeomSetCategoryBits(newspace, (uint)(CollisionCategories.Space |
621 CollisionCategories.Geom |
622 CollisionCategories.Land |
623 CollisionCategories.Water |
624 CollisionCategories.Phantom |
625 CollisionCategories.VolumeDtc
626 ));
627 d.GeomSetCollideBits(newspace, 0);
628
629 staticPrimspaceOffRegion[i] = newspace;
630 }
631
632 m_lastframe = DateTime.UtcNow;
633 m_lastMeshExpire = m_lastframe;
634 }
635
636 internal void waitForSpaceUnlock(IntPtr space)
637 {
638 //if (space != IntPtr.Zero)
639 //while (d.SpaceLockQuery(space)) { } // Wait and do nothing
640 }
641
642 #region Collision Detection
643
644 // sets a global contact for a joint for contactgeom , and base contact description)
645 private IntPtr CreateContacJoint(ref d.ContactGeom contactGeom,bool smooth)
646 {
647 if (m_global_contactcount >= maxContactsbeforedeath)
648 return IntPtr.Zero;
649
650 m_global_contactcount++;
651 if(smooth)
652 SharedTmpcontact.geom.depth = contactGeom.depth * 0.05f;
653 else
654 SharedTmpcontact.geom.depth = contactGeom.depth;
655 SharedTmpcontact.geom.pos = contactGeom.pos;
656 SharedTmpcontact.geom.normal = contactGeom.normal;
657
658 IntPtr contact = new IntPtr(GlobalContactsArray.ToInt64() + (Int64)(m_global_contactcount * d.Contact.unmanagedSizeOf));
659 Marshal.StructureToPtr(SharedTmpcontact, contact, true);
660 return d.JointCreateContactPtr(world, contactgroup, contact);
661 }
662
663 private bool GetCurContactGeom(int index, ref d.ContactGeom newcontactgeom)
664 {
665 if (ContactgeomsArray == IntPtr.Zero || index >= contactsPerCollision)
666 return false;
667
668 IntPtr contactptr = new IntPtr(ContactgeomsArray.ToInt64() + (Int64)(index * d.ContactGeom.unmanagedSizeOf));
669 newcontactgeom = (d.ContactGeom)Marshal.PtrToStructure(contactptr, typeof(d.ContactGeom));
670 return true;
671 }
672
673 /// <summary>
674 /// This is our near callback. A geometry is near a body
675 /// </summary>
676 /// <param name="space">The space that contains the geoms. Remember, spaces are also geoms</param>
677 /// <param name="g1">a geometry or space</param>
678 /// <param name="g2">another geometry or space</param>
679 ///
680
681 private void near(IntPtr space, IntPtr g1, IntPtr g2)
682 {
683 // no lock here! It's invoked from within Simulate(), which is thread-locked
684
685 if (m_global_contactcount >= maxContactsbeforedeath)
686 return;
687
688 // Test if we're colliding a geom with a space.
689 // If so we have to drill down into the space recursively
690
691 if (g1 == IntPtr.Zero || g2 == IntPtr.Zero)
692 return;
693
694 if (d.GeomIsSpace(g1) || d.GeomIsSpace(g2))
695 {
696 // We'll be calling near recursivly if one
697 // of them is a space to find all of the
698 // contact points in the space
699 try
700 {
701 d.SpaceCollide2(g1, g2, IntPtr.Zero, nearCallback);
702 }
703 catch (AccessViolationException)
704 {
705 m_log.Warn("[PHYSICS]: Unable to collide test a space");
706 return;
707 }
708 //here one should check collisions of geoms inside a space
709 // but on each space we only should have geoms that not colide amoung each other
710 // so we don't dig inside spaces
711 return;
712 }
713
714 // get geom bodies to check if we already a joint contact
715 // guess this shouldn't happen now
716 IntPtr b1 = d.GeomGetBody(g1);
717 IntPtr b2 = d.GeomGetBody(g2);
718
719 // d.GeomClassID id = d.GeomGetClass(g1);
720
721 // Figure out how many contact points we have
722 int count = 0;
723 try
724 {
725 // Colliding Geom To Geom
726 // This portion of the function 'was' blatantly ripped off from BoxStack.cs
727
728 if (g1 == g2)
729 return; // Can't collide with yourself
730
731 if (b1 != IntPtr.Zero && b2 != IntPtr.Zero && d.AreConnectedExcluding(b1, b2, d.JointType.Contact))
732 return;
733 /*
734 // debug
735 PhysicsActor dp2;
736 if (d.GeomGetClass(g1) == d.GeomClassID.HeightfieldClass)
737 {
738 d.AABB aabb;
739 d.GeomGetAABB(g2, out aabb);
740 float x = aabb.MaxX - aabb.MinX;
741 float y = aabb.MaxY - aabb.MinY;
742 float z = aabb.MaxZ - aabb.MinZ;
743 if (x > 60.0f || y > 60.0f || z > 60.0f)
744 {
745 if (!actor_name_map.TryGetValue(g2, out dp2))
746 m_log.WarnFormat("[PHYSICS]: failed actor mapping for geom 2");
747 else
748 m_log.WarnFormat("[PHYSICS]: land versus large prim geo {0},size {1}, AABBsize <{2},{3},{4}>, at {5} ori {6},({7})",
749 dp2.Name, dp2.Size, x, y, z,
750 dp2.Position.ToString(),
751 dp2.Orientation.ToString(),
752 dp2.Orientation.Length());
753 return;
754 }
755 }
756 //
757 */
758
759
760 if (d.GeomGetCategoryBits(g1) == (uint)CollisionCategories.VolumeDtc ||
761 d.GeomGetCategoryBits(g2) == (uint)CollisionCategories.VolumeDtc)
762 {
763 int cflags;
764 unchecked
765 {
766 cflags = (int)(1 | d.CONTACTS_UNIMPORTANT);
767 }
768 count = d.CollidePtr(g1, g2, cflags, ContactgeomsArray, d.ContactGeom.unmanagedSizeOf);
769 }
770 else
771 count = d.CollidePtr(g1, g2, (contactsPerCollision & 0xffff), ContactgeomsArray, d.ContactGeom.unmanagedSizeOf);
772 }
773 catch (SEHException)
774 {
775 m_log.Error("[PHYSICS]: The Operating system shut down ODE because of corrupt memory. This could be a result of really irregular terrain. If this repeats continuously, restart using Basic Physics and terrain fill your terrain. Restarting the sim.");
776 // ode.drelease(world);
777 base.TriggerPhysicsBasedRestart();
778 }
779 catch (Exception e)
780 {
781 m_log.WarnFormat("[PHYSICS]: Unable to collide test an object: {0}", e.Message);
782 return;
783 }
784
785 // contacts done
786 if (count == 0)
787 return;
788
789 // try get physical actors
790 PhysicsActor p1;
791 PhysicsActor p2;
792
793 if (!actor_name_map.TryGetValue(g1, out p1))
794 {
795 m_log.WarnFormat("[PHYSICS]: failed actor mapping for geom 1");
796 return;
797 }
798
799 if (!actor_name_map.TryGetValue(g2, out p2))
800 {
801 m_log.WarnFormat("[PHYSICS]: failed actor mapping for geom 2");
802 return;
803 }
804
805 // update actors collision score
806 if (p1.CollisionScore >= float.MaxValue - count)
807 p1.CollisionScore = 0;
808 p1.CollisionScore += count;
809
810 if (p2.CollisionScore >= float.MaxValue - count)
811 p2.CollisionScore = 0;
812 p2.CollisionScore += count;
813
814 // get first contact
815 d.ContactGeom curContact = new d.ContactGeom();
816
817 if (!GetCurContactGeom(0, ref curContact))
818 return;
819
820 ContactPoint maxDepthContact = new ContactPoint();
821
822 // do volume detection case
823 if ((p1.IsVolumeDtc || p2.IsVolumeDtc))
824 {
825 maxDepthContact = new ContactPoint(
826 new Vector3(curContact.pos.X, curContact.pos.Y, curContact.pos.Z),
827 new Vector3(curContact.normal.X, curContact.normal.Y, curContact.normal.Z),
828 curContact.depth, false
829 );
830
831 collision_accounting_events(p1, p2, maxDepthContact);
832 return;
833 }
834
835 // big messy collision analises
836
837 float mu = 0;
838 float bounce = 0;
839// bool IgnoreNegSides = false;
840
841 ContactData contactdata1 = new ContactData(0, 0, false);
842 ContactData contactdata2 = new ContactData(0, 0, false);
843
844 bool dop1ava = false;
845 bool dop2ava = false;
846 bool ignore = false;
847 bool smoothMesh = false;
848
849 switch (p1.PhysicsActorType)
850 {
851 case (int)ActorTypes.Agent:
852 {
853 dop1ava = true;
854 switch (p2.PhysicsActorType)
855 {
856 case (int)ActorTypes.Agent:
857 case (int)ActorTypes.Prim:
858 break;
859
860 default:
861 ignore = true; // avatar to terrain and water ignored
862 break;
863 }
864 break;
865 }
866
867 case (int)ActorTypes.Prim:
868 {
869 switch (p2.PhysicsActorType)
870 {
871 case (int)ActorTypes.Agent:
872 dop2ava = true;
873 break;
874
875 case (int)ActorTypes.Prim:
876 Vector3 relV = p1.Velocity - p2.Velocity;
877 float relVlenSQ = relV.LengthSquared();
878 if (relVlenSQ > 0.0001f)
879 {
880 p1.CollidingObj = true;
881 p2.CollidingObj = true;
882 }
883 p1.getContactData(ref contactdata1);
884 p2.getContactData(ref contactdata2);
885 bounce = contactdata1.bounce * contactdata2.bounce;
886 mu = (float)Math.Sqrt(contactdata1.mu * contactdata2.mu);
887
888 if (relVlenSQ > 0.01f)
889 mu *= frictionMovementMult;
890
891 if(d.GeomGetClass(g2) == d.GeomClassID.TriMeshClass &&
892 d.GeomGetClass(g1) == d.GeomClassID.TriMeshClass)
893 smoothMesh = true;
894 break;
895
896 case (int)ActorTypes.Ground:
897 p1.getContactData(ref contactdata1);
898 bounce = contactdata1.bounce * TerrainBounce;
899 mu = (float)Math.Sqrt(contactdata1.mu * TerrainFriction);
900
901 if (Math.Abs(p1.Velocity.X) > 0.1f || Math.Abs(p1.Velocity.Y) > 0.1f)
902 mu *= frictionMovementMult;
903 p1.CollidingGround = true;
904
905 if(d.GeomGetClass(g1) == d.GeomClassID.TriMeshClass)
906 smoothMesh = true;
907 break;
908
909 case (int)ActorTypes.Water:
910 default:
911 ignore = true;
912 break;
913 }
914 }
915 break;
916
917 case (int)ActorTypes.Ground:
918 if (p2.PhysicsActorType == (int)ActorTypes.Prim)
919 {
920 p2.CollidingGround = true;
921 p2.getContactData(ref contactdata2);
922 bounce = contactdata2.bounce * TerrainBounce;
923 mu = (float)Math.Sqrt(contactdata2.mu * TerrainFriction);
924
925// if (curContact.side1 > 0) // should be 2 ?
926// IgnoreNegSides = true;
927
928 if (Math.Abs(p2.Velocity.X) > 0.1f || Math.Abs(p2.Velocity.Y) > 0.1f)
929 mu *= frictionMovementMult;
930
931 if(d.GeomGetClass(g2) == d.GeomClassID.TriMeshClass)
932 smoothMesh = true;
933 }
934 else
935 ignore = true;
936 break;
937
938 case (int)ActorTypes.Water:
939 default:
940 break;
941 }
942
943 if (ignore)
944 return;
945
946 IntPtr Joint;
947 bool FeetCollision = false;
948 int ncontacts = 0;
949
950 int i = 0;
951
952 maxDepthContact = new ContactPoint();
953 maxDepthContact.PenetrationDepth = float.MinValue;
954 ContactPoint minDepthContact = new ContactPoint();
955 minDepthContact.PenetrationDepth = float.MaxValue;
956
957 SharedTmpcontact.geom.depth = 0;
958 SharedTmpcontact.surface.mu = mu;
959 SharedTmpcontact.surface.bounce = bounce;
960
961 d.ContactGeom altContact = new d.ContactGeom();
962 bool useAltcontact = false;
963 bool noskip = true;
964
965 if(dop1ava || dop2ava)
966 smoothMesh = false;
967
968 while (true)
969 {
970 noskip = true;
971 useAltcontact = false;
972
973 if (dop1ava)
974 {
975 if ((((OdeCharacter)p1).Collide(g1, g2, false, ref curContact, ref altContact , ref useAltcontact, ref FeetCollision)))
976 {
977 if (p2.PhysicsActorType == (int)ActorTypes.Agent)
978 {
979 p1.CollidingObj = true;
980 p2.CollidingObj = true;
981 }
982 else if (p2.Velocity.LengthSquared() > 0.0f)
983 p2.CollidingObj = true;
984 }
985 else
986 noskip = false;
987 }
988 else if (dop2ava)
989 {
990 if ((((OdeCharacter)p2).Collide(g2, g1, true, ref curContact, ref altContact , ref useAltcontact, ref FeetCollision)))
991 {
992 if (p1.PhysicsActorType == (int)ActorTypes.Agent)
993 {
994 p1.CollidingObj = true;
995 p2.CollidingObj = true;
996 }
997 else if (p2.Velocity.LengthSquared() > 0.0f)
998 p1.CollidingObj = true;
999 }
1000 else
1001 noskip = false;
1002 }
1003
1004 if (noskip)
1005 {
1006 if(useAltcontact)
1007 Joint = CreateContacJoint(ref altContact,smoothMesh);
1008 else
1009 Joint = CreateContacJoint(ref curContact,smoothMesh);
1010
1011 if (Joint == IntPtr.Zero)
1012 break;
1013
1014 d.JointAttach(Joint, b1, b2);
1015
1016 ncontacts++;
1017
1018 if (curContact.depth > maxDepthContact.PenetrationDepth)
1019 {
1020 maxDepthContact.Position.X = curContact.pos.X;
1021 maxDepthContact.Position.Y = curContact.pos.Y;
1022 maxDepthContact.Position.Z = curContact.pos.Z;
1023 maxDepthContact.PenetrationDepth = curContact.depth;
1024 maxDepthContact.CharacterFeet = FeetCollision;
1025 }
1026
1027 if (curContact.depth < minDepthContact.PenetrationDepth)
1028 {
1029 minDepthContact.PenetrationDepth = curContact.depth;
1030 minDepthContact.SurfaceNormal.X = curContact.normal.X;
1031 minDepthContact.SurfaceNormal.Y = curContact.normal.Y;
1032 minDepthContact.SurfaceNormal.Z = curContact.normal.Z;
1033 }
1034 }
1035
1036 if (++i >= count)
1037 break;
1038
1039 if (!GetCurContactGeom(i, ref curContact))
1040 break;
1041 }
1042
1043 if (ncontacts > 0)
1044 {
1045 maxDepthContact.SurfaceNormal.X = minDepthContact.SurfaceNormal.X;
1046 maxDepthContact.SurfaceNormal.Y = minDepthContact.SurfaceNormal.Y;
1047 maxDepthContact.SurfaceNormal.Z = minDepthContact.SurfaceNormal.Z;
1048
1049 collision_accounting_events(p1, p2, maxDepthContact);
1050 }
1051 }
1052
1053 private void collision_accounting_events(PhysicsActor p1, PhysicsActor p2, ContactPoint contact)
1054 {
1055 uint obj2LocalID = 0;
1056
1057 bool p1events = p1.SubscribedEvents();
1058 bool p2events = p2.SubscribedEvents();
1059
1060 if (p1.IsVolumeDtc)
1061 p2events = false;
1062 if (p2.IsVolumeDtc)
1063 p1events = false;
1064
1065 if (!p2events && !p1events)
1066 return;
1067
1068 Vector3 vel = Vector3.Zero;
1069 if (p2 != null && p2.IsPhysical)
1070 vel = p2.Velocity;
1071
1072 if (p1 != null && p1.IsPhysical)
1073 vel -= p1.Velocity;
1074
1075 contact.RelativeSpeed = Vector3.Dot(vel, contact.SurfaceNormal);
1076
1077 switch ((ActorTypes)p1.PhysicsActorType)
1078 {
1079 case ActorTypes.Agent:
1080 case ActorTypes.Prim:
1081 {
1082 switch ((ActorTypes)p2.PhysicsActorType)
1083 {
1084 case ActorTypes.Agent:
1085 case ActorTypes.Prim:
1086 if (p2events)
1087 {
1088 AddCollisionEventReporting(p2);
1089 p2.AddCollisionEvent(p1.ParentActor.LocalID, contact);
1090 }
1091 obj2LocalID = p2.ParentActor.LocalID;
1092 break;
1093
1094 case ActorTypes.Ground:
1095 case ActorTypes.Unknown:
1096 default:
1097 obj2LocalID = 0;
1098 break;
1099 }
1100 if (p1events)
1101 {
1102 contact.SurfaceNormal = -contact.SurfaceNormal;
1103 AddCollisionEventReporting(p1);
1104 p1.AddCollisionEvent(obj2LocalID, contact);
1105 }
1106 break;
1107 }
1108 case ActorTypes.Ground:
1109 case ActorTypes.Unknown:
1110 default:
1111 {
1112 if (p2events && !p2.IsVolumeDtc)
1113 {
1114 AddCollisionEventReporting(p2);
1115 p2.AddCollisionEvent(0, contact);
1116 }
1117 break;
1118 }
1119 }
1120 }
1121
1122 /// <summary>
1123 /// This is our collision testing routine in ODE
1124 /// </summary>
1125 /// <param name="timeStep"></param>
1126 private void collision_optimized()
1127 {
1128 lock (_characters)
1129 {
1130 try
1131 {
1132 foreach (OdeCharacter chr in _characters)
1133 {
1134 if (chr == null)
1135 continue;
1136
1137 chr.IsColliding = false;
1138 // chr.CollidingGround = false; not done here
1139 chr.CollidingObj = false;
1140
1141 if(chr.Body == IntPtr.Zero || chr.collider == IntPtr.Zero )
1142 continue;
1143
1144 // do colisions with static space
1145 d.SpaceCollide2(chr.collider, StaticSpace, IntPtr.Zero, nearCallback);
1146
1147 // no coll with gnd
1148 }
1149 // chars with chars
1150 d.SpaceCollide(CharsSpace, IntPtr.Zero, nearCallback);
1151
1152 }
1153 catch (AccessViolationException)
1154 {
1155 m_log.Warn("[PHYSICS]: Unable to collide Character to static space");
1156 }
1157
1158 }
1159
1160 lock (_activeprims)
1161 {
1162 foreach (OdePrim aprim in _activeprims)
1163 {
1164 aprim.CollisionScore = 0;
1165 aprim.IsColliding = false;
1166 }
1167 }
1168 lock (_activegroups)
1169 {
1170 try
1171 {
1172 foreach (OdePrim aprim in _activegroups)
1173 {
1174 if(!aprim.m_outbounds && d.BodyIsEnabled(aprim.Body) &&
1175 aprim.collide_geom != IntPtr.Zero)
1176 {
1177 d.SpaceCollide2(StaticSpace, aprim.collide_geom, IntPtr.Zero, nearCallback);
1178 d.SpaceCollide2(GroundSpace, aprim.collide_geom, IntPtr.Zero, nearCallback);
1179 }
1180 }
1181 }
1182 catch (Exception e)
1183 {
1184 m_log.Warn("[PHYSICS]: Unable to collide Active to Static: " + e.Message);
1185 }
1186 }
1187
1188 // colide active amoung them
1189 try
1190 {
1191 d.SpaceCollide(ActiveSpace, IntPtr.Zero, nearCallback);
1192 }
1193 catch (Exception e)
1194 {
1195 m_log.Warn("[PHYSICS]: Unable to collide in Active: " + e.Message);
1196 }
1197
1198 // and with chars
1199 try
1200 {
1201 d.SpaceCollide2(CharsSpace,ActiveSpace, IntPtr.Zero, nearCallback);
1202 }
1203 catch (Exception e)
1204 {
1205 m_log.Warn("[PHYSICS]: Unable to collide Active to Character: " + e.Message);
1206 }
1207 }
1208
1209 #endregion
1210 /// <summary>
1211 /// Add actor to the list that should receive collision events in the simulate loop.
1212 /// </summary>
1213 /// <param name="obj"></param>
1214 public void AddCollisionEventReporting(PhysicsActor obj)
1215 {
1216 if (!_collisionEventPrim.Contains(obj))
1217 _collisionEventPrim.Add(obj);
1218 }
1219
1220 /// <summary>
1221 /// Remove actor from the list that should receive collision events in the simulate loop.
1222 /// </summary>
1223 /// <param name="obj"></param>
1224 public void RemoveCollisionEventReporting(PhysicsActor obj)
1225 {
1226 if (_collisionEventPrim.Contains(obj) && !_collisionEventPrimRemove.Contains(obj))
1227 _collisionEventPrimRemove.Add(obj);
1228 }
1229
1230 public override float TimeDilation
1231 {
1232 get { return m_timeDilation; }
1233 }
1234
1235 public override bool SupportsNINJAJoints
1236 {
1237 get { return false; }
1238 }
1239
1240 #region Add/Remove Entities
1241
1242 public override PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 velocity, Vector3 size, bool isFlying)
1243 {
1244 return null;
1245 }
1246
1247 public override PhysicsActor AddAvatar(uint localID, string avName, Vector3 position, Vector3 size, float feetOffset, bool isFlying)
1248 {
1249 OdeCharacter newAv = new OdeCharacter(localID, avName, this, position,
1250 size, feetOffset, avDensity, avMovementDivisorWalk, avMovementDivisorRun);
1251 newAv.Flying = isFlying;
1252 newAv.MinimumGroundFlightOffset = minimumGroundFlightOffset;
1253
1254 return newAv;
1255 }
1256
1257 public void AddCharacter(OdeCharacter chr)
1258 {
1259 lock (_characters)
1260 {
1261 if (!_characters.Contains(chr))
1262 {
1263 _characters.Add(chr);
1264 if (chr.bad)
1265 m_log.DebugFormat("[PHYSICS] Added BAD actor {0} to characters list", chr.m_uuid);
1266 }
1267 }
1268 }
1269
1270 public void RemoveCharacter(OdeCharacter chr)
1271 {
1272 lock (_characters)
1273 {
1274 if (_characters.Contains(chr))
1275 {
1276 _characters.Remove(chr);
1277 }
1278 }
1279 }
1280
1281 public void BadCharacter(OdeCharacter chr)
1282 {
1283 lock (_badCharacter)
1284 {
1285 if (!_badCharacter.Contains(chr))
1286 _badCharacter.Add(chr);
1287 }
1288 }
1289
1290 public override void RemoveAvatar(PhysicsActor actor)
1291 {
1292 //m_log.Debug("[PHYSICS]:ODELOCK");
1293 ((OdeCharacter) actor).Destroy();
1294 }
1295
1296
1297 public void addActivePrim(OdePrim activatePrim)
1298 {
1299 // adds active prim..
1300 lock (_activeprims)
1301 {
1302 if (!_activeprims.Contains(activatePrim))
1303 _activeprims.Add(activatePrim);
1304 }
1305 }
1306
1307 public void addActiveGroups(OdePrim activatePrim)
1308 {
1309 lock (_activegroups)
1310 {
1311 if (!_activegroups.Contains(activatePrim))
1312 _activegroups.Add(activatePrim);
1313 }
1314 }
1315
1316 private PhysicsActor AddPrim(String name, Vector3 position, Vector3 size, Quaternion rotation,
1317 PrimitiveBaseShape pbs, bool isphysical, bool isPhantom, byte shapeType, uint localID)
1318 {
1319 OdePrim newPrim;
1320 lock (OdeLock)
1321 {
1322 newPrim = new OdePrim(name, this, position, size, rotation, pbs, isphysical, isPhantom, shapeType, localID);
1323 lock (_prims)
1324 _prims.Add(newPrim);
1325 }
1326 return newPrim;
1327 }
1328
1329 public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position,
1330 Vector3 size, Quaternion rotation, bool isPhysical, bool isPhantom, uint localid)
1331 {
1332 return AddPrim(primName, position, size, rotation, pbs, isPhysical, isPhantom, 0 , localid);
1333 }
1334
1335
1336 public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position,
1337 Vector3 size, Quaternion rotation, bool isPhysical, uint localid)
1338 {
1339 return AddPrim(primName, position, size, rotation, pbs, isPhysical,false, 0, localid);
1340 }
1341
1342 public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position,
1343 Vector3 size, Quaternion rotation, bool isPhysical, bool isPhantom, byte shapeType, uint localid)
1344 {
1345
1346 return AddPrim(primName, position, size, rotation, pbs, isPhysical,isPhantom, shapeType, localid);
1347 }
1348
1349 public void remActivePrim(OdePrim deactivatePrim)
1350 {
1351 lock (_activeprims)
1352 {
1353 _activeprims.Remove(deactivatePrim);
1354 }
1355 }
1356 public void remActiveGroup(OdePrim deactivatePrim)
1357 {
1358 lock (_activegroups)
1359 {
1360 _activegroups.Remove(deactivatePrim);
1361 }
1362 }
1363
1364 public override void RemovePrim(PhysicsActor prim)
1365 {
1366 // As with all ODE physics operations, we don't remove the prim immediately but signal that it should be
1367 // removed in the next physics simulate pass.
1368 if (prim is OdePrim)
1369 {
1370// lock (OdeLock)
1371 {
1372
1373 OdePrim p = (OdePrim)prim;
1374 p.setPrimForRemoval();
1375 }
1376 }
1377 }
1378
1379 public void RemovePrimThreadLocked(OdePrim prim)
1380 {
1381 //Console.WriteLine("RemovePrimThreadLocked " + prim.m_primName);
1382 lock (prim)
1383 {
1384// RemoveCollisionEventReporting(prim);
1385 lock (_prims)
1386 _prims.Remove(prim);
1387 }
1388
1389 }
1390
1391 public bool havePrim(OdePrim prm)
1392 {
1393 lock (_prims)
1394 return _prims.Contains(prm);
1395 }
1396
1397 public bool haveActor(PhysicsActor actor)
1398 {
1399 if (actor is OdePrim)
1400 {
1401 lock (_prims)
1402 return _prims.Contains((OdePrim)actor);
1403 }
1404 else if (actor is OdeCharacter)
1405 {
1406 lock (_characters)
1407 return _characters.Contains((OdeCharacter)actor);
1408 }
1409 return false;
1410 }
1411
1412 #endregion
1413
1414 #region Space Separation Calculation
1415
1416 /// <summary>
1417 /// Called when a static prim moves or becomes static
1418 /// Places the prim in a space one the static sub-spaces grid
1419 /// </summary>
1420 /// <param name="geom">the pointer to the geom that moved</param>
1421 /// <param name="pos">the position that the geom moved to</param>
1422 /// <param name="currentspace">a pointer to the space it was in before it was moved.</param>
1423 /// <returns>a pointer to the new space it's in</returns>
1424 public IntPtr MoveGeomToStaticSpace(IntPtr geom, Vector3 pos, IntPtr currentspace)
1425 {
1426 // moves a prim into another static sub-space or from another space into a static sub-space
1427
1428 // Called ODEPrim so
1429 // it's already in locked space.
1430
1431 if (geom == IntPtr.Zero) // shouldn't happen
1432 return IntPtr.Zero;
1433
1434 // get the static sub-space for current position
1435 IntPtr newspace = calculateSpaceForGeom(pos);
1436
1437 if (newspace == currentspace) // if we are there all done
1438 return newspace;
1439
1440 // else remove it from its current space
1441 if (currentspace != IntPtr.Zero && d.SpaceQuery(currentspace, geom))
1442 {
1443 if (d.GeomIsSpace(currentspace))
1444 {
1445 waitForSpaceUnlock(currentspace);
1446 d.SpaceRemove(currentspace, geom);
1447
1448 if (d.SpaceGetSublevel(currentspace) > 2 && d.SpaceGetNumGeoms(currentspace) == 0)
1449 {
1450 d.SpaceDestroy(currentspace);
1451 }
1452 }
1453 else
1454 {
1455 m_log.Info("[Physics]: Invalid or empty Space passed to 'MoveGeomToStaticSpace':" + currentspace +
1456 " Geom:" + geom);
1457 }
1458 }
1459 else // odd currentspace is null or doesn't contain the geom? lets try the geom ideia of current space
1460 {
1461 currentspace = d.GeomGetSpace(geom);
1462 if (currentspace != IntPtr.Zero)
1463 {
1464 if (d.GeomIsSpace(currentspace))
1465 {
1466 waitForSpaceUnlock(currentspace);
1467 d.SpaceRemove(currentspace, geom);
1468
1469 if (d.SpaceGetSublevel(currentspace) > 2 && d.SpaceGetNumGeoms(currentspace) == 0)
1470 {
1471 d.SpaceDestroy(currentspace);
1472 }
1473
1474 }
1475 }
1476 }
1477
1478 // put the geom in the newspace
1479 waitForSpaceUnlock(newspace);
1480 d.SpaceAdd(newspace, geom);
1481
1482 // let caller know this newspace
1483 return newspace;
1484 }
1485
1486 /// <summary>
1487 /// Calculates the space the prim should be in by its position
1488 /// </summary>
1489 /// <param name="pos"></param>
1490 /// <returns>a pointer to the space. This could be a new space or reused space.</returns>
1491 public IntPtr calculateSpaceForGeom(Vector3 pos)
1492 {
1493 int x, y;
1494
1495 if (pos.X < 0)
1496 return staticPrimspaceOffRegion[0];
1497
1498 if (pos.Y < 0)
1499 return staticPrimspaceOffRegion[2];
1500
1501 x = (int)(pos.X * spacesPerMeterX);
1502 if (x > spaceGridMaxX)
1503 return staticPrimspaceOffRegion[1];
1504
1505 y = (int)(pos.Y * spacesPerMeterY);
1506 if (y > spaceGridMaxY)
1507 return staticPrimspaceOffRegion[3];
1508
1509 return staticPrimspace[x, y];
1510 }
1511
1512 #endregion
1513
1514
1515 /// <summary>
1516 /// Called to queue a change to a actor
1517 /// to use in place of old taint mechanism so changes do have a time sequence
1518 /// </summary>
1519
1520 public void AddChange(PhysicsActor actor, changes what, Object arg)
1521 {
1522 ODEchangeitem item = new ODEchangeitem();
1523 item.actor = actor;
1524 item.what = what;
1525 item.arg = arg;
1526 ChangesQueue.Enqueue(item);
1527 }
1528
1529 /// <summary>
1530 /// Called after our prim properties are set Scale, position etc.
1531 /// We use this event queue like method to keep changes to the physical scene occuring in the threadlocked mutex
1532 /// This assures us that we have no race conditions
1533 /// </summary>
1534 /// <param name="prim"></param>
1535 public override void AddPhysicsActorTaint(PhysicsActor prim)
1536 {
1537 }
1538
1539 // does all pending changes generated during region load process
1540 public override void ProcessPreSimulation()
1541 {
1542 lock (OdeLock)
1543 {
1544 if (world == IntPtr.Zero)
1545 {
1546 ChangesQueue.Clear();
1547 return;
1548 }
1549
1550 ODEchangeitem item;
1551
1552 int donechanges = 0;
1553 if (ChangesQueue.Count > 0)
1554 {
1555 m_log.InfoFormat("[ubOde] start processing pending actor operations");
1556 int tstart = Util.EnvironmentTickCount();
1557
1558 while (ChangesQueue.Dequeue(out item))
1559 {
1560 if (item.actor != null)
1561 {
1562 try
1563 {
1564 if (item.actor is OdeCharacter)
1565 ((OdeCharacter)item.actor).DoAChange(item.what, item.arg);
1566 else if (((OdePrim)item.actor).DoAChange(item.what, item.arg))
1567 RemovePrimThreadLocked((OdePrim)item.actor);
1568 }
1569 catch
1570 {
1571 m_log.WarnFormat("[PHYSICS]: Operation failed for a actor {0} {1}",
1572 item.actor.Name, item.what.ToString());
1573 }
1574 }
1575 donechanges++;
1576 }
1577 int time = Util.EnvironmentTickCountSubtract(tstart);
1578 m_log.InfoFormat("[ubOde] finished {0} operations in {1}ms", donechanges, time);
1579 }
1580 m_log.InfoFormat("[ubOde] {0} prim actors loaded",_prims.Count);
1581 }
1582 }
1583
1584 /// <summary>
1585 /// This is our main simulate loop
1586 /// It's thread locked by a Mutex in the scene.
1587 /// It holds Collisions, it instructs ODE to step through the physical reactions
1588 /// It moves the objects around in memory
1589 /// It calls the methods that report back to the object owners.. (scenepresence, SceneObjectGroup)
1590 /// </summary>
1591 /// <param name="timeStep"></param>
1592 /// <returns></returns>
1593 public override float Simulate(float reqTimeStep)
1594 {
1595 DateTime now = DateTime.UtcNow;
1596 TimeSpan timedif = now - m_lastframe;
1597 float timeStep = (float)timedif.TotalSeconds;
1598 m_lastframe = now;
1599
1600 // acumulate time so we can reduce error
1601 step_time += timeStep;
1602
1603 if (step_time < HalfOdeStep)
1604 return 0;
1605
1606 if (framecount < 0)
1607 framecount = 0;
1608
1609 framecount++;
1610
1611// checkThread();
1612 int nodeframes = 0;
1613 float fps = 0;
1614
1615 lock (SimulationLock)
1616 lock(OdeLock)
1617 {
1618 if (world == IntPtr.Zero)
1619 {
1620 ChangesQueue.Clear();
1621 return 0;
1622 }
1623
1624 ODEchangeitem item;
1625
1626// d.WorldSetQuickStepNumIterations(world, curphysiteractions);
1627
1628 int loopstartMS = Util.EnvironmentTickCount();
1629 int looptimeMS = 0;
1630 int changestimeMS = 0;
1631 int maxChangestime = (int)(reqTimeStep * 500f); // half the time
1632 int maxLoopTime = (int)(reqTimeStep * 1200f); // 1.2 the time
1633
1634 if (ChangesQueue.Count > 0)
1635 {
1636 while (ChangesQueue.Dequeue(out item))
1637 {
1638 if (item.actor != null)
1639 {
1640 try
1641 {
1642 if (item.actor is OdeCharacter)
1643 ((OdeCharacter)item.actor).DoAChange(item.what, item.arg);
1644 else if (((OdePrim)item.actor).DoAChange(item.what, item.arg))
1645 RemovePrimThreadLocked((OdePrim)item.actor);
1646 }
1647 catch
1648 {
1649 m_log.WarnFormat("[PHYSICS]: doChange failed for a actor {0} {1}",
1650 item.actor.Name, item.what.ToString());
1651 }
1652 }
1653 changestimeMS = Util.EnvironmentTickCountSubtract(loopstartMS);
1654 if (changestimeMS > maxChangestime)
1655 break;
1656 }
1657 }
1658
1659 // do simulation taking at most 150ms total time including changes
1660 while (step_time > HalfOdeStep)
1661 {
1662 try
1663 {
1664 // clear pointer/counter to contacts to pass into joints
1665 m_global_contactcount = 0;
1666
1667
1668 // Move characters
1669 lock (_characters)
1670 {
1671 List<OdeCharacter> defects = new List<OdeCharacter>();
1672 foreach (OdeCharacter actor in _characters)
1673 {
1674 if (actor != null)
1675 actor.Move(defects);
1676 }
1677 if (defects.Count != 0)
1678 {
1679 foreach (OdeCharacter defect in defects)
1680 {
1681 RemoveCharacter(defect);
1682 }
1683 defects.Clear();
1684 }
1685 }
1686
1687 // Move other active objects
1688 lock (_activegroups)
1689 {
1690 foreach (OdePrim aprim in _activegroups)
1691 {
1692 aprim.Move();
1693 }
1694 }
1695
1696 m_rayCastManager.ProcessQueuedRequests();
1697
1698 collision_optimized();
1699
1700 foreach (PhysicsActor obj in _collisionEventPrim)
1701 {
1702 if (obj == null)
1703 continue;
1704
1705 switch ((ActorTypes)obj.PhysicsActorType)
1706 {
1707 case ActorTypes.Agent:
1708 OdeCharacter cobj = (OdeCharacter)obj;
1709 cobj.AddCollisionFrameTime((int)(odetimestepMS));
1710 cobj.SendCollisions();
1711 break;
1712
1713 case ActorTypes.Prim:
1714 OdePrim pobj = (OdePrim)obj;
1715 if (pobj.Body == IntPtr.Zero || (d.BodyIsEnabled(pobj.Body) && !pobj.m_outbounds))
1716 if (!pobj.m_outbounds)
1717 {
1718 pobj.AddCollisionFrameTime((int)(odetimestepMS));
1719 pobj.SendCollisions();
1720 }
1721 break;
1722 }
1723 }
1724
1725 foreach (PhysicsActor obj in _collisionEventPrimRemove)
1726 _collisionEventPrim.Remove(obj);
1727
1728 _collisionEventPrimRemove.Clear();
1729
1730 // do a ode simulation step
1731 d.WorldQuickStep(world, ODE_STEPSIZE);
1732 d.JointGroupEmpty(contactgroup);
1733
1734 // update managed ideia of physical data and do updates to core
1735 /*
1736 lock (_characters)
1737 {
1738 foreach (OdeCharacter actor in _characters)
1739 {
1740 if (actor != null)
1741 {
1742 if (actor.bad)
1743 m_log.WarnFormat("[PHYSICS]: BAD Actor {0} in _characters list was not removed?", actor.m_uuid);
1744
1745 actor.UpdatePositionAndVelocity();
1746 }
1747 }
1748 }
1749 */
1750
1751 lock (_activegroups)
1752 {
1753 {
1754 foreach (OdePrim actor in _activegroups)
1755 {
1756 if (actor.IsPhysical)
1757 {
1758 actor.UpdatePositionAndVelocity(framecount);
1759 }
1760 }
1761 }
1762 }
1763 }
1764 catch (Exception e)
1765 {
1766 m_log.ErrorFormat("[PHYSICS]: {0}, {1}, {2}", e.Message, e.TargetSite, e);
1767// ode.dunlock(world);
1768 }
1769
1770 step_time -= ODE_STEPSIZE;
1771 nodeframes++;
1772
1773 looptimeMS = Util.EnvironmentTickCountSubtract(loopstartMS);
1774 if (looptimeMS > maxLoopTime)
1775 break;
1776 }
1777
1778 lock (_badCharacter)
1779 {
1780 if (_badCharacter.Count > 0)
1781 {
1782 foreach (OdeCharacter chr in _badCharacter)
1783 {
1784 RemoveCharacter(chr);
1785 }
1786
1787 _badCharacter.Clear();
1788 }
1789 }
1790
1791 timedif = now - m_lastMeshExpire;
1792
1793 if (timedif.Seconds > 10)
1794 {
1795 mesher.ExpireReleaseMeshs();
1796 m_lastMeshExpire = now;
1797 }
1798
1799// information block for in debug breakpoint only
1800/*
1801 int ntopactivegeoms = d.SpaceGetNumGeoms(ActiveSpace);
1802 int ntopstaticgeoms = d.SpaceGetNumGeoms(StaticSpace);
1803 int ngroundgeoms = d.SpaceGetNumGeoms(GroundSpace);
1804
1805 int nactivegeoms = 0;
1806 int nactivespaces = 0;
1807
1808 int nstaticgeoms = 0;
1809 int nstaticspaces = 0;
1810 IntPtr sp;
1811
1812 for (int i = 0; i < ntopactivegeoms; i++)
1813 {
1814 sp = d.SpaceGetGeom(ActiveSpace, i);
1815 if (d.GeomIsSpace(sp))
1816 {
1817 nactivespaces++;
1818 nactivegeoms += d.SpaceGetNumGeoms(sp);
1819 }
1820 else
1821 nactivegeoms++;
1822 }
1823
1824 for (int i = 0; i < ntopstaticgeoms; i++)
1825 {
1826 sp = d.SpaceGetGeom(StaticSpace, i);
1827 if (d.GeomIsSpace(sp))
1828 {
1829 nstaticspaces++;
1830 nstaticgeoms += d.SpaceGetNumGeoms(sp);
1831 }
1832 else
1833 nstaticgeoms++;
1834 }
1835
1836 int ntopgeoms = d.SpaceGetNumGeoms(TopSpace);
1837
1838 int totgeoms = nstaticgeoms + nactivegeoms + ngroundgeoms + 1; // one ray
1839 int nbodies = d.NTotalBodies;
1840 int ngeoms = d.NTotalGeoms;
1841*/
1842 // Finished with all sim stepping. If requested, dump world state to file for debugging.
1843 // TODO: This call to the export function is already inside lock (OdeLock) - but is an extra lock needed?
1844 // TODO: This overwrites all dump files in-place. Should this be a growing logfile, or separate snapshots?
1845 if (physics_logging && (physics_logging_interval > 0) && (framecount % physics_logging_interval == 0))
1846 {
1847 string fname = "state-" + world.ToString() + ".DIF"; // give each physics world a separate filename
1848 string prefix = "world" + world.ToString(); // prefix for variable names in exported .DIF file
1849
1850 if (physics_logging_append_existing_logfile)
1851 {
1852 string header = "-------------- START OF PHYSICS FRAME " + framecount.ToString() + " --------------";
1853 TextWriter fwriter = File.AppendText(fname);
1854 fwriter.WriteLine(header);
1855 fwriter.Close();
1856 }
1857
1858 d.WorldExportDIF(world, fname, physics_logging_append_existing_logfile, prefix);
1859 }
1860
1861 fps = (float)nodeframes * ODE_STEPSIZE / reqTimeStep;
1862
1863 if(step_time < HalfOdeStep)
1864 m_timeDilation = 1.0f;
1865 else if (step_time > m_SkipFramesAtms)
1866 {
1867 // if we lag too much skip frames
1868 m_timeDilation = 0.0f;
1869 step_time = 0;
1870 m_lastframe = DateTime.UtcNow; // skip also the time lost
1871 }
1872 else
1873 {
1874 m_timeDilation = ODE_STEPSIZE / step_time;
1875 if (m_timeDilation > 1)
1876 m_timeDilation = 1;
1877 }
1878 }
1879
1880 return fps;
1881 }
1882
1883 /// <summary>
1884 public override void GetResults()
1885 {
1886 }
1887
1888 public override bool IsThreaded
1889 {
1890 // for now we won't be multithreaded
1891 get { return (false); }
1892 }
1893
1894 public float GetTerrainHeightAtXY(float x, float y)
1895 {
1896
1897 int offsetX = 0;
1898 int offsetY = 0;
1899
1900 if (m_suportCombine)
1901 {
1902 offsetX = ((int)(x / (int)Constants.RegionSize)) * (int)Constants.RegionSize;
1903 offsetY = ((int)(y / (int)Constants.RegionSize)) * (int)Constants.RegionSize;
1904 }
1905
1906 // get region map
1907 IntPtr heightFieldGeom = IntPtr.Zero;
1908 if (!RegionTerrain.TryGetValue(new Vector3(offsetX, offsetY, 0), out heightFieldGeom))
1909 return 0f;
1910
1911 if (heightFieldGeom == IntPtr.Zero)
1912 return 0f;
1913
1914 if (!TerrainHeightFieldHeights.ContainsKey(heightFieldGeom))
1915 return 0f;
1916
1917 // TerrainHeightField for ODE as offset 1m
1918 x += 1f - offsetX;
1919 y += 1f - offsetY;
1920
1921 // make position fit into array
1922 if (x < 0)
1923 x = 0;
1924 if (y < 0)
1925 y = 0;
1926
1927 // integer indexs
1928 int ix;
1929 int iy;
1930 // interpolators offset
1931 float dx;
1932 float dy;
1933
1934 int regsizeX = (int)m_regionWidth + 3; // map size see setterrain number of samples
1935 int regsizeY = (int)m_regionHeight + 3; // map size see setterrain number of samples
1936 int regsize = regsizeX;
1937
1938 if (m_OSOdeLib)
1939 {
1940 if (x < regsizeX - 1)
1941 {
1942 ix = (int)x;
1943 dx = x - (float)ix;
1944 }
1945 else // out world use external height
1946 {
1947 ix = regsizeX - 2;
1948 dx = 0;
1949 }
1950 if (y < regsizeY - 1)
1951 {
1952 iy = (int)y;
1953 dy = y - (float)iy;
1954 }
1955 else
1956 {
1957 iy = regsizeY - 2;
1958 dy = 0;
1959 }
1960 }
1961 else
1962 {
1963 // we still have square fixed size regions
1964 // also flip x and y because of how map is done for ODE fliped axis
1965 // so ix,iy,dx and dy are inter exchanged
1966
1967 regsize = regsizeY;
1968
1969 if (x < regsizeX - 1)
1970 {
1971 iy = (int)x;
1972 dy = x - (float)iy;
1973 }
1974 else // out world use external height
1975 {
1976 iy = regsizeX - 2;
1977 dy = 0;
1978 }
1979 if (y < regsizeY - 1)
1980 {
1981 ix = (int)y;
1982 dx = y - (float)ix;
1983 }
1984 else
1985 {
1986 ix = regsizeY - 2;
1987 dx = 0;
1988 }
1989 }
1990
1991 float h0;
1992 float h1;
1993 float h2;
1994
1995 iy *= regsize;
1996 iy += ix; // all indexes have iy + ix
1997
1998 float[] heights = TerrainHeightFieldHeights[heightFieldGeom];
1999 /*
2000 if ((dx + dy) <= 1.0f)
2001 {
2002 h0 = ((float)heights[iy]); // 0,0 vertice
2003 h1 = (((float)heights[iy + 1]) - h0) * dx; // 1,0 vertice minus 0,0
2004 h2 = (((float)heights[iy + regsize]) - h0) * dy; // 0,1 vertice minus 0,0
2005 }
2006 else
2007 {
2008 h0 = ((float)heights[iy + regsize + 1]); // 1,1 vertice
2009 h1 = (((float)heights[iy + 1]) - h0) * (1 - dy); // 1,1 vertice minus 1,0
2010 h2 = (((float)heights[iy + regsize]) - h0) * (1 - dx); // 1,1 vertice minus 0,1
2011 }
2012 */
2013 h0 = ((float)heights[iy]); // 0,0 vertice
2014
2015 if (dy>dx)
2016 {
2017 iy += regsize;
2018 h2 = (float)heights[iy]; // 0,1 vertice
2019 h1 = (h2 - h0) * dy; // 0,1 vertice minus 0,0
2020 h2 = ((float)heights[iy + 1] - h2) * dx; // 1,1 vertice minus 0,1
2021 }
2022 else
2023 {
2024 iy++;
2025 h2 = (float)heights[iy]; // vertice 1,0
2026 h1 = (h2 - h0) * dx; // 1,0 vertice minus 0,0
2027 h2 = (((float)heights[iy + regsize]) - h2) * dy; // 1,1 vertice minus 1,0
2028 }
2029
2030 return h0 + h1 + h2;
2031 }
2032
2033 public Vector3 GetTerrainNormalAtXY(float x, float y)
2034 {
2035 int offsetX = 0;
2036 int offsetY = 0;
2037
2038 if (m_suportCombine)
2039 {
2040 offsetX = ((int)(x / (int)Constants.RegionSize)) * (int)Constants.RegionSize;
2041 offsetY = ((int)(y / (int)Constants.RegionSize)) * (int)Constants.RegionSize;
2042 }
2043
2044 // get region map
2045 IntPtr heightFieldGeom = IntPtr.Zero;
2046 Vector3 norm = new Vector3(0, 0, 1);
2047
2048 if (!RegionTerrain.TryGetValue(new Vector3(offsetX, offsetY, 0), out heightFieldGeom))
2049 return norm; ;
2050
2051 if (heightFieldGeom == IntPtr.Zero)
2052 return norm;
2053
2054 if (!TerrainHeightFieldHeights.ContainsKey(heightFieldGeom))
2055 return norm;
2056
2057 // TerrainHeightField for ODE as offset 1m
2058 x += 1f - offsetX;
2059 y += 1f - offsetY;
2060
2061 // make position fit into array
2062 if (x < 0)
2063 x = 0;
2064 if (y < 0)
2065 y = 0;
2066
2067 // integer indexs
2068 int ix;
2069 int iy;
2070 // interpolators offset
2071 float dx;
2072 float dy;
2073
2074 int regsizeX = (int)m_regionWidth + 3; // map size see setterrain number of samples
2075 int regsizeY = (int)m_regionHeight + 3; // map size see setterrain number of samples
2076 int regsize = regsizeX;
2077
2078 int xstep = 1;
2079 int ystep = regsizeX;
2080 bool firstTri = false;
2081
2082 if (m_OSOdeLib)
2083 {
2084 if (x < regsizeX - 1)
2085 {
2086 ix = (int)x;
2087 dx = x - (float)ix;
2088 }
2089 else // out world use external height
2090 {
2091 ix = regsizeX - 2;
2092 dx = 0;
2093 }
2094 if (y < regsizeY - 1)
2095 {
2096 iy = (int)y;
2097 dy = y - (float)iy;
2098 }
2099 else
2100 {
2101 iy = regsizeY - 2;
2102 dy = 0;
2103 }
2104 firstTri = dy > dx;
2105 }
2106
2107 else
2108 {
2109 xstep = regsizeY;
2110 ystep = 1;
2111 regsize = regsizeY;
2112
2113 // we still have square fixed size regions
2114 // also flip x and y because of how map is done for ODE fliped axis
2115 // so ix,iy,dx and dy are inter exchanged
2116 if (x < regsizeX - 1)
2117 {
2118 iy = (int)x;
2119 dy = x - (float)iy;
2120 }
2121 else // out world use external height
2122 {
2123 iy = regsizeX - 2;
2124 dy = 0;
2125 }
2126 if (y < regsizeY - 1)
2127 {
2128 ix = (int)y;
2129 dx = y - (float)ix;
2130 }
2131 else
2132 {
2133 ix = regsizeY - 2;
2134 dx = 0;
2135 }
2136 firstTri = dx > dy;
2137 }
2138
2139 float h0;
2140 float h1;
2141 float h2;
2142
2143 iy *= regsize;
2144 iy += ix; // all indexes have iy + ix
2145
2146 float[] heights = TerrainHeightFieldHeights[heightFieldGeom];
2147
2148 if (firstTri)
2149 {
2150 h1 = ((float)heights[iy]); // 0,0 vertice
2151 iy += ystep;
2152 h0 = (float)heights[iy]; // 0,1
2153 h2 = (float)heights[iy+xstep]; // 1,1 vertice
2154 norm.X = h0 - h2;
2155 norm.Y = h1 - h0;
2156 }
2157 else
2158 {
2159 h2 = ((float)heights[iy]); // 0,0 vertice
2160 iy += xstep;
2161 h0 = ((float)heights[iy]); // 1,0 vertice
2162 h1 = (float)heights[iy+ystep]; // vertice 1,1
2163 norm.X = h2 - h0;
2164 norm.Y = h0 - h1;
2165 }
2166 norm.Z = 1;
2167 norm.Normalize();
2168 return norm;
2169 }
2170
2171 public override void SetTerrain(float[] heightMap)
2172 {
2173 if (m_worldOffset != Vector3.Zero && m_parentScene != null)
2174 {
2175 if (m_parentScene is ODEScene)
2176 {
2177 ((ODEScene)m_parentScene).SetTerrain(heightMap, m_worldOffset);
2178 }
2179 }
2180 else
2181 {
2182 SetTerrain(heightMap, m_worldOffset);
2183 }
2184 }
2185
2186 public override void CombineTerrain(float[] heightMap, Vector3 pOffset)
2187 {
2188 if(m_suportCombine)
2189 SetTerrain(heightMap, pOffset);
2190 }
2191
2192 public void SetTerrain(float[] heightMap, Vector3 pOffset)
2193 {
2194 if (m_OSOdeLib)
2195 OSSetTerrain(heightMap, pOffset);
2196 else
2197 OriSetTerrain(heightMap, pOffset);
2198 }
2199
2200 public void OriSetTerrain(float[] heightMap, Vector3 pOffset)
2201 {
2202 // assumes 1m size grid and constante size square regions
2203 // needs to know about sims around in future
2204
2205 float[] _heightmap;
2206
2207 uint regionsizeX = m_regionWidth;
2208 uint regionsizeY = m_regionHeight;
2209
2210 // map is rotated
2211 uint heightmapWidth = regionsizeY + 2;
2212 uint heightmapHeight = regionsizeX + 2;
2213
2214 uint heightmapWidthSamples = heightmapWidth + 1;
2215 uint heightmapHeightSamples = heightmapHeight + 1;
2216
2217 _heightmap = new float[heightmapWidthSamples * heightmapHeightSamples];
2218
2219 const float scale = 1.0f;
2220 const float offset = 0.0f;
2221 const float thickness = 10f;
2222 const int wrap = 0;
2223
2224
2225 float hfmin = float.MaxValue;
2226 float hfmax = float.MinValue;
2227 float val;
2228 uint xx;
2229 uint yy;
2230
2231 uint maxXX = regionsizeX - 1;
2232 uint maxYY = regionsizeY - 1;
2233 // flipping map adding one margin all around so things don't fall in edges
2234
2235 uint xt = 0;
2236 xx = 0;
2237
2238 for (uint x = 0; x < heightmapWidthSamples; x++)
2239 {
2240 if (x > 1 && xx < maxXX)
2241 xx++;
2242 yy = 0;
2243 for (uint y = 0; y < heightmapHeightSamples; y++)
2244 {
2245 if (y > 1 && y < maxYY)
2246 yy += regionsizeX;
2247
2248 val = heightMap[yy + xx];
2249 if (val < 0.0f)
2250 val = 0.0f; // no neg terrain as in chode
2251 _heightmap[xt + y] = val;
2252
2253 if (hfmin > val)
2254 hfmin = val;
2255 if (hfmax < val)
2256 hfmax = val;
2257 }
2258 xt += heightmapHeightSamples;
2259 }
2260
2261 lock (OdeLock)
2262 {
2263 IntPtr GroundGeom = IntPtr.Zero;
2264 if (RegionTerrain.TryGetValue(pOffset, out GroundGeom))
2265 {
2266 RegionTerrain.Remove(pOffset);
2267 if (GroundGeom != IntPtr.Zero)
2268 {
2269 actor_name_map.Remove(GroundGeom);
2270 d.GeomDestroy(GroundGeom);
2271
2272 if (TerrainHeightFieldHeights.ContainsKey(GroundGeom))
2273 {
2274 TerrainHeightFieldHeightsHandlers[GroundGeom].Free();
2275 TerrainHeightFieldHeightsHandlers.Remove(GroundGeom);
2276 TerrainHeightFieldHeights.Remove(GroundGeom);
2277 }
2278 }
2279 }
2280 IntPtr HeightmapData = d.GeomHeightfieldDataCreate();
2281
2282 GCHandle _heightmaphandler = GCHandle.Alloc(_heightmap, GCHandleType.Pinned);
2283
2284 d.GeomHeightfieldDataBuildSingle(HeightmapData, _heightmaphandler.AddrOfPinnedObject(), 0,
2285 heightmapHeight, heightmapWidth ,
2286 (int)heightmapHeightSamples, (int)heightmapWidthSamples, scale,
2287 offset, thickness, wrap);
2288
2289 d.GeomHeightfieldDataSetBounds(HeightmapData, hfmin - 1, hfmax + 1);
2290
2291 GroundGeom = d.CreateHeightfield(GroundSpace, HeightmapData, 1);
2292
2293 if (GroundGeom != IntPtr.Zero)
2294 {
2295 d.GeomSetCategoryBits(GroundGeom, (uint)(CollisionCategories.Land));
2296 d.GeomSetCollideBits(GroundGeom, 0);
2297
2298 PhysicsActor pa = new NullPhysicsActor();
2299 pa.Name = "Terrain";
2300 pa.PhysicsActorType = (int)ActorTypes.Ground;
2301 actor_name_map[GroundGeom] = pa;
2302
2303// geom_name_map[GroundGeom] = "Terrain";
2304
2305 d.Quaternion q = new d.Quaternion();
2306 q.X = 0.5f;
2307 q.Y = 0.5f;
2308 q.Z = 0.5f;
2309 q.W = 0.5f;
2310
2311 d.GeomSetQuaternion(GroundGeom, ref q);
2312 d.GeomSetPosition(GroundGeom, pOffset.X + m_regionWidth * 0.5f, pOffset.Y + m_regionHeight * 0.5f, 0.0f);
2313 RegionTerrain.Add(pOffset, GroundGeom);
2314 TerrainHeightFieldHeights.Add(GroundGeom, _heightmap);
2315 TerrainHeightFieldHeightsHandlers.Add(GroundGeom, _heightmaphandler);
2316 }
2317 }
2318 }
2319
2320 public void OSSetTerrain(float[] heightMap, Vector3 pOffset)
2321 {
2322 // assumes 1m size grid and constante size square regions
2323 // needs to know about sims around in future
2324
2325 float[] _heightmap;
2326
2327 uint regionsizeX = m_regionWidth;
2328 uint regionsizeY = m_regionHeight;
2329
2330 uint heightmapWidth = regionsizeX + 2;
2331 uint heightmapHeight = regionsizeY + 2;
2332
2333 uint heightmapWidthSamples = heightmapWidth + 1;
2334 uint heightmapHeightSamples = heightmapHeight + 1;
2335
2336 _heightmap = new float[heightmapWidthSamples * heightmapHeightSamples];
2337
2338
2339 float hfmin = float.MaxValue;
2340// float hfmax = float.MinValue;
2341 float val;
2342
2343
2344 uint maxXX = regionsizeX - 1;
2345 uint maxYY = regionsizeY - 1;
2346 // adding one margin all around so things don't fall in edges
2347
2348 uint xx;
2349 uint yy = 0;
2350 uint yt = 0;
2351
2352 for (uint y = 0; y < heightmapHeightSamples; y++)
2353 {
2354 if (y > 1 && y < maxYY)
2355 yy += regionsizeX;
2356 xx = 0;
2357 for (uint x = 0; x < heightmapWidthSamples; x++)
2358 {
2359 if (x > 1 && x < maxXX)
2360 xx++;
2361
2362 val = heightMap[yy + xx];
2363 if (val < 0.0f)
2364 val = 0.0f; // no neg terrain as in chode
2365 _heightmap[yt + x] = val;
2366
2367 if (hfmin > val)
2368 hfmin = val;
2369// if (hfmax < val)
2370// hfmax = val;
2371 }
2372 yt += heightmapWidthSamples;
2373 }
2374 lock (OdeLock)
2375 {
2376 IntPtr GroundGeom = IntPtr.Zero;
2377 if (RegionTerrain.TryGetValue(pOffset, out GroundGeom))
2378 {
2379 RegionTerrain.Remove(pOffset);
2380 if (GroundGeom != IntPtr.Zero)
2381 {
2382 actor_name_map.Remove(GroundGeom);
2383 d.GeomDestroy(GroundGeom);
2384
2385 if (TerrainHeightFieldHeights.ContainsKey(GroundGeom))
2386 {
2387 if (TerrainHeightFieldHeightsHandlers[GroundGeom].IsAllocated)
2388 TerrainHeightFieldHeightsHandlers[GroundGeom].Free();
2389 TerrainHeightFieldHeightsHandlers.Remove(GroundGeom);
2390 TerrainHeightFieldHeights.Remove(GroundGeom);
2391 }
2392 }
2393 }
2394 IntPtr HeightmapData = d.GeomOSTerrainDataCreate();
2395
2396 const int wrap = 0;
2397 float thickness = hfmin;
2398 if (thickness < 0)
2399 thickness = 1;
2400
2401 GCHandle _heightmaphandler = GCHandle.Alloc(_heightmap, GCHandleType.Pinned);
2402
2403 d.GeomOSTerrainDataBuild(HeightmapData, _heightmaphandler.AddrOfPinnedObject(), 0, 1.0f,
2404 (int)heightmapWidthSamples, (int)heightmapHeightSamples,
2405 thickness, wrap);
2406
2407// d.GeomOSTerrainDataSetBounds(HeightmapData, hfmin - 1, hfmax + 1);
2408 GroundGeom = d.CreateOSTerrain(GroundSpace, HeightmapData, 1);
2409 if (GroundGeom != IntPtr.Zero)
2410 {
2411 d.GeomSetCategoryBits(GroundGeom, (uint)(CollisionCategories.Land));
2412 d.GeomSetCollideBits(GroundGeom, 0);
2413
2414
2415 PhysicsActor pa = new NullPhysicsActor();
2416 pa.Name = "Terrain";
2417 pa.PhysicsActorType = (int)ActorTypes.Ground;
2418 actor_name_map[GroundGeom] = pa;
2419
2420// geom_name_map[GroundGeom] = "Terrain";
2421
2422 d.GeomSetPosition(GroundGeom, pOffset.X + m_regionWidth * 0.5f, pOffset.Y + m_regionHeight * 0.5f, 0.0f);
2423 RegionTerrain.Add(pOffset, GroundGeom);
2424 TerrainHeightFieldHeights.Add(GroundGeom, _heightmap);
2425 TerrainHeightFieldHeightsHandlers.Add(GroundGeom, _heightmaphandler);
2426 }
2427 }
2428 }
2429
2430 public override void DeleteTerrain()
2431 {
2432 }
2433
2434 public float GetWaterLevel()
2435 {
2436 return waterlevel;
2437 }
2438
2439 public override bool SupportsCombining()
2440 {
2441 return m_suportCombine;
2442 }
2443
2444 public override void SetWaterLevel(float baseheight)
2445 {
2446 waterlevel = baseheight;
2447 }
2448
2449 public override void Dispose()
2450 {
2451 lock (OdeLock)
2452 {
2453 if (world == IntPtr.Zero)
2454 return;
2455
2456 if (m_meshWorker != null)
2457 m_meshWorker.Stop();
2458
2459 if (m_rayCastManager != null)
2460 {
2461 m_rayCastManager.Dispose();
2462 m_rayCastManager = null;
2463 }
2464
2465 lock (_prims)
2466 {
2467 ChangesQueue.Clear();
2468 foreach (OdePrim prm in _prims)
2469 {
2470 prm.DoAChange(changes.Remove, null);
2471 _collisionEventPrim.Remove(prm);
2472 }
2473 _prims.Clear();
2474 }
2475
2476 OdeCharacter[] chtorem;
2477 lock (_characters)
2478 {
2479 chtorem = new OdeCharacter[_characters.Count];
2480 _characters.CopyTo(chtorem);
2481 }
2482
2483 ChangesQueue.Clear();
2484 foreach (OdeCharacter ch in chtorem)
2485 ch.DoAChange(changes.Remove, null);
2486
2487
2488 foreach (IntPtr GroundGeom in RegionTerrain.Values)
2489 {
2490 if (GroundGeom != IntPtr.Zero)
2491 d.GeomDestroy(GroundGeom);
2492 }
2493
2494 RegionTerrain.Clear();
2495
2496 if (TerrainHeightFieldHeightsHandlers.Count > 0)
2497 {
2498 foreach (GCHandle gch in TerrainHeightFieldHeightsHandlers.Values)
2499 {
2500 if (gch.IsAllocated)
2501 gch.Free();
2502 }
2503 }
2504
2505 TerrainHeightFieldHeightsHandlers.Clear();
2506 TerrainHeightFieldHeights.Clear();
2507
2508 if (ContactgeomsArray != IntPtr.Zero)
2509 {
2510 Marshal.FreeHGlobal(ContactgeomsArray);
2511 ContactgeomsArray = IntPtr.Zero;
2512 }
2513 if (GlobalContactsArray != IntPtr.Zero)
2514 {
2515 Marshal.FreeHGlobal(GlobalContactsArray);
2516 GlobalContactsArray = IntPtr.Zero;
2517 }
2518
2519 d.WorldDestroy(world);
2520 world = IntPtr.Zero;
2521 //d.CloseODE();
2522 }
2523 }
2524
2525 public override Dictionary<uint, float> GetTopColliders()
2526 {
2527 Dictionary<uint, float> returncolliders = new Dictionary<uint, float>();
2528 int cnt = 0;
2529 lock (_prims)
2530 {
2531 foreach (OdePrim prm in _prims)
2532 {
2533 if (prm.CollisionScore > 0)
2534 {
2535 returncolliders.Add(prm.LocalID, prm.CollisionScore);
2536 cnt++;
2537 prm.CollisionScore = 0f;
2538 if (cnt > 25)
2539 {
2540 break;
2541 }
2542 }
2543 }
2544 }
2545 return returncolliders;
2546 }
2547
2548 public override bool SupportsRayCast()
2549 {
2550 return true;
2551 }
2552
2553 public override void RaycastWorld(Vector3 position, Vector3 direction, float length, RaycastCallback retMethod)
2554 {
2555 if (retMethod != null)
2556 {
2557 ODERayRequest req = new ODERayRequest();
2558 req.actor = null;
2559 req.callbackMethod = retMethod;
2560 req.length = length;
2561 req.Normal = direction;
2562 req.Origin = position;
2563 req.Count = 0;
2564 req.filter = RayFilterFlags.AllPrims;
2565
2566 m_rayCastManager.QueueRequest(req);
2567 }
2568 }
2569
2570 public override void RaycastWorld(Vector3 position, Vector3 direction, float length, int Count, RayCallback retMethod)
2571 {
2572 if (retMethod != null)
2573 {
2574 ODERayRequest req = new ODERayRequest();
2575 req.actor = null;
2576 req.callbackMethod = retMethod;
2577 req.length = length;
2578 req.Normal = direction;
2579 req.Origin = position;
2580 req.Count = Count;
2581 req.filter = RayFilterFlags.AllPrims;
2582
2583 m_rayCastManager.QueueRequest(req);
2584 }
2585 }
2586
2587
2588 public override List<ContactResult> RaycastWorld(Vector3 position, Vector3 direction, float length, int Count)
2589 {
2590 List<ContactResult> ourresults = new List<ContactResult>();
2591 object SyncObject = new object();
2592
2593 RayCallback retMethod = delegate(List<ContactResult> results)
2594 {
2595 lock (SyncObject)
2596 {
2597 ourresults = results;
2598 Monitor.PulseAll(SyncObject);
2599 }
2600 };
2601
2602 ODERayRequest req = new ODERayRequest();
2603 req.actor = null;
2604 req.callbackMethod = retMethod;
2605 req.length = length;
2606 req.Normal = direction;
2607 req.Origin = position;
2608 req.Count = Count;
2609 req.filter = RayFilterFlags.AllPrims;
2610
2611 lock (SyncObject)
2612 {
2613 m_rayCastManager.QueueRequest(req);
2614 if (!Monitor.Wait(SyncObject, 500))
2615 return null;
2616 else
2617 return ourresults;
2618 }
2619 }
2620
2621 public override bool SupportsRaycastWorldFiltered()
2622 {
2623 return true;
2624 }
2625
2626 public override object RaycastWorld(Vector3 position, Vector3 direction, float length, int Count, RayFilterFlags filter)
2627 {
2628 object SyncObject = new object();
2629 List<ContactResult> ourresults = new List<ContactResult>();
2630
2631 RayCallback retMethod = delegate(List<ContactResult> results)
2632 {
2633 lock (SyncObject)
2634 {
2635 ourresults = results;
2636 Monitor.PulseAll(SyncObject);
2637 }
2638 };
2639
2640 ODERayRequest req = new ODERayRequest();
2641 req.actor = null;
2642 req.callbackMethod = retMethod;
2643 req.length = length;
2644 req.Normal = direction;
2645 req.Origin = position;
2646 req.Count = Count;
2647 req.filter = filter;
2648
2649 lock (SyncObject)
2650 {
2651 m_rayCastManager.QueueRequest(req);
2652 if (!Monitor.Wait(SyncObject, 500))
2653 return null;
2654 else
2655 return ourresults;
2656 }
2657 }
2658
2659 public override List<ContactResult> RaycastActor(PhysicsActor actor, Vector3 position, Vector3 direction, float length, int Count, RayFilterFlags flags)
2660 {
2661 if (actor == null)
2662 return new List<ContactResult>();
2663
2664 IntPtr geom;
2665 if (actor is OdePrim)
2666 geom = ((OdePrim)actor).prim_geom;
2667 else if (actor is OdeCharacter)
2668 geom = ((OdePrim)actor).prim_geom;
2669 else
2670 return new List<ContactResult>();
2671
2672 if (geom == IntPtr.Zero)
2673 return new List<ContactResult>();
2674
2675 List<ContactResult> ourResults = null;
2676 object SyncObject = new object();
2677
2678 RayCallback retMethod = delegate(List<ContactResult> results)
2679 {
2680 lock (SyncObject)
2681 {
2682 ourResults = results;
2683 Monitor.PulseAll(SyncObject);
2684 }
2685 };
2686
2687 ODERayRequest req = new ODERayRequest();
2688 req.actor = actor;
2689 req.callbackMethod = retMethod;
2690 req.length = length;
2691 req.Normal = direction;
2692 req.Origin = position;
2693 req.Count = Count;
2694 req.filter = flags;
2695
2696 lock (SyncObject)
2697 {
2698 m_rayCastManager.QueueRequest(req);
2699 if (!Monitor.Wait(SyncObject, 500))
2700 return new List<ContactResult>();
2701 }
2702
2703 if (ourResults == null)
2704 return new List<ContactResult>();
2705 return ourResults;
2706 }
2707
2708 public override List<ContactResult> BoxProbe(Vector3 position, Vector3 size, Quaternion orientation, int Count, RayFilterFlags flags)
2709 {
2710 List<ContactResult> ourResults = null;
2711 object SyncObject = new object();
2712
2713 ProbeBoxCallback retMethod = delegate(List<ContactResult> results)
2714 {
2715 lock (SyncObject)
2716 {
2717 ourResults = results;
2718 Monitor.PulseAll(SyncObject);
2719 }
2720 };
2721
2722 ODERayRequest req = new ODERayRequest();
2723 req.actor = null;
2724 req.callbackMethod = retMethod;
2725 req.Normal = size;
2726 req.Origin = position;
2727 req.orientation = orientation;
2728 req.Count = Count;
2729 req.filter = flags;
2730
2731 lock (SyncObject)
2732 {
2733 m_rayCastManager.QueueRequest(req);
2734 if (!Monitor.Wait(SyncObject, 500))
2735 return new List<ContactResult>();
2736 }
2737
2738 if (ourResults == null)
2739 return new List<ContactResult>();
2740 return ourResults;
2741 }
2742
2743 public override List<ContactResult> SphereProbe(Vector3 position, float radius, int Count, RayFilterFlags flags)
2744 {
2745 List<ContactResult> ourResults = null;
2746 object SyncObject = new object();
2747
2748 ProbeSphereCallback retMethod = delegate(List<ContactResult> results)
2749 {
2750 ourResults = results;
2751 Monitor.PulseAll(SyncObject);
2752 };
2753
2754 ODERayRequest req = new ODERayRequest();
2755 req.actor = null;
2756 req.callbackMethod = retMethod;
2757 req.length = radius;
2758 req.Origin = position;
2759 req.Count = Count;
2760 req.filter = flags;
2761
2762
2763 lock (SyncObject)
2764 {
2765 m_rayCastManager.QueueRequest(req);
2766 if (!Monitor.Wait(SyncObject, 500))
2767 return new List<ContactResult>();
2768 }
2769
2770 if (ourResults == null)
2771 return new List<ContactResult>();
2772 return ourResults;
2773 }
2774
2775 public override List<ContactResult> PlaneProbe(PhysicsActor actor, Vector4 plane, int Count, RayFilterFlags flags)
2776 {
2777 IntPtr geom = IntPtr.Zero;;
2778
2779 if (actor != null)
2780 {
2781 if (actor is OdePrim)
2782 geom = ((OdePrim)actor).prim_geom;
2783 else if (actor is OdeCharacter)
2784 geom = ((OdePrim)actor).prim_geom;
2785 }
2786
2787 List<ContactResult> ourResults = null;
2788 object SyncObject = new object();
2789
2790 ProbePlaneCallback retMethod = delegate(List<ContactResult> results)
2791 {
2792 ourResults = results;
2793 Monitor.PulseAll(SyncObject);
2794 };
2795
2796 ODERayRequest req = new ODERayRequest();
2797 req.actor = null;
2798 req.callbackMethod = retMethod;
2799 req.length = plane.W;
2800 req.Normal.X = plane.X;
2801 req.Normal.Y = plane.Y;
2802 req.Normal.Z = plane.Z;
2803 req.Count = Count;
2804 req.filter = flags;
2805
2806 lock (SyncObject)
2807 {
2808 m_rayCastManager.QueueRequest(req);
2809 if (!Monitor.Wait(SyncObject, 500))
2810 return new List<ContactResult>();
2811 }
2812
2813 if (ourResults == null)
2814 return new List<ContactResult>();
2815 return ourResults;
2816 }
2817
2818 public override int SitAvatar(PhysicsActor actor, Vector3 AbsolutePosition, Vector3 CameraPosition, Vector3 offset, Vector3 AvatarSize, SitAvatarCallback PhysicsSitResponse)
2819 {
2820 Util.FireAndForget( delegate
2821 {
2822 ODESitAvatar sitAvatar = new ODESitAvatar(this, m_rayCastManager);
2823 if(sitAvatar != null)
2824 sitAvatar.Sit(actor, AbsolutePosition, CameraPosition, offset, AvatarSize, PhysicsSitResponse);
2825 });
2826 return 1;
2827 }
2828
2829 }
2830}
diff --git a/OpenSim/Region/PhysicsModules/ubOde/ODESitAvatar.cs b/OpenSim/Region/PhysicsModules/ubOde/ODESitAvatar.cs
new file mode 100644
index 0000000..214205d
--- /dev/null
+++ b/OpenSim/Region/PhysicsModules/ubOde/ODESitAvatar.cs
@@ -0,0 +1,356 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27// Ubit Umarov 2012
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31using System.Runtime.InteropServices;
32using System.Text;
33using OpenSim.Framework;
34using OpenSim.Region.PhysicsModules.SharedBase;
35using OdeAPI;
36using log4net;
37using OpenMetaverse;
38
39namespace OpenSim.Region.PhysicsModule.ubOde
40{
41 /// <summary>
42 /// </summary>
43 public class ODESitAvatar
44 {
45 private ODEScene m_scene;
46 private ODERayCastRequestManager m_raymanager;
47
48 public ODESitAvatar(ODEScene pScene, ODERayCastRequestManager raymanager)
49 {
50 m_scene = pScene;
51 m_raymanager = raymanager;
52 }
53
54 private static Vector3 SitAjust = new Vector3(0, 0, 0.4f);
55 private const RayFilterFlags RaySitFlags = RayFilterFlags.AllPrims | RayFilterFlags.ClosestHit;
56
57 private void RotAroundZ(float x, float y, ref Quaternion ori)
58 {
59 double ang = Math.Atan2(y, x);
60 ang *= 0.5d;
61 float s = (float)Math.Sin(ang);
62 float c = (float)Math.Cos(ang);
63
64 ori.X = 0;
65 ori.Y = 0;
66 ori.Z = s;
67 ori.W = c;
68 }
69
70
71 public void Sit(PhysicsActor actor, Vector3 avPos, Vector3 avCameraPosition, Vector3 offset, Vector3 avOffset, SitAvatarCallback PhysicsSitResponse)
72 {
73 if (!m_scene.haveActor(actor) || !(actor is OdePrim) || ((OdePrim)actor).prim_geom == IntPtr.Zero)
74 {
75 PhysicsSitResponse(-1, actor.LocalID, offset, Quaternion.Identity);
76 return;
77 }
78
79 IntPtr geom = ((OdePrim)actor).prim_geom;
80
81 Vector3 geopos = d.GeomGetPositionOMV(geom);
82 Quaternion geomOri = d.GeomGetQuaternionOMV(geom);
83
84// Vector3 geopos = actor.Position;
85// Quaternion geomOri = actor.Orientation;
86
87 Quaternion geomInvOri = Quaternion.Conjugate(geomOri);
88
89 Quaternion ori = Quaternion.Identity;
90
91 Vector3 rayDir = geopos + offset - avCameraPosition;
92
93 float raylen = rayDir.Length();
94 if (raylen < 0.001f)
95 {
96 PhysicsSitResponse(-1, actor.LocalID, offset, Quaternion.Identity);
97 return;
98 }
99 float t = 1 / raylen;
100 rayDir.X *= t;
101 rayDir.Y *= t;
102 rayDir.Z *= t;
103
104 raylen += 30f; // focal point may be far
105 List<ContactResult> rayResults;
106
107 rayResults = m_scene.RaycastActor(actor, avCameraPosition, rayDir, raylen, 1, RaySitFlags);
108 if (rayResults.Count == 0)
109 {
110/* if this fundamental ray failed, then just fail so user can try another spot and not be sitted far on a big prim
111 d.AABB aabb;
112 d.GeomGetAABB(geom, out aabb);
113 offset = new Vector3(avOffset.X, 0, aabb.MaxZ + avOffset.Z - geopos.Z);
114 ori = geomInvOri;
115 offset *= geomInvOri;
116 PhysicsSitResponse(1, actor.LocalID, offset, ori);
117*/
118 PhysicsSitResponse(0, actor.LocalID, offset, ori);
119 return;
120 }
121
122 int status = 1;
123
124 offset = rayResults[0].Pos - geopos;
125
126 d.GeomClassID geoclass = d.GeomGetClass(geom);
127
128 if (geoclass == d.GeomClassID.SphereClass)
129 {
130 float r = d.GeomSphereGetRadius(geom);
131
132 offset.Normalize();
133 offset *= r;
134
135 RotAroundZ(offset.X, offset.Y, ref ori);
136
137 if (r < 0.4f)
138 {
139 offset = new Vector3(0, 0, r);
140 }
141 else
142 {
143 if (offset.Z < 0.4f)
144 {
145 t = offset.Z;
146 float rsq = r * r;
147
148 t = 1.0f / (rsq - t * t);
149 offset.X *= t;
150 offset.Y *= t;
151 offset.Z = 0.4f;
152 t = rsq - 0.16f;
153 offset.X *= t;
154 offset.Y *= t;
155 }
156 else if (r > 0.8f && offset.Z > 0.8f * r)
157 {
158 status = 3;
159 avOffset.X = -avOffset.X;
160 avOffset.Z *= 1.6f;
161 }
162 }
163
164 offset += avOffset * ori;
165
166 ori = geomInvOri * ori;
167 offset *= geomInvOri;
168
169 PhysicsSitResponse(status, actor.LocalID, offset, ori);
170 return;
171 }
172
173 Vector3 norm = rayResults[0].Normal;
174
175 if (norm.Z < -0.4f)
176 {
177 PhysicsSitResponse(0, actor.LocalID, offset, Quaternion.Identity);
178 return;
179 }
180
181
182 float SitNormX = -rayDir.X;
183 float SitNormY = -rayDir.Y;
184
185 Vector3 pivot = geopos + offset;
186
187 float edgeNormalX = norm.X;
188 float edgeNormalY = norm.Y;
189 float edgeDirX = -rayDir.X;
190 float edgeDirY = -rayDir.Y;
191 Vector3 edgePos = rayResults[0].Pos;
192 float edgeDist = float.MaxValue;
193
194 bool foundEdge = false;
195
196 if (norm.Z < 0.5f)
197 {
198 float rayDist = 4.0f;
199
200 for (int i = 0; i < 6; i++)
201 {
202 pivot.X -= 0.01f * norm.X;
203 pivot.Y -= 0.01f * norm.Y;
204 pivot.Z -= 0.01f * norm.Z;
205
206 rayDir.X = -norm.X * norm.Z;
207 rayDir.Y = -norm.Y * norm.Z;
208 rayDir.Z = 1.0f - norm.Z * norm.Z;
209 rayDir.Normalize();
210
211 rayResults = m_scene.RaycastActor(actor, pivot, rayDir, rayDist, 1, RayFilterFlags.AllPrims);
212 if (rayResults.Count == 0)
213 break;
214
215 if (Math.Abs(rayResults[0].Normal.Z) < 0.7f)
216 {
217 rayDist -= rayResults[0].Depth;
218 if (rayDist < 0f)
219 break;
220
221 pivot = rayResults[0].Pos;
222 norm = rayResults[0].Normal;
223 edgeNormalX = norm.X;
224 edgeNormalY = norm.Y;
225 edgeDirX = -rayDir.X;
226 edgeDirY = -rayDir.Y;
227 }
228 else
229 {
230 foundEdge = true;
231 edgePos = rayResults[0].Pos;
232 break;
233 }
234 }
235
236 if (!foundEdge)
237 {
238 PhysicsSitResponse(0, actor.LocalID, offset, ori);
239 return;
240 }
241 avOffset.X *= 0.5f;
242 }
243
244 else if (norm.Z > 0.866f)
245 {
246 float toCamBaseX = avCameraPosition.X - pivot.X;
247 float toCamBaseY = avCameraPosition.Y - pivot.Y;
248 float toCamX = toCamBaseX;
249 float toCamY = toCamBaseY;
250
251 for (int j = 0; j < 4; j++)
252 {
253 float rayDist = 1.0f;
254 float curEdgeDist = 0.0f;
255
256 for (int i = 0; i < 3; i++)
257 {
258 pivot.Z -= 0.01f;
259 rayDir.X = toCamX;
260 rayDir.Y = toCamY;
261 rayDir.Z = (-toCamX * norm.X - toCamY * norm.Y) / norm.Z;
262 rayDir.Normalize();
263
264 rayResults = m_scene.RaycastActor(actor, pivot, rayDir, rayDist, 1, RayFilterFlags.AllPrims);
265 if (rayResults.Count == 0)
266 break;
267
268 curEdgeDist += rayResults[0].Depth;
269
270 if (rayResults[0].Normal.Z > 0.5f)
271 {
272 rayDist -= rayResults[0].Depth;
273 if (rayDist < 0f)
274 break;
275
276 pivot = rayResults[0].Pos;
277 norm = rayResults[0].Normal;
278 }
279 else
280 {
281 foundEdge = true;
282 if (curEdgeDist < edgeDist)
283 {
284 edgeDist = curEdgeDist;
285 edgeNormalX = rayResults[0].Normal.X;
286 edgeNormalY = rayResults[0].Normal.Y;
287 edgeDirX = rayDir.X;
288 edgeDirY = rayDir.Y;
289 edgePos = rayResults[0].Pos;
290 }
291 break;
292 }
293 }
294 if (foundEdge && edgeDist < 0.2f)
295 break;
296
297 pivot = geopos + offset;
298
299 switch (j)
300 {
301 case 0:
302 toCamX = -toCamBaseY;
303 toCamY = toCamBaseX;
304 break;
305 case 1:
306 toCamX = toCamBaseY;
307 toCamY = -toCamBaseX;
308 break;
309 case 2:
310 toCamX = -toCamBaseX;
311 toCamY = -toCamBaseY;
312 break;
313 default:
314 break;
315 }
316 }
317
318 if (!foundEdge)
319 {
320 avOffset.X = -avOffset.X;
321 avOffset.Z *= 1.6f;
322
323 RotAroundZ(SitNormX, SitNormY, ref ori);
324
325 offset += avOffset * ori;
326
327 ori = geomInvOri * ori;
328 offset *= geomInvOri;
329
330 PhysicsSitResponse(3, actor.LocalID, offset, ori);
331 return;
332 }
333 avOffset.X *= 0.5f;
334 }
335
336 SitNormX = edgeNormalX;
337 SitNormY = edgeNormalY;
338 if (edgeDirX * SitNormX + edgeDirY * SitNormY < 0)
339 {
340 SitNormX = -SitNormX;
341 SitNormY = -SitNormY;
342 }
343
344 RotAroundZ(SitNormX, SitNormY, ref ori);
345
346 offset = edgePos + avOffset * ori;
347 offset -= geopos;
348
349 ori = geomInvOri * ori;
350 offset *= geomInvOri;
351
352 PhysicsSitResponse(1, actor.LocalID, offset, ori);
353 return;
354 }
355 }
356}
diff --git a/OpenSim/Region/PhysicsModules/ubOde/Properties/AssemblyInfo.cs b/OpenSim/Region/PhysicsModules/ubOde/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..293454a
--- /dev/null
+++ b/OpenSim/Region/PhysicsModules/ubOde/Properties/AssemblyInfo.cs
@@ -0,0 +1,61 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System.Reflection;
29using System.Runtime.InteropServices;
30using Mono.Addins;
31
32// Information about this assembly is defined by the following
33// attributes.
34//
35// change them to the information which is associated with the assembly
36// you compile.
37
38[assembly : AssemblyTitle("OpenSim.Region.PhysicsModule.ubOde")]
39[assembly : AssemblyDescription("Ubit Variation of ODE")]
40[assembly : AssemblyConfiguration("")]
41[assembly : AssemblyCompany("http://opensimulator.org")]
42[assembly : AssemblyProduct("ubOde")]
43[assembly : AssemblyCopyright("Copyright (c) OpenSimulator.org Developers 2007-2009")]
44[assembly : AssemblyTrademark("")]
45[assembly : AssemblyCulture("")]
46
47// This sets the default COM visibility of types in the assembly to invisible.
48// If you need to expose a type to COM, use [ComVisible(true)] on that type.
49
50[assembly : ComVisible(false)]
51
52// The assembly version has following format :
53//
54// Major.Minor.Build.Revision
55//
56// You can specify all values by your own or you can build default build and revision
57// numbers with the '*' character (the default):
58
59[assembly : AssemblyVersion("0.8.2.*")]
60[assembly: Addin("OpenSim.Region.PhysicsModule.ubOde", OpenSim.VersionInfo.VersionNumber)]
61[assembly: AddinDependency("OpenSim.Region.Framework", OpenSim.VersionInfo.VersionNumber)] \ No newline at end of file
diff --git a/OpenSim/Region/PhysicsModules/ubOdeMeshing/HelperTypes.cs b/OpenSim/Region/PhysicsModules/ubOdeMeshing/HelperTypes.cs
new file mode 100644
index 0000000..ea37301
--- /dev/null
+++ b/OpenSim/Region/PhysicsModules/ubOdeMeshing/HelperTypes.cs
@@ -0,0 +1,340 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Diagnostics;
31using System.Globalization;
32using OpenMetaverse;
33using OpenSim.Region.PhysicsModules.SharedBase;
34using OpenSim.Region.PhysicsModule.ubODEMeshing;
35
36public class Vertex : IComparable<Vertex>
37{
38 Vector3 vector;
39
40 public float X
41 {
42 get { return vector.X; }
43 set { vector.X = value; }
44 }
45
46 public float Y
47 {
48 get { return vector.Y; }
49 set { vector.Y = value; }
50 }
51
52 public float Z
53 {
54 get { return vector.Z; }
55 set { vector.Z = value; }
56 }
57
58 public Vertex(float x, float y, float z)
59 {
60 vector.X = x;
61 vector.Y = y;
62 vector.Z = z;
63 }
64
65 public Vertex normalize()
66 {
67 float tlength = vector.Length();
68 if (tlength != 0f)
69 {
70 float mul = 1.0f / tlength;
71 return new Vertex(vector.X * mul, vector.Y * mul, vector.Z * mul);
72 }
73 else
74 {
75 return new Vertex(0f, 0f, 0f);
76 }
77 }
78
79 public Vertex cross(Vertex v)
80 {
81 return new Vertex(vector.Y * v.Z - vector.Z * v.Y, vector.Z * v.X - vector.X * v.Z, vector.X * v.Y - vector.Y * v.X);
82 }
83
84 // disable warning: mono compiler moans about overloading
85 // operators hiding base operator but should not according to C#
86 // language spec
87#pragma warning disable 0108
88 public static Vertex operator *(Vertex v, Quaternion q)
89 {
90 // From http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/transforms/
91
92 Vertex v2 = new Vertex(0f, 0f, 0f);
93
94 v2.X = q.W * q.W * v.X +
95 2f * q.Y * q.W * v.Z -
96 2f * q.Z * q.W * v.Y +
97 q.X * q.X * v.X +
98 2f * q.Y * q.X * v.Y +
99 2f * q.Z * q.X * v.Z -
100 q.Z * q.Z * v.X -
101 q.Y * q.Y * v.X;
102
103 v2.Y =
104 2f * q.X * q.Y * v.X +
105 q.Y * q.Y * v.Y +
106 2f * q.Z * q.Y * v.Z +
107 2f * q.W * q.Z * v.X -
108 q.Z * q.Z * v.Y +
109 q.W * q.W * v.Y -
110 2f * q.X * q.W * v.Z -
111 q.X * q.X * v.Y;
112
113 v2.Z =
114 2f * q.X * q.Z * v.X +
115 2f * q.Y * q.Z * v.Y +
116 q.Z * q.Z * v.Z -
117 2f * q.W * q.Y * v.X -
118 q.Y * q.Y * v.Z +
119 2f * q.W * q.X * v.Y -
120 q.X * q.X * v.Z +
121 q.W * q.W * v.Z;
122
123 return v2;
124 }
125
126 public static Vertex operator +(Vertex v1, Vertex v2)
127 {
128 return new Vertex(v1.X + v2.X, v1.Y + v2.Y, v1.Z + v2.Z);
129 }
130
131 public static Vertex operator -(Vertex v1, Vertex v2)
132 {
133 return new Vertex(v1.X - v2.X, v1.Y - v2.Y, v1.Z - v2.Z);
134 }
135
136 public static Vertex operator *(Vertex v1, Vertex v2)
137 {
138 return new Vertex(v1.X * v2.X, v1.Y * v2.Y, v1.Z * v2.Z);
139 }
140
141 public static Vertex operator +(Vertex v1, float am)
142 {
143 v1.X += am;
144 v1.Y += am;
145 v1.Z += am;
146 return v1;
147 }
148
149 public static Vertex operator -(Vertex v1, float am)
150 {
151 v1.X -= am;
152 v1.Y -= am;
153 v1.Z -= am;
154 return v1;
155 }
156
157 public static Vertex operator *(Vertex v1, float am)
158 {
159 v1.X *= am;
160 v1.Y *= am;
161 v1.Z *= am;
162 return v1;
163 }
164
165 public static Vertex operator /(Vertex v1, float am)
166 {
167 if (am == 0f)
168 {
169 return new Vertex(0f,0f,0f);
170 }
171 float mul = 1.0f / am;
172 v1.X *= mul;
173 v1.Y *= mul;
174 v1.Z *= mul;
175 return v1;
176 }
177#pragma warning restore 0108
178
179
180 public float dot(Vertex v)
181 {
182 return X * v.X + Y * v.Y + Z * v.Z;
183 }
184
185 public Vertex(Vector3 v)
186 {
187 vector = v;
188 }
189
190 public Vertex Clone()
191 {
192 return new Vertex(X, Y, Z);
193 }
194
195 public static Vertex FromAngle(double angle)
196 {
197 return new Vertex((float) Math.Cos(angle), (float) Math.Sin(angle), 0.0f);
198 }
199
200 public float Length()
201 {
202 return vector.Length();
203 }
204
205 public virtual bool Equals(Vertex v, float tolerance)
206 {
207 Vertex diff = this - v;
208 float d = diff.Length();
209 if (d < tolerance)
210 return true;
211
212 return false;
213 }
214
215
216 public int CompareTo(Vertex other)
217 {
218 if (X < other.X)
219 return -1;
220
221 if (X > other.X)
222 return 1;
223
224 if (Y < other.Y)
225 return -1;
226
227 if (Y > other.Y)
228 return 1;
229
230 if (Z < other.Z)
231 return -1;
232
233 if (Z > other.Z)
234 return 1;
235
236 return 0;
237 }
238
239 public static bool operator >(Vertex me, Vertex other)
240 {
241 return me.CompareTo(other) > 0;
242 }
243
244 public static bool operator <(Vertex me, Vertex other)
245 {
246 return me.CompareTo(other) < 0;
247 }
248
249 public String ToRaw()
250 {
251 // Why this stuff with the number formatter?
252 // Well, the raw format uses the english/US notation of numbers
253 // where the "," separates groups of 1000 while the "." marks the border between 1 and 10E-1.
254 // The german notation uses these characters exactly vice versa!
255 // The Float.ToString() routine is a localized one, giving different results depending on the country
256 // settings your machine works with. Unusable for a machine readable file format :-(
257 NumberFormatInfo nfi = new NumberFormatInfo();
258 nfi.NumberDecimalSeparator = ".";
259 nfi.NumberDecimalDigits = 6;
260
261 String s1 = X.ToString(nfi) + " " + Y.ToString(nfi) + " " + Z.ToString(nfi);
262
263 return s1;
264 }
265}
266
267public class Triangle
268{
269 public Vertex v1;
270 public Vertex v2;
271 public Vertex v3;
272
273 public Triangle(Vertex _v1, Vertex _v2, Vertex _v3)
274 {
275 v1 = _v1;
276 v2 = _v2;
277 v3 = _v3;
278 }
279
280 public Triangle(float _v1x,float _v1y,float _v1z,
281 float _v2x,float _v2y,float _v2z,
282 float _v3x,float _v3y,float _v3z)
283 {
284 v1 = new Vertex(_v1x, _v1y, _v1z);
285 v2 = new Vertex(_v2x, _v2y, _v2z);
286 v3 = new Vertex(_v3x, _v3y, _v3z);
287 }
288
289 public override String ToString()
290 {
291 NumberFormatInfo nfi = new NumberFormatInfo();
292 nfi.CurrencyDecimalDigits = 2;
293 nfi.CurrencyDecimalSeparator = ".";
294
295 String s1 = "<" + v1.X.ToString(nfi) + "," + v1.Y.ToString(nfi) + "," + v1.Z.ToString(nfi) + ">";
296 String s2 = "<" + v2.X.ToString(nfi) + "," + v2.Y.ToString(nfi) + "," + v2.Z.ToString(nfi) + ">";
297 String s3 = "<" + v3.X.ToString(nfi) + "," + v3.Y.ToString(nfi) + "," + v3.Z.ToString(nfi) + ">";
298
299 return s1 + ";" + s2 + ";" + s3;
300 }
301
302 public Vector3 getNormal()
303 {
304 // Vertices
305
306 // Vectors for edges
307 Vector3 e1;
308 Vector3 e2;
309
310 e1 = new Vector3(v1.X - v2.X, v1.Y - v2.Y, v1.Z - v2.Z);
311 e2 = new Vector3(v1.X - v3.X, v1.Y - v3.Y, v1.Z - v3.Z);
312
313 // Cross product for normal
314 Vector3 n = Vector3.Cross(e1, e2);
315
316 // Length
317 float l = n.Length();
318
319 // Normalized "normal"
320 n = n/l;
321
322 return n;
323 }
324
325 public void invertNormal()
326 {
327 Vertex vt;
328 vt = v1;
329 v1 = v2;
330 v2 = vt;
331 }
332
333 // Dumps a triangle in the "raw faces" format, blender can import. This is for visualisation and
334 // debugging purposes
335 public String ToStringRaw()
336 {
337 String output = v1.ToRaw() + " " + v2.ToRaw() + " " + v3.ToRaw();
338 return output;
339 }
340}
diff --git a/OpenSim/Region/PhysicsModules/ubOdeMeshing/Mesh.cs b/OpenSim/Region/PhysicsModules/ubOdeMeshing/Mesh.cs
new file mode 100644
index 0000000..97501a4
--- /dev/null
+++ b/OpenSim/Region/PhysicsModules/ubOdeMeshing/Mesh.cs
@@ -0,0 +1,633 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.IO;
31using System.Runtime.InteropServices;
32using OpenSim.Region.PhysicsModules.SharedBase;
33using PrimMesher;
34using OpenMetaverse;
35using System.Runtime.Serialization;
36using System.Runtime.Serialization.Formatters.Binary;
37
38namespace OpenSim.Region.PhysicsModule.ubODEMeshing
39{
40 public class MeshBuildingData
41 {
42 public Dictionary<Vertex, int> m_vertices;
43 public List<Triangle> m_triangles;
44 public float m_obbXmin;
45 public float m_obbXmax;
46 public float m_obbYmin;
47 public float m_obbYmax;
48 public float m_obbZmin;
49 public float m_obbZmax;
50 public Vector3 m_centroid;
51 public int m_centroidDiv;
52 }
53
54 [Serializable()]
55 public class Mesh : IMesh
56 {
57 float[] vertices;
58 int[] indexes;
59 Vector3 m_obb;
60 Vector3 m_obboffset;
61 [NonSerialized()]
62 MeshBuildingData m_bdata;
63 [NonSerialized()]
64 GCHandle vhandler;
65 [NonSerialized()]
66 GCHandle ihandler;
67 [NonSerialized()]
68 IntPtr m_verticesPtr = IntPtr.Zero;
69 [NonSerialized()]
70 IntPtr m_indicesPtr = IntPtr.Zero;
71 [NonSerialized()]
72 int m_vertexCount = 0;
73 [NonSerialized()]
74 int m_indexCount = 0;
75
76 public int RefCount { get; set; }
77 public AMeshKey Key { get; set; }
78
79 private class vertexcomp : IEqualityComparer<Vertex>
80 {
81 public bool Equals(Vertex v1, Vertex v2)
82 {
83 if (v1.X == v2.X && v1.Y == v2.Y && v1.Z == v2.Z)
84 return true;
85 else
86 return false;
87 }
88 public int GetHashCode(Vertex v)
89 {
90 int a = v.X.GetHashCode();
91 int b = v.Y.GetHashCode();
92 int c = v.Z.GetHashCode();
93 return (a << 16) ^ (b << 8) ^ c;
94 }
95 }
96
97 public Mesh()
98 {
99 vertexcomp vcomp = new vertexcomp();
100
101 m_bdata = new MeshBuildingData();
102 m_bdata.m_vertices = new Dictionary<Vertex, int>(vcomp);
103 m_bdata.m_triangles = new List<Triangle>();
104 m_bdata.m_centroid = Vector3.Zero;
105 m_bdata.m_centroidDiv = 0;
106 m_bdata.m_obbXmin = float.MaxValue;
107 m_bdata.m_obbXmax = float.MinValue;
108 m_bdata.m_obbYmin = float.MaxValue;
109 m_bdata.m_obbYmax = float.MinValue;
110 m_bdata.m_obbZmin = float.MaxValue;
111 m_bdata.m_obbZmax = float.MinValue;
112 m_obb = new Vector3(0.5f, 0.5f, 0.5f);
113 m_obboffset = Vector3.Zero;
114 }
115
116
117 public Mesh Scale(Vector3 scale)
118 {
119 if (m_verticesPtr == null || m_indicesPtr == null)
120 return null;
121
122 Mesh result = new Mesh();
123
124 float x = scale.X;
125 float y = scale.Y;
126 float z = scale.Z;
127
128 float tmp;
129 tmp = m_obb.X * x;
130 if(tmp < 0.0005f)
131 tmp = 0.0005f;
132 result.m_obb.X = tmp;
133
134 tmp = m_obb.Y * y;
135 if(tmp < 0.0005f)
136 tmp = 0.0005f;
137 result.m_obb.Y = tmp;
138
139 tmp = m_obb.Z * z;
140 if(tmp < 0.0005f)
141 tmp = 0.0005f;
142 result.m_obb.Z = tmp;
143
144 result.m_obboffset.X = m_obboffset.X * x;
145 result.m_obboffset.Y = m_obboffset.Y * y;
146 result.m_obboffset.Z = m_obboffset.Z * z;
147
148 result.vertices = new float[vertices.Length];
149 int j = 0;
150 for (int i = 0; i < m_vertexCount; i++)
151 {
152 result.vertices[j] = vertices[j] * x;
153 j++;
154 result.vertices[j] = vertices[j] * y;
155 j++;
156 result.vertices[j] = vertices[j] * z;
157 j++;
158 }
159
160 result.indexes = new int[indexes.Length];
161 indexes.CopyTo(result.indexes,0);
162
163 result.pinMemory();
164
165 return result;
166 }
167
168 public Mesh Clone()
169 {
170 Mesh result = new Mesh();
171
172 if (m_bdata != null)
173 {
174 result.m_bdata = new MeshBuildingData();
175 foreach (Triangle t in m_bdata.m_triangles)
176 {
177 result.Add(new Triangle(t.v1.Clone(), t.v2.Clone(), t.v3.Clone()));
178 }
179 result.m_bdata.m_centroid = m_bdata.m_centroid;
180 result.m_bdata.m_centroidDiv = m_bdata.m_centroidDiv;
181 result.m_bdata.m_obbXmin = m_bdata.m_obbXmin;
182 result.m_bdata.m_obbXmax = m_bdata.m_obbXmax;
183 result.m_bdata.m_obbYmin = m_bdata.m_obbYmin;
184 result.m_bdata.m_obbYmax = m_bdata.m_obbYmax;
185 result.m_bdata.m_obbZmin = m_bdata.m_obbZmin;
186 result.m_bdata.m_obbZmax = m_bdata.m_obbZmax;
187 }
188 result.m_obb = m_obb;
189 result.m_obboffset = m_obboffset;
190 return result;
191 }
192
193 public void addVertexLStats(Vertex v)
194 {
195 float x = v.X;
196 float y = v.Y;
197 float z = v.Z;
198
199 m_bdata.m_centroid.X += x;
200 m_bdata.m_centroid.Y += y;
201 m_bdata.m_centroid.Z += z;
202 m_bdata.m_centroidDiv++;
203
204 if (x > m_bdata.m_obbXmax)
205 m_bdata.m_obbXmax = x;
206 if (x < m_bdata.m_obbXmin)
207 m_bdata.m_obbXmin = x;
208
209 if (y > m_bdata.m_obbYmax)
210 m_bdata.m_obbYmax = y;
211 if (y < m_bdata.m_obbYmin)
212 m_bdata.m_obbYmin = y;
213
214 if (z > m_bdata.m_obbZmax)
215 m_bdata.m_obbZmax = z;
216 if (z < m_bdata.m_obbZmin)
217 m_bdata.m_obbZmin = z;
218
219 }
220
221 public void Add(Triangle triangle)
222 {
223 if (m_indicesPtr != IntPtr.Zero || m_verticesPtr != IntPtr.Zero)
224 throw new NotSupportedException("Attempt to Add to a pinned Mesh");
225
226
227 triangle.v1.X = (float)Math.Round(triangle.v1.X, 6);
228 triangle.v1.Y = (float)Math.Round(triangle.v1.Y, 6);
229 triangle.v1.Z = (float)Math.Round(triangle.v1.Z, 6);
230 triangle.v2.X = (float)Math.Round(triangle.v2.X, 6);
231 triangle.v2.Y = (float)Math.Round(triangle.v2.Y, 6);
232 triangle.v2.Z = (float)Math.Round(triangle.v2.Z, 6);
233 triangle.v3.X = (float)Math.Round(triangle.v3.X, 6);
234 triangle.v3.Y = (float)Math.Round(triangle.v3.Y, 6);
235 triangle.v3.Z = (float)Math.Round(triangle.v3.Z, 6);
236
237 if ((triangle.v1.X == triangle.v2.X && triangle.v1.Y == triangle.v2.Y && triangle.v1.Z == triangle.v2.Z)
238 || (triangle.v1.X == triangle.v3.X && triangle.v1.Y == triangle.v3.Y && triangle.v1.Z == triangle.v3.Z)
239 || (triangle.v2.X == triangle.v3.X && triangle.v2.Y == triangle.v3.Y && triangle.v2.Z == triangle.v3.Z)
240 )
241 {
242 return;
243 }
244
245 if (m_bdata.m_vertices.Count == 0)
246 {
247 m_bdata.m_centroidDiv = 0;
248 m_bdata.m_centroid = Vector3.Zero;
249 }
250
251 if (!m_bdata.m_vertices.ContainsKey(triangle.v1))
252 {
253 m_bdata.m_vertices[triangle.v1] = m_bdata.m_vertices.Count;
254 addVertexLStats(triangle.v1);
255 }
256 if (!m_bdata.m_vertices.ContainsKey(triangle.v2))
257 {
258 m_bdata.m_vertices[triangle.v2] = m_bdata.m_vertices.Count;
259 addVertexLStats(triangle.v2);
260 }
261 if (!m_bdata.m_vertices.ContainsKey(triangle.v3))
262 {
263 m_bdata.m_vertices[triangle.v3] = m_bdata.m_vertices.Count;
264 addVertexLStats(triangle.v3);
265 }
266 m_bdata.m_triangles.Add(triangle);
267 }
268
269 public Vector3 GetCentroid()
270 {
271 return m_obboffset;
272
273 }
274
275 public Vector3 GetOBB()
276 {
277 return m_obb;
278/*
279 float x, y, z;
280 if (m_bdata.m_centroidDiv > 0)
281 {
282 x = (m_bdata.m_obbXmax - m_bdata.m_obbXmin) * 0.5f;
283 y = (m_bdata.m_obbYmax - m_bdata.m_obbYmin) * 0.5f;
284 z = (m_bdata.m_obbZmax - m_bdata.m_obbZmin) * 0.5f;
285 }
286 else // ??
287 {
288 x = 0.5f;
289 y = 0.5f;
290 z = 0.5f;
291 }
292 return new Vector3(x, y, z);
293*/
294 }
295
296 public int numberVertices()
297 {
298 return m_bdata.m_vertices.Count;
299 }
300
301 public int numberTriangles()
302 {
303 return m_bdata.m_triangles.Count;
304 }
305
306 public List<Vector3> getVertexList()
307 {
308 List<Vector3> result = new List<Vector3>();
309 foreach (Vertex v in m_bdata.m_vertices.Keys)
310 {
311 result.Add(new Vector3(v.X, v.Y, v.Z));
312 }
313 return result;
314 }
315
316 public float[] getVertexListAsFloat()
317 {
318 if (m_bdata.m_vertices == null)
319 throw new NotSupportedException();
320 float[] result = new float[m_bdata.m_vertices.Count * 3];
321 foreach (KeyValuePair<Vertex, int> kvp in m_bdata.m_vertices)
322 {
323 Vertex v = kvp.Key;
324 int i = kvp.Value;
325 result[3 * i + 0] = v.X;
326 result[3 * i + 1] = v.Y;
327 result[3 * i + 2] = v.Z;
328 }
329 return result;
330 }
331
332 public float[] getVertexListAsFloatLocked()
333 {
334 return null;
335 }
336
337 public void getVertexListAsPtrToFloatArray(out IntPtr _vertices, out int vertexStride, out int vertexCount)
338 {
339 // A vertex is 3 floats
340 vertexStride = 3 * sizeof(float);
341
342 // If there isn't an unmanaged array allocated yet, do it now
343 if (m_verticesPtr == IntPtr.Zero && m_bdata != null)
344 {
345 vertices = getVertexListAsFloat();
346 // Each vertex is 3 elements (floats)
347 m_vertexCount = vertices.Length / 3;
348 vhandler = GCHandle.Alloc(vertices, GCHandleType.Pinned);
349 m_verticesPtr = vhandler.AddrOfPinnedObject();
350 GC.AddMemoryPressure(Buffer.ByteLength(vertices));
351 }
352 _vertices = m_verticesPtr;
353 vertexCount = m_vertexCount;
354 }
355
356 public int[] getIndexListAsInt()
357 {
358 if (m_bdata.m_triangles == null)
359 throw new NotSupportedException();
360 int[] result = new int[m_bdata.m_triangles.Count * 3];
361 for (int i = 0; i < m_bdata.m_triangles.Count; i++)
362 {
363 Triangle t = m_bdata.m_triangles[i];
364 result[3 * i + 0] = m_bdata.m_vertices[t.v1];
365 result[3 * i + 1] = m_bdata.m_vertices[t.v2];
366 result[3 * i + 2] = m_bdata.m_vertices[t.v3];
367 }
368 return result;
369 }
370
371 /// <summary>
372 /// creates a list of index values that defines triangle faces. THIS METHOD FREES ALL NON-PINNED MESH DATA
373 /// </summary>
374 /// <returns></returns>
375 public int[] getIndexListAsIntLocked()
376 {
377 return null;
378 }
379
380 public void getIndexListAsPtrToIntArray(out IntPtr indices, out int triStride, out int indexCount)
381 {
382 // If there isn't an unmanaged array allocated yet, do it now
383 if (m_indicesPtr == IntPtr.Zero && m_bdata != null)
384 {
385 indexes = getIndexListAsInt();
386 m_indexCount = indexes.Length;
387 ihandler = GCHandle.Alloc(indexes, GCHandleType.Pinned);
388 m_indicesPtr = ihandler.AddrOfPinnedObject();
389 GC.AddMemoryPressure(Buffer.ByteLength(indexes));
390 }
391 // A triangle is 3 ints (indices)
392 triStride = 3 * sizeof(int);
393 indices = m_indicesPtr;
394 indexCount = m_indexCount;
395 }
396
397 public void releasePinned()
398 {
399 if (m_verticesPtr != IntPtr.Zero)
400 {
401 vhandler.Free();
402 vertices = null;
403 m_verticesPtr = IntPtr.Zero;
404 }
405 if (m_indicesPtr != IntPtr.Zero)
406 {
407 ihandler.Free();
408 indexes = null;
409 m_indicesPtr = IntPtr.Zero;
410 }
411 }
412
413 /// <summary>
414 /// frees up the source mesh data to minimize memory - call this method after calling get*Locked() functions
415 /// </summary>
416 public void releaseSourceMeshData()
417 {
418 if (m_bdata != null)
419 {
420 m_bdata.m_triangles = null;
421 m_bdata.m_vertices = null;
422 }
423 }
424
425 public void releaseBuildingMeshData()
426 {
427 if (m_bdata != null)
428 {
429 m_bdata.m_triangles = null;
430 m_bdata.m_vertices = null;
431 m_bdata = null;
432 }
433 }
434
435 public void Append(IMesh newMesh)
436 {
437 if (m_indicesPtr != IntPtr.Zero || m_verticesPtr != IntPtr.Zero)
438 throw new NotSupportedException("Attempt to Append to a pinned Mesh");
439
440 if (!(newMesh is Mesh))
441 return;
442
443 foreach (Triangle t in ((Mesh)newMesh).m_bdata.m_triangles)
444 Add(t);
445 }
446
447 // Do a linear transformation of mesh.
448 public void TransformLinear(float[,] matrix, float[] offset)
449 {
450 if (m_indicesPtr != IntPtr.Zero || m_verticesPtr != IntPtr.Zero)
451 throw new NotSupportedException("Attempt to TransformLinear a pinned Mesh");
452
453 foreach (Vertex v in m_bdata.m_vertices.Keys)
454 {
455 if (v == null)
456 continue;
457 float x, y, z;
458 x = v.X*matrix[0, 0] + v.Y*matrix[1, 0] + v.Z*matrix[2, 0];
459 y = v.X*matrix[0, 1] + v.Y*matrix[1, 1] + v.Z*matrix[2, 1];
460 z = v.X*matrix[0, 2] + v.Y*matrix[1, 2] + v.Z*matrix[2, 2];
461 v.X = x + offset[0];
462 v.Y = y + offset[1];
463 v.Z = z + offset[2];
464 }
465 }
466
467 public void DumpRaw(String path, String name, String title)
468 {
469 if (path == null)
470 return;
471 if (m_bdata == null)
472 return;
473 String fileName = name + "_" + title + ".raw";
474 String completePath = System.IO.Path.Combine(path, fileName);
475 StreamWriter sw = new StreamWriter(completePath);
476 foreach (Triangle t in m_bdata.m_triangles)
477 {
478 String s = t.ToStringRaw();
479 sw.WriteLine(s);
480 }
481 sw.Close();
482 }
483
484 public void TrimExcess()
485 {
486 m_bdata.m_triangles.TrimExcess();
487 }
488
489 public void pinMemory()
490 {
491 m_vertexCount = vertices.Length / 3;
492 vhandler = GCHandle.Alloc(vertices, GCHandleType.Pinned);
493 m_verticesPtr = vhandler.AddrOfPinnedObject();
494 GC.AddMemoryPressure(Buffer.ByteLength(vertices));
495
496 m_indexCount = indexes.Length;
497 ihandler = GCHandle.Alloc(indexes, GCHandleType.Pinned);
498 m_indicesPtr = ihandler.AddrOfPinnedObject();
499 GC.AddMemoryPressure(Buffer.ByteLength(indexes));
500 }
501
502 public void PrepForOde()
503 {
504 // If there isn't an unmanaged array allocated yet, do it now
505 if (m_verticesPtr == IntPtr.Zero)
506 vertices = getVertexListAsFloat();
507
508 // If there isn't an unmanaged array allocated yet, do it now
509 if (m_indicesPtr == IntPtr.Zero)
510 indexes = getIndexListAsInt();
511
512 pinMemory();
513
514 float x, y, z;
515
516 if (m_bdata.m_centroidDiv > 0)
517 {
518 m_obboffset = new Vector3(m_bdata.m_centroid.X / m_bdata.m_centroidDiv, m_bdata.m_centroid.Y / m_bdata.m_centroidDiv, m_bdata.m_centroid.Z / m_bdata.m_centroidDiv);
519 x = (m_bdata.m_obbXmax - m_bdata.m_obbXmin) * 0.5f;
520 if(x < 0.0005f)
521 x = 0.0005f;
522 y = (m_bdata.m_obbYmax - m_bdata.m_obbYmin) * 0.5f;
523 if(y < 0.0005f)
524 y = 0.0005f;
525 z = (m_bdata.m_obbZmax - m_bdata.m_obbZmin) * 0.5f;
526 if(z < 0.0005f)
527 z = 0.0005f;
528 }
529
530 else
531 {
532 m_obboffset = Vector3.Zero;
533 x = 0.5f;
534 y = 0.5f;
535 z = 0.5f;
536 }
537
538 m_obb = new Vector3(x, y, z);
539
540 releaseBuildingMeshData();
541 }
542 public bool ToStream(Stream st)
543 {
544 if (m_indicesPtr == IntPtr.Zero || m_verticesPtr == IntPtr.Zero)
545 return false;
546
547 BinaryWriter bw = new BinaryWriter(st);
548 bool ok = true;
549
550 try
551 {
552
553 bw.Write(m_vertexCount);
554 bw.Write(m_indexCount);
555
556 for (int i = 0; i < 3 * m_vertexCount; i++)
557 bw.Write(vertices[i]);
558 for (int i = 0; i < m_indexCount; i++)
559 bw.Write(indexes[i]);
560 bw.Write(m_obb.X);
561 bw.Write(m_obb.Y);
562 bw.Write(m_obb.Z);
563 bw.Write(m_obboffset.X);
564 bw.Write(m_obboffset.Y);
565 bw.Write(m_obboffset.Z);
566 }
567 catch
568 {
569 ok = false;
570 }
571
572 if (bw != null)
573 {
574 bw.Flush();
575 bw.Close();
576 }
577
578 return ok;
579 }
580
581 public static Mesh FromStream(Stream st, AMeshKey key)
582 {
583 Mesh mesh = new Mesh();
584 mesh.releaseBuildingMeshData();
585
586 BinaryReader br = new BinaryReader(st);
587
588 bool ok = true;
589 try
590 {
591 mesh.m_vertexCount = br.ReadInt32();
592 mesh.m_indexCount = br.ReadInt32();
593
594 int n = 3 * mesh.m_vertexCount;
595 mesh.vertices = new float[n];
596 for (int i = 0; i < n; i++)
597 mesh.vertices[i] = br.ReadSingle();
598
599 mesh.indexes = new int[mesh.m_indexCount];
600 for (int i = 0; i < mesh.m_indexCount; i++)
601 mesh.indexes[i] = br.ReadInt32();
602
603 mesh.m_obb.X = br.ReadSingle();
604 mesh.m_obb.Y = br.ReadSingle();
605 mesh.m_obb.Z = br.ReadSingle();
606
607 mesh.m_obboffset.X = br.ReadSingle();
608 mesh.m_obboffset.Y = br.ReadSingle();
609 mesh.m_obboffset.Z = br.ReadSingle();
610 }
611 catch
612 {
613 ok = false;
614 }
615
616 br.Close();
617
618 if (ok)
619 {
620 mesh.pinMemory();
621
622 mesh.Key = key;
623 mesh.RefCount = 1;
624
625 return mesh;
626 }
627
628 mesh.vertices = null;
629 mesh.indexes = null;
630 return null;
631 }
632 }
633}
diff --git a/OpenSim/Region/PhysicsModules/ubOdeMeshing/Meshmerizer.cs b/OpenSim/Region/PhysicsModules/ubOdeMeshing/Meshmerizer.cs
new file mode 100644
index 0000000..a6e303a
--- /dev/null
+++ b/OpenSim/Region/PhysicsModules/ubOdeMeshing/Meshmerizer.cs
@@ -0,0 +1,1465 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27//#define SPAM
28
29using System;
30using System.Collections.Generic;
31using OpenSim.Framework;
32using OpenSim.Region.Framework.Scenes;
33using OpenSim.Region.Framework.Interfaces;
34using OpenSim.Region.PhysicsModules.SharedBase;
35using OpenSim.Region.PhysicsModules.ConvexDecompositionDotNet;
36using OpenMetaverse;
37using OpenMetaverse.StructuredData;
38using System.Drawing;
39using System.Drawing.Imaging;
40using System.IO.Compression;
41using PrimMesher;
42using log4net;
43using Nini.Config;
44using System.Reflection;
45using System.IO;
46using System.Runtime.Serialization;
47using System.Runtime.Serialization.Formatters.Binary;
48
49using Mono.Addins;
50
51namespace OpenSim.Region.PhysicsModule.ubODEMeshing
52{
53 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "ubODEMeshmerizer")]
54 public class ubMeshmerizer : IMesher, INonSharedRegionModule
55 {
56 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
57
58 // Setting baseDir to a path will enable the dumping of raw files
59 // raw files can be imported by blender so a visual inspection of the results can be done
60
61 private bool m_Enabled = false;
62
63 public object diskLock = new object();
64
65 public bool doMeshFileCache = true;
66
67 public string cachePath = "MeshCache";
68 public TimeSpan CacheExpire;
69 public bool doCacheExpire = true;
70
71// const string baseDir = "rawFiles";
72 private const string baseDir = null; //"rawFiles";
73
74 private bool useMeshiesPhysicsMesh = false;
75
76 private float minSizeForComplexMesh = 0.2f; // prims with all dimensions smaller than this will have a bounding box mesh
77
78 private Dictionary<AMeshKey, Mesh> m_uniqueMeshes = new Dictionary<AMeshKey, Mesh>();
79 private Dictionary<AMeshKey, Mesh> m_uniqueReleasedMeshes = new Dictionary<AMeshKey, Mesh>();
80
81 #region INonSharedRegionModule
82 public string Name
83 {
84 get { return "ubODEMeshmerizer"; }
85 }
86
87 public Type ReplaceableInterface
88 {
89 get { return null; }
90 }
91
92 public void Initialise(IConfigSource config)
93 {
94 IConfig start_config = config.Configs["Startup"];
95
96 string mesher = start_config.GetString("meshing", string.Empty);
97 if (mesher == Name)
98 {
99 float fcache = 48.0f;
100 // float fcache = 0.02f;
101
102 IConfig mesh_config = config.Configs["Mesh"];
103 if (mesh_config != null)
104 {
105 useMeshiesPhysicsMesh = mesh_config.GetBoolean("UseMeshiesPhysicsMesh", useMeshiesPhysicsMesh);
106 if (useMeshiesPhysicsMesh)
107 {
108 doMeshFileCache = mesh_config.GetBoolean("MeshFileCache", doMeshFileCache);
109 cachePath = mesh_config.GetString("MeshFileCachePath", cachePath);
110 fcache = mesh_config.GetFloat("MeshFileCacheExpireHours", fcache);
111 doCacheExpire = mesh_config.GetBoolean("MeshFileCacheDoExpire", doCacheExpire);
112 }
113 else
114 {
115 doMeshFileCache = false;
116 doCacheExpire = false;
117 }
118
119 m_Enabled = true;
120 }
121
122 CacheExpire = TimeSpan.FromHours(fcache);
123
124 }
125 }
126
127 public void Close()
128 {
129 }
130
131 public void AddRegion(Scene scene)
132 {
133 if (!m_Enabled)
134 return;
135
136 scene.RegisterModuleInterface<IMesher>(this);
137 }
138
139 public void RemoveRegion(Scene scene)
140 {
141 if (!m_Enabled)
142 return;
143
144 scene.UnregisterModuleInterface<IMesher>(this);
145 }
146
147 public void RegionLoaded(Scene scene)
148 {
149 if (!m_Enabled)
150 return;
151 }
152
153 #endregion
154
155 /// <summary>
156 /// creates a simple box mesh of the specified size. This mesh is of very low vertex count and may
157 /// be useful as a backup proxy when level of detail is not needed or when more complex meshes fail
158 /// for some reason
159 /// </summary>
160 /// <param name="minX"></param>
161 /// <param name="maxX"></param>
162 /// <param name="minY"></param>
163 /// <param name="maxY"></param>
164 /// <param name="minZ"></param>
165 /// <param name="maxZ"></param>
166 /// <returns></returns>
167 private static Mesh CreateSimpleBoxMesh(float minX, float maxX, float minY, float maxY, float minZ, float maxZ)
168 {
169 Mesh box = new Mesh();
170 List<Vertex> vertices = new List<Vertex>();
171 // bottom
172
173 vertices.Add(new Vertex(minX, maxY, minZ));
174 vertices.Add(new Vertex(maxX, maxY, minZ));
175 vertices.Add(new Vertex(maxX, minY, minZ));
176 vertices.Add(new Vertex(minX, minY, minZ));
177
178 box.Add(new Triangle(vertices[0], vertices[1], vertices[2]));
179 box.Add(new Triangle(vertices[0], vertices[2], vertices[3]));
180
181 // top
182
183 vertices.Add(new Vertex(maxX, maxY, maxZ));
184 vertices.Add(new Vertex(minX, maxY, maxZ));
185 vertices.Add(new Vertex(minX, minY, maxZ));
186 vertices.Add(new Vertex(maxX, minY, maxZ));
187
188 box.Add(new Triangle(vertices[4], vertices[5], vertices[6]));
189 box.Add(new Triangle(vertices[4], vertices[6], vertices[7]));
190
191 // sides
192
193 box.Add(new Triangle(vertices[5], vertices[0], vertices[3]));
194 box.Add(new Triangle(vertices[5], vertices[3], vertices[6]));
195
196 box.Add(new Triangle(vertices[1], vertices[0], vertices[5]));
197 box.Add(new Triangle(vertices[1], vertices[5], vertices[4]));
198
199 box.Add(new Triangle(vertices[7], vertices[1], vertices[4]));
200 box.Add(new Triangle(vertices[7], vertices[2], vertices[1]));
201
202 box.Add(new Triangle(vertices[3], vertices[2], vertices[7]));
203 box.Add(new Triangle(vertices[3], vertices[7], vertices[6]));
204
205 return box;
206 }
207
208 /// <summary>
209 /// Creates a simple bounding box mesh for a complex input mesh
210 /// </summary>
211 /// <param name="meshIn"></param>
212 /// <returns></returns>
213 private static Mesh CreateBoundingBoxMesh(Mesh meshIn)
214 {
215 float minX = float.MaxValue;
216 float maxX = float.MinValue;
217 float minY = float.MaxValue;
218 float maxY = float.MinValue;
219 float minZ = float.MaxValue;
220 float maxZ = float.MinValue;
221
222 foreach (Vector3 v in meshIn.getVertexList())
223 {
224 if (v.X < minX) minX = v.X;
225 if (v.Y < minY) minY = v.Y;
226 if (v.Z < minZ) minZ = v.Z;
227
228 if (v.X > maxX) maxX = v.X;
229 if (v.Y > maxY) maxY = v.Y;
230 if (v.Z > maxZ) maxZ = v.Z;
231 }
232
233 return CreateSimpleBoxMesh(minX, maxX, minY, maxY, minZ, maxZ);
234 }
235
236 private void ReportPrimError(string message, string primName, PrimMesh primMesh)
237 {
238 m_log.Error(message);
239 m_log.Error("\nPrim Name: " + primName);
240 m_log.Error("****** PrimMesh Parameters ******\n" + primMesh.ParamsToDisplayString());
241 }
242
243 /// <summary>
244 /// Add a submesh to an existing list of coords and faces.
245 /// </summary>
246 /// <param name="subMeshData"></param>
247 /// <param name="size">Size of entire object</param>
248 /// <param name="coords"></param>
249 /// <param name="faces"></param>
250 private void AddSubMesh(OSDMap subMeshData, List<Coord> coords, List<Face> faces)
251 {
252 // Console.WriteLine("subMeshMap for {0} - {1}", primName, Util.GetFormattedXml((OSD)subMeshMap));
253
254 // As per http://wiki.secondlife.com/wiki/Mesh/Mesh_Asset_Format, some Mesh Level
255 // of Detail Blocks (maps) contain just a NoGeometry key to signal there is no
256 // geometry for this submesh.
257 if (subMeshData.ContainsKey("NoGeometry") && ((OSDBoolean)subMeshData["NoGeometry"]))
258 return;
259
260 OpenMetaverse.Vector3 posMax;
261 OpenMetaverse.Vector3 posMin;
262 if (subMeshData.ContainsKey("PositionDomain"))
263 {
264 posMax = ((OSDMap)subMeshData["PositionDomain"])["Max"].AsVector3();
265 posMin = ((OSDMap)subMeshData["PositionDomain"])["Min"].AsVector3();
266 }
267 else
268 {
269 posMax = new Vector3(0.5f, 0.5f, 0.5f);
270 posMin = new Vector3(-0.5f, -0.5f, -0.5f);
271 }
272
273 ushort faceIndexOffset = (ushort)coords.Count;
274
275 byte[] posBytes = subMeshData["Position"].AsBinary();
276 for (int i = 0; i < posBytes.Length; i += 6)
277 {
278 ushort uX = Utils.BytesToUInt16(posBytes, i);
279 ushort uY = Utils.BytesToUInt16(posBytes, i + 2);
280 ushort uZ = Utils.BytesToUInt16(posBytes, i + 4);
281
282 Coord c = new Coord(
283 Utils.UInt16ToFloat(uX, posMin.X, posMax.X),
284 Utils.UInt16ToFloat(uY, posMin.Y, posMax.Y),
285 Utils.UInt16ToFloat(uZ, posMin.Z, posMax.Z));
286
287 coords.Add(c);
288 }
289
290 byte[] triangleBytes = subMeshData["TriangleList"].AsBinary();
291 for (int i = 0; i < triangleBytes.Length; i += 6)
292 {
293 ushort v1 = (ushort)(Utils.BytesToUInt16(triangleBytes, i) + faceIndexOffset);
294 ushort v2 = (ushort)(Utils.BytesToUInt16(triangleBytes, i + 2) + faceIndexOffset);
295 ushort v3 = (ushort)(Utils.BytesToUInt16(triangleBytes, i + 4) + faceIndexOffset);
296 Face f = new Face(v1, v2, v3);
297 faces.Add(f);
298 }
299 }
300
301 /// <summary>
302 /// Create a physics mesh from data that comes with the prim. The actual data used depends on the prim type.
303 /// </summary>
304 /// <param name="primName"></param>
305 /// <param name="primShape"></param>
306 /// <param name="size"></param>
307 /// <param name="lod"></param>
308 /// <returns></returns>
309 private Mesh CreateMeshFromPrimMesher(string primName, PrimitiveBaseShape primShape, float lod, bool convex)
310 {
311// m_log.DebugFormat(
312// "[MESH]: Creating physics proxy for {0}, shape {1}",
313// primName, (OpenMetaverse.SculptType)primShape.SculptType);
314
315 List<Coord> coords;
316 List<Face> faces;
317
318 if (primShape.SculptEntry)
319 {
320 if (((OpenMetaverse.SculptType)primShape.SculptType) == SculptType.Mesh)
321 {
322 if (!useMeshiesPhysicsMesh)
323 return null;
324
325 if (!GenerateCoordsAndFacesFromPrimMeshData(primName, primShape, out coords, out faces, convex))
326 return null;
327 }
328 else
329 {
330 if (!GenerateCoordsAndFacesFromPrimSculptData(primName, primShape, lod, out coords, out faces))
331 return null;
332 }
333 }
334 else
335 {
336 if (!GenerateCoordsAndFacesFromPrimShapeData(primName, primShape, lod, out coords, out faces))
337 return null;
338 }
339
340
341 int numCoords = coords.Count;
342 int numFaces = faces.Count;
343
344 Mesh mesh = new Mesh();
345 // Add the corresponding triangles to the mesh
346 for (int i = 0; i < numFaces; i++)
347 {
348 Face f = faces[i];
349 mesh.Add(new Triangle(coords[f.v1].X, coords[f.v1].Y, coords[f.v1].Z,
350 coords[f.v2].X, coords[f.v2].Y, coords[f.v2].Z,
351 coords[f.v3].X, coords[f.v3].Y, coords[f.v3].Z));
352 }
353
354 coords.Clear();
355 faces.Clear();
356
357 if(mesh.numberVertices() < 3 || mesh.numberTriangles() < 1)
358 {
359 m_log.ErrorFormat("[MESH]: invalid degenerated mesh for prim " + primName + " ignored");
360 return null;
361 }
362
363 primShape.SculptData = Utils.EmptyBytes;
364
365 return mesh;
366 }
367
368 /// <summary>
369 /// Generate the co-ords and faces necessary to construct a mesh from the mesh data the accompanies a prim.
370 /// </summary>
371 /// <param name="primName"></param>
372 /// <param name="primShape"></param>
373 /// <param name="size"></param>
374 /// <param name="coords">Coords are added to this list by the method.</param>
375 /// <param name="faces">Faces are added to this list by the method.</param>
376 /// <returns>true if coords and faces were successfully generated, false if not</returns>
377 private bool GenerateCoordsAndFacesFromPrimMeshData(
378 string primName, PrimitiveBaseShape primShape, out List<Coord> coords, out List<Face> faces, bool convex)
379 {
380// m_log.DebugFormat("[MESH]: experimental mesh proxy generation for {0}", primName);
381
382 bool usemesh = false;
383
384 coords = new List<Coord>();
385 faces = new List<Face>();
386 OSD meshOsd = null;
387
388 if (primShape.SculptData.Length <= 0)
389 {
390// m_log.InfoFormat("[MESH]: asset data for {0} is zero length", primName);
391 return false;
392 }
393
394 long start = 0;
395 using (MemoryStream data = new MemoryStream(primShape.SculptData))
396 {
397 try
398 {
399 OSD osd = OSDParser.DeserializeLLSDBinary(data);
400 if (osd is OSDMap)
401 meshOsd = (OSDMap)osd;
402 else
403 {
404 m_log.Warn("[Mesh}: unable to cast mesh asset to OSDMap");
405 return false;
406 }
407 }
408 catch (Exception e)
409 {
410 m_log.Error("[MESH]: Exception deserializing mesh asset header:" + e.ToString());
411 }
412
413 start = data.Position;
414 }
415
416 if (meshOsd is OSDMap)
417 {
418 OSDMap physicsParms = null;
419 OSDMap map = (OSDMap)meshOsd;
420
421 if (!convex)
422 {
423 if (map.ContainsKey("physics_shape"))
424 physicsParms = (OSDMap)map["physics_shape"]; // old asset format
425 else if (map.ContainsKey("physics_mesh"))
426 physicsParms = (OSDMap)map["physics_mesh"]; // new asset format
427
428 if (physicsParms != null)
429 usemesh = true;
430 }
431
432 if(!usemesh && (map.ContainsKey("physics_convex")))
433 physicsParms = (OSDMap)map["physics_convex"];
434
435
436 if (physicsParms == null)
437 {
438 m_log.Warn("[MESH]: unknown mesh type");
439 return false;
440 }
441
442 int physOffset = physicsParms["offset"].AsInteger() + (int)start;
443 int physSize = physicsParms["size"].AsInteger();
444
445 if (physOffset < 0 || physSize == 0)
446 return false; // no mesh data in asset
447
448 OSD decodedMeshOsd = new OSD();
449 byte[] meshBytes = new byte[physSize];
450 System.Buffer.BlockCopy(primShape.SculptData, physOffset, meshBytes, 0, physSize);
451
452 try
453 {
454 using (MemoryStream inMs = new MemoryStream(meshBytes))
455 {
456 using (MemoryStream outMs = new MemoryStream())
457 {
458 using (DeflateStream decompressionStream = new DeflateStream(inMs, CompressionMode.Decompress))
459 {
460 byte[] readBuffer = new byte[2048];
461 inMs.Read(readBuffer, 0, 2); // skip first 2 bytes in header
462 int readLen = 0;
463
464 while ((readLen = decompressionStream.Read(readBuffer, 0, readBuffer.Length)) > 0)
465 outMs.Write(readBuffer, 0, readLen);
466
467 outMs.Flush();
468 outMs.Seek(0, SeekOrigin.Begin);
469
470 byte[] decompressedBuf = outMs.GetBuffer();
471
472 decodedMeshOsd = OSDParser.DeserializeLLSDBinary(decompressedBuf);
473 }
474 }
475 }
476 }
477 catch (Exception e)
478 {
479 m_log.Error("[MESH]: exception decoding physical mesh prim " + primName +" : " + e.ToString());
480 return false;
481 }
482
483 if (usemesh)
484 {
485 OSDArray decodedMeshOsdArray = null;
486
487 // physics_shape is an array of OSDMaps, one for each submesh
488 if (decodedMeshOsd is OSDArray)
489 {
490// Console.WriteLine("decodedMeshOsd for {0} - {1}", primName, Util.GetFormattedXml(decodedMeshOsd));
491
492 decodedMeshOsdArray = (OSDArray)decodedMeshOsd;
493 foreach (OSD subMeshOsd in decodedMeshOsdArray)
494 {
495 if (subMeshOsd is OSDMap)
496 AddSubMesh(subMeshOsd as OSDMap, coords, faces);
497 }
498 }
499 }
500 else
501 {
502 OSDMap cmap = (OSDMap)decodedMeshOsd;
503 if (cmap == null)
504 return false;
505
506 byte[] data;
507
508 List<float3> vs = new List<float3>();
509 PHullResult hullr = new PHullResult();
510 float3 f3;
511 Coord c;
512 Face f;
513 Vector3 range;
514 Vector3 min;
515
516 const float invMaxU16 = 1.0f / 65535f;
517 int t1;
518 int t2;
519 int t3;
520 int i;
521 int nverts;
522 int nindexs;
523
524 if (cmap.ContainsKey("Max"))
525 range = cmap["Max"].AsVector3();
526 else
527 range = new Vector3(0.5f, 0.5f, 0.5f);
528
529 if (cmap.ContainsKey("Min"))
530 min = cmap["Min"].AsVector3();
531 else
532 min = new Vector3(-0.5f, -0.5f, -0.5f);
533
534 range = range - min;
535 range *= invMaxU16;
536
537 if (!convex && cmap.ContainsKey("HullList") && cmap.ContainsKey("Positions"))
538 {
539 List<int> hsizes = new List<int>();
540 int totalpoints = 0;
541 data = cmap["HullList"].AsBinary();
542 for (i = 0; i < data.Length; i++)
543 {
544 t1 = data[i];
545 if (t1 == 0)
546 t1 = 256;
547 totalpoints += t1;
548 hsizes.Add(t1);
549 }
550
551 data = cmap["Positions"].AsBinary();
552 int ptr = 0;
553 int vertsoffset = 0;
554
555 if (totalpoints == data.Length / 6) // 2 bytes per coord, 3 coords per point
556 {
557 foreach (int hullsize in hsizes)
558 {
559 for (i = 0; i < hullsize; i++ )
560 {
561 t1 = data[ptr++];
562 t1 += data[ptr++] << 8;
563 t2 = data[ptr++];
564 t2 += data[ptr++] << 8;
565 t3 = data[ptr++];
566 t3 += data[ptr++] << 8;
567
568 f3 = new float3((t1 * range.X + min.X),
569 (t2 * range.Y + min.Y),
570 (t3 * range.Z + min.Z));
571 vs.Add(f3);
572 }
573
574 if(hullsize <3)
575 {
576 vs.Clear();
577 continue;
578 }
579
580 if (hullsize <5)
581 {
582 foreach (float3 point in vs)
583 {
584 c.X = point.x;
585 c.Y = point.y;
586 c.Z = point.z;
587 coords.Add(c);
588 }
589 f = new Face(vertsoffset, vertsoffset + 1, vertsoffset + 2);
590 faces.Add(f);
591
592 if (hullsize == 4)
593 {
594 // not sure about orientation..
595 f = new Face(vertsoffset, vertsoffset + 2, vertsoffset + 3);
596 faces.Add(f);
597 f = new Face(vertsoffset, vertsoffset + 3, vertsoffset + 1);
598 faces.Add(f);
599 f = new Face(vertsoffset + 3, vertsoffset + 2, vertsoffset + 1);
600 faces.Add(f);
601 }
602 vertsoffset += vs.Count;
603 vs.Clear();
604 continue;
605 }
606
607 if (!HullUtils.ComputeHull(vs, ref hullr, 0, 0.0f))
608 {
609 vs.Clear();
610 continue;
611 }
612
613 nverts = hullr.Vertices.Count;
614 nindexs = hullr.Indices.Count;
615
616 if (nindexs % 3 != 0)
617 {
618 vs.Clear();
619 continue;
620 }
621
622 for (i = 0; i < nverts; i++)
623 {
624 c.X = hullr.Vertices[i].x;
625 c.Y = hullr.Vertices[i].y;
626 c.Z = hullr.Vertices[i].z;
627 coords.Add(c);
628 }
629
630 for (i = 0; i < nindexs; i += 3)
631 {
632 t1 = hullr.Indices[i];
633 if (t1 > nverts)
634 break;
635 t2 = hullr.Indices[i + 1];
636 if (t2 > nverts)
637 break;
638 t3 = hullr.Indices[i + 2];
639 if (t3 > nverts)
640 break;
641 f = new Face(vertsoffset + t1, vertsoffset + t2, vertsoffset + t3);
642 faces.Add(f);
643 }
644 vertsoffset += nverts;
645 vs.Clear();
646 }
647 }
648 if (coords.Count > 0 && faces.Count > 0)
649 return true;
650 }
651
652 vs.Clear();
653
654 if (cmap.ContainsKey("BoundingVerts"))
655 {
656 data = cmap["BoundingVerts"].AsBinary();
657
658 for (i = 0; i < data.Length; )
659 {
660 t1 = data[i++];
661 t1 += data[i++] << 8;
662 t2 = data[i++];
663 t2 += data[i++] << 8;
664 t3 = data[i++];
665 t3 += data[i++] << 8;
666
667 f3 = new float3((t1 * range.X + min.X),
668 (t2 * range.Y + min.Y),
669 (t3 * range.Z + min.Z));
670 vs.Add(f3);
671 }
672
673 if (vs.Count < 3)
674 {
675 vs.Clear();
676 return false;
677 }
678
679 if (vs.Count < 5)
680 {
681 foreach (float3 point in vs)
682 {
683 c.X = point.x;
684 c.Y = point.y;
685 c.Z = point.z;
686 coords.Add(c);
687 }
688 f = new Face(0, 1, 2);
689 faces.Add(f);
690
691 if (vs.Count == 4)
692 {
693 f = new Face(0, 2, 3);
694 faces.Add(f);
695 f = new Face(0, 3, 1);
696 faces.Add(f);
697 f = new Face( 3, 2, 1);
698 faces.Add(f);
699 }
700 vs.Clear();
701 return true;
702 }
703
704 if (!HullUtils.ComputeHull(vs, ref hullr, 0, 0.0f))
705 return false;
706
707 nverts = hullr.Vertices.Count;
708 nindexs = hullr.Indices.Count;
709
710 if (nindexs % 3 != 0)
711 return false;
712
713 for (i = 0; i < nverts; i++)
714 {
715 c.X = hullr.Vertices[i].x;
716 c.Y = hullr.Vertices[i].y;
717 c.Z = hullr.Vertices[i].z;
718 coords.Add(c);
719 }
720 for (i = 0; i < nindexs; i += 3)
721 {
722 t1 = hullr.Indices[i];
723 if (t1 > nverts)
724 break;
725 t2 = hullr.Indices[i + 1];
726 if (t2 > nverts)
727 break;
728 t3 = hullr.Indices[i + 2];
729 if (t3 > nverts)
730 break;
731 f = new Face(t1, t2, t3);
732 faces.Add(f);
733 }
734
735 if (coords.Count > 0 && faces.Count > 0)
736 return true;
737 }
738 else
739 return false;
740 }
741 }
742
743 return true;
744 }
745
746 /// <summary>
747 /// Generate the co-ords and faces necessary to construct a mesh from the sculpt data the accompanies a prim.
748 /// </summary>
749 /// <param name="primName"></param>
750 /// <param name="primShape"></param>
751 /// <param name="size"></param>
752 /// <param name="lod"></param>
753 /// <param name="coords">Coords are added to this list by the method.</param>
754 /// <param name="faces">Faces are added to this list by the method.</param>
755 /// <returns>true if coords and faces were successfully generated, false if not</returns>
756 private bool GenerateCoordsAndFacesFromPrimSculptData(
757 string primName, PrimitiveBaseShape primShape, float lod, out List<Coord> coords, out List<Face> faces)
758 {
759 coords = new List<Coord>();
760 faces = new List<Face>();
761 PrimMesher.SculptMesh sculptMesh;
762 Image idata = null;
763
764 if (primShape.SculptData == null || primShape.SculptData.Length == 0)
765 return false;
766
767 try
768 {
769 OpenMetaverse.Imaging.ManagedImage unusedData;
770 OpenMetaverse.Imaging.OpenJPEG.DecodeToImage(primShape.SculptData, out unusedData, out idata);
771
772 unusedData = null;
773
774 if (idata == null)
775 {
776 // In some cases it seems that the decode can return a null bitmap without throwing
777 // an exception
778 m_log.WarnFormat("[PHYSICS]: OpenJPEG decoded sculpt data for {0} to a null bitmap. Ignoring.", primName);
779 return false;
780 }
781 }
782 catch (DllNotFoundException)
783 {
784 m_log.Error("[PHYSICS]: OpenJpeg is not installed correctly on this system. Physics Proxy generation failed. Often times this is because of an old version of GLIBC. You must have version 2.4 or above!");
785 return false;
786 }
787 catch (IndexOutOfRangeException)
788 {
789 m_log.Error("[PHYSICS]: OpenJpeg was unable to decode this. Physics Proxy generation failed");
790 return false;
791 }
792 catch (Exception ex)
793 {
794 m_log.Error("[PHYSICS]: Unable to generate a Sculpty physics proxy. Sculpty texture decode failed: " + ex.Message);
795 return false;
796 }
797
798 PrimMesher.SculptMesh.SculptType sculptType;
799 // remove mirror and invert bits
800 OpenMetaverse.SculptType pbsSculptType = ((OpenMetaverse.SculptType)(primShape.SculptType & 0x3f));
801 switch (pbsSculptType)
802 {
803 case OpenMetaverse.SculptType.Cylinder:
804 sculptType = PrimMesher.SculptMesh.SculptType.cylinder;
805 break;
806 case OpenMetaverse.SculptType.Plane:
807 sculptType = PrimMesher.SculptMesh.SculptType.plane;
808 break;
809 case OpenMetaverse.SculptType.Torus:
810 sculptType = PrimMesher.SculptMesh.SculptType.torus;
811 break;
812 case OpenMetaverse.SculptType.Sphere:
813 sculptType = PrimMesher.SculptMesh.SculptType.sphere;
814 break;
815 default:
816 sculptType = PrimMesher.SculptMesh.SculptType.plane;
817 break;
818 }
819
820 bool mirror = ((primShape.SculptType & 128) != 0);
821 bool invert = ((primShape.SculptType & 64) != 0);
822
823 sculptMesh = new PrimMesher.SculptMesh((Bitmap)idata, sculptType, (int)lod, mirror, invert);
824
825 idata.Dispose();
826
827// sculptMesh.DumpRaw(baseDir, primName, "primMesh");
828
829 coords = sculptMesh.coords;
830 faces = sculptMesh.faces;
831
832 return true;
833 }
834
835 /// <summary>
836 /// Generate the co-ords and faces necessary to construct a mesh from the shape data the accompanies a prim.
837 /// </summary>
838 /// <param name="primName"></param>
839 /// <param name="primShape"></param>
840 /// <param name="size"></param>
841 /// <param name="coords">Coords are added to this list by the method.</param>
842 /// <param name="faces">Faces are added to this list by the method.</param>
843 /// <returns>true if coords and faces were successfully generated, false if not</returns>
844 private bool GenerateCoordsAndFacesFromPrimShapeData(
845 string primName, PrimitiveBaseShape primShape, float lod, out List<Coord> coords, out List<Face> faces)
846 {
847 PrimMesh primMesh;
848 coords = new List<Coord>();
849 faces = new List<Face>();
850
851 float pathShearX = primShape.PathShearX < 128 ? (float)primShape.PathShearX * 0.01f : (float)(primShape.PathShearX - 256) * 0.01f;
852 float pathShearY = primShape.PathShearY < 128 ? (float)primShape.PathShearY * 0.01f : (float)(primShape.PathShearY - 256) * 0.01f;
853 float pathBegin = (float)primShape.PathBegin * 2.0e-5f;
854 float pathEnd = 1.0f - (float)primShape.PathEnd * 2.0e-5f;
855 float pathScaleX = (float)(primShape.PathScaleX - 100) * 0.01f;
856 float pathScaleY = (float)(primShape.PathScaleY - 100) * 0.01f;
857
858 float profileBegin = (float)primShape.ProfileBegin * 2.0e-5f;
859 float profileEnd = 1.0f - (float)primShape.ProfileEnd * 2.0e-5f;
860
861 if (profileBegin < 0.0f)
862 profileBegin = 0.0f;
863
864 if (profileEnd < 0.02f)
865 profileEnd = 0.02f;
866 else if (profileEnd > 1.0f)
867 profileEnd = 1.0f;
868
869 if (profileBegin >= profileEnd)
870 profileBegin = profileEnd - 0.02f;
871
872 float profileHollow = (float)primShape.ProfileHollow * 2.0e-5f;
873 if (profileHollow > 0.95f)
874 profileHollow = 0.95f;
875
876 int sides = 4;
877 LevelOfDetail iLOD = (LevelOfDetail)lod;
878 byte profshape = (byte)(primShape.ProfileCurve & 0x07);
879
880 if (profshape == (byte)ProfileShape.EquilateralTriangle
881 || profshape == (byte)ProfileShape.IsometricTriangle
882 || profshape == (byte)ProfileShape.RightTriangle)
883 sides = 3;
884 else if (profshape == (byte)ProfileShape.Circle)
885 {
886 switch (iLOD)
887 {
888 case LevelOfDetail.High: sides = 24; break;
889 case LevelOfDetail.Medium: sides = 12; break;
890 case LevelOfDetail.Low: sides = 6; break;
891 case LevelOfDetail.VeryLow: sides = 3; break;
892 default: sides = 24; break;
893 }
894 }
895 else if (profshape == (byte)ProfileShape.HalfCircle)
896 { // half circle, prim is a sphere
897 switch (iLOD)
898 {
899 case LevelOfDetail.High: sides = 24; break;
900 case LevelOfDetail.Medium: sides = 12; break;
901 case LevelOfDetail.Low: sides = 6; break;
902 case LevelOfDetail.VeryLow: sides = 3; break;
903 default: sides = 24; break;
904 }
905
906 profileBegin = 0.5f * profileBegin + 0.5f;
907 profileEnd = 0.5f * profileEnd + 0.5f;
908 }
909
910 int hollowSides = sides;
911 if (primShape.HollowShape == HollowShape.Circle)
912 {
913 switch (iLOD)
914 {
915 case LevelOfDetail.High: hollowSides = 24; break;
916 case LevelOfDetail.Medium: hollowSides = 12; break;
917 case LevelOfDetail.Low: hollowSides = 6; break;
918 case LevelOfDetail.VeryLow: hollowSides = 3; break;
919 default: hollowSides = 24; break;
920 }
921 }
922 else if (primShape.HollowShape == HollowShape.Square)
923 hollowSides = 4;
924 else if (primShape.HollowShape == HollowShape.Triangle)
925 {
926 if (profshape == (byte)ProfileShape.HalfCircle)
927 hollowSides = 6;
928 else
929 hollowSides = 3;
930 }
931
932 primMesh = new PrimMesh(sides, profileBegin, profileEnd, profileHollow, hollowSides);
933
934 if (primMesh.errorMessage != null)
935 if (primMesh.errorMessage.Length > 0)
936 m_log.Error("[ERROR] " + primMesh.errorMessage);
937
938 primMesh.topShearX = pathShearX;
939 primMesh.topShearY = pathShearY;
940 primMesh.pathCutBegin = pathBegin;
941 primMesh.pathCutEnd = pathEnd;
942
943 if (primShape.PathCurve == (byte)Extrusion.Straight || primShape.PathCurve == (byte) Extrusion.Flexible)
944 {
945 primMesh.twistBegin = (primShape.PathTwistBegin * 18) / 10;
946 primMesh.twistEnd = (primShape.PathTwist * 18) / 10;
947 primMesh.taperX = pathScaleX;
948 primMesh.taperY = pathScaleY;
949
950#if SPAM
951 m_log.Debug("****** PrimMesh Parameters (Linear) ******\n" + primMesh.ParamsToDisplayString());
952#endif
953 try
954 {
955 primMesh.ExtrudeLinear();
956 }
957 catch (Exception ex)
958 {
959 ReportPrimError("Extrusion failure: exception: " + ex.ToString(), primName, primMesh);
960 return false;
961 }
962 }
963 else
964 {
965 primMesh.holeSizeX = (200 - primShape.PathScaleX) * 0.01f;
966 primMesh.holeSizeY = (200 - primShape.PathScaleY) * 0.01f;
967 primMesh.radius = 0.01f * primShape.PathRadiusOffset;
968 primMesh.revolutions = 1.0f + 0.015f * primShape.PathRevolutions;
969 primMesh.skew = 0.01f * primShape.PathSkew;
970 primMesh.twistBegin = (primShape.PathTwistBegin * 36) / 10;
971 primMesh.twistEnd = (primShape.PathTwist * 36) / 10;
972 primMesh.taperX = primShape.PathTaperX * 0.01f;
973 primMesh.taperY = primShape.PathTaperY * 0.01f;
974
975#if SPAM
976 m_log.Debug("****** PrimMesh Parameters (Circular) ******\n" + primMesh.ParamsToDisplayString());
977#endif
978 try
979 {
980 primMesh.ExtrudeCircular();
981 }
982 catch (Exception ex)
983 {
984 ReportPrimError("Extrusion failure: exception: " + ex.ToString(), primName, primMesh);
985 return false;
986 }
987 }
988
989// primMesh.DumpRaw(baseDir, primName, "primMesh");
990
991 coords = primMesh.coords;
992 faces = primMesh.faces;
993
994 return true;
995 }
996
997 public AMeshKey GetMeshUniqueKey(PrimitiveBaseShape primShape, Vector3 size, byte lod, bool convex)
998 {
999 AMeshKey key = new AMeshKey();
1000 Byte[] someBytes;
1001
1002 key.hashB = 5181;
1003 key.hashC = 5181;
1004 ulong hash = 5381;
1005
1006 if (primShape.SculptEntry)
1007 {
1008 key.uuid = primShape.SculptTexture;
1009 key.hashC = mdjb2(key.hashC, primShape.SculptType);
1010 key.hashC = mdjb2(key.hashC, primShape.PCode);
1011 }
1012 else
1013 {
1014 hash = mdjb2(hash, primShape.PathCurve);
1015 hash = mdjb2(hash, (byte)primShape.HollowShape);
1016 hash = mdjb2(hash, (byte)primShape.ProfileShape);
1017 hash = mdjb2(hash, primShape.PathBegin);
1018 hash = mdjb2(hash, primShape.PathEnd);
1019 hash = mdjb2(hash, primShape.PathScaleX);
1020 hash = mdjb2(hash, primShape.PathScaleY);
1021 hash = mdjb2(hash, primShape.PathShearX);
1022 key.hashA = hash;
1023 hash = key.hashB;
1024 hash = mdjb2(hash, primShape.PathShearY);
1025 hash = mdjb2(hash, (byte)primShape.PathTwist);
1026 hash = mdjb2(hash, (byte)primShape.PathTwistBegin);
1027 hash = mdjb2(hash, (byte)primShape.PathRadiusOffset);
1028 hash = mdjb2(hash, (byte)primShape.PathTaperX);
1029 hash = mdjb2(hash, (byte)primShape.PathTaperY);
1030 hash = mdjb2(hash, primShape.PathRevolutions);
1031 hash = mdjb2(hash, (byte)primShape.PathSkew);
1032 hash = mdjb2(hash, primShape.ProfileBegin);
1033 hash = mdjb2(hash, primShape.ProfileEnd);
1034 hash = mdjb2(hash, primShape.ProfileHollow);
1035 hash = mdjb2(hash, primShape.PCode);
1036 key.hashB = hash;
1037 }
1038
1039 hash = key.hashC;
1040
1041 hash = mdjb2(hash, lod);
1042
1043 if (size == m_MeshUnitSize)
1044 {
1045 hash = hash << 8;
1046 hash |= 8;
1047 }
1048 else
1049 {
1050 someBytes = size.GetBytes();
1051 for (int i = 0; i < someBytes.Length; i++)
1052 hash = mdjb2(hash, someBytes[i]);
1053 hash = hash << 8;
1054 }
1055
1056 if (convex)
1057 hash |= 4;
1058
1059 if (primShape.SculptEntry)
1060 {
1061 hash |= 1;
1062 if (primShape.SculptType == (byte)SculptType.Mesh)
1063 hash |= 2;
1064 }
1065
1066 key.hashC = hash;
1067
1068 return key;
1069 }
1070
1071 private ulong mdjb2(ulong hash, byte c)
1072 {
1073 return ((hash << 5) + hash) + (ulong)c;
1074 }
1075
1076 private ulong mdjb2(ulong hash, ushort c)
1077 {
1078 hash = ((hash << 5) + hash) + (ulong)((byte)c);
1079 return ((hash << 5) + hash) + (ulong)(c >> 8);
1080 }
1081
1082 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod)
1083 {
1084 return CreateMesh(primName, primShape, size, lod, false,false,false);
1085 }
1086
1087 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical)
1088 {
1089 return CreateMesh(primName, primShape, size, lod, false,false,false);
1090 }
1091
1092 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool shouldCache, bool convex, bool forOde)
1093 {
1094 return CreateMesh(primName, primShape, size, lod, false, false, false);
1095 }
1096
1097 public IMesh GetMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex)
1098 {
1099 Mesh mesh = null;
1100
1101 if (size.X < 0.01f) size.X = 0.01f;
1102 if (size.Y < 0.01f) size.Y = 0.01f;
1103 if (size.Z < 0.01f) size.Z = 0.01f;
1104
1105 AMeshKey key = GetMeshUniqueKey(primShape, size, (byte)lod, convex);
1106 lock (m_uniqueMeshes)
1107 {
1108 m_uniqueMeshes.TryGetValue(key, out mesh);
1109
1110 if (mesh != null)
1111 {
1112 mesh.RefCount++;
1113 return mesh;
1114 }
1115
1116 // try to find a identical mesh on meshs recently released
1117 lock (m_uniqueReleasedMeshes)
1118 {
1119 m_uniqueReleasedMeshes.TryGetValue(key, out mesh);
1120 if (mesh != null)
1121 {
1122 m_uniqueReleasedMeshes.Remove(key);
1123 try
1124 {
1125 m_uniqueMeshes.Add(key, mesh);
1126 }
1127 catch { }
1128 mesh.RefCount = 1;
1129 return mesh;
1130 }
1131 }
1132 }
1133 return null;
1134 }
1135
1136 private static Vector3 m_MeshUnitSize = new Vector3(1.0f, 1.0f, 1.0f);
1137
1138 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex, bool forOde)
1139 {
1140#if SPAM
1141 m_log.DebugFormat("[MESH]: Creating mesh for {0}", primName);
1142#endif
1143
1144 Mesh mesh = null;
1145
1146 if (size.X < 0.01f) size.X = 0.01f;
1147 if (size.Y < 0.01f) size.Y = 0.01f;
1148 if (size.Z < 0.01f) size.Z = 0.01f;
1149
1150 // try to find a identical mesh on meshs in use
1151
1152 AMeshKey key = GetMeshUniqueKey(primShape,size,(byte)lod, convex);
1153
1154 lock (m_uniqueMeshes)
1155 {
1156 m_uniqueMeshes.TryGetValue(key, out mesh);
1157
1158 if (mesh != null)
1159 {
1160 mesh.RefCount++;
1161 return mesh;
1162 }
1163
1164 // try to find a identical mesh on meshs recently released
1165 lock (m_uniqueReleasedMeshes)
1166 {
1167 m_uniqueReleasedMeshes.TryGetValue(key, out mesh);
1168 if (mesh != null)
1169 {
1170 m_uniqueReleasedMeshes.Remove(key);
1171 try
1172 {
1173 m_uniqueMeshes.Add(key, mesh);
1174 }
1175 catch { }
1176 mesh.RefCount = 1;
1177 return mesh;
1178 }
1179 }
1180 }
1181
1182 Mesh UnitMesh = null;
1183 AMeshKey unitKey = GetMeshUniqueKey(primShape, m_MeshUnitSize, (byte)lod, convex);
1184
1185 lock (m_uniqueReleasedMeshes)
1186 {
1187 m_uniqueReleasedMeshes.TryGetValue(unitKey, out UnitMesh);
1188 if (UnitMesh != null)
1189 {
1190 UnitMesh.RefCount = 1;
1191 }
1192 }
1193
1194 if (UnitMesh == null && primShape.SculptEntry && doMeshFileCache)
1195 UnitMesh = GetFromFileCache(unitKey);
1196
1197 if (UnitMesh == null)
1198 {
1199 UnitMesh = CreateMeshFromPrimMesher(primName, primShape, lod, convex);
1200
1201 if (UnitMesh == null)
1202 return null;
1203
1204 UnitMesh.DumpRaw(baseDir, unitKey.ToString(), "Z");
1205
1206 if (forOde)
1207 {
1208 // force pinned mem allocation
1209 UnitMesh.PrepForOde();
1210 }
1211 else
1212 UnitMesh.TrimExcess();
1213
1214 UnitMesh.Key = unitKey;
1215 UnitMesh.RefCount = 1;
1216
1217 if (doMeshFileCache && primShape.SculptEntry)
1218 StoreToFileCache(unitKey, UnitMesh);
1219
1220 lock (m_uniqueReleasedMeshes)
1221 {
1222 try
1223 {
1224 m_uniqueReleasedMeshes.Add(unitKey, UnitMesh);
1225 }
1226 catch { }
1227 }
1228 }
1229
1230 mesh = UnitMesh.Scale(size);
1231 mesh.Key = key;
1232 mesh.RefCount = 1;
1233 lock (m_uniqueMeshes)
1234 {
1235 try
1236 {
1237 m_uniqueMeshes.Add(key, mesh);
1238 }
1239 catch { }
1240 }
1241
1242 return mesh;
1243 }
1244
1245 public void ReleaseMesh(IMesh imesh)
1246 {
1247 if (imesh == null)
1248 return;
1249
1250 Mesh mesh = (Mesh)imesh;
1251
1252 lock (m_uniqueMeshes)
1253 {
1254 int curRefCount = mesh.RefCount;
1255 curRefCount--;
1256
1257 if (curRefCount > 0)
1258 {
1259 mesh.RefCount = curRefCount;
1260 return;
1261 }
1262
1263 mesh.RefCount = 0;
1264 m_uniqueMeshes.Remove(mesh.Key);
1265 lock (m_uniqueReleasedMeshes)
1266 {
1267 try
1268 {
1269 m_uniqueReleasedMeshes.Add(mesh.Key, mesh);
1270 }
1271 catch { }
1272 }
1273 }
1274 }
1275
1276 public void ExpireReleaseMeshs()
1277 {
1278 if (m_uniqueReleasedMeshes.Count == 0)
1279 return;
1280
1281 List<Mesh> meshstodelete = new List<Mesh>();
1282 int refcntr;
1283
1284 lock (m_uniqueReleasedMeshes)
1285 {
1286 foreach (Mesh m in m_uniqueReleasedMeshes.Values)
1287 {
1288 refcntr = m.RefCount;
1289 refcntr--;
1290 if (refcntr > -6)
1291 m.RefCount = refcntr;
1292 else
1293 meshstodelete.Add(m);
1294 }
1295
1296 foreach (Mesh m in meshstodelete)
1297 {
1298 m_uniqueReleasedMeshes.Remove(m.Key);
1299 m.releaseBuildingMeshData();
1300 m.releasePinned();
1301 }
1302 }
1303 }
1304
1305 public void FileNames(AMeshKey key, out string dir,out string fullFileName)
1306 {
1307 string id = key.ToString();
1308 string init = id.Substring(0, 1);
1309 dir = System.IO.Path.Combine(cachePath, init);
1310 fullFileName = System.IO.Path.Combine(dir, id);
1311 }
1312
1313 public string FullFileName(AMeshKey key)
1314 {
1315 string id = key.ToString();
1316 string init = id.Substring(0,1);
1317 id = System.IO.Path.Combine(init, id);
1318 id = System.IO.Path.Combine(cachePath, id);
1319 return id;
1320 }
1321
1322 private Mesh GetFromFileCache(AMeshKey key)
1323 {
1324 Mesh mesh = null;
1325 string filename = FullFileName(key);
1326 bool ok = true;
1327
1328 lock (diskLock)
1329 {
1330 if (File.Exists(filename))
1331 {
1332 FileStream stream = null;
1333 try
1334 {
1335 stream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read);
1336 BinaryFormatter bformatter = new BinaryFormatter();
1337
1338 mesh = Mesh.FromStream(stream, key);
1339
1340 }
1341 catch (Exception e)
1342 {
1343 ok = false;
1344 m_log.ErrorFormat(
1345 "[MESH CACHE]: Failed to get file {0}. Exception {1} {2}",
1346 filename, e.Message, e.StackTrace);
1347 }
1348
1349 if (stream != null)
1350 stream.Close();
1351
1352 if (mesh == null || !ok)
1353 File.Delete(filename);
1354 else
1355 File.SetLastAccessTimeUtc(filename, DateTime.UtcNow);
1356 }
1357 }
1358
1359 return mesh;
1360 }
1361
1362 private void StoreToFileCache(AMeshKey key, Mesh mesh)
1363 {
1364 Stream stream = null;
1365 bool ok = false;
1366
1367 // Make sure the target cache directory exists
1368 string dir = String.Empty;
1369 string filename = String.Empty;
1370
1371 FileNames(key, out dir, out filename);
1372
1373 lock (diskLock)
1374 {
1375 try
1376 {
1377 if (!Directory.Exists(dir))
1378 {
1379 Directory.CreateDirectory(dir);
1380 }
1381
1382 stream = File.Open(filename, FileMode.Create);
1383 ok = mesh.ToStream(stream);
1384 }
1385 catch (IOException e)
1386 {
1387 m_log.ErrorFormat(
1388 "[MESH CACHE]: Failed to write file {0}. Exception {1} {2}.",
1389 filename, e.Message, e.StackTrace);
1390 ok = false;
1391 }
1392
1393 if (stream != null)
1394 stream.Close();
1395
1396 if (File.Exists(filename))
1397 {
1398 if (ok)
1399 File.SetLastAccessTimeUtc(filename, DateTime.UtcNow);
1400 else
1401 File.Delete(filename);
1402 }
1403 }
1404 }
1405
1406 public void ExpireFileCache()
1407 {
1408 if (!doCacheExpire)
1409 return;
1410
1411 string controlfile = System.IO.Path.Combine(cachePath, "cntr");
1412
1413 lock (diskLock)
1414 {
1415 try
1416 {
1417 if (File.Exists(controlfile))
1418 {
1419 int ndeleted = 0;
1420 int totalfiles = 0;
1421 int ndirs = 0;
1422 DateTime OlderTime = File.GetLastAccessTimeUtc(controlfile) - CacheExpire;
1423 File.SetLastAccessTimeUtc(controlfile, DateTime.UtcNow);
1424
1425 foreach (string dir in Directory.GetDirectories(cachePath))
1426 {
1427 try
1428 {
1429 foreach (string file in Directory.GetFiles(dir))
1430 {
1431 try
1432 {
1433 if (File.GetLastAccessTimeUtc(file) < OlderTime)
1434 {
1435 File.Delete(file);
1436 ndeleted++;
1437 }
1438 }
1439 catch { }
1440 totalfiles++;
1441 }
1442 }
1443 catch { }
1444 ndirs++;
1445 }
1446
1447 if (ndeleted == 0)
1448 m_log.InfoFormat("[MESH CACHE]: {0} Files in {1} cache folders, no expires",
1449 totalfiles,ndirs);
1450 else
1451 m_log.InfoFormat("[MESH CACHE]: {0} Files in {1} cache folders, expired {2} files accessed before {3}",
1452 totalfiles,ndirs, ndeleted, OlderTime.ToString());
1453 }
1454 else
1455 {
1456 m_log.Info("[MESH CACHE]: Expire delayed to next startup");
1457 FileStream fs = File.Create(controlfile,4096,FileOptions.WriteThrough);
1458 fs.Close();
1459 }
1460 }
1461 catch { }
1462 }
1463 }
1464 }
1465}
diff --git a/OpenSim/Region/PhysicsModules/ubOdeMeshing/PrimMesher.cs b/OpenSim/Region/PhysicsModules/ubOdeMeshing/PrimMesher.cs
new file mode 100644
index 0000000..8eb136b
--- /dev/null
+++ b/OpenSim/Region/PhysicsModules/ubOdeMeshing/PrimMesher.cs
@@ -0,0 +1,1708 @@
1/*
2 * Copyright (c) Contributors
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Text;
31using System.IO;
32
33namespace PrimMesher
34{
35 public struct Quat
36 {
37 /// <summary>X value</summary>
38 public float X;
39 /// <summary>Y value</summary>
40 public float Y;
41 /// <summary>Z value</summary>
42 public float Z;
43 /// <summary>W value</summary>
44 public float W;
45
46 public Quat(float x, float y, float z, float w)
47 {
48 X = x;
49 Y = y;
50 Z = z;
51 W = w;
52 }
53
54 public Quat(Coord axis, float angle)
55 {
56 axis = axis.Normalize();
57
58 angle *= 0.5f;
59 float c = (float)Math.Cos(angle);
60 float s = (float)Math.Sin(angle);
61
62 X = axis.X * s;
63 Y = axis.Y * s;
64 Z = axis.Z * s;
65 W = c;
66
67 Normalize();
68 }
69
70 public float Length()
71 {
72 return (float)Math.Sqrt(X * X + Y * Y + Z * Z + W * W);
73 }
74
75 public Quat Normalize()
76 {
77 const float MAG_THRESHOLD = 0.0000001f;
78 float mag = Length();
79
80 // Catch very small rounding errors when normalizing
81 if (mag > MAG_THRESHOLD)
82 {
83 float oomag = 1f / mag;
84 X *= oomag;
85 Y *= oomag;
86 Z *= oomag;
87 W *= oomag;
88 }
89 else
90 {
91 X = 0f;
92 Y = 0f;
93 Z = 0f;
94 W = 1f;
95 }
96
97 return this;
98 }
99
100 public static Quat operator *(Quat q1, Quat q2)
101 {
102 float x = q1.W * q2.X + q1.X * q2.W + q1.Y * q2.Z - q1.Z * q2.Y;
103 float y = q1.W * q2.Y - q1.X * q2.Z + q1.Y * q2.W + q1.Z * q2.X;
104 float z = q1.W * q2.Z + q1.X * q2.Y - q1.Y * q2.X + q1.Z * q2.W;
105 float w = q1.W * q2.W - q1.X * q2.X - q1.Y * q2.Y - q1.Z * q2.Z;
106 return new Quat(x, y, z, w);
107 }
108
109 public override string ToString()
110 {
111 return "< X: " + this.X.ToString() + ", Y: " + this.Y.ToString() + ", Z: " + this.Z.ToString() + ", W: " + this.W.ToString() + ">";
112 }
113 }
114
115 public struct Coord
116 {
117 public float X;
118 public float Y;
119 public float Z;
120
121 public Coord(float x, float y, float z)
122 {
123 this.X = x;
124 this.Y = y;
125 this.Z = z;
126 }
127
128 public float Length()
129 {
130 return (float)Math.Sqrt(this.X * this.X + this.Y * this.Y + this.Z * this.Z);
131 }
132
133 public Coord Invert()
134 {
135 this.X = -this.X;
136 this.Y = -this.Y;
137 this.Z = -this.Z;
138
139 return this;
140 }
141
142 public Coord Normalize()
143 {
144 const float MAG_THRESHOLD = 0.0000001f;
145 float mag = Length();
146
147 // Catch very small rounding errors when normalizing
148 if (mag > MAG_THRESHOLD)
149 {
150 float oomag = 1.0f / mag;
151 this.X *= oomag;
152 this.Y *= oomag;
153 this.Z *= oomag;
154 }
155 else
156 {
157 this.X = 0.0f;
158 this.Y = 0.0f;
159 this.Z = 0.0f;
160 }
161
162 return this;
163 }
164
165 public override string ToString()
166 {
167 return this.X.ToString() + " " + this.Y.ToString() + " " + this.Z.ToString();
168 }
169
170 public static Coord Cross(Coord c1, Coord c2)
171 {
172 return new Coord(
173 c1.Y * c2.Z - c2.Y * c1.Z,
174 c1.Z * c2.X - c2.Z * c1.X,
175 c1.X * c2.Y - c2.X * c1.Y
176 );
177 }
178
179 public static Coord operator +(Coord v, Coord a)
180 {
181 return new Coord(v.X + a.X, v.Y + a.Y, v.Z + a.Z);
182 }
183
184 public static Coord operator *(Coord v, Coord m)
185 {
186 return new Coord(v.X * m.X, v.Y * m.Y, v.Z * m.Z);
187 }
188
189 public static Coord operator *(Coord v, Quat q)
190 {
191 // From http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/transforms/
192
193 Coord c2 = new Coord(0.0f, 0.0f, 0.0f);
194
195 c2.X = q.W * q.W * v.X +
196 2f * q.Y * q.W * v.Z -
197 2f * q.Z * q.W * v.Y +
198 q.X * q.X * v.X +
199 2f * q.Y * q.X * v.Y +
200 2f * q.Z * q.X * v.Z -
201 q.Z * q.Z * v.X -
202 q.Y * q.Y * v.X;
203
204 c2.Y =
205 2f * q.X * q.Y * v.X +
206 q.Y * q.Y * v.Y +
207 2f * q.Z * q.Y * v.Z +
208 2f * q.W * q.Z * v.X -
209 q.Z * q.Z * v.Y +
210 q.W * q.W * v.Y -
211 2f * q.X * q.W * v.Z -
212 q.X * q.X * v.Y;
213
214 c2.Z =
215 2f * q.X * q.Z * v.X +
216 2f * q.Y * q.Z * v.Y +
217 q.Z * q.Z * v.Z -
218 2f * q.W * q.Y * v.X -
219 q.Y * q.Y * v.Z +
220 2f * q.W * q.X * v.Y -
221 q.X * q.X * v.Z +
222 q.W * q.W * v.Z;
223
224 return c2;
225 }
226 }
227
228 public struct Face
229 {
230 public int primFace;
231
232 // vertices
233 public int v1;
234 public int v2;
235 public int v3;
236
237 public Face(int v1, int v2, int v3)
238 {
239 primFace = 0;
240
241 this.v1 = v1;
242 this.v2 = v2;
243 this.v3 = v3;
244
245 }
246
247 public Coord SurfaceNormal(List<Coord> coordList)
248 {
249 Coord c1 = coordList[this.v1];
250 Coord c2 = coordList[this.v2];
251 Coord c3 = coordList[this.v3];
252
253 Coord edge1 = new Coord(c2.X - c1.X, c2.Y - c1.Y, c2.Z - c1.Z);
254 Coord edge2 = new Coord(c3.X - c1.X, c3.Y - c1.Y, c3.Z - c1.Z);
255
256 return Coord.Cross(edge1, edge2).Normalize();
257 }
258 }
259
260 internal struct Angle
261 {
262 internal float angle;
263 internal float X;
264 internal float Y;
265
266 internal Angle(float angle, float x, float y)
267 {
268 this.angle = angle;
269 this.X = x;
270 this.Y = y;
271 }
272 }
273
274 internal class AngleList
275 {
276 private float iX, iY; // intersection point
277
278 private static Angle[] angles3 =
279 {
280 new Angle(0.0f, 1.0f, 0.0f),
281 new Angle(0.33333333333333333f, -0.5f, 0.86602540378443871f),
282 new Angle(0.66666666666666667f, -0.5f, -0.86602540378443837f),
283 new Angle(1.0f, 1.0f, 0.0f)
284 };
285
286 private static Angle[] angles4 =
287 {
288 new Angle(0.0f, 1.0f, 0.0f),
289 new Angle(0.25f, 0.0f, 1.0f),
290 new Angle(0.5f, -1.0f, 0.0f),
291 new Angle(0.75f, 0.0f, -1.0f),
292 new Angle(1.0f, 1.0f, 0.0f)
293 };
294
295 private static Angle[] angles6 =
296 {
297 new Angle(0.0f, 1.0f, 0.0f),
298 new Angle(0.16666666666666667f, 0.5f, 0.8660254037844386f),
299 new Angle(0.33333333333333333f, -0.5f, 0.86602540378443871f),
300 new Angle(0.5f, -1.0f, 0.0f),
301 new Angle(0.66666666666666667f, -0.5f, -0.86602540378443837f),
302 new Angle(0.83333333333333326f, 0.5f, -0.86602540378443904f),
303 new Angle(1.0f, 1.0f, 0.0f)
304 };
305
306 private static Angle[] angles12 =
307 {
308 new Angle(0.0f, 1.0f, 0.0f),
309 new Angle(0.083333333333333329f, 0.86602540378443871f, 0.5f),
310 new Angle(0.16666666666666667f, 0.5f, 0.8660254037844386f),
311 new Angle(0.25f, 0.0f, 1.0f),
312 new Angle(0.33333333333333333f, -0.5f, 0.86602540378443871f),
313 new Angle(0.41666666666666663f, -0.86602540378443849f, 0.5f),
314 new Angle(0.5f, -1.0f, 0.0f),
315 new Angle(0.58333333333333326f, -0.86602540378443882f, -0.5f),
316 new Angle(0.66666666666666667f, -0.5f, -0.86602540378443837f),
317 new Angle(0.75f, 0.0f, -1.0f),
318 new Angle(0.83333333333333326f, 0.5f, -0.86602540378443904f),
319 new Angle(0.91666666666666663f, 0.86602540378443837f, -0.5f),
320 new Angle(1.0f, 1.0f, 0.0f)
321 };
322
323 private static Angle[] angles24 =
324 {
325 new Angle(0.0f, 1.0f, 0.0f),
326 new Angle(0.041666666666666664f, 0.96592582628906831f, 0.25881904510252074f),
327 new Angle(0.083333333333333329f, 0.86602540378443871f, 0.5f),
328 new Angle(0.125f, 0.70710678118654757f, 0.70710678118654746f),
329 new Angle(0.16666666666666667f, 0.5f, 0.8660254037844386f),
330 new Angle(0.20833333333333331f, 0.25881904510252096f, 0.9659258262890682f),
331 new Angle(0.25f, 0.0f, 1.0f),
332 new Angle(0.29166666666666663f, -0.25881904510252063f, 0.96592582628906831f),
333 new Angle(0.33333333333333333f, -0.5f, 0.86602540378443871f),
334 new Angle(0.375f, -0.70710678118654746f, 0.70710678118654757f),
335 new Angle(0.41666666666666663f, -0.86602540378443849f, 0.5f),
336 new Angle(0.45833333333333331f, -0.9659258262890682f, 0.25881904510252102f),
337 new Angle(0.5f, -1.0f, 0.0f),
338 new Angle(0.54166666666666663f, -0.96592582628906842f, -0.25881904510252035f),
339 new Angle(0.58333333333333326f, -0.86602540378443882f, -0.5f),
340 new Angle(0.62499999999999989f, -0.70710678118654791f, -0.70710678118654713f),
341 new Angle(0.66666666666666667f, -0.5f, -0.86602540378443837f),
342 new Angle(0.70833333333333326f, -0.25881904510252152f, -0.96592582628906809f),
343 new Angle(0.75f, 0.0f, -1.0f),
344 new Angle(0.79166666666666663f, 0.2588190451025203f, -0.96592582628906842f),
345 new Angle(0.83333333333333326f, 0.5f, -0.86602540378443904f),
346 new Angle(0.875f, 0.70710678118654735f, -0.70710678118654768f),
347 new Angle(0.91666666666666663f, 0.86602540378443837f, -0.5f),
348 new Angle(0.95833333333333326f, 0.96592582628906809f, -0.25881904510252157f),
349 new Angle(1.0f, 1.0f, 0.0f)
350 };
351
352 private Angle interpolatePoints(float newPoint, Angle p1, Angle p2)
353 {
354 float m = (newPoint - p1.angle) / (p2.angle - p1.angle);
355 return new Angle(newPoint, p1.X + m * (p2.X - p1.X), p1.Y + m * (p2.Y - p1.Y));
356 }
357
358 private void intersection(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4)
359 { // ref: http://local.wasp.uwa.edu.au/~pbourke/geometry/lineline2d/
360 double denom = (y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1);
361 double uaNumerator = (x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3);
362
363 if (denom != 0.0)
364 {
365 double ua = uaNumerator / denom;
366 iX = (float)(x1 + ua * (x2 - x1));
367 iY = (float)(y1 + ua * (y2 - y1));
368 }
369 }
370
371 internal List<Angle> angles;
372
373 internal void makeAngles(int sides, float startAngle, float stopAngle, bool hasCut)
374 {
375 angles = new List<Angle>();
376
377 const double twoPi = System.Math.PI * 2.0;
378 const float twoPiInv = (float)(1.0d / twoPi);
379
380 if (sides < 1)
381 throw new Exception("number of sides not greater than zero");
382 if (stopAngle <= startAngle)
383 throw new Exception("stopAngle not greater than startAngle");
384
385 if ((sides == 3 || sides == 4 || sides == 6 || sides == 12 || sides == 24))
386 {
387 startAngle *= twoPiInv;
388 stopAngle *= twoPiInv;
389
390 Angle[] sourceAngles;
391 switch (sides)
392 {
393 case 3:
394 sourceAngles = angles3;
395 break;
396 case 4:
397 sourceAngles = angles4;
398 break;
399 case 6:
400 sourceAngles = angles6;
401 break;
402 case 12:
403 sourceAngles = angles12;
404 break;
405 default:
406 sourceAngles = angles24;
407 break;
408 }
409
410 int startAngleIndex = (int)(startAngle * sides);
411 int endAngleIndex = sourceAngles.Length - 1;
412
413 if (hasCut)
414 {
415 if (stopAngle < 1.0f)
416 endAngleIndex = (int)(stopAngle * sides) + 1;
417 if (endAngleIndex == startAngleIndex)
418 endAngleIndex++;
419
420 for (int angleIndex = startAngleIndex; angleIndex < endAngleIndex + 1; angleIndex++)
421 {
422 angles.Add(sourceAngles[angleIndex]);
423 }
424
425 if (startAngle > 0.0f)
426 angles[0] = interpolatePoints(startAngle, angles[0], angles[1]);
427
428 if (stopAngle < 1.0f)
429 {
430 int lastAngleIndex = angles.Count - 1;
431 angles[lastAngleIndex] = interpolatePoints(stopAngle, angles[lastAngleIndex - 1], angles[lastAngleIndex]);
432 }
433 }
434 else
435 {
436 for (int angleIndex = startAngleIndex; angleIndex < endAngleIndex; angleIndex++)
437 angles.Add(sourceAngles[angleIndex]);
438 }
439 }
440 else
441 {
442 double stepSize = twoPi / sides;
443
444 int startStep = (int)(startAngle / stepSize);
445 double angle = stepSize * startStep;
446 int step = startStep;
447 double stopAngleTest = stopAngle;
448 if (stopAngle < twoPi)
449 {
450 stopAngleTest = stepSize * ((int)(stopAngle / stepSize) + 1);
451 if (stopAngleTest < stopAngle)
452 stopAngleTest += stepSize;
453 if (stopAngleTest > twoPi)
454 stopAngleTest = twoPi;
455 }
456
457 while (angle <= stopAngleTest)
458 {
459 Angle newAngle;
460 newAngle.angle = (float)angle;
461 newAngle.X = (float)System.Math.Cos(angle);
462 newAngle.Y = (float)System.Math.Sin(angle);
463 angles.Add(newAngle);
464 step += 1;
465 angle = stepSize * step;
466 }
467
468 if (startAngle > angles[0].angle)
469 {
470 Angle newAngle;
471 intersection(angles[0].X, angles[0].Y, angles[1].X, angles[1].Y, 0.0f, 0.0f, (float)Math.Cos(startAngle), (float)Math.Sin(startAngle));
472 newAngle.angle = startAngle;
473 newAngle.X = iX;
474 newAngle.Y = iY;
475 angles[0] = newAngle;
476 }
477
478 int index = angles.Count - 1;
479 if (stopAngle < angles[index].angle)
480 {
481 Angle newAngle;
482 intersection(angles[index - 1].X, angles[index - 1].Y, angles[index].X, angles[index].Y, 0.0f, 0.0f, (float)Math.Cos(stopAngle), (float)Math.Sin(stopAngle));
483 newAngle.angle = stopAngle;
484 newAngle.X = iX;
485 newAngle.Y = iY;
486 angles[index] = newAngle;
487 }
488 }
489 }
490 }
491
492 /// <summary>
493 /// generates a profile for extrusion
494 /// </summary>
495 public class Profile
496 {
497 private const float twoPi = 2.0f * (float)Math.PI;
498
499 public string errorMessage = null;
500
501 public List<Coord> coords;
502 public List<Face> faces;
503
504 // use these for making individual meshes for each prim face
505 public List<int> outerCoordIndices = null;
506 public List<int> hollowCoordIndices = null;
507
508 public int numOuterVerts = 0;
509 public int numHollowVerts = 0;
510
511 public int outerFaceNumber = -1;
512 public int hollowFaceNumber = -1;
513
514 public int bottomFaceNumber = 0;
515 public int numPrimFaces = 0;
516
517 public Profile()
518 {
519 this.coords = new List<Coord>();
520 this.faces = new List<Face>();
521 }
522
523 public Profile(int sides, float profileStart, float profileEnd, float hollow, int hollowSides, bool hasProfileCut, bool createFaces)
524 {
525 const float halfSqr2 = 0.7071067811866f;
526
527 this.coords = new List<Coord>();
528 this.faces = new List<Face>();
529
530 List<Coord> hollowCoords = new List<Coord>();
531
532 bool hasHollow = (hollow > 0.0f);
533
534 AngleList angles = new AngleList();
535 AngleList hollowAngles = new AngleList();
536
537 float xScale = 0.5f;
538 float yScale = 0.5f;
539 if (sides == 4) // corners of a square are sqrt(2) from center
540 {
541 xScale = halfSqr2;
542 yScale = halfSqr2;
543 }
544
545 float startAngle = profileStart * twoPi;
546 float stopAngle = profileEnd * twoPi;
547
548 try { angles.makeAngles(sides, startAngle, stopAngle,hasProfileCut); }
549 catch (Exception ex)
550 {
551
552 errorMessage = "makeAngles failed: Exception: " + ex.ToString()
553 + "\nsides: " + sides.ToString() + " startAngle: " + startAngle.ToString() + " stopAngle: " + stopAngle.ToString();
554
555 return;
556 }
557
558 this.numOuterVerts = angles.angles.Count;
559
560 Angle angle;
561 Coord newVert = new Coord();
562
563 // flag to create as few triangles as possible for 3 or 4 side profile
564 bool simpleFace = (sides < 5 && !hasHollow && !hasProfileCut);
565
566 if (hasHollow)
567 {
568 if (sides == hollowSides)
569 hollowAngles = angles;
570 else
571 {
572 try { hollowAngles.makeAngles(hollowSides, startAngle, stopAngle, hasProfileCut); }
573 catch (Exception ex)
574 {
575 errorMessage = "makeAngles failed: Exception: " + ex.ToString()
576 + "\nsides: " + sides.ToString() + " startAngle: " + startAngle.ToString() + " stopAngle: " + stopAngle.ToString();
577
578 return;
579 }
580
581 int numHollowAngles = hollowAngles.angles.Count;
582 for (int i = 0; i < numHollowAngles; i++)
583 {
584 angle = hollowAngles.angles[i];
585 newVert.X = hollow * xScale * angle.X;
586 newVert.Y = hollow * yScale * angle.Y;
587 newVert.Z = 0.0f;
588
589 hollowCoords.Add(newVert);
590 }
591 }
592 this.numHollowVerts = hollowAngles.angles.Count;
593 }
594 else if (!simpleFace)
595 {
596 Coord center = new Coord(0.0f, 0.0f, 0.0f);
597 this.coords.Add(center);
598 }
599
600 int numAngles = angles.angles.Count;
601 bool hollowsame = (hasHollow && hollowSides == sides);
602
603 for (int i = 0; i < numAngles; i++)
604 {
605 angle = angles.angles[i];
606 newVert.X = angle.X * xScale;
607 newVert.Y = angle.Y * yScale;
608 newVert.Z = 0.0f;
609 this.coords.Add(newVert);
610 if (hollowsame)
611 {
612 newVert.X *= hollow;
613 newVert.Y *= hollow;
614 hollowCoords.Add(newVert);
615 }
616 }
617
618 if (hasHollow)
619 {
620 hollowCoords.Reverse();
621 this.coords.AddRange(hollowCoords);
622
623 if (createFaces)
624 {
625 int numTotalVerts = this.numOuterVerts + this.numHollowVerts;
626
627 if (this.numOuterVerts == this.numHollowVerts)
628 {
629 Face newFace = new Face();
630
631 for (int coordIndex = 0; coordIndex < this.numOuterVerts - 1; coordIndex++)
632 {
633 newFace.v1 = coordIndex;
634 newFace.v2 = coordIndex + 1;
635 newFace.v3 = numTotalVerts - coordIndex - 1;
636 this.faces.Add(newFace);
637
638 newFace.v1 = coordIndex + 1;
639 newFace.v2 = numTotalVerts - coordIndex - 2;
640 newFace.v3 = numTotalVerts - coordIndex - 1;
641 this.faces.Add(newFace);
642 }
643 if (!hasProfileCut)
644 {
645 newFace.v1 = this.numOuterVerts - 1;
646 newFace.v2 = 0;
647 newFace.v3 = this.numOuterVerts;
648 this.faces.Add(newFace);
649
650 newFace.v1 = 0;
651 newFace.v2 = numTotalVerts - 1;
652 newFace.v3 = this.numOuterVerts;
653 this.faces.Add(newFace);
654 }
655 }
656 else if (this.numOuterVerts < this.numHollowVerts)
657 {
658 Face newFace = new Face();
659 int j = 0; // j is the index for outer vertices
660 int i;
661 int maxJ = this.numOuterVerts - 1;
662 float curHollowAngle = 0;
663 for (i = 0; i < this.numHollowVerts; i++) // i is the index for inner vertices
664 {
665 curHollowAngle = hollowAngles.angles[i].angle;
666 if (j < maxJ)
667 {
668 if (angles.angles[j + 1].angle - curHollowAngle < curHollowAngle - angles.angles[j].angle + 0.000001f)
669 {
670 newFace.v1 = numTotalVerts - i - 1;
671 newFace.v2 = j;
672 newFace.v3 = j + 1;
673 this.faces.Add(newFace);
674 j++;
675 }
676 }
677 else
678 {
679 if (1.0f - curHollowAngle < curHollowAngle - angles.angles[j].angle + 0.000001f)
680 break;
681 }
682
683 newFace.v1 = j;
684 newFace.v2 = numTotalVerts - i - 2;
685 newFace.v3 = numTotalVerts - i - 1;
686
687 this.faces.Add(newFace);
688 }
689
690 if (!hasProfileCut)
691 {
692 if (i == this.numHollowVerts)
693 {
694 newFace.v1 = numTotalVerts - this.numHollowVerts;
695 newFace.v2 = maxJ;
696 newFace.v3 = 0;
697
698 this.faces.Add(newFace);
699 }
700 else
701 {
702 if (1.0f - curHollowAngle < curHollowAngle - angles.angles[maxJ].angle + 0.000001f)
703 {
704 newFace.v1 = numTotalVerts - i - 1;
705 newFace.v2 = maxJ;
706 newFace.v3 = 0;
707
708 this.faces.Add(newFace);
709 }
710
711 for (; i < this.numHollowVerts - 1; i++)
712 {
713 newFace.v1 = 0;
714 newFace.v2 = numTotalVerts - i - 2;
715 newFace.v3 = numTotalVerts - i - 1;
716
717 this.faces.Add(newFace);
718 }
719 }
720
721 newFace.v1 = 0;
722 newFace.v2 = numTotalVerts - this.numHollowVerts;
723 newFace.v3 = numTotalVerts - 1;
724 this.faces.Add(newFace);
725 }
726 }
727 else // numHollowVerts < numOuterVerts
728 {
729 Face newFace = new Face();
730 int j = 0; // j is the index for inner vertices
731 int maxJ = this.numHollowVerts - 1;
732 for (int i = 0; i < this.numOuterVerts; i++)
733 {
734 if (j < maxJ)
735 if (hollowAngles.angles[j + 1].angle - angles.angles[i].angle < angles.angles[i].angle - hollowAngles.angles[j].angle + 0.000001f)
736 {
737 newFace.v1 = i;
738 newFace.v2 = numTotalVerts - j - 2;
739 newFace.v3 = numTotalVerts - j - 1;
740
741 this.faces.Add(newFace);
742 j += 1;
743 }
744
745 newFace.v1 = numTotalVerts - j - 1;
746 newFace.v2 = i;
747 newFace.v3 = i + 1;
748
749 this.faces.Add(newFace);
750 }
751
752 if (!hasProfileCut)
753 {
754 int i = this.numOuterVerts - 1;
755
756 if (hollowAngles.angles[0].angle - angles.angles[i].angle < angles.angles[i].angle - hollowAngles.angles[maxJ].angle + 0.000001f)
757 {
758 newFace.v1 = 0;
759 newFace.v2 = numTotalVerts - maxJ - 1;
760 newFace.v3 = numTotalVerts - 1;
761
762 this.faces.Add(newFace);
763 }
764
765 newFace.v1 = numTotalVerts - maxJ - 1;
766 newFace.v2 = i;
767 newFace.v3 = 0;
768
769 this.faces.Add(newFace);
770 }
771 }
772 }
773
774 }
775
776 else if (createFaces)
777 {
778 if (simpleFace)
779 {
780 if (sides == 3)
781 this.faces.Add(new Face(0, 1, 2));
782 else if (sides == 4)
783 {
784 this.faces.Add(new Face(0, 1, 2));
785 this.faces.Add(new Face(0, 2, 3));
786 }
787 }
788 else
789 {
790 for (int i = 1; i < numAngles ; i++)
791 {
792 Face newFace = new Face();
793 newFace.v1 = 0;
794 newFace.v2 = i;
795 newFace.v3 = i + 1;
796 this.faces.Add(newFace);
797 }
798 if (!hasProfileCut)
799 {
800 Face newFace = new Face();
801 newFace.v1 = 0;
802 newFace.v2 = numAngles;
803 newFace.v3 = 1;
804 this.faces.Add(newFace);
805 }
806 }
807 }
808
809
810 hollowCoords = null;
811 }
812
813
814 public Profile Copy()
815 {
816 return this.Copy(true);
817 }
818
819 public Profile Copy(bool needFaces)
820 {
821 Profile copy = new Profile();
822
823 copy.coords.AddRange(this.coords);
824
825 if (needFaces)
826 copy.faces.AddRange(this.faces);
827
828 copy.numOuterVerts = this.numOuterVerts;
829 copy.numHollowVerts = this.numHollowVerts;
830
831 return copy;
832 }
833
834 public void AddPos(Coord v)
835 {
836 this.AddPos(v.X, v.Y, v.Z);
837 }
838
839 public void AddPos(float x, float y, float z)
840 {
841 int i;
842 int numVerts = this.coords.Count;
843 Coord vert;
844
845 for (i = 0; i < numVerts; i++)
846 {
847 vert = this.coords[i];
848 vert.X += x;
849 vert.Y += y;
850 vert.Z += z;
851 this.coords[i] = vert;
852 }
853 }
854
855 public void AddRot(Quat q)
856 {
857 int i;
858 int numVerts = this.coords.Count;
859
860 for (i = 0; i < numVerts; i++)
861 this.coords[i] *= q;
862 }
863
864 public void Scale(float x, float y)
865 {
866 int i;
867 int numVerts = this.coords.Count;
868 Coord vert;
869
870 for (i = 0; i < numVerts; i++)
871 {
872 vert = this.coords[i];
873 vert.X *= x;
874 vert.Y *= y;
875 this.coords[i] = vert;
876 }
877 }
878
879 /// <summary>
880 /// Changes order of the vertex indices and negates the center vertex normal. Does not alter vertex normals of radial vertices
881 /// </summary>
882 public void FlipNormals()
883 {
884 int i;
885 int numFaces = this.faces.Count;
886 Face tmpFace;
887 int tmp;
888
889 for (i = 0; i < numFaces; i++)
890 {
891 tmpFace = this.faces[i];
892 tmp = tmpFace.v3;
893 tmpFace.v3 = tmpFace.v1;
894 tmpFace.v1 = tmp;
895 this.faces[i] = tmpFace;
896 }
897 }
898
899 public void AddValue2FaceVertexIndices(int num)
900 {
901 int numFaces = this.faces.Count;
902 Face tmpFace;
903 for (int i = 0; i < numFaces; i++)
904 {
905 tmpFace = this.faces[i];
906 tmpFace.v1 += num;
907 tmpFace.v2 += num;
908 tmpFace.v3 += num;
909
910 this.faces[i] = tmpFace;
911 }
912 }
913
914 public void DumpRaw(String path, String name, String title)
915 {
916 if (path == null)
917 return;
918 String fileName = name + "_" + title + ".raw";
919 String completePath = System.IO.Path.Combine(path, fileName);
920 StreamWriter sw = new StreamWriter(completePath);
921
922 for (int i = 0; i < this.faces.Count; i++)
923 {
924 string s = this.coords[this.faces[i].v1].ToString();
925 s += " " + this.coords[this.faces[i].v2].ToString();
926 s += " " + this.coords[this.faces[i].v3].ToString();
927
928 sw.WriteLine(s);
929 }
930
931 sw.Close();
932 }
933 }
934
935 public struct PathNode
936 {
937 public Coord position;
938 public Quat rotation;
939 public float xScale;
940 public float yScale;
941 public float percentOfPath;
942 }
943
944 public enum PathType { Linear = 0, Circular = 1, Flexible = 2 }
945
946 public class Path
947 {
948 public List<PathNode> pathNodes = new List<PathNode>();
949
950 public float twistBegin = 0.0f;
951 public float twistEnd = 0.0f;
952 public float topShearX = 0.0f;
953 public float topShearY = 0.0f;
954 public float pathCutBegin = 0.0f;
955 public float pathCutEnd = 1.0f;
956 public float dimpleBegin = 0.0f;
957 public float dimpleEnd = 1.0f;
958 public float skew = 0.0f;
959 public float holeSizeX = 1.0f; // called pathScaleX in pbs
960 public float holeSizeY = 0.25f;
961 public float taperX = 0.0f;
962 public float taperY = 0.0f;
963 public float radius = 0.0f;
964 public float revolutions = 1.0f;
965 public int stepsPerRevolution = 24;
966
967 private const float twoPi = 2.0f * (float)Math.PI;
968
969 public void Create(PathType pathType, int steps)
970 {
971 if (this.taperX > 0.999f)
972 this.taperX = 0.999f;
973 if (this.taperX < -0.999f)
974 this.taperX = -0.999f;
975 if (this.taperY > 0.999f)
976 this.taperY = 0.999f;
977 if (this.taperY < -0.999f)
978 this.taperY = -0.999f;
979
980 if (pathType == PathType.Linear || pathType == PathType.Flexible)
981 {
982 int step = 0;
983
984 float length = this.pathCutEnd - this.pathCutBegin;
985 float twistTotal = twistEnd - twistBegin;
986 float twistTotalAbs = Math.Abs(twistTotal);
987 if (twistTotalAbs > 0.01f)
988 steps += (int)(twistTotalAbs * 3.66); // dahlia's magic number
989
990 float start = -0.5f;
991 float stepSize = length / (float)steps;
992 float percentOfPathMultiplier = stepSize * 0.999999f;
993 float xOffset = this.topShearX * this.pathCutBegin;
994 float yOffset = this.topShearY * this.pathCutBegin;
995 float zOffset = start;
996 float xOffsetStepIncrement = this.topShearX * length / steps;
997 float yOffsetStepIncrement = this.topShearY * length / steps;
998
999 float percentOfPath = this.pathCutBegin;
1000 zOffset += percentOfPath;
1001
1002 // sanity checks
1003
1004 bool done = false;
1005
1006 while (!done)
1007 {
1008 PathNode newNode = new PathNode();
1009
1010 newNode.xScale = 1.0f;
1011 if (this.taperX == 0.0f)
1012 newNode.xScale = 1.0f;
1013 else if (this.taperX > 0.0f)
1014 newNode.xScale = 1.0f - percentOfPath * this.taperX;
1015 else newNode.xScale = 1.0f + (1.0f - percentOfPath) * this.taperX;
1016
1017 newNode.yScale = 1.0f;
1018 if (this.taperY == 0.0f)
1019 newNode.yScale = 1.0f;
1020 else if (this.taperY > 0.0f)
1021 newNode.yScale = 1.0f - percentOfPath * this.taperY;
1022 else newNode.yScale = 1.0f + (1.0f - percentOfPath) * this.taperY;
1023
1024 float twist = twistBegin + twistTotal * percentOfPath;
1025
1026 newNode.rotation = new Quat(new Coord(0.0f, 0.0f, 1.0f), twist);
1027 newNode.position = new Coord(xOffset, yOffset, zOffset);
1028 newNode.percentOfPath = percentOfPath;
1029
1030 pathNodes.Add(newNode);
1031
1032 if (step < steps)
1033 {
1034 step += 1;
1035 percentOfPath += percentOfPathMultiplier;
1036 xOffset += xOffsetStepIncrement;
1037 yOffset += yOffsetStepIncrement;
1038 zOffset += stepSize;
1039 if (percentOfPath > this.pathCutEnd)
1040 done = true;
1041 }
1042 else done = true;
1043 }
1044 } // end of linear path code
1045
1046 else // pathType == Circular
1047 {
1048 float twistTotal = twistEnd - twistBegin;
1049
1050 // if the profile has a lot of twist, add more layers otherwise the layers may overlap
1051 // and the resulting mesh may be quite inaccurate. This method is arbitrary and doesn't
1052 // accurately match the viewer
1053 float twistTotalAbs = Math.Abs(twistTotal);
1054 if (twistTotalAbs > 0.01f)
1055 {
1056 if (twistTotalAbs > Math.PI * 1.5f)
1057 steps *= 2;
1058 if (twistTotalAbs > Math.PI * 3.0f)
1059 steps *= 2;
1060 }
1061
1062 float yPathScale = this.holeSizeY * 0.5f;
1063 float pathLength = this.pathCutEnd - this.pathCutBegin;
1064 float totalSkew = this.skew * 2.0f * pathLength;
1065 float skewStart = this.pathCutBegin * 2.0f * this.skew - this.skew;
1066 float xOffsetTopShearXFactor = this.topShearX * (0.25f + 0.5f * (0.5f - this.holeSizeY));
1067 float yShearCompensation = 1.0f + Math.Abs(this.topShearY) * 0.25f;
1068
1069 // It's not quite clear what pushY (Y top shear) does, but subtracting it from the start and end
1070 // angles appears to approximate it's effects on path cut. Likewise, adding it to the angle used
1071 // to calculate the sine for generating the path radius appears to approximate it's effects there
1072 // too, but there are some subtle differences in the radius which are noticeable as the prim size
1073 // increases and it may affect megaprims quite a bit. The effect of the Y top shear parameter on
1074 // the meshes generated with this technique appear nearly identical in shape to the same prims when
1075 // displayed by the viewer.
1076
1077 float startAngle = (twoPi * this.pathCutBegin * this.revolutions) - this.topShearY * 0.9f;
1078 float endAngle = (twoPi * this.pathCutEnd * this.revolutions) - this.topShearY * 0.9f;
1079 float stepSize = twoPi / this.stepsPerRevolution;
1080
1081 int step = (int)(startAngle / stepSize);
1082 float angle = startAngle;
1083
1084 bool done = false;
1085 while (!done) // loop through the length of the path and add the layers
1086 {
1087 PathNode newNode = new PathNode();
1088
1089 float xProfileScale = (1.0f - Math.Abs(this.skew)) * this.holeSizeX;
1090 float yProfileScale = this.holeSizeY;
1091
1092 float percentOfPath = angle / (twoPi * this.revolutions);
1093 float percentOfAngles = (angle - startAngle) / (endAngle - startAngle);
1094
1095 if (this.taperX > 0.01f)
1096 xProfileScale *= 1.0f - percentOfPath * this.taperX;
1097 else if (this.taperX < -0.01f)
1098 xProfileScale *= 1.0f + (1.0f - percentOfPath) * this.taperX;
1099
1100 if (this.taperY > 0.01f)
1101 yProfileScale *= 1.0f - percentOfPath * this.taperY;
1102 else if (this.taperY < -0.01f)
1103 yProfileScale *= 1.0f + (1.0f - percentOfPath) * this.taperY;
1104
1105 newNode.xScale = xProfileScale;
1106 newNode.yScale = yProfileScale;
1107
1108 float radiusScale = 1.0f;
1109 if (this.radius > 0.001f)
1110 radiusScale = 1.0f - this.radius * percentOfPath;
1111 else if (this.radius < 0.001f)
1112 radiusScale = 1.0f + this.radius * (1.0f - percentOfPath);
1113
1114 float twist = twistBegin + twistTotal * percentOfPath;
1115
1116 float xOffset = 0.5f * (skewStart + totalSkew * percentOfAngles);
1117 xOffset += (float)Math.Sin(angle) * xOffsetTopShearXFactor;
1118
1119 float yOffset = yShearCompensation * (float)Math.Cos(angle) * (0.5f - yPathScale) * radiusScale;
1120
1121 float zOffset = (float)Math.Sin(angle + this.topShearY) * (0.5f - yPathScale) * radiusScale;
1122
1123 newNode.position = new Coord(xOffset, yOffset, zOffset);
1124
1125 // now orient the rotation of the profile layer relative to it's position on the path
1126 // adding taperY to the angle used to generate the quat appears to approximate the viewer
1127
1128 newNode.rotation = new Quat(new Coord(1.0f, 0.0f, 0.0f), angle + this.topShearY);
1129
1130 // next apply twist rotation to the profile layer
1131 if (twistTotal != 0.0f || twistBegin != 0.0f)
1132 newNode.rotation *= new Quat(new Coord(0.0f, 0.0f, 1.0f), twist);
1133
1134 newNode.percentOfPath = percentOfPath;
1135
1136 pathNodes.Add(newNode);
1137
1138 // calculate terms for next iteration
1139 // calculate the angle for the next iteration of the loop
1140
1141 if (angle >= endAngle - 0.01)
1142 done = true;
1143 else
1144 {
1145 step += 1;
1146 angle = stepSize * step;
1147 if (angle > endAngle)
1148 angle = endAngle;
1149 }
1150 }
1151 }
1152 }
1153 }
1154
1155 public class PrimMesh
1156 {
1157 public string errorMessage = "";
1158 private const float twoPi = 2.0f * (float)Math.PI;
1159
1160 public List<Coord> coords;
1161// public List<Coord> normals;
1162 public List<Face> faces;
1163
1164 private int sides = 4;
1165 private int hollowSides = 4;
1166 private float profileStart = 0.0f;
1167 private float profileEnd = 1.0f;
1168 private float hollow = 0.0f;
1169 public int twistBegin = 0;
1170 public int twistEnd = 0;
1171 public float topShearX = 0.0f;
1172 public float topShearY = 0.0f;
1173 public float pathCutBegin = 0.0f;
1174 public float pathCutEnd = 1.0f;
1175 public float dimpleBegin = 0.0f;
1176 public float dimpleEnd = 1.0f;
1177 public float skew = 0.0f;
1178 public float holeSizeX = 1.0f; // called pathScaleX in pbs
1179 public float holeSizeY = 0.25f;
1180 public float taperX = 0.0f;
1181 public float taperY = 0.0f;
1182 public float radius = 0.0f;
1183 public float revolutions = 1.0f;
1184 public int stepsPerRevolution = 24;
1185
1186 private bool hasProfileCut = false;
1187 private bool hasHollow = false;
1188
1189 public int numPrimFaces = 0;
1190
1191 /// <summary>
1192 /// Human readable string representation of the parameters used to create a mesh.
1193 /// </summary>
1194 /// <returns></returns>
1195 public string ParamsToDisplayString()
1196 {
1197 string s = "";
1198 s += "sides..................: " + this.sides.ToString();
1199 s += "\nhollowSides..........: " + this.hollowSides.ToString();
1200 s += "\nprofileStart.........: " + this.profileStart.ToString();
1201 s += "\nprofileEnd...........: " + this.profileEnd.ToString();
1202 s += "\nhollow...............: " + this.hollow.ToString();
1203 s += "\ntwistBegin...........: " + this.twistBegin.ToString();
1204 s += "\ntwistEnd.............: " + this.twistEnd.ToString();
1205 s += "\ntopShearX............: " + this.topShearX.ToString();
1206 s += "\ntopShearY............: " + this.topShearY.ToString();
1207 s += "\npathCutBegin.........: " + this.pathCutBegin.ToString();
1208 s += "\npathCutEnd...........: " + this.pathCutEnd.ToString();
1209 s += "\ndimpleBegin..........: " + this.dimpleBegin.ToString();
1210 s += "\ndimpleEnd............: " + this.dimpleEnd.ToString();
1211 s += "\nskew.................: " + this.skew.ToString();
1212 s += "\nholeSizeX............: " + this.holeSizeX.ToString();
1213 s += "\nholeSizeY............: " + this.holeSizeY.ToString();
1214 s += "\ntaperX...............: " + this.taperX.ToString();
1215 s += "\ntaperY...............: " + this.taperY.ToString();
1216 s += "\nradius...............: " + this.radius.ToString();
1217 s += "\nrevolutions..........: " + this.revolutions.ToString();
1218 s += "\nstepsPerRevolution...: " + this.stepsPerRevolution.ToString();
1219 s += "\nhasProfileCut........: " + this.hasProfileCut.ToString();
1220 s += "\nhasHollow............: " + this.hasHollow.ToString();
1221
1222 return s;
1223 }
1224
1225 public bool HasProfileCut
1226 {
1227 get { return hasProfileCut; }
1228 set { hasProfileCut = value; }
1229 }
1230
1231 public bool HasHollow
1232 {
1233 get { return hasHollow; }
1234 }
1235
1236
1237 /// <summary>
1238 /// Constructs a PrimMesh object and creates the profile for extrusion.
1239 /// </summary>
1240 /// <param name="sides"></param>
1241 /// <param name="profileStart"></param>
1242 /// <param name="profileEnd"></param>
1243 /// <param name="hollow"></param>
1244 /// <param name="hollowSides"></param>
1245 /// <param name="sphereMode"></param>
1246 public PrimMesh(int sides, float profileStart, float profileEnd, float hollow, int hollowSides)
1247 {
1248 this.coords = new List<Coord>();
1249 this.faces = new List<Face>();
1250
1251 this.sides = sides;
1252 this.profileStart = profileStart;
1253 this.profileEnd = profileEnd;
1254 this.hollow = hollow;
1255 this.hollowSides = hollowSides;
1256
1257 if (sides < 3)
1258 this.sides = 3;
1259 if (hollowSides < 3)
1260 this.hollowSides = 3;
1261 if (profileStart < 0.0f)
1262 this.profileStart = 0.0f;
1263 if (profileEnd > 1.0f)
1264 this.profileEnd = 1.0f;
1265 if (profileEnd < 0.02f)
1266 this.profileEnd = 0.02f;
1267 if (profileStart >= profileEnd)
1268 this.profileStart = profileEnd - 0.02f;
1269 if (hollow > 0.99f)
1270 this.hollow = 0.99f;
1271 if (hollow < 0.0f)
1272 this.hollow = 0.0f;
1273 }
1274
1275 /// <summary>
1276 /// Extrudes a profile along a path.
1277 /// </summary>
1278 public void Extrude(PathType pathType)
1279 {
1280 bool needEndFaces = false;
1281
1282 this.coords = new List<Coord>();
1283 this.faces = new List<Face>();
1284
1285 int steps = 1;
1286
1287 float length = this.pathCutEnd - this.pathCutBegin;
1288
1289 this.hasProfileCut = this.profileEnd - this.profileStart < 0.9999f;
1290
1291 this.hasHollow = (this.hollow > 0.001f);
1292
1293 float twistBegin = this.twistBegin / 360.0f * twoPi;
1294 float twistEnd = this.twistEnd / 360.0f * twoPi;
1295 float twistTotal = twistEnd - twistBegin;
1296 float twistTotalAbs = Math.Abs(twistTotal);
1297 if (twistTotalAbs > 0.01f)
1298 steps += (int)(twistTotalAbs * 3.66); // dahlia's magic number
1299
1300 float hollow = this.hollow;
1301
1302 if (pathType == PathType.Circular)
1303 {
1304 needEndFaces = false;
1305 if (this.pathCutBegin != 0.0f || this.pathCutEnd != 1.0f)
1306 needEndFaces = true;
1307 else if (this.taperX != 0.0f || this.taperY != 0.0f)
1308 needEndFaces = true;
1309 else if (this.skew != 0.0f)
1310 needEndFaces = true;
1311 else if (twistTotal != 0.0f)
1312 needEndFaces = true;
1313 else if (this.radius != 0.0f)
1314 needEndFaces = true;
1315 }
1316 else needEndFaces = true;
1317
1318 // sanity checks
1319 float initialProfileRot = 0.0f;
1320 if (pathType == PathType.Circular)
1321 {
1322 if (this.sides == 3)
1323 {
1324 initialProfileRot = (float)Math.PI;
1325 if (this.hollowSides == 4)
1326 {
1327 if (hollow > 0.7f)
1328 hollow = 0.7f;
1329 hollow *= 0.707f;
1330 }
1331 else hollow *= 0.5f;
1332 }
1333 else if (this.sides == 4)
1334 {
1335 initialProfileRot = 0.25f * (float)Math.PI;
1336 if (this.hollowSides != 4)
1337 hollow *= 0.707f;
1338 }
1339 else if (this.sides > 4)
1340 {
1341 initialProfileRot = (float)Math.PI;
1342 if (this.hollowSides == 4)
1343 {
1344 if (hollow > 0.7f)
1345 hollow = 0.7f;
1346 hollow /= 0.7f;
1347 }
1348 }
1349 }
1350 else
1351 {
1352 if (this.sides == 3)
1353 {
1354 if (this.hollowSides == 4)
1355 {
1356 if (hollow > 0.7f)
1357 hollow = 0.7f;
1358 hollow *= 0.707f;
1359 }
1360 else hollow *= 0.5f;
1361 }
1362 else if (this.sides == 4)
1363 {
1364 initialProfileRot = 1.25f * (float)Math.PI;
1365 if (this.hollowSides != 4)
1366 hollow *= 0.707f;
1367 }
1368 else if (this.sides == 24 && this.hollowSides == 4)
1369 hollow *= 1.414f;
1370 }
1371
1372 Profile profile = new Profile(this.sides, this.profileStart, this.profileEnd, hollow, this.hollowSides, this.hasProfileCut,true);
1373 this.errorMessage = profile.errorMessage;
1374
1375 this.numPrimFaces = profile.numPrimFaces;
1376
1377 if (initialProfileRot != 0.0f)
1378 {
1379 profile.AddRot(new Quat(new Coord(0.0f, 0.0f, 1.0f), initialProfileRot));
1380 }
1381
1382 float thisV = 0.0f;
1383 float lastV = 0.0f;
1384
1385 Path path = new Path();
1386 path.twistBegin = twistBegin;
1387 path.twistEnd = twistEnd;
1388 path.topShearX = topShearX;
1389 path.topShearY = topShearY;
1390 path.pathCutBegin = pathCutBegin;
1391 path.pathCutEnd = pathCutEnd;
1392 path.dimpleBegin = dimpleBegin;
1393 path.dimpleEnd = dimpleEnd;
1394 path.skew = skew;
1395 path.holeSizeX = holeSizeX;
1396 path.holeSizeY = holeSizeY;
1397 path.taperX = taperX;
1398 path.taperY = taperY;
1399 path.radius = radius;
1400 path.revolutions = revolutions;
1401 path.stepsPerRevolution = stepsPerRevolution;
1402
1403 path.Create(pathType, steps);
1404
1405 int lastNode = path.pathNodes.Count -1;
1406
1407 for (int nodeIndex = 0; nodeIndex < path.pathNodes.Count; nodeIndex++)
1408 {
1409 PathNode node = path.pathNodes[nodeIndex];
1410 Profile newLayer = profile.Copy();
1411
1412 newLayer.Scale(node.xScale, node.yScale);
1413 newLayer.AddRot(node.rotation);
1414 newLayer.AddPos(node.position);
1415
1416 if (needEndFaces && nodeIndex == 0)
1417 {
1418 newLayer.FlipNormals();
1419 } // if (nodeIndex == 0)
1420
1421 // append this layer
1422
1423 int coordsLen = this.coords.Count;
1424 newLayer.AddValue2FaceVertexIndices(coordsLen);
1425
1426 this.coords.AddRange(newLayer.coords);
1427
1428 if (needEndFaces)
1429 {
1430 if (nodeIndex == 0)
1431 this.faces.AddRange(newLayer.faces);
1432 else if (nodeIndex == lastNode)
1433 {
1434 if (node.xScale > 1e-6 && node.yScale > 1e-6)
1435 this.faces.AddRange(newLayer.faces);
1436 }
1437 }
1438
1439 // fill faces between layers
1440
1441 int numVerts = newLayer.coords.Count;
1442 Face newFace1 = new Face();
1443 Face newFace2 = new Face();
1444
1445 thisV = 1.0f - node.percentOfPath;
1446
1447 if (nodeIndex > 0)
1448 {
1449 int startVert = coordsLen;
1450 int endVert = this.coords.Count;
1451 if (!this.hasProfileCut)
1452 {
1453 int i = startVert;
1454 for (int l = 0; l < profile.numOuterVerts - 1; l++)
1455 {
1456 newFace1.v1 = i;
1457 newFace1.v2 = i - numVerts;
1458 newFace1.v3 = i + 1;
1459 this.faces.Add(newFace1);
1460
1461 newFace2.v1 = i + 1;
1462 newFace2.v2 = i - numVerts;
1463 newFace2.v3 = i + 1 - numVerts;
1464 this.faces.Add(newFace2);
1465 i++;
1466 }
1467
1468 newFace1.v1 = i;
1469 newFace1.v2 = i - numVerts;
1470 newFace1.v3 = startVert;
1471 this.faces.Add(newFace1);
1472
1473 newFace2.v1 = startVert;
1474 newFace2.v2 = i - numVerts;
1475 newFace2.v3 = startVert - numVerts;
1476 this.faces.Add(newFace2);
1477
1478 if (this.hasHollow)
1479 {
1480 startVert = ++i;
1481 for (int l = 0; l < profile.numHollowVerts - 1; l++)
1482 {
1483 newFace1.v1 = i;
1484 newFace1.v2 = i - numVerts;
1485 newFace1.v3 = i + 1;
1486 this.faces.Add(newFace1);
1487
1488 newFace2.v1 = i + 1;
1489 newFace2.v2 = i - numVerts;
1490 newFace2.v3 = i + 1 - numVerts;
1491 this.faces.Add(newFace2);
1492 i++;
1493 }
1494
1495 newFace1.v1 = i;
1496 newFace1.v2 = i - numVerts;
1497 newFace1.v3 = startVert;
1498 this.faces.Add(newFace1);
1499
1500 newFace2.v1 = startVert;
1501 newFace2.v2 = i - numVerts;
1502 newFace2.v3 = startVert - numVerts;
1503 this.faces.Add(newFace2);
1504 }
1505
1506
1507 }
1508 else
1509 {
1510 for (int i = startVert; i < endVert; i++)
1511 {
1512 int iNext = i + 1;
1513 if (i == endVert - 1)
1514 iNext = startVert;
1515
1516 newFace1.v1 = i;
1517 newFace1.v2 = i - numVerts;
1518 newFace1.v3 = iNext;
1519 this.faces.Add(newFace1);
1520
1521 newFace2.v1 = iNext;
1522 newFace2.v2 = i - numVerts;
1523 newFace2.v3 = iNext - numVerts;
1524 this.faces.Add(newFace2);
1525
1526 }
1527 }
1528 }
1529
1530 lastV = thisV;
1531
1532 } // for (int nodeIndex = 0; nodeIndex < path.pathNodes.Count; nodeIndex++)
1533
1534 }
1535
1536
1537 /// <summary>
1538 /// DEPRICATED - use Extrude(PathType.Linear) instead
1539 /// Extrudes a profile along a straight line path. Used for prim types box, cylinder, and prism.
1540 /// </summary>
1541 ///
1542 public void ExtrudeLinear()
1543 {
1544 this.Extrude(PathType.Linear);
1545 }
1546
1547
1548 /// <summary>
1549 /// DEPRICATED - use Extrude(PathType.Circular) instead
1550 /// Extrude a profile into a circular path prim mesh. Used for prim types torus, tube, and ring.
1551 /// </summary>
1552 ///
1553 public void ExtrudeCircular()
1554 {
1555 this.Extrude(PathType.Circular);
1556 }
1557
1558
1559 private Coord SurfaceNormal(Coord c1, Coord c2, Coord c3)
1560 {
1561 Coord edge1 = new Coord(c2.X - c1.X, c2.Y - c1.Y, c2.Z - c1.Z);
1562 Coord edge2 = new Coord(c3.X - c1.X, c3.Y - c1.Y, c3.Z - c1.Z);
1563
1564 Coord normal = Coord.Cross(edge1, edge2);
1565
1566 normal.Normalize();
1567
1568 return normal;
1569 }
1570
1571 private Coord SurfaceNormal(Face face)
1572 {
1573 return SurfaceNormal(this.coords[face.v1], this.coords[face.v2], this.coords[face.v3]);
1574 }
1575
1576 /// <summary>
1577 /// Calculate the surface normal for a face in the list of faces
1578 /// </summary>
1579 /// <param name="faceIndex"></param>
1580 /// <returns></returns>
1581 public Coord SurfaceNormal(int faceIndex)
1582 {
1583 int numFaces = this.faces.Count;
1584 if (faceIndex < 0 || faceIndex >= numFaces)
1585 throw new Exception("faceIndex out of range");
1586
1587 return SurfaceNormal(this.faces[faceIndex]);
1588 }
1589
1590 /// <summary>
1591 /// Duplicates a PrimMesh object. All object properties are copied by value, including lists.
1592 /// </summary>
1593 /// <returns></returns>
1594 public PrimMesh Copy()
1595 {
1596 PrimMesh copy = new PrimMesh(this.sides, this.profileStart, this.profileEnd, this.hollow, this.hollowSides);
1597 copy.twistBegin = this.twistBegin;
1598 copy.twistEnd = this.twistEnd;
1599 copy.topShearX = this.topShearX;
1600 copy.topShearY = this.topShearY;
1601 copy.pathCutBegin = this.pathCutBegin;
1602 copy.pathCutEnd = this.pathCutEnd;
1603 copy.dimpleBegin = this.dimpleBegin;
1604 copy.dimpleEnd = this.dimpleEnd;
1605 copy.skew = this.skew;
1606 copy.holeSizeX = this.holeSizeX;
1607 copy.holeSizeY = this.holeSizeY;
1608 copy.taperX = this.taperX;
1609 copy.taperY = this.taperY;
1610 copy.radius = this.radius;
1611 copy.revolutions = this.revolutions;
1612 copy.stepsPerRevolution = this.stepsPerRevolution;
1613
1614 copy.numPrimFaces = this.numPrimFaces;
1615 copy.errorMessage = this.errorMessage;
1616
1617 copy.coords = new List<Coord>(this.coords);
1618 copy.faces = new List<Face>(this.faces);
1619
1620 return copy;
1621 }
1622
1623 /// <summary>
1624 /// Adds a value to each XYZ vertex coordinate in the mesh
1625 /// </summary>
1626 /// <param name="x"></param>
1627 /// <param name="y"></param>
1628 /// <param name="z"></param>
1629 public void AddPos(float x, float y, float z)
1630 {
1631 int i;
1632 int numVerts = this.coords.Count;
1633 Coord vert;
1634
1635 for (i = 0; i < numVerts; i++)
1636 {
1637 vert = this.coords[i];
1638 vert.X += x;
1639 vert.Y += y;
1640 vert.Z += z;
1641 this.coords[i] = vert;
1642 }
1643 }
1644
1645 /// <summary>
1646 /// Rotates the mesh
1647 /// </summary>
1648 /// <param name="q"></param>
1649 public void AddRot(Quat q)
1650 {
1651 int i;
1652 int numVerts = this.coords.Count;
1653
1654 for (i = 0; i < numVerts; i++)
1655 this.coords[i] *= q;
1656 }
1657
1658#if VERTEX_INDEXER
1659 public VertexIndexer GetVertexIndexer()
1660 {
1661 return null;
1662 }
1663#endif
1664
1665 /// <summary>
1666 /// Scales the mesh
1667 /// </summary>
1668 /// <param name="x"></param>
1669 /// <param name="y"></param>
1670 /// <param name="z"></param>
1671 public void Scale(float x, float y, float z)
1672 {
1673 int i;
1674 int numVerts = this.coords.Count;
1675 //Coord vert;
1676
1677 Coord m = new Coord(x, y, z);
1678 for (i = 0; i < numVerts; i++)
1679 this.coords[i] *= m;
1680 }
1681
1682 /// <summary>
1683 /// Dumps the mesh to a Blender compatible "Raw" format file
1684 /// </summary>
1685 /// <param name="path"></param>
1686 /// <param name="name"></param>
1687 /// <param name="title"></param>
1688 public void DumpRaw(String path, String name, String title)
1689 {
1690 if (path == null)
1691 return;
1692 String fileName = name + "_" + title + ".raw";
1693 String completePath = System.IO.Path.Combine(path, fileName);
1694 StreamWriter sw = new StreamWriter(completePath);
1695
1696 for (int i = 0; i < this.faces.Count; i++)
1697 {
1698 string s = this.coords[this.faces[i].v1].ToString();
1699 s += " " + this.coords[this.faces[i].v2].ToString();
1700 s += " " + this.coords[this.faces[i].v3].ToString();
1701
1702 sw.WriteLine(s);
1703 }
1704
1705 sw.Close();
1706 }
1707 }
1708}
diff --git a/OpenSim/Region/PhysicsModules/ubOdeMeshing/Properties/AssemblyInfo.cs b/OpenSim/Region/PhysicsModules/ubOdeMeshing/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..91df7ab
--- /dev/null
+++ b/OpenSim/Region/PhysicsModules/ubOdeMeshing/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
1using System.Reflection;
2using System.Runtime.CompilerServices;
3using System.Runtime.InteropServices;
4using Mono.Addins;
5
6// General Information about an assembly is controlled through the following
7// set of attributes. Change these attribute values to modify the information
8// associated with an assembly.
9[assembly: AssemblyTitle("OpenSim.Region.PhysicsModule.ubODEMeshing")]
10[assembly: AssemblyDescription("Mesher for ubODE")]
11[assembly: AssemblyConfiguration("")]
12[assembly: AssemblyCompany("http://opensimulator.org")]
13[assembly: AssemblyProduct("OpenSim")]
14[assembly: AssemblyCopyright("OpenSimulator developers")]
15[assembly: AssemblyTrademark("")]
16[assembly: AssemblyCulture("")]
17
18// Setting ComVisible to false makes the types in this assembly not visible
19// to COM components. If you need to access a type in this assembly from
20// COM, set the ComVisible attribute to true on that type.
21[assembly: ComVisible(false)]
22
23// The following GUID is for the ID of the typelib if this project is exposed to COM
24[assembly: Guid("4b7e35c2-a9dd-4b10-b778-eb417f4f6884")]
25
26// Version information for an assembly consists of the following four values:
27//
28// Major Version
29// Minor Version
30// Build Number
31// Revision
32//
33[assembly: AssemblyVersion("0.8.2.*")]
34
35[assembly: Addin("OpenSim.Region.PhysicsModule.ubOdeMeshing", OpenSim.VersionInfo.VersionNumber)]
36[assembly: AddinDependency("OpenSim.Region.Framework", OpenSim.VersionInfo.VersionNumber)]
diff --git a/OpenSim/Region/PhysicsModules/ubOdeMeshing/SculptMap.cs b/OpenSim/Region/PhysicsModules/ubOdeMeshing/SculptMap.cs
new file mode 100644
index 0000000..1c75db6
--- /dev/null
+++ b/OpenSim/Region/PhysicsModules/ubOdeMeshing/SculptMap.cs
@@ -0,0 +1,244 @@
1/*
2 * Copyright (c) Contributors
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Text;
31
32using System.Drawing;
33using System.Drawing.Imaging;
34
35namespace PrimMesher
36{
37 public class SculptMap
38 {
39 public int width;
40 public int height;
41 public byte[] redBytes;
42 public byte[] greenBytes;
43 public byte[] blueBytes;
44
45 public SculptMap()
46 {
47 }
48
49 public SculptMap(Bitmap bm, int lod)
50 {
51 int bmW = bm.Width;
52 int bmH = bm.Height;
53
54 if (bmW == 0 || bmH == 0)
55 throw new Exception("SculptMap: bitmap has no data");
56
57 int numLodPixels = lod * lod; // (32 * 2)^2 = 64^2 pixels for default sculpt map image
58
59 bool needsScaling = false;
60 bool smallMap = false;
61
62 width = bmW;
63 height = bmH;
64
65 while (width * height > numLodPixels * 4)
66 {
67 width >>= 1;
68 height >>= 1;
69 needsScaling = true;
70 }
71
72 try
73 {
74 if (needsScaling)
75 bm = ScaleImage(bm, width, height);
76 }
77
78 catch (Exception e)
79 {
80 throw new Exception("Exception in ScaleImage(): e: " + e.ToString());
81 }
82
83 if (width * height > numLodPixels)
84 {
85 smallMap = false;
86 width >>= 1;
87 height >>= 1;
88 }
89 else
90 smallMap = true;
91
92 int numBytes = (width + 1) * (height + 1);
93 redBytes = new byte[numBytes];
94 greenBytes = new byte[numBytes];
95 blueBytes = new byte[numBytes];
96
97 int byteNdx = 0;
98 Color c;
99
100 try
101 {
102 for (int y = 0; y <= height; y++)
103 {
104 for (int x = 0; x < width; x++)
105 {
106 if (smallMap)
107 c = bm.GetPixel(x, y < height ? y : y - 1);
108 else
109 c = bm.GetPixel(x * 2, y < height ? y * 2 : y * 2 - 1);
110
111 redBytes[byteNdx] = c.R;
112 greenBytes[byteNdx] = c.G;
113 blueBytes[byteNdx] = c.B;
114
115 ++byteNdx;
116 }
117
118 if (smallMap)
119 c = bm.GetPixel(width - 1, y < height ? y : y - 1);
120 else
121 c = bm.GetPixel(width * 2 - 1, y < height ? y * 2 : y * 2 - 1);
122
123 redBytes[byteNdx] = c.R;
124 greenBytes[byteNdx] = c.G;
125 blueBytes[byteNdx] = c.B;
126
127 ++byteNdx;
128 }
129 }
130 catch (Exception e)
131 {
132 throw new Exception("Caught exception processing byte arrays in SculptMap(): e: " + e.ToString());
133 }
134
135 width++;
136 height++;
137 }
138
139 public List<List<Coord>> ToRows(bool mirror)
140 {
141 int numRows = height;
142 int numCols = width;
143
144 List<List<Coord>> rows = new List<List<Coord>>(numRows);
145
146 float pixScale = 1.0f / 255;
147
148 int rowNdx, colNdx;
149 int smNdx = 0;
150
151 for (rowNdx = 0; rowNdx < numRows; rowNdx++)
152 {
153 List<Coord> row = new List<Coord>(numCols);
154 for (colNdx = 0; colNdx < numCols; colNdx++)
155 {
156
157 if (mirror)
158 row.Add(new Coord(-((float)redBytes[smNdx] * pixScale - 0.5f), ((float)greenBytes[smNdx] * pixScale - 0.5f), (float)blueBytes[smNdx] * pixScale - 0.5f));
159 else
160 row.Add(new Coord((float)redBytes[smNdx] * pixScale - 0.5f, (float)greenBytes[smNdx] * pixScale - 0.5f, (float)blueBytes[smNdx] * pixScale - 0.5f));
161
162 ++smNdx;
163 }
164 rows.Add(row);
165 }
166 return rows;
167 }
168
169 private Bitmap ScaleImage(Bitmap srcImage, int destWidth, int destHeight)
170 {
171
172 Bitmap scaledImage = new Bitmap(destWidth, destHeight, PixelFormat.Format24bppRgb);
173
174 Color c;
175
176
177 // will let last step to be eventually diferent, as seems to be in sl
178
179 float xscale = (float)srcImage.Width / (float)destWidth;
180 float yscale = (float)srcImage.Height / (float)destHeight;
181
182 int lastsx = srcImage.Width - 1;
183 int lastsy = srcImage.Height - 1;
184 int lastdx = destWidth - 1;
185 int lastdy = destHeight - 1;
186
187 float sy = 0.5f;
188 float sx;
189
190 for (int y = 0; y < lastdy; y++)
191 {
192 sx = 0.5f;
193 for (int x = 0; x < lastdx; x++)
194 {
195 try
196 {
197 c = srcImage.GetPixel((int)(sx), (int)(sy));
198 scaledImage.SetPixel(x, y, Color.FromArgb(c.R, c.G, c.B));
199 }
200 catch (IndexOutOfRangeException)
201 {
202 }
203 sx += xscale;
204 }
205 try
206 {
207 c = srcImage.GetPixel(lastsx, (int)(sy));
208 scaledImage.SetPixel(lastdx, y, Color.FromArgb(c.R, c.G, c.B));
209 }
210 catch (IndexOutOfRangeException)
211 {
212 }
213
214 sy += yscale;
215 }
216
217 sx = 0.5f;
218 for (int x = 0; x < lastdx; x++)
219 {
220 try
221 {
222 c = srcImage.GetPixel((int)(sx), lastsy);
223 scaledImage.SetPixel(x, lastdy, Color.FromArgb(c.R, c.G, c.B));
224 }
225 catch (IndexOutOfRangeException)
226 {
227 }
228
229 sx += xscale;
230 }
231 try
232 {
233 c = srcImage.GetPixel(lastsx, lastsy);
234 scaledImage.SetPixel(lastdx, lastdy, Color.FromArgb(c.R, c.G, c.B));
235 }
236 catch (IndexOutOfRangeException)
237 {
238 }
239
240 srcImage.Dispose();
241 return scaledImage;
242 }
243 }
244} \ No newline at end of file
diff --git a/OpenSim/Region/PhysicsModules/ubOdeMeshing/SculptMesh.cs b/OpenSim/Region/PhysicsModules/ubOdeMeshing/SculptMesh.cs
new file mode 100644
index 0000000..bc1375b
--- /dev/null
+++ b/OpenSim/Region/PhysicsModules/ubOdeMeshing/SculptMesh.cs
@@ -0,0 +1,220 @@
1/*
2 * Copyright (c) Contributors
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Text;
31using System.IO;
32
33using System.Drawing;
34using System.Drawing.Imaging;
35
36namespace PrimMesher
37{
38
39 public class SculptMesh
40 {
41 public List<Coord> coords;
42 public List<Face> faces;
43
44 public enum SculptType { sphere = 1, torus = 2, plane = 3, cylinder = 4 };
45
46
47 public SculptMesh(Bitmap sculptBitmap, SculptType sculptType, int lod, bool mirror, bool invert)
48 {
49 if (mirror)
50 invert = !invert;
51
52 SculptMap smap = new SculptMap(sculptBitmap, lod);
53
54 List<List<Coord>> rows = smap.ToRows(mirror);
55
56 _SculptMesh(rows, sculptType, invert);
57 }
58
59 private void _SculptMesh(List<List<Coord>> rows, SculptType sculptType, bool invert)
60 {
61 coords = new List<Coord>();
62 faces = new List<Face>();
63
64 sculptType = (SculptType)(((int)sculptType) & 0x07);
65
66 int width = rows[0].Count;
67
68 int p1, p2, p3, p4;
69
70 int imageX, imageY;
71
72 if (sculptType != SculptType.plane)
73 {
74 if (rows.Count % 2 == 0)
75 {
76 for (int rowNdx = 0; rowNdx < rows.Count; rowNdx++)
77 rows[rowNdx].Add(rows[rowNdx][0]);
78 }
79 else
80 {
81 int lastIndex = rows[0].Count - 1;
82
83 for (int i = 0; i < rows.Count; i++)
84 rows[i][0] = rows[i][lastIndex];
85 }
86 }
87
88 Coord topPole = rows[0][width / 2];
89 Coord bottomPole = rows[rows.Count - 1][width / 2];
90
91 if (sculptType == SculptType.sphere)
92 {
93 if (rows.Count % 2 == 0)
94 {
95 int count = rows[0].Count;
96 List<Coord> topPoleRow = new List<Coord>(count);
97 List<Coord> bottomPoleRow = new List<Coord>(count);
98
99 for (int i = 0; i < count; i++)
100 {
101 topPoleRow.Add(topPole);
102 bottomPoleRow.Add(bottomPole);
103 }
104 rows.Insert(0, topPoleRow);
105 rows.Add(bottomPoleRow);
106 }
107 else
108 {
109 int count = rows[0].Count;
110
111 List<Coord> topPoleRow = rows[0];
112 List<Coord> bottomPoleRow = rows[rows.Count - 1];
113
114 for (int i = 0; i < count; i++)
115 {
116 topPoleRow[i] = topPole;
117 bottomPoleRow[i] = bottomPole;
118 }
119 }
120 }
121
122 if (sculptType == SculptType.torus)
123 rows.Add(rows[0]);
124
125 int coordsDown = rows.Count;
126 int coordsAcross = rows[0].Count;
127
128 float widthUnit = 1.0f / (coordsAcross - 1);
129 float heightUnit = 1.0f / (coordsDown - 1);
130
131 for (imageY = 0; imageY < coordsDown; imageY++)
132 {
133 int rowOffset = imageY * coordsAcross;
134
135 for (imageX = 0; imageX < coordsAcross; imageX++)
136 {
137 /*
138 * p1-----p2
139 * | \ f2 |
140 * | \ |
141 * | f1 \|
142 * p3-----p4
143 */
144
145 p4 = rowOffset + imageX;
146 p3 = p4 - 1;
147
148 p2 = p4 - coordsAcross;
149 p1 = p3 - coordsAcross;
150
151 this.coords.Add(rows[imageY][imageX]);
152
153 if (imageY > 0 && imageX > 0)
154 {
155 Face f1, f2;
156
157 if (invert)
158 {
159 f1 = new Face(p1, p4, p3);
160 f2 = new Face(p1, p2, p4);
161 }
162 else
163 {
164 f1 = new Face(p1, p3, p4);
165 f2 = new Face(p1, p4, p2);
166 }
167
168 this.faces.Add(f1);
169 this.faces.Add(f2);
170 }
171 }
172 }
173 }
174
175 /// <summary>
176 /// Duplicates a SculptMesh object. All object properties are copied by value, including lists.
177 /// </summary>
178 /// <returns></returns>
179 public SculptMesh Copy()
180 {
181 return new SculptMesh(this);
182 }
183
184 public SculptMesh(SculptMesh sm)
185 {
186 coords = new List<Coord>(sm.coords);
187 faces = new List<Face>(sm.faces);
188 }
189
190 public void Scale(float x, float y, float z)
191 {
192 int i;
193 int numVerts = this.coords.Count;
194
195 Coord m = new Coord(x, y, z);
196 for (i = 0; i < numVerts; i++)
197 this.coords[i] *= m;
198 }
199
200 public void DumpRaw(String path, String name, String title)
201 {
202 if (path == null)
203 return;
204 String fileName = name + "_" + title + ".raw";
205 String completePath = System.IO.Path.Combine(path, fileName);
206 StreamWriter sw = new StreamWriter(completePath);
207
208 for (int i = 0; i < this.faces.Count; i++)
209 {
210 string s = this.coords[this.faces[i].v1].ToString();
211 s += " " + this.coords[this.faces[i].v2].ToString();
212 s += " " + this.coords[this.faces[i].v3].ToString();
213
214 sw.WriteLine(s);
215 }
216
217 sw.Close();
218 }
219 }
220}