diff --git a/OpenSim/Capabilities/Handlers/UploadBakedTexture/UploadBakedTextureHandler.cs b/OpenSim/Capabilities/Handlers/UploadBakedTexture/UploadBakedTextureHandler.cs index 8849a59ce3..4fa604fc30 100644 --- a/OpenSim/Capabilities/Handlers/UploadBakedTexture/UploadBakedTextureHandler.cs +++ b/OpenSim/Capabilities/Handlers/UploadBakedTexture/UploadBakedTextureHandler.cs @@ -117,7 +117,7 @@ namespace OpenSim.Capabilities.Handlers /// private void BakedTextureUploaded(UUID assetID, byte[] data) { -// m_log.DebugFormat("[UPLOAD BAKED TEXTURE HANDLER]: Received baked texture {0}", assetID.ToString()); + m_log.DebugFormat("[UPLOAD BAKED TEXTURE HANDLER]: Received baked texture {0}", assetID.ToString()); AssetBase asset; asset = new AssetBase(assetID, "Baked Texture", (sbyte)AssetType.Texture, m_HostCapsObj.AgentID.ToString()); diff --git a/OpenSim/Framework/AvatarAppearance.cs b/OpenSim/Framework/AvatarAppearance.cs index 2183fb6c8a..4df4fb6717 100644 --- a/OpenSim/Framework/AvatarAppearance.cs +++ b/OpenSim/Framework/AvatarAppearance.cs @@ -66,7 +66,7 @@ namespace OpenSim.Framework protected Vector3 m_avatarBoxSize = new Vector3(0.45f, 0.6f, 1.9f); protected float m_avatarFeetOffset = 0; protected float m_avatarAnimOffset = 0; - + protected WearableCacheItem[] cacheitems; public virtual int Serial { get { return m_serial; } @@ -115,6 +115,12 @@ namespace OpenSim.Framework get { return m_avatarHeight; } set { m_avatarHeight = value; } } + + public virtual WearableCacheItem[] WearableCacheItems + { + get { return cacheitems; } + set { cacheitems = value; } + } public AvatarAppearance() { diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs index c9b67defdf..04650425bf 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, Vector3 AvSize); + public delegate void SetAppearance(IClientAPI remoteClient, Primitive.TextureEntry textureEntry, byte[] visualParams, Vector3 AvSize, WearableCacheItem[] CacheItems); public delegate void StartAnim(IClientAPI remoteClient, UUID animID); diff --git a/OpenSim/Framework/ILandObject.cs b/OpenSim/Framework/ILandObject.cs index 4f98d7bb30..7a24d1ec6a 100644 --- a/OpenSim/Framework/ILandObject.cs +++ b/OpenSim/Framework/ILandObject.cs @@ -70,6 +70,7 @@ namespace OpenSim.Framework void UpdateLandProperties(LandUpdateArgs args, IClientAPI remote_client); bool IsEitherBannedOrRestricted(UUID avatar); bool IsBannedFromLand(UUID avatar); + bool CanBeOnThisLand(UUID avatar, float posHeight); bool IsRestrictedFromLand(UUID avatar); bool IsInLandAccessList(UUID avatar); void SendLandUpdateToClient(IClientAPI remote_client); diff --git a/OpenSim/Framework/WearableCacheItem.cs b/OpenSim/Framework/WearableCacheItem.cs new file mode 100644 index 0000000000..83b1346230 --- /dev/null +++ b/OpenSim/Framework/WearableCacheItem.cs @@ -0,0 +1,39 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using OpenMetaverse; + +namespace OpenSim.Framework +{ + public class WearableCacheItem + { + public uint TextureIndex { get; set; } + public UUID CacheId { get; set; } + public UUID TextureID { get; set; } + } +} diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index ee664857c2..7364f45eb2 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -460,6 +460,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP } public bool SendLogoutPacketWhenClosing { set { m_SendLogoutPacketWhenClosing = value; } } + #endregion Properties @@ -585,6 +586,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP // Disable UDP handling for this client m_udpClient.Shutdown(); + //m_log.InfoFormat("[CLIENTVIEW] Memory pre GC {0}", System.GC.GetTotalMemory(false)); //GC.Collect(); //m_log.InfoFormat("[CLIENTVIEW] Memory post GC {0}", System.GC.GetTotalMemory(true)); @@ -2750,8 +2752,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP req.AssetInf.ID, req.AssetInf.Metadata.ContentType); return; } + int WearableOut = 0; + bool isWearable = false; - //m_log.Debug("sending asset " + req.RequestAssetID); + if (req.AssetInf != null) + isWearable = + ((AssetType) req.AssetInf.Type == + AssetType.Bodypart || (AssetType) req.AssetInf.Type == AssetType.Clothing); + + + //m_log.Debug("sending asset " + req.RequestAssetID + ", iswearable: " + isWearable); + + + //if (isWearable) + // m_log.Debug((AssetType)req.AssetInf.Type); + TransferInfoPacket Transfer = new TransferInfoPacket(); Transfer.TransferInfo.ChannelType = 2; Transfer.TransferInfo.Status = 0; @@ -2773,7 +2788,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP Transfer.TransferInfo.Size = req.AssetInf.Data.Length; Transfer.TransferInfo.TransferID = req.TransferRequestID; Transfer.Header.Zerocoded = true; - OutPacket(Transfer, ThrottleOutPacketType.Asset); + OutPacket(Transfer, isWearable ? ThrottleOutPacketType.State : ThrottleOutPacketType.Asset); if (req.NumPackets == 1) { @@ -2784,7 +2799,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP TransferPacket.TransferData.Data = req.AssetInf.Data; TransferPacket.TransferData.Status = 1; TransferPacket.Header.Zerocoded = true; - OutPacket(TransferPacket, ThrottleOutPacketType.Asset); + OutPacket(TransferPacket, isWearable ? ThrottleOutPacketType.State : ThrottleOutPacketType.Asset); } else { @@ -2817,7 +2832,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP TransferPacket.TransferData.Status = 1; } TransferPacket.Header.Zerocoded = true; - OutPacket(TransferPacket, ThrottleOutPacketType.Asset); + OutPacket(TransferPacket, isWearable ? ThrottleOutPacketType.State : ThrottleOutPacketType.Asset); processedLength += chunkSize; packetNumber++; @@ -3572,24 +3587,25 @@ namespace OpenSim.Region.ClientStack.LindenUDP aw.WearableData = new AgentWearablesUpdatePacket.WearableDataBlock[count]; AgentWearablesUpdatePacket.WearableDataBlock awb; int idx = 0; - for (int i = 0; i < wearables.Length; i++) - { - for (int j = 0; j < wearables[i].Count; j++) - { - awb = new AgentWearablesUpdatePacket.WearableDataBlock(); - awb.WearableType = (byte)i; - awb.AssetID = wearables[i][j].AssetID; - awb.ItemID = wearables[i][j].ItemID; - aw.WearableData[idx] = awb; - idx++; + + for (int i = 0; i < wearables.Length; i++) + { + for (int j = 0; j < wearables[i].Count; j++) + { + awb = new AgentWearablesUpdatePacket.WearableDataBlock(); + awb.WearableType = (byte) i; + awb.AssetID = wearables[i][j].AssetID; + awb.ItemID = wearables[i][j].ItemID; + aw.WearableData[idx] = awb; + idx++; -// m_log.DebugFormat( -// "[APPEARANCE]: Sending wearable item/asset {0} {1} (index {2}) for {3}", -// awb.ItemID, awb.AssetID, i, Name); - } - } + // m_log.DebugFormat( + // "[APPEARANCE]: Sending wearable item/asset {0} {1} (index {2}) for {3}", + // awb.ItemID, awb.AssetID, i, Name); + } + } - OutPacket(aw, ThrottleOutPacketType.Task); + OutPacket(aw, ThrottleOutPacketType.State); } public void SendAppearance(UUID agentID, byte[] visualParams, byte[] textureEntry) @@ -3614,7 +3630,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP avp.Sender.IsTrial = false; avp.Sender.ID = agentID; //m_log.DebugFormat("[CLIENT]: Sending appearance for {0} to {1}", agentID.ToString(), AgentId.ToString()); - OutPacket(avp, ThrottleOutPacketType.Task); + OutPacket(avp, ThrottleOutPacketType.State); } public void SendAnimations(UUID[] animations, int[] seqs, UUID sourceAgentId, UUID[] objectIDs) @@ -6282,12 +6298,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP byte[] visualparams = new byte[appear.VisualParam.Length]; for (int i = 0; i < appear.VisualParam.Length; i++) visualparams[i] = appear.VisualParam[i].ParamValue; - + //var b = appear.WearableData[0]; + Primitive.TextureEntry te = null; if (appear.ObjectData.TextureEntry.Length > 1) te = new Primitive.TextureEntry(appear.ObjectData.TextureEntry, 0, appear.ObjectData.TextureEntry.Length); + + WearableCacheItem[] cacheitems = new WearableCacheItem[appear.WearableData.Length]; + for (int i=0; i(); + // var item = fac.GetBakedTextureFaces(AgentId); + //WearableCacheItem[] items = fac.GetCachedItems(AgentId); + IImprovedAssetCache cache = m_scene.RequestModuleInterface(); if (cache == null) { @@ -11703,7 +11732,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP { cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock(); cachedresp.WearableData[i].TextureIndex = cachedtex.WearableData[i].TextureIndex; - cachedresp.WearableData[i].TextureID = UUID.Zero; + cachedresp.WearableData[i].TextureID = UUID.Zero; //UUID.Parse("8334fb6e-c2f5-46ee-807d-a435f61a8d46"); cachedresp.WearableData[i].HostName = new byte[0]; } } @@ -11713,10 +11742,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP { cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock(); cachedresp.WearableData[i].TextureIndex = cachedtex.WearableData[i].TextureIndex; - if(cache.Check(cachedtex.WearableData[i].ID.ToString())) + + + + if (cache.Check(cachedtex.WearableData[i].ID.ToString())) cachedresp.WearableData[i].TextureID = UUID.Zero; + //UUID.Parse("8334fb6e-c2f5-46ee-807d-a435f61a8d46"); else - cachedresp.WearableData[i].TextureID = UUID.Zero; + cachedresp.WearableData[i].TextureID = UUID.Zero; // UUID.Parse("8334fb6e-c2f5-46ee-807d-a435f61a8d46"); cachedresp.WearableData[i].HostName = new byte[0]; } } diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs index 3532b1dfe2..3080023c0f 100644 --- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs @@ -140,18 +140,18 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory /// /// /// - public void SetAppearance(IScenePresence sp, AvatarAppearance appearance) + public void SetAppearance(IScenePresence sp, AvatarAppearance appearance, WearableCacheItem[] cacheItems) { - SetAppearance(sp, appearance.Texture, appearance.VisualParams); + SetAppearance(sp, appearance.Texture, appearance.VisualParams, cacheItems); } - public void SetAppearance(IScenePresence sp, Primitive.TextureEntry textureEntry, byte[] visualParams, Vector3 avSize) + public void SetAppearance(IScenePresence sp, Primitive.TextureEntry textureEntry, byte[] visualParams, Vector3 avSize, WearableCacheItem[] cacheItems) { float oldoff = sp.Appearance.AvatarFeetOffset; Vector3 oldbox = sp.Appearance.AvatarBoxSize; - SetAppearance(sp, textureEntry, visualParams); + SetAppearance(sp, textureEntry, visualParams, cacheItems); sp.Appearance.SetSize(avSize); float off = sp.Appearance.AvatarFeetOffset; @@ -166,7 +166,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory /// /// /// - public void SetAppearance(IScenePresence sp, Primitive.TextureEntry textureEntry, byte[] visualParams) + public void SetAppearance(IScenePresence sp, Primitive.TextureEntry textureEntry, byte[] visualParams, WearableCacheItem[] cacheItems) { // m_log.DebugFormat( // "[AVFACTORY]: start SetAppearance for {0}, te {1}, visualParams {2}", @@ -205,11 +205,14 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory // ((ScenePresence)sp).SetSize(box,off); } - + //if (cacheItems.Length > 0) + //{ + sp.Appearance.WearableCacheItems = cacheItems; + //} // Process the baked texture array if (textureEntry != null) { -// m_log.DebugFormat("[AVFACTORY]: Received texture update for {0} {1}", sp.Name, sp.UUID); + m_log.DebugFormat("[AVFACTORY]: Received texture update for {0} {1}", sp.Name, sp.UUID); // WriteBakedTexturesReport(sp, m_log.DebugFormat); @@ -278,6 +281,19 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory return GetBakedTextureFaces(sp); } + public WearableCacheItem[] GetCachedItems(UUID agentId) + { + ScenePresence sp = m_scene.GetScenePresence(agentId); + Dictionary bakedTextures = GetBakedTextureFaces(sp); + + WearableCacheItem[] items = sp.Appearance.WearableCacheItems; + //foreach (WearableCacheItem item in items) + //{ + + //} + return items; + } + public bool SaveBakedTextures(UUID agentId) { ScenePresence sp = m_scene.GetScenePresence(agentId); @@ -660,12 +676,12 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory /// /// /// - private void Client_OnSetAppearance(IClientAPI client, Primitive.TextureEntry textureEntry, byte[] visualParams, Vector3 avSize) + private void Client_OnSetAppearance(IClientAPI client, Primitive.TextureEntry textureEntry, byte[] visualParams, Vector3 avSize, WearableCacheItem[] cacheItems) { // 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,avSize); + SetAppearance(sp, textureEntry, visualParams,avSize, cacheItems); else m_log.WarnFormat("[AVFACTORY]: Client_OnSetAppearance unable to find presence for {0}", client.AgentId); } diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs index 1830d41880..f090e1566a 100644 --- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs @@ -61,7 +61,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory for (byte i = 0; i < visualParams.Length; i++) visualParams[i] = i; - afm.SetAppearance(sp, new Primitive.TextureEntry(TestHelpers.ParseTail(0x10)), visualParams); + afm.SetAppearance(sp, new Primitive.TextureEntry(TestHelpers.ParseTail(0x10)), visualParams, new WearableCacheItem[0]); // TODO: Check baked texture Assert.AreEqual(visualParams, sp.Appearance.VisualParams); @@ -102,7 +102,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory Primitive.TextureEntryFace eyesFace = bakedTextureEntry.CreateFace(eyesFaceIndex); eyesFace.TextureID = eyesTextureId; - afm.SetAppearance(sp, bakedTextureEntry, visualParams); + afm.SetAppearance(sp, bakedTextureEntry, visualParams, new WearableCacheItem[0]); afm.SaveBakedTextures(userId); // Dictionary bakedTextures = afm.GetBakedTextureFaces(userId); diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs index 8ddff99cfb..07d00c091e 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs @@ -442,6 +442,19 @@ namespace OpenSim.Region.CoreModules.World.Land return false; } + public bool CanBeOnThisLand(UUID avatar, float posHeight) + { + if (posHeight < LandChannel.BAN_LINE_SAFETY_HIEGHT && IsBannedFromLand(avatar)) + { + return false; + } + else if (IsRestrictedFromLand(avatar)) + { + return false; + } + return true; + } + public bool HasGroupAccess(UUID avatar) { if (LandData.GroupID != UUID.Zero && (LandData.Flags & (uint)ParcelFlags.UseAccessGroup) == (uint)ParcelFlags.UseAccessGroup) diff --git a/OpenSim/Region/Framework/Interfaces/IAvatarFactoryModule.cs b/OpenSim/Region/Framework/Interfaces/IAvatarFactoryModule.cs index 34aca33349..d25c930d8b 100644 --- a/OpenSim/Region/Framework/Interfaces/IAvatarFactoryModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IAvatarFactoryModule.cs @@ -35,8 +35,8 @@ namespace OpenSim.Region.Framework.Interfaces public interface IAvatarFactoryModule { - void SetAppearance(IScenePresence sp, AvatarAppearance appearance); - void SetAppearance(IScenePresence sp, Primitive.TextureEntry textureEntry, byte[] visualParams); + void SetAppearance(IScenePresence sp, AvatarAppearance appearance, WearableCacheItem[] cacheItems); + void SetAppearance(IScenePresence sp, Primitive.TextureEntry textureEntry, byte[] visualParams, WearableCacheItem[] cacheItems); /// /// Send the appearance of an avatar to others in the scene. @@ -52,6 +52,8 @@ namespace OpenSim.Region.Framework.Interfaces /// An empty list if this agent has no baked textures (e.g. because it's a child agent) Dictionary GetBakedTextureFaces(UUID agentId); + + WearableCacheItem[] GetCachedItems(UUID agentId); /// /// Save the baked textures for the given agent permanently in the asset database. /// diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index fa1a5afb81..b9cd3fc561 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -923,6 +923,33 @@ namespace OpenSim.Region.Framework.Scenes m_scene.EventManager.TriggerSetRootAgentScene(m_uuid, m_scene); + UUID groupUUID = UUID.Zero; + string GroupName = string.Empty; + ulong groupPowers = 0; + + // ---------------------------------- + // Previous Agent Difference - AGNI sends an unsolicited AgentDataUpdate upon root agent status + try + { + if (gm != null) + { + groupUUID = ControllingClient.ActiveGroupId; + GroupRecord record = gm.GetGroupRecord(groupUUID); + if (record != null) + GroupName = record.GroupName; + GroupMembershipData groupMembershipData = gm.GetMembershipData(groupUUID, m_uuid); + if (groupMembershipData != null) + groupPowers = groupMembershipData.GroupPowers; + } + ControllingClient.SendAgentDataUpdate(m_uuid, groupUUID, Firstname, Lastname, groupPowers, GroupName, + Grouptitle); + } + catch (Exception e) + { + m_log.Debug("[AGENTUPDATE]: " + e.ToString()); + } + // ------------------------------------ + if (ParentID == 0) { // Moved this from SendInitialData to ensure that Appearance is initialized @@ -1961,7 +1988,8 @@ namespace OpenSim.Region.Framework.Scenes // m_log.DebugFormat("[SCENE PRESENCE]: Resetting move to target for {0}", Name); MovingToTarget = false; - MoveToPositionTarget = Vector3.Zero; +// MoveToPositionTarget = Vector3.Zero; + m_forceToApply = null; // cancel possible last action // We need to reset the control flag as the ScenePresenceAnimator uses this to determine the correct // resting animation (e.g. hover or stand). NPCs don't have a client that will quickly reset this flag. @@ -2080,9 +2108,6 @@ namespace OpenSim.Region.Framework.Scenes if (part == null) return; - // TODO: determine position to sit at based on scene geometry; don't trust offset from client - // see http://wiki.secondlife.com/wiki/User:Andrew_Linden/Office_Hours/2007_11_06 for details on how LL does it - if (PhysicsActor != null) m_sitAvatarHeight = PhysicsActor.Size.Z * 0.5f; @@ -2101,25 +2126,8 @@ namespace OpenSim.Region.Framework.Scenes } else { -// if (Util.GetDistanceTo(AbsolutePosition, pos) <= 10) -// { -// m_log.DebugFormat( -// "[SCENE PRESENCE]: Sitting {0} on {1} {2} because sit target is unset and within 10m", -// Name, part.Name, part.LocalId); - - if (m_scene.PhysicsScene != null && - part.PhysActor != null && - Util.GetDistanceTo(AbsolutePosition, pos) <= 30) - { - - Vector3 camdif = CameraPosition - part.AbsolutePosition; - camdif.Normalize(); - -// m_log.InfoFormat("sit {0} {1}", offset.ToString(), camdif.ToString()); - - if (m_scene.PhysicsScene.SitAvatar(part.PhysActor, AbsolutePosition, CameraPosition, offset, new Vector3(0.35f, 0, 0.65f), PhysicsSitResponse) != 0) - return; - } + if (PhysicsSit(part,offset)) // physics engine + return; if (Util.GetDistanceTo(AbsolutePosition, pos) <= 10) { @@ -2127,22 +2135,22 @@ namespace OpenSim.Region.Framework.Scenes AbsolutePosition = pos + new Vector3(0.0f, 0.0f, m_sitAvatarHeight); canSit = true; } -// else -// { -// m_log.DebugFormat( -// "[SCENE PRESENCE]: Ignoring sit request of {0} on {1} {2} because sit target is unset and outside 10m", -// Name, part.Name, part.LocalId); -// } } if (canSit) { + if (PhysicsActor != null) { // We can remove the physicsActor until they stand up. RemoveFromPhysicalScene(); } + if (MovingToTarget) + ResetMoveToTarget(); + + Velocity = Vector3.Zero; + part.AddSittingAvatar(UUID); cameraAtOffset = part.GetCameraAtOffset(); @@ -2179,14 +2187,6 @@ namespace OpenSim.Region.Framework.Scenes m_requestedSitTargetID = part.LocalId; m_requestedSitTargetUUID = targetID; -// m_log.DebugFormat("[SIT]: Client requested Sit Position: {0}", offset); - - if (m_scene.PhysicsScene.SupportsRayCast()) - { - //m_scene.PhysicsScene.RaycastWorld(Vector3.Zero,Vector3.Zero, 0.01f,new RaycastCallback()); - //SitRayCastAvatarPosition(part); - //return; - } } else { @@ -2196,28 +2196,87 @@ namespace OpenSim.Region.Framework.Scenes SendSitResponse(targetID, offset, Quaternion.Identity); } - public void PhysicsSitResponse(int status, uint partID, Vector3 offset, Quaternion Orientation) + // returns false if does not suport so older sit can be tried + public bool PhysicsSit(SceneObjectPart part, Vector3 offset) { - - if (status < 0) - { - ControllingClient.SendAlertMessage("Sit position no longer exists"); - return; - } - - if (status == 0) - return; - - SceneObjectPart part = m_scene.GetSceneObjectPart(partID); if (part == null || part.ParentGroup.IsAttachment) { + return true; + } + + if ( m_scene.PhysicsScene == null) + return false; + + if (part.PhysActor == null) + { + // none physcis shape + if (part.PhysicsShapeType == (byte)PhysicsShapeType.None) + ControllingClient.SendAlertMessage(" There is no suitable surface to sit on, try another spot."); + else + { // non physical phantom TODO + ControllingClient.SendAlertMessage(" There is no suitable surface to sit on, try another spot."); + return false; + } + return true; + } + + + // not doing autopilot + m_requestedSitTargetID = 0; + + if (m_scene.PhysicsScene.SitAvatar(part.PhysActor, AbsolutePosition, CameraPosition, offset, new Vector3(0.35f, 0, 0.65f), PhysicsSitResponse) != 0) + return true; + + return false; + } + + + private bool CanEnterLandPosition(Vector3 testPos) + { + ILandObject land = m_scene.LandChannel.GetLandObject(testPos.X, testPos.Y); + + if (land == null || land.LandData.Name == "NO_LAND") + return true; + + return land.CanBeOnThisLand(UUID,testPos.Z); + } + + // status + // < 0 ignore + // 0 bad sit spot + public void PhysicsSitResponse(int status, uint partID, Vector3 offset, Quaternion Orientation) + { + if (status < 0) + return; + + if (status == 0) + { + ControllingClient.SendAlertMessage(" There is no suitable surface to sit on, try another spot."); return; } + SceneObjectPart part = m_scene.GetSceneObjectPart(partID); + if (part == null) + return; + + Vector3 targetPos = part.GetWorldPosition() + offset * part.GetWorldRotation(); + if(!CanEnterLandPosition(targetPos)) + { + ControllingClient.SendAlertMessage(" Sit position on restricted land, try another spot"); + return; + } // m_log.InfoFormat("physsit {0} {1}", offset.ToString(),Orientation.ToString()); + RemoveFromPhysicalScene(); + + if (MovingToTarget) + ResetMoveToTarget(); + + Velocity = Vector3.Zero; + part.AddSittingAvatar(UUID); + Vector3 cameraAtOffset = part.GetCameraAtOffset(); Vector3 cameraEyeOffset = part.GetCameraEyeOffset(); bool forceMouselook = part.GetForceMouselook(); @@ -2225,23 +2284,23 @@ namespace OpenSim.Region.Framework.Scenes ControllingClient.SendSitResponse( part.UUID, offset, Orientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook); - part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK); - - // assuming no autopilot in use - Velocity = Vector3.Zero; - RemoveFromPhysicalScene(); + // not using autopilot Rotation = Orientation; m_pos = offset; - m_requestedSitTargetID = 0; // invalidate the viewer sit comand for now + m_requestedSitTargetID = 0; part.ParentGroup.AddAvatar(UUID); ParentPart = part; ParentID = part.LocalId; - - Animator.TrySetMovementAnimation("SIT"); + if(status == 3) + Animator.TrySetMovementAnimation("SIT_GROUND"); + else + Animator.TrySetMovementAnimation("SIT"); SendAvatarDataToAllAgents(); + + part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK); } @@ -2260,6 +2319,7 @@ namespace OpenSim.Region.Framework.Scenes return; } + if (part.SitTargetAvatar == UUID) { Vector3 sitTargetPos = part.SitTargetPosition; diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs index 1b4ed1e76e..5ac4e27d71 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(),appearance.AvatarSize); + OnSetAppearance(this, appearance.Texture, (byte[])appearance.VisualParams.Clone(),appearance.AvatarSize, new WearableCacheItem[0]); } public void SendRegionHandshake(RegionInfo regionInfo, RegionHandshakeArgs args) diff --git a/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs b/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs index a522277e8a..365fd7830b 100644 --- a/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs +++ b/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs @@ -108,7 +108,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests // ScenePresence.SendInitialData() to reset our entire appearance. m_scene.AssetService.Store(AssetHelpers.CreateNotecardAsset(originalFace8TextureId)); - m_afMod.SetAppearance(sp, originalTe, null); + m_afMod.SetAppearance(sp, originalTe, null, new WearableCacheItem[0] ); UUID npcId = m_npcMod.CreateNPC("John", "Smith", new Vector3(128, 128, 30), UUID.Zero, true, m_scene, sp.Appearance); diff --git a/OpenSim/Region/Physics/Manager/PhysicsScene.cs b/OpenSim/Region/Physics/Manager/PhysicsScene.cs index a442cf0970..d24ab2ac73 100644 --- a/OpenSim/Region/Physics/Manager/PhysicsScene.cs +++ b/OpenSim/Region/Physics/Manager/PhysicsScene.cs @@ -38,6 +38,9 @@ namespace OpenSim.Region.Physics.Manager public delegate void RaycastCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance, Vector3 normal); public delegate void RayCallback(List list); + public delegate void ProbeBoxCallback(List list); + public delegate void ProbeSphereCallback(List list); + public delegate void ProbePlaneCallback(List list); public delegate void SitAvatarCallback(int status, uint partID, Vector3 offset, Quaternion Orientation); public delegate void JointMoved(PhysicsJoint joint); @@ -56,6 +59,7 @@ namespace OpenSim.Region.Physics.Manager volumedtc = 0x40, // ray cast colision control (may only work for meshs) + ContactsUnImportant = 0x2000, BackFaceCull = 0x4000, ClosestHit = 0x8000, @@ -351,9 +355,22 @@ namespace OpenSim.Region.Physics.Manager return false; } - public virtual void RaycastActor(PhysicsActor actor, Vector3 position, Vector3 direction, float length, RaycastCallback retMethod){} - public virtual void RaycastActor(PhysicsActor actor, Vector3 position, Vector3 direction, float length, int Count, RayCallback retMethod) { } - public virtual List RaycastActor(PhysicsActor actor, Vector3 position, Vector3 direction, float length, int Count) + public virtual List RaycastActor(PhysicsActor actor, Vector3 position, Vector3 direction, float length, int Count, RayFilterFlags flags) + { + return new List(); + } + + public virtual List BoxProbe(Vector3 position, Vector3 size, Quaternion orientation, int Count, RayFilterFlags flags) + { + return new List(); + } + + public virtual List SphereProbe(Vector3 position, float radius, int Count, RayFilterFlags flags) + { + return new List(); + } + + public virtual List PlaneProbe(PhysicsActor actor, Vector4 plane, int Count, RayFilterFlags flags) { return new List(); } diff --git a/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs b/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs index bb04ea73be..f7e4c1cca1 100644 --- a/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs +++ b/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs @@ -715,7 +715,17 @@ namespace OpenSim.Region.Physics.OdePlugin Vector3 off = _velocity; float t = 0.5f * timeStep; off = off * t; + d.Quaternion qtmp; + d.GeomCopyQuaternion(bbox, out qtmp); + Quaternion q; + q.X = qtmp.X; + q.Y = qtmp.Y; + q.Z = qtmp.Z; + q.W = qtmp.W; + off *= Quaternion.Conjugate(q); + 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); @@ -741,6 +751,9 @@ namespace OpenSim.Region.Physics.OdePlugin d.GeomSetCategoryBits(feetbox, (uint)m_collisionCategories); d.GeomSetCollideBits(feetbox, (uint)m_collisionFlags); } + uint cat1 = d.GeomGetCategoryBits(bbox); + uint col1 = d.GeomGetCollideBits(bbox); + } } @@ -1527,8 +1540,11 @@ namespace OpenSim.Region.Physics.OdePlugin { if (CollisionEventsThisFrame != null) { - CollisionEventsThisFrame.Clear(); - CollisionEventsThisFrame = null; + lock (CollisionEventsThisFrame) + { + CollisionEventsThisFrame.Clear(); + CollisionEventsThisFrame = null; + } } m_eventsubscription = 0; } @@ -1537,8 +1553,11 @@ namespace OpenSim.Region.Physics.OdePlugin { if (CollisionEventsThisFrame == null) CollisionEventsThisFrame = new CollisionEventUpdate(); - CollisionEventsThisFrame.AddCollider(CollidedWith, contact); - _parent_scene.AddCollisionEventReporting(this); + lock (CollisionEventsThisFrame) + { + CollisionEventsThisFrame.AddCollider(CollidedWith, contact); + _parent_scene.AddCollisionEventReporting(this); + } } public void SendCollisions() @@ -1546,26 +1565,29 @@ namespace OpenSim.Region.Physics.OdePlugin if (CollisionEventsThisFrame == null) return; - if (m_cureventsubscription < m_eventsubscription) - return; - - m_cureventsubscription = 0; - - int ncolisions = CollisionEventsThisFrame.m_objCollisionList.Count; - - if (!SentEmptyCollisionsEvent || ncolisions > 0) + lock (CollisionEventsThisFrame) { - base.SendCollisionUpdate(CollisionEventsThisFrame); + if (m_cureventsubscription < m_eventsubscription) + return; - if (ncolisions == 0) + m_cureventsubscription = 0; + + int ncolisions = CollisionEventsThisFrame.m_objCollisionList.Count; + + if (!SentEmptyCollisionsEvent || ncolisions > 0) { - SentEmptyCollisionsEvent = true; - _parent_scene.RemoveCollisionEventReporting(this); - } - else - { - SentEmptyCollisionsEvent = false; - CollisionEventsThisFrame.Clear(); + base.SendCollisionUpdate(CollisionEventsThisFrame); + + if (ncolisions == 0) + { + SentEmptyCollisionsEvent = true; + _parent_scene.RemoveCollisionEventReporting(this); + } + else + { + SentEmptyCollisionsEvent = false; + CollisionEventsThisFrame.Clear(); + } } } } diff --git a/OpenSim/Region/Physics/UbitOdePlugin/ODERayCastRequestManager.cs b/OpenSim/Region/Physics/UbitOdePlugin/ODERayCastRequestManager.cs index 561ab1c0aa..6e9281b1be 100644 --- a/OpenSim/Region/Physics/UbitOdePlugin/ODERayCastRequestManager.cs +++ b/OpenSim/Region/Physics/UbitOdePlugin/ODERayCastRequestManager.cs @@ -56,8 +56,11 @@ namespace OpenSim.Region.Physics.OdePlugin private OdeScene m_scene; IntPtr ray; // the ray. we only need one for our lifetime + IntPtr Sphere; + IntPtr Box; + IntPtr Plane; - private const int ColisionContactGeomsPerTest = 5; + private int CollisionContactGeomsPerTest = 25; private const int DefaultMaxCount = 25; private const int MaxTimePerCallMS = 30; @@ -65,6 +68,7 @@ namespace OpenSim.Region.Physics.OdePlugin /// ODE near callback delegate /// private d.NearCallback nearCallback; + private d.NearCallback nearProbeCallback; private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private List m_contactResults = new List(); private RayFilterFlags CurrentRayFilter; @@ -74,155 +78,21 @@ namespace OpenSim.Region.Physics.OdePlugin { m_scene = pScene; nearCallback = near; + nearProbeCallback = nearProbe; ray = d.CreateRay(IntPtr.Zero, 1.0f); - d.GeomSetCategoryBits(ray,0); + d.GeomSetCategoryBits(ray, 0); + Box = d.CreateBox(IntPtr.Zero, 1.0f, 1.0f, 1.0f); + d.GeomSetCategoryBits(Box, 0); + Sphere = d.CreateSphere(IntPtr.Zero,1.0f); + d.GeomSetCategoryBits(Sphere, 0); + Plane = d.CreatePlane(IntPtr.Zero, 0f,0f,1f,1f); + d.GeomSetCategoryBits(Sphere, 0); } - /// - /// Queues request for a raycast to all world - /// - /// Origin of Ray - /// Ray direction - /// Ray length - /// Return method to send the results - public void QueueRequest(Vector3 position, Vector3 direction, float length, RayCallback retMethod) + public void QueueRequest(ODERayRequest req) { - ODERayRequest req = new ODERayRequest(); - req.geom = IntPtr.Zero; - req.callbackMethod = retMethod; - req.Count = DefaultMaxCount; - req.length = length; - req.Normal = direction; - req.Origin = position; - req.filter = RayFilterFlags.AllPrims; - - m_PendingRequests.Enqueue(req); - } - - /// - /// Queues request for a raycast to particular part - /// - /// Origin of Ray - /// Ray direction - /// Ray length - /// Return method to send the results - public void QueueRequest(IntPtr geom, Vector3 position, Vector3 direction, float length, RayCallback retMethod) - { - ODERayRequest req = new ODERayRequest(); - req.geom = geom; - req.callbackMethod = retMethod; - req.length = length; - req.Normal = direction; - req.Origin = position; - req.Count = DefaultMaxCount; - req.filter = RayFilterFlags.AllPrims; - - m_PendingRequests.Enqueue(req); - } - - public void QueueRequest(Vector3 position, Vector3 direction, float length, RaycastCallback retMethod) - { - ODERayRequest req = new ODERayRequest(); - req.geom = IntPtr.Zero; - req.callbackMethod = retMethod; - req.Count = DefaultMaxCount; - req.length = length; - req.Normal = direction; - req.Origin = position; - req.filter = RayFilterFlags.AllPrims | RayFilterFlags.land; - - m_PendingRequests.Enqueue(req); - } - - public void QueueRequest(IntPtr geom, Vector3 position, Vector3 direction, float length, RaycastCallback retMethod) - { - ODERayRequest req = new ODERayRequest(); - req.geom = geom; - req.callbackMethod = retMethod; - req.length = length; - req.Normal = direction; - req.Origin = position; - req.Count = DefaultMaxCount; - req.filter = RayFilterFlags.AllPrims; - - m_PendingRequests.Enqueue(req); - } - - /// - /// Queues a raycast - /// - /// Origin of Ray - /// Ray normal - /// Ray length - /// - /// Return method to send the results - public void QueueRequest(Vector3 position, Vector3 direction, float length, int count, RayCallback retMethod) - { - ODERayRequest req = new ODERayRequest(); - req.geom = IntPtr.Zero; - req.callbackMethod = retMethod; - req.length = length; - req.Normal = direction; - req.Origin = position; - req.Count = count; - req.filter = RayFilterFlags.AllPrims; - - m_PendingRequests.Enqueue(req); - } - - - public void QueueRequest(Vector3 position, Vector3 direction, float length, int count,RayFilterFlags filter , RayCallback retMethod) - { - ODERayRequest req = new ODERayRequest(); - req.geom = IntPtr.Zero; - req.callbackMethod = retMethod; - req.length = length; - req.Normal = direction; - req.Origin = position; - req.Count = count; - req.filter = filter; - - m_PendingRequests.Enqueue(req); - } - - public void QueueRequest(IntPtr geom, Vector3 position, Vector3 direction, float length, int count, RayCallback retMethod) - { - ODERayRequest req = new ODERayRequest(); - req.geom = geom; - req.callbackMethod = retMethod; - req.length = length; - req.Normal = direction; - req.Origin = position; - req.Count = count; - req.filter = RayFilterFlags.AllPrims; - - m_PendingRequests.Enqueue(req); - } - - public void QueueRequest(Vector3 position, Vector3 direction, float length, int count, RaycastCallback retMethod) - { - ODERayRequest req = new ODERayRequest(); - req.geom = IntPtr.Zero; - req.callbackMethod = retMethod; - req.length = length; - req.Normal = direction; - req.Origin = position; - req.Count = count; - req.filter = RayFilterFlags.AllPrims; - - m_PendingRequests.Enqueue(req); - } - - public void QueueRequest(IntPtr geom, Vector3 position, Vector3 direction, float length, int count, RaycastCallback retMethod) - { - ODERayRequest req = new ODERayRequest(); - req.geom = geom; - req.callbackMethod = retMethod; - req.length = length; - req.Normal = direction; - req.Origin = position; - req.Count = count; - req.filter = RayFilterFlags.AllPrims; + if (req.Count == 0) + req.Count = DefaultMaxCount; m_PendingRequests.Enqueue(req); } @@ -258,21 +128,64 @@ namespace OpenSim.Region.Physics.OdePlugin CurrentRayFilter = req.filter; CurrentMaxCount = req.Count; + CollisionContactGeomsPerTest = req.Count & 0xffff; + closestHit = ((CurrentRayFilter & RayFilterFlags.ClosestHit) == 0 ? 0 : 1); backfacecull = ((CurrentRayFilter & RayFilterFlags.BackFaceCull) == 0 ? 0 : 1); - d.GeomRaySetLength(ray, req.length); - d.GeomRaySet(ray, req.Origin.X, req.Origin.Y, req.Origin.Z, req.Normal.X, req.Normal.Y, req.Normal.Z); - d.GeomRaySetParams(ray, 0, backfacecull); - d.GeomRaySetClosestHit(ray, closestHit); + if (req.callbackMethod is ProbeBoxCallback) + { + if (CollisionContactGeomsPerTest > 80) + CollisionContactGeomsPerTest = 80; + d.GeomBoxSetLengths(Box, req.Normal.X, req.Normal.Y, req.Normal.Z); + d.GeomSetPosition(Box, req.Origin.X, req.Origin.Y, req.Origin.Z); + d.Quaternion qtmp; + qtmp.X = req.orientation.X; + qtmp.Y = req.orientation.Y; + qtmp.Z = req.orientation.Z; + qtmp.W = req.orientation.W; + d.GeomSetQuaternion(Box, ref qtmp); + } + else if (req.callbackMethod is ProbeSphereCallback) + { + if (CollisionContactGeomsPerTest > 80) + CollisionContactGeomsPerTest = 80; - if (req.callbackMethod is RaycastCallback) - // if we only want one get only one per colision pair saving memory - CurrentRayFilter |= RayFilterFlags.ClosestHit; + d.GeomSphereSetRadius(Sphere, req.length); + d.GeomSetPosition(Sphere, req.Origin.X, req.Origin.Y, req.Origin.Z); + } + else if (req.callbackMethod is ProbePlaneCallback) + { + if (CollisionContactGeomsPerTest > 80) + CollisionContactGeomsPerTest = 80; + + d.GeomPlaneSetParams(Plane, req.Normal.X, req.Normal.Y, req.Normal.Z, req.length); + } + + else + { + if (CollisionContactGeomsPerTest > 25) + CollisionContactGeomsPerTest = 25; + + d.GeomRaySetLength(ray, req.length); + d.GeomRaySet(ray, req.Origin.X, req.Origin.Y, req.Origin.Z, req.Normal.X, req.Normal.Y, req.Normal.Z); + d.GeomRaySetParams(ray, 0, backfacecull); + d.GeomRaySetClosestHit(ray, closestHit); + + if (req.callbackMethod is RaycastCallback) + // if we only want one get only one per Collision pair saving memory + CurrentRayFilter |= RayFilterFlags.ClosestHit; + } + + if ((CurrentRayFilter & RayFilterFlags.ContactsUnImportant) != 0) + unchecked + { + CollisionContactGeomsPerTest |= (int)d.CONTACTS_UNIMPORTANT; + } if (req.geom == IntPtr.Zero) { - // translate ray filter to colision flags + // translate ray filter to Collision flags catflags = 0; if ((CurrentRayFilter & RayFilterFlags.volumedtc) != 0) catflags |= CollisionCategories.VolumeDtc; @@ -289,15 +202,48 @@ namespace OpenSim.Region.Physics.OdePlugin if (catflags != 0) { - d.GeomSetCollideBits(ray, (uint)catflags); - doSpaceRay(req); + if (req.callbackMethod is ProbeBoxCallback) + { + catflags |= CollisionCategories.Space; + d.GeomSetCollideBits(Box, (uint)catflags); + d.GeomSetCategoryBits(Box, (uint)catflags); + doProbe(req, Box); + } + else if (req.callbackMethod is ProbeSphereCallback) + { + catflags |= CollisionCategories.Space; + d.GeomSetCollideBits(Sphere, (uint)catflags); + d.GeomSetCategoryBits(Sphere, (uint)catflags); + doProbe(req, Sphere); + } + else if (req.callbackMethod is ProbePlaneCallback) + { + catflags |= CollisionCategories.Space; + d.GeomSetCollideBits(Plane, (uint)catflags); + d.GeomSetCategoryBits(Plane, (uint)catflags); + doPlane(req); + } + else + { + d.GeomSetCollideBits(ray, (uint)catflags); + doSpaceRay(req); + } } } else { // if we select a geom don't use filters - d.GeomSetCollideBits(ray, (uint)CollisionCategories.All); - doGeomRay(req); + + if (req.callbackMethod is ProbePlaneCallback) + { + d.GeomSetCollideBits(Plane, (uint)CollisionCategories.All); + doPlane(req); + } + else + { + d.GeomSetCollideBits(ray, (uint)CollisionCategories.All); + doGeomRay(req); + } } } @@ -382,6 +328,61 @@ namespace OpenSim.Region.Physics.OdePlugin } } + private void doProbe(ODERayRequest req, IntPtr probe) + { + // Collide tests + if ((CurrentRayFilter & FilterActiveSpace) != 0) + { + d.SpaceCollide2(probe, m_scene.ActiveSpace, IntPtr.Zero, nearCallback); + d.SpaceCollide2(probe, m_scene.CharsSpace, IntPtr.Zero, nearCallback); + } + if ((CurrentRayFilter & FilterStaticSpace) != 0 && (m_contactResults.Count < CurrentMaxCount)) + d.SpaceCollide2(probe, m_scene.StaticSpace, IntPtr.Zero, nearCallback); + if ((CurrentRayFilter & RayFilterFlags.land) != 0 && (m_contactResults.Count < CurrentMaxCount)) + d.SpaceCollide2(probe, m_scene.GroundSpace, IntPtr.Zero, nearCallback); + + List cresult = new List(m_contactResults.Count); + lock (m_PendingRequests) + { + cresult.AddRange(m_contactResults); + m_contactResults.Clear(); + } + if (req.callbackMethod is ProbeBoxCallback) + ((ProbeBoxCallback)req.callbackMethod)(cresult); + else if (req.callbackMethod is ProbeSphereCallback) + ((ProbeSphereCallback)req.callbackMethod)(cresult); + } + + private void doPlane(ODERayRequest req) + { + // Collide tests + if (req.geom == IntPtr.Zero) + { + if ((CurrentRayFilter & FilterActiveSpace) != 0) + { + d.SpaceCollide2(Plane, m_scene.ActiveSpace, IntPtr.Zero, nearCallback); + d.SpaceCollide2(Plane, m_scene.CharsSpace, IntPtr.Zero, nearCallback); + } + if ((CurrentRayFilter & FilterStaticSpace) != 0 && (m_contactResults.Count < CurrentMaxCount)) + d.SpaceCollide2(Plane, m_scene.StaticSpace, IntPtr.Zero, nearCallback); + if ((CurrentRayFilter & RayFilterFlags.land) != 0 && (m_contactResults.Count < CurrentMaxCount)) + d.SpaceCollide2(Plane, m_scene.GroundSpace, IntPtr.Zero, nearCallback); + } + else + { + d.SpaceCollide2(Plane, req.geom, IntPtr.Zero, nearCallback); + } + + List cresult = new List(m_contactResults.Count); + lock (m_PendingRequests) + { + cresult.AddRange(m_contactResults); + m_contactResults.Clear(); + } + + ((ProbePlaneCallback)req.callbackMethod)(cresult); + } + /// /// Method that actually initiates the raycast with a geom /// @@ -436,7 +437,7 @@ namespace OpenSim.Region.Physics.OdePlugin private bool GetCurContactGeom(int index, ref d.ContactGeom newcontactgeom) { IntPtr ContactgeomsArray = m_scene.ContactgeomsArray; - if (ContactgeomsArray == IntPtr.Zero || index >= ColisionContactGeomsPerTest) + if (ContactgeomsArray == IntPtr.Zero || index >= CollisionContactGeomsPerTest) return false; IntPtr contactptr = new IntPtr(ContactgeomsArray.ToInt64() + (Int64)(index * d.ContactGeom.unmanagedSizeOf)); @@ -469,7 +470,157 @@ namespace OpenSim.Region.Physics.OdePlugin int count = 0; try { - count = d.CollidePtr(g1, g2, ColisionContactGeomsPerTest, m_scene.ContactgeomsArray, d.ContactGeom.unmanagedSizeOf); + count = d.CollidePtr(g1, g2, CollisionContactGeomsPerTest, m_scene.ContactgeomsArray, d.ContactGeom.unmanagedSizeOf); + } + catch (Exception e) + { + m_log.WarnFormat("[PHYSICS Ray]: Unable to collide test an object: {0}", e.Message); + return; + } + + if (count == 0) + return; +/* + uint cat1 = d.GeomGetCategoryBits(g1); + uint cat2 = d.GeomGetCategoryBits(g2); + uint col1 = d.GeomGetCollideBits(g1); + uint col2 = d.GeomGetCollideBits(g2); +*/ + + uint ID = 0; + PhysicsActor p2 = null; + + m_scene.actor_name_map.TryGetValue(g2, out p2); + + if (p2 == null) + return; + + switch (p2.PhysicsActorType) + { + case (int)ActorTypes.Prim: + + RayFilterFlags thisFlags; + + if (p2.IsPhysical) + thisFlags = RayFilterFlags.physical; + else + thisFlags = RayFilterFlags.nonphysical; + + if (p2.Phantom) + thisFlags |= RayFilterFlags.phantom; + + if (p2.IsVolumeDtc) + thisFlags |= RayFilterFlags.volumedtc; + + if ((thisFlags & CurrentRayFilter) == 0) + return; + + ID = ((OdePrim)p2).LocalID; + break; + + case (int)ActorTypes.Agent: + + if ((CurrentRayFilter & RayFilterFlags.agent) == 0) + return; + else + ID = ((OdeCharacter)p2).LocalID; + break; + + case (int)ActorTypes.Ground: + + if ((CurrentRayFilter & RayFilterFlags.land) == 0) + return; + break; + + case (int)ActorTypes.Water: + + if ((CurrentRayFilter & RayFilterFlags.water) == 0) + return; + break; + + default: + break; + } + + d.ContactGeom curcontact = new d.ContactGeom(); + + // closestHit for now only works for meshs, so must do it for others + if ((CurrentRayFilter & RayFilterFlags.ClosestHit) == 0) + { + // Loop all contacts, build results. + for (int i = 0; i < count; i++) + { + if (!GetCurContactGeom(i, ref curcontact)) + break; + + ContactResult collisionresult = new ContactResult(); + collisionresult.ConsumerID = ID; + collisionresult.Pos = new Vector3(curcontact.pos.X, curcontact.pos.Y, curcontact.pos.Z); + collisionresult.Depth = curcontact.depth; + collisionresult.Normal = new Vector3(curcontact.normal.X, curcontact.normal.Y, + curcontact.normal.Z); + lock (m_contactResults) + { + m_contactResults.Add(collisionresult); + if (m_contactResults.Count >= CurrentMaxCount) + return; + } + } + } + else + { + // keep only closest contact + ContactResult collisionresult = new ContactResult(); + collisionresult.ConsumerID = ID; + collisionresult.Depth = float.MaxValue; + + for (int i = 0; i < count; i++) + { + if (!GetCurContactGeom(i, ref curcontact)) + break; + + if (curcontact.depth < collisionresult.Depth) + { + collisionresult.Pos = new Vector3(curcontact.pos.X, curcontact.pos.Y, curcontact.pos.Z); + collisionresult.Depth = curcontact.depth; + collisionresult.Normal = new Vector3(curcontact.normal.X, curcontact.normal.Y, + curcontact.normal.Z); + } + } + + if (collisionresult.Depth != float.MaxValue) + { + lock (m_contactResults) + m_contactResults.Add(collisionresult); + } + } + } + + private void nearProbe(IntPtr space, IntPtr g1, IntPtr g2) + { + if (g1 == IntPtr.Zero || g1 == g2) + return; + + if (m_contactResults.Count >= CurrentMaxCount) + return; + + if (d.GeomIsSpace(g1)) + { + try + { + d.SpaceCollide2(g1, g2, IntPtr.Zero, nearProbeCallback); + } + catch (Exception e) + { + m_log.WarnFormat("[PHYSICS Ray]: Unable to Space collide test an object: {0}", e.Message); + } + return; + } + + int count = 0; + try + { + count = d.CollidePtr(g1, g2, CollisionContactGeomsPerTest, m_scene.ContactgeomsArray, d.ContactGeom.unmanagedSizeOf); } catch (Exception e) { @@ -481,82 +632,58 @@ namespace OpenSim.Region.Physics.OdePlugin return; uint ID = 0; - PhysicsActor p2 = null; + PhysicsActor p1 = null; - m_scene.actor_name_map.TryGetValue(g2, out p2); + m_scene.actor_name_map.TryGetValue(g1, out p1); - if (p2 == null) - { - /* - string name; - - if (!m_scene.geom_name_map.TryGetValue(g2, out name)) - return; - - if (name == "Terrain") - { - // land colision - if ((CurrentRayFilter & RayFilterFlags.land) == 0) - return; - } - else if (name == "Water") - { - if ((CurrentRayFilter & RayFilterFlags.water) == 0) - return; - } - else - return; - */ + if (p1 == null) return; - } - else + + switch (p1.PhysicsActorType) { - switch (p2.PhysicsActorType) - { - case (int)ActorTypes.Prim: + case (int)ActorTypes.Prim: - RayFilterFlags thisFlags; + RayFilterFlags thisFlags; - if (p2.IsPhysical) - thisFlags = RayFilterFlags.physical; - else - thisFlags = RayFilterFlags.nonphysical; + if (p1.IsPhysical) + thisFlags = RayFilterFlags.physical; + else + thisFlags = RayFilterFlags.nonphysical; - if (p2.Phantom) - thisFlags |= RayFilterFlags.phantom; + if (p1.Phantom) + thisFlags |= RayFilterFlags.phantom; - if (p2.IsVolumeDtc) - thisFlags |= RayFilterFlags.volumedtc; + if (p1.IsVolumeDtc) + thisFlags |= RayFilterFlags.volumedtc; - if ((thisFlags & CurrentRayFilter) == 0) - return; + if ((thisFlags & CurrentRayFilter) == 0) + return; - ID = ((OdePrim)p2).LocalID; - break; + ID = ((OdePrim)p1).LocalID; + break; - case (int)ActorTypes.Agent: + case (int)ActorTypes.Agent: - if ((CurrentRayFilter & RayFilterFlags.agent) == 0) - return; - else - ID = ((OdeCharacter)p2).LocalID; - break; + if ((CurrentRayFilter & RayFilterFlags.agent) == 0) + return; + else + ID = ((OdeCharacter)p1).LocalID; + break; - case (int)ActorTypes.Ground: + case (int)ActorTypes.Ground: - if ((CurrentRayFilter & RayFilterFlags.land) == 0) - return; - break; + if ((CurrentRayFilter & RayFilterFlags.land) == 0) + return; + break; - case (int)ActorTypes.Water: + case (int)ActorTypes.Water: - if ((CurrentRayFilter & RayFilterFlags.water) == 0) - return; - break; + if ((CurrentRayFilter & RayFilterFlags.water) == 0) + return; + break; - default: - break; - } + default: + break; } d.ContactGeom curcontact = new d.ContactGeom(); @@ -624,6 +751,21 @@ namespace OpenSim.Region.Physics.OdePlugin d.GeomDestroy(ray); ray = IntPtr.Zero; } + if (Box != IntPtr.Zero) + { + d.GeomDestroy(Box); + Box = IntPtr.Zero; + } + if (Sphere != IntPtr.Zero) + { + d.GeomDestroy(Sphere); + Sphere = IntPtr.Zero; + } + if (Plane != IntPtr.Zero) + { + d.GeomDestroy(Plane); + Plane = IntPtr.Zero; + } } } @@ -636,5 +778,6 @@ namespace OpenSim.Region.Physics.OdePlugin public float length; public object callbackMethod; public RayFilterFlags filter; + public Quaternion orientation; } } \ No newline at end of file diff --git a/OpenSim/Region/Physics/UbitOdePlugin/ODESitAvatar.cs b/OpenSim/Region/Physics/UbitOdePlugin/ODESitAvatar.cs index 225bff8e65..ecc732a129 100644 --- a/OpenSim/Region/Physics/UbitOdePlugin/ODESitAvatar.cs +++ b/OpenSim/Region/Physics/UbitOdePlugin/ODESitAvatar.cs @@ -52,6 +52,21 @@ namespace OpenSim.Region.Physics.OdePlugin } private static Vector3 SitAjust = new Vector3(0, 0, 0.4f); + private const RayFilterFlags RaySitFlags = RayFilterFlags.AllPrims | RayFilterFlags.ClosestHit; + + private void RotAroundZ(float x, float y, ref Quaternion ori) + { + double ang = Math.Atan2(y, x); + ang *= 0.5d; + float s = (float)Math.Sin(ang); + float c = (float)Math.Cos(ang); + + ori.X = 0; + ori.Y = 0; + ori.Z = s; + ori.W = c; + } + public void Sit(PhysicsActor actor, Vector3 avPos, Vector3 avCameraPosition, Vector3 offset, Vector3 avOffset, SitAvatarCallback PhysicsSitResponse) { @@ -63,88 +78,82 @@ namespace OpenSim.Region.Physics.OdePlugin IntPtr geom = ((OdePrim)actor).prim_geom; - d.Vector3 dtmp = d.GeomGetPosition(geom); - Vector3 geopos; - geopos.X = dtmp.X; - geopos.Y = dtmp.Y; - geopos.Z = dtmp.Z; + Vector3 geopos = d.GeomGetPositionOMV(geom); + Quaternion geomOri = d.GeomGetQuaternionOMV(geom); + Quaternion geomInvOri = Quaternion.Conjugate(geomOri); + Quaternion ori = Quaternion.Identity; - d.AABB aabb; - Quaternion ori; - d.Quaternion qtmp; - d.GeomCopyQuaternion(geom, out qtmp); - Quaternion geomOri; - geomOri.X = qtmp.X; - geomOri.Y = qtmp.Y; - geomOri.Z = qtmp.Z; - geomOri.W = qtmp.W; - Quaternion geomInvOri; - geomInvOri.X = -qtmp.X; - geomInvOri.Y = -qtmp.Y; - geomInvOri.Z = -qtmp.Z; - geomInvOri.W = qtmp.W; + Vector3 rayDir = geopos + offset - avCameraPosition; - Vector3 target = geopos + offset; - Vector3 rayDir = target - avCameraPosition; float raylen = rayDir.Length(); + if (raylen < 0.001f) + { + PhysicsSitResponse(-1, actor.LocalID, offset, Quaternion.Identity); + return; + } float t = 1 / raylen; rayDir.X *= t; rayDir.Y *= t; rayDir.Z *= t; - raylen += 0.5f; + raylen += 30f; // focal point may be far List rayResults; - rayResults = m_scene.RaycastActor(actor, avCameraPosition, rayDir , raylen, 1); - if (rayResults.Count == 0 || rayResults[0].ConsumerID != actor.LocalID) + rayResults = m_scene.RaycastActor(actor, avCameraPosition, rayDir, raylen, 1, RaySitFlags); + if (rayResults.Count == 0) { - d.GeomGetAABB(geom,out aabb); +/* if this fundamental ray failed, then just fail so user can try another spot and not be sitted far on a big prim + d.AABB aabb; + d.GeomGetAABB(geom, out aabb); offset = new Vector3(avOffset.X, 0, aabb.MaxZ + avOffset.Z - geopos.Z); ori = geomInvOri; offset *= geomInvOri; - PhysicsSitResponse(1, actor.LocalID, offset, ori); +*/ + PhysicsSitResponse(0, actor.LocalID, offset, ori); return; } + int status = 1; offset = rayResults[0].Pos - geopos; - double ang; - float s; - float c; d.GeomClassID geoclass = d.GeomGetClass(geom); if (geoclass == d.GeomClassID.SphereClass) { - float r = d.GeomSphereGetRadius(geom); + float r = d.GeomSphereGetRadius(geom); offset.Normalize(); offset *= r; - ang = Math.Atan2(offset.Y, offset.X); - ang *= 0.5d; - s = (float)Math.Sin(ang); - c = (float)Math.Cos(ang); - - ori = new Quaternion(0, 0, s, c); + RotAroundZ(offset.X, offset.Y, ref ori); if (r < 0.4f) { offset = new Vector3(0, 0, r); } - else if (offset.Z < 0.4f) + else { - t = offset.Z; - float rsq = r * r; + if (offset.Z < 0.4f) + { + t = offset.Z; + float rsq = r * r; - t = 1.0f / (rsq - t * t); - offset.X *= t; - offset.Y *= t; - offset.Z = 0.4f; - t = rsq - 0.16f; - offset.X *= t; - offset.Y *= t; + t = 1.0f / (rsq - t * t); + offset.X *= t; + offset.Y *= t; + offset.Z = 0.4f; + t = rsq - 0.16f; + offset.X *= t; + offset.Y *= t; + } + else if (r > 0.8f && offset.Z > 0.8f * r) + { + status = 3; + avOffset.X = -avOffset.X; + avOffset.Z *= 1.6f; + } } offset += avOffset * ori; @@ -152,26 +161,189 @@ namespace OpenSim.Region.Physics.OdePlugin ori = geomInvOri * ori; offset *= geomInvOri; - PhysicsSitResponse(1, actor.LocalID, offset, ori); + PhysicsSitResponse(status, actor.LocalID, offset, ori); return; } Vector3 norm = rayResults[0].Normal; - if (norm.Z < 0) + if (norm.Z < -0.4f) { PhysicsSitResponse(0, actor.LocalID, offset, Quaternion.Identity); return; } - ang = Math.Atan2(-rayDir.Y, -rayDir.X); - ang *= 0.5d; - s = (float)Math.Sin(ang); - c = (float)Math.Cos(ang); - ori = new Quaternion(0, 0, s, c); + float SitNormX = -rayDir.X; + float SitNormY = -rayDir.Y; - offset += avOffset * ori; + Vector3 pivot = geopos + offset; + + float edgeNormalX = norm.X; + float edgeNormalY = norm.Y; + float edgeDirX = -rayDir.X; + float edgeDirY = -rayDir.Y; + Vector3 edgePos = rayResults[0].Pos; + float edgeDist = float.MaxValue; + + bool foundEdge = false; + + if (norm.Z < 0.5f) + { + float rayDist = 4.0f; + float curEdgeDist = 0.0f; + + for (int i = 0; i < 6; i++) + { + pivot.X -= 0.005f * norm.X; + pivot.Y -= 0.005f * norm.Y; + pivot.Z -= 0.005f * norm.Z; + + rayDir.X = -norm.X * norm.Z; + rayDir.Y = -norm.Y * norm.Z; + rayDir.Z = 1.0f - norm.Z * norm.Z; + rayDir.Normalize(); + + rayResults = m_scene.RaycastActor(actor, pivot, rayDir, rayDist, 1, RayFilterFlags.AllPrims); + if (rayResults.Count == 0) + break; + + curEdgeDist += rayResults[0].Depth; + + if (Math.Abs(rayResults[0].Normal.Z) < 0.7f) + { + rayDist -= rayResults[0].Depth; + if (rayDist < 0f) + break; + + pivot = rayResults[0].Pos; + norm = rayResults[0].Normal; + edgeNormalX = norm.X; + edgeNormalY = norm.Y; + edgeDirX = -rayDir.X; + edgeDirY = -rayDir.Y; + } + else + { + foundEdge = true; + edgeDist = curEdgeDist; + edgePos = rayResults[0].Pos; + break; + } + } + + if (!foundEdge) + { + PhysicsSitResponse(0, actor.LocalID, offset, ori); + return; + } + avOffset.X *= 0.5f; + } + + else if (norm.Z > 0.866f) + { + float toCamBaseX = avCameraPosition.X - pivot.X; + float toCamBaseY = avCameraPosition.Y - pivot.Y; + float toCamX = toCamBaseX; + float toCamY = toCamBaseY; + + for (int j = 0; j < 4; j++) + { + float rayDist = 1.0f; + float curEdgeDist = 0.0f; + + for (int i = 0; i < 3; i++) + { + pivot.Z -= 0.005f; + rayDir.X = toCamX; + rayDir.Y = toCamY; + rayDir.Z = (-toCamX * norm.X - toCamY * norm.Y) / norm.Z; + rayDir.Normalize(); + + rayResults = m_scene.RaycastActor(actor, pivot, rayDir, rayDist, 1, RayFilterFlags.AllPrims); + if (rayResults.Count == 0) + break; + + curEdgeDist += rayResults[0].Depth; + + if (rayResults[0].Normal.Z > 0.5f) + { + rayDist -= rayResults[0].Depth; + if (rayDist < 0f) + break; + + pivot = rayResults[0].Pos; + norm = rayResults[0].Normal; + } + else + { + foundEdge = true; + if (curEdgeDist < edgeDist) + { + edgeDist = curEdgeDist; + edgeNormalX = rayResults[0].Normal.X; + edgeNormalY = rayResults[0].Normal.Y; + edgeDirX = rayDir.X; + edgeDirY = rayDir.Y; + edgePos = rayResults[0].Pos; + } + break; + } + } + if (foundEdge && edgeDist < 0.2f) + break; + + pivot = geopos + offset; + + switch (j) + { + case 0: + toCamX = -toCamBaseY; + toCamY = toCamBaseX; + break; + case 1: + toCamX = toCamBaseY; + toCamY = -toCamBaseX; + break; + case 2: + toCamX = -toCamBaseX; + toCamY = -toCamBaseY; + break; + default: + break; + } + } + + if (!foundEdge) + { + avOffset.X = -avOffset.X; + avOffset.Z *= 1.6f; + + RotAroundZ(SitNormX, SitNormY, ref ori); + + offset += avOffset * ori; + + ori = geomInvOri * ori; + offset *= geomInvOri; + + PhysicsSitResponse(3, actor.LocalID, offset, ori); + return; + } + avOffset.X *= 0.5f; + } + + SitNormX = edgeNormalX; + SitNormY = edgeNormalY; + if (edgeDirX * SitNormX + edgeDirY * SitNormY < 0) + { + SitNormX = -SitNormX; + SitNormY = -SitNormY; + } + + RotAroundZ(SitNormX, SitNormY, ref ori); + + offset = edgePos + avOffset * ori; + offset -= geopos; ori = geomInvOri * ori; offset *= geomInvOri; diff --git a/OpenSim/Region/Physics/UbitOdePlugin/OdeApi.cs b/OpenSim/Region/Physics/UbitOdePlugin/OdeApi.cs index 403a4ce85b..10d7d50d95 100644 --- a/OpenSim/Region/Physics/UbitOdePlugin/OdeApi.cs +++ b/OpenSim/Region/Physics/UbitOdePlugin/OdeApi.cs @@ -44,7 +44,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. using System; using System.Runtime.InteropServices; using System.Security; - +using OMV = OpenMetaverse; namespace OdeAPI { //#if dDOUBLE @@ -925,9 +925,20 @@ namespace OdeAPI { unsafe { return *(GeomGetPositionUnsafe(geom)); } } + public static OMV.Vector3 GeomGetPositionOMV(IntPtr geom) + { + Vector3 vtmp = GeomGetPosition(geom); + return new OMV.Vector3(vtmp.X, vtmp.Y, vtmp.Z); + } [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetQuaternion"), SuppressUnmanagedCodeSecurity] - public static extern void GeomCopyQuaternion(IntPtr geom, out Quaternion q); + public static extern void GeomCopyQuaternion(IntPtr geom, out Quaternion q); + public static OMV.Quaternion GeomGetQuaternionOMV(IntPtr geom) + { + Quaternion qtmp; + GeomCopyQuaternion(geom, out qtmp); + return new OMV.Quaternion(qtmp.X, qtmp.Y, qtmp.Z, qtmp.W); + } [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetQuaternion"), SuppressUnmanagedCodeSecurity] public static extern void GeomCopyQuaternion(IntPtr geom, out dReal X); diff --git a/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs b/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs index fbf2f0dabd..d045b59484 100644 --- a/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs +++ b/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs @@ -2579,7 +2579,16 @@ namespace OpenSim.Region.Physics.OdePlugin { if (retMethod != null) { - m_rayCastManager.QueueRequest(position, direction, length, retMethod); + ODERayRequest req = new ODERayRequest(); + req.geom = IntPtr.Zero; + req.callbackMethod = retMethod; + req.length = length; + req.Normal = direction; + req.Origin = position; + req.Count = 0; + req.filter = RayFilterFlags.All; + + m_rayCastManager.QueueRequest(req); } } @@ -2587,29 +2596,51 @@ namespace OpenSim.Region.Physics.OdePlugin { if (retMethod != null) { - m_rayCastManager.QueueRequest(position, direction, length, Count, retMethod); + ODERayRequest req = new ODERayRequest(); + req.geom = IntPtr.Zero; + req.callbackMethod = retMethod; + req.length = length; + req.Normal = direction; + req.Origin = position; + req.Count = Count; + req.filter = RayFilterFlags.All; + + m_rayCastManager.QueueRequest(req); } } - // don't like this + public override List RaycastWorld(Vector3 position, Vector3 direction, float length, int Count) { - ContactResult[] ourResults = null; + List ourresults = new List(); + object SyncObject = new object(); + RayCallback retMethod = delegate(List results) { - ourResults = new ContactResult[results.Count]; - results.CopyTo(ourResults, 0); + lock (SyncObject) + { + ourresults = results; + Monitor.PulseAll(SyncObject); + } }; - int waitTime = 0; - m_rayCastManager.QueueRequest(position, direction, length, Count, retMethod); - while (ourResults == null && waitTime < 1000) + + ODERayRequest req = new ODERayRequest(); + req.geom = IntPtr.Zero; + req.callbackMethod = retMethod; + req.length = length; + req.Normal = direction; + req.Origin = position; + req.Count = Count; + req.filter = RayFilterFlags.All; + + lock (SyncObject) { - Thread.Sleep(1); - waitTime++; + m_rayCastManager.QueueRequest(req); + if (!Monitor.Wait(SyncObject, 500)) + return null; + else + return ourresults; } - if (ourResults == null) - return new List(); - return new List(ourResults); } public override bool SuportsRaycastWorldFiltered() @@ -2631,9 +2662,18 @@ namespace OpenSim.Region.Physics.OdePlugin } }; + ODERayRequest req = new ODERayRequest(); + req.geom = IntPtr.Zero; + req.callbackMethod = retMethod; + req.length = length; + req.Normal = direction; + req.Origin = position; + req.Count = Count; + req.filter = filter; + lock (SyncObject) { - m_rayCastManager.QueueRequest(position, direction, length, Count,filter, retMethod); + m_rayCastManager.QueueRequest(req); if (!Monitor.Wait(SyncObject, 500)) return null; else @@ -2641,74 +2681,163 @@ namespace OpenSim.Region.Physics.OdePlugin } } - public override void RaycastActor(PhysicsActor actor, Vector3 position, Vector3 direction, float length, RaycastCallback retMethod) + public override List RaycastActor(PhysicsActor actor, Vector3 position, Vector3 direction, float length, int Count, RayFilterFlags flags) { - if (retMethod != null && actor !=null) + if (actor == null) + return new List(); + + IntPtr geom; + if (actor is OdePrim) + geom = ((OdePrim)actor).prim_geom; + else if (actor is OdeCharacter) + geom = ((OdePrim)actor).prim_geom; + else + return new List(); + + if (geom == IntPtr.Zero) + return new List(); + + List ourResults = null; + object SyncObject = new object(); + + RayCallback retMethod = delegate(List results) { - IntPtr geom; - if (actor is OdePrim) - geom = ((OdePrim)actor).prim_geom; - else if (actor is OdeCharacter) - geom = ((OdePrim)actor).prim_geom; - else - return; - if (geom == IntPtr.Zero) - return; - m_rayCastManager.QueueRequest(geom, position, direction, length, retMethod); + lock (SyncObject) + { + ourResults = results; + Monitor.PulseAll(SyncObject); + } + }; + + ODERayRequest req = new ODERayRequest(); + req.geom = geom; + req.callbackMethod = retMethod; + req.length = length; + req.Normal = direction; + req.Origin = position; + req.Count = Count; + req.filter = flags; + + lock (SyncObject) + { + m_rayCastManager.QueueRequest(req); + if (!Monitor.Wait(SyncObject, 500)) + return new List(); } + + if (ourResults == null) + return new List(); + return ourResults; } - public override void RaycastActor(PhysicsActor actor, Vector3 position, Vector3 direction, float length, int Count, RayCallback retMethod) + public override List BoxProbe(Vector3 position, Vector3 size, Quaternion orientation, int Count, RayFilterFlags flags) { - if (retMethod != null && actor != null) - { - IntPtr geom; - if (actor is OdePrim) - geom = ((OdePrim)actor).prim_geom; - else if (actor is OdeCharacter) - geom = ((OdePrim)actor).prim_geom; - else - return; - if (geom == IntPtr.Zero) - return; + List ourResults = null; + object SyncObject = new object(); - m_rayCastManager.QueueRequest(geom,position, direction, length, Count, retMethod); + ProbeBoxCallback retMethod = delegate(List results) + { + lock (SyncObject) + { + ourResults = results; + Monitor.PulseAll(SyncObject); + } + }; + + ODERayRequest req = new ODERayRequest(); + req.geom = IntPtr.Zero; + req.callbackMethod = retMethod; + req.Normal = size; + req.Origin = position; + req.orientation = orientation; + req.Count = Count; + req.filter = flags; + + lock (SyncObject) + { + m_rayCastManager.QueueRequest(req); + if (!Monitor.Wait(SyncObject, 500)) + return new List(); } + + if (ourResults == null) + return new List(); + return ourResults; } - // don't like this - public override List RaycastActor(PhysicsActor actor, Vector3 position, Vector3 direction, float length, int Count) + public override List SphereProbe(Vector3 position, float radius, int Count, RayFilterFlags flags) { + List ourResults = null; + object SyncObject = new object(); + + ProbeSphereCallback retMethod = delegate(List results) + { + ourResults = results; + Monitor.PulseAll(SyncObject); + }; + + ODERayRequest req = new ODERayRequest(); + req.geom = IntPtr.Zero; + req.callbackMethod = retMethod; + req.length = radius; + req.Origin = position; + req.Count = Count; + req.filter = flags; + + + lock (SyncObject) + { + m_rayCastManager.QueueRequest(req); + if (!Monitor.Wait(SyncObject, 500)) + return new List(); + } + + if (ourResults == null) + return new List(); + return ourResults; + } + + public override List PlaneProbe(PhysicsActor actor, Vector4 plane, int Count, RayFilterFlags flags) + { + IntPtr geom = IntPtr.Zero;; + if (actor != null) { - IntPtr geom; if (actor is OdePrim) geom = ((OdePrim)actor).prim_geom; else if (actor is OdeCharacter) geom = ((OdePrim)actor).prim_geom; - else - return new List(); - if (geom == IntPtr.Zero) - return new List(); - - ContactResult[] ourResults = null; - RayCallback retMethod = delegate(List results) - { - ourResults = new ContactResult[results.Count]; - results.CopyTo(ourResults, 0); - }; - int waitTime = 0; - m_rayCastManager.QueueRequest(geom,position, direction, length, Count, retMethod); - while (ourResults == null && waitTime < 1000) - { - Thread.Sleep(1); - waitTime++; - } - if (ourResults == null) - return new List(); - return new List(ourResults); } - return new List(); + + List ourResults = null; + object SyncObject = new object(); + + ProbePlaneCallback retMethod = delegate(List results) + { + ourResults = results; + Monitor.PulseAll(SyncObject); + }; + + ODERayRequest req = new ODERayRequest(); + req.geom = geom; + req.callbackMethod = retMethod; + req.length = plane.W; + req.Normal.X = plane.X; + req.Normal.Y = plane.Y; + req.Normal.Z = plane.Z; + req.Count = Count; + req.filter = flags; + + lock (SyncObject) + { + m_rayCastManager.QueueRequest(req); + if (!Monitor.Wait(SyncObject, 500)) + return new List(); + } + + if (ourResults == null) + return new List(); + return ourResults; } public override int SitAvatar(PhysicsActor actor, Vector3 AbsolutePosition, Vector3 CameraPosition, Vector3 offset, Vector3 AvatarSize, SitAvatarCallback PhysicsSitResponse) diff --git a/OpenSim/Tests/Performance/NPCPerformanceTests.cs b/OpenSim/Tests/Performance/NPCPerformanceTests.cs index 2026a881f0..fde1b912a6 100644 --- a/OpenSim/Tests/Performance/NPCPerformanceTests.cs +++ b/OpenSim/Tests/Performance/NPCPerformanceTests.cs @@ -144,7 +144,7 @@ namespace OpenSim.Tests.Performance // ScenePresence.SendInitialData() to reset our entire appearance. scene.AssetService.Store(AssetHelpers.CreateNotecardAsset(originalFace8TextureId)); - afm.SetAppearance(sp, originalTe, null); + afm.SetAppearance(sp, originalTe, null, new WearableCacheItem[0]); INPCModule npcModule = scene.RequestModuleInterface();