From 0916b38b8300c41f66c2f22e79c77f3c5f6f4cb7 Mon Sep 17 00:00:00 2001 From: Teravus Ovares Date: Fri, 17 Oct 2008 23:19:00 +0000 Subject: * Fix an over compensation for bounciness on flat Primitive * Implement the linear impulse portion of llPushObject. We should have a lsl compatible implementation of that portion of the push. Angular.. well. still have yet to implement a torque accumulator. * llPushObject respects the region and parcel settings for Restrict Push, it also respects GodMode as is defined in the LSL spec. --- OpenSim/Region/Physics/OdePlugin/ODECharacter.cs | 3 +- OpenSim/Region/Physics/OdePlugin/OdePlugin.cs | 13 +- .../Shared/Api/Implementation/LSL_Api.cs | 172 ++++++++++++++++++++- 3 files changed, 176 insertions(+), 12 deletions(-) diff --git a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs index 23481c6..2cb7e43 100644 --- a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs +++ b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs @@ -634,8 +634,9 @@ namespace OpenSim.Region.Physics.OdePlugin if (pushforce) { m_pidControllerActive = false; + force *= 100f; doForce(force); - + //System.Console.WriteLine("Push!"); //_target_velocity.X += force.X; // _target_velocity.Y += force.Y; //_target_velocity.Z += force.Z; diff --git a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs b/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs index 1dcec12..0cbcb6b 100644 --- a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs +++ b/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs @@ -575,10 +575,7 @@ namespace OpenSim.Region.Physics.OdePlugin for (int i = 0; i < count; i++) { - if (checkDupe(contacts[i],p2.PhysicsActorType)) - { - continue; - } + max_collision_depth = (contacts[i].depth > max_collision_depth) ? contacts[i].depth : max_collision_depth; //m_log.Warn("[CCOUNT]: " + count); @@ -588,7 +585,7 @@ namespace OpenSim.Region.Physics.OdePlugin // We only need to test p2 for 'jump crouch purposes' p2.IsColliding = true; - + //if ((framecount % m_returncollisions) == 0) switch (p1.PhysicsActorType) @@ -759,7 +756,7 @@ namespace OpenSim.Region.Physics.OdePlugin #endregion - if (contacts[i].depth >= 0f) + if (contacts[i].depth >= 0f && !checkDupe(contacts[i], p2.PhysicsActorType)) { // If we're colliding against terrain if (name1 == "Terrain" || name2 == "Terrain") @@ -863,11 +860,11 @@ namespace OpenSim.Region.Physics.OdePlugin if (((Math.Abs(contactGeom.normal.X - contact.normal.X) < 1.026f) && (Math.Abs(contactGeom.normal.Y - contact.normal.Y) < 0.303f) && (Math.Abs(contactGeom.normal.Z - contact.normal.Z) < 0.065f)) && contactGeom.g1 != LandGeom && contactGeom.g2 != LandGeom) { - if (Math.Abs(contact.depth - contactGeom.depth) < 0.272f) + if (Math.Abs(contact.depth - contactGeom.depth) < 0.072f) { //contactGeom.depth *= .00005f; //m_log.DebugFormat("[Collsion]: Depth {0}", Math.Abs(contact.depth - contactGeom.depth)); - // m_log.DebugFormat("[Collision]: <{0},{1},{2}>", Math.Abs(contactGeom.normal.X - contact.normal.X), Math.Abs(contactGeom.normal.Y - contact.normal.Y), Math.Abs(contactGeom.normal.Z - contact.normal.Z)); + //m_log.DebugFormat("[Collision]: <{0},{1},{2}>", Math.Abs(contactGeom.normal.X - contact.normal.X), Math.Abs(contactGeom.normal.Y - contact.normal.Y), Math.Abs(contactGeom.normal.Z - contact.normal.Z)); result = true; break; } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 6a6109b..956a500 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -3456,10 +3456,176 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void llPushObject(string target, LSL_Vector impulse, LSL_Vector ang_impulse, int local) { m_host.AddScriptLPS(1); - SceneObjectPart targ = World.GetSceneObjectPart((UUID)target); - if (targ == null) + bool pushrestricted = World.RegionInfo.RegionSettings.RestrictPushing; + bool pushAllowed = false; + + bool pusheeIsAvatar = false; + UUID targetID = UUID.Zero; + + if (!UUID.TryParse(target,out targetID)) return; - targ.ApplyImpulse(new Vector3((float)impulse.x, (float)impulse.y, (float)impulse.z), local != 0); + + ScenePresence pusheeav = null; + //SceneObjectPart pusheeob = null; + EntityBase obj = null; + Vector3 PusheePos = Vector3.Zero; + SceneObjectPart pusheeob = null; + + List avatars = World.GetAvatars(); + + foreach (ScenePresence avatar in avatars) + { + if (avatar.UUID == targetID) + { + pusheeIsAvatar = true; + + // Pushee doesn't have a physics actor + if (avatar.PhysicsActor == null) + return; + + // Pushee is in GodMode this pushing object isn't owned by them + if (avatar.GodLevel > 0 && m_host.OwnerID != targetID) + return; + + pusheeav = avatar; + + // Find pushee position + // Pushee Linked? + if (pusheeav.ParentID != 0) + { + SceneObjectPart parentobj = World.GetSceneObjectPart(pusheeav.ParentID); + if (parentobj != null) + { + PusheePos = parentobj.AbsolutePosition; + } + else + { + PusheePos = pusheeav.AbsolutePosition; + } + } + else + { + PusheePos = pusheeav.AbsolutePosition; + } + + obj = (EntityBase)pusheeav; + break; + } + } + + if (!pusheeIsAvatar) + { + pusheeob = World.GetSceneObjectPart((UUID)target); + + // We can't find object + if (pusheeob == null) + return; + + // Object not pushable. Not an attachment and has no physics component + if (!pusheeob.IsAttachment && pusheeob.PhysActor == null) + return; + + PusheePos = pusheeob.AbsolutePosition; + //obj = (EntityBase)pusheeob; + } + + + if (pushrestricted) + { + ILandObject targetlandObj = World.LandChannel.GetLandObject(PusheePos.X,PusheePos.Y); + + // We didn't find the parcel but region is push restricted so assume it is NOT ok + if (targetlandObj == null) + return; + + // Need provisions for Group Owned here + if (m_host.OwnerID == targetlandObj.landData.OwnerID || targetlandObj.landData.IsGroupOwned || m_host.OwnerID == targetID) + { + pushAllowed = true; + } + } + else + { + ILandObject targetlandObj = World.LandChannel.GetLandObject(PusheePos.X, PusheePos.Y); + if (targetlandObj == null) + { + // We didn't find the parcel but region isn't push restricted so assume it's ok + pushAllowed = true; + } + else + { + // Parcel push restriction + if ((targetlandObj.landData.Flags & (uint)Parcel.ParcelFlags.RestrictPushObject) == (uint)Parcel.ParcelFlags.RestrictPushObject) + { + // Need provisions for Group Owned here + if (m_host.OwnerID == targetlandObj.landData.OwnerID || targetlandObj.landData.IsGroupOwned || m_host.OwnerID == targetID) + { + pushAllowed = true; + } + + //Parcel.ParcelFlags.RestrictPushObject + //pushAllowed = true; + } + else + { + // Parcel isn't push restricted + pushAllowed = true; + } + } + } + if (pushAllowed) + { + float distance = (PusheePos - m_host.AbsolutePosition).Length(); + float distance_term = distance * distance * distance; // Script Energy + float pusher_mass = m_host.GetMass(); + + float PUSH_ATTENUATION_DISTANCE = 17f; + float PUSH_ATTENUATION_SCALE = 5f; + float distance_attenuation = 1f; + if (distance > PUSH_ATTENUATION_DISTANCE) + { + float normalized_units = 1f + (distance - PUSH_ATTENUATION_DISTANCE) / PUSH_ATTENUATION_SCALE; + distance_attenuation = 1f / normalized_units; + } + + Vector3 applied_linear_impulse = new Vector3((float)impulse.x, (float)impulse.y, (float)impulse.z); + { + float impulse_length = applied_linear_impulse.Length(); + + float desired_energy = impulse_length * pusher_mass; + if (desired_energy > 0f) + desired_energy += distance_term; + + float scaling_factor = 1f; + scaling_factor *= distance_attenuation; + applied_linear_impulse *= scaling_factor; + + } + if (pusheeIsAvatar) + { + if (pusheeav != null) + { + if (pusheeav.PhysicsActor != null) + { + if (local != 0) + { + applied_linear_impulse *= m_host.GetWorldRotation(); + } + pusheeav.PhysicsActor.AddForce(new PhysicsVector(applied_linear_impulse.X, applied_linear_impulse.Y, applied_linear_impulse.Z), true); + } + } + } + else + { + if (pusheeob != null) + { + if (pusheeob.PhysActor != null) + { + pusheeob.ApplyImpulse(applied_linear_impulse, local != 0); + } + } + } + } } public void llPassCollisions(int pass) -- cgit v1.1