public void AddCollider(uint localID, ContactPoint contact) { Cleared = false; /*ContactPoint oldCol; if(!m_objCollisionList.TryGetValue(localID, out oldCol)) { */ lock (m_objCollisionList) m_objCollisionList[localID] = contact; /*} else { if(oldCol.PenetrationDepth < contact.PenetrationDepth) lock(m_objCollisionList) m_objCollisionList[localID] = contact; }*/ }
public abstract void AddCollisionEvent(uint localID, ContactPoint contact);
public override void AddCollisionEvent(uint CollidedWith, ContactPoint contact) { }
public override void AddCollisionEvent(uint CollidedWith, ContactPoint contact) { if (base.SubscribedToCollisions() && SubscribedEvents()) //If we don't have anything that we are going to trigger, don't even add { if (CollisionEventsThisFrame == null) CollisionEventsThisFrame = new CollisionEventUpdate(); CollisionEventsThisFrame.AddCollider(CollidedWith, contact); } }
public override void AddCollisionEvent(uint localID, ContactPoint contact) { CollisionCollection.AddCollider(localID, contact); }
private void collision_accounting_events(PhysicsActor p1, PhysicsActor p2, ContactPoint contact) { if (!p2.SubscribedEvents() && !p1.SubscribedEvents()) return; if (p1.SubscribedEvents()) p1.AddCollisionEvent(p2.LocalID, contact); if (p2.SubscribedEvents()) p2.AddCollisionEvent(p1.LocalID, contact); }
/// <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) 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 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.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(); 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; } } } if (p1 is AuroraODECharacter || p2 is AuroraODECharacter) 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); } //); }
private void AddODECollision(d.ContactGeom curContact, PhysicsActor p1, PhysicsActor p2, IntPtr b1, IntPtr b2, ContactPoint maxDepthContact, ref int NotSkipedCount) { IntPtr joint = IntPtr.Zero; 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.5f)) p2col = false; } p2.IsTruelyColliding = true; 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 // No collision on volume detect prims if ((p1 is AuroraODEPrim && p1.VolumeDetect) || (p2 is AuroraODEPrim && p2.VolumeDetect)) return; if (curContact.depth < 0f) return; //Has to be penetrating if (m_filterCollisions && checkDupe(curContact, p2.PhysicsActorType)) return; if (m_filterCollisions) _perloopContact.Add(curContact); NotSkipedCount++; // If we're colliding against terrain if (p1.PhysicsActorType == (int) ActorTypes.Ground) { if (p2.PhysicsActorType == (int) ActorTypes.Prim) { ((AuroraODEPrim) p2).GetContactParam(p2, ref newGlobalcontact); joint = CreateContacJoint(curContact); } else { newGlobalcontact = new d.Contact(); newGlobalcontact.surface.mode |= d.ContactFlags.SoftERP; newGlobalcontact.surface.mu = 75; newGlobalcontact.surface.bounce = 0.1f; newGlobalcontact.surface.soft_erp = 0.05025f; //GetContactParam(0.0f, AvatarContactBounce, ref newGlobalcontact); joint = CreateContacJoint(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); joint = CreateContacJoint(curContact); } else if (p1.PhysicsActorType == (int) ActorTypes.Prim) { //Add restitution and friction changes ((AuroraODEPrim) p1).GetContactParam(p2, ref newGlobalcontact); joint = CreateContacJoint(curContact); } if (m_global_contactcount < m_currentmaxContactsbeforedeath && joint != IntPtr.Zero) { d.JointAttach(joint, b1, b2); m_global_contactcount++; joint = IntPtr.Zero; } }
/// <summary> /// Called from Simulate /// This is the avatar's movement control + PID Controller /// </summary> /// <param name="timeStep"></param> /// <returns>True if the avatar should be removed from the simulation</returns> public void Move(float timeStep) { if (Body == IntPtr.Zero || !IsPhysical) return; Vector3 vec = Vector3.Zero; Vector3 vel = d.BodyGetLinearVel(Body).ToVector3(); Vector3 tempPos = d.BodyGetPosition(Body).ToVector3(); #region Flight Ceiling // rex, added height check if (_parent_scene.m_useFlightCeilingHeight && tempPos.Z > _parent_scene.m_flightCeilingHeight) { tempPos.Z = _parent_scene.m_flightCeilingHeight; d.BodySetPosition(Body, tempPos.X, tempPos.Y, tempPos.Z); if (vel.Z > 0.0f) { vel.Z = 0.0f; d.BodySetLinearVel(Body, vel.X, vel.Y, vel.Z); } if (m_targetVelocity.Z > 0.0f) m_targetVelocity.Z = 0.0f; } // endrex #endregion #region NonFinite Pos Vector3 localPos = new Vector3(tempPos.X, tempPos.Y, tempPos.Z); if (!localPos.IsFinite()) { MainConsole.Instance.Warn("[PHYSICS]: Avatar Position is non-finite!"); _parent_scene.BadCharacter(this); return; } #endregion #region Check for out of region if (Position.X < 0.25f || Position.Y < 0.25f || Position.X > _parent_scene.Region.RegionSizeX - .25f || Position.Y > _parent_scene.Region.RegionSizeY - .25f) { if (!CheckForRegionCrossing()) { Vector3 newPos = Position; newPos.X = Util.Clip(Position.X, 0.75f, _parent_scene.Region.RegionSizeX - 0.75f); newPos.Y = Util.Clip(Position.Y, 0.75f, _parent_scene.Region.RegionSizeY - 0.75f); Position = newPos; d.BodySetPosition(Body, newPos.X, newPos.Y, newPos.Z); } } #endregion #region Movement Multiplier float movementmult = 1f; if (!m_alwaysRun) movementmult /= _parent_scene.avMovementDivisorWalk; else movementmult /= _parent_scene.avMovementDivisorRun; movementmult *= 10; movementmult *= SpeedModifier; if (flying) movementmult *= _parent_scene.m_AvFlySpeed; #endregion #region Jump code if (IsJumping) { if (flying || ((IsColliding) && m_preJumpCounter > _parent_scene.m_preJumpTime || m_preJumpCounter > 150)) { m_isJumping = false; m_preJumpCounter = 0; m_targetVelocity.X /= 2; m_targetVelocity.Y /= 2; m_targetVelocity.Z = -0.5f; } else { m_targetVelocity.X = m_preJumpForce.X * _parent_scene.m_preJumpForceMultiplierX / 2.5f; m_targetVelocity.Y = m_preJumpForce.Y * _parent_scene.m_preJumpForceMultiplierY / 2.5f; m_preJumpCounter++; } } else if (m_ispreJumping) { if (m_preJumpCounter == _parent_scene.m_preJumpTime) { m_ispreJumping = false; m_targetVelocity.X = m_preJumpForce.X; m_targetVelocity.Y = m_preJumpForce.Y; m_targetVelocity.Z = m_preJumpForce.Z * (m_alwaysRun ? _parent_scene.m_preJumpForceMultiplierZ/2.5f : _parent_scene.m_preJumpForceMultiplierZ/2.25f); m_preJumpCounter = 0; m_isJumping = true; } else { m_preJumpCounter++; TriggerMovementUpdate(); return; } } #endregion #region Check for underground d.AABB aabb; d.GeomGetAABB(Shell, out aabb); float chrminZ = aabb.MinZ; Vector3 posch = localPos; float ftmp; if (flying) { ftmp = 0.75f*timeStep; posch.X += vel.X*ftmp; posch.Y += vel.Y*ftmp; } float groundHeight = _parent_scene.GetTerrainHeightAtXY(posch.X, posch.Y); if (chrminZ < groundHeight) { float depth = groundHeight - chrminZ; if (m_targetVelocity.Z < 0) m_targetVelocity.Z = 0; if (!flying) { if (vel.Z < -10f) vel.Z = -10f; vec.Z = -vel.Z*PID_D*1.5f + depth*PID_P*50.0f; } else { vec.Z = depth*PID_P*50.0f; } if (depth < 0.12f) { if (!m_iscolliding) { m_iscolliding = true; m_colliderfilter = 15; ContactPoint point = new ContactPoint { Type = ActorTypes.Ground, PenetrationDepth = depth, Position = {X = localPos.X, Y = localPos.Y, Z = chrminZ}, SurfaceNormal = new Vector3(0, 0, -1f) }; //0 is the ground localID AddCollisionEvent(0, point); } vec.Z *= 0.5f; } } /* if(Flying && _target_velocity == Vector3.Zero && Math.Abs(vel.Z) < 0.1) notMoving = true; */ #endregion #region Gravity if (!flying) vec.Z += -9.8f*35*Mass*(_appliedFallingForce > 100 ? 1 : _appliedFallingForce++/100f)* (this.IsTruelyColliding ? 0.5f : 1.0f); else if (_parent_scene.AllowAvGravity && m_targetVelocity.Z > 0 && tempPos.Z > _parent_scene.AvGravityHeight) //Should be stop avies from flying upwards { //How much should we force them down? float Multiplier = (_parent_scene.AllowAvsToEscapeGravity ? .03f : .1f); //How much should we force them down? float fudgeHeight = (_parent_scene.AllowAvsToEscapeGravity ? 80 : 30); //We add the 30 so that gravity is resonably strong once they pass the min height Multiplier *= tempPos.Z + fudgeHeight - _parent_scene.AvGravityHeight; //Limit these so that things don't go wrong if (Multiplier < 1) Multiplier = 1; float maxpower = (_parent_scene.AllowAvsToEscapeGravity ? 1.5f : 3f); if (Multiplier > maxpower) Multiplier = maxpower; m_targetVelocity.Z /= Multiplier; vel.Z /= Multiplier; } if (IsColliding) _appliedFallingForce = 10; #endregion #region Auto Fly Height if (Flying) { //Added for auto fly height. Kitto Flora //Changed to only check if the avatar is flying around, // Revolution: If the avatar is going down, they are trying to land (probably), so don't push them up to make it harder // Only if they are moving around sideways do we need to push them up if (m_targetVelocity.X != 0 || m_targetVelocity.Y != 0) { Vector3 forwardVel = new Vector3(m_targetVelocity.X > 0 ? 2 : (m_targetVelocity.X < 0 ? -2 : 0), m_targetVelocity.Y > 0 ? 2 : (m_targetVelocity.Y < 0 ? -2 : 0), 0); float target_altitude = _parent_scene.GetTerrainHeightAtXY(tempPos.X, tempPos.Y) + MinimumGroundFlightOffset; //We cheat a bit and do a bit lower than normal if ((tempPos.Z - CAPSULE_LENGTH) < target_altitude || (tempPos.Z - CAPSULE_LENGTH) < _parent_scene.GetTerrainHeightAtXY(tempPos.X + forwardVel.X, tempPos.Y + forwardVel.Y) + MinimumGroundFlightOffset) if (m_targetVelocity.Z < 0) vec.Z += (target_altitude - tempPos.Z) * PID_D * 0.5f; //Don't apply so much else if ((tempPos.Z - CAPSULE_LENGTH) + 5 < target_altitude) vec.Z += (target_altitude - tempPos.Z) * PID_D * 3.05f; else vec.Z += (target_altitude - tempPos.Z) * PID_D * 1.75f; } else { //Straight up and down, only apply when they are very close to the ground float target_altitude = _parent_scene.GetTerrainHeightAtXY(tempPos.X, tempPos.Y); if ((tempPos.Z - CAPSULE_LENGTH + (MinimumGroundFlightOffset / 1.5)) < target_altitude + MinimumGroundFlightOffset) { if ((tempPos.Z - CAPSULE_LENGTH) < target_altitude + 1) { vec.Z += ((target_altitude + 4) - (tempPos.Z - CAPSULE_LENGTH)) * PID_D; } else vec.Z += ((target_altitude + MinimumGroundFlightOffset) - (tempPos.Z - CAPSULE_LENGTH)) * PID_D * 0.5f; } } } #endregion #region Force application #region Force push application bool noDisable = false; if (_target_force != Vector3.Zero) { _target_vel_force = _target_force/2; _target_force = Vector3.Zero; noDisable = true; } if (_target_vel_force.X != 0) vec.X += (_target_vel_force.X)*PID_D*2; if (_target_vel_force.Y != 0) vec.Y += (_target_vel_force.Y)*PID_D*2; if (_target_vel_force.Z != 0) vec.Z += (_target_vel_force.Z)*PID_D; #endregion if (!flying && !IsTruelyColliding) { //Falling, and haven't yet hit the ground vec.X += ((m_targetVelocity.X + m_forceAppliedBeforeFalling.X) * movementmult - vel.X) * PID_D * 2; vec.Y += ((m_targetVelocity.Y + m_forceAppliedBeforeFalling.Y) * movementmult - vel.Y) * PID_D * 2; vec.Z += ((m_targetVelocity.Z + m_forceAppliedBeforeFalling.Z) * movementmult - vel.Z) * PID_D; } else { m_forceAppliedBeforeFalling = !flying ? Vector3.Zero : m_targetVelocity; vec.X += (m_targetVelocity.X * movementmult - vel.X) * PID_D * 2; vec.Y += (m_targetVelocity.Y * movementmult - vel.Y) * PID_D * 2; vec.Z += (m_targetVelocity.Z * movementmult - vel.Z) * PID_D; } Vector3 combinedForceVelocity = m_targetVelocity + _target_vel_force; if ((combinedForceVelocity == Vector3.Zero || (Math.Abs(combinedForceVelocity.X) < 0.01f && Math.Abs(combinedForceVelocity.Y) < 0.01f && Math.Abs(combinedForceVelocity.Z) < 0.01f)) && Math.Abs(vel.X) < 0.1 && Math.Abs(vel.Y) < 0.1 && Math.Abs(vel.Z) < 0.1 && !(_appliedFallingForce > 0) && !noDisable) { //Body isn't moving, disable it m_targetVelocity = Vector3.Zero; _target_vel_force = Vector3.Zero; d.BodySetLinearVel(Body, 0, 0, 0); d.BodyDisable(Body); } else { m_targetVelocity *= _parent_scene.AvDecayTime; _target_vel_force *= _parent_scene.AvDecayTime; d.BodyEnable(Body); d.BodyAddForce(Body, vec.X, vec.Y, vec.Z); } #endregion }
public void PhysicsCollision(EventArgs e) { // single threaded here if (e == null) return; CollisionEventUpdate a = (CollisionEventUpdate) e; Dictionary<uint, ContactPoint> collissionswith = a.GetCollisionEvents(); List<uint> thisHitColliders = new List<uint>(); List<uint> startedColliders = new List<uint>(); ContactPoint startedCollider = new ContactPoint(); // calculate things that started colliding this time // and build up list of colliders this time foreach (uint localID in collissionswith.Keys) { thisHitColliders.Add(localID); if (!m_lastColliders.Contains(localID)) { startedCollider = collissionswith[localID]; startedColliders.Add(localID); } //MainConsole.Instance.Debug("[OBJECT]: Collided with:" + localid.ToString() + " at depth of: " + collissionswith[localid].ToString()); } // calculate things that ended colliding List<uint> endedColliders = m_lastColliders.Where(localID => !thisHitColliders.Contains(localID)).ToList(); //add the items that started colliding this time to the last colliders list. m_lastColliders.AddRange(startedColliders); // remove things that ended colliding from the last colliders list foreach (uint localID in endedColliders) m_lastColliders.Remove(localID); if (m_parentGroup == null) return; if (m_parentGroup.IsDeleted) return; const string SoundGlassCollision = "6a45ba0b-5775-4ea8-8513-26008a17f873"; const string SoundMetalCollision = "9e5c1297-6eed-40c0-825a-d9bcd86e3193"; const string SoundStoneCollision = "9538f37c-456e-4047-81be-6435045608d4"; const string SoundFleshCollision = "dce5fdd4-afe4-4ea1-822f-dd52cac46b08"; const string SoundPlasticCollision = "0e24a717-b97e-4b77-9c94-b59a5a88b2da"; const string SoundRubberCollision = "153c8bf7-fb89-4d89-b263-47e58b1b4774"; const string SoundWoodCollision = "063c97d3-033a-4e9b-98d8-05c8074922cb"; // play the sound. if (startedColliders.Count > 0 && CollisionSound != UUID.Zero && CollisionSoundVolume > 0.0f) { SendSound(CollisionSound.ToString(), CollisionSoundVolume, true, 0, 0); } else if (startedColliders.Count > 0) { switch (startedCollider.Type) { case ActorTypes.Agent: break; // Agents will play the sound so we don't case ActorTypes.Ground: SendSound(SoundWoodCollision, 1, true, 0, 0); break; //Always play the click or thump sound when hitting ground case ActorTypes.Prim: switch (Material) { case (int) OpenMetaverse.Material.Flesh: SendSound(SoundFleshCollision, 1, true, 0, 0); break; case (int) OpenMetaverse.Material.Glass: SendSound(SoundGlassCollision, 1, true, 0, 0); break; case (int) OpenMetaverse.Material.Metal: SendSound(SoundMetalCollision, 1, true, 0, 0); break; case (int) OpenMetaverse.Material.Plastic: SendSound(SoundPlasticCollision, 1, true, 0, 0); break; case (int) OpenMetaverse.Material.Rubber: SendSound(SoundRubberCollision, 1, true, 0, 0); break; case (int) OpenMetaverse.Material.Stone: SendSound(SoundStoneCollision, 1, true, 0, 0); break; case (int) OpenMetaverse.Material.Wood: SendSound(SoundWoodCollision, 1, true, 0, 0); break; } break; //Play based on material type in prim2prim collisions default: break; //Unclear of what this object is, no sounds } } if (CollisionSprite != UUID.Zero && CollisionSoundVolume > 0.0f) // The collision volume isn't a mistake, its an SL feature/bug { // TODO: make a sprite! } if (((AggregateScriptEvents & scriptEvents.collision) != 0) || ((AggregateScriptEvents & scriptEvents.collision_end) != 0) || ((AggregateScriptEvents & scriptEvents.collision_start) != 0) || ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) || ((AggregateScriptEvents & scriptEvents.land_collision) != 0) || ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) || (CollisionSound != UUID.Zero) || PassCollisions != 2) { if ((AggregateScriptEvents & scriptEvents.collision_start) != 0 || (AggregateScriptEvents & scriptEvents.collision) != 0) { // do event notification if (startedColliders.Count > 0) { ColliderArgs StartCollidingMessage = new ColliderArgs(); List<DetectedObject> colliding = new List<DetectedObject>(); foreach (uint localId in startedColliders) { if (localId != 0) { // always running this check because if the user deletes the object it would return a null reference. if (m_parentGroup == null) return; if (m_parentGroup.Scene == null) return; ISceneChildEntity obj = m_parentGroup.Scene.GetSceneObjectPart(localId); string data = ""; if (obj != null) { if (m_parentGroup.RootPart.CollisionFilter.ContainsValue(obj.UUID.ToString()) || m_parentGroup.RootPart.CollisionFilter.ContainsValue(obj.Name)) { bool found = m_parentGroup.RootPart.CollisionFilter.TryGetValue(1, out data); //If it is 1, it is to accept ONLY collisions from this object if (found) { DetectedObject detobj = new DetectedObject { keyUUID = obj.UUID, nameStr = obj.Name, ownerUUID = obj.OwnerID, posVector = obj.AbsolutePosition, rotQuat = obj.GetWorldRotation(), velVector = obj.Velocity, colliderType = 0, groupUUID = obj.GroupID }; colliding.Add(detobj); } //If it is 0, it is to not accept collisions from this object else { } } else { bool found = m_parentGroup.RootPart.CollisionFilter.TryGetValue(1, out data); //If it is 1, it is to accept ONLY collisions from this object, so this other object will not work if (!found) { DetectedObject detobj = new DetectedObject { keyUUID = obj.UUID, nameStr = obj.Name, ownerUUID = obj.OwnerID, posVector = obj.AbsolutePosition, rotQuat = obj.GetWorldRotation(), velVector = obj.Velocity, colliderType = 0, groupUUID = obj.GroupID }; colliding.Add(detobj); } } } else { IScenePresence av = ParentGroup.Scene.GetScenePresence(localId); if (av != null) { if (av.LocalId == localId) { if ( m_parentGroup.RootPart.CollisionFilter.ContainsValue(av.UUID.ToString()) || m_parentGroup.RootPart.CollisionFilter.ContainsValue(av.Name)) { bool found = m_parentGroup.RootPart.CollisionFilter.TryGetValue(1, out data); //If it is 1, it is to accept ONLY collisions from this avatar if (found) { DetectedObject detobj = new DetectedObject { keyUUID = av.UUID, nameStr = av.ControllingClient.Name, ownerUUID = av.UUID, posVector = av.AbsolutePosition, rotQuat = av.Rotation, velVector = av.Velocity, colliderType = 0, groupUUID = av.ControllingClient .ActiveGroupId }; colliding.Add(detobj); } //If it is 0, it is to not accept collisions from this avatar else { } } else { bool found = m_parentGroup.RootPart.CollisionFilter.TryGetValue(1, out data); //If it is 1, it is to accept ONLY collisions from this avatar, so this other avatar will not work if (!found) { DetectedObject detobj = new DetectedObject { keyUUID = av.UUID, nameStr = av.ControllingClient.Name, ownerUUID = av.UUID, posVector = av.AbsolutePosition, rotQuat = av.Rotation, velVector = av.Velocity, colliderType = 0, groupUUID = av.ControllingClient .ActiveGroupId }; colliding.Add(detobj); } } } } } } } if (colliding.Count > 0) { StartCollidingMessage.Colliders = colliding; // always running this check because if the user deletes the object it would return a null reference. if (m_parentGroup == null) return; if (m_parentGroup.Scene == null) return; //Always send to the prim it is occuring to m_parentGroup.Scene.EventManager.TriggerScriptCollidingStart(this, StartCollidingMessage); if ((this.UUID != this.ParentGroup.RootPart.UUID)) { const int PASS_IF_NOT_HANDLED = 0; const int PASS_ALWAYS = 1; const int PASS_NEVER = 2; if (this.PassCollisions == PASS_NEVER) { } if (this.PassCollisions == PASS_ALWAYS) { m_parentGroup.Scene.EventManager.TriggerScriptCollidingStart( this.ParentGroup.RootPart, StartCollidingMessage); } else if (((this.ScriptEvents & scriptEvents.collision_start) == 0) && this.PassCollisions == PASS_IF_NOT_HANDLED) //If no event in this prim, pass to parent { m_parentGroup.Scene.EventManager.TriggerScriptCollidingStart( this.ParentGroup.RootPart, StartCollidingMessage); } } } } } if ((AggregateScriptEvents & scriptEvents.collision) != 0) { if (m_lastColliders.Count > 0) { ColliderArgs CollidingMessage = new ColliderArgs(); List<DetectedObject> colliding = new List<DetectedObject>(); foreach (uint localId in m_lastColliders) { if (localId != 0) { if (m_parentGroup == null) return; if (m_parentGroup.Scene == null) return; ISceneChildEntity obj = m_parentGroup.Scene.GetSceneObjectPart(localId); string data = ""; if (obj != null) { if (m_parentGroup.RootPart.CollisionFilter.ContainsValue(obj.UUID.ToString()) || m_parentGroup.RootPart.CollisionFilter.ContainsValue(obj.Name)) { bool found = m_parentGroup.RootPart.CollisionFilter.TryGetValue(1, out data); //If it is 1, it is to accept ONLY collisions from this object if (found) { DetectedObject detobj = new DetectedObject { keyUUID = obj.UUID, nameStr = obj.Name, ownerUUID = obj.OwnerID, posVector = obj.AbsolutePosition, rotQuat = obj.GetWorldRotation(), velVector = obj.Velocity, colliderType = 0, groupUUID = obj.GroupID }; colliding.Add(detobj); } //If it is 0, it is to not accept collisions from this object else { } } else { bool found = m_parentGroup.RootPart.CollisionFilter.TryGetValue(1, out data); //If it is 1, it is to accept ONLY collisions from this object, so this other object will not work if (!found) { DetectedObject detobj = new DetectedObject { keyUUID = obj.UUID, nameStr = obj.Name, ownerUUID = obj.OwnerID, posVector = obj.AbsolutePosition, rotQuat = obj.GetWorldRotation(), velVector = obj.Velocity, colliderType = 0, groupUUID = obj.GroupID }; colliding.Add(detobj); } } } else { IScenePresence av = ParentGroup.Scene.GetScenePresence(localId); if (av != null) { if (m_parentGroup.RootPart.CollisionFilter.ContainsValue(av.UUID.ToString()) || m_parentGroup.RootPart.CollisionFilter.ContainsValue(av.Name)) { bool found = m_parentGroup.RootPart.CollisionFilter.TryGetValue(1, out data); //If it is 1, it is to accept ONLY collisions from this avatar if (found) { DetectedObject detobj = new DetectedObject { keyUUID = av.UUID, nameStr = av.ControllingClient.Name, ownerUUID = av.UUID, posVector = av.AbsolutePosition, rotQuat = av.Rotation, velVector = av.Velocity, colliderType = 0, groupUUID = av.ControllingClient.ActiveGroupId }; colliding.Add(detobj); } //If it is 0, it is to not accept collisions from this avatar else { } } else { bool found = m_parentGroup.RootPart.CollisionFilter.TryGetValue(1, out data); //If it is 1, it is to accept ONLY collisions from this avatar, so this other avatar will not work if (!found) { DetectedObject detobj = new DetectedObject { keyUUID = av.UUID, nameStr = av.ControllingClient.Name, ownerUUID = av.UUID, posVector = av.AbsolutePosition, rotQuat = av.Rotation, velVector = av.Velocity, colliderType = 0, groupUUID = av.ControllingClient.ActiveGroupId }; colliding.Add(detobj); } } } } } } if (colliding.Count > 0) { CollidingMessage.Colliders = colliding; // always running this check because if the user deletes the object it would return a null reference. if (m_parentGroup == null) return; if (m_parentGroup.Scene == null) return; m_parentGroup.Scene.EventManager.TriggerScriptColliding(this, CollidingMessage); if ((this.UUID != this.ParentGroup.RootPart.UUID)) { const int PASS_IF_NOT_HANDLED = 0; const int PASS_ALWAYS = 1; const int PASS_NEVER = 2; if (this.PassCollisions == PASS_NEVER) { } if (this.PassCollisions == PASS_ALWAYS) { m_parentGroup.Scene.EventManager.TriggerScriptColliding(this.ParentGroup.RootPart, CollidingMessage); } else if (((this.ScriptEvents & scriptEvents.collision) == 0) && this.PassCollisions == PASS_IF_NOT_HANDLED) //If no event in this prim, pass to parent { m_parentGroup.Scene.EventManager.TriggerScriptColliding( this.ParentGroup.RootPart, CollidingMessage); } } } } } if ((AggregateScriptEvents & scriptEvents.collision_end) != 0) { if (endedColliders.Count > 0) { ColliderArgs EndCollidingMessage = new ColliderArgs(); List<DetectedObject> colliding = new List<DetectedObject>(); foreach (uint localId in endedColliders) { if (localId != 0) { // always running this check because if the user deletes the object it would return a null reference. if (m_parentGroup == null) return; if (m_parentGroup.Scene == null) return; ISceneChildEntity obj = m_parentGroup.Scene.GetSceneObjectPart(localId); string data = ""; if (obj != null) { if (m_parentGroup.RootPart.CollisionFilter.ContainsValue(obj.UUID.ToString()) || m_parentGroup.RootPart.CollisionFilter.ContainsValue(obj.Name)) { bool found = m_parentGroup.RootPart.CollisionFilter.TryGetValue(1, out data); //If it is 1, it is to accept ONLY collisions from this object if (found) { DetectedObject detobj = new DetectedObject { keyUUID = obj.UUID, nameStr = obj.Name, ownerUUID = obj.OwnerID, posVector = obj.AbsolutePosition, rotQuat = obj.GetWorldRotation(), velVector = obj.Velocity, colliderType = 0, groupUUID = obj.GroupID }; colliding.Add(detobj); } //If it is 0, it is to not accept collisions from this object else { } } else { bool found = m_parentGroup.RootPart.CollisionFilter.TryGetValue(1, out data); //If it is 1, it is to accept ONLY collisions from this object, so this other object will not work if (!found) { DetectedObject detobj = new DetectedObject { keyUUID = obj.UUID, nameStr = obj.Name, ownerUUID = obj.OwnerID, posVector = obj.AbsolutePosition, rotQuat = obj.GetWorldRotation(), velVector = obj.Velocity, colliderType = 0, groupUUID = obj.GroupID }; colliding.Add(detobj); } } } else { IScenePresence av = ParentGroup.Scene.GetScenePresence(localId); if (av != null) { if (av.LocalId == localId) { if ( m_parentGroup.RootPart.CollisionFilter.ContainsValue(av.UUID.ToString()) || m_parentGroup.RootPart.CollisionFilter.ContainsValue(av.Name)) { bool found = m_parentGroup.RootPart.CollisionFilter.TryGetValue(1, out data); //If it is 1, it is to accept ONLY collisions from this avatar if (found) { DetectedObject detobj = new DetectedObject { keyUUID = av.UUID, nameStr = av.ControllingClient.Name, ownerUUID = av.UUID, posVector = av.AbsolutePosition, rotQuat = av.Rotation, velVector = av.Velocity, colliderType = 0, groupUUID = av.ControllingClient .ActiveGroupId }; colliding.Add(detobj); } //If it is 0, it is to not accept collisions from this avatar else { } } else { bool found = m_parentGroup.RootPart.CollisionFilter.TryGetValue(1, out data); //If it is 1, it is to accept ONLY collisions from this avatar, so this other avatar will not work if (!found) { DetectedObject detobj = new DetectedObject { keyUUID = av.UUID, nameStr = av.ControllingClient.Name, ownerUUID = av.UUID, posVector = av.AbsolutePosition, rotQuat = av.Rotation, velVector = av.Velocity, colliderType = 0, groupUUID = av.ControllingClient .ActiveGroupId }; colliding.Add(detobj); } } } } } } } if (colliding.Count > 0) { EndCollidingMessage.Colliders = colliding; // always running this check because if the user deletes the object it would return a null reference. if (m_parentGroup == null) return; if (m_parentGroup.Scene == null) return; m_parentGroup.Scene.EventManager.TriggerScriptCollidingEnd(this, EndCollidingMessage); if ((this.UUID != this.ParentGroup.RootPart.UUID)) { const int PASS_IF_NOT_HANDLED = 0; const int PASS_ALWAYS = 1; const int PASS_NEVER = 2; if (this.PassCollisions == PASS_NEVER) { } if (this.PassCollisions == PASS_ALWAYS) { m_parentGroup.Scene.EventManager.TriggerScriptCollidingEnd( this.ParentGroup.RootPart, EndCollidingMessage); } else if (((this.ScriptEvents & scriptEvents.collision_end) == 0) && this.PassCollisions == PASS_IF_NOT_HANDLED) //If no event in this prim, pass to parent { m_parentGroup.Scene.EventManager.TriggerScriptCollidingEnd( this.ParentGroup.RootPart, EndCollidingMessage); } } } } } if ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0 || (AggregateScriptEvents & scriptEvents.land_collision) != 0) { if (startedColliders.Count > 0) { ColliderArgs LandStartCollidingMessage = new ColliderArgs(); List<DetectedObject> colliding = (from localId in startedColliders where localId == 0 select new DetectedObject { keyUUID = UUID.Zero, nameStr = "", ownerUUID = UUID.Zero, posVector = m_parentGroup.RootPart.AbsolutePosition, rotQuat = Quaternion.Identity, velVector = Vector3.Zero, colliderType = 0, groupUUID = UUID.Zero }).ToList(); if (colliding.Count > 0) { LandStartCollidingMessage.Colliders = colliding; // always running this check because if the user deletes the object it would return a null reference. if (m_parentGroup == null) return; if (m_parentGroup.Scene == null) return; m_parentGroup.Scene.EventManager.TriggerScriptLandCollidingStart(this, LandStartCollidingMessage); if ((this.UUID != this.ParentGroup.RootPart.UUID)) { const int PASS_IF_NOT_HANDLED = 0; const int PASS_ALWAYS = 1; const int PASS_NEVER = 2; if (this.PassCollisions == PASS_NEVER) { } if (this.PassCollisions == PASS_ALWAYS) { m_parentGroup.Scene.EventManager.TriggerScriptLandCollidingStart( this.ParentGroup.RootPart, LandStartCollidingMessage); } else if (((this.ScriptEvents & scriptEvents.land_collision_start) == 0) && this.PassCollisions == PASS_IF_NOT_HANDLED) //If no event in this prim, pass to parent { m_parentGroup.Scene.EventManager.TriggerScriptLandCollidingStart( this.ParentGroup.RootPart, LandStartCollidingMessage); } } } } } if ((AggregateScriptEvents & scriptEvents.land_collision) != 0) { if (m_lastColliders.Count > 0) { ColliderArgs LandCollidingMessage = new ColliderArgs(); List<DetectedObject> colliding = new List<DetectedObject>(); foreach (uint localId in m_lastColliders) { if (localId == 0) { //Hope that all is left is ground! DetectedObject detobj = new DetectedObject { keyUUID = UUID.Zero, nameStr = "", ownerUUID = UUID.Zero, posVector = m_parentGroup.RootPart.AbsolutePosition, rotQuat = Quaternion.Identity, velVector = Vector3.Zero, colliderType = 0, groupUUID = UUID.Zero }; colliding.Add(detobj); } } if (colliding.Count > 0) { LandCollidingMessage.Colliders = colliding; // always running this check because if the user deletes the object it would return a null reference. if (m_parentGroup == null) return; if (m_parentGroup.Scene == null) return; m_parentGroup.Scene.EventManager.TriggerScriptLandColliding(this, LandCollidingMessage); if ((this.UUID != this.ParentGroup.RootPart.UUID)) { const int PASS_IF_NOT_HANDLED = 0; const int PASS_ALWAYS = 1; const int PASS_NEVER = 2; if (this.PassCollisions == PASS_NEVER) { } if (this.PassCollisions == PASS_ALWAYS) { m_parentGroup.Scene.EventManager.TriggerScriptLandColliding( this.ParentGroup.RootPart, LandCollidingMessage); } else if (((this.ScriptEvents & scriptEvents.land_collision) == 0) && this.PassCollisions == PASS_IF_NOT_HANDLED) //If no event in this prim, pass to parent { m_parentGroup.Scene.EventManager.TriggerScriptLandColliding( this.ParentGroup.RootPart, LandCollidingMessage); } } } } } if ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) { if (endedColliders.Count > 0) { ColliderArgs LandEndCollidingMessage = new ColliderArgs(); List<DetectedObject> colliding = (from localId in startedColliders where localId == 0 select new DetectedObject { keyUUID = UUID.Zero, nameStr = "", ownerUUID = UUID.Zero, posVector = m_parentGroup.RootPart.AbsolutePosition, rotQuat = Quaternion.Identity, velVector = Vector3.Zero, colliderType = 0, groupUUID = UUID.Zero }).ToList(); if (colliding.Count > 0) { LandEndCollidingMessage.Colliders = colliding; // always running this check because if the user deletes the object it would return a null reference. if (m_parentGroup == null) return; if (m_parentGroup.Scene == null) return; m_parentGroup.Scene.EventManager.TriggerScriptLandCollidingEnd(this, LandEndCollidingMessage); if ((this.UUID != this.ParentGroup.RootPart.UUID)) { const int PASS_IF_NOT_HANDLED = 0; const int PASS_ALWAYS = 1; const int PASS_NEVER = 2; if (this.PassCollisions == PASS_NEVER) { } if (this.PassCollisions == PASS_ALWAYS) { m_parentGroup.Scene.EventManager.TriggerScriptLandCollidingEnd( this.ParentGroup.RootPart, LandEndCollidingMessage); } else if (((this.ScriptEvents & scriptEvents.land_collision_end) == 0) && this.PassCollisions == PASS_IF_NOT_HANDLED) //If no event in this prim, pass to parent { m_parentGroup.Scene.EventManager.TriggerScriptLandCollidingEnd( this.ParentGroup.RootPart, LandEndCollidingMessage); } } } } } } }
public void AddCollider(uint localID, ContactPoint contact) { Cleared = false; lock (m_objCollisionList) m_objCollisionList[localID] = contact; }
public override void AddCollisionEvent(uint CollidedWith, ContactPoint contact) { CollisionEventsThisFrame.AddCollider(CollidedWith, contact); }