Merge branch 'avination' into careminster

avinationmerge
Melanie 2013-01-06 10:52:22 +00:00
commit 083ac92b34
20 changed files with 1130 additions and 466 deletions

View File

@ -117,7 +117,7 @@ namespace OpenSim.Capabilities.Handlers
/// <param name="data"></param> /// <param name="data"></param>
private void BakedTextureUploaded(UUID assetID, byte[] data) 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; AssetBase asset;
asset = new AssetBase(assetID, "Baked Texture", (sbyte)AssetType.Texture, m_HostCapsObj.AgentID.ToString()); asset = new AssetBase(assetID, "Baked Texture", (sbyte)AssetType.Texture, m_HostCapsObj.AgentID.ToString());

View File

@ -66,7 +66,7 @@ namespace OpenSim.Framework
protected Vector3 m_avatarBoxSize = new Vector3(0.45f, 0.6f, 1.9f); protected Vector3 m_avatarBoxSize = new Vector3(0.45f, 0.6f, 1.9f);
protected float m_avatarFeetOffset = 0; protected float m_avatarFeetOffset = 0;
protected float m_avatarAnimOffset = 0; protected float m_avatarAnimOffset = 0;
protected WearableCacheItem[] cacheitems;
public virtual int Serial public virtual int Serial
{ {
get { return m_serial; } get { return m_serial; }
@ -115,6 +115,12 @@ namespace OpenSim.Framework
get { return m_avatarHeight; } get { return m_avatarHeight; }
set { m_avatarHeight = value; } set { m_avatarHeight = value; }
} }
public virtual WearableCacheItem[] WearableCacheItems
{
get { return cacheitems; }
set { cacheitems = value; }
}
public AvatarAppearance() public AvatarAppearance()
{ {

View File

@ -64,7 +64,7 @@ namespace OpenSim.Framework
public delegate void NetworkStats(int inPackets, int outPackets, int unAckedBytes); 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); public delegate void StartAnim(IClientAPI remoteClient, UUID animID);

View File

@ -70,6 +70,7 @@ namespace OpenSim.Framework
void UpdateLandProperties(LandUpdateArgs args, IClientAPI remote_client); void UpdateLandProperties(LandUpdateArgs args, IClientAPI remote_client);
bool IsEitherBannedOrRestricted(UUID avatar); bool IsEitherBannedOrRestricted(UUID avatar);
bool IsBannedFromLand(UUID avatar); bool IsBannedFromLand(UUID avatar);
bool CanBeOnThisLand(UUID avatar, float posHeight);
bool IsRestrictedFromLand(UUID avatar); bool IsRestrictedFromLand(UUID avatar);
bool IsInLandAccessList(UUID avatar); bool IsInLandAccessList(UUID avatar);
void SendLandUpdateToClient(IClientAPI remote_client); void SendLandUpdateToClient(IClientAPI remote_client);

View File

@ -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; }
}
}

View File

