/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs
C# | 3758 lines | 2460 code | 479 blank | 819 comment | 478 complexity | 171260a727b01f2dffc7410dfb31181e MD5 | raw file
Possible License(s): BSD-3-Clause
Large files files are truncated, but you can click here to view the full file
- /*
- * Copyright (c) Contributors, http://opensimulator.org/
- * See CONTRIBUTORS.TXT for a full list of copyright holders.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of the OpenSimulator Project nor the
- * names of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- //#define USE_DRAWSTUFF
- using System;
- using System.Collections.Generic;
- using System.Reflection;
- using System.Runtime.InteropServices;
- using System.Threading;
- using System.IO;
- using System.Diagnostics;
- using log4net;
- using Nini.Config;
- using Ode.NET;
- #if USE_DRAWSTUFF
- using Drawstuff.NET;
- #endif
- using OpenSim.Framework;
- using OpenSim.Region.Physics.Manager;
- using OpenMetaverse;
- //using OpenSim.Region.Physics.OdePlugin.Meshing;
- namespace OpenSim.Region.Physics.OdePlugin
- {
- /// <summary>
- /// ODE plugin
- /// </summary>
- public class OdePlugin : IPhysicsPlugin
- {
- //private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
- private CollisionLocker ode;
- private OdeScene _mScene;
- public OdePlugin()
- {
- ode = new CollisionLocker();
- }
- public bool Init()
- {
- return true;
- }
- public PhysicsScene GetScene(String sceneIdentifier)
- {
- if (_mScene == null)
- {
- // Initializing ODE only when a scene is created allows alternative ODE plugins to co-habit (according to
- // http://opensimulator.org/mantis/view.php?id=2750).
- d.InitODE();
-
- _mScene = new OdeScene(ode, sceneIdentifier);
- }
- return (_mScene);
- }
- public string GetName()
- {
- return ("OpenDynamicsEngine");
- }
- public void Dispose()
- {
- }
- }
- public enum StatusIndicators : int
- {
- Generic = 0,
- Start = 1,
- End = 2
- }
- public struct sCollisionData
- {
- public uint ColliderLocalId;
- public uint CollidedWithLocalId;
- public int NumberOfCollisions;
- public int CollisionType;
- public int StatusIndicator;
- public int lastframe;
- }
- [Flags]
- public enum CollisionCategories : int
- {
- Disabled = 0,
- Geom = 0x00000001,
- Body = 0x00000002,
- Space = 0x00000004,
- Character = 0x00000008,
- Land = 0x00000010,
- Water = 0x00000020,
- Wind = 0x00000040,
- Sensor = 0x00000080,
- Selected = 0x00000100
- }
- /// <summary>
- /// Material type for a primitive
- /// </summary>
- public enum Material : int
- {
- /// <summary></summary>
- Stone = 0,
- /// <summary></summary>
- Metal = 1,
- /// <summary></summary>
- Glass = 2,
- /// <summary></summary>
- Wood = 3,
- /// <summary></summary>
- Flesh = 4,
- /// <summary></summary>
- Plastic = 5,
- /// <summary></summary>
- Rubber = 6
- }
- public sealed class OdeScene : PhysicsScene
- {
- private readonly ILog m_log;
- // private Dictionary<string, sCollisionData> m_storedCollisions = new Dictionary<string, sCollisionData>();
- CollisionLocker ode;
- private Random fluidRandomizer = new Random(Environment.TickCount);
- private const uint m_regionWidth = Constants.RegionSize;
- private const uint m_regionHeight = Constants.RegionSize;
- private float ODE_STEPSIZE = 0.020f;
- private float metersInSpace = 29.9f;
- private float m_timeDilation = 1.0f;
- public float gravityx = 0f;
- public float gravityy = 0f;
- public float gravityz = -9.8f;
- private float contactsurfacelayer = 0.001f;
- private int worldHashspaceLow = -4;
- private int worldHashspaceHigh = 128;
- private int smallHashspaceLow = -4;
- private int smallHashspaceHigh = 66;
- private float waterlevel = 0f;
- private int framecount = 0;
- //private int m_returncollisions = 10;
- private readonly IntPtr contactgroup;
- internal IntPtr LandGeom;
- internal IntPtr WaterGeom;
- private float nmTerrainContactFriction = 255.0f;
- private float nmTerrainContactBounce = 0.1f;
- private float nmTerrainContactERP = 0.1025f;
- private float mTerrainContactFriction = 75f;
- private float mTerrainContactBounce = 0.1f;
- private float mTerrainContactERP = 0.05025f;
- private float nmAvatarObjectContactFriction = 250f;
- private float nmAvatarObjectContactBounce = 0.1f;
- private float mAvatarObjectContactFriction = 75f;
- private float mAvatarObjectContactBounce = 0.1f;
- private float avPIDD = 3200f;
- private float avPIDP = 1400f;
- private float avCapRadius = 0.37f;
- private float avStandupTensor = 2000000f;
- private bool avCapsuleTilted = true; // true = old compatibility mode with leaning capsule; false = new corrected mode
- public bool IsAvCapsuleTilted { get { return avCapsuleTilted; } set { avCapsuleTilted = value; } }
- private float avDensity = 80f;
- private float avHeightFudgeFactor = 0.52f;
- private float avMovementDivisorWalk = 1.3f;
- private float avMovementDivisorRun = 0.8f;
- private float minimumGroundFlightOffset = 3f;
- public float maximumMassObject = 10000.01f;
- public bool meshSculptedPrim = true;
- public bool forceSimplePrimMeshing = false;
- public float meshSculptLOD = 32;
- public float MeshSculptphysicalLOD = 16;
- public float geomDefaultDensity = 10.000006836f;
- public int geomContactPointsStartthrottle = 3;
- public int geomUpdatesPerThrottledUpdate = 15;
- public float bodyPIDD = 35f;
- public float bodyPIDG = 25;
- public int geomCrossingFailuresBeforeOutofbounds = 5;
- public float bodyMotorJointMaxforceTensor = 2;
- public int bodyFramesAutoDisable = 20;
-
- private float[] _watermap;
- private bool m_filterCollisions = true;
- private d.NearCallback nearCallback;
- public d.TriCallback triCallback;
- public d.TriArrayCallback triArrayCallback;
- private readonly HashSet<OdeCharacter> _characters = new HashSet<OdeCharacter>();
- private readonly HashSet<OdePrim> _prims = new HashSet<OdePrim>();
- private readonly HashSet<OdePrim> _activeprims = new HashSet<OdePrim>();
- private readonly HashSet<OdePrim> _taintedPrimH = new HashSet<OdePrim>();
- private readonly Object _taintedPrimLock = new Object();
- private readonly List<OdePrim> _taintedPrimL = new List<OdePrim>();
- private readonly HashSet<OdeCharacter> _taintedActors = new HashSet<OdeCharacter>();
- private readonly List<d.ContactGeom> _perloopContact = new List<d.ContactGeom>();
- private readonly List<PhysicsActor> _collisionEventPrim = new List<PhysicsActor>();
- private readonly HashSet<OdeCharacter> _badCharacter = new HashSet<OdeCharacter>();
- public Dictionary<IntPtr, String> geom_name_map = new Dictionary<IntPtr, String>();
- public Dictionary<IntPtr, PhysicsActor> actor_name_map = new Dictionary<IntPtr, PhysicsActor>();
- private bool m_NINJA_physics_joints_enabled = false;
- //private Dictionary<String, IntPtr> jointpart_name_map = new Dictionary<String,IntPtr>();
- private readonly Dictionary<String, List<PhysicsJoint>> joints_connecting_actor = new Dictionary<String, List<PhysicsJoint>>();
- private d.ContactGeom[] contacts;
- private readonly List<PhysicsJoint> requestedJointsToBeCreated = new List<PhysicsJoint>(); // lock only briefly. accessed by external code (to request new joints) and by OdeScene.Simulate() to move those joints into pending/active
- private readonly List<PhysicsJoint> pendingJoints = new List<PhysicsJoint>(); // can lock for longer. accessed only by OdeScene.
- private readonly List<PhysicsJoint> activeJoints = new List<PhysicsJoint>(); // can lock for longer. accessed only by OdeScene.
- private readonly List<string> requestedJointsToBeDeleted = new List<string>(); // lock only briefly. accessed by external code (to request deletion of joints) and by OdeScene.Simulate() to move those joints out of pending/active
- private Object externalJointRequestsLock = new Object();
- private readonly Dictionary<String, PhysicsJoint> SOPName_to_activeJoint = new Dictionary<String, PhysicsJoint>();
- private readonly Dictionary<String, PhysicsJoint> SOPName_to_pendingJoint = new Dictionary<String, PhysicsJoint>();
- private readonly DoubleDictionary<Vector3, IntPtr, IntPtr> RegionTerrain = new DoubleDictionary<Vector3, IntPtr, IntPtr>();
- private readonly Dictionary<IntPtr,float[]> TerrainHeightFieldHeights = new Dictionary<IntPtr, float[]>();
- private d.Contact contact;
- private d.Contact TerrainContact;
- private d.Contact AvatarMovementprimContact;
- private d.Contact AvatarMovementTerrainContact;
- private d.Contact WaterContact;
- private d.Contact[,] m_materialContacts;
- //Ckrinke: Comment out until used. We declare it, initialize it, but do not use it
- //Ckrinke private int m_randomizeWater = 200;
- private int m_physicsiterations = 10;
- private const float m_SkipFramesAtms = 0.40f; // Drop frames gracefully at a 400 ms lag
- private readonly PhysicsActor PANull = new NullPhysicsActor();
- private float step_time = 0.0f;
- //Ckrinke: Comment out until used. We declare it, initialize it, but do not use it
- //Ckrinke private int ms = 0;
- public IntPtr world;
- //private bool returncollisions = false;
- // private uint obj1LocalID = 0;
- private uint obj2LocalID = 0;
- //private int ctype = 0;
- private OdeCharacter cc1;
- private OdePrim cp1;
- private OdeCharacter cc2;
- private OdePrim cp2;
- //private int cStartStop = 0;
- //private string cDictKey = "";
- public IntPtr space;
- //private IntPtr tmpSpace;
- // split static geometry collision handling into spaces of 30 meters
- public IntPtr[,] staticPrimspace;
- public Object OdeLock;
- public IMesher mesher;
- public IVoxelMesher voxmesher;
- private IConfigSource m_config;
- public bool physics_logging = false;
- public int physics_logging_interval = 0;
- public bool physics_logging_append_existing_logfile = false;
- public d.Vector3 xyz = new d.Vector3(128.1640f, 128.3079f, 25.7600f);
- public d.Vector3 hpr = new d.Vector3(125.5000f, -17.0000f, 0.0000f);
- // TODO: unused: private uint heightmapWidth = m_regionWidth + 1;
- // TODO: unused: private uint heightmapHeight = m_regionHeight + 1;
- // TODO: unused: private uint mapWidthSamples;
- // TODO: unused: private uint heightmapHeightSamples;
- private volatile int m_global_contactcount = 0;
- private Vector3 m_worldOffset = Vector3.Zero;
- public Vector2 WorldExtents = new Vector2((int)Constants.RegionSize, (int)Constants.RegionSize);
- private PhysicsScene m_parentScene = null;
- private ODERayCastRequestManager m_rayCastManager;
- /// <summary>
- /// Initiailizes the scene
- /// Sets many properties that ODE requires to be stable
- /// These settings need to be tweaked 'exactly' right or weird stuff happens.
- /// </summary>
- public OdeScene(CollisionLocker dode, string sceneIdentifier)
- {
- m_log
- = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType.ToString() + "." + sceneIdentifier);
- OdeLock = new Object();
- ode = dode;
- nearCallback = near;
- triCallback = TriCallback;
- triArrayCallback = TriArrayCallback;
- m_rayCastManager = new ODERayCastRequestManager(this);
- lock (OdeLock)
- {
- // Create the world and the first space
- world = d.WorldCreate();
- space = d.HashSpaceCreate(IntPtr.Zero);
-
- contactgroup = d.JointGroupCreate(0);
- //contactgroup
- d.WorldSetAutoDisableFlag(world, false);
- #if USE_DRAWSTUFF
-
- Thread viewthread = new Thread(new ParameterizedThreadStart(startvisualization));
- viewthread.Start();
- #endif
- }
- _watermap = new float[258 * 258];
- // Zero out the prim spaces array (we split our space into smaller spaces so
- // we can hit test less.
- }
- #if USE_DRAWSTUFF
- public void startvisualization(object o)
- {
- ds.Functions fn;
- fn.version = ds.VERSION;
- fn.start = new ds.CallbackFunction(start);
- fn.step = new ds.CallbackFunction(step);
- fn.command = new ds.CallbackFunction(command);
- fn.stop = null;
- fn.path_to_textures = "./textures";
- string[] args = new string[0];
- ds.SimulationLoop(args.Length, args, 352, 288, ref fn);
- }
- #endif
- // Initialize the mesh plugin
- public override void Initialise(IMesher meshmerizer, IVoxelMesher voxmesh, IConfigSource config)
- {
- mesher = meshmerizer;
- voxmesher = voxmesh;
- m_config = config;
- // Defaults
- if (Environment.OSVersion.Platform == PlatformID.Unix)
- {
- avPIDD = 3200.0f;
- avPIDP = 1400.0f;
- avStandupTensor = 2000000f;
- }
- else
- {
- avPIDD = 2200.0f;
- avPIDP = 900.0f;
- avStandupTensor = 550000f;
- }
- int contactsPerCollision = 80;
- if (m_config != null)
- {
- IConfig physicsconfig = m_config.Configs["ODEPhysicsSettings"];
- if (physicsconfig != null)
- {
- gravityx = physicsconfig.GetFloat("world_gravityx", 0f);
- gravityy = physicsconfig.GetFloat("world_gravityy", 0f);
- gravityz = physicsconfig.GetFloat("world_gravityz", -9.8f);
- worldHashspaceLow = physicsconfig.GetInt("world_hashspace_size_low", -4);
- worldHashspaceHigh = physicsconfig.GetInt("world_hashspace_size_high", 128);
- metersInSpace = physicsconfig.GetFloat("meters_in_small_space", 29.9f);
- smallHashspaceLow = physicsconfig.GetInt("small_hashspace_size_low", -4);
- smallHashspaceHigh = physicsconfig.GetInt("small_hashspace_size_high", 66);
- contactsurfacelayer = physicsconfig.GetFloat("world_contact_surface_layer", 0.001f);
- nmTerrainContactFriction = physicsconfig.GetFloat("nm_terraincontact_friction", 255.0f);
- nmTerrainContactBounce = physicsconfig.GetFloat("nm_terraincontact_bounce", 0.1f);
- nmTerrainContactERP = physicsconfig.GetFloat("nm_terraincontact_erp", 0.1025f);
- mTerrainContactFriction = physicsconfig.GetFloat("m_terraincontact_friction", 75f);
- mTerrainContactBounce = physicsconfig.GetFloat("m_terraincontact_bounce", 0.05f);
- mTerrainContactERP = physicsconfig.GetFloat("m_terraincontact_erp", 0.05025f);
- nmAvatarObjectContactFriction = physicsconfig.GetFloat("objectcontact_friction", 250f);
- nmAvatarObjectContactBounce = physicsconfig.GetFloat("objectcontact_bounce", 0.2f);
- mAvatarObjectContactFriction = physicsconfig.GetFloat("m_avatarobjectcontact_friction", 75f);
- mAvatarObjectContactBounce = physicsconfig.GetFloat("m_avatarobjectcontact_bounce", 0.1f);
- ODE_STEPSIZE = physicsconfig.GetFloat("world_stepsize", 0.020f);
- m_physicsiterations = physicsconfig.GetInt("world_internal_steps_without_collisions", 10);
- avDensity = physicsconfig.GetFloat("av_density", 80f);
- avHeightFudgeFactor = physicsconfig.GetFloat("av_height_fudge_factor", 0.52f);
- avMovementDivisorWalk = physicsconfig.GetFloat("av_movement_divisor_walk", 1.3f);
- avMovementDivisorRun = physicsconfig.GetFloat("av_movement_divisor_run", 0.8f);
- avCapRadius = physicsconfig.GetFloat("av_capsule_radius", 0.37f);
- avCapsuleTilted = physicsconfig.GetBoolean("av_capsule_tilted", false);
- contactsPerCollision = physicsconfig.GetInt("contacts_per_collision", 80);
- geomContactPointsStartthrottle = physicsconfig.GetInt("geom_contactpoints_start_throttling", 3);
- geomUpdatesPerThrottledUpdate = physicsconfig.GetInt("geom_updates_before_throttled_update", 15);
- geomCrossingFailuresBeforeOutofbounds = physicsconfig.GetInt("geom_crossing_failures_before_outofbounds", 5);
- geomDefaultDensity = physicsconfig.GetFloat("geometry_default_density", 10.000006836f);
- bodyFramesAutoDisable = physicsconfig.GetInt("body_frames_auto_disable", 20);
- bodyPIDD = physicsconfig.GetFloat("body_pid_derivative", 35f);
- bodyPIDG = physicsconfig.GetFloat("body_pid_gain", 25f);
- forceSimplePrimMeshing = physicsconfig.GetBoolean("force_simple_prim_meshing", forceSimplePrimMeshing);
- meshSculptedPrim = physicsconfig.GetBoolean("mesh_sculpted_prim", true);
- meshSculptLOD = physicsconfig.GetFloat("mesh_lod", 32f);
- MeshSculptphysicalLOD = physicsconfig.GetFloat("mesh_physical_lod", 16f);
- m_filterCollisions = physicsconfig.GetBoolean("filter_collisions", false);
- if (Environment.OSVersion.Platform == PlatformID.Unix)
- {
- avPIDD = physicsconfig.GetFloat("av_pid_derivative_linux", 2200.0f);
- avPIDP = physicsconfig.GetFloat("av_pid_proportional_linux", 900.0f);
- avStandupTensor = physicsconfig.GetFloat("av_capsule_standup_tensor_linux", 550000f);
- bodyMotorJointMaxforceTensor = physicsconfig.GetFloat("body_motor_joint_maxforce_tensor_linux", 5f);
- }
- else
- {
- avPIDD = physicsconfig.GetFloat("av_pid_derivative_win", 2200.0f);
- avPIDP = physicsconfig.GetFloat("av_pid_proportional_win", 900.0f);
- avStandupTensor = physicsconfig.GetFloat("av_capsule_standup_tensor_win", 550000f);
- bodyMotorJointMaxforceTensor = physicsconfig.GetFloat("body_motor_joint_maxforce_tensor_win", 5f);
- }
- physics_logging = physicsconfig.GetBoolean("physics_logging", false);
- physics_logging_interval = physicsconfig.GetInt("physics_logging_interval", 0);
- physics_logging_append_existing_logfile = physicsconfig.GetBoolean("physics_logging_append_existing_logfile", false);
- m_NINJA_physics_joints_enabled = physicsconfig.GetBoolean("use_NINJA_physics_joints", false);
- minimumGroundFlightOffset = physicsconfig.GetFloat("minimum_ground_flight_offset", 3f);
- maximumMassObject = physicsconfig.GetFloat("maximum_mass_object", 10000.01f);
- }
- }
- contacts = new d.ContactGeom[contactsPerCollision];
- staticPrimspace = new IntPtr[(int)(300 / metersInSpace), (int)(300 / metersInSpace)];
- // Centeral contact friction and bounce
- // ckrinke 11/10/08 Enabling soft_erp but not soft_cfm until I figure out why
- // an avatar falls through in Z but not in X or Y when walking on a prim.
- contact.surface.mode |= d.ContactFlags.SoftERP;
- contact.surface.mu = nmAvatarObjectContactFriction;
- contact.surface.bounce = nmAvatarObjectContactBounce;
- contact.surface.soft_cfm = 0.010f;
- contact.surface.soft_erp = 0.010f;
- // Terrain contact friction and Bounce
- // This is the *non* moving version. Use this when an avatar
- // isn't moving to keep it in place better
- TerrainContact.surface.mode |= d.ContactFlags.SoftERP;
- TerrainContact.surface.mu = nmTerrainContactFriction;
- TerrainContact.surface.bounce = nmTerrainContactBounce;
- TerrainContact.surface.soft_erp = nmTerrainContactERP;
- WaterContact.surface.mode |= (d.ContactFlags.SoftERP | d.ContactFlags.SoftCFM);
- WaterContact.surface.mu = 0f; // No friction
- WaterContact.surface.bounce = 0.0f; // No bounce
- WaterContact.surface.soft_cfm = 0.010f;
- WaterContact.surface.soft_erp = 0.010f;
- // Prim contact friction and bounce
- // THis is the *non* moving version of friction and bounce
- // Use this when an avatar comes in contact with a prim
- // and is moving
- AvatarMovementprimContact.surface.mu = mAvatarObjectContactFriction;
- AvatarMovementprimContact.surface.bounce = mAvatarObjectContactBounce;
- // Terrain contact friction bounce and various error correcting calculations
- // Use this when an avatar is in contact with the terrain and moving.
- AvatarMovementTerrainContact.surface.mode |= d.ContactFlags.SoftERP;
- AvatarMovementTerrainContact.surface.mu = mTerrainContactFriction;
- AvatarMovementTerrainContact.surface.bounce = mTerrainContactBounce;
- AvatarMovementTerrainContact.surface.soft_erp = mTerrainContactERP;
- /*
- <summary></summary>
- Stone = 0,
- /// <summary></summary>
- Metal = 1,
- /// <summary></summary>
- Glass = 2,
- /// <summary></summary>
- Wood = 3,
- /// <summary></summary>
- Flesh = 4,
- /// <summary></summary>
- Plastic = 5,
- /// <summary></summary>
- Rubber = 6
- */
- m_materialContacts = new d.Contact[7,2];
- m_materialContacts[(int)Material.Stone, 0] = new d.Contact();
- m_materialContacts[(int)Material.Stone, 0].surface.mode |= d.ContactFlags.SoftERP;
- m_materialContacts[(int)Material.Stone, 0].surface.mu = nmAvatarObjectContactFriction;
- m_materialContacts[(int)Material.Stone, 0].surface.bounce = nmAvatarObjectContactBounce;
- m_materialContacts[(int)Material.Stone, 0].surface.soft_cfm = 0.010f;
- m_materialContacts[(int)Material.Stone, 0].surface.soft_erp = 0.010f;
- m_materialContacts[(int)Material.Stone, 1] = new d.Contact();
- m_materialContacts[(int)Material.Stone, 1].surface.mode |= d.ContactFlags.SoftERP;
- m_materialContacts[(int)Material.Stone, 1].surface.mu = mAvatarObjectContactFriction;
- m_materialContacts[(int)Material.Stone, 1].surface.bounce = mAvatarObjectContactBounce;
- m_materialContacts[(int)Material.Stone, 1].surface.soft_cfm = 0.010f;
- m_materialContacts[(int)Material.Stone, 1].surface.soft_erp = 0.010f;
- m_materialContacts[(int)Material.Metal, 0] = new d.Contact();
- m_materialContacts[(int)Material.Metal, 0].surface.mode |= d.ContactFlags.SoftERP;
- m_materialContacts[(int)Material.Metal, 0].surface.mu = nmAvatarObjectContactFriction;
- m_materialContacts[(int)Material.Metal, 0].surface.bounce = nmAvatarObjectContactBounce;
- m_materialContacts[(int)Material.Metal, 0].surface.soft_cfm = 0.010f;
- m_materialContacts[(int)Material.Metal, 0].surface.soft_erp = 0.010f;
- m_materialContacts[(int)Material.Metal, 1] = new d.Contact();
- m_materialContacts[(int)Material.Metal, 1].surface.mode |= d.ContactFlags.SoftERP;
- m_materialContacts[(int)Material.Metal, 1].surface.mu = mAvatarObjectContactFriction;
- m_materialContacts[(int)Material.Metal, 1].surface.bounce = mAvatarObjectContactBounce;
- m_materialContacts[(int)Material.Metal, 1].surface.soft_cfm = 0.010f;
- m_materialContacts[(int)Material.Metal, 1].surface.soft_erp = 0.010f;
- m_materialContacts[(int)Material.Glass, 0] = new d.Contact();
- m_materialContacts[(int)Material.Glass, 0].surface.mode |= d.ContactFlags.SoftERP;
- m_materialContacts[(int)Material.Glass, 0].surface.mu = 1f;
- m_materialContacts[(int)Material.Glass, 0].surface.bounce = 0.5f;
- m_materialContacts[(int)Material.Glass, 0].surface.soft_cfm = 0.010f;
- m_materialContacts[(int)Material.Glass, 0].surface.soft_erp = 0.010f;
- /*
- private float nmAvatarObjectContactFriction = 250f;
- private float nmAvatarObjectContactBounce = 0.1f;
- private float mAvatarObjectContactFriction = 75f;
- private float mAvatarObjectContactBounce = 0.1f;
- */
- m_materialContacts[(int)Material.Glass, 1] = new d.Contact();
- m_materialContacts[(int)Material.Glass, 1].surface.mode |= d.ContactFlags.SoftERP;
- m_materialContacts[(int)Material.Glass, 1].surface.mu = 1f;
- m_materialContacts[(int)Material.Glass, 1].surface.bounce = 0.5f;
- m_materialContacts[(int)Material.Glass, 1].surface.soft_cfm = 0.010f;
- m_materialContacts[(int)Material.Glass, 1].surface.soft_erp = 0.010f;
- m_materialContacts[(int)Material.Wood, 0] = new d.Contact();
- m_materialContacts[(int)Material.Wood, 0].surface.mode |= d.ContactFlags.SoftERP;
- m_materialContacts[(int)Material.Wood, 0].surface.mu = nmAvatarObjectContactFriction;
- m_materialContacts[(int)Material.Wood, 0].surface.bounce = nmAvatarObjectContactBounce;
- m_materialContacts[(int)Material.Wood, 0].surface.soft_cfm = 0.010f;
- m_materialContacts[(int)Material.Wood, 0].surface.soft_erp = 0.010f;
- m_materialContacts[(int)Material.Wood, 1] = new d.Contact();
- m_materialContacts[(int)Material.Wood, 1].surface.mode |= d.ContactFlags.SoftERP;
- m_materialContacts[(int)Material.Wood, 1].surface.mu = mAvatarObjectContactFriction;
- m_materialContacts[(int)Material.Wood, 1].surface.bounce = mAvatarObjectContactBounce;
- m_materialContacts[(int)Material.Wood, 1].surface.soft_cfm = 0.010f;
- m_materialContacts[(int)Material.Wood, 1].surface.soft_erp = 0.010f;
- m_materialContacts[(int)Material.Flesh, 0] = new d.Contact();
- m_materialContacts[(int)Material.Flesh, 0].surface.mode |= d.ContactFlags.SoftERP;
- m_materialContacts[(int)Material.Flesh, 0].surface.mu = nmAvatarObjectContactFriction;
- m_materialContacts[(int)Material.Flesh, 0].surface.bounce = nmAvatarObjectContactBounce;
- m_materialContacts[(int)Material.Flesh, 0].surface.soft_cfm = 0.010f;
- m_materialContacts[(int)Material.Flesh, 0].surface.soft_erp = 0.010f;
- m_materialContacts[(int)Material.Flesh, 1] = new d.Contact();
- m_materialContacts[(int)Material.Flesh, 1].surface.mode |= d.ContactFlags.SoftERP;
- m_materialContacts[(int)Material.Flesh, 1].surface.mu = mAvatarObjectContactFriction;
- m_materialContacts[(int)Material.Flesh, 1].surface.bounce = mAvatarObjectContactBounce;
- m_materialContacts[(int)Material.Flesh, 1].surface.soft_cfm = 0.010f;
- m_materialContacts[(int)Material.Flesh, 1].surface.soft_erp = 0.010f;
- m_materialContacts[(int)Material.Plastic, 0] = new d.Contact();
- m_materialContacts[(int)Material.Plastic, 0].surface.mode |= d.ContactFlags.SoftERP;
- m_materialContacts[(int)Material.Plastic, 0].surface.mu = nmAvatarObjectContactFriction;
- m_materialContacts[(int)Material.Plastic, 0].surface.bounce = nmAvatarObjectContactBounce;
- m_materialContacts[(int)Material.Plastic, 0].surface.soft_cfm = 0.010f;
- m_materialContacts[(int)Material.Plastic, 0].surface.soft_erp = 0.010f;
- m_materialContacts[(int)Material.Plastic, 1] = new d.Contact();
- m_materialContacts[(int)Material.Plastic, 1].surface.mode |= d.ContactFlags.SoftERP;
- m_materialContacts[(int)Material.Plastic, 1].surface.mu = mAvatarObjectContactFriction;
- m_materialContacts[(int)Material.Plastic, 1].surface.bounce = mAvatarObjectContactBounce;
- m_materialContacts[(int)Material.Plastic, 1].surface.soft_cfm = 0.010f;
- m_materialContacts[(int)Material.Plastic, 1].surface.soft_erp = 0.010f;
- m_materialContacts[(int)Material.Rubber, 0] = new d.Contact();
- m_materialContacts[(int)Material.Rubber, 0].surface.mode |= d.ContactFlags.SoftERP;
- m_materialContacts[(int)Material.Rubber, 0].surface.mu = nmAvatarObjectContactFriction;
- m_materialContacts[(int)Material.Rubber, 0].surface.bounce = nmAvatarObjectContactBounce;
- m_materialContacts[(int)Material.Rubber, 0].surface.soft_cfm = 0.010f;
- m_materialContacts[(int)Material.Rubber, 0].surface.soft_erp = 0.010f;
- m_materialContacts[(int)Material.Rubber, 1] = new d.Contact();
- m_materialContacts[(int)Material.Rubber, 1].surface.mode |= d.ContactFlags.SoftERP;
- m_materialContacts[(int)Material.Rubber, 1].surface.mu = mAvatarObjectContactFriction;
- m_materialContacts[(int)Material.Rubber, 1].surface.bounce = mAvatarObjectContactBounce;
- m_materialContacts[(int)Material.Rubber, 1].surface.soft_cfm = 0.010f;
- m_materialContacts[(int)Material.Rubber, 1].surface.soft_erp = 0.010f;
- d.HashSpaceSetLevels(space, worldHashspaceLow, worldHashspaceHigh);
- // Set the gravity,, don't disable things automatically (we set it explicitly on some things)
- d.WorldSetGravity(world, gravityx, gravityy, gravityz);
- d.WorldSetContactSurfaceLayer(world, contactsurfacelayer);
- d.WorldSetLinearDamping(world, 256f);
- d.WorldSetAngularDamping(world, 256f);
- d.WorldSetAngularDampingThreshold(world, 256f);
- d.WorldSetLinearDampingThreshold(world, 256f);
- d.WorldSetMaxAngularSpeed(world, 256f);
- // Set how many steps we go without running collision testing
- // This is in addition to the step size.
- // Essentially Steps * m_physicsiterations
- d.WorldSetQuickStepNumIterations(world, m_physicsiterations);
- //d.WorldSetContactMaxCorrectingVel(world, 1000.0f);
-
- for (int i = 0; i < staticPrimspace.GetLength(0); i++)
- {
- for (int j = 0; j < staticPrimspace.GetLength(1); j++)
- {
- staticPrimspace[i, j] = IntPtr.Zero;
- }
- }
- }
- internal void waitForSpaceUnlock(IntPtr space)
- {
- //if (space != IntPtr.Zero)
- //while (d.SpaceLockQuery(space)) { } // Wait and do nothing
- }
- /// <summary>
- /// Debug space message for printing the space that a prim/avatar is in.
- /// </summary>
- /// <param name="pos"></param>
- /// <returns>Returns which split up space the given position is in.</returns>
- public string whichspaceamIin(Vector3 pos)
- {
- return calculateSpaceForGeom(pos).ToString();
- }
- #region Collision Detection
- /// <summary>
- /// This is our near callback. A geometry is near a body
- /// </summary>
- /// <param name="space">The space that contains the geoms. Remember, spaces are also geoms</param>
- /// <param name="g1">a geometry or space</param>
- /// <param name="g2">another geometry or space</param>
- private void near(IntPtr space, IntPtr g1, IntPtr g2)
- {
- // no lock here! It's invoked from within Simulate(), which is thread-locked
- // Test if we're colliding a geom with a space.
- // If so we have to drill down into the space recursively
- if (d.GeomIsSpace(g1) || d.GeomIsSpace(g2))
- {
- if (g1 == IntPtr.Zero || g2 == IntPtr.Zero)
- return;
-
- // Separating static prim geometry spaces.
- // We'll be calling near recursivly if one
- // of them is a space to find all of the
- // contact points in the space
- try
- {
- d.SpaceCollide2(g1, g2, IntPtr.Zero, nearCallback);
- }
- catch (AccessViolationException)
- {
- m_log.Warn("[PHYSICS]: Unable to collide test a space");
- return;
- }
- //Colliding a space or a geom with a space or a geom. so drill down
- //Collide all geoms in each space..
- //if (d.GeomIsSpace(g1)) d.SpaceCollide(g1, IntPtr.Zero, nearCallback);
- //if (d.GeomIsSpace(g2)) d.SpaceCollide(g2, IntPtr.Zero, nearCallback);
- return;
- }
- if (g1 == IntPtr.Zero || g2 == IntPtr.Zero)
- return;
- IntPtr b1 = d.GeomGetBody(g1);
- IntPtr b2 = d.GeomGetBody(g2);
- // d.GeomClassID id = d.GeomGetClass(g1);
- String name1 = null;
- String name2 = null;
- if (!geom_name_map.TryGetValue(g1, out name1))
- {
- name1 = "null";
- }
- if (!geom_name_map.TryGetValue(g2, out name2))
- {
- name2 = "null";
- }
- //if (id == d.GeomClassId.TriMeshClass)
- //{
- // m_log.InfoFormat("near: A collision was detected between {1} and {2}", 0, name1, name2);
- //m_log.Debug("near: A collision was detected between {1} and {2}", 0, name1, name2);
- //}
- // Figure out how many contact points we have
- int count = 0;
- try
- {
- // Colliding Geom To Geom
- // This portion of the function 'was' blatantly ripped off from BoxStack.cs
- if (g1 == g2)
- return; // Can't collide with yourself
- if (b1 != IntPtr.Zero && b2 != IntPtr.Zero && d.AreConnectedExcluding(b1, b2, d.JointType.Contact))
- return;
- lock (contacts)
- {
- count = d.Collide(g1, g2, contacts.Length, contacts, d.ContactGeom.SizeOf);
- if (count > contacts.Length)
- m_log.Error("[PHYSICS]: Got " + count + " contacts when we asked for a maximum of " + contacts.Length);
- }
- }
- catch (SEHException)
- {
- 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.");
- ode.drelease(world);
- base.TriggerPhysicsBasedRestart();
- }
- catch (Exception e)
- {
- m_log.WarnFormat("[PHYSICS]: Unable to collide test an object: {0}", e.Message);
- return;
- }
- PhysicsActor p1;
- PhysicsActor p2;
- if (!actor_name_map.TryGetValue(g1, out p1))
- {
- p1 = PANull;
- }
- if (!actor_name_map.TryGetValue(g2, out p2))
- {
- p2 = PANull;
- }
- ContactPoint maxDepthContact = new ContactPoint();
- if (p1.CollisionScore + count >= float.MaxValue)
- p1.CollisionScore = 0;
- p1.CollisionScore += count;
- if (p2.CollisionScore + count >= float.MaxValue)
- p2.CollisionScore = 0;
- p2.CollisionScore += count;
- for (int i = 0; i < count; i++)
- {
- d.ContactGeom curContact = contacts[i];
- if (curContact.depth > maxDepthContact.PenetrationDepth)
- {
- maxDepthContact = new ContactPoint(
- new Vector3(curContact.pos.X, curContact.pos.Y, curContact.pos.Z),
- new Vector3(curContact.normal.X, curContact.normal.Y, curContact.normal.Z),
- curContact.depth
- );
- }
- //m_log.Warn("[CCOUNT]: " + count);
- IntPtr joint;
- // If we're colliding with terrain, use 'TerrainContact' instead of contact.
- // allows us to have different settings
-
- // We only need to test p2 for 'jump crouch purposes'
- if (p2 is OdeCharacter && p1.PhysicsActorType == (int)ActorTypes.Prim)
- {
- // Testing if the collision is at the feet of the avatar
- //m_log.DebugFormat("[PHYSICS]: {0} - {1} - {2} - {3}", curContact.pos.Z, p2.Position.Z, (p2.Position.Z - curContact.pos.Z), (p2.Size.Z * 0.6f));
- if ((p2.Position.Z - curContact.pos.Z) > (p2.Size.Z * 0.6f))
- p2.IsColliding = true;
- }
- else
- {
- p2.IsColliding = true;
- }
-
- //if ((framecount % m_returncollisions) == 0)
- switch (p1.PhysicsActorType)
- {
- case (int)ActorTypes.Agent:
- p2.CollidingObj = true;
- break;
- case (int)ActorTypes.Prim:
- if (p2.Velocity.LengthSquared() > 0.0f)
- p2.CollidingObj = true;
- break;
- case (int)ActorTypes.Unknown:
- p2.CollidingGround = true;
- break;
- default:
- p2.CollidingGround = true;
- break;
- }
- // we don't want prim or avatar to explode
- #region InterPenetration Handling - Unintended physics explosions
- # region disabled code1
- if (curContact.depth >= 0.08f)
- {
- //This is disabled at the moment only because it needs more tweaking
- //It will eventually be uncommented
- /*
- if (contact.depth >= 1.00f)
- {
- //m_log.Debug("[PHYSICS]: " + contact.depth.ToString());
- }
- //If you interpenetrate a prim with an agent
- if ((p2.PhysicsActorType == (int) ActorTypes.Agent &&
- p1.PhysicsActorType == (int) ActorTypes.Prim) ||
- (p1.PhysicsActorType == (int) ActorTypes.Agent &&
- p2.PhysicsActorType == (int) ActorTypes.Prim))
- {
-
- //contact.depth = contact.depth * 4.15f;
- /*
- if (p2.PhysicsActorType == (int) ActorTypes.Agent)
- {
- p2.CollidingObj = true;
- contact.depth = 0.003f;
- p2.Velocity = p2.Velocity + new PhysicsVector(0, 0, 2.5f);
- OdeCharacter character = (OdeCharacter) p2;
- character.SetPidStatus(true);
- contact.pos = new d.Vector3(contact.pos.X + (p1.Size.X / 2), contact.pos.Y + (p1.Size.Y / 2), contact.pos.Z + (p1.Size.Z / 2));
- }
- else
- {
- //contact.depth = 0.0000000f;
- }
- if (p1.PhysicsActorType == (int) ActorTypes.Agent)
- {
- p1.CollidingObj = true;
- contact.depth = 0.003f;
- p1.Velocity = p1.Velocity + new PhysicsVector(0, 0, 2.5f);
- contact.pos = new d.Vector3(contact.pos.X + (p2.Size.X / 2), contact.pos.Y + (p2.Size.Y / 2), contact.pos.Z + (p2.Size.Z / 2));
- OdeCharacter character = (OdeCharacter)p1;
- character.SetPidStatus(true);
- }
- else
- {
- //contact.depth = 0.0000000f;
- }
-
-
-
- }
- */
- // If you interpenetrate a prim with another prim
- /*
- if (p1.PhysicsActorType == (int) ActorTypes.Prim && p2.PhysicsActorType == (int) ActorTypes.Prim)
- {
- #region disabledcode2
- //OdePrim op1 = (OdePrim)p1;
- //OdePrim op2 = (OdePrim)p2;
- //op1.m_collisionscore++;
- //op2.m_collisionscore++;
- //if (op1.m_collisionscore > 8000 || op2.m_collisionscore > 8000)
- //{
- //op1.m_taintdisable = true;
- //AddPhysicsActorTaint(p1);
- //op2.m_taintdisable = true;
- //AddPhysicsActorTaint(p2);
- //}
- //if (contact.depth >= 0.25f)
- //{
- // Don't collide, one or both prim will expld.
- //op1.m_interpenetrationcount++;
- //op2.m_interpenetrationcount++;
- //interpenetrations_before_disable = 200;
- //if (op1.m_interpenetrationcount >= interpenetrations_before_disable)
- //{
- //op1.m_taintdisable = true;
- //AddPhysicsActorTaint(p1);
- //}
- //if (op2.m_interpenetrationcount >= interpenetrations_before_disable)
- //{
- // op2.m_taintdisable = true;
- //AddPhysicsActorTaint(p2);
- //}
- //contact.depth = contact.depth / 8f;
- //contact.normal = new d.Vector3(0, 0, 1);
- //}
- //if (op1.m_disabled || op2.m_disabled)
- //{
- //Manually disabled objects stay disabled
- //contact.depth = 0f;
- //}
- #endregion
- }
- */
- #endregion
- if (curContact.depth >= 1.00f)
- {
- //m_log.Info("[P]: " + contact.depth.ToString());
- if ((p2.PhysicsActorType == (int) ActorTypes.Agent &&
- p1.PhysicsActorType == (int) ActorTypes.Unknown) ||
- (p1.PhysicsActorType == (int) ActorTypes.Agent &&
- p2.PhysicsActorType == (int) ActorTypes.Unknown))
- {
- if (p2.PhysicsActorType == (int) ActorTypes.Agent)
- {
- if (p2 is OdeCharacter)
- {
- OdeCharacter character = (OdeCharacter) p2;
- //p2.CollidingObj = true;
- curContact.depth = 0.00000003f;
- p2.Velocity = p2.Velocity + new Vector3(0f, 0f, 0.5f);
- curContact.pos =
- new d.Vector3(curContact.pos.X + (p1.Size.X/2),
- curContact.pos.Y + (p1.Size.Y/2),
- curContact.pos.Z + (p1.Size.Z/2));
- character.SetPidStatus(true);
- }
- }
-
- if (p1.PhysicsActorType == (int) ActorTypes.Agent)
- {
- if (p1 is OdeCharacter)
- {
- OdeCharacter character = (OdeCharacter) p1;
- //p2.CollidingObj = true;
- curContact.depth = 0.00000003f;
- p1.Velocity = p1.Velocity + new Vector3(0f, 0f, 0.5f);
- curContact.pos =
- new d.Vector3(curContact.pos.X + (p1.Size.X/2),
- curContact.pos.Y + (p1.Size.Y/2),
- curContact.pos.Z + (p1.Size.Z/2));
- character.SetPidStatus(true);
- }
- }
- }
- }
- }
- #endregion
- // Logic for collision handling
- // Note, that if *all* contacts are skipped (VolumeDetect)
- // The prim still detects (and forwards) collision events but
- // appears to be phantom for the world
- Boolean skipThisContact = false;
- if ((p1 is OdePrim) && (((OdePrim)p1).m_isVolumeDetect))
- skipThisContact = true; // No collision on volume detect prims
- if (!skipThisContact && (p2 is OdePrim) && (((OdePrim)p2).m_isVolumeDetect))
- skipThisContact = true; // No collision on volume detect prims
- if (!skipThisContact && curContact.depth < 0f)
- skipThisContact = true;
- if (!skipThisContact && checkDupe(curContact, p2.PhysicsActorType))
- skipThisContact = true;
- const int maxContactsbeforedeath = 4000;
- joint = IntPtr.Zero;
- if (!skipThisContact)
- {
- // If we're colliding against terrain
- if (name1 == "Terrain" || name2 == "Terrain")
- {
- // If we're moving
- if ((p2.PhysicsActorType == (int) ActorTypes.Agent) &&
- (Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f))
- {
- // Use the movement terrain contact
- AvatarMovementTerrainContact.geom = curContact;
- _perloopContact.Add(curContact);
- if (m_global_contactcount < maxContactsbeforedeath)
- {
- joint = d.JointCreateContact(world, contactgroup, ref AvatarMovementTerrainContact);
- m_global_contactcount++;
- }
- }
- else
- {
- if (p2.PhysicsActorType == (int)ActorTypes.Agent)
- {
- …
Large files files are truncated, but you can click here to view the full file