diff --git a/OpenSim/Framework/AvatarAppearance.cs b/OpenSim/Framework/AvatarAppearance.cs index 16385417e6..2183fb6c8a 100644 --- a/OpenSim/Framework/AvatarAppearance.cs +++ b/OpenSim/Framework/AvatarAppearance.cs @@ -40,6 +40,13 @@ namespace OpenSim.Framework /// public class AvatarAppearance { + // SL box diferent to size + const float AVBOXAJUST = 0.2f; + // constrains for ubitode physics + const float AVBOXMINX = 0.2f; + const float AVBOXMINY = 0.3f; + const float AVBOXMINZ = 1.2f; + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); // this is viewer capabilities and weared things dependent @@ -55,6 +62,10 @@ namespace OpenSim.Framework protected AvatarWearable[] m_wearables; protected Dictionary> m_attachments; protected float m_avatarHeight = 0; + protected Vector3 m_avatarSize = new Vector3(0.45f, 0.6f, 1.9f); // sl Z cloud value + protected Vector3 m_avatarBoxSize = new Vector3(0.45f, 0.6f, 1.9f); + protected float m_avatarFeetOffset = 0; + protected float m_avatarAnimOffset = 0; public virtual int Serial { @@ -68,6 +79,21 @@ namespace OpenSim.Framework set { m_visualparams = value; } } + public virtual Vector3 AvatarSize + { + get { return m_avatarSize; } + } + + public virtual Vector3 AvatarBoxSize + { + get { return m_avatarBoxSize; } + } + + public virtual float AvatarFeetOffset + { + get { return m_avatarFeetOffset + m_avatarAnimOffset; } + } + public virtual Primitive.TextureEntry Texture { get { return m_texture; } @@ -98,7 +124,8 @@ namespace OpenSim.Framework SetDefaultWearables(); SetDefaultTexture(); SetDefaultParams(); - SetHeight(); +// SetHeight(); + SetSize(new Vector3(0.45f,0.6f,1.9f)); m_attachments = new Dictionary>(); } @@ -107,7 +134,7 @@ namespace OpenSim.Framework // m_log.WarnFormat("[AVATAR APPEARANCE]: create appearance from OSDMap"); Unpack(map); - SetHeight(); +// SetHeight(); done in Unpack } public AvatarAppearance(AvatarWearable[] wearables, Primitive.TextureEntry textureEntry, byte[] visualParams) @@ -131,7 +158,9 @@ namespace OpenSim.Framework else SetDefaultParams(); - SetHeight(); +// SetHeight(); + if(m_avatarHeight == 0) + SetSize(new Vector3(0.45f,0.6f,1.9f)); m_attachments = new Dictionary>(); } @@ -150,7 +179,8 @@ namespace OpenSim.Framework SetDefaultWearables(); SetDefaultTexture(); SetDefaultParams(); - SetHeight(); +// SetHeight(); + SetSize(new Vector3(0.45f, 0.6f, 1.9f)); m_attachments = new Dictionary>(); return; @@ -179,7 +209,8 @@ namespace OpenSim.Framework if (appearance.VisualParams != null) m_visualparams = (byte[])appearance.VisualParams.Clone(); - m_avatarHeight = appearance.m_avatarHeight; +// m_avatarHeight = appearance.m_avatarHeight; + SetSize(appearance.AvatarSize); // Copy the attachment, force append mode since that ensures consistency m_attachments = new Dictionary>(); @@ -346,8 +377,8 @@ namespace OpenSim.Framework } } // Reset the height if the visual parameters actually changed - if (changed) - SetHeight(); +// if (changed) +// SetHeight(); return changed; } @@ -363,6 +394,7 @@ namespace OpenSim.Framework /// public virtual void SetHeight() { +/* // Start with shortest possible female avatar height m_avatarHeight = 1.14597f; // Add offset for male avatars @@ -375,6 +407,35 @@ namespace OpenSim.Framework + 0.07f * (float)m_visualparams[(int)VPElement.SHOES_PLATFORM_HEIGHT] / 255.0f + 0.08f * (float)m_visualparams[(int)VPElement.SHOES_HEEL_HEIGHT] / 255.0f + 0.076f * (float)m_visualparams[(int)VPElement.SHAPE_NECK_LENGTH] / 255.0f; +*/ + } + + public void SetSize(Vector3 avSize) + { + if (avSize.X > 32f) + avSize.X = 32f; + else if (avSize.X < 0.1f) + avSize.X = 0.1f; + + if (avSize.Y > 32f) + avSize.Y = 32f; + else if (avSize.Y < 0.1f) + avSize.Y = 0.1f; + if (avSize.Z > 32f) + avSize.Z = 32f; + else if (avSize.Z < 0.1f) + avSize.Z = 0.1f; + + m_avatarSize = avSize; + m_avatarBoxSize = avSize; + m_avatarBoxSize.Z += AVBOXAJUST; + if (m_avatarBoxSize.X < AVBOXMINX) + m_avatarBoxSize.X = AVBOXMINX; + if (m_avatarBoxSize.Y < AVBOXMINY) + m_avatarBoxSize.Y = AVBOXMINY; + if (m_avatarBoxSize.Z < AVBOXMINZ) + m_avatarBoxSize.Z = AVBOXMINZ; + m_avatarHeight = m_avatarSize.Z; } public virtual void SetWearable(int wearableId, AvatarWearable wearable) @@ -649,7 +710,8 @@ namespace OpenSim.Framework if ((data != null) && (data["serial"] != null)) m_serial = data["serial"].AsInteger(); if ((data != null) && (data["height"] != null)) - m_avatarHeight = (float)data["height"].AsReal(); +// m_avatarHeight = (float)data["height"].AsReal(); + SetSize(new Vector3(0.45f,0.6f, (float)data["height"].AsReal())); try { diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs index f686c6035d..c9b67defdf 100644 --- a/OpenSim/Framework/IClientAPI.cs +++ b/OpenSim/Framework/IClientAPI.cs @@ -64,7 +64,7 @@ namespace OpenSim.Framework public delegate void NetworkStats(int inPackets, int outPackets, int unAckedBytes); - public delegate void SetAppearance(IClientAPI remoteClient, Primitive.TextureEntry textureEntry, byte[] visualParams); + public delegate void SetAppearance(IClientAPI remoteClient, Primitive.TextureEntry textureEntry, byte[] visualParams, Vector3 AvSize); public delegate void StartAnim(IClientAPI remoteClient, UUID animID); diff --git a/OpenSim/Framework/IImprovedAssetCache.cs b/OpenSim/Framework/IImprovedAssetCache.cs index 251215a559..a0b8b55aaa 100644 --- a/OpenSim/Framework/IImprovedAssetCache.cs +++ b/OpenSim/Framework/IImprovedAssetCache.cs @@ -33,6 +33,7 @@ namespace OpenSim.Framework { void Cache(AssetBase asset); AssetBase Get(string id); + bool Check(string id); void Expire(string id); void Clear(); } diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 8e0b72fe50..4860da051a 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -331,6 +331,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP private Prioritizer m_prioritizer; private bool m_disableFacelights = false; + private bool m_VelocityInterpolate = false; private const uint MaxTransferBytesPerPacket = 600; @@ -4971,7 +4972,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP // in that direction, even though we don't model this on the server. Implementing this in the future // may improve movement smoothness. // acceleration = new Vector3(1, 0, 0); - + angularVelocity = Vector3.Zero; if (sendTexture) @@ -5121,7 +5122,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP update.PCode = (byte)PCode.Avatar; update.ProfileCurve = 1; update.PSBlock = Utils.EmptyBytes; - update.Scale = new Vector3(0.45f, 0.6f, 1.9f); + update.Scale = data.Appearance.AvatarSize; +// update.Scale.Z -= 0.2f; + update.Text = Utils.EmptyBytes; update.TextColor = new byte[4]; @@ -5309,8 +5312,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP // If AgentUpdate is ever handled asynchronously, then we will also need to construct a new AgentUpdateArgs // for each AgentUpdate packet. AddLocalPacketHandler(PacketType.AgentUpdate, HandleAgentUpdate, false); - + AddLocalPacketHandler(PacketType.ViewerEffect, HandleViewerEffect, false); + AddLocalPacketHandler(PacketType.VelocityInterpolateOff, HandleVelocityInterpolateOff, false); + AddLocalPacketHandler(PacketType.VelocityInterpolateOn, HandleVelocityInterpolateOn, false); AddLocalPacketHandler(PacketType.AgentCachedTexture, HandleAgentTextureCached, false); AddLocalPacketHandler(PacketType.MultipleObjectUpdate, HandleMultipleObjUpdate, false); AddLocalPacketHandler(PacketType.MoneyTransferRequest, HandleMoneyTransferRequest, false); @@ -5828,6 +5833,29 @@ namespace OpenSim.Region.ClientStack.LindenUDP return true; } + private bool HandleVelocityInterpolateOff(IClientAPI sender, Packet Pack) + { + VelocityInterpolateOffPacket p = (VelocityInterpolateOffPacket)Pack; + if (p.AgentData.SessionID != SessionId || + p.AgentData.AgentID != AgentId) + return true; + + m_VelocityInterpolate = false; + return true; + } + + private bool HandleVelocityInterpolateOn(IClientAPI sender, Packet Pack) + { + VelocityInterpolateOnPacket p = (VelocityInterpolateOnPacket)Pack; + if (p.AgentData.SessionID != SessionId || + p.AgentData.AgentID != AgentId) + return true; + + m_VelocityInterpolate = true; + return true; + } + + private bool HandleAvatarPropertiesRequest(IClientAPI sender, Packet Pack) { AvatarPropertiesRequestPacket avatarProperties = (AvatarPropertiesRequestPacket)Pack; @@ -6248,6 +6276,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP // Temporarily protect ourselves from the mantis #951 failure. // However, we could do this for several other handlers where a failure isn't terminal // for the client session anyway, in order to protect ourselves against bad code in plugins + Vector3 avSize = appear.AgentData.Size; try { byte[] visualparams = new byte[appear.VisualParam.Length]; @@ -6258,7 +6287,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (appear.ObjectData.TextureEntry.Length > 1) te = new Primitive.TextureEntry(appear.ObjectData.TextureEntry, 0, appear.ObjectData.TextureEntry.Length); - handlerSetAppearance(sender, te, visualparams); + handlerSetAppearance(sender, te, visualparams,avSize); } catch (Exception e) { @@ -11667,14 +11696,30 @@ namespace OpenSim.Region.ClientStack.LindenUDP cachedresp.WearableData = new AgentCachedTextureResponsePacket.WearableDataBlock[cachedtex.WearableData.Length]; - for (int i = 0; i < cachedtex.WearableData.Length; i++) + IImprovedAssetCache cache = m_scene.RequestModuleInterface(); + if (cache == null) { - cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock(); - cachedresp.WearableData[i].TextureIndex = cachedtex.WearableData[i].TextureIndex; - cachedresp.WearableData[i].TextureID = UUID.Zero; - cachedresp.WearableData[i].HostName = new byte[0]; + for (int i = 0; i < cachedtex.WearableData.Length; i++) + { + cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock(); + cachedresp.WearableData[i].TextureIndex = cachedtex.WearableData[i].TextureIndex; + cachedresp.WearableData[i].TextureID = UUID.Zero; + cachedresp.WearableData[i].HostName = new byte[0]; + } + } + else + { + for (int i = 0; i < cachedtex.WearableData.Length; i++) + { + cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock(); + cachedresp.WearableData[i].TextureIndex = cachedtex.WearableData[i].TextureIndex; + if(cache.Check(cachedtex.WearableData[i].ID.ToString())) + cachedresp.WearableData[i].TextureID = UUID.Zero; + else + cachedresp.WearableData[i].TextureID = UUID.Zero; + cachedresp.WearableData[i].HostName = new byte[0]; + } } - cachedresp.Header.Zerocoded = true; OutPacket(cachedresp, ThrottleOutPacketType.Task); diff --git a/OpenSim/Region/CoreModules/Asset/CenomeAssetCache.cs b/OpenSim/Region/CoreModules/Asset/CenomeAssetCache.cs index e40caeca4d..f43305ff40 100644 --- a/OpenSim/Region/CoreModules/Asset/CenomeAssetCache.cs +++ b/OpenSim/Region/CoreModules/Asset/CenomeAssetCache.cs @@ -194,6 +194,12 @@ namespace OpenSim.Region.CoreModules.Asset #region IImprovedAssetCache Members + + public bool Check(string id) + { + return false; + } + /// /// Cache asset. /// diff --git a/OpenSim/Region/CoreModules/Asset/CoreAssetCache.cs b/OpenSim/Region/CoreModules/Asset/CoreAssetCache.cs index 9742a5caa4..58ce61ac4e 100644 --- a/OpenSim/Region/CoreModules/Asset/CoreAssetCache.cs +++ b/OpenSim/Region/CoreModules/Asset/CoreAssetCache.cs @@ -112,6 +112,10 @@ namespace OpenSim.Region.CoreModules.Asset //////////////////////////////////////////////////////////// // IImprovedAssetCache // + public bool Check(string id) + { + return false; + } public void Cache(AssetBase asset) { diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs index b1bb56bb0b..a0f1e8c560 100644 --- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs +++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs @@ -348,6 +348,17 @@ namespace OpenSim.Region.CoreModules.Asset return asset; } + private bool CheckFromMemoryCache(string id) + { + AssetBase asset = null; + + if (m_MemoryCache.TryGetValue(id, out asset)) + return true; + + return false; + } + + /// /// Try to get an asset from the file cache. /// @@ -420,6 +431,50 @@ namespace OpenSim.Region.CoreModules.Asset return asset; } + private bool CheckFromFileCache(string id) + { + bool found = false; + + string filename = GetFileName(id); + if (File.Exists(filename)) + { + // actually check if we can open it, and so update expire + FileStream stream = null; + try + { + stream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read); + if (stream != null) + { + found = true; + stream.Close(); + } + + } + catch (System.Runtime.Serialization.SerializationException e) + { + found = false; + m_log.ErrorFormat( + "[FLOTSAM ASSET CACHE]: Failed to check file {0} for asset {1}. Exception {2} {3}", + filename, id, e.Message, e.StackTrace); + + // If there was a problem deserializing the asset, the asset may + // either be corrupted OR was serialized under an old format + // {different version of AssetBase} -- we should attempt to + // delete it and re-cache + File.Delete(filename); + } + catch (Exception e) + { + found = false; + m_log.ErrorFormat( + "[FLOTSAM ASSET CACHE]: Failed to check file {0} for asset {1}. Exception {2} {3}", + filename, id, e.Message, e.StackTrace); + } + } + + return found; + } + public AssetBase Get(string id) { m_Requests++; @@ -456,11 +511,26 @@ namespace OpenSim.Region.CoreModules.Asset return asset; } + public bool Check(string id) + { + if (m_MemoryCacheEnabled && CheckFromMemoryCache(id)) + return true; + + if (m_FileCacheEnabled && CheckFromFileCache(id)) + return true; + return false; + } + public AssetBase GetCached(string id) { return Get(id); } + public AssetBase CheckCached(string id) + { + return Get(id); + } + public void Expire(string id) { if (m_LogLevel >= 2) @@ -941,6 +1011,11 @@ namespace OpenSim.Region.CoreModules.Asset return asset.Data; } + public bool CheckData(string id) + { + return Check(id); ; + } + public bool Get(string id, object sender, AssetRetrieved handler) { AssetBase asset = Get(id); diff --git a/OpenSim/Region/CoreModules/Asset/GlynnTuckerAssetCache.cs b/OpenSim/Region/CoreModules/Asset/GlynnTuckerAssetCache.cs index 9592ca0019..ce9b5467f6 100644 --- a/OpenSim/Region/CoreModules/Asset/GlynnTuckerAssetCache.cs +++ b/OpenSim/Region/CoreModules/Asset/GlynnTuckerAssetCache.cs @@ -115,6 +115,11 @@ namespace OpenSim.Region.CoreModules.Asset // IImprovedAssetCache // + public bool Check(string id) + { + return false; + } + public void Cache(AssetBase asset) { if (asset != null) diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs index 849600520c..3532b1dfe2 100644 --- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs @@ -145,6 +145,21 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory SetAppearance(sp, appearance.Texture, appearance.VisualParams); } + + public void SetAppearance(IScenePresence sp, Primitive.TextureEntry textureEntry, byte[] visualParams, Vector3 avSize) + { + float oldoff = sp.Appearance.AvatarFeetOffset; + Vector3 oldbox = sp.Appearance.AvatarBoxSize; + + SetAppearance(sp, textureEntry, visualParams); + sp.Appearance.SetSize(avSize); + + float off = sp.Appearance.AvatarFeetOffset; + Vector3 box = sp.Appearance.AvatarBoxSize; + if (oldoff != off || oldbox != box) + ((ScenePresence)sp).SetSize(box, off); + } + /// /// Set appearance data (texture asset IDs and slider settings) /// @@ -174,12 +189,21 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory // m_log.DebugFormat( // "[AVFACTORY]: Setting visual params for {0} to {1}", // client.Name, string.Join(", ", visualParamsStrings)); - +/* float oldHeight = sp.Appearance.AvatarHeight; changed = sp.Appearance.SetVisualParams(visualParams); if (sp.Appearance.AvatarHeight != oldHeight && sp.Appearance.AvatarHeight > 0) ((ScenePresence)sp).SetHeight(sp.Appearance.AvatarHeight); + */ +// float oldoff = sp.Appearance.AvatarFeetOffset; +// Vector3 oldbox = sp.Appearance.AvatarBoxSize; + changed = sp.Appearance.SetVisualParams(visualParams); +// float off = sp.Appearance.AvatarFeetOffset; +// Vector3 box = sp.Appearance.AvatarBoxSize; +// if(oldoff != off || oldbox != box) +// ((ScenePresence)sp).SetSize(box,off); + } // Process the baked texture array @@ -337,6 +361,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory public bool ValidateBakedTextureCache(IScenePresence sp) { bool defonly = true; // are we only using default textures + IImprovedAssetCache cache = m_scene.RequestModuleInterface(); // Process the texture entry for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++) @@ -361,8 +386,16 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory defonly = false; // found a non-default texture reference - if (m_scene.AssetService.Get(face.TextureID.ToString()) == null) - return false; + if (cache != null) + { + if (!cache.Check(face.TextureID.ToString())) + return false; + } + else + { + if (m_scene.AssetService.Get(face.TextureID.ToString()) == null) + return false; + } } // m_log.DebugFormat("[AVFACTORY]: Completed texture check for {0} {1}", sp.Name, sp.UUID); @@ -374,6 +407,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory public int RequestRebake(IScenePresence sp, bool missingTexturesOnly) { int texturesRebaked = 0; + IImprovedAssetCache cache = m_scene.RequestModuleInterface(); for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++) { @@ -397,21 +431,36 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory if (missingTexturesOnly) { - if (m_scene.AssetService.Get(face.TextureID.ToString()) != null) + if (cache != null) { - continue; + if (cache.Check(face.TextureID.ToString())) + continue; + else + { + m_log.DebugFormat( + "[AVFACTORY]: Missing baked texture {0} ({1}) for {2}, requesting rebake.", + face.TextureID, idx, sp.Name); + } } else { - // On inter-simulator teleports, this occurs if baked textures are not being stored by the - // grid asset service (which means that they are not available to the new region and so have - // to be re-requested from the client). - // - // The only available core OpenSimulator behaviour right now - // is not to store these textures, temporarily or otherwise. - m_log.DebugFormat( - "[AVFACTORY]: Missing baked texture {0} ({1}) for {2}, requesting rebake.", - face.TextureID, idx, sp.Name); + if (m_scene.AssetService.Get(face.TextureID.ToString()) != null) + { + continue; + } + + else + { + // On inter-simulator teleports, this occurs if baked textures are not being stored by the + // grid asset service (which means that they are not available to the new region and so have + // to be re-requested from the client). + // + // The only available core OpenSimulator behaviour right now + // is not to store these textures, temporarily or otherwise. + m_log.DebugFormat( + "[AVFACTORY]: Missing baked texture {0} ({1}) for {2}, requesting rebake.", + face.TextureID, idx, sp.Name); + } } } else @@ -611,12 +660,12 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory /// /// /// - private void Client_OnSetAppearance(IClientAPI client, Primitive.TextureEntry textureEntry, byte[] visualParams) + private void Client_OnSetAppearance(IClientAPI client, Primitive.TextureEntry textureEntry, byte[] visualParams, Vector3 avSize) { // m_log.WarnFormat("[AVFACTORY]: Client_OnSetAppearance called for {0} ({1})", client.Name, client.AgentId); ScenePresence sp = m_scene.GetScenePresence(client.AgentId); if (sp != null) - SetAppearance(sp, textureEntry, visualParams); + SetAppearance(sp, textureEntry, visualParams,avSize); else m_log.WarnFormat("[AVFACTORY]: Client_OnSetAppearance unable to find presence for {0}", client.AgentId); } diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index bacc9c90a3..e026ffd549 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -140,6 +140,8 @@ namespace OpenSim.Region.Framework.Scenes private Vector3 m_lastPosition; private Quaternion m_lastRotation; private Vector3 m_lastVelocity; + private Vector3 m_lastSize = new Vector3(0.45f,0.6f,1.9f); + private Vector3? m_forceToApply; private int m_userFlags; @@ -562,7 +564,24 @@ namespace OpenSim.Region.Framework.Scenes // Scene.RegionInfo.RegionName, Name, m_velocity); } } +/* + public override Vector3 AngularVelocity + { + get + { + if (PhysicsActor != null) + { + m_rotationalvelocity = PhysicsActor.RotationalVelocity; + // m_log.DebugFormat( + // "[SCENE PRESENCE]: Set velocity {0} for {1} in {2} via getting Velocity!", + // m_velocity, Name, Scene.RegionInfo.RegionName); + } + + return m_rotationalvelocity; + } + } +*/ private Quaternion m_bodyRot = Quaternion.Identity; public Quaternion Rotation @@ -1260,6 +1279,13 @@ namespace OpenSim.Region.Framework.Scenes PhysicsActor.Size = new Vector3(0.45f, 0.6f, height); } + public void SetSize(Vector3 size, float feetoffset) + { + if (PhysicsActor != null && !IsChildAgent) + PhysicsActor.setAvatarSize(size, feetoffset); + + } + /// /// Complete Avatar's movement into the region. /// @@ -2566,9 +2592,13 @@ namespace OpenSim.Region.Framework.Scenes // NOTE: Velocity is not the same as m_velocity. Velocity will attempt to // grab the latest PhysicsActor velocity, whereas m_velocity is often // storing a requested force instead of an actual traveling velocity + if (Appearance.AvatarSize != m_lastSize) + { + m_lastSize = Appearance.AvatarSize; + SendAvatarDataToAllAgents(); + } - // Throw away duplicate or insignificant updates - if (!Rotation.ApproxEquals(m_lastRotation, ROTATION_TOLERANCE) || + else if (!Rotation.ApproxEquals(m_lastRotation, ROTATION_TOLERANCE) || !Velocity.ApproxEquals(m_lastVelocity, VELOCITY_TOLERANCE) || !m_pos.ApproxEquals(m_lastPosition, POSITION_TOLERANCE)) { @@ -2866,6 +2896,8 @@ namespace OpenSim.Region.Framework.Scenes avatar.ControllingClient.SendAppearance( UUID, Appearance.VisualParams, Appearance.Texture.GetBytes()); + + } #endregion @@ -3438,15 +3470,22 @@ namespace OpenSim.Region.Framework.Scenes } if (Appearance.AvatarHeight == 0) - Appearance.SetHeight(); +// Appearance.SetHeight(); + Appearance.SetSize(new Vector3(0.45f,0.6f,1.9f)); PhysicsScene scene = m_scene.PhysicsScene; Vector3 pVec = AbsolutePosition; +/* PhysicsActor = scene.AddAvatar( LocalId, Firstname + "." + Lastname, pVec, new Vector3(0.45f, 0.6f, Appearance.AvatarHeight), isFlying); +*/ + + PhysicsActor = scene.AddAvatar( + LocalId, Firstname + "." + Lastname, pVec, + Appearance.AvatarBoxSize,Appearance.AvatarFeetOffset, isFlying); //PhysicsActor.OnRequestTerseUpdate += SendTerseUpdateToAllClients; PhysicsActor.OnCollisionUpdate += PhysicsCollisionUpdate; @@ -3465,6 +3504,7 @@ namespace OpenSim.Region.Framework.Scenes ControllingClient.SendAgentAlertMessage("Physics is having a problem with your avatar. You may not be able to move until you relog.", true); } + /// /// Event called by the physics plugin to tell the avatar about a collision. /// @@ -3494,7 +3534,6 @@ namespace OpenSim.Region.Framework.Scenes CollisionEventUpdate collisionData = (CollisionEventUpdate)e; Dictionary coldata = collisionData.m_objCollisionList; - CollisionPlane = Vector4.UnitW; // // No collisions at all means we may be flying. Update always // // to make falling work @@ -3506,6 +3545,7 @@ namespace OpenSim.Region.Framework.Scenes if (coldata.Count != 0) { +/* switch (Animator.CurrentMovementAnimation) { case "STAND": @@ -3514,24 +3554,36 @@ namespace OpenSim.Region.Framework.Scenes case "CROUCH": case "CROUCHWALK": { + */ ContactPoint lowest; lowest.SurfaceNormal = Vector3.Zero; lowest.Position = Vector3.Zero; - lowest.Position.Z = Single.NaN; + lowest.Position.Z = float.MaxValue; foreach (ContactPoint contact in coldata.Values) { - if (Single.IsNaN(lowest.Position.Z) || contact.Position.Z < lowest.Position.Z) + + if (contact.CharacterFeet && contact.Position.Z < lowest.Position.Z) { lowest = contact; } } - CollisionPlane = new Vector4(-lowest.SurfaceNormal, -Vector3.Dot(lowest.Position, lowest.SurfaceNormal)); + if (lowest.Position.Z != float.MaxValue) + { + lowest.SurfaceNormal = -lowest.SurfaceNormal; + CollisionPlane = new Vector4(lowest.SurfaceNormal, Vector3.Dot(lowest.Position, lowest.SurfaceNormal)); + } + else + CollisionPlane = Vector4.UnitW; +/* } break; } +*/ } + else + CollisionPlane = Vector4.UnitW; RaiseCollisionScriptEvents(coldata); diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs index a31ccacdb1..1b4ed1e76e 100644 --- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs +++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs @@ -911,7 +911,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server // Mimicking LLClientView which gets always set appearance from client. AvatarAppearance appearance; m_scene.GetAvatarAppearance(this, out appearance); - OnSetAppearance(this, appearance.Texture, (byte[])appearance.VisualParams.Clone()); + OnSetAppearance(this, appearance.Texture, (byte[])appearance.VisualParams.Clone(),appearance.AvatarSize); } public void SendRegionHandshake(RegionInfo regionInfo, RegionHandshakeArgs args) diff --git a/OpenSim/Region/Physics/Manager/PhysicsActor.cs b/OpenSim/Region/Physics/Manager/PhysicsActor.cs index 5af6373f0e..e39cee7d0d 100644 --- a/OpenSim/Region/Physics/Manager/PhysicsActor.cs +++ b/OpenSim/Region/Physics/Manager/PhysicsActor.cs @@ -61,6 +61,7 @@ namespace OpenSim.Region.Physics.Manager public Vector3 SurfaceNormal; public float PenetrationDepth; public float RelativeSpeed; + public bool CharacterFeet; public ContactPoint(Vector3 position, Vector3 surfaceNormal, float penetrationDepth) { @@ -68,6 +69,16 @@ namespace OpenSim.Region.Physics.Manager SurfaceNormal = surfaceNormal; PenetrationDepth = penetrationDepth; RelativeSpeed = 0f; // for now let this one be set explicity + CharacterFeet = true; // keep other plugins work as before + } + + public ContactPoint(Vector3 position, Vector3 surfaceNormal, float penetrationDepth, bool feet) + { + Position = position; + SurfaceNormal = surfaceNormal; + PenetrationDepth = penetrationDepth; + RelativeSpeed = 0f; // for now let this one be set explicity + CharacterFeet = feet; // keep other plugins work as before } } @@ -173,6 +184,11 @@ namespace OpenSim.Region.Physics.Manager public abstract Vector3 Size { get; set; } + public virtual void setAvatarSize(Vector3 size, float feetOffset) + { + Size = size; + } + public virtual bool Phantom { get; set; } public virtual bool IsVolumeDtc diff --git a/OpenSim/Region/Physics/Manager/PhysicsScene.cs b/OpenSim/Region/Physics/Manager/PhysicsScene.cs index ce269fabc1..cdffa6b3c6 100644 --- a/OpenSim/Region/Physics/Manager/PhysicsScene.cs +++ b/OpenSim/Region/Physics/Manager/PhysicsScene.cs @@ -127,8 +127,10 @@ namespace OpenSim.Region.Physics.Manager /// /// /// - public abstract PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 size, bool isFlying); - + public virtual PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 size, bool isFlying) + { + return null; + } /// /// Add an avatar /// @@ -145,6 +147,12 @@ namespace OpenSim.Region.Physics.Manager return ret; } + public virtual PhysicsActor AddAvatar(uint localID, string avName, Vector3 position, Vector3 size, float feetOffset, bool isFlying) + { + PhysicsActor ret = AddAvatar(localID, avName, position, size, isFlying); + return ret; + } + /// /// Remove an avatar. /// diff --git a/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs b/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs index 3d5be3e590..bb04ea73be 100644 --- a/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs +++ b/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs @@ -74,31 +74,31 @@ namespace OpenSim.Region.Physics.OdePlugin private Vector3 _position; private Vector3 _zeroPosition; - private bool _zeroFlag = false; private Vector3 _velocity; private Vector3 _target_velocity; private Vector3 _acceleration; private Vector3 m_rotationalVelocity; private Vector3 m_size; private Quaternion m_orientation; + private Quaternion m_orientation2D; private float m_mass = 80f; public float m_density = 60f; private bool m_pidControllerActive = true; - public float PID_D = 800.0f; - public float PID_P = 900.0f; - //private static float POSTURE_SERVO = 10000.0f; + const float basePID_D = 0.55f; // scaled for unit mass unit time (2200 /(50*80)) + const float basePID_P = 0.225f; // scaled for unit mass unit time (900 /(50*80)) + public float PID_D; + public float PID_P; - private float m_invElipSizeX; - private float m_invElipSizeY; + private float timeStep; + private float invtimeStep; + private float m_feetOffset = 0; private float feetOff = 0; private float feetSZ = 0.5f; - const float feetScale = 0.9f; - const float invFeetScale = 1.0f / 0.9f; - const float sizeZAdjust = 0.15f; + const float feetScale = 0.8f; private float boneOff = 0; - + private float m_lastVelocitySqr = 0; public float walkDivisor = 1.3f; public float runDivisor = 0.8f; @@ -107,6 +107,9 @@ namespace OpenSim.Region.Physics.OdePlugin private bool m_iscollidingGround = false; private bool m_iscollidingObj = false; private bool m_alwaysRun = false; + + private bool _zeroFlag = false; + private int m_requestedUpdateFrequency = 0; private uint m_localID = 0; public bool m_returnCollisions = false; @@ -124,6 +127,7 @@ namespace OpenSim.Region.Physics.OdePlugin int m_colliderfilter = 0; int m_colliderGroundfilter = 0; int m_colliderObjectfilter = 0; + bool m_collisionException = false; // Default we're a Character private CollisionCategories m_collisionCategories = (CollisionCategories.Character); @@ -136,10 +140,11 @@ namespace OpenSim.Region.Physics.OdePlugin // we do land collisions not ode | CollisionCategories.Land); public IntPtr Body = IntPtr.Zero; private OdeScene _parent_scene; - public IntPtr topbox = IntPtr.Zero; - public IntPtr midbox = IntPtr.Zero; - public IntPtr feetbox = IntPtr.Zero; - public IntPtr bonebox = IntPtr.Zero; + private IntPtr topbox = IntPtr.Zero; + private IntPtr midbox = IntPtr.Zero; + private IntPtr feetbox = IntPtr.Zero; + private IntPtr bbox = IntPtr.Zero; + public IntPtr collider = IntPtr.Zero; public IntPtr Amotor = IntPtr.Zero; @@ -147,6 +152,7 @@ namespace OpenSim.Region.Physics.OdePlugin + public int m_eventsubscription = 0; private int m_cureventsubscription = 0; private CollisionEventUpdate CollisionEventsThisFrame = null; @@ -160,9 +166,13 @@ namespace OpenSim.Region.Physics.OdePlugin - public OdeCharacter(String avName, OdeScene parent_scene, Vector3 pos, Vector3 pSize, float pid_d, float pid_p, float density, float walk_divisor, float rundivisor) + public OdeCharacter(uint localID, String avName, OdeScene parent_scene, Vector3 pos, Vector3 pSize, float pfeetOffset, float density, float walk_divisor, float rundivisor) { m_uuid = UUID.Random(); + m_localID = localID; + + timeStep = parent_scene.ODE_STEPSIZE; + invtimeStep = 1 / timeStep; if (pos.IsFinite()) { @@ -184,8 +194,6 @@ namespace OpenSim.Region.Physics.OdePlugin _parent_scene = parent_scene; - PID_D = pid_d; - PID_P = pid_p; m_size.X = pSize.X; m_size.Y = pSize.Y; @@ -198,12 +206,16 @@ namespace OpenSim.Region.Physics.OdePlugin if(m_size.Z <0.01f) m_size.Z = 0.01f; + m_feetOffset = pfeetOffset; m_orientation = Quaternion.Identity; + m_orientation2D = Quaternion.Identity; m_density = density; // force lower density for testing m_density = 3.0f; + m_density *= 1.4f; // scale to have mass similar to capsule + mu = parent_scene.AvatarFriction; walkDivisor = walk_divisor; @@ -211,6 +223,9 @@ namespace OpenSim.Region.Physics.OdePlugin m_mass = m_density * m_size.X * m_size.Y * m_size.Z; ; // sure we have a default + PID_D = basePID_D * m_mass * invtimeStep; + PID_P = basePID_P * m_mass * invtimeStep; + m_isPhysical = false; // current status: no ODE information exists Name = avName; @@ -292,7 +307,7 @@ namespace OpenSim.Region.Physics.OdePlugin set { flying = value; - // m_log.DebugFormat("[PHYSICS]: Set OdeCharacter Flying to {0}", flying); +// m_log.DebugFormat("[PHYSICS]: Set OdeCharacter Flying to {0}", flying); } } @@ -336,25 +351,25 @@ namespace OpenSim.Region.Physics.OdePlugin get { return m_iscollidingGround; } set { - /* we now control this - if (value) - { - m_colliderGroundfilter += 2; - if (m_colliderGroundfilter > 2) - m_colliderGroundfilter = 2; - } - else - { - m_colliderGroundfilter--; - if (m_colliderGroundfilter < 0) - m_colliderGroundfilter = 0; - } +/* we now control this + if (value) + { + m_colliderGroundfilter += 2; + if (m_colliderGroundfilter > 2) + m_colliderGroundfilter = 2; + } + else + { + m_colliderGroundfilter--; + if (m_colliderGroundfilter < 0) + m_colliderGroundfilter = 0; + } - if (m_colliderGroundfilter == 0) - m_iscollidingGround = false; - else - m_iscollidingGround = true; - */ + if (m_colliderGroundfilter == 0) + m_iscollidingGround = false; + else + m_iscollidingGround = true; + */ } } @@ -386,7 +401,7 @@ namespace OpenSim.Region.Physics.OdePlugin else m_iscollidingObj = true; - // m_iscollidingObj = value; +// m_iscollidingObj = value; if (m_iscollidingObj) m_pidControllerActive = false; @@ -475,6 +490,28 @@ namespace OpenSim.Region.Physics.OdePlugin } } + public override void setAvatarSize(Vector3 size, float feetOffset) + { + if (size.IsFinite()) + { + if (size.X < 0.01f) + size.X = 0.01f; + if (size.Y < 0.01f) + size.Y = 0.01f; + if (size.Z < 0.01f) + size.Z = 0.01f; + + strAvatarSize st = new strAvatarSize(); + st.size = size; + st.offset = feetOffset; + AddChange(changes.AvatarSize, st); + } + else + { + m_log.Warn("[PHYSICS]: Got a NaN AvatarSize from Scene on a Character"); + } + + } /// /// This creates the Avatar's physical Surrogate at the position supplied /// @@ -491,7 +528,7 @@ namespace OpenSim.Region.Physics.OdePlugin { get { - return m_density * m_size.X * m_size.Y * m_size.Z; + return m_mass; } } public override void link(PhysicsActor obj) @@ -612,9 +649,8 @@ namespace OpenSim.Region.Physics.OdePlugin get { return m_orientation; } set { - // fakeori = value; - // givefakeori++; - +// fakeori = value; +// givefakeori++; value.Normalize(); AddChange(changes.Orientation, value); } @@ -668,33 +704,72 @@ namespace OpenSim.Region.Physics.OdePlugin AddChange(changes.Momentum, momentum); } + private void ajustCollider() + { + float vq = _velocity.LengthSquared(); + if (m_lastVelocitySqr != vq) + { + m_lastVelocitySqr = vq; + if (vq > 100.0f) + { + Vector3 off = _velocity; + float t = 0.5f * timeStep; + off = off * t; + d.GeomSetOffsetPosition(bbox, off.X, off.Y, off.Z); + off.X = 2.0f * (m_size.X + Math.Abs(off.X)); + off.Y = 2.0f * (m_size.Y + Math.Abs(off.Y)); + off.Z = m_size.Z + 2.0f * Math.Abs(off.Z); + d.GeomBoxSetLengths(bbox, off.X, off.Y, off.Z); + + d.GeomSetCategoryBits(bbox, (uint)m_collisionCategories); + d.GeomSetCollideBits(bbox, (uint)m_collisionFlags); + d.GeomSetCategoryBits(topbox, 0); + d.GeomSetCollideBits(topbox, 0); + d.GeomSetCategoryBits(midbox, 0); + d.GeomSetCollideBits(midbox, 0); + d.GeomSetCategoryBits(feetbox, 0); + d.GeomSetCollideBits(feetbox, 0); + } + else + { + d.GeomSetCategoryBits(bbox, 0); + d.GeomSetCollideBits(bbox, 0); + d.GeomSetCategoryBits(topbox, (uint)m_collisionCategories); + d.GeomSetCollideBits(topbox, (uint)m_collisionFlags); + d.GeomSetCategoryBits(midbox, (uint)m_collisionCategories); + d.GeomSetCollideBits(midbox, (uint)m_collisionFlags); + d.GeomSetCategoryBits(feetbox, (uint)m_collisionCategories); + d.GeomSetCollideBits(feetbox, (uint)m_collisionFlags); + } + } + } + private void AvatarGeomAndBodyCreation(float npositionX, float npositionY, float npositionZ) { // sizes one day should came from visual parameters - float sz = m_size.Z + sizeZAdjust; + float sx = m_size.X; + float sy = m_size.Y; + float sz = m_size.Z; - m_invElipSizeX = 1.0f / m_size.X; - m_invElipSizeY = 1.0f / m_size.Y; + float topsx = sx * 0.9f; + float midsx = sx; + float feetsx = sx * feetScale; + float bonesx = sx * 0.2f; - float topsx = m_size.X; - float midsx = m_size.X; - float feetsx = m_size.X * feetScale; - float bonesx = feetsx * 0.2f; - - float topsy = m_size.Y * 0.5f; - float midsy = m_size.Y; - float feetsy = m_size.Y * feetScale; + float topsy = sy * 0.4f; + float midsy = sy; + float feetsy = sy * feetScale * 0.8f; float bonesy = feetsy * 0.2f; float topsz = sz * 0.15f; - float feetsz = sz * 0.3f; + float feetsz = sz * 0.45f; if (feetsz > 0.6f) feetsz = 0.6f; float midsz = sz - topsz - feetsz; float bonesz = sz; - float bot = -sz * 0.5f; + float bot = -sz * 0.5f + m_feetOffset; boneOff = bot + 0.3f; @@ -708,47 +783,37 @@ namespace OpenSim.Region.Physics.OdePlugin bot += midsz; float topz = bot + topsz * 0.5f; - _parent_scene.waitForSpaceUnlock(_parent_scene.ActiveSpace); + _parent_scene.waitForSpaceUnlock(_parent_scene.CharsSpace); - feetbox = d.CreateBox(_parent_scene.ActiveSpace, feetsx, feetsy, feetsz); - d.GeomSetCategoryBits(feetbox, (uint)m_collisionCategories); - d.GeomSetCollideBits(feetbox, (uint)m_collisionFlags); + collider = d.HashSpaceCreate(_parent_scene.CharsSpace); + d.HashSpaceSetLevels(collider, -4, 3); + d.SpaceSetSublevel(collider, 3); + d.SpaceSetCleanup(collider, false); + d.GeomSetCategoryBits(collider, (uint)m_collisionCategories); + d.GeomSetCollideBits(collider, (uint)m_collisionFlags); - midbox = d.CreateBox(_parent_scene.ActiveSpace, midsx, midsy, midsz); - d.GeomSetCategoryBits(midbox, (uint)m_collisionCategories); - d.GeomSetCollideBits(midbox, (uint)m_collisionFlags); + feetbox = d.CreateBox(collider, feetsx, feetsy, feetsz); + midbox = d.CreateBox(collider, midsx, midsy, midsz); + topbox = d.CreateBox(collider, topsx, topsy, topsz); + bbox = d.CreateBox(collider, m_size.X, m_size.Y, m_size.Z); - topbox = d.CreateBox(_parent_scene.ActiveSpace, topsx, topsy, topsz); - d.GeomSetCategoryBits(topbox, (uint)m_collisionCategories); - d.GeomSetCollideBits(topbox, (uint)m_collisionFlags); + m_mass = m_density * m_size.X * m_size.Y * m_size.Z; // update mass - bonebox = d.CreateBox(_parent_scene.ActiveSpace, bonesx, bonesy, bonesz); - d.GeomSetCategoryBits(bonebox, (uint)m_collisionCategories); - d.GeomSetCollideBits(bonebox, (uint)m_collisionFlags); + d.MassSetBoxTotal(out ShellMass, m_mass, m_size.X, m_size.Y, m_size.Z); - d.MassSetBox(out ShellMass, m_density, m_size.X , m_size.Y, m_size.Z); - - m_mass = ShellMass.mass; // update mass - - // rescale PID parameters - PID_D = _parent_scene.avPIDD; - PID_P = _parent_scene.avPIDP; - - // rescale PID parameters so that this aren't affected by mass - // and so don't get unstable for some masses - // also scale by ode time step so you don't need to refix them - - PID_D /= 50 * 80; //scale to original mass of around 80 and 50 ODE fps - PID_D *= m_mass / _parent_scene.ODE_STEPSIZE; - PID_P /= 50 * 80; - PID_P *= m_mass / _parent_scene.ODE_STEPSIZE; + PID_D = basePID_D * m_mass / _parent_scene.ODE_STEPSIZE; + PID_P = basePID_P * m_mass / _parent_scene.ODE_STEPSIZE; Body = d.BodyCreate(_parent_scene.world); _zeroFlag = false; + m_collisionException = false; m_pidControllerActive = true; m_freemove = false; + _velocity = Vector3.Zero; + m_lastVelocitySqr = 0; + d.BodySetAutoDisableFlag(Body, false); d.BodySetPosition(Body, npositionX, npositionY, npositionZ); @@ -760,12 +825,15 @@ namespace OpenSim.Region.Physics.OdePlugin d.GeomSetBody(feetbox, Body); d.GeomSetBody(midbox, Body); d.GeomSetBody(topbox, Body); - d.GeomSetBody(bonebox, Body); + d.GeomSetBody(bbox, Body); d.GeomSetOffsetPosition(feetbox, 0, 0, feetz); d.GeomSetOffsetPosition(midbox, 0, 0, midz); d.GeomSetOffsetPosition(topbox, 0, 0, topz); + ajustCollider(); + + // The purpose of the AMotor here is to keep the avatar's physical // surrogate from rotating while moving Amotor = d.JointCreateAMotor(_parent_scene.world, IntPtr.Zero); @@ -828,142 +896,212 @@ namespace OpenSim.Region.Physics.OdePlugin if (topbox != IntPtr.Zero) { _parent_scene.actor_name_map.Remove(topbox); - _parent_scene.waitForSpaceUnlock(_parent_scene.ActiveSpace); + _parent_scene.waitForSpaceUnlock(collider); d.GeomDestroy(topbox); topbox = IntPtr.Zero; } if (midbox != IntPtr.Zero) { _parent_scene.actor_name_map.Remove(midbox); - _parent_scene.waitForSpaceUnlock(_parent_scene.ActiveSpace); + _parent_scene.waitForSpaceUnlock(collider); d.GeomDestroy(midbox); midbox = IntPtr.Zero; } if (feetbox != IntPtr.Zero) { _parent_scene.actor_name_map.Remove(feetbox); - _parent_scene.waitForSpaceUnlock(_parent_scene.ActiveSpace); + _parent_scene.waitForSpaceUnlock(collider); d.GeomDestroy(feetbox); feetbox = IntPtr.Zero; } - if (bonebox != IntPtr.Zero) + if (bbox != IntPtr.Zero) { - _parent_scene.actor_name_map.Remove(bonebox); - _parent_scene.waitForSpaceUnlock(_parent_scene.ActiveSpace); - d.GeomDestroy(bonebox); - bonebox = IntPtr.Zero; + _parent_scene.actor_name_map.Remove(bbox); + _parent_scene.waitForSpaceUnlock(collider); + d.GeomDestroy(bbox); + bbox = IntPtr.Zero; + } + + if (collider != IntPtr.Zero) + { + d.SpaceDestroy(collider); + collider = IntPtr.Zero; } } - public bool Collide(IntPtr me, bool reverse, ref d.ContactGeom contact) + //in place 2D rotation around Z assuming rot is normalised and is a rotation around Z + public void RotateXYonZ(ref float x, ref float y, ref Quaternion rot) { + float sin = 2.0f * rot.Z * rot.W; + float cos = rot.W * rot.W - rot.Z * rot.Z; + float tx = x; - if (me == bonebox) // inner bone + x = tx * cos - y * sin; + y = tx * sin + y * cos; + } + public void RotateXYonZ(ref float x, ref float y, ref float sin, ref float cos) + { + float tx = x; + x = tx * cos - y * sin; + y = tx * sin + y * cos; + } + public void invRotateXYonZ(ref float x, ref float y, ref float sin, ref float cos) + { + float tx = x; + x = tx * cos + y * sin; + y = -tx * sin + y * cos; + } + + public void invRotateXYonZ(ref float x, ref float y, ref Quaternion rot) + { + float sin = - 2.0f * rot.Z * rot.W; + float cos = rot.W * rot.W - rot.Z * rot.Z; + float tx = x; + + x = tx * cos - y * sin; + y = tx * sin + y * cos; + } + + + public bool Collide(IntPtr me, bool reverse, ref d.ContactGeom contact, ref bool feetcollision) + { + feetcollision = false; + if (m_collisionException) + return false; + + Vector3 offset; + + if (me == bbox) // if moving fast { - if (contact.pos.Z - _position.Z < boneOff) - IsColliding = true; - return true; - } + // force a full inelastic collision + m_collisionException = true; - if (me == topbox) // keep a box head - return true; + offset = m_size * m_orientation2D; - // rotate elipsoide assuming only rotation around Z - float ca = m_orientation.W * m_orientation.W - m_orientation.Z * m_orientation.Z; - float sa = 2 * m_orientation.W * m_orientation.Z; - - float isx; - float isy; - - if (me == feetbox) // feet have narrow bounds - { - - isx = m_invElipSizeX * invFeetScale; - isy = m_invElipSizeY * invFeetScale; - } - else - { - isx = m_invElipSizeX; - isy = m_invElipSizeY; - } - - float a = isx * ca - isy * sa; - float b = isx * sa + isy * ca; - - float offx = contact.pos.X - _position.X; - float er = offx * a; - er *= er; - - float offy = contact.pos.Y - _position.Y; - float ty = offy * b; - er += ty * ty; - - if (me == midbox) - { - if (er > 4.0f) // no collision - return false; - if (er < 0.2f) - return true; - - float t = offx * offx + offy * offy; - t = (float)Math.Sqrt(t); - t = 1 / t; - offx *= t; - offy *= t; + offset.X = (float)Math.Abs(offset.X) * 0.5f + contact.depth; + offset.Y = (float)Math.Abs(offset.Y) * 0.5f + contact.depth; + offset.Z = (float)Math.Abs(offset.Z) * 0.5f + contact.depth; if (reverse) { - contact.normal.X = offx; - contact.normal.Y = offy; + offset.X *= -contact.normal.X; + offset.Y *= -contact.normal.Y; + offset.Z *= -contact.normal.Z; } else { - contact.normal.X = -offx; - contact.normal.Y = -offy; + offset.X *= contact.normal.X; + offset.Y *= contact.normal.Y; + offset.Z *= contact.normal.Z; + } + + offset.X += contact.pos.X; + offset.Y += contact.pos.Y; + offset.Z += contact.pos.Z; + + _position = offset; + return false; + } + + offset.X = contact.pos.X - _position.X; + offset.Y = contact.pos.Y - _position.Y; + + if (me == topbox) + { + offset.Z = contact.pos.Z - _position.Z; + + offset.Normalize(); + + if (reverse) + { + contact.normal.X = offset.X; + contact.normal.Y = offset.Y; + contact.normal.Z = offset.Z; + } + else + { + contact.normal.X = -offset.X; + contact.normal.Y = -offset.Y; + contact.normal.Z = -offset.Z; + } + return true; + } + + if (me == midbox) + { + if (Math.Abs(contact.normal.Z) > 0.95f) + offset.Z = contact.pos.Z - _position.Z; + else + offset.Z = contact.normal.Z; + + offset.Normalize(); + + if (reverse) + { + contact.normal.X = offset.X; + contact.normal.Y = offset.Y; + contact.normal.Z = offset.Z; + } + else + { + contact.normal.X = -offset.X; + contact.normal.Y = -offset.Y; + contact.normal.Z = -offset.Z; } - contact.normal.Z = 0; return true; } else if (me == feetbox) { - float c = feetSZ * 2; float h = contact.pos.Z - _position.Z; - float offz = h - feetOff; // distance from top of feetbox - float tz = offz / c; - er += tz * tz; - - if (er > 4.0f) // no collision - return false; - - if (er > 0.2f) + if (Math.Abs(contact.normal.Z) > 0.95f) { - float t = offx * offx + offy * offy + offz * offz; - t = (float)Math.Sqrt(t); - t = 1 / t; - offx *= t; - offy *= t; - offz *= t; - - if (reverse) - { - contact.normal.X = offx; - contact.normal.Y = offy; - contact.normal.Z = offz; - } + if (contact.normal.Z > 0) + contact.normal.Z = 1.0f; else - { - contact.normal.X = -offx; - contact.normal.Y = -offy; - contact.normal.Z = -offz; - } + contact.normal.Z = -1.0f; + contact.normal.X = 0.0f; + contact.normal.Y = 0.0f; + feetcollision = true; + if (h < boneOff) + IsColliding = true; + return true; } - if(h < boneOff) + offset.Z = h - feetOff; // distance from top of feetbox + + if (offset.Z > 0) + return false; + + if (offset.Z > -0.01) + { + offset.X = 0; + offset.Y = 0; + offset.Z = -1.0f; + } + else + { + offset.Normalize(); + } + + if (reverse) + { + contact.normal.X = offset.X; + contact.normal.Y = offset.Y; + contact.normal.Z = offset.Z; + } + else + { + contact.normal.X = -offset.X; + contact.normal.Y = -offset.Y; + contact.normal.Z = -offset.Z; + } + feetcollision = true; + if (h < boneOff) IsColliding = true; } else @@ -977,11 +1115,28 @@ namespace OpenSim.Region.Physics.OdePlugin /// This is the avatar's movement control + PID Controller /// /// - public void Move(float timeStep, List defects) + public void Move(List defects) { if (Body == IntPtr.Zero) return; + if (m_collisionException) + { + d.BodySetPosition(Body,_position.X, _position.Y, _position.Z); + d.BodySetLinearVel(Body, 0, 0, 0); + + float v = _velocity.Length(); + if (v != 0) + { + v = 5.0f / v; + _velocity = _velocity * v; + d.BodySetLinearVel(Body, _velocity.X, _velocity.Y, _velocity.Z); + } + ajustCollider(); + m_collisionException = false; + return; + } + d.Vector3 dtmp = d.BodyGetPosition(Body); Vector3 localpos = new Vector3(dtmp.X, dtmp.Y, dtmp.Z); @@ -989,10 +1144,10 @@ namespace OpenSim.Region.Physics.OdePlugin // so force it back to identity d.Quaternion qtmp; - qtmp.W = m_orientation.W; - qtmp.X = m_orientation.X; - qtmp.Y = m_orientation.Y; - qtmp.Z = m_orientation.Z; + qtmp.W = m_orientation2D.W; + qtmp.X = m_orientation2D.X; + qtmp.Y = m_orientation2D.Y; + qtmp.Z = m_orientation2D.Z; d.BodySetQuaternion(Body, ref qtmp); if (m_pidControllerActive == false) @@ -1055,9 +1210,10 @@ namespace OpenSim.Region.Physics.OdePlugin //****************************************** // colide with land + d.AABB aabb; d.GeomGetAABB(feetbox, out aabb); - float chrminZ = aabb.MinZ - 0.04f; // move up a bit + float chrminZ = aabb.MinZ; ; // move up a bit Vector3 posch = localpos; float ftmp; @@ -1100,11 +1256,12 @@ namespace OpenSim.Region.Physics.OdePlugin contact.PenetrationDepth = depth; contact.Position.X = localpos.X; contact.Position.Y = localpos.Y; - contact.Position.Z = chrminZ; - contact.SurfaceNormal.X = 0f; - contact.SurfaceNormal.Y = 0f; + contact.Position.Z = terrainheight; + contact.SurfaceNormal.X = 0.0f; + contact.SurfaceNormal.Y = 0.0f; contact.SurfaceNormal.Z = -1f; contact.RelativeSpeed = -vel.Z; + contact.CharacterFeet = true; AddCollisionEvent(0, contact); vec.Z *= 0.5f; @@ -1123,6 +1280,7 @@ namespace OpenSim.Region.Physics.OdePlugin m_iscollidingGround = false; } + //****************************************** bool tviszero = (_target_velocity.X == 0.0f && _target_velocity.Y == 0.0f && _target_velocity.Z == 0.0f); @@ -1258,21 +1416,58 @@ namespace OpenSim.Region.Physics.OdePlugin } // update our local ideia of position velocity and aceleration + // _position = localpos; _position = localpos; + if (_zeroFlag) { _velocity = Vector3.Zero; _acceleration = Vector3.Zero; + m_rotationalVelocity = Vector3.Zero; } else { - _acceleration = _velocity; // previus velocity - _velocity = vel; - _acceleration = (vel - _acceleration) / timeStep; + Vector3 a =_velocity; // previus velocity + SetSmooth(ref _velocity, ref vel, 2); + a = (_velocity - a) * invtimeStep; + SetSmooth(ref _acceleration, ref a, 2); + + dtmp = d.BodyGetAngularVel(Body); + m_rotationalVelocity.X = 0f; + m_rotationalVelocity.Y = 0f; + m_rotationalVelocity.Z = dtmp.Z; + Math.Round(m_rotationalVelocity.Z,3); } - + ajustCollider(); } + public void round(ref Vector3 v, int digits) + { + v.X = (float)Math.Round(v.X, digits); + v.Y = (float)Math.Round(v.Y, digits); + v.Z = (float)Math.Round(v.Z, digits); + } + + public void SetSmooth(ref Vector3 dst, ref Vector3 value) + { + dst.X = 0.1f * dst.X + 0.9f * value.X; + dst.Y = 0.1f * dst.Y + 0.9f * value.Y; + dst.Z = 0.1f * dst.Z + 0.9f * value.Z; + } + + public void SetSmooth(ref Vector3 dst, ref Vector3 value, int rounddigits) + { + dst.X = 0.4f * dst.X + 0.6f * value.X; + dst.X = (float)Math.Round(dst.X, rounddigits); + + dst.Y = 0.4f * dst.Y + 0.6f * value.Y; + dst.Y = (float)Math.Round(dst.Y, rounddigits); + + dst.Z = 0.4f * dst.Z + 0.6f * value.Z; + dst.Z = (float)Math.Round(dst.Z, rounddigits); + } + + /// /// Updates the reported position and velocity. /// Used to copy variables from unmanaged space at heartbeat rate and also trigger scene updates acording @@ -1399,10 +1594,11 @@ namespace OpenSim.Region.Physics.OdePlugin AvatarGeomAndBodyCreation(_position.X, _position.Y, _position.Z); - _parent_scene.actor_name_map[topbox] = (PhysicsActor)this; - _parent_scene.actor_name_map[midbox] = (PhysicsActor)this; + _parent_scene.actor_name_map[collider] = (PhysicsActor)this; _parent_scene.actor_name_map[feetbox] = (PhysicsActor)this; - _parent_scene.actor_name_map[bonebox] = (PhysicsActor)this; + _parent_scene.actor_name_map[midbox] = (PhysicsActor)this; + _parent_scene.actor_name_map[topbox] = (PhysicsActor)this; + _parent_scene.actor_name_map[bbox] = (PhysicsActor)this; _parent_scene.AddCharacter(this); } else @@ -1431,6 +1627,12 @@ namespace OpenSim.Region.Physics.OdePlugin { } + private void changeAvatarSize(strAvatarSize st) + { + m_feetOffset = st.offset; + changeSize(st.size); + } + private void changeSize(Vector3 pSize) { if (pSize.IsFinite()) @@ -1449,13 +1651,16 @@ namespace OpenSim.Region.Physics.OdePlugin _position.Z + (m_size.Z - oldsz) * 0.5f); Velocity = Vector3.Zero; + - _parent_scene.actor_name_map[topbox] = (PhysicsActor)this; - _parent_scene.actor_name_map[midbox] = (PhysicsActor)this; + _parent_scene.actor_name_map[collider] = (PhysicsActor)this; _parent_scene.actor_name_map[feetbox] = (PhysicsActor)this; - _parent_scene.actor_name_map[bonebox] = (PhysicsActor)this; + _parent_scene.actor_name_map[midbox] = (PhysicsActor)this; + _parent_scene.actor_name_map[topbox] = (PhysicsActor)this; + _parent_scene.actor_name_map[bbox] = (PhysicsActor)this; } m_freemove = false; + m_collisionException = false; m_pidControllerActive = true; } else @@ -1475,14 +1680,36 @@ namespace OpenSim.Region.Physics.OdePlugin private void changeOrientation(Quaternion newOri) { - d.Quaternion myrot = new d.Quaternion(); - myrot.X = newOri.X; - myrot.Y = newOri.Y; - myrot.Z = newOri.Z; - myrot.W = newOri.W; - float t = d.JointGetAMotorAngle(Amotor, 2); - d.BodySetQuaternion(Body,ref myrot); - m_orientation = newOri; + if (m_orientation != newOri) + { + m_orientation = newOri; // keep a copy for core use + // but only use rotations around Z + + m_orientation2D.W = newOri.W; + m_orientation2D.Z = newOri.Z; + + float t = m_orientation2D.W * m_orientation2D.W + m_orientation2D.Z * m_orientation2D.Z; + if (t > 0) + { + t = 1.0f / (float)Math.Sqrt(t); + m_orientation2D.W *= t; + m_orientation2D.Z *= t; + } + else + { + m_orientation2D.W = 1.0f; + m_orientation2D.Z = 0f; + } + m_orientation2D.Y = 0f; + m_orientation2D.X = 0f; + + d.Quaternion myrot = new d.Quaternion(); + myrot.X = m_orientation2D.X; + myrot.Y = m_orientation2D.Y; + myrot.Z = m_orientation2D.Z; + myrot.W = m_orientation2D.W; + d.BodySetQuaternion(Body, ref myrot); + } } private void changeVelocity(Vector3 newVel) @@ -1564,6 +1791,7 @@ namespace OpenSim.Region.Physics.OdePlugin if (Body != IntPtr.Zero) d.BodySetLinearVel(Body, newmomentum.X, newmomentum.Y, newmomentum.Z); + ajustCollider(); } private void donullchange() @@ -1572,7 +1800,7 @@ namespace OpenSim.Region.Physics.OdePlugin public bool DoAChange(changes what, object arg) { - if (topbox == IntPtr.Zero && what != changes.Add && what != changes.Remove) + if (collider == IntPtr.Zero && what != changes.Add && what != changes.Remove) { return false; } @@ -1638,6 +1866,10 @@ namespace OpenSim.Region.Physics.OdePlugin changeSize((Vector3)arg); break; + case changes.AvatarSize: + changeAvatarSize((strAvatarSize)arg); + break; + case changes.Momentum: changeMomentum((Vector3)arg); break; @@ -1685,5 +1917,12 @@ namespace OpenSim.Region.Physics.OdePlugin { _parent_scene.AddChange((PhysicsActor)this, what, arg); } + + private struct strAvatarSize + { + public Vector3 size; + public float offset; + } + } } diff --git a/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs index dc247a9fa2..faa948809f 100644 --- a/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs @@ -84,7 +84,7 @@ namespace OpenSim.Region.Physics.OdePlugin private Vector3 _position; private Vector3 _velocity; - private Vector3 _torque; + private Vector3 m_torque; private Vector3 m_lastVelocity; private Vector3 m_lastposition; private Vector3 m_rotationalVelocity; @@ -597,7 +597,7 @@ namespace OpenSim.Region.Physics.OdePlugin if (!IsPhysical || Body == IntPtr.Zero) return Vector3.Zero; - return _torque; + return m_torque; } set @@ -2425,10 +2425,10 @@ namespace OpenSim.Region.Physics.OdePlugin { if (!childPrim) { - m_force = Vector3.Zero; +// m_force = Vector3.Zero; m_forceacc = Vector3.Zero; m_angularForceacc = Vector3.Zero; - _torque = Vector3.Zero; +// m_torque = Vector3.Zero; _velocity = Vector3.Zero; _acceleration = Vector3.Zero; m_rotationalVelocity = Vector3.Zero; @@ -2521,7 +2521,7 @@ namespace OpenSim.Region.Physics.OdePlugin prm.m_collisionCategories = m_collisionCategories; prm.m_collisionFlags = m_collisionFlags; - if (prm.prim_geom != null) + if (prm.prim_geom != IntPtr.Zero) { if (prm.m_NoColide) @@ -2542,7 +2542,7 @@ namespace OpenSim.Region.Physics.OdePlugin // ((OdePrim)_parent).ChildSelectedChange(true); - if (prim_geom != null) + if (prim_geom != IntPtr.Zero) { if (m_NoColide) { @@ -2968,7 +2968,7 @@ namespace OpenSim.Region.Physics.OdePlugin d.BodyEnable(Body); } - _torque = newtorque; + m_torque = newtorque; } } @@ -3364,7 +3364,7 @@ namespace OpenSim.Region.Physics.OdePlugin Vector3 trq; - trq = _torque; + trq = m_torque; trq += m_angularForceacc; m_angularForceacc = Vector3.Zero; if (trq.X != 0 || trq.Y != 0 || trq.Z != 0) diff --git a/OpenSim/Region/Physics/UbitOdePlugin/ODERayCastRequestManager.cs b/OpenSim/Region/Physics/UbitOdePlugin/ODERayCastRequestManager.cs index 799a324f4b..561ab1c0aa 100644 --- a/OpenSim/Region/Physics/UbitOdePlugin/ODERayCastRequestManager.cs +++ b/OpenSim/Region/Physics/UbitOdePlugin/ODERayCastRequestManager.cs @@ -324,7 +324,10 @@ namespace OpenSim.Region.Physics.OdePlugin { // Collide tests if ((CurrentRayFilter & FilterActiveSpace) != 0) + { d.SpaceCollide2(ray, m_scene.ActiveSpace, IntPtr.Zero, nearCallback); + d.SpaceCollide2(ray, m_scene.CharsSpace, IntPtr.Zero, nearCallback); + } if ((CurrentRayFilter & FilterStaticSpace) != 0 && (m_contactResults.Count < CurrentMaxCount)) d.SpaceCollide2(ray, m_scene.StaticSpace, IntPtr.Zero, nearCallback); if ((CurrentRayFilter & RayFilterFlags.land) != 0 && (m_contactResults.Count < CurrentMaxCount)) @@ -552,7 +555,6 @@ namespace OpenSim.Region.Physics.OdePlugin break; default: - return; break; } } diff --git a/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs b/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs index 003a91c942..15eb01fa21 100644 --- a/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs +++ b/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs @@ -147,6 +147,7 @@ namespace OpenSim.Region.Physics.OdePlugin PIDHoverActive, Size, + AvatarSize, Shape, PhysRepData, AddPhysRep, @@ -177,7 +178,9 @@ namespace OpenSim.Region.Physics.OdePlugin public changes what; public Object arg; } - + + + public class OdeScene : PhysicsScene { private readonly ILog m_log; @@ -224,9 +227,6 @@ namespace OpenSim.Region.Physics.OdePlugin // private IntPtr WaterHeightmapData = IntPtr.Zero; // private GCHandle WaterMapHandler = new GCHandle(); - public float avPIDD = 2200f; // make it visible - public float avPIDP = 900f; // make it visible - private float avCapRadius = 0.37f; private float avDensity = 3f; private float avMovementDivisorWalk = 1.3f; private float avMovementDivisorRun = 0.8f; @@ -299,9 +299,12 @@ namespace OpenSim.Region.Physics.OdePlugin public IntPtr TopSpace; // the global space public IntPtr ActiveSpace; // space for active prims + public IntPtr CharsSpace; // space for active prims public IntPtr StaticSpace; // space for the static things around public IntPtr GroundSpace; // space for ground + public IntPtr SharedRay; + // some speedup variables private int spaceGridMaxX; private int spaceGridMaxY; @@ -372,21 +375,25 @@ namespace OpenSim.Region.Physics.OdePlugin // now the major subspaces ActiveSpace = d.HashSpaceCreate(TopSpace); + CharsSpace = d.HashSpaceCreate(TopSpace); StaticSpace = d.HashSpaceCreate(TopSpace); GroundSpace = d.HashSpaceCreate(TopSpace); } catch { // i must RtC#FM + // i did! } d.HashSpaceSetLevels(TopSpace, -2, 8); d.HashSpaceSetLevels(ActiveSpace, -2, 8); + d.HashSpaceSetLevels(CharsSpace, -4, 3); d.HashSpaceSetLevels(StaticSpace, -2, 8); d.HashSpaceSetLevels(GroundSpace, 0, 8); // demote to second level d.SpaceSetSublevel(ActiveSpace, 1); + d.SpaceSetSublevel(CharsSpace, 1); d.SpaceSetSublevel(StaticSpace, 1); d.SpaceSetSublevel(GroundSpace, 1); @@ -396,11 +403,24 @@ namespace OpenSim.Region.Physics.OdePlugin CollisionCategories.Phantom | CollisionCategories.VolumeDtc )); - d.GeomSetCollideBits(ActiveSpace, 0); + d.GeomSetCollideBits(ActiveSpace, (uint)(CollisionCategories.Space | + CollisionCategories.Geom | + CollisionCategories.Character | + CollisionCategories.Phantom | + CollisionCategories.VolumeDtc + )); + d.GeomSetCategoryBits(CharsSpace, (uint)(CollisionCategories.Space | + CollisionCategories.Geom | + CollisionCategories.Character | + CollisionCategories.Phantom | + CollisionCategories.VolumeDtc + )); + d.GeomSetCollideBits(CharsSpace, 0); + d.GeomSetCategoryBits(StaticSpace, (uint)(CollisionCategories.Space | CollisionCategories.Geom | - CollisionCategories.Land | - CollisionCategories.Water | +// CollisionCategories.Land | +// CollisionCategories.Water | CollisionCategories.Phantom | CollisionCategories.VolumeDtc )); @@ -412,6 +432,8 @@ namespace OpenSim.Region.Physics.OdePlugin contactgroup = d.JointGroupCreate(0); //contactgroup + SharedRay = d.CreateRay(TopSpace, 1.0f); + d.WorldSetAutoDisableFlag(world, false); } } @@ -468,7 +490,6 @@ namespace OpenSim.Region.Physics.OdePlugin avDensity = physicsconfig.GetFloat("av_density", avDensity); avMovementDivisorWalk = physicsconfig.GetFloat("av_movement_divisor_walk", avMovementDivisorWalk); avMovementDivisorRun = physicsconfig.GetFloat("av_movement_divisor_run", avMovementDivisorRun); - avCapRadius = physicsconfig.GetFloat("av_capsule_radius", avCapRadius); contactsPerCollision = physicsconfig.GetInt("contacts_per_collision", contactsPerCollision); @@ -494,7 +515,7 @@ namespace OpenSim.Region.Physics.OdePlugin odetimestepMS = (int)(1000.0f * ODE_STEPSIZE +0.5f); ContactgeomsArray = Marshal.AllocHGlobal(contactsPerCollision * d.ContactGeom.unmanagedSizeOf); - GlobalContactsArray = GlobalContactsArray = Marshal.AllocHGlobal(maxContactsbeforedeath * d.Contact.unmanagedSizeOf); + GlobalContactsArray = Marshal.AllocHGlobal(maxContactsbeforedeath * d.Contact.unmanagedSizeOf); m_materialContactsData[(int)Material.Stone].mu = 0.8f; m_materialContactsData[(int)Material.Stone].bounce = 0.4f; @@ -718,35 +739,35 @@ namespace OpenSim.Region.Physics.OdePlugin if (b1 != IntPtr.Zero && b2 != IntPtr.Zero && d.AreConnectedExcluding(b1, b2, d.JointType.Contact)) return; -/* -// debug - PhysicsActor dp2; - if (d.GeomGetClass(g1) == d.GeomClassID.HeightfieldClass) - { - d.AABB aabb; - d.GeomGetAABB(g2, out aabb); - float x = aabb.MaxX - aabb.MinX; - float y = aabb.MaxY - aabb.MinY; - float z = aabb.MaxZ - aabb.MinZ; - if (x > 60.0f || y > 60.0f || z > 60.0f) - { - if (!actor_name_map.TryGetValue(g2, out dp2)) - m_log.WarnFormat("[PHYSICS]: failed actor mapping for geom 2"); - else - m_log.WarnFormat("[PHYSICS]: land versus large prim geo {0},size {1}, AABBsize <{2},{3},{4}>, at {5} ori {6},({7})", - dp2.Name, dp2.Size, x, y, z, - dp2.Position.ToString(), - dp2.Orientation.ToString(), - dp2.Orientation.Length()); - return; - } - } -// -*/ + /* + // debug + PhysicsActor dp2; + if (d.GeomGetClass(g1) == d.GeomClassID.HeightfieldClass) + { + d.AABB aabb; + d.GeomGetAABB(g2, out aabb); + float x = aabb.MaxX - aabb.MinX; + float y = aabb.MaxY - aabb.MinY; + float z = aabb.MaxZ - aabb.MinZ; + if (x > 60.0f || y > 60.0f || z > 60.0f) + { + if (!actor_name_map.TryGetValue(g2, out dp2)) + m_log.WarnFormat("[PHYSICS]: failed actor mapping for geom 2"); + else + m_log.WarnFormat("[PHYSICS]: land versus large prim geo {0},size {1}, AABBsize <{2},{3},{4}>, at {5} ori {6},({7})", + dp2.Name, dp2.Size, x, y, z, + dp2.Position.ToString(), + dp2.Orientation.ToString(), + dp2.Orientation.Length()); + return; + } + } + // + */ - if(d.GeomGetCategoryBits(g1) == (uint)CollisionCategories.VolumeDtc || - d.GeomGetCategoryBits(g1) == (uint)CollisionCategories.VolumeDtc) + if (d.GeomGetCategoryBits(g1) == (uint)CollisionCategories.VolumeDtc || + d.GeomGetCategoryBits(g2) == (uint)CollisionCategories.VolumeDtc) { int cflags; unchecked @@ -761,7 +782,7 @@ namespace OpenSim.Region.Physics.OdePlugin catch (SEHException) { m_log.Error("[PHYSICS]: The Operating system shut down ODE because of corrupt memory. This could be a result of really irregular terrain. If this repeats continuously, restart using Basic Physics and terrain fill your terrain. Restarting the sim."); -// ode.drelease(world); + // ode.drelease(world); base.TriggerPhysicsBasedRestart(); } catch (Exception e) @@ -801,26 +822,25 @@ namespace OpenSim.Region.Physics.OdePlugin // get first contact d.ContactGeom curContact = new d.ContactGeom(); + if (!GetCurContactGeom(0, ref curContact)) return; - // for now it's the one with max depth - ContactPoint maxDepthContact = new ContactPoint( - new Vector3(curContact.pos.X, curContact.pos.Y, curContact.pos.Z), - new Vector3(curContact.normal.X, curContact.normal.Y, curContact.normal.Z), - curContact.depth - ); + // do volume detection case - if ( - (p1.IsVolumeDtc || p2.IsVolumeDtc)) + if ((p1.IsVolumeDtc || p2.IsVolumeDtc)) { + ContactPoint maxDepthContact = new ContactPoint( + new Vector3(curContact.pos.X, curContact.pos.Y, curContact.pos.Z), + new Vector3(curContact.normal.X, curContact.normal.Y, curContact.normal.Z), + curContact.depth, false + ); + collision_accounting_events(p1, p2, maxDepthContact); return; } // big messy collision analises - Vector3 normoverride = Vector3.Zero; //damm c# - float mu = 0; float bounce = 0; float cfm = 0.0001f; @@ -831,36 +851,15 @@ namespace OpenSim.Region.Physics.OdePlugin ContactData contactdata1 = new ContactData(0, 0, false); ContactData contactdata2 = new ContactData(0, 0, false); - bool dop1foot = false; - bool dop2foot = false; + bool dop1ava = false; + bool dop2ava = false; bool ignore = false; - bool AvanormOverride = false; switch (p1.PhysicsActorType) { case (int)ActorTypes.Agent: { - dop1foot = true; - - AvanormOverride = true; - Vector3 tmp = p2.Position - p1.Position; - normoverride = p2.Velocity - p1.Velocity; - mu = normoverride.LengthSquared(); - - if (mu > 1e-6) - { - mu = 1.0f / (float)Math.Sqrt(mu); - normoverride *= mu; - mu = Vector3.Dot(tmp, normoverride); - if (mu > 0) - normoverride *= -1; - } - else - { - tmp.Normalize(); - normoverride = -tmp; - } - + dop1ava = true; switch (p2.PhysicsActorType) { case (int)ActorTypes.Agent: @@ -871,7 +870,6 @@ namespace OpenSim.Region.Physics.OdePlugin case (int)ActorTypes.Prim: if (p2.Velocity.LengthSquared() > 0.0f) p2.CollidingObj = true; - dop1foot = true; break; default: @@ -886,33 +884,8 @@ namespace OpenSim.Region.Physics.OdePlugin { case (int)ActorTypes.Agent: + dop2ava = true; - dop2foot = true; - - AvanormOverride = true; - - Vector3 tmp = p2.Position - p1.Position; - normoverride = p2.Velocity - p1.Velocity; - mu = normoverride.LengthSquared(); - if (mu > 1e-6) - { - mu = 1.0f / (float)Math.Sqrt(mu); - normoverride *= mu; - mu = Vector3.Dot(tmp, normoverride); - if (mu > 0) - normoverride *= -1; - } - else - { - tmp.Normalize(); - normoverride = -tmp; - } - - bounce = 0; - mu = 0; - cfm = 0.0001f; - - dop2foot = true; if (p1.Velocity.LengthSquared() > 0.0f) p1.CollidingObj = true; break; @@ -1017,166 +990,78 @@ namespace OpenSim.Region.Physics.OdePlugin default: break; } + if (ignore) return; + + d.ContactGeom maxContact = curContact; +// if (IgnoreNegSides && curContact.side1 < 0) +// maxContact.depth = float.MinValue; + + d.ContactGeom minContact = curContact; +// if (IgnoreNegSides && curContact.side1 < 0) +// minContact.depth = float.MaxValue; + IntPtr Joint; - - int i = 0; + bool FeetCollision = false; int ncontacts = 0; - while(true) + + + int i = 0; + + while (true) + { + if (m_global_contactcount >= maxContactsbeforedeath) + break; + +// if (!(IgnoreNegSides && curContact.side1 < 0)) + { + bool noskip = true; + if (dop1ava) + { + if (!(((OdeCharacter)p1).Collide(g1,false, ref curContact, ref FeetCollision))) + + noskip = false; + } + else if (dop2ava) + { + if (!(((OdeCharacter)p2).Collide(g2,true, ref curContact, ref FeetCollision))) + noskip = false; + } + + if (noskip) + { + m_global_contactcount++; + ncontacts++; + + Joint = CreateContacJoint(ref curContact, mu, bounce, cfm, erpscale, dscale); + d.JointAttach(Joint, b1, b2); + + if (curContact.depth > maxContact.depth) + maxContact = curContact; + + if (curContact.depth < minContact.depth) + minContact = curContact; + } + } + + if (++i >= count) + break; + + if (!GetCurContactGeom(i, ref curContact)) + break; + } + + if (ncontacts > 0) { - - if (IgnoreNegSides && curContact.side1 < 0) - { - if (++i >= count) - break; - - if (!GetCurContactGeom(i, ref curContact)) - break; - } - else - - { - if(dop1foot) - { - if (!(((OdeCharacter)p1).Collide(g1,false, ref curContact))) - { - if (++i >= count) - break; - else - continue; - } - } - else if(dop2foot) - { - if(!(((OdeCharacter) p2).Collide(g2,true,ref curContact))) - { - if (++i >= count) - break; - else - continue; - } - } - -/* - if (AvanormOverride) - { - if (curContact.depth > 0.3f) - { - if (dop1foot && (p1.Position.Z - curContact.pos.Z) > (p1.Size.Z - avCapRadius) * 0.5f) - p1.IsColliding = true; - if (dop2foot && (p2.Position.Z - curContact.pos.Z) > (p2.Size.Z - avCapRadius) * 0.5f) - p2.IsColliding = true; - curContact.normal.X = normoverride.X; - curContact.normal.Y = normoverride.Y; - curContact.normal.Z = normoverride.Z; - } - - else - { - if (dop1foot) - { - float sz = p1.Size.Z; - Vector3 vtmp = p1.Position; - float ppos = curContact.pos.Z - vtmp.Z + (sz - avCapRadius) * 0.5f; - if (ppos > 0f) - { - if (!p1.Flying) - { - d.AABB aabb; - d.GeomGetAABB(g2, out aabb); - float tmp = vtmp.Z - sz * .18f; - - if (aabb.MaxZ < tmp) - { - vtmp.X = curContact.pos.X - vtmp.X; - vtmp.Y = curContact.pos.Y - vtmp.Y; - vtmp.Z = -0.2f; - vtmp.Normalize(); - curContact.normal.X = vtmp.X; - curContact.normal.Y = vtmp.Y; - curContact.normal.Z = vtmp.Z; - } - } - } - else - p1.IsColliding = true; - - } - - if (dop2foot) - { - float sz = p2.Size.Z; - Vector3 vtmp = p2.Position; - vtmp.Z -= sz * 0.5f; - vtmp.Z += 0.5f; - float ppos = vtmp.Z - curContact.pos.Z; - if (ppos > 0f) - { - if (!p2.Flying) - { - float tmp = vtmp.Z - sz * .18f; - vtmp.X = curContact.pos.X - vtmp.X; - vtmp.Y = curContact.pos.Y - vtmp.Y; - vtmp.Z = curContact.pos.Z - vtmp.Z; - vtmp.Normalize(); - curContact.normal.X = vtmp.X; - curContact.normal.Y = vtmp.Y; - curContact.normal.Z = vtmp.Z; - } - } -// else - p2.IsColliding = true; - - } - } - } -*/ - ncontacts++; - Joint = CreateContacJoint(ref curContact, mu, bounce, cfm, erpscale, dscale); - d.JointAttach(Joint, b1, b2); - - if (++m_global_contactcount >= maxContactsbeforedeath) - break; - - if (++i >= count) - break; - - if (!GetCurContactGeom(i, ref curContact)) - break; - - if (curContact.depth > maxDepthContact.PenetrationDepth) - { - maxDepthContact.Position.X = curContact.pos.X; - maxDepthContact.Position.Y = curContact.pos.Y; - maxDepthContact.Position.Z = curContact.pos.Z; - maxDepthContact.SurfaceNormal.X = curContact.normal.X; - maxDepthContact.SurfaceNormal.Y = curContact.normal.Y; - maxDepthContact.SurfaceNormal.Z = curContact.normal.Z; - maxDepthContact.PenetrationDepth = curContact.depth; - } - } - } - - if(ncontacts > 0) + ContactPoint maxDepthContact = new ContactPoint( + new Vector3(maxContact.pos.X, maxContact.pos.Y, maxContact.pos.Z), + new Vector3(minContact.normal.X, minContact.normal.Y, minContact.normal.Z), + maxContact.depth, FeetCollision + ); collision_accounting_events(p1, p2, maxDepthContact); - -/* - 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. - this needs checking so out for now - if (b1 != IntPtr.Zero) - p1.ThrottleUpdates = true; - if (b2 != IntPtr.Zero) - p2.ThrottleUpdates = true; - } - */ } private void collision_accounting_events(PhysicsActor p1, PhysicsActor p2, ContactPoint contact) @@ -1267,10 +1152,10 @@ namespace OpenSim.Region.Physics.OdePlugin // chr.CollidingGround = false; not done here chr.CollidingObj = false; // do colisions with static space - d.SpaceCollide2(StaticSpace, chr.topbox, IntPtr.Zero, nearCallback); - d.SpaceCollide2(StaticSpace, chr.midbox, IntPtr.Zero, nearCallback); - d.SpaceCollide2(StaticSpace, chr.feetbox, IntPtr.Zero, nearCallback); - d.SpaceCollide2(StaticSpace, chr.bonebox, IntPtr.Zero, nearCallback); + d.SpaceCollide2(chr.collider, StaticSpace, IntPtr.Zero, nearCallback); + + // chars with chars + d.SpaceCollide(CharsSpace, IntPtr.Zero, nearCallback); // no coll with gnd } } @@ -1312,16 +1197,25 @@ namespace OpenSim.Region.Physics.OdePlugin m_log.Warn("[PHYSICS]: Unable to collide Active prim to static space"); } } - // finally colide active things amoung them + // colide active amoung them try { d.SpaceCollide(ActiveSpace, IntPtr.Zero, nearCallback); } catch (AccessViolationException) + { + m_log.Warn("[PHYSICS]: Unable to collide Active with Characters space"); + } + // and with chars + try + { + d.SpaceCollide2(CharsSpace,ActiveSpace, IntPtr.Zero, nearCallback); + } + catch (AccessViolationException) { m_log.Warn("[PHYSICS]: Unable to collide in Active space"); } -// _perloopContact.Clear(); + // _perloopContact.Clear(); } #endregion @@ -1357,13 +1251,13 @@ namespace OpenSim.Region.Physics.OdePlugin #region Add/Remove Entities - public override PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 size, bool isFlying) + public override PhysicsActor AddAvatar(uint localID, string avName, Vector3 position, Vector3 size, float feetOffset, bool isFlying) { Vector3 pos; pos.X = position.X; pos.Y = position.Y; pos.Z = position.Z; - OdeCharacter newAv = new OdeCharacter(avName, this, pos, size, avPIDD, avPIDP, avDensity, avMovementDivisorWalk, avMovementDivisorRun); + OdeCharacter newAv = new OdeCharacter(localID,avName, this, pos, size, feetOffset, avDensity, avMovementDivisorWalk, avMovementDivisorRun); newAv.Flying = isFlying; newAv.MinimumGroundFlightOffset = minimumGroundFlightOffset; @@ -1806,7 +1700,7 @@ namespace OpenSim.Region.Physics.OdePlugin foreach (OdeCharacter actor in _characters) { if (actor != null) - actor.Move(ODE_STEPSIZE, defects); + actor.Move(defects); } if (defects.Count != 0) { diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs index 94fd940dc1..6879ebbe97 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs @@ -317,8 +317,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api comms.DeleteListener(itemID); IXMLRPC xmlrpc = engine.World.RequestModuleInterface(); - xmlrpc.DeleteChannels(itemID); - xmlrpc.CancelSRDRequests(itemID); + if (xmlrpc != null) + { + xmlrpc.DeleteChannels(itemID); + xmlrpc.CancelSRDRequests(itemID); + } // Remove Sensors m_SensorRepeat[engine].UnSetSenseRepeaterEvents(localID, itemID); diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 6b63d9401d..7ff30ca844 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -3013,7 +3013,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } bool result = money.ObjectGiveMoney( - m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount, UUID.Zero); + m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount,UUID.Zero); if (result) return 1; @@ -6384,7 +6384,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } else { - agentSize = new LSL_Vector(0.45, 0.6, avatar.Appearance.AvatarHeight); +// agentSize = new LSL_Vector(0.45f, 0.6f, avatar.Appearance.AvatarHeight); + Vector3 s = avatar.Appearance.AvatarSize; + agentSize = new LSL_Vector(s.X, s.Y, s.Z); } return agentSize; } @@ -8591,8 +8593,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // and standing avatar since server 1.36 LSL_Vector lower; LSL_Vector upper; + + Vector3 box = presence.Appearance.AvatarBoxSize * 0.5f; + if (presence.Animator.Animations.ImplicitDefaultAnimation.AnimID == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"]) +/* { // This is for ground sitting avatars float height = presence.Appearance.AvatarHeight / 2.66666667f; @@ -8610,6 +8616,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // Adjust to the documented error offsets (see LSL Wiki) lower += new LSL_Vector(0.05f, 0.05f, 0.05f); upper -= new LSL_Vector(0.05f, 0.05f, 0.05f); +*/ + { + // This is for ground sitting avatars TODO! + lower = new LSL_Vector(-box.X - 0.1125, -box.Y, box.Z * -1.0f); + upper = new LSL_Vector(box.X + 0.1125, box.Y, box.Z * -1.0f); + } + else + { + // This is for standing/flying avatars + lower = new LSL_Vector(-box.X, -box.Y, -box.Z); + upper = new LSL_Vector(box.X, box.Y, box.Z); + } if (lower.x > upper.x) lower.x = upper.x; @@ -12529,7 +12547,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } bool result = money.ObjectGiveMoney( - m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount, txn); + m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount,UUID.Zero); if (result) { @@ -12931,7 +12949,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.PRIM_SIZE: // as in llGetAgentSize above - res.Add(new LSL_Vector(0.45f, 0.6f, avatar.Appearance.AvatarHeight)); +// res.Add(new LSL_Vector(0.45f, 0.6f, avatar.Appearance.AvatarHeight)); + Vector3 s = avatar.Appearance.AvatarSize; + res.Add(new LSL_Vector(s.X, s.Y, s.Z)); + break; case (int)ScriptBaseClass.PRIM_ROTATION: diff --git a/OpenSim/Services/Interfaces/IAvatarService.cs b/OpenSim/Services/Interfaces/IAvatarService.cs index 0caa5211c8..c0130f139b 100644 --- a/OpenSim/Services/Interfaces/IAvatarService.cs +++ b/OpenSim/Services/Interfaces/IAvatarService.cs @@ -201,7 +201,13 @@ namespace OpenSim.Services.Interfaces appearance.Serial = Int32.Parse(Data["Serial"]); if (Data.ContainsKey("AvatarHeight")) - appearance.AvatarHeight = float.Parse(Data["AvatarHeight"]); + { + float h = float.Parse(Data["AvatarHeight"]); + if( h == 0f) + h = 1.9f; + appearance.SetSize(new Vector3(0.45f, 0.6f, h )); +// appearance.AvatarHeight = float.Parse(Data["AvatarHeight"]); + } // Legacy Wearables if (Data.ContainsKey("BodyItem")) @@ -339,6 +345,7 @@ namespace OpenSim.Services.Interfaces appearance.Wearables[AvatarWearable.EYES].Wear( AvatarWearable.DefaultWearables[ AvatarWearable.EYES][0]); + } catch {