@ -460,6 +460,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
} }
public bool SendLogoutPacketWhenClosing { set { m_SendLogoutPacketWhenClosing = value; } } public bool SendLogoutPacketWhenClosing { set { m_SendLogoutPacketWhenClosing = value; } }
#endregion Properties #endregion Properties
@ -585,6 +586,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// Disable UDP handling for this client // Disable UDP handling for this client
m_udpClient.Shutdown(); m_udpClient.Shutdown();
//m_log.InfoFormat("[CLIENTVIEW] Memory pre GC {0}", System.GC.GetTotalMemory(false)); //m_log.InfoFormat("[CLIENTVIEW] Memory pre GC {0}", System.GC.GetTotalMemory(false));
//GC.Collect(); //GC.Collect();
//m_log.InfoFormat("[CLIENTVIEW] Memory post GC {0}", System.GC.GetTotalMemory(true)); //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); req.AssetInf.ID, req.AssetInf.Metadata.ContentType);
return; 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(); TransferInfoPacket Transfer = new TransferInfoPacket();
Transfer.TransferInfo.ChannelType = 2; Transfer.TransferInfo.ChannelType = 2;
Transfer.TransferInfo.Status = 0; Transfer.TransferInfo.Status = 0;
@ -2773,7 +2788,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
Transfer.TransferInfo.Size = req.AssetInf.Data.Length; Transfer.TransferInfo.Size = req.AssetInf.Data.Length;
Transfer.TransferInfo.TransferID = req.TransferRequestID; Transfer.TransferInfo.TransferID = req.TransferRequestID;
Transfer.Header.Zerocoded = true; Transfer.Header.Zerocoded = true;
OutPacket(Transfer, ThrottleOutPacketType.Asset); OutPacket(Transfer, isWearable ? ThrottleOutPacketType.State : ThrottleOutPacketType.Asset);
if (req.NumPackets == 1) if (req.NumPackets == 1)
{ {
@ -2784,7 +2799,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
TransferPacket.TransferData.Data = req.AssetInf.Data; TransferPacket.TransferData.Data = req.AssetInf.Data;
TransferPacket.TransferData.Status = 1; TransferPacket.TransferData.Status = 1;
TransferPacket.Header.Zerocoded = true; TransferPacket.Header.Zerocoded = true;
OutPacket(TransferPacket, ThrottleOutPacketType.Asset); OutPacket(TransferPacket, isWearable ? ThrottleOutPacketType.State : ThrottleOutPacketType.Asset);
} }
else else
{ {
@ -2817,7 +2832,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
TransferPacket.TransferData.Status = 1; TransferPacket.TransferData.Status = 1;
} }
TransferPacket.Header.Zerocoded = true; TransferPacket.Header.Zerocoded = true;
OutPacket(TransferPacket, ThrottleOutPacketType.Asset); OutPacket(TransferPacket, isWearable ? ThrottleOutPacketType.State : ThrottleOutPacketType.Asset);
processedLength += chunkSize; processedLength += chunkSize;
packetNumber++; packetNumber++;
@ -3572,24 +3587,25 @@ namespace OpenSim.Region.ClientStack.LindenUDP
aw.WearableData = new AgentWearablesUpdatePacket.WearableDataBlock[count]; aw.WearableData = new AgentWearablesUpdatePacket.WearableDataBlock[count];
AgentWearablesUpdatePacket.WearableDataBlock awb; AgentWearablesUpdatePacket.WearableDataBlock awb;
int idx = 0; int idx = 0;
for (int i = 0; i < wearables.Length; i++)
{ for (int i = 0; i < wearables.Length; i++)
for (int j = 0; j < wearables[i].Count; j++) {
{ for (int j = 0; j < wearables[i].Count; j++)
awb = new AgentWearablesUpdatePacket.WearableDataBlock(); {
awb.WearableType = (byte)i; awb = new AgentWearablesUpdatePacket.WearableDataBlock();
awb.AssetID = wearables[i][j].AssetID; awb.WearableType = (byte) i;
awb.ItemID = wearables[i][j].ItemID; awb.AssetID = wearables[i][j].AssetID;
aw.WearableData[idx] = awb; awb.ItemID = wearables[i][j].ItemID;
idx++; aw.WearableData[idx] = awb;
idx++;
// m_log.DebugFormat( // m_log.DebugFormat(
// "[APPEARANCE]: Sending wearable item/asset {0} {1} (index {2}) for {3}", // "[APPEARANCE]: Sending wearable item/asset {0} {1} (index {2}) for {3}",
// awb.ItemID, awb.AssetID, i, Name); // awb.ItemID, awb.AssetID, i, Name);
} }
} }
OutPacket(aw, ThrottleOutPacketType.Task); OutPacket(aw, ThrottleOutPacketType.State);
} }
public void SendAppearance(UUID agentID, byte[] visualParams, byte[] textureEntry) public void SendAppearance(UUID agentID, byte[] visualParams, byte[] textureEntry)
@ -3614,7 +3630,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
avp.Sender.IsTrial = false; avp.Sender.IsTrial = false;
avp.Sender.ID = agentID; avp.Sender.ID = agentID;
//m_log.DebugFormat("[CLIENT]: Sending appearance for {0} to {1}", agentID.ToString(), AgentId.ToString()); //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) 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]; byte[] visualparams = new byte[appear.VisualParam.Length];
for (int i = 0; i < appear.VisualParam.Length; i++) for (int i = 0; i < appear.VisualParam.Length; i++)
visualparams[i] = appear.VisualParam[i].ParamValue; visualparams[i] = appear.VisualParam[i].ParamValue;
//var b = appear.WearableData[0];
Primitive.TextureEntry te = null; Primitive.TextureEntry te = null;
if (appear.ObjectData.TextureEntry.Length > 1) if (appear.ObjectData.TextureEntry.Length > 1)
te = new Primitive.TextureEntry(appear.ObjectData.TextureEntry, 0, appear.ObjectData.TextureEntry.Length); te = new Primitive.TextureEntry(appear.ObjectData.TextureEntry, 0, appear.ObjectData.TextureEntry.Length);
WearableCacheItem[] cacheitems = new WearableCacheItem[appear.WearableData.Length];
for (int i=0; i<appear.WearableData.Length;i++)
cacheitems[i] = new WearableCacheItem(){CacheId = appear.WearableData[i].CacheID,TextureIndex=Convert.ToUInt32(appear.WearableData[i].TextureIndex)};
handlerSetAppearance(sender, te, visualparams,avSize);
handlerSetAppearance(sender, te, visualparams,avSize, cacheitems);
} }
catch (Exception e) catch (Exception e)
{ {
@ -7798,6 +7821,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// surrounding scene // surrounding scene
if ((ImageType)block.Type == ImageType.Baked) if ((ImageType)block.Type == ImageType.Baked)
args.Priority *= 2.0f; args.Priority *= 2.0f;
int wearableout = 0;
ImageManager.EnqueueReq(args); ImageManager.EnqueueReq(args);
} }
@ -11687,6 +11711,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
if (cachedtex.AgentData.SessionID != SessionId) if (cachedtex.AgentData.SessionID != SessionId)
return false; return false;
// TODO: don't create new blocks if recycling an old packet // TODO: don't create new blocks if recycling an old packet
cachedresp.AgentData.AgentID = AgentId; cachedresp.AgentData.AgentID = AgentId;
@ -11696,6 +11721,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
cachedresp.WearableData = cachedresp.WearableData =
new AgentCachedTextureResponsePacket.WearableDataBlock[cachedtex.WearableData.Length]; new AgentCachedTextureResponsePacket.WearableDataBlock[cachedtex.WearableData.Length];
//IAvatarFactoryModule fac = m_scene.RequestModuleInterface<IAvatarFactoryModule>();
// var item = fac.GetBakedTextureFaces(AgentId);
//WearableCacheItem[] items = fac.GetCachedItems(AgentId);
IImprovedAssetCache cache = m_scene.RequestModuleInterface<IImprovedAssetCache>(); IImprovedAssetCache cache = m_scene.RequestModuleInterface<IImprovedAssetCache>();
if (cache == null) if (cache == null)
{ {
@ -11703,7 +11732,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
{ {
cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock(); cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock();
cachedresp.WearableData[i].TextureIndex = cachedtex.WearableData[i].TextureIndex; 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]; 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] = new AgentCachedTextureResponsePacket.WearableDataBlock();
cachedresp.WearableData[i].TextureIndex = cachedtex.WearableData[i].TextureIndex; 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; cachedresp.WearableData[i].TextureID = UUID.Zero;
//UUID.Parse("8334fb6e-c2f5-46ee-807d-a435f61a8d46");
else 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]; cachedresp.WearableData[i].HostName = new byte[0];
} }
} }

View File

