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();