private bool GetCurContactGeom(int index, ref d.ContactGeom newcontactgeom) { if (ContactgeomsArray == IntPtr.Zero || index >= contactsPerCollision) { return(false); } IntPtr contactptr = new IntPtr(ContactgeomsArray.ToInt64() + (index * d.ContactGeom.unmanagedSizeOf)); newcontactgeom = (d.ContactGeom)Marshal.PtrToStructure(contactptr, typeof(d.ContactGeom)); return(true); }
// This is the standard Near. Uses space AABBs to speed up detection. private void near(IntPtr space, IntPtr g1, IntPtr g2) { //Don't test against heightfield Geom, or you'll be sorry! /* * terminate called after throwing an instance of 'std::bad_alloc' * what(): std::bad_alloc * Stacktrace: * * at (wrapper managed-to-native) Ode.NET.d.Collide (intptr,intptr,int,Ode.NET.d/ContactGeom[],int) <0x00004> * at (wrapper managed-to-native) Ode.NET.d.Collide (intptr,intptr,int,Ode.NET.d/ContactGeom[],int) <0xffffffff> * at OpenSim.Region.Physics.OdePlugin.ODERayCastRequestManager.near (intptr,intptr,intptr) <0x00280> * at (wrapper native-to-managed) OpenSim.Region.Physics.OdePlugin.ODERayCastRequestManager.near (intptr,intptr,intptr) <0xfff * fffff> * at (wrapper managed-to-native) Ode.NET.d.SpaceCollide2 (intptr,intptr,intptr,Ode.NET.d/NearCallback) <0x00004> * at (wrapper managed-to-native) Ode.NET.d.SpaceCollide2 (intptr,intptr,intptr,Ode.NET.d/NearCallback) <0xffffffff> * at OpenSim.Region.Physics.OdePlugin.ODERayCastRequestManager.RayCast (OpenSim.Region.Physics.OdePlugin.ODERayCastRequest) < * 0x00114> * at OpenSim.Region.Physics.OdePlugin.ODERayCastRequestManager.ProcessQueuedRequests () <0x000eb> * at OpenSim.Region.Physics.OdePlugin.OdeScene.Simulate (single) <0x017e6> * at OpenSim.Region.Framework.Scenes.SceneGraph.UpdatePhysics (double) <0x00042> * at OpenSim.Region.Framework.Scenes.Scene.Update () <0x0039e> * at OpenSim.Region.Framework.Scenes.Scene.Heartbeat (object) <0x00019> * at (wrapper runtime-invoke) object.runtime_invoke_void__this___object (object,intptr,intptr,intptr) <0xffffffff> * * Native stacktrace: * * mono [0x80d2a42] * [0xb7f5840c] * /lib/i686/cmov/libc.so.6(abort+0x188) [0xb7d1a018] * /usr/lib/libstdc++.so.6(_ZN9__gnu_cxx27__verbose_terminate_handlerEv+0x158) [0xb45fc988] * /usr/lib/libstdc++.so.6 [0xb45fa865] * /usr/lib/libstdc++.so.6 [0xb45fa8a2] * /usr/lib/libstdc++.so.6 [0xb45fa9da] * /usr/lib/libstdc++.so.6(_Znwj+0x83) [0xb45fb033] * /usr/lib/libstdc++.so.6(_Znaj+0x1d) [0xb45fb11d] * libode.so(_ZN13dxHeightfield23dCollideHeightfieldZoneEiiiiP6dxGeomiiP12dContactGeomi+0xd04) [0xb46678e4] * libode.so(_Z19dCollideHeightfieldP6dxGeomS0_iP12dContactGeomi+0x54b) [0xb466832b] * libode.so(dCollide+0x102) [0xb46571b2] * [0x95cfdec9] * [0x8ea07fe1] * [0xab260146] * libode.so [0xb465a5c4] * libode.so(_ZN11dxHashSpace8collide2EPvP6dxGeomPFvS0_S2_S2_E+0x75) [0xb465bcf5] * libode.so(dSpaceCollide2+0x177) [0xb465ac67] * [0x95cf978e] * [0x8ea07945] * [0x95cf2bbc] * [0xab2787e7] * [0xab419fb3] * [0xab416657] * [0xab415bda] * [0xb609b08e] * mono(mono_runtime_delegate_invoke+0x34) [0x8192534] * mono [0x81a2f0f] * mono [0x81d28b6] * mono [0x81ea2c6] * /lib/i686/cmov/libpthread.so.0 [0xb7e744c0] * /lib/i686/cmov/libc.so.6(clone+0x5e) [0xb7dcd6de] */ // Exclude heightfield geom if (g1 == IntPtr.Zero || g2 == IntPtr.Zero) { return; } if (d.GeomGetClass(g1) == d.GeomClassID.HeightfieldClass || d.GeomGetClass(g2) == d.GeomClassID.HeightfieldClass) { return; } // Raytest against AABBs of spaces first, then dig into the spaces it hits for actual geoms. 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) { MainConsole.Instance.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; } int count = 0; try { if (g1 == g2) { return; // Can't collide with yourself } count = d.CollidePtr(g1, g2, (contactsPerCollision & 0xffff), ContactgeomsArray, d.ContactGeom.unmanagedSizeOf); } catch (SEHException) { MainConsole.Instance.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."); } catch (Exception e) { MainConsole.Instance.WarnFormat("[PHYSICS]: Unable to collide test an object: {0}", e); return; } PhysicsActor p1 = null; if (g1 != IntPtr.Zero) { m_scene.actor_name_map.TryGetValue(g1, out p1); } // Loop over contacts, build results. d.ContactGeom curContact = new d.ContactGeom(); for (int i = 0; i < count; i++) { if (!GetCurContactGeom(i, ref curContact)) { break; } if (p1 != null) { if (p1 is AuroraODEPrim) { ContactResult collisionresult = new ContactResult { ConsumerID = ((AuroraODEPrim)p1).LocalID, Pos = new Vector3(curContact.pos.X, curContact.pos.Y, curContact.pos.Z), Depth = curContact.depth, Normal = new Vector3(curContact.normal.X, curContact.normal.Y, curContact.normal.Z) }; lock (m_contactResults) m_contactResults.Add(collisionresult); } } } }
/// <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 if (g1 == IntPtr.Zero || g2 == IntPtr.Zero || g1 == g2) return; // 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)) { // 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 (Exception e) { MainConsole.Instance.WarnFormat("[PHYSICS]: SpaceCollide2 failed: {0} ", e); return; } return; } IntPtr b1 = d.GeomGetBody(g1); IntPtr b2 = d.GeomGetBody(g2); int FindContactsTime = Util.EnvironmentTickCount(); // 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; count = d.CollidePtr(g1, g2, (contactsPerCollision & 0xffff), ContactgeomsArray, d.ContactGeom.unmanagedSizeOf); } catch (Exception e) { MainConsole.Instance.WarnFormat("[PHYSICS]: ode Collide failed: {0} ", e); PhysicsActor badObj; if (actor_name_map.TryGetValue(g1, out badObj)) if (badObj is AuroraODEPrim) RemovePrim((AuroraODEPrim)badObj); else if (badObj is AuroraODECharacter) RemoveAvatar((AuroraODECharacter)badObj); if (actor_name_map.TryGetValue(g2, out badObj)) if (badObj is AuroraODEPrim) RemovePrim((AuroraODEPrim)badObj); else if (badObj is AuroraODECharacter) RemoveAvatar((AuroraODECharacter)badObj); return; } if (count == 0) 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; /* if (p1 is AuroraODEPrim && (p1 as AuroraODEPrim)._zeroFlag) (p1 as AuroraODEPrim)._zeroFlag = false; if (p2 is AuroraODEPrim && (p2 as AuroraODEPrim)._zeroFlag) (p2 as AuroraODEPrim)._zeroFlag = false; */ m_StatFindContactsTime = Util.EnvironmentTickCountSubtract(FindContactsTime); if (p1.CollisionScore >= float.MaxValue - count) p1.CollisionScore = 0; p1.CollisionScore += count; if (p2.CollisionScore >= float.MaxValue - count) p2.CollisionScore = 0; p2.CollisionScore += count; int ContactLoopTime = Util.EnvironmentTickCount(); ContactPoint maxDepthContact = new ContactPoint(); d.ContactGeom curContact = new d.ContactGeom(); int NotSkipedCount = 0; #region Contact Loop IntPtr joint = IntPtr.Zero; for (int i = 0; i < count; i++) { if (!GetCurContactGeom(i, ref curContact)) break; if (curContact.depth > maxDepthContact.PenetrationDepth) { maxDepthContact.PenetrationDepth = curContact.depth; maxDepthContact.Position.X = curContact.pos.X; maxDepthContact.Position.Y = curContact.pos.Y; maxDepthContact.Position.Z = curContact.pos.Z; maxDepthContact.Type = (ActorTypes) p1.PhysicsActorType; maxDepthContact.SurfaceNormal.X = curContact.normal.X; maxDepthContact.SurfaceNormal.Y = curContact.normal.Y; maxDepthContact.SurfaceNormal.Z = curContact.normal.Z; } bool p2col = true; // We only need to test p2 for 'jump crouch purposes' if (p2 is AuroraODECharacter && p1.PhysicsActorType == (int) ActorTypes.Prim) { // Testing if the collision is at the feet of the avatar if ((p2.Position.Z - maxDepthContact.Position.Z) < (p2.Size.Z*0.6f)) p2col = false; } p2.IsColliding = p2col; // 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 PhysicsObject && ((PhysicsObject) p1).VolumeDetect) skipThisContact = true; // No collision on volume detect prims if (p2 is PhysicsObject && ((PhysicsObject) p2).VolumeDetect) skipThisContact = true; // No collision on volume detect prims if (curContact.depth < 0f) skipThisContact = true; if (!skipThisContact && m_filterCollisions && checkDupe(curContact, p2.PhysicsActorType)) skipThisContact = true; if (!skipThisContact) { NotSkipedCount++; // If we're colliding against terrain if (p1.PhysicsActorType == (int) ActorTypes.Ground) { if (p2.PhysicsActorType == (int) ActorTypes.Prim) { if (m_filterCollisions) _perloopContact.Add(curContact); ((AuroraODEPrim)p2).GetContactParam(p2, ref newGlobalcontact); joint = CreateContacJoint(ref curContact); } //Can't collide against anything else, agents do their own ground checks } else if ((p1.PhysicsActorType == (int) ActorTypes.Agent) && (p2.PhysicsActorType == (int) ActorTypes.Agent)) { GetContactParam(0.0f, AvatarContactBounce, ref newGlobalcontact); if (m_filterCollisions) _perloopContact.Add(curContact); joint = CreateContacJoint(ref curContact); } else if (p1.PhysicsActorType == (int) ActorTypes.Prim) { if (p2.PhysicsActorType == (int) ActorTypes.Agent) { ((AuroraODEPrim)p1).GetContactParam(p2, ref newGlobalcontact); if (m_filterCollisions) _perloopContact.Add(curContact); joint = CreateContacJoint(ref curContact); } else if (p2.PhysicsActorType == (int) ActorTypes.Prim) { if (m_filterCollisions) _perloopContact.Add(curContact); //Add restitution and friction changes ((AuroraODEPrim)p1).GetContactParam(p2, ref newGlobalcontact); joint = CreateContacJoint(ref curContact); } } if (m_global_contactcount < m_currentmaxContactsbeforedeath && joint != IntPtr.Zero) // stack collide! { d.JointAttach(joint, b1, b2); m_global_contactcount++; joint = IntPtr.Zero; } } } #endregion m_StatContactLoopTime = Util.EnvironmentTickCountSubtract(ContactLoopTime); int CollisionAccountingTime = Util.EnvironmentTickCount(); if (NotSkipedCount > 0) { if (count > geomContactPointsStartthrottle) { // If there are more then 3 contact points, it's likely // that we've got a pile of objects, so ... // We don't want to send out hundreds of terse updates over and over again // so lets throttle them and send them again after it's somewhat sorted out. p2.ThrottleUpdates = true; } } collision_accounting_events(p1, p2, maxDepthContact); m_StatCollisionAccountingTime = Util.EnvironmentTickCountSubtract(CollisionAccountingTime); }
// This is the standard Near. Uses space AABBs to speed up detection. private void near(IntPtr space, IntPtr g1, IntPtr g2) { //Don't test against heightfield Geom, or you'll be sorry! /* terminate called after throwing an instance of 'std::bad_alloc' what(): std::bad_alloc Stacktrace: at (wrapper managed-to-native) Ode.NET.d.Collide (intptr,intptr,int,Ode.NET.d/ContactGeom[],int) <0x00004> at (wrapper managed-to-native) Ode.NET.d.Collide (intptr,intptr,int,Ode.NET.d/ContactGeom[],int) <0xffffffff> at OpenSim.Region.Physics.OdePlugin.ODERayCastRequestManager.near (intptr,intptr,intptr) <0x00280> at (wrapper native-to-managed) OpenSim.Region.Physics.OdePlugin.ODERayCastRequestManager.near (intptr,intptr,intptr) <0xfff fffff> at (wrapper managed-to-native) Ode.NET.d.SpaceCollide2 (intptr,intptr,intptr,Ode.NET.d/NearCallback) <0x00004> at (wrapper managed-to-native) Ode.NET.d.SpaceCollide2 (intptr,intptr,intptr,Ode.NET.d/NearCallback) <0xffffffff> at OpenSim.Region.Physics.OdePlugin.ODERayCastRequestManager.RayCast (OpenSim.Region.Physics.OdePlugin.ODERayCastRequest) < 0x00114> at OpenSim.Region.Physics.OdePlugin.ODERayCastRequestManager.ProcessQueuedRequests () <0x000eb> at OpenSim.Region.Physics.OdePlugin.OdeScene.Simulate (single) <0x017e6> at OpenSim.Region.Framework.Scenes.SceneGraph.UpdatePhysics (double) <0x00042> at OpenSim.Region.Framework.Scenes.Scene.Update () <0x0039e> at OpenSim.Region.Framework.Scenes.Scene.Heartbeat (object) <0x00019> at (wrapper runtime-invoke) object.runtime_invoke_void__this___object (object,intptr,intptr,intptr) <0xffffffff> Native stacktrace: mono [0x80d2a42] [0xb7f5840c] /lib/i686/cmov/libc.so.6(abort+0x188) [0xb7d1a018] /usr/lib/libstdc++.so.6(_ZN9__gnu_cxx27__verbose_terminate_handlerEv+0x158) [0xb45fc988] /usr/lib/libstdc++.so.6 [0xb45fa865] /usr/lib/libstdc++.so.6 [0xb45fa8a2] /usr/lib/libstdc++.so.6 [0xb45fa9da] /usr/lib/libstdc++.so.6(_Znwj+0x83) [0xb45fb033] /usr/lib/libstdc++.so.6(_Znaj+0x1d) [0xb45fb11d] libode.so(_ZN13dxHeightfield23dCollideHeightfieldZoneEiiiiP6dxGeomiiP12dContactGeomi+0xd04) [0xb46678e4] libode.so(_Z19dCollideHeightfieldP6dxGeomS0_iP12dContactGeomi+0x54b) [0xb466832b] libode.so(dCollide+0x102) [0xb46571b2] [0x95cfdec9] [0x8ea07fe1] [0xab260146] libode.so [0xb465a5c4] libode.so(_ZN11dxHashSpace8collide2EPvP6dxGeomPFvS0_S2_S2_E+0x75) [0xb465bcf5] libode.so(dSpaceCollide2+0x177) [0xb465ac67] [0x95cf978e] [0x8ea07945] [0x95cf2bbc] [0xab2787e7] [0xab419fb3] [0xab416657] [0xab415bda] [0xb609b08e] mono(mono_runtime_delegate_invoke+0x34) [0x8192534] mono [0x81a2f0f] mono [0x81d28b6] mono [0x81ea2c6] /lib/i686/cmov/libpthread.so.0 [0xb7e744c0] /lib/i686/cmov/libc.so.6(clone+0x5e) [0xb7dcd6de] */ // Exclude heightfield geom if (g1 == IntPtr.Zero || g2 == IntPtr.Zero) return; if (d.GeomGetClass(g1) == d.GeomClassID.HeightfieldClass || d.GeomGetClass(g2) == d.GeomClassID.HeightfieldClass) return; // Raytest against AABBs of spaces first, then dig into the spaces it hits for actual geoms. 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) { MainConsole.Instance.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; int count = 0; try { if (g1 == g2) return; // Can't collide with yourself count = d.CollidePtr(g1, g2, (contactsPerCollision & 0xffff), ContactgeomsArray, d.ContactGeom.unmanagedSizeOf); } catch (SEHException) { MainConsole.Instance.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."); } catch (Exception e) { MainConsole.Instance.WarnFormat("[PHYSICS]: Unable to collide test an object: {0}", e); return; } PhysicsActor p1 = null; if (g1 != IntPtr.Zero) m_scene.actor_name_map.TryGetValue(g1, out p1); // Loop over contacts, build results. d.ContactGeom curContact = new d.ContactGeom(); for (int i = 0; i < count; i++) { if (!GetCurContactGeom(i, ref curContact)) break; if (p1 != null) { if (p1 is WhiteCoreODEPrim) { ContactResult collisionresult = new ContactResult { ConsumerID = ((WhiteCoreODEPrim) p1).LocalID, Pos = new Vector3(curContact.pos.X, curContact.pos.Y, curContact.pos.Z), Depth = curContact.depth, Normal = new Vector3(curContact.normal.X, curContact.normal.Y, curContact.normal.Z) }; lock (m_contactResults) m_contactResults.Add(collisionresult); } } } }
/// <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) { if (g1 == IntPtr.Zero || g2 == IntPtr.Zero || g1 == g2 || !ContinueCollisionProcessing) return; // 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)) { // 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 (Exception e) { MainConsole.Instance.WarnFormat("[PHYSICS]: SpaceCollide2 failed: {0} ", e); return; } return; } IntPtr b1 = d.GeomGetBody(g1); IntPtr b2 = d.GeomGetBody(g2); // 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; count = d.CollidePtr(g1, g2, (contactsPerCollision & 0xffff), ContactgeomsArray, d.ContactGeom.unmanagedSizeOf); } catch (Exception e) { MainConsole.Instance.WarnFormat("[PHYSICS]: ode Collide failed: {0} ", e.ToString()); PhysicsActor badObj; if (actor_name_map.TryGetValue(g1, out badObj)) if (badObj is WhiteCoreODEPrim) RemovePrim((WhiteCoreODEPrim) badObj); else if (badObj is WhiteCoreODECharacter) RemoveAvatar((WhiteCoreODECharacter) badObj); if (actor_name_map.TryGetValue(g2, out badObj)) if (badObj is WhiteCoreODEPrim) RemovePrim((WhiteCoreODEPrim) badObj); else if (badObj is WhiteCoreODECharacter) RemoveAvatar((WhiteCoreODECharacter) badObj); return; } if (count == 0) 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; if (p1.CollisionScore >= float.MaxValue - count) p1.CollisionScore = 0; p1.CollisionScore += count; if (p2.CollisionScore >= float.MaxValue - count) p2.CollisionScore = 0; p2.CollisionScore += count; ContactPoint maxDepthContact = new ContactPoint(); d.ContactGeom curContact = new d.ContactGeom(); // 20131224 not used d.ContactGeom maxContact = new d.ContactGeom(); int NotSkipedCount = 0; //StatContactLoopTime = CollectTime(() => #region Contact Loop for (int i = 0; i < count; i++) { if (!GetCurContactGeom(i, ref curContact)) break; if (curContact.depth > maxDepthContact.PenetrationDepth) { maxDepthContact.PenetrationDepth = curContact.depth; maxDepthContact.Position.X = curContact.pos.X; maxDepthContact.Position.Y = curContact.pos.Y; maxDepthContact.Position.Z = curContact.pos.Z; maxDepthContact.Type = (ActorTypes)p1.PhysicsActorType; maxDepthContact.SurfaceNormal.X = curContact.normal.X; maxDepthContact.SurfaceNormal.Y = curContact.normal.Y; maxDepthContact.SurfaceNormal.Z = curContact.normal.Z; // 20131224 not used maxContact = curContact; } } if (p1 is WhiteCoreODECharacter || p2 is WhiteCoreODECharacter) //This really should be maxContact, but there are crashes that users have reported when this is used... //AddODECollision(maxContact, p1, p2, b1, b2, maxDepthContact, ref NotSkipedCount); AddODECollision(curContact, p1, p2, b1, b2, maxDepthContact, ref NotSkipedCount); else { for (int i = 0; i < count; i++) { if (!GetCurContactGeom(i, ref curContact)) break; AddODECollision(curContact, p1, p2, b1, b2, maxDepthContact, ref NotSkipedCount); } } #endregion //StatCollisionAccountingTime = CollectTime(() => { if (NotSkipedCount > 0) { if (NotSkipedCount > geomContactPointsStartthrottle) { // If there are more then 3 contact points, it's likely // that we've got a pile of objects, so ... // We don't want to send out hundreds of terse updates over and over again // so lets throttle them and send them again after it's somewhat sorted out. p2.ThrottleUpdates = true; } } collision_accounting_events(p1, p2, maxDepthContact); } //); }
// This is the standard Near. g1 is the ray private void near(IntPtr space, IntPtr g1, IntPtr g2) { if (g2 == IntPtr.Zero || g1 == g2) { return; } if (m_contactResults.Count >= CurrentMaxCount) { return; } if (d.GeomIsSpace(g2)) { try { d.SpaceCollide2(g1, g2, IntPtr.Zero, nearCallback); } catch (Exception e) { m_log.WarnFormat("[PHYSICS Ray]: Unable to Space collide test an object: {0}", e.Message); } return; } int count = 0; try { count = d.CollidePtr(g1, g2, CollisionContactGeomsPerTest, m_scene.ContactgeomsArray, d.ContactGeom.unmanagedSizeOf); } catch (Exception e) { m_log.WarnFormat("[PHYSICS Ray]: Unable to collide test an object: {0}", e.Message); return; } if (count == 0) { return; } /* * uint cat1 = d.GeomGetCategoryBits(g1); * uint cat2 = d.GeomGetCategoryBits(g2); * uint col1 = d.GeomGetCollideBits(g1); * uint col2 = d.GeomGetCollideBits(g2); */ uint ID = 0; PhysicsActor p2 = null; m_scene.actor_name_map.TryGetValue(g2, out p2); if (p2 == null) { return; } switch (p2.PhysicsActorType) { case (int)ActorTypes.Prim: RayFilterFlags thisFlags; if (p2.IsPhysical) { thisFlags = RayFilterFlags.physical; } else { thisFlags = RayFilterFlags.nonphysical; } if (p2.Phantom) { thisFlags |= RayFilterFlags.phantom; } if (p2.IsVolumeDtc) { thisFlags |= RayFilterFlags.volumedtc; } if ((thisFlags & CurrentRayFilter) == 0) { return; } ID = ((OdePrim)p2).LocalID; break; case (int)ActorTypes.Agent: if ((CurrentRayFilter & RayFilterFlags.agent) == 0) { return; } else { ID = ((OdeCharacter)p2).LocalID; } break; case (int)ActorTypes.Ground: if ((CurrentRayFilter & RayFilterFlags.land) == 0) { return; } break; case (int)ActorTypes.Water: if ((CurrentRayFilter & RayFilterFlags.water) == 0) { return; } break; default: break; } d.ContactGeom curcontact = new d.ContactGeom(); // closestHit for now only works for meshs, so must do it for others if ((CurrentRayFilter & RayFilterFlags.ClosestHit) == 0) { // Loop all contacts, build results. for (int i = 0; i < count; i++) { if (!GetCurContactGeom(i, ref curcontact)) { break; } ContactResult collisionresult = new ContactResult(); collisionresult.ConsumerID = ID; collisionresult.Pos.X = curcontact.pos.X; collisionresult.Pos.Y = curcontact.pos.Y; collisionresult.Pos.Z = curcontact.pos.Z; collisionresult.Depth = curcontact.depth; collisionresult.Normal.X = curcontact.normal.X; collisionresult.Normal.Y = curcontact.normal.Y; collisionresult.Normal.Z = curcontact.normal.Z; lock (m_contactResults) { m_contactResults.Add(collisionresult); if (m_contactResults.Count >= CurrentMaxCount) { return; } } } } else { // keep only closest contact ContactResult collisionresult = new ContactResult(); collisionresult.ConsumerID = ID; collisionresult.Depth = float.MaxValue; for (int i = 0; i < count; i++) { if (!GetCurContactGeom(i, ref curcontact)) { break; } if (curcontact.depth < collisionresult.Depth) { collisionresult.Pos.X = curcontact.pos.X; collisionresult.Pos.Y = curcontact.pos.Y; collisionresult.Pos.Z = curcontact.pos.Z; collisionresult.Depth = curcontact.depth; collisionresult.Normal.X = curcontact.normal.X; collisionresult.Normal.Y = curcontact.normal.Y; collisionresult.Normal.Z = curcontact.normal.Z; } } if (collisionresult.Depth != float.MaxValue) { lock (m_contactResults) m_contactResults.Add(collisionresult); } } }
// This is the standard Near. Uses space AABBs to speed up detection. private void near(IntPtr space, IntPtr g1, IntPtr g2) { //Don't test against heightfield Geom, or you'll be sorry! // Exclude heightfield geom if (g1 == IntPtr.Zero || g2 == IntPtr.Zero) { return; } if (d.GeomGetClass(g1) == d.GeomClassID.HeightfieldClass || d.GeomGetClass(g2) == d.GeomClassID.HeightfieldClass) { return; } // Raytest against AABBs of spaces first, then dig into the spaces it hits for actual geoms. 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) { MainConsole.Instance.Warn("[PHYSICS]: Unable to collide test a space"); return; } return; } if (g1 == IntPtr.Zero || g2 == IntPtr.Zero) { return; } int count = 0; try { if (g1 == g2) { return; // Can't collide with yourself } count = d.CollidePtr(g1, g2, (contactsPerCollision & 0xffff), ContactgeomsArray, d.ContactGeom.unmanagedSizeOf); } catch (SEHException) { MainConsole.Instance.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."); } catch (Exception e) { MainConsole.Instance.WarnFormat("[PHYSICS]: Unable to collide test an object: {0}", e); return; } PhysicsActor p1 = null; if (g1 != IntPtr.Zero) { m_scene.actor_name_map.TryGetValue(g1, out p1); } // Loop over contacts, build results. d.ContactGeom curContact = new d.ContactGeom(); for (int i = 0; i < count; i++) { if (!GetCurContactGeom(i, ref curContact)) { break; } if (p1 != null) { if (p1 is AuroraODEPrim) { ContactResult collisionresult = new ContactResult { ConsumerID = ((AuroraODEPrim)p1).LocalID, Pos = new Vector3(curContact.pos.X, curContact.pos.Y, curContact.pos.Z), Depth = curContact.depth, Normal = new Vector3(curContact.normal.X, curContact.normal.Y, curContact.normal.Z) }; lock (m_contactResults) m_contactResults.Add(collisionresult); } } } }