@ -140,18 +140,18 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
/// <param name="sp"></param> /// <param name="sp"></param>
/// <param name="texture"></param> /// <param name="texture"></param>
/// <param name="visualParam"></param> /// <param name="visualParam"></param>
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; float oldoff = sp.Appearance.AvatarFeetOffset;
Vector3 oldbox = sp.Appearance.AvatarBoxSize; Vector3 oldbox = sp.Appearance.AvatarBoxSize;
SetAppearance(sp, textureEntry, visualParams); SetAppearance(sp, textureEntry, visualParams, cacheItems);
sp.Appearance.SetSize(avSize); sp.Appearance.SetSize(avSize);
float off = sp.Appearance.AvatarFeetOffset; float off = sp.Appearance.AvatarFeetOffset;
@ -166,7 +166,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
/// <param name="sp"></param> /// <param name="sp"></param>
/// <param name="texture"></param> /// <param name="texture"></param>
/// <param name="visualParam"></param> /// <param name="visualParam"></param>
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( // m_log.DebugFormat(
// "[AVFACTORY]: start SetAppearance for {0}, te {1}, visualParams {2}", // "[AVFACTORY]: start SetAppearance for {0}, te {1}, visualParams {2}",
@ -205,11 +205,14 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
// ((ScenePresence)sp).SetSize(box,off); // ((ScenePresence)sp).SetSize(box,off);
} }
//if (cacheItems.Length > 0)
//{
sp.Appearance.WearableCacheItems = cacheItems;
//}
// Process the baked texture array // Process the baked texture array
if (textureEntry != null) 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); // WriteBakedTexturesReport(sp, m_log.DebugFormat);
@ -278,6 +281,19 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
return GetBakedTextureFaces(sp); return GetBakedTextureFaces(sp);
} }
public WearableCacheItem[] GetCachedItems(UUID agentId)
{
ScenePresence sp = m_scene.GetScenePresence(agentId);
Dictionary<BakeType, Primitive.TextureEntryFace> bakedTextures = GetBakedTextureFaces(sp);
WearableCacheItem[] items = sp.Appearance.WearableCacheItems;
//foreach (WearableCacheItem item in items)
//{
//}
return items;
}
public bool SaveBakedTextures(UUID agentId) public bool SaveBakedTextures(UUID agentId)
{ {
ScenePresence sp = m_scene.GetScenePresence(agentId); ScenePresence sp = m_scene.GetScenePresence(agentId);
@ -660,12 +676,12 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
/// <param name="client"></param> /// <param name="client"></param>
/// <param name="texture"></param> /// <param name="texture"></param>
/// <param name="visualParam"></param> /// <param name="visualParam"></param>
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); // m_log.WarnFormat("[AVFACTORY]: Client_OnSetAppearance called for {0} ({1})", client.Name, client.AgentId);
ScenePresence sp = m_scene.GetScenePresence(client.AgentId); ScenePresence sp = m_scene.GetScenePresence(client.AgentId);
if (sp != null) if (sp != null)
SetAppearance(sp, textureEntry, visualParams,avSize); SetAppearance(sp, textureEntry, visualParams,avSize, cacheItems);
else else
m_log.WarnFormat("[AVFACTORY]: Client_OnSetAppearance unable to find presence for {0}", client.AgentId); m_log.WarnFormat("[AVFACTORY]: Client_OnSetAppearance unable to find presence for {0}", client.AgentId);
} }

View File

@ -61,7 +61,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
for (byte i = 0; i < visualParams.Length; i++) for (byte i = 0; i < visualParams.Length; i++)
visualParams[i] = 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 // TODO: Check baked texture
Assert.AreEqual(visualParams, sp.Appearance.VisualParams); Assert.AreEqual(visualParams, sp.Appearance.VisualParams);
@ -102,7 +102,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
Primitive.TextureEntryFace eyesFace = bakedTextureEntry.CreateFace(eyesFaceIndex); Primitive.TextureEntryFace eyesFace = bakedTextureEntry.CreateFace(eyesFaceIndex);
eyesFace.TextureID = eyesTextureId; eyesFace.TextureID = eyesTextureId;
afm.SetAppearance(sp, bakedTextureEntry, visualParams); afm.SetAppearance(sp, bakedTextureEntry, visualParams, new WearableCacheItem[0]);
afm.SaveBakedTextures(userId); afm.SaveBakedTextures(userId);
// Dictionary<BakeType, Primitive.TextureEntryFace> bakedTextures = afm.GetBakedTextureFaces(userId); // Dictionary<BakeType, Primitive.TextureEntryFace> bakedTextures = afm.GetBakedTextureFaces(userId);

View File

