32 using System.Collections.Generic;
33 using System.Reflection;
34 using System.Runtime.InteropServices;
35 using System.Threading;
37 using System.Diagnostics;
42 using OpenSim.Framework;
43 using OpenSim.Region.Framework.Scenes;
44 using OpenSim.Region.Framework.Interfaces;
45 using OpenSim.Region.PhysicsModules.SharedBase;
48 namespace OpenSim.
Region.PhysicsModule.ubOde
170 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
172 public bool m_OSOdeLib =
false;
173 public bool m_suportCombine =
false;
174 public Scene m_frameWorkScene = null;
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;
185 float frictionMovementMult = 0.8f;
187 float TerrainBounce = 0.1f;
188 float TerrainFriction = 0.3f;
190 public float AvatarFriction = 0;
195 private uint m_regionWidth = Constants.RegionSize;
196 private uint m_regionHeight = Constants.RegionSize;
198 public float ODE_STEPSIZE = 0.020f;
199 public float HalfOdeStep = 0.01f;
200 public int odetimestepMS = 20;
201 private float metersInSpace = 25.6f;
202 private float m_timeDilation = 1.0f;
204 private DateTime m_lastframe;
205 private DateTime m_lastMeshExpire;
207 public float gravityx = 0f;
208 public float gravityy = 0f;
209 public float gravityz = -9.8f;
211 private float waterlevel = 0f;
212 private int framecount = 0;
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;
221 public float maximumAngularVelocity = 12.0f;
222 public float maxAngVelocitySQ = 144f;
224 public float bodyPIDD = 35f;
225 public float bodyPIDG = 25;
227 public int bodyFramesAutoDisable = 5;
229 private d.NearCallback nearCallback;
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>();
241 private List<PhysicsActor> _collisionEventPrim =
new List<PhysicsActor>();
242 private List<PhysicsActor> _collisionEventPrimRemove =
new List<PhysicsActor>();
244 private HashSet<OdeCharacter> _badCharacter =
new HashSet<OdeCharacter>();
245 public Dictionary<IntPtr, PhysicsActor> actor_name_map =
new Dictionary<IntPtr, PhysicsActor>();
247 private float contactsurfacelayer = 0.002f;
249 private int contactsPerCollision = 80;
250 internal IntPtr ContactgeomsArray = IntPtr.Zero;
251 private IntPtr GlobalContactsArray = IntPtr.Zero;
254 const int maxContactsbeforedeath = 6000;
255 private volatile int m_global_contactcount = 0;
257 private IntPtr contactgroup;
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>();
265 private int m_physicsiterations = 15;
266 private const float m_SkipFramesAtms = 0.40f;
268 private float step_time = 0.0f;
285 private int spaceGridMaxX;
286 private int spaceGridMaxY;
287 private float spacesPerMeterX;
288 private float spacesPerMeterY;
291 private IntPtr[,] staticPrimspace;
292 private IntPtr[] staticPrimspaceOffRegion;
301 public bool physics_logging =
false;
302 public int physics_logging_interval = 0;
303 public bool physics_logging_append_existing_logfile =
false;
305 private Vector3 m_worldOffset = Vector3.Zero;
325 IConfig physicsconfig = null;
327 public ODEScene(
Scene pscene, IConfigSource psourceconfig,
string pname,
bool pOSOdeLib)
332 PhysicsSceneName = EngineType +
"/" + pscene.RegionInfo.RegionName;
334 m_config = psourceconfig;
335 m_OSOdeLib = pOSOdeLib;
339 m_frameWorkScene = pscene;
341 m_frameWorkScene.RegisterModuleInterface<
PhysicsScene>(
this);
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);
352 mesher = m_frameWorkScene.RequestModuleInterface<
IMesher>();
355 m_log.ErrorFormat(
"[ubOde] No mesher. module disabled");
359 m_meshWorker =
new ODEMeshWorker(
this, m_log, mesher, physicsconfig);
360 m_frameWorkScene.PhysicsEnabled =
true;
367 private void Initialization()
369 d.AllocateODEDataForThread(~0U);
371 SimulationLock =
new Object();
377 WorldExtents.X = m_frameWorkScene.RegionInfo.RegionSizeX;
378 m_regionWidth = (uint)WorldExtents.X;
379 WorldExtents.Y = m_frameWorkScene.RegionInfo.RegionSizeY;
380 m_regionHeight = (uint)WorldExtents.Y;
382 m_suportCombine =
false;
389 world = d.WorldCreate();
390 TopSpace = d.HashSpaceCreate(IntPtr.Zero);
393 ActiveSpace = d.HashSpaceCreate(TopSpace);
394 CharsSpace = d.HashSpaceCreate(TopSpace);
395 StaticSpace = d.HashSpaceCreate(TopSpace);
396 GroundSpace = d.HashSpaceCreate(TopSpace);
404 d.HashSpaceSetLevels(TopSpace, -5, 12);
405 d.HashSpaceSetLevels(ActiveSpace, -5, 10);
406 d.HashSpaceSetLevels(CharsSpace, -4, 3);
407 d.HashSpaceSetLevels(StaticSpace, -5, 12);
408 d.HashSpaceSetLevels(GroundSpace, 0, 8);
411 d.SpaceSetSublevel(ActiveSpace, 1);
412 d.SpaceSetSublevel(CharsSpace, 1);
413 d.SpaceSetSublevel(StaticSpace, 1);
414 d.SpaceSetSublevel(GroundSpace, 1);
434 d.GeomSetCollideBits(CharsSpace, 0);
443 d.GeomSetCollideBits(StaticSpace, 0);
446 d.GeomSetCollideBits(GroundSpace, 0);
448 contactgroup = d.JointGroupCreate(maxContactsbeforedeath + 1);
451 d.WorldSetAutoDisableFlag(world,
false);
460 int contactsPerCollision = 80;
462 physicsconfig = null;
464 if (m_config != null)
466 physicsconfig = m_config.Configs[
"ODEPhysicsSettings"];
467 if (physicsconfig != null)
469 gravityx = physicsconfig.GetFloat(
"world_gravityx", gravityx);
470 gravityy = physicsconfig.GetFloat(
"world_gravityy", gravityy);
471 gravityz = physicsconfig.GetFloat(
"world_gravityz", gravityz);
473 metersInSpace = physicsconfig.GetFloat(
"meters_in_small_space", metersInSpace);
477 ODE_STEPSIZE = physicsconfig.GetFloat(
"world_stepsize", ODE_STEPSIZE);
479 avDensity = physicsconfig.GetFloat(
"av_density", avDensity);
480 avMovementDivisorWalk = physicsconfig.GetFloat(
"av_movement_divisor_walk", avMovementDivisorWalk);
481 avMovementDivisorRun = physicsconfig.GetFloat(
"av_movement_divisor_run", avMovementDivisorRun);
483 contactsPerCollision = physicsconfig.GetInt(
"contacts_per_collision", contactsPerCollision);
485 geomDefaultDensity = physicsconfig.GetFloat(
"geometry_default_density", geomDefaultDensity);
486 bodyFramesAutoDisable = physicsconfig.GetInt(
"body_frames_auto_disable", bodyFramesAutoDisable);
488 physics_logging = physicsconfig.GetBoolean(
"physics_logging",
false);
489 physics_logging_interval = physicsconfig.GetInt(
"physics_logging_interval", 0);
490 physics_logging_append_existing_logfile = physicsconfig.GetBoolean(
"physics_logging_append_existing_logfile",
false);
492 minimumGroundFlightOffset = physicsconfig.GetFloat(
"minimum_ground_flight_offset", minimumGroundFlightOffset);
493 maximumMassObject = physicsconfig.GetFloat(
"maximum_mass_object", maximumMassObject);
495 avDensity *= 3f / 80f;
499 float heartbeat = 1/m_frameWorkScene.FrameTime;
500 maximumAngularVelocity = 0.49f * heartbeat *(float)Math.PI;
501 maxAngVelocitySQ = maximumAngularVelocity * maximumAngularVelocity;
503 d.WorldSetCFM(world, comumContactCFM);
504 d.WorldSetERP(world, comumContactERP);
506 d.WorldSetGravity(world, gravityx, gravityy, gravityz);
508 d.WorldSetLinearDamping(world, 0.002f);
509 d.WorldSetAngularDamping(world, 0.002f);
510 d.WorldSetAngularDampingThreshold(world, 0f);
511 d.WorldSetLinearDampingThreshold(world, 0f);
512 d.WorldSetMaxAngularSpeed(world, maximumAngularVelocity);
514 d.WorldSetQuickStepNumIterations(world, m_physicsiterations);
516 d.WorldSetContactSurfaceLayer(world, contactsurfacelayer);
517 d.WorldSetContactMaxCorrectingVel(world, 60.0f);
519 HalfOdeStep = ODE_STEPSIZE * 0.5f;
520 odetimestepMS = (int)(1000.0f * ODE_STEPSIZE + 0.5f);
522 ContactgeomsArray = Marshal.AllocHGlobal(contactsPerCollision * d.ContactGeom.unmanagedSizeOf);
523 GlobalContactsArray = Marshal.AllocHGlobal((maxContactsbeforedeath + 100) * d.Contact.unmanagedSizeOf);
525 SharedTmpcontact.geom.g1 = IntPtr.Zero;
526 SharedTmpcontact.geom.g2 = IntPtr.Zero;
528 SharedTmpcontact.geom.side1 = -1;
529 SharedTmpcontact.geom.side2 = -1;
531 SharedTmpcontact.surface.mode = comumContactFlags;
532 SharedTmpcontact.surface.mu = 0;
533 SharedTmpcontact.surface.bounce = 0;
534 SharedTmpcontact.surface.soft_cfm = comumContactCFM;
535 SharedTmpcontact.surface.soft_erp = comumContactERP;
536 SharedTmpcontact.surface.slip1 = comumContactSLIP;
537 SharedTmpcontact.surface.slip2 = comumContactSLIP;
539 m_materialContactsData[(int)
Material.Stone].mu = 0.8f;
540 m_materialContactsData[(
int)Material.Stone].bounce = 0.4f;
542 m_materialContactsData[(int)
Material.Metal].mu = 0.3f;
543 m_materialContactsData[(
int)Material.Metal].bounce = 0.4f;
545 m_materialContactsData[(int)
Material.Glass].mu = 0.2f;
546 m_materialContactsData[(
int)Material.Glass].bounce = 0.7f;
548 m_materialContactsData[(int)
Material.Wood].mu = 0.6f;
549 m_materialContactsData[(
int)Material.Wood].bounce = 0.5f;
551 m_materialContactsData[(int)
Material.Flesh].mu = 0.9f;
552 m_materialContactsData[(
int)Material.Flesh].bounce = 0.3f;
554 m_materialContactsData[(int)
Material.Plastic].mu = 0.4f;
555 m_materialContactsData[(
int)Material.Plastic].bounce = 0.7f;
557 m_materialContactsData[(int)
Material.Rubber].mu = 0.9f;
558 m_materialContactsData[(
int)Material.Rubber].bounce = 0.95f;
560 m_materialContactsData[(int)
Material.light].mu = 0.0f;
561 m_materialContactsData[(
int)Material.light].bounce = 0.0f;
564 spacesPerMeterX = 1.0f / metersInSpace;
565 spacesPerMeterY = spacesPerMeterX;
566 spaceGridMaxX = (int)(WorldExtents.X * spacesPerMeterX);
567 spaceGridMaxY = (int)(WorldExtents.Y * spacesPerMeterY);
569 if (spaceGridMaxX > 24)
572 spacesPerMeterX = spaceGridMaxX / WorldExtents.X;
575 if (spaceGridMaxY > 24)
578 spacesPerMeterY = spaceGridMaxY / WorldExtents.Y;
581 staticPrimspace =
new IntPtr[spaceGridMaxX, spaceGridMaxY];
587 for (i = 0; i < spaceGridMaxX; i++)
588 for (j = 0; j < spaceGridMaxY; j++)
590 newspace = d.HashSpaceCreate(StaticSpace);
592 waitForSpaceUnlock(newspace);
593 d.SpaceSetSublevel(newspace, 2);
594 d.HashSpaceSetLevels(newspace, -2, 8);
602 d.GeomSetCollideBits(newspace, 0);
604 staticPrimspace[i, j] = newspace;
612 staticPrimspaceOffRegion =
new IntPtr[4];
614 for (i = 0; i < 4; i++)
616 newspace = d.HashSpaceCreate(StaticSpace);
618 waitForSpaceUnlock(newspace);
619 d.SpaceSetSublevel(newspace, 2);
620 d.HashSpaceSetLevels(newspace, -2, 8);
628 d.GeomSetCollideBits(newspace, 0);
630 staticPrimspaceOffRegion[i] = newspace;
633 m_lastframe = DateTime.UtcNow;
634 m_lastMeshExpire = m_lastframe;
637 internal void waitForSpaceUnlock(IntPtr space)
643 #region Collision Detection
646 private IntPtr CreateContacJoint(ref d.ContactGeom contactGeom,
bool smooth)
648 if (m_global_contactcount >= maxContactsbeforedeath)
651 m_global_contactcount++;
653 SharedTmpcontact.geom.depth = contactGeom.depth * 0.05f;
655 SharedTmpcontact.geom.depth = contactGeom.depth;
656 SharedTmpcontact.geom.pos = contactGeom.pos;
657 SharedTmpcontact.geom.normal = contactGeom.normal;
659 IntPtr contact =
new IntPtr(GlobalContactsArray.ToInt64() + (Int64)(m_global_contactcount * d.Contact.unmanagedSizeOf));
660 Marshal.StructureToPtr(SharedTmpcontact, contact,
true);
661 return d.JointCreateContactPtr(world, contactgroup, contact);
664 private bool GetCurContactGeom(
int index, ref d.ContactGeom newcontactgeom)
666 if (ContactgeomsArray == IntPtr.Zero || index >= contactsPerCollision)
669 IntPtr contactptr =
new IntPtr(ContactgeomsArray.ToInt64() + (Int64)(index * d.ContactGeom.unmanagedSizeOf));
670 newcontactgeom = (
d.ContactGeom)Marshal.PtrToStructure(contactptr, typeof(d.ContactGeom));
682 private void near(IntPtr space, IntPtr g1, IntPtr g2)
686 if (m_global_contactcount >= maxContactsbeforedeath)
692 if (g1 == IntPtr.Zero || g2 == IntPtr.Zero)
695 if (d.GeomIsSpace(g1) || d.GeomIsSpace(g2))
702 d.SpaceCollide2(g1, g2, IntPtr.Zero, nearCallback);
704 catch (AccessViolationException)
706 m_log.Warn(
"[PHYSICS]: Unable to collide test a space");
717 IntPtr b1 = d.GeomGetBody(g1);
718 IntPtr b2 = d.GeomGetBody(g2);
732 if (b1 != IntPtr.Zero && b2 != IntPtr.Zero && d.AreConnectedExcluding(b1, b2, d.JointType.Contact))
767 cflags = (int)(1 | d.CONTACTS_UNIMPORTANT);
769 count = d.CollidePtr(g1, g2, cflags, ContactgeomsArray, d.ContactGeom.unmanagedSizeOf);
772 count = d.CollidePtr(g1, g2, (contactsPerCollision & 0xffff), ContactgeomsArray, d.ContactGeom.unmanagedSizeOf);
776 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.");
778 base.TriggerPhysicsBasedRestart();
782 m_log.WarnFormat(
"[PHYSICS]: Unable to collide test an object: {0}", e.Message);
794 if (!actor_name_map.TryGetValue(g1, out p1))
796 m_log.WarnFormat(
"[PHYSICS]: failed actor mapping for geom 1");
800 if (!actor_name_map.TryGetValue(g2, out p2))
802 m_log.WarnFormat(
"[PHYSICS]: failed actor mapping for geom 2");
807 if (p1.CollisionScore >=
float.MaxValue - count)
808 p1.CollisionScore = 0;
809 p1.CollisionScore += count;
811 if (p2.CollisionScore >=
float.MaxValue - count)
812 p2.CollisionScore = 0;
813 p2.CollisionScore += count;
818 if (!GetCurContactGeom(0, ref curContact))
824 if ((p1.IsVolumeDtc || p2.IsVolumeDtc))
827 new Vector3(curContact.pos.X, curContact.pos.Y, curContact.pos.Z),
828 new Vector3(curContact.normal.X, curContact.normal.Y, curContact.normal.Z),
829 curContact.depth,
false
832 collision_accounting_events(p1, p2, maxDepthContact);
845 bool dop1ava =
false;
846 bool dop2ava =
false;
848 bool smoothMesh =
false;
850 switch (p1.PhysicsActorType)
852 case (
int)ActorTypes.Agent:
855 switch (p2.PhysicsActorType)
857 case (
int)ActorTypes.Agent:
858 case (
int)ActorTypes.Prim:
868 case (
int)ActorTypes.Prim:
870 switch (p2.PhysicsActorType)
872 case (
int)ActorTypes.Agent:
876 case (
int)ActorTypes.Prim:
877 Vector3 relV = p1.Velocity - p2.Velocity;
878 float relVlenSQ = relV.LengthSquared();
879 if (relVlenSQ > 0.0001f)
881 p1.CollidingObj =
true;
882 p2.CollidingObj =
true;
884 p1.getContactData(ref contactdata1);
885 p2.getContactData(ref contactdata2);
886 bounce = contactdata1.bounce * contactdata2.bounce;
887 mu = (float)Math.Sqrt(contactdata1.
mu * contactdata2.
mu);
889 if (relVlenSQ > 0.01f)
890 mu *= frictionMovementMult;
892 if(d.GeomGetClass(g2) == d.GeomClassID.TriMeshClass &&
893 d.GeomGetClass(g1) == d.GeomClassID.TriMeshClass)
897 case (
int)ActorTypes.Ground:
898 p1.getContactData(ref contactdata1);
899 bounce = contactdata1.bounce * TerrainBounce;
900 mu = (float)Math.Sqrt(contactdata1.
mu * TerrainFriction);
902 if (Math.Abs(p1.Velocity.X) > 0.1f || Math.Abs(p1.Velocity.Y) > 0.1f)
903 mu *= frictionMovementMult;
904 p1.CollidingGround =
true;
906 if(d.GeomGetClass(g1) == d.GeomClassID.TriMeshClass)
910 case (
int)ActorTypes.Water:
918 case (
int)ActorTypes.Ground:
919 if (p2.PhysicsActorType == (
int)ActorTypes.Prim)
921 p2.CollidingGround =
true;
922 p2.getContactData(ref contactdata2);
923 bounce = contactdata2.bounce * TerrainBounce;
924 mu = (float)Math.Sqrt(contactdata2.
mu * TerrainFriction);
929 if (Math.Abs(p2.Velocity.X) > 0.1f || Math.Abs(p2.Velocity.Y) > 0.1f)
930 mu *= frictionMovementMult;
932 if(d.GeomGetClass(g2) == d.GeomClassID.TriMeshClass)
939 case (
int)ActorTypes.Water:
948 bool FeetCollision =
false;
954 maxDepthContact.PenetrationDepth = float.MinValue;
956 minDepthContact.PenetrationDepth = float.MaxValue;
958 SharedTmpcontact.geom.depth = 0;
959 SharedTmpcontact.surface.mu = mu;
960 SharedTmpcontact.surface.bounce = bounce;
963 bool useAltcontact =
false;
966 if(dop1ava || dop2ava)
972 useAltcontact =
false;
976 if ((((OdeCharacter)p1).Collide(g1, g2,
false, ref curContact, ref altContact , ref useAltcontact, ref FeetCollision)))
978 if (p2.PhysicsActorType == (
int)ActorTypes.Agent)
980 p1.CollidingObj =
true;
981 p2.CollidingObj =
true;
983 else if (p2.Velocity.LengthSquared() > 0.0f)
984 p2.CollidingObj =
true;
991 if ((((OdeCharacter)p2).Collide(g2, g1,
true, ref curContact, ref altContact , ref useAltcontact, ref FeetCollision)))
993 if (p1.PhysicsActorType == (
int)ActorTypes.Agent)
995 p1.CollidingObj =
true;
996 p2.CollidingObj =
true;
998 else if (p2.Velocity.LengthSquared() > 0.0f)
999 p1.CollidingObj =
true;
1008 Joint = CreateContacJoint(ref altContact,smoothMesh);
1010 Joint = CreateContacJoint(ref curContact,smoothMesh);
1012 if (Joint == IntPtr.Zero)
1015 d.JointAttach(Joint, b1, b2);
1021 maxDepthContact.Position.X = curContact.pos.X;
1022 maxDepthContact.Position.Y = curContact.pos.Y;
1023 maxDepthContact.Position.Z = curContact.pos.Z;
1024 maxDepthContact.PenetrationDepth = curContact.depth;
1025 maxDepthContact.CharacterFeet = FeetCollision;
1030 minDepthContact.PenetrationDepth = curContact.depth;
1031 minDepthContact.SurfaceNormal.X = curContact.normal.X;
1032 minDepthContact.SurfaceNormal.Y = curContact.normal.Y;
1033 minDepthContact.SurfaceNormal.Z = curContact.normal.Z;
1040 if (!GetCurContactGeom(i, ref curContact))
1046 maxDepthContact.SurfaceNormal.X = minDepthContact.SurfaceNormal.X;
1047 maxDepthContact.SurfaceNormal.Y = minDepthContact.SurfaceNormal.Y;
1048 maxDepthContact.SurfaceNormal.Z = minDepthContact.SurfaceNormal.Z;
1050 collision_accounting_events(p1, p2, maxDepthContact);
1056 uint obj2LocalID = 0;
1058 bool p1events = p1.SubscribedEvents();
1059 bool p2events = p2.SubscribedEvents();
1066 if (!p2events && !p1events)
1069 Vector3 vel = Vector3.Zero;
1076 contact.RelativeSpeed = Vector3.Dot(vel, contact.SurfaceNormal);
1080 case ActorTypes.Agent:
1081 case ActorTypes.Prim:
1085 case ActorTypes.Agent:
1086 case ActorTypes.Prim:
1089 AddCollisionEventReporting(p2);
1090 p2.AddCollisionEvent(p1.ParentActor.LocalID, contact);
1092 obj2LocalID = p2.ParentActor.LocalID;
1095 case ActorTypes.Ground:
1096 case ActorTypes.Unknown:
1103 contact.SurfaceNormal = -contact.SurfaceNormal;
1104 AddCollisionEventReporting(p1);
1105 p1.AddCollisionEvent(obj2LocalID, contact);
1109 case ActorTypes.Ground:
1110 case ActorTypes.Unknown:
1115 AddCollisionEventReporting(p2);
1116 p2.AddCollisionEvent(0, contact);
1127 private void collision_optimized()
1133 foreach (OdeCharacter chr
in _characters)
1138 chr.IsColliding =
false;
1140 chr.CollidingObj =
false;
1142 if(chr.Body == IntPtr.Zero || chr.collider == IntPtr.Zero )
1146 d.SpaceCollide2(chr.collider, StaticSpace, IntPtr.Zero, nearCallback);
1151 d.SpaceCollide(CharsSpace, IntPtr.Zero, nearCallback);
1154 catch (AccessViolationException)
1156 m_log.Warn(
"[PHYSICS]: Unable to collide Character to static space");
1163 foreach (OdePrim aprim
in _activeprims)
1165 aprim.CollisionScore = 0;
1166 aprim.IsColliding =
false;
1169 lock (_activegroups)
1173 foreach (OdePrim aprim
in _activegroups)
1175 if(!aprim.m_outbounds && d.BodyIsEnabled(aprim.Body) &&
1176 aprim.collide_geom != IntPtr.Zero)
1178 d.SpaceCollide2(StaticSpace, aprim.collide_geom, IntPtr.Zero, nearCallback);
1179 d.SpaceCollide2(GroundSpace, aprim.collide_geom, IntPtr.Zero, nearCallback);
1185 m_log.Warn(
"[PHYSICS]: Unable to collide Active to Static: " + e.Message);
1192 d.SpaceCollide(ActiveSpace, IntPtr.Zero, nearCallback);
1196 m_log.Warn(
"[PHYSICS]: Unable to collide in Active: " + e.Message);
1202 d.SpaceCollide2(CharsSpace,ActiveSpace, IntPtr.Zero, nearCallback);
1206 m_log.Warn(
"[PHYSICS]: Unable to collide Active to Character: " + e.Message);
1211 public void AddCollisionEventReporting(
PhysicsActor obj)
1217 if (!_collisionEventPrim.Contains(obj))
1218 _collisionEventPrim.Add(obj);
1227 if (_collisionEventPrim.Contains(obj) && !_collisionEventPrimRemove.Contains(obj))
1228 _collisionEventPrimRemove.Add(obj);
1231 public override float TimeDilation
1233 get {
return m_timeDilation; }
1236 public override bool SupportsNINJAJoints
1238 get {
return false; }
1241 #region Add/Remove Entities
1248 public override PhysicsActor AddAvatar(uint localID,
string avName, Vector3 position, Vector3 size,
float feetOffset,
bool isFlying)
1251 size, feetOffset, avDensity, avMovementDivisorWalk, avMovementDivisorRun);
1252 newAv.Flying = isFlying;
1253 newAv.MinimumGroundFlightOffset = minimumGroundFlightOffset;
1262 if (!_characters.Contains(chr))
1264 _characters.Add(chr);
1266 m_log.DebugFormat(
"[PHYSICS] Added BAD actor {0} to characters list", chr.m_uuid);
1275 if (_characters.Contains(chr))
1277 _characters.Remove(chr);
1284 lock (_badCharacter)
1286 if (!_badCharacter.Contains(chr))
1287 _badCharacter.Add(chr);
1296 d.AllocateODEDataForThread(0);
1307 if (!_activeprims.Contains(activatePrim))
1308 _activeprims.Add(activatePrim);
1314 lock (_activegroups)
1316 if (!_activegroups.Contains(activatePrim))
1317 _activegroups.Add(activatePrim);
1322 PrimitiveBaseShape pbs,
bool isphysical,
bool isPhantom, byte shapeType, uint localID)
1328 newPrim =
new OdePrim(name,
this, position, size, rotation, pbs, isphysical, isPhantom, shapeType, localID);
1330 _prims.Add(newPrim);
1336 Vector3 size, Quaternion rotation,
bool isPhysical,
bool isPhantom, uint localid)
1338 return AddPrim(primName, position, size, rotation, pbs, isPhysical, isPhantom, 0 , localid);
1343 Vector3 size, Quaternion rotation,
bool isPhysical, uint localid)
1345 return AddPrim(primName, position, size, rotation, pbs, isPhysical,
false, 0, localid);
1349 Vector3 size, Quaternion rotation,
bool isPhysical,
bool isPhantom, byte shapeType, uint localid)
1352 return AddPrim(primName, position, size, rotation, pbs, isPhysical,isPhantom, shapeType, localid);
1359 _activeprims.Remove(deactivatePrim);
1364 lock (_activegroups)
1366 _activegroups.Remove(deactivatePrim);
1379 OdePrim p = (OdePrim)prim;
1380 p.setPrimForRemoval();
1392 _prims.Remove(prim);
1400 return _prims.Contains(prm);
1408 return _prims.Contains((OdePrim)actor);
1413 return _characters.Contains((OdeCharacter)actor);
1420 #region Space Separation Calculation
1437 if (geom == IntPtr.Zero)
1441 IntPtr newspace = calculateSpaceForGeom(pos);
1443 if (newspace == currentspace)
1447 if (currentspace != IntPtr.Zero && d.SpaceQuery(currentspace, geom))
1449 if (d.GeomIsSpace(currentspace))
1451 waitForSpaceUnlock(currentspace);
1452 d.SpaceRemove(currentspace, geom);
1454 if (d.SpaceGetSublevel(currentspace) > 2 && d.SpaceGetNumGeoms(currentspace) == 0)
1456 d.SpaceDestroy(currentspace);
1461 m_log.Info(
"[Physics]: Invalid or empty Space passed to 'MoveGeomToStaticSpace':" + currentspace +
1467 currentspace = d.GeomGetSpace(geom);
1468 if (currentspace != IntPtr.Zero)
1470 if (d.GeomIsSpace(currentspace))
1472 waitForSpaceUnlock(currentspace);
1473 d.SpaceRemove(currentspace, geom);
1475 if (d.SpaceGetSublevel(currentspace) > 2 && d.SpaceGetNumGeoms(currentspace) == 0)
1477 d.SpaceDestroy(currentspace);
1485 waitForSpaceUnlock(newspace);
1486 d.SpaceAdd(newspace, geom);
1502 return staticPrimspaceOffRegion[0];
1505 return staticPrimspaceOffRegion[2];
1507 x = (int)(pos.X * spacesPerMeterX);
1508 if (x > spaceGridMaxX)
1509 return staticPrimspaceOffRegion[1];
1511 y = (int)(pos.Y * spacesPerMeterY);
1512 if (y > spaceGridMaxY)
1513 return staticPrimspaceOffRegion[3];
1515 return staticPrimspace[x, y];
1532 ChangesQueue.Enqueue(item);
1550 if (world == IntPtr.Zero)
1552 ChangesQueue.Clear();
1556 d.AllocateODEDataForThread(~0U);
1560 int donechanges = 0;
1561 if (ChangesQueue.Count > 0)
1563 m_log.InfoFormat(
"[ubOde] start processing pending actor operations");
1564 int tstart = Util.EnvironmentTickCount();
1566 while (ChangesQueue.Dequeue(out item))
1568 if (item.actor != null)
1573 ((OdeCharacter)item.actor).DoAChange(item.what, item.arg);
1574 else if (((
OdePrim)item.actor).DoAChange(item.what, item.arg))
1575 RemovePrimThreadLocked((
OdePrim)item.actor);
1579 m_log.WarnFormat(
"[PHYSICS]: Operation failed for a actor {0} {1}",
1580 item.actor.Name, item.what.ToString());
1585 int time = Util.EnvironmentTickCountSubtract(tstart);
1586 m_log.InfoFormat(
"[ubOde] finished {0} operations in {1}ms", donechanges, time);
1588 m_log.InfoFormat(
"[ubOde] {0} prim actors loaded",_prims.Count);
1603 DateTime now = DateTime.UtcNow;
1604 TimeSpan timedif = now - m_lastframe;
1605 float timeStep = (float)timedif.TotalSeconds;
1609 step_time += timeStep;
1611 if (step_time < HalfOdeStep)
1623 lock (SimulationLock)
1626 if (world == IntPtr.Zero)
1628 ChangesQueue.Clear();
1636 int loopstartMS = Util.EnvironmentTickCount();
1638 int changestimeMS = 0;
1639 int maxChangestime = (int)(reqTimeStep * 500f);
1640 int maxLoopTime = (int)(reqTimeStep * 1200f);
1642 d.AllocateODEDataForThread(~0U);
1644 if (ChangesQueue.Count > 0)
1646 while (ChangesQueue.Dequeue(out item))
1648 if (item.actor != null)
1653 ((OdeCharacter)item.actor).DoAChange(item.what, item.arg);
1654 else if (((
OdePrim)item.actor).DoAChange(item.what, item.arg))
1655 RemovePrimThreadLocked((
OdePrim)item.actor);
1659 m_log.WarnFormat(
"[PHYSICS]: doChange failed for a actor {0} {1}",
1660 item.actor.Name, item.what.ToString());
1663 changestimeMS = Util.EnvironmentTickCountSubtract(loopstartMS);
1664 if (changestimeMS > maxChangestime)
1670 while (step_time > HalfOdeStep)
1675 m_global_contactcount = 0;
1681 List<OdeCharacter> defects =
new List<OdeCharacter>();
1685 actor.Move(defects);
1687 if (defects.Count != 0)
1691 RemoveCharacter(defect);
1698 lock (_activegroups)
1700 foreach (
OdePrim aprim
in _activegroups)
1706 m_rayCastManager.ProcessQueuedRequests();
1708 collision_optimized();
1717 case ActorTypes.Agent:
1719 cobj.AddCollisionFrameTime((int)(odetimestepMS));
1720 cobj.SendCollisions();
1723 case ActorTypes.Prim:
1725 if (pobj.
Body == IntPtr.Zero || (d.BodyIsEnabled(pobj.
Body) && !pobj.m_outbounds))
1726 if (!pobj.m_outbounds)
1728 pobj.AddCollisionFrameTime((int)(odetimestepMS));
1729 pobj.SendCollisions();
1735 foreach (
PhysicsActor obj
in _collisionEventPrimRemove)
1736 _collisionEventPrim.Remove(obj);
1738 _collisionEventPrimRemove.Clear();
1741 d.WorldQuickStep(world, ODE_STEPSIZE);
1742 d.JointGroupEmpty(contactgroup);
1761 lock (_activegroups)
1764 foreach (
OdePrim actor
in _activegroups)
1768 actor.UpdatePositionAndVelocity(framecount);
1776 m_log.ErrorFormat(
"[PHYSICS]: {0}, {1}, {2}", e.Message, e.TargetSite, e);
1780 step_time -= ODE_STEPSIZE;
1783 looptimeMS = Util.EnvironmentTickCountSubtract(loopstartMS);
1784 if (looptimeMS > maxLoopTime)
1788 lock (_badCharacter)
1790 if (_badCharacter.Count > 0)
1794 RemoveCharacter(chr);
1797 _badCharacter.Clear();
1801 timedif = now - m_lastMeshExpire;
1803 if (timedif.Seconds > 10)
1805 mesher.ExpireReleaseMeshs();
1806 m_lastMeshExpire = now;
1855 if (physics_logging && (physics_logging_interval > 0) && (framecount % physics_logging_interval == 0))
1857 string fname =
"state-" + world.ToString() +
".DIF";
1858 string prefix =
"world" + world.ToString();
1860 if (physics_logging_append_existing_logfile)
1862 string header =
"-------------- START OF PHYSICS FRAME " + framecount.ToString() +
" --------------";
1863 TextWriter fwriter = File.AppendText(fname);
1864 fwriter.WriteLine(header);
1868 d.WorldExportDIF(world, fname, physics_logging_append_existing_logfile, prefix);
1871 fps = (float)nodeframes * ODE_STEPSIZE / reqTimeStep;
1873 if(step_time < HalfOdeStep)
1874 m_timeDilation = 1.0f;
1875 else if (step_time > m_SkipFramesAtms)
1878 m_timeDilation = 0.0f;
1880 m_lastframe = DateTime.UtcNow;
1884 m_timeDilation = ODE_STEPSIZE / step_time;
1885 if (m_timeDilation > 1)
1898 public override bool IsThreaded
1901 get {
return (
false); }
1910 if (m_suportCombine)
1917 IntPtr heightFieldGeom = IntPtr.Zero;
1918 if (!RegionTerrain.TryGetValue(
new Vector3(offsetX, offsetY, 0), out heightFieldGeom))
1921 if (heightFieldGeom == IntPtr.Zero)
1924 if (!TerrainHeightFieldHeights.ContainsKey(heightFieldGeom))
1944 int regsizeX = (int)m_regionWidth + 3;
1945 int regsizeY = (int)m_regionHeight + 3;
1946 int regsize = regsizeX;
1950 if (x < regsizeX - 1)
1960 if (y < regsizeY - 1)
1979 if (x < regsizeX - 1)
1989 if (y < regsizeY - 1)
2008 float[] heights = TerrainHeightFieldHeights[heightFieldGeom];
2023 h0 = ((float)heights[iy]);
2028 h2 = (float)heights[iy];
2029 h1 = (h2 - h0) * dy;
2030 h2 = ((float)heights[iy + 1] - h2) * dx;
2035 h2 = (float)heights[iy];
2036 h1 = (h2 - h0) * dx;
2037 h2 = (((float)heights[iy + regsize]) - h2) * dy;
2040 return h0 + h1 + h2;
2048 if (m_suportCombine)
2055 IntPtr heightFieldGeom = IntPtr.Zero;
2056 Vector3 norm =
new Vector3(0, 0, 1);
2058 if (!RegionTerrain.TryGetValue(
new Vector3(offsetX, offsetY, 0), out heightFieldGeom))
2061 if (heightFieldGeom == IntPtr.Zero)
2064 if (!TerrainHeightFieldHeights.ContainsKey(heightFieldGeom))
2084 int regsizeX = (int)m_regionWidth + 3;
2085 int regsizeY = (int)m_regionHeight + 3;
2086 int regsize = regsizeX;
2089 int ystep = regsizeX;
2090 bool firstTri =
false;
2094 if (x < regsizeX - 1)
2104 if (y < regsizeY - 1)
2126 if (x < regsizeX - 1)
2136 if (y < regsizeY - 1)
2156 float[] heights = TerrainHeightFieldHeights[heightFieldGeom];
2160 h1 = ((float)heights[iy]);
2162 h0 = (float)heights[iy];
2163 h2 = (float)heights[iy+xstep];
2169 h2 = ((float)heights[iy]);
2171 h0 = ((float)heights[iy]);
2172 h1 = (float)heights[iy+ystep];
2183 if (m_worldOffset != Vector3.Zero && m_parentScene != null)
2187 ((ODEScene)m_parentScene).SetTerrain(heightMap, m_worldOffset);
2192 SetTerrain(heightMap, m_worldOffset);
2199 SetTerrain(heightMap, pOffset);
2205 OSSetTerrain(heightMap, pOffset);
2207 OriSetTerrain(heightMap, pOffset);
2217 uint regionsizeX = m_regionWidth;
2218 uint regionsizeY = m_regionHeight;
2221 uint heightmapWidth = regionsizeY + 2;
2222 uint heightmapHeight = regionsizeX + 2;
2224 uint heightmapWidthSamples = heightmapWidth + 1;
2225 uint heightmapHeightSamples = heightmapHeight + 1;
2227 _heightmap =
new float[heightmapWidthSamples * heightmapHeightSamples];
2229 const float scale = 1.0f;
2230 const float offset = 0.0f;
2231 const float thickness = 10f;
2235 float hfmin = float.MaxValue;
2236 float hfmax = float.MinValue;
2241 uint maxXX = regionsizeX - 1;
2242 uint maxYY = regionsizeY - 1;
2248 for (uint x = 0; x < heightmapWidthSamples; x++)
2250 if (x > 1 && xx < maxXX)
2253 for (uint y = 0; y < heightmapHeightSamples; y++)
2255 if (y > 1 && y < maxYY)
2258 val = heightMap[yy + xx];
2261 _heightmap[xt + y] = val;
2268 xt += heightmapHeightSamples;
2273 d.AllocateODEDataForThread(~0U);
2275 IntPtr GroundGeom = IntPtr.Zero;
2276 if (RegionTerrain.TryGetValue(pOffset, out GroundGeom))
2278 RegionTerrain.Remove(pOffset);
2279 if (GroundGeom != IntPtr.Zero)
2281 actor_name_map.Remove(GroundGeom);
2282 d.GeomDestroy(GroundGeom);
2284 if (TerrainHeightFieldHeights.ContainsKey(GroundGeom))
2286 TerrainHeightFieldHeightsHandlers[GroundGeom].Free();
2287 TerrainHeightFieldHeightsHandlers.Remove(GroundGeom);
2288 TerrainHeightFieldHeights.Remove(GroundGeom);
2292 IntPtr HeightmapData = d.GeomHeightfieldDataCreate();
2294 GCHandle _heightmaphandler = GCHandle.Alloc(_heightmap, GCHandleType.Pinned);
2296 d.GeomHeightfieldDataBuildSingle(HeightmapData, _heightmaphandler.AddrOfPinnedObject(), 0,
2297 heightmapHeight, heightmapWidth ,
2298 (
int)heightmapHeightSamples, (int)heightmapWidthSamples, scale,
2299 offset, thickness, wrap);
2301 d.GeomHeightfieldDataSetBounds(HeightmapData, hfmin - 1, hfmax + 1);
2303 GroundGeom = d.CreateHeightfield(GroundSpace, HeightmapData, 1);
2305 if (GroundGeom != IntPtr.Zero)
2308 d.GeomSetCollideBits(GroundGeom, 0);
2311 pa.Name =
"Terrain";
2312 pa.PhysicsActorType = (int)
ActorTypes.Ground;
2313 actor_name_map[GroundGeom] = pa;
2317 d.Quaternion q =
new d.Quaternion();
2323 d.GeomSetQuaternion(GroundGeom, ref q);
2324 d.GeomSetPosition(GroundGeom, pOffset.X + m_regionWidth * 0.5f, pOffset.Y + m_regionHeight * 0.5f, 0.0f);
2325 RegionTerrain.Add(pOffset, GroundGeom);
2326 TerrainHeightFieldHeights.Add(GroundGeom, _heightmap);
2327 TerrainHeightFieldHeightsHandlers.Add(GroundGeom, _heightmaphandler);
2339 uint regionsizeX = m_regionWidth;
2340 uint regionsizeY = m_regionHeight;
2342 uint heightmapWidth = regionsizeX + 2;
2343 uint heightmapHeight = regionsizeY + 2;
2345 uint heightmapWidthSamples = heightmapWidth + 1;
2346 uint heightmapHeightSamples = heightmapHeight + 1;
2348 _heightmap =
new float[heightmapWidthSamples * heightmapHeightSamples];
2351 float hfmin = float.MaxValue;
2356 uint maxXX = regionsizeX - 1;
2357 uint maxYY = regionsizeY - 1;
2364 for (uint y = 0; y < heightmapHeightSamples; y++)
2366 if (y > 1 && y < maxYY)
2369 for (uint x = 0; x < heightmapWidthSamples; x++)
2371 if (x > 1 && x < maxXX)
2374 val = heightMap[yy + xx];
2377 _heightmap[yt + x] = val;
2384 yt += heightmapWidthSamples;
2388 IntPtr GroundGeom = IntPtr.Zero;
2389 if (RegionTerrain.TryGetValue(pOffset, out GroundGeom))
2391 RegionTerrain.Remove(pOffset);
2392 if (GroundGeom != IntPtr.Zero)
2394 actor_name_map.Remove(GroundGeom);
2395 d.GeomDestroy(GroundGeom);
2397 if (TerrainHeightFieldHeights.ContainsKey(GroundGeom))
2399 if (TerrainHeightFieldHeightsHandlers[GroundGeom].IsAllocated)
2400 TerrainHeightFieldHeightsHandlers[GroundGeom].Free();
2401 TerrainHeightFieldHeightsHandlers.Remove(GroundGeom);
2402 TerrainHeightFieldHeights.Remove(GroundGeom);
2406 IntPtr HeightmapData = d.GeomOSTerrainDataCreate();
2409 float thickness = hfmin;
2413 GCHandle _heightmaphandler = GCHandle.Alloc(_heightmap, GCHandleType.Pinned);
2415 d.GeomOSTerrainDataBuild(HeightmapData, _heightmaphandler.AddrOfPinnedObject(), 0, 1.0f,
2416 (
int)heightmapWidthSamples, (int)heightmapHeightSamples,
2420 GroundGeom = d.CreateOSTerrain(GroundSpace, HeightmapData, 1);
2421 if (GroundGeom != IntPtr.Zero)
2424 d.GeomSetCollideBits(GroundGeom, 0);
2428 pa.Name =
"Terrain";
2429 pa.PhysicsActorType = (int)
ActorTypes.Ground;
2430 actor_name_map[GroundGeom] = pa;
2434 d.GeomSetPosition(GroundGeom, pOffset.X + m_regionWidth * 0.5f, pOffset.Y + m_regionHeight * 0.5f, 0.0f);
2435 RegionTerrain.Add(pOffset, GroundGeom);
2436 TerrainHeightFieldHeights.Add(GroundGeom, _heightmap);
2437 TerrainHeightFieldHeightsHandlers.Add(GroundGeom, _heightmaphandler);
2453 return m_suportCombine;
2458 waterlevel = baseheight;
2466 if (world == IntPtr.Zero)
2469 d.AllocateODEDataForThread(~0U);
2471 if (m_meshWorker != null)
2472 m_meshWorker.Stop();
2474 if (m_rayCastManager != null)
2476 m_rayCastManager.Dispose();
2477 m_rayCastManager = null;
2482 ChangesQueue.Clear();
2483 foreach (
OdePrim prm
in _prims)
2485 prm.DoAChange(changes.Remove, null);
2486 _collisionEventPrim.Remove(prm);
2495 _characters.CopyTo(chtorem);
2498 ChangesQueue.Clear();
2500 ch.DoAChange(changes.Remove, null);
2503 foreach (IntPtr GroundGeom
in RegionTerrain.Values)
2505 if (GroundGeom != IntPtr.Zero)
2506 d.GeomDestroy(GroundGeom);
2509 RegionTerrain.Clear();
2511 if (TerrainHeightFieldHeightsHandlers.Count > 0)
2513 foreach (GCHandle gch
in TerrainHeightFieldHeightsHandlers.Values)
2515 if (gch.IsAllocated)
2520 TerrainHeightFieldHeightsHandlers.Clear();
2521 TerrainHeightFieldHeights.Clear();
2523 if (ContactgeomsArray != IntPtr.Zero)
2525 Marshal.FreeHGlobal(ContactgeomsArray);
2526 ContactgeomsArray = IntPtr.Zero;
2528 if (GlobalContactsArray != IntPtr.Zero)
2530 Marshal.FreeHGlobal(GlobalContactsArray);
2531 GlobalContactsArray = IntPtr.Zero;
2534 d.WorldDestroy(world);
2535 world = IntPtr.Zero;
2542 Dictionary<uint, float> returncolliders =
new Dictionary<uint, float>();
2546 foreach (
OdePrim prm
in _prims)
2550 returncolliders.Add(prm.LocalID, prm.CollisionScore);
2552 prm.CollisionScore = 0f;
2560 return returncolliders;
2570 if (retMethod != null)
2574 req.callbackMethod = retMethod;
2575 req.length = length;
2576 req.Normal = direction;
2577 req.Origin = position;
2579 req.filter = RayFilterFlags.AllPrims;
2581 m_rayCastManager.QueueRequest(req);
2587 if (retMethod != null)
2591 req.callbackMethod = retMethod;
2592 req.length = length;
2593 req.Normal = direction;
2594 req.Origin = position;
2596 req.filter = RayFilterFlags.AllPrims;
2598 m_rayCastManager.QueueRequest(req);
2603 public override List<ContactResult>
RaycastWorld(Vector3 position, Vector3 direction,
float length,
int Count)
2605 List<ContactResult> ourresults =
new List<ContactResult>();
2606 object SyncObject =
new object();
2608 RayCallback retMethod = delegate(List<ContactResult> results)
2612 ourresults = results;
2613 Monitor.PulseAll(SyncObject);
2619 req.callbackMethod = retMethod;
2620 req.length = length;
2621 req.Normal = direction;
2622 req.Origin = position;
2624 req.filter = RayFilterFlags.AllPrims;
2628 m_rayCastManager.QueueRequest(req);
2629 if (!Monitor.Wait(SyncObject, 500))
2643 object SyncObject =
new object();
2644 List<ContactResult> ourresults =
new List<ContactResult>();
2646 RayCallback retMethod = delegate(List<ContactResult> results)
2650 ourresults = results;
2651 Monitor.PulseAll(SyncObject);
2657 req.callbackMethod = retMethod;
2658 req.length = length;
2659 req.Normal = direction;
2660 req.Origin = position;
2662 req.filter = filter;
2666 m_rayCastManager.QueueRequest(req);
2667 if (!Monitor.Wait(SyncObject, 500))
2677 return new List<ContactResult>();
2681 geom = ((OdePrim)actor).prim_geom;
2683 geom = ((OdePrim)actor).prim_geom;
2685 return new List<ContactResult>();
2687 if (geom == IntPtr.Zero)
2688 return new List<ContactResult>();
2690 List<ContactResult> ourResults = null;
2691 object SyncObject =
new object();
2693 RayCallback retMethod = delegate(List<ContactResult> results)
2697 ourResults = results;
2698 Monitor.PulseAll(SyncObject);
2704 req.callbackMethod = retMethod;
2705 req.length = length;
2706 req.Normal = direction;
2707 req.Origin = position;
2713 m_rayCastManager.QueueRequest(req);
2714 if (!Monitor.Wait(SyncObject, 500))
2715 return new List<ContactResult>();
2718 if (ourResults == null)
2719 return new List<ContactResult>();
2723 public override List<ContactResult>
BoxProbe(Vector3 position, Vector3 size, Quaternion orientation,
int Count,
RayFilterFlags flags)
2725 List<ContactResult> ourResults = null;
2726 object SyncObject =
new object();
2732 ourResults = results;
2733 Monitor.PulseAll(SyncObject);
2739 req.callbackMethod = retMethod;
2741 req.Origin = position;
2742 req.orientation = orientation;
2748 m_rayCastManager.QueueRequest(req);
2749 if (!Monitor.Wait(SyncObject, 500))
2750 return new List<ContactResult>();
2753 if (ourResults == null)
2754 return new List<ContactResult>();
2760 List<ContactResult> ourResults = null;
2761 object SyncObject =
new object();
2765 ourResults = results;
2766 Monitor.PulseAll(SyncObject);
2771 req.callbackMethod = retMethod;
2772 req.length = radius;
2773 req.Origin = position;
2780 m_rayCastManager.QueueRequest(req);
2781 if (!Monitor.Wait(SyncObject, 500))
2782 return new List<ContactResult>();
2785 if (ourResults == null)
2786 return new List<ContactResult>();
2792 IntPtr geom = IntPtr.Zero;;
2797 geom = ((OdePrim)actor).prim_geom;
2799 geom = ((OdePrim)actor).prim_geom;
2802 List<ContactResult> ourResults = null;
2803 object SyncObject =
new object();
2807 ourResults = results;
2808 Monitor.PulseAll(SyncObject);
2813 req.callbackMethod = retMethod;
2814 req.length = plane.W;
2815 req.Normal.X = plane.X;
2816 req.Normal.Y = plane.Y;
2817 req.Normal.Z = plane.Z;
2823 m_rayCastManager.QueueRequest(req);
2824 if (!Monitor.Wait(SyncObject, 500))
2825 return new List<ContactResult>();
2828 if (ourResults == null)
2829 return new List<ContactResult>();
2835 Util.FireAndForget( delegate
2838 if(sitAvatar != null)
2839 sitAvatar.Sit(actor, AbsolutePosition, CameraPosition, offset, AvatarSize, PhysicsSitResponse);
override List< ContactResult > PlaneProbe(PhysicsActor actor, Vector4 plane, int Count, RayFilterFlags flags)
void SetTerrain(float[] heightMap, Vector3 pOffset)
override void RaycastWorld(Vector3 position, Vector3 direction, float length, RaycastCallback retMethod)
Queue a raycast against the physics scene. The provided callback method will be called when the rayca...
override float CollisionScore
override object RaycastWorld(Vector3 position, Vector3 direction, float length, int Count, RayFilterFlags filter)
IntPtr calculateSpaceForGeom(Vector3 pos)
Calculates the space the prim should be in by its position
override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position, Vector3 size, Quaternion rotation, bool isPhysical, uint localid)
abstract int PhysicsActorType
void RemovePrimThreadLocked(OdePrim prim)
override void DeleteTerrain()
Processes raycast requests as ODE is in a state to be able to do them. This ensures that it's thread ...
void addActiveGroups(OdePrim activatePrim)
override List< ContactResult > SphereProbe(Vector3 position, float radius, int Count, RayFilterFlags flags)
override int SitAvatar(PhysicsActor actor, Vector3 AbsolutePosition, Vector3 CameraPosition, Vector3 offset, Vector3 AvatarSize, SitAvatarCallback PhysicsSitResponse)
override bool IsPhysical
Is this prim subject to physics? Even if not, it's still solid for collision purposes.
void remActivePrim(OdePrim deactivatePrim)
delegate void ProbePlaneCallback(List< ContactResult > list)
delegate void RayCallback(List< ContactResult > list)
override void ProcessPreSimulation()
ODEMeshWorker m_meshWorker
bool haveActor(PhysicsActor actor)
IntPtr MoveGeomToStaticSpace(IntPtr geom, Vector3 pos, IntPtr currentspace)
Called when a static prim moves or becomes static Places the prim in a space one the static sub-space...
override PhysicsActor AddAvatar(uint localID, string avName, Vector3 position, Vector3 size, float feetOffset, bool isFlying)
void remActiveGroup(OdePrim deactivatePrim)
delegate void RaycastCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance, Vector3 normal)
override void GetResults()
override void RemoveAvatar(PhysicsActor actor)
Remove an avatar.
override void SetWaterLevel(float baseheight)
Vector3 GetTerrainNormalAtXY(float x, float y)
override void RemovePrim(PhysicsActor prim)
Remove a prim.
float GetTerrainHeightAtXY(float x, float y)
delegate void ProbeBoxCallback(List< ContactResult > list)
void BadCharacter(OdeCharacter chr)
void OSSetTerrain(float[] heightMap, Vector3 pOffset)
OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion rotation
override void SetTerrain(float[] heightMap)
override List< ContactResult > RaycastWorld(Vector3 position, Vector3 direction, float length, int Count)
override void RaycastWorld(Vector3 position, Vector3 direction, float length, int Count, RayCallback retMethod)
void RemoveCollisionEventReporting(PhysicsActor obj)
Remove actor from the list that should receive collision events in the simulate loop.
override bool SupportsRayCast()
True if the physics plugin supports raycasting against the physics scene
bool havePrim(OdePrim prm)
override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position, Vector3 size, Quaternion rotation, bool isPhysical, bool isPhantom, byte shapeType, uint localid)
void addActivePrim(OdePrim activatePrim)
delegate void ProbeSphereCallback(List< ContactResult > list)
static Object SimulationLock
override float Simulate(float reqTimeStep)
This is our main simulate loop It's thread locked by a Mutex in the scene. It holds Collisions...
override bool SupportsCombining()
ODEScene(Scene pscene, IConfigSource psourceconfig, string pname, bool pOSOdeLib)
void AddCharacter(OdeCharacter chr)
void RemoveCharacter(OdeCharacter chr)
delegate void SitAvatarCallback(int status, uint partID, Vector3 offset, Quaternion Orientation)
void OriSetTerrain(float[] heightMap, Vector3 pOffset)
override List< ContactResult > BoxProbe(Vector3 position, Vector3 size, Quaternion orientation, int Count, RayFilterFlags flags)
Material
Material type for a primitive
override bool SupportsRaycastWorldFiltered()
override List< ContactResult > RaycastActor(PhysicsActor actor, Vector3 position, Vector3 direction, float length, int Count, RayFilterFlags flags)
override PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 velocity, Vector3 size, bool isFlying)
Add an avatar
override void CombineTerrain(float[] heightMap, Vector3 pOffset)
override void AddPhysicsActorTaint(PhysicsActor prim)
Called after our prim properties are set Scale, position etc. We use this event queue like method to ...
override Dictionary< uint, float > GetTopColliders()
void AddChange(PhysicsActor actor, changes what, Object arg)
Called to queue a change to a actor to use in place of old taint mechanism so changes do have a time ...