@ -442,6 +442,19 @@ namespace OpenSim.Region.CoreModules.World.Land
return false; 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) public bool HasGroupAccess(UUID avatar)
{ {
if (LandData.GroupID != UUID.Zero && (LandData.Flags & (uint)ParcelFlags.UseAccessGroup) == (uint)ParcelFlags.UseAccessGroup) if (LandData.GroupID != UUID.Zero && (LandData.Flags & (uint)ParcelFlags.UseAccessGroup) == (uint)ParcelFlags.UseAccessGroup)

View File

@ -35,8 +35,8 @@ namespace OpenSim.Region.Framework.Interfaces
public interface IAvatarFactoryModule public interface IAvatarFactoryModule
{ {
void SetAppearance(IScenePresence sp, AvatarAppearance appearance); void SetAppearance(IScenePresence sp, AvatarAppearance appearance, WearableCacheItem[] cacheItems);
void SetAppearance(IScenePresence sp, Primitive.TextureEntry textureEntry, byte[] visualParams); void SetAppearance(IScenePresence sp, Primitive.TextureEntry textureEntry, byte[] visualParams, WearableCacheItem[] cacheItems);
/// <summary> /// <summary>
/// Send the appearance of an avatar to others in the scene. /// Send the appearance of an avatar to others in the scene.
@ -52,6 +52,8 @@ namespace OpenSim.Region.Framework.Interfaces
/// <returns>An empty list if this agent has no baked textures (e.g. because it's a child agent)</returns> /// <returns>An empty list if this agent has no baked textures (e.g. because it's a child agent)</returns>
Dictionary<BakeType, Primitive.TextureEntryFace> GetBakedTextureFaces(UUID agentId); Dictionary<BakeType, Primitive.TextureEntryFace> GetBakedTextureFaces(UUID agentId);
WearableCacheItem[] GetCachedItems(UUID agentId);
/// <summary> /// <summary>
/// Save the baked textures for the given agent permanently in the asset database. /// Save the baked textures for the given agent permanently in the asset database.
/// </summary> /// </summary>

View File

@ -923,6 +923,33 @@ namespace OpenSim.Region.Framework.Scenes
m_scene.EventManager.TriggerSetRootAgentScene(m_uuid, m_scene); 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) if (ParentID == 0)
{ {
// Moved this from SendInitialData to ensure that Appearance is initialized // 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); // m_log.DebugFormat("[SCENE PRESENCE]: Resetting move to target for {0}", Name);
MovingToTarget = false; 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 // 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. // 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) if (part == null)
return; 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) if (PhysicsActor != null)
m_sitAvatarHeight = PhysicsActor.Size.Z * 0.5f; m_sitAvatarHeight = PhysicsActor.Size.Z * 0.5f;
@ -2101,25 +2126,8 @@ namespace OpenSim.Region.Framework.Scenes
} }
else else
{ {
// if (Util.GetDistanceTo(AbsolutePosition, pos) <= 10) if (PhysicsSit(part,offset)) // physics engine
// { return;
// 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 (Util.GetDistanceTo(AbsolutePosition, pos) <= 10) 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); AbsolutePosition = pos + new Vector3(0.0f, 0.0f, m_sitAvatarHeight);
canSit = true; 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 (canSit)
{ {
if (PhysicsActor != null) if (PhysicsActor != null)
{ {
// We can remove the physicsActor until they stand up. // We can remove the physicsActor until they stand up.
RemoveFromPhysicalScene(); RemoveFromPhysicalScene();
} }
if (MovingToTarget)
ResetMoveToTarget();
Velocity = Vector3.Zero;
part.AddSittingAvatar(UUID); part.AddSittingAvatar(UUID);
cameraAtOffset = part.GetCameraAtOffset(); cameraAtOffset = part.GetCameraAtOffset();
@ -2179,14 +2187,6 @@ namespace OpenSim.Region.Framework.Scenes
m_requestedSitTargetID = part.LocalId; m_requestedSitTargetID = part.LocalId;
m_requestedSitTargetUUID = targetID; 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 else
{ {
@ -2196,28 +2196,87 @@ namespace OpenSim.Region.Framework.Scenes
SendSitResponse(targetID, offset, Quaternion.Identity); 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) 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; 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()); // m_log.InfoFormat("physsit {0} {1}", offset.ToString(),Orientation.ToString());
RemoveFromPhysicalScene();
if (MovingToTarget)
ResetMoveToTarget();
Velocity = Vector3.Zero;
part.AddSittingAvatar(UUID); part.AddSittingAvatar(UUID);
Vector3 cameraAtOffset = part.GetCameraAtOffset(); Vector3 cameraAtOffset = part.GetCameraAtOffset();
Vector3 cameraEyeOffset = part.GetCameraEyeOffset(); Vector3 cameraEyeOffset = part.GetCameraEyeOffset();
bool forceMouselook = part.GetForceMouselook(); bool forceMouselook = part.GetForceMouselook();
@ -2225,23 +2284,23 @@ namespace OpenSim.Region.Framework.Scenes
ControllingClient.SendSitResponse( ControllingClient.SendSitResponse(
part.UUID, offset, Orientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook); part.UUID, offset, Orientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook);
part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK); // not using autopilot
// assuming no autopilot in use
Velocity = Vector3.Zero;
RemoveFromPhysicalScene();
Rotation = Orientation; Rotation = Orientation;
m_pos = offset; m_pos = offset;
m_requestedSitTargetID = 0; // invalidate the viewer sit comand for now m_requestedSitTargetID = 0;
part.ParentGroup.AddAvatar(UUID); part.ParentGroup.AddAvatar(UUID);
ParentPart = part; ParentPart = part;
ParentID = part.LocalId; ParentID = part.LocalId;
if(status == 3)
Animator.TrySetMovementAnimation("SIT"); Animator.TrySetMovementAnimation("SIT_GROUND");
else
Animator.TrySetMovementAnimation("SIT");
SendAvatarDataToAllAgents(); SendAvatarDataToAllAgents();
part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK);
} }
@ -2260,6 +2319,7 @@ namespace OpenSim.Region.Framework.Scenes
return; return;
} }
if (part.SitTargetAvatar == UUID) if (part.SitTargetAvatar == UUID)
{ {
Vector3 sitTargetPos = part.SitTargetPosition; Vector3 sitTargetPos = part.SitTargetPosition;

View File

@ -911,7 +911,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
// Mimicking LLClientView which gets always set appearance from client. // Mimicking LLClientView which gets always set appearance from client.
AvatarAppearance appearance; AvatarAppearance appearance;
m_scene.GetAvatarAppearance(this, out 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) public void SendRegionHandshake(RegionInfo regionInfo, RegionHandshakeArgs args)

View File

@ -108,7 +108,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests
// ScenePresence.SendInitialData() to reset our entire appearance. // ScenePresence.SendInitialData() to reset our entire appearance.
m_scene.AssetService.Store(AssetHelpers.CreateNotecardAsset(originalFace8TextureId)); 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); UUID npcId = m_npcMod.CreateNPC("John", "Smith", new Vector3(128, 128, 30), UUID.Zero, true, m_scene, sp.Appearance);

View File

@ -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 RaycastCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance, Vector3 normal);
public delegate void RayCallback(List<ContactResult> list); public delegate void RayCallback(List<ContactResult> list);
public delegate void ProbeBoxCallback(List<ContactResult> list);
public delegate void ProbeSphereCallback(List<ContactResult> list);
public delegate void ProbePlaneCallback(List<ContactResult> list);
public delegate void SitAvatarCallback(int status, uint partID, Vector3 offset, Quaternion Orientation); public delegate void SitAvatarCallback(int status, uint partID, Vector3 offset, Quaternion Orientation);
public delegate void JointMoved(PhysicsJoint joint); public delegate void JointMoved(PhysicsJoint joint);
@ -56,6 +59,7 @@ namespace OpenSim.Region.Physics.Manager
volumedtc = 0x40, volumedtc = 0x40,
// ray cast colision control (may only work for meshs) // ray cast colision control (may only work for meshs)
ContactsUnImportant = 0x2000,
BackFaceCull = 0x4000, BackFaceCull = 0x4000,
ClosestHit = 0x8000, ClosestHit = 0x8000,
@ -351,9 +355,22 @@ namespace OpenSim.Region.Physics.Manager
return false; return false;
} }
public virtual void RaycastActor(PhysicsActor actor, Vector3 position, Vector3 direction, float length, RaycastCallback retMethod){} public virtual List<ContactResult> RaycastActor(PhysicsActor actor, Vector3 position, Vector3 direction, float length, int Count, RayFilterFlags flags)
public virtual void RaycastActor(PhysicsActor actor, Vector3 position, Vector3 direction, float length, int Count, RayCallback retMethod) { } {
public virtual List<ContactResult> RaycastActor(PhysicsActor actor, Vector3 position, Vector3 direction, float length, int Count) return new List<ContactResult>();
}
public virtual List<ContactResult> BoxProbe(Vector3 position, Vector3 size, Quaternion orientation, int Count, RayFilterFlags flags)
{
return new List<ContactResult>();
}
public virtual List<ContactResult> SphereProbe(Vector3 position, float radius, int Count, RayFilterFlags flags)
{
return new List<ContactResult>();
}
public virtual List<ContactResult> PlaneProbe(PhysicsActor actor, Vector4 plane, int Count, RayFilterFlags flags)
{ {
return new List<ContactResult>(); return new List<ContactResult>();
} }

View File

@ -715,7 +715,17 @@ namespace OpenSim.Region.Physics.OdePlugin
Vector3 off = _velocity; Vector3 off = _velocity;
float t = 0.5f * timeStep; float t = 0.5f * timeStep;
off = off * t; 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); d.GeomSetOffsetPosition(bbox, off.X, off.Y, off.Z);
off.X = 2.0f * (m_size.X + Math.Abs(off.X)); off.X = 2.0f * (m_size.X + Math.Abs(off.X));
off.Y = 2.0f * (m_size.Y + Math.Abs(off.Y)); off.Y = 2.0f * (m_size.Y + Math.Abs(off.Y));
off.Z = m_size.Z + 2.0f * Math.Abs(off.Z); 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.GeomSetCategoryBits(feetbox, (uint)m_collisionCategories);
d.GeomSetCollideBits(feetbox, (uint)m_collisionFlags); 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) if (CollisionEventsThisFrame != null)
{ {
CollisionEventsThisFrame.Clear(); lock (CollisionEventsThisFrame)
CollisionEventsThisFrame = null; {
CollisionEventsThisFrame.Clear();
CollisionEventsThisFrame = null;
}
} }
m_eventsubscription = 0; m_eventsubscription = 0;
} }
@ -1537,8 +1553,11 @@ namespace OpenSim.Region.Physics.OdePlugin
{ {
if (CollisionEventsThisFrame == null) if (CollisionEventsThisFrame == null)
CollisionEventsThisFrame = new CollisionEventUpdate(); CollisionEventsThisFrame = new CollisionEventUpdate();
CollisionEventsThisFrame.AddCollider(CollidedWith, contact); lock (CollisionEventsThisFrame)
_parent_scene.AddCollisionEventReporting(this); {
CollisionEventsThisFrame.AddCollider(CollidedWith, contact);
_parent_scene.AddCollisionEventReporting(this);
}
} }
public void SendCollisions() public void SendCollisions()
@ -1546,26 +1565,29 @@ namespace OpenSim.Region.Physics.OdePlugin
if (CollisionEventsThisFrame == null) if (CollisionEventsThisFrame == null)
return; return;
if (m_cureventsubscription < m_eventsubscription) lock (CollisionEventsThisFrame)
return;
m_cureventsubscription = 0;
int ncolisions = CollisionEventsThisFrame.m_objCollisionList.Count;
if (!SentEmptyCollisionsEvent || ncolisions > 0)
{ {
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; base.SendCollisionUpdate(CollisionEventsThisFrame);
_parent_scene.RemoveCollisionEventReporting(this);
} if (ncolisions == 0)
else {
{ SentEmptyCollisionsEvent = true;
SentEmptyCollisionsEvent = false; _parent_scene.RemoveCollisionEventReporting(this);
CollisionEventsThisFrame.Clear(); }
else
{
SentEmptyCollisionsEvent = false;
CollisionEventsThisFrame.Clear();
}
} }
} }
} }

View File

@ -56,8 +56,11 @@ namespace OpenSim.Region.Physics.OdePlugin
private OdeScene m_scene; private OdeScene m_scene;
IntPtr ray; // the ray. we only need one for our lifetime 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 DefaultMaxCount = 25;
private const int MaxTimePerCallMS = 30; private const int MaxTimePerCallMS = 30;
@ -65,6 +68,7 @@ namespace OpenSim.Region.Physics.OdePlugin
/// ODE near callback delegate /// ODE near callback delegate
/// </summary> /// </summary>
private d.NearCallback nearCallback; private d.NearCallback nearCallback;
private d.NearCallback nearProbeCallback;
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private List<ContactResult> m_contactResults = new List<ContactResult>(); private List<ContactResult> m_contactResults = new List<ContactResult>();
private RayFilterFlags CurrentRayFilter; private RayFilterFlags CurrentRayFilter;
@ -74,155 +78,21 @@ namespace OpenSim.Region.Physics.OdePlugin
{ {
m_scene = pScene; m_scene = pScene;
nearCallback = near; nearCallback = near;
nearProbeCallback = nearProbe;
ray = d.CreateRay(IntPtr.Zero, 1.0f); 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);
} }
/// <summary> public void QueueRequest(ODERayRequest req)
/// Queues request for a raycast to all world
/// </summary>
/// <param name="position">Origin of Ray</param>
/// <param name="direction">Ray direction</param>
/// <param name="length">Ray length</param>
/// <param name="retMethod">Return method to send the results</param>
public void QueueRequest(Vector3 position, Vector3 direction, float length, RayCallback retMethod)
{ {
ODERayRequest req = new ODERayRequest(); if (req.Count == 0)
req.geom = IntPtr.Zero; req.Count = DefaultMaxCount;
req.callbackMethod = retMethod;
req.Count = DefaultMaxCount;
req.length = length;
req.Normal = direction;
req.Origin = position;
req.filter = RayFilterFlags.AllPrims;
m_PendingRequests.Enqueue(req);
}
/// <summary>
/// Queues request for a raycast to particular part
/// </summary>
/// <param name="position">Origin of Ray</param>
/// <param name="direction">Ray direction</param>
/// <param name="length">Ray length</param>
/// <param name="retMethod">Return method to send the results</param>
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);
}
/// <summary>
/// Queues a raycast
/// </summary>
/// <param name="position">Origin of Ray</param>
/// <param name="direction">Ray normal</param>
/// <param name="length">Ray length</param>
/// <param name="count"></param>
/// <param name="retMethod">Return method to send the results</param>
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;
m_PendingRequests.Enqueue(req); m_PendingRequests.Enqueue(req);
} }
@ -258,21 +128,64 @@ namespace OpenSim.Region.Physics.OdePlugin
CurrentRayFilter = req.filter; CurrentRayFilter = req.filter;
CurrentMaxCount = req.Count; CurrentMaxCount = req.Count;
CollisionContactGeomsPerTest = req.Count & 0xffff;
closestHit = ((CurrentRayFilter & RayFilterFlags.ClosestHit) == 0 ? 0 : 1); closestHit = ((CurrentRayFilter & RayFilterFlags.ClosestHit) == 0 ? 0 : 1);
backfacecull = ((CurrentRayFilter & RayFilterFlags.BackFaceCull) == 0 ? 0 : 1); backfacecull = ((CurrentRayFilter & RayFilterFlags.BackFaceCull) == 0 ? 0 : 1);
d.GeomRaySetLength(ray, req.length); if (req.callbackMethod is ProbeBoxCallback)
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); if (CollisionContactGeomsPerTest > 80)
d.GeomRaySetClosestHit(ray, closestHit); 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) d.GeomSphereSetRadius(Sphere, req.length);
// if we only want one get only one per colision pair saving memory d.GeomSetPosition(Sphere, req.Origin.X, req.Origin.Y, req.Origin.Z);
CurrentRayFilter |= RayFilterFlags.ClosestHit; }
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) if (req.geom == IntPtr.Zero)
{ {
// translate ray filter to colision flags // translate ray filter to Collision flags
catflags = 0; catflags = 0;
if ((CurrentRayFilter & RayFilterFlags.volumedtc) != 0) if ((CurrentRayFilter & RayFilterFlags.volumedtc) != 0)
catflags |= CollisionCategories.VolumeDtc; catflags |= CollisionCategories.VolumeDtc;
@ -289,15 +202,48 @@ namespace OpenSim.Region.Physics.OdePlugin
if (catflags != 0) if (catflags != 0)
{ {
d.GeomSetCollideBits(ray, (uint)catflags); if (req.callbackMethod is ProbeBoxCallback)
doSpaceRay(req); {
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 else
{ {
// if we select a geom don't use filters // 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<ContactResult> cresult = new List<ContactResult>(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<ContactResult> cresult = new List<ContactResult>(m_contactResults.Count);
lock (m_PendingRequests)
{
cresult.AddRange(m_contactResults);
m_contactResults.Clear();
}
((ProbePlaneCallback)req.callbackMethod)(cresult);
}
/// <summary> /// <summary>
/// Method that actually initiates the raycast with a geom /// Method that actually initiates the raycast with a geom
/// </summary> /// </summary>
@ -436,7 +437,7 @@ namespace OpenSim.Region.Physics.OdePlugin
private bool GetCurContactGeom(int index, ref d.ContactGeom newcontactgeom) private bool GetCurContactGeom(int index, ref d.ContactGeom newcontactgeom)
{ {
IntPtr ContactgeomsArray = m_scene.ContactgeomsArray; IntPtr ContactgeomsArray = m_scene.ContactgeomsArray;
if (ContactgeomsArray == IntPtr.Zero || index >= ColisionContactGeomsPerTest) if (ContactgeomsArray == IntPtr.Zero || index >= CollisionContactGeomsPerTest)
return false; return false;
IntPtr contactptr = new IntPtr(ContactgeomsArray.ToInt64() + (Int64)(index * d.ContactGeom.unmanagedSizeOf)); IntPtr contactptr = new IntPtr(ContactgeomsArray.ToInt64() + (Int64)(index * d.ContactGeom.unmanagedSizeOf));
@ -469,7 +470,157 @@ namespace OpenSim.Region.Physics.OdePlugin
int count = 0; int count = 0;
try 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) catch (Exception e)
{ {
@ -481,82 +632,58 @@ namespace OpenSim.Region.Physics.OdePlugin
return; return;
uint ID = 0; 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) if (p1 == 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;
*/
return; return;
}
else switch (p1.PhysicsActorType)
{ {
switch (p2.PhysicsActorType) case (int)ActorTypes.Prim:
{
case (int)ActorTypes.Prim:
RayFilterFlags thisFlags; RayFilterFlags thisFlags;
if (p2.IsPhysical) if (p1.IsPhysical)
thisFlags = RayFilterFlags.physical; thisFlags = RayFilterFlags.physical;
else else
thisFlags = RayFilterFlags.nonphysical; thisFlags = RayFilterFlags.nonphysical;
if (p2.Phantom) if (p1.Phantom)
thisFlags |= RayFilterFlags.phantom; thisFlags |= RayFilterFlags.phantom;
if (p2.IsVolumeDtc) if (p1.IsVolumeDtc)
thisFlags |= RayFilterFlags.volumedtc; thisFlags |= RayFilterFlags.volumedtc;
if ((thisFlags & CurrentRayFilter) == 0) if ((thisFlags & CurrentRayFilter) == 0)
return; return;
ID = ((OdePrim)p2).LocalID; ID = ((OdePrim)p1).LocalID;
break; break;
case (int)ActorTypes.Agent: case (int)ActorTypes.Agent:
if ((CurrentRayFilter & RayFilterFlags.agent) == 0) if ((CurrentRayFilter & RayFilterFlags.agent) == 0)
return; return;
else else
ID = ((OdeCharacter)p2).LocalID; ID = ((OdeCharacter)p1).LocalID;
break; break;
case (int)ActorTypes.Ground: case (int)ActorTypes.Ground:
if ((CurrentRayFilter & RayFilterFlags.land) == 0) if ((CurrentRayFilter & RayFilterFlags.land) == 0)
return; return;
break; break;
case (int)ActorTypes.Water: case (int)ActorTypes.Water:
if ((CurrentRayFilter & RayFilterFlags.water) == 0) if ((CurrentRayFilter & RayFilterFlags.water) == 0)
return; return;
break; break;
default: default:
break; break;
}
} }
d.ContactGeom curcontact = new d.ContactGeom(); d.ContactGeom curcontact = new d.ContactGeom();
@ -624,6 +751,21 @@ namespace OpenSim.Region.Physics.OdePlugin
d.GeomDestroy(ray); d.GeomDestroy(ray);
ray = IntPtr.Zero; 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 float length;
public object callbackMethod; public object callbackMethod;
public RayFilterFlags filter; public RayFilterFlags filter;
public Quaternion orientation;
} }
} }

View File

@ -52,6 +52,21 @@ namespace OpenSim.Region.Physics.OdePlugin
} }
private static Vector3 SitAjust = new Vector3(0, 0, 0.4f); 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) 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; IntPtr geom = ((OdePrim)actor).prim_geom;
d.Vector3 dtmp = d.GeomGetPosition(geom); Vector3 geopos = d.GeomGetPositionOMV(geom);
Vector3 geopos; Quaternion geomOri = d.GeomGetQuaternionOMV(geom);
geopos.X = dtmp.X; Quaternion geomInvOri = Quaternion.Conjugate(geomOri);
geopos.Y = dtmp.Y;
geopos.Z = dtmp.Z;
Quaternion ori = Quaternion.Identity;
d.AABB aabb; Vector3 rayDir = geopos + offset - avCameraPosition;
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 target = geopos + offset;
Vector3 rayDir = target - avCameraPosition;
float raylen = rayDir.Length(); float raylen = rayDir.Length();
if (raylen < 0.001f)
{
PhysicsSitResponse(-1, actor.LocalID, offset, Quaternion.Identity);
return;
}
float t = 1 / raylen; float t = 1 / raylen;
rayDir.X *= t; rayDir.X *= t;
rayDir.Y *= t; rayDir.Y *= t;
rayDir.Z *= t; rayDir.Z *= t;
raylen += 0.5f; raylen += 30f; // focal point may be far
List<ContactResult> rayResults; List<ContactResult> rayResults;
rayResults = m_scene.RaycastActor(actor, avCameraPosition, rayDir , raylen, 1); rayResults = m_scene.RaycastActor(actor, avCameraPosition, rayDir, raylen, 1, RaySitFlags);
if (rayResults.Count == 0 || rayResults[0].ConsumerID != actor.LocalID) 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); offset = new Vector3(avOffset.X, 0, aabb.MaxZ + avOffset.Z - geopos.Z);
ori = geomInvOri; ori = geomInvOri;
offset *= geomInvOri; offset *= geomInvOri;
PhysicsSitResponse(1, actor.LocalID, offset, ori); PhysicsSitResponse(1, actor.LocalID, offset, ori);
*/
PhysicsSitResponse(0, actor.LocalID, offset, ori);
return; return;
} }
int status = 1;
offset = rayResults[0].Pos - geopos; offset = rayResults[0].Pos - geopos;
double ang;
float s;
float c;
d.GeomClassID geoclass = d.GeomGetClass(geom); d.GeomClassID geoclass = d.GeomGetClass(geom);
if (geoclass == d.GeomClassID.SphereClass) if (geoclass == d.GeomClassID.SphereClass)
{ {
float r = d.GeomSphereGetRadius(geom); float r = d.GeomSphereGetRadius(geom);
offset.Normalize(); offset.Normalize();
offset *= r; offset *= r;
ang = Math.Atan2(offset.Y, offset.X); RotAroundZ(offset.X, offset.Y, ref ori);
ang *= 0.5d;
s = (float)Math.Sin(ang);
c = (float)Math.Cos(ang);
ori = new Quaternion(0, 0, s, c);
if (r < 0.4f) if (r < 0.4f)
{ {
offset = new Vector3(0, 0, r); offset = new Vector3(0, 0, r);
} }
else if (offset.Z < 0.4f) else
{ {
t = offset.Z; if (offset.Z < 0.4f)
float rsq = r * r; {
t = offset.Z;
float rsq = r * r;
t = 1.0f / (rsq - t * t); t = 1.0f / (rsq - t * t);
offset.X *= t; offset.X *= t;
offset.Y *= t; offset.Y *= t;
offset.Z = 0.4f; offset.Z = 0.4f;
t = rsq - 0.16f; t = rsq - 0.16f;
offset.X *= t; offset.X *= t;
offset.Y *= 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; offset += avOffset * ori;
@ -152,26 +161,189 @@ namespace OpenSim.Region.Physics.OdePlugin
ori = geomInvOri * ori; ori = geomInvOri * ori;
offset *= geomInvOri; offset *= geomInvOri;
PhysicsSitResponse(1, actor.LocalID, offset, ori); PhysicsSitResponse(status, actor.LocalID, offset, ori);
return; return;
} }
Vector3 norm = rayResults[0].Normal; Vector3 norm = rayResults[0].Normal;
if (norm.Z < 0) if (norm.Z < -0.4f)
{ {
PhysicsSitResponse(0, actor.LocalID, offset, Quaternion.Identity); PhysicsSitResponse(0, actor.LocalID, offset, Quaternion.Identity);
return; 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; ori = geomInvOri * ori;
offset *= geomInvOri; offset *= geomInvOri;

View File

@ -44,7 +44,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using System; using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Security; using System.Security;
using OMV = OpenMetaverse;
namespace OdeAPI namespace OdeAPI
{ {
//#if dDOUBLE //#if dDOUBLE
@ -925,9 +925,20 @@ namespace OdeAPI
{ {
unsafe { return *(GeomGetPositionUnsafe(geom)); } 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] [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] [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetQuaternion"), SuppressUnmanagedCodeSecurity]
public static extern void GeomCopyQuaternion(IntPtr geom, out dReal X); public static extern void GeomCopyQuaternion(IntPtr geom, out dReal X);

View File

@ -2579,7 +2579,16 @@ namespace OpenSim.Region.Physics.OdePlugin
{ {
if (retMethod != null) 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) 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<ContactResult> RaycastWorld(Vector3 position, Vector3 direction, float length, int Count) public override List<ContactResult> RaycastWorld(Vector3 position, Vector3 direction, float length, int Count)
{ {
ContactResult[] ourResults = null; List<ContactResult> ourresults = new List<ContactResult>();
object SyncObject = new object();
RayCallback retMethod = delegate(List<ContactResult> results) RayCallback retMethod = delegate(List<ContactResult> results)
{ {
ourResults = new ContactResult[results.Count]; lock (SyncObject)
results.CopyTo(ourResults, 0); {
ourresults = results;
Monitor.PulseAll(SyncObject);
}
}; };
int waitTime = 0;
m_rayCastManager.QueueRequest(position, direction, length, Count, retMethod); ODERayRequest req = new ODERayRequest();
while (ourResults == null && waitTime < 1000) 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); m_rayCastManager.QueueRequest(req);
waitTime++; if (!Monitor.Wait(SyncObject, 500))
return null;
else
return ourresults;
} }
if (ourResults == null)
return new List<ContactResult>();
return new List<ContactResult>(ourResults);
} }
public override bool SuportsRaycastWorldFiltered() 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) lock (SyncObject)
{ {
m_rayCastManager.QueueRequest(position, direction, length, Count,filter, retMethod); m_rayCastManager.QueueRequest(req);
if (!Monitor.Wait(SyncObject, 500)) if (!Monitor.Wait(SyncObject, 500))
return null; return null;
else 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<ContactResult> RaycastActor(PhysicsActor actor, Vector3 position, Vector3 direction, float length, int Count, RayFilterFlags flags)
{ {
if (retMethod != null && actor !=null) if (actor == null)
return new List<ContactResult>();
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<ContactResult>();
if (geom == IntPtr.Zero)
return new List<ContactResult>();
List<ContactResult> ourResults = null;
object SyncObject = new object();
RayCallback retMethod = delegate(List<ContactResult> results)
{ {
IntPtr geom; lock (SyncObject)
if (actor is OdePrim) {
geom = ((OdePrim)actor).prim_geom; ourResults = results;
else if (actor is OdeCharacter) Monitor.PulseAll(SyncObject);
geom = ((OdePrim)actor).prim_geom; }
else };
return;
if (geom == IntPtr.Zero) ODERayRequest req = new ODERayRequest();
return; req.geom = geom;
m_rayCastManager.QueueRequest(geom, position, direction, length, retMethod); 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<ContactResult>();
} }
if (ourResults == null)
return new List<ContactResult>();
return ourResults;
} }
public override void RaycastActor(PhysicsActor actor, Vector3 position, Vector3 direction, float length, int Count, RayCallback retMethod) public override List<ContactResult> BoxProbe(Vector3 position, Vector3 size, Quaternion orientation, int Count, RayFilterFlags flags)
{ {
if (retMethod != null && actor != null) List<ContactResult> ourResults = null;
{ object SyncObject = new object();
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, Count, retMethod); ProbeBoxCallback retMethod = delegate(List<ContactResult> 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<ContactResult>();
} }
if (ourResults == null)
return new List<ContactResult>();
return ourResults;
} }
// don't like this public override List<ContactResult> SphereProbe(Vector3 position, float radius, int Count, RayFilterFlags flags)
public override List<ContactResult> RaycastActor(PhysicsActor actor, Vector3 position, Vector3 direction, float length, int Count)
{ {
List<ContactResult> ourResults = null;
object SyncObject = new object();
ProbeSphereCallback retMethod = delegate(List<ContactResult> 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<ContactResult>();
}
if (ourResults == null)
return new List<ContactResult>();
return ourResults;
}
public override List<ContactResult> PlaneProbe(PhysicsActor actor, Vector4 plane, int Count, RayFilterFlags flags)
{
IntPtr geom = IntPtr.Zero;;
if (actor != null) if (actor != null)
{ {
IntPtr geom;
if (actor is OdePrim) if (actor is OdePrim)
geom = ((OdePrim)actor).prim_geom; geom = ((OdePrim)actor).prim_geom;
else if (actor is OdeCharacter) else if (actor is OdeCharacter)
geom = ((OdePrim)actor).prim_geom; geom = ((OdePrim)actor).prim_geom;
else
return new List<ContactResult>();
if (geom == IntPtr.Zero)
return new List<ContactResult>();
ContactResult[] ourResults = null;
RayCallback retMethod = delegate(List<ContactResult> 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<ContactResult>();
return new List<ContactResult>(ourResults);
} }
return new List<ContactResult>();
List<ContactResult> ourResults = null;
object SyncObject = new object();
ProbePlaneCallback retMethod = delegate(List<ContactResult> 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<ContactResult>();
}
if (ourResults == null)
return new List<ContactResult>();
return ourResults;
} }
public override int SitAvatar(PhysicsActor actor, Vector3 AbsolutePosition, Vector3 CameraPosition, Vector3 offset, Vector3 AvatarSize, SitAvatarCallback PhysicsSitResponse) public override int SitAvatar(PhysicsActor actor, Vector3 AbsolutePosition, Vector3 CameraPosition, Vector3 offset, Vector3 AvatarSize, SitAvatarCallback PhysicsSitResponse)

View File

@ -144,7 +144,7 @@ namespace OpenSim.Tests.Performance
// ScenePresence.SendInitialData() to reset our entire appearance. // ScenePresence.SendInitialData() to reset our entire appearance.
scene.AssetService.Store(AssetHelpers.CreateNotecardAsset(originalFace8TextureId)); scene.AssetService.Store(AssetHelpers.CreateNotecardAsset(originalFace8TextureId));
afm.SetAppearance(sp, originalTe, null); afm.SetAppearance(sp, originalTe, null, new WearableCacheItem[0]);
INPCModule npcModule = scene.RequestModuleInterface<INPCModule>(); INPCModule npcModule = scene.RequestModuleInterface<INPCModule>();