Merge branch 'master' of ssh://opensimulator.org/var/git/opensim

cpu-performance
Diva Canto 2013-05-28 20:59:54 -07:00
commit 233b9ec4d7
39 changed files with 834 additions and 348 deletions

View File

@ -766,7 +766,7 @@ namespace OpenSim.Groups
remoteClient.SendCreateGroupReply(UUID.Zero, false, "Insufficient funds to create a group."); remoteClient.SendCreateGroupReply(UUID.Zero, false, "Insufficient funds to create a group.");
return UUID.Zero; return UUID.Zero;
} }
money.ApplyCharge(remoteClient.AgentId, money.GroupCreationCharge, "Group Creation"); money.ApplyCharge(remoteClient.AgentId, money.GroupCreationCharge, MoneyTransactionType.GroupCreate);
} }
string reason = string.Empty; string reason = string.Empty;
UUID groupID = m_groupData.CreateGroup(remoteClient.AgentId, name, charter, showInList, insigniaID, membershipFee, openEnrollment, UUID groupID = m_groupData.CreateGroup(remoteClient.AgentId, name, charter, showInList, insigniaID, membershipFee, openEnrollment,

View File

@ -53,6 +53,7 @@ namespace OpenSim.Framework
protected AvatarWearable[] m_wearables; protected AvatarWearable[] m_wearables;
protected Dictionary<int, List<AvatarAttachment>> m_attachments; protected Dictionary<int, List<AvatarAttachment>> m_attachments;
protected float m_avatarHeight = 0; protected float m_avatarHeight = 0;
protected UUID[] m_texturehashes;
public virtual int Serial public virtual int Serial
{ {
@ -98,6 +99,8 @@ namespace OpenSim.Framework
SetDefaultParams(); SetDefaultParams();
SetHeight(); SetHeight();
m_attachments = new Dictionary<int, List<AvatarAttachment>>(); m_attachments = new Dictionary<int, List<AvatarAttachment>>();
ResetTextureHashes();
} }
public AvatarAppearance(OSDMap map) public AvatarAppearance(OSDMap map)
@ -108,32 +111,6 @@ namespace OpenSim.Framework
SetHeight(); SetHeight();
} }
public AvatarAppearance(AvatarWearable[] wearables, Primitive.TextureEntry textureEntry, byte[] visualParams)
{
// m_log.WarnFormat("[AVATAR APPEARANCE] create initialized appearance");
m_serial = 0;
if (wearables != null)
m_wearables = wearables;
else
SetDefaultWearables();
if (textureEntry != null)
m_texture = textureEntry;
else
SetDefaultTexture();
if (visualParams != null)
m_visualparams = visualParams;
else
SetDefaultParams();
SetHeight();
m_attachments = new Dictionary<int, List<AvatarAttachment>>();
}
public AvatarAppearance(AvatarAppearance appearance) : this(appearance, true) public AvatarAppearance(AvatarAppearance appearance) : this(appearance, true)
{ {
} }
@ -151,6 +128,8 @@ namespace OpenSim.Framework
SetHeight(); SetHeight();
m_attachments = new Dictionary<int, List<AvatarAttachment>>(); m_attachments = new Dictionary<int, List<AvatarAttachment>>();
ResetTextureHashes();
return; return;
} }
@ -166,6 +145,10 @@ namespace OpenSim.Framework
SetWearable(i,appearance.Wearables[i]); SetWearable(i,appearance.Wearables[i]);
} }
m_texturehashes = new UUID[AvatarAppearance.TEXTURE_COUNT];
for (int i = 0; i < AvatarAppearance.TEXTURE_COUNT; i++)
m_texturehashes[i] = new UUID(appearance.m_texturehashes[i]);
m_texture = null; m_texture = null;
if (appearance.Texture != null) if (appearance.Texture != null)
{ {
@ -200,6 +183,37 @@ namespace OpenSim.Framework
} }
} }
public void ResetTextureHashes()
{
m_texturehashes = new UUID[AvatarAppearance.TEXTURE_COUNT];
for (uint i = 0; i < AvatarAppearance.TEXTURE_COUNT; i++)
m_texturehashes[i] = UUID.Zero;
}
public UUID GetTextureHash(int textureIndex)
{
return m_texturehashes[NormalizeBakedTextureIndex(textureIndex)];
}
public void SetTextureHash(int textureIndex, UUID textureHash)
{
m_texturehashes[NormalizeBakedTextureIndex(textureIndex)] = new UUID(textureHash);
}
/// <summary>
/// Normalizes the texture index to the actual bake index, this is done to
/// accommodate older viewers that send the BAKE_INDICES index rather than
/// the actual texture index
/// </summary>
private int NormalizeBakedTextureIndex(int textureIndex)
{
// Earlier viewer send the index into the baked index array, just trying to be careful here
if (textureIndex < BAKE_INDICES.Length)
return BAKE_INDICES[textureIndex];
return textureIndex;
}
public void ClearWearables() public void ClearWearables()
{ {
m_wearables = new AvatarWearable[AvatarWearable.MAX_WEARABLES]; m_wearables = new AvatarWearable[AvatarWearable.MAX_WEARABLES];
@ -223,12 +237,7 @@ namespace OpenSim.Framework
m_serial = 0; m_serial = 0;
SetDefaultTexture(); SetDefaultTexture();
ResetTextureHashes();
//for (int i = 0; i < BAKE_INDICES.Length; i++)
// {
// int idx = BAKE_INDICES[i];
// m_texture.FaceTextures[idx].TextureID = UUID.Zero;
// }
} }
protected virtual void SetDefaultParams() protected virtual void SetDefaultParams()
@ -598,6 +607,12 @@ namespace OpenSim.Framework
data["serial"] = OSD.FromInteger(m_serial); data["serial"] = OSD.FromInteger(m_serial);
data["height"] = OSD.FromReal(m_avatarHeight); data["height"] = OSD.FromReal(m_avatarHeight);
// Hashes
OSDArray hashes = new OSDArray(AvatarAppearance.TEXTURE_COUNT);
for (uint i = 0; i < AvatarAppearance.TEXTURE_COUNT; i++)
hashes.Add(OSD.FromUUID(m_texturehashes[i]));
data["hashes"] = hashes;
// Wearables // Wearables
OSDArray wears = new OSDArray(AvatarWearable.MAX_WEARABLES); OSDArray wears = new OSDArray(AvatarWearable.MAX_WEARABLES);
for (int i = 0; i < AvatarWearable.MAX_WEARABLES; i++) for (int i = 0; i < AvatarWearable.MAX_WEARABLES; i++)
@ -642,6 +657,25 @@ namespace OpenSim.Framework
try try
{ {
// Hashes
m_texturehashes = new UUID[AvatarAppearance.TEXTURE_COUNT];
if ((data != null) && (data["hashes"] != null) && (data["hashes"]).Type == OSDType.Array)
{
OSDArray hashes = (OSDArray)(data["hashes"]);
for (int i = 0; i < AvatarAppearance.TEXTURE_COUNT; i++)
{
UUID hashID = UUID.Zero;
if (i < hashes.Count && hashes[i] != null)
hashID = hashes[i].AsUUID();
m_texturehashes[i] = hashID;
}
}
else
{
for (uint i = 0; i < AvatarAppearance.TEXTURE_COUNT; i++)
m_texturehashes[i] = UUID.Zero;
}
// Wearables // Wearables
SetDefaultWearables(); SetDefaultWearables();
if ((data != null) && (data["wearables"] != null) && (data["wearables"]).Type == OSDType.Array) if ((data != null) && (data["wearables"] != null) && (data["wearables"]).Type == OSDType.Array)

View File

@ -66,7 +66,7 @@ namespace OpenSim.Framework
public delegate void CachedTextureRequest(IClientAPI remoteClient, int serial, List<CachedTextureRequestArg> cachedTextureRequest); public delegate void CachedTextureRequest(IClientAPI remoteClient, int serial, List<CachedTextureRequestArg> cachedTextureRequest);
public delegate void SetAppearance(IClientAPI remoteClient, Primitive.TextureEntry textureEntry, byte[] visualParams); public delegate void SetAppearance(IClientAPI remoteClient, Primitive.TextureEntry textureEntry, byte[] visualParams, List<CachedTextureRequestArg> cachedTextureData);
public delegate void StartAnim(IClientAPI remoteClient, UUID animID); public delegate void StartAnim(IClientAPI remoteClient, UUID animID);
@ -1159,7 +1159,8 @@ namespace OpenSim.Framework
void SendTeleportStart(uint flags); void SendTeleportStart(uint flags);
void SendTeleportProgress(uint flags, string message); void SendTeleportProgress(uint flags, string message);
void SendMoneyBalance(UUID transaction, bool success, byte[] description, int balance); void SendMoneyBalance(UUID transaction, bool success, byte[] description, int balance, int transactionType, UUID sourceID, bool sourceIsGroup, UUID destID, bool destIsGroup, int amount, string item);
void SendPayPrice(UUID objectID, int[] payPrice); void SendPayPrice(UUID objectID, int[] payPrice);
void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations); void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations);
@ -1254,8 +1255,6 @@ namespace OpenSim.Framework
void SendDialog(string objectname, UUID objectID, UUID ownerID, string ownerFirstName, string ownerLastName, string msg, UUID textureID, int ch, void SendDialog(string objectname, UUID objectID, UUID ownerID, string ownerFirstName, string ownerLastName, string msg, UUID textureID, int ch,
string[] buttonlabels); string[] buttonlabels);
bool AddMoney(int debit);
/// <summary> /// <summary>
/// Update the client as to where the sun is currently located. /// Update the client as to where the sun is currently located.
/// </summary> /// </summary>

View File

@ -38,7 +38,8 @@ namespace OpenSim.Framework
int GetBalance(UUID agentID); int GetBalance(UUID agentID);
bool UploadCovered(UUID agentID, int amount); bool UploadCovered(UUID agentID, int amount);
bool AmountCovered(UUID agentID, int amount); bool AmountCovered(UUID agentID, int amount);
void ApplyCharge(UUID agentID, int amount, string text); void ApplyCharge(UUID agentID, int amount, MoneyTransactionType type);
void ApplyCharge(UUID agentID, int amount, MoneyTransactionType type, string extraData);
void ApplyUploadCharge(UUID agentID, int amount, string text); void ApplyUploadCharge(UUID agentID, int amount, string text);
int UploadCharge { get; } int UploadCharge { get; }

View File

@ -2136,7 +2136,7 @@ namespace OpenSim.Framework
/// <param name="secret">the secret part</param> /// <param name="secret">the secret part</param>
public static bool ParseUniversalUserIdentifier(string value, out UUID uuid, out string url, out string firstname, out string lastname, out string secret) public static bool ParseUniversalUserIdentifier(string value, out UUID uuid, out string url, out string firstname, out string lastname, out string secret)
{ {
uuid = UUID.Zero; url = string.Empty; firstname = "Unknown"; lastname = "User"; secret = string.Empty; uuid = UUID.Zero; url = string.Empty; firstname = "Unknown"; lastname = "UserUPUUI"; secret = string.Empty;
string[] parts = value.Split(';'); string[] parts = value.Split(';');
if (parts.Length >= 1) if (parts.Length >= 1)

View File

@ -345,7 +345,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// protected HashSet<uint> m_attachmentsSent; // protected HashSet<uint> m_attachmentsSent;
private int m_moneyBalance;
private int m_animationSequenceNumber = 1; private int m_animationSequenceNumber = 1;
private bool m_SendLogoutPacketWhenClosing = true; private bool m_SendLogoutPacketWhenClosing = true;
@ -420,7 +419,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
public string Name { get { return FirstName + " " + LastName; } } public string Name { get { return FirstName + " " + LastName; } }
public uint CircuitCode { get { return m_circuitCode; } } public uint CircuitCode { get { return m_circuitCode; } }
public int MoneyBalance { get { return m_moneyBalance; } }
public int NextAnimationSequenceNumber { get { return m_animationSequenceNumber++; } } public int NextAnimationSequenceNumber { get { return m_animationSequenceNumber++; } }
/// <summary> /// <summary>
@ -483,7 +481,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
m_firstName = sessionInfo.LoginInfo.First; m_firstName = sessionInfo.LoginInfo.First;
m_lastName = sessionInfo.LoginInfo.Last; m_lastName = sessionInfo.LoginInfo.Last;
m_startpos = sessionInfo.LoginInfo.StartPos; m_startpos = sessionInfo.LoginInfo.StartPos;
m_moneyBalance = 1000;
m_udpServer = udpServer; m_udpServer = udpServer;
m_udpClient = udpClient; m_udpClient = udpClient;
@ -1538,7 +1535,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
OutPacket(tpProgress, ThrottleOutPacketType.Unknown); OutPacket(tpProgress, ThrottleOutPacketType.Unknown);
} }
public void SendMoneyBalance(UUID transaction, bool success, byte[] description, int balance) public void SendMoneyBalance(UUID transaction, bool success, byte[] description, int balance, int transactionType, UUID sourceID, bool sourceIsGroup, UUID destID, bool destIsGroup, int amount, string item)
{ {
MoneyBalanceReplyPacket money = (MoneyBalanceReplyPacket)PacketPool.Instance.GetPacket(PacketType.MoneyBalanceReply); MoneyBalanceReplyPacket money = (MoneyBalanceReplyPacket)PacketPool.Instance.GetPacket(PacketType.MoneyBalanceReply);
money.MoneyData.AgentID = AgentId; money.MoneyData.AgentID = AgentId;
@ -1546,7 +1543,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
money.MoneyData.TransactionSuccess = success; money.MoneyData.TransactionSuccess = success;
money.MoneyData.Description = description; money.MoneyData.Description = description;
money.MoneyData.MoneyBalance = balance; money.MoneyData.MoneyBalance = balance;
money.TransactionInfo.ItemDescription = Util.StringToBytes256("NONE"); money.TransactionInfo.TransactionType = transactionType;
money.TransactionInfo.SourceID = sourceID;
money.TransactionInfo.IsSourceGroup = sourceIsGroup;
money.TransactionInfo.DestID = destID;
money.TransactionInfo.IsDestGroup = destIsGroup;
money.TransactionInfo.Amount = amount;
money.TransactionInfo.ItemDescription = Util.StringToBytes256(item);
OutPacket(money, ThrottleOutPacketType.Task); OutPacket(money, ThrottleOutPacketType.Task);
} }
@ -2279,6 +2283,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// <returns></returns> /// <returns></returns>
public AgentAlertMessagePacket BuildAgentAlertPacket(string message, bool modal) public AgentAlertMessagePacket BuildAgentAlertPacket(string message, bool modal)
{ {
// Prepend a slash to make the message come up in the top right
// again.
// Allow special formats to be sent from aware modules.
if (!modal && !message.StartsWith("ALERT: ") && !message.StartsWith("NOTIFY: ") && message != "Home position set." && message != "You died and have been teleported to your home location")
message = "/" + message;
AgentAlertMessagePacket alertPack = (AgentAlertMessagePacket)PacketPool.Instance.GetPacket(PacketType.AgentAlertMessage); AgentAlertMessagePacket alertPack = (AgentAlertMessagePacket)PacketPool.Instance.GetPacket(PacketType.AgentAlertMessage);
alertPack.AgentData.AgentID = AgentId; alertPack.AgentData.AgentID = AgentId;
alertPack.AlertData.Message = Util.StringToBytes256(message); alertPack.AlertData.Message = Util.StringToBytes256(message);
@ -6214,7 +6223,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
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);
handlerSetAppearance(sender, te, visualparams); List<CachedTextureRequestArg> hashes = new List<CachedTextureRequestArg>();
for (int i = 0; i < appear.WearableData.Length; i++)
{
CachedTextureRequestArg arg = new CachedTextureRequestArg();
arg.BakedTextureIndex = appear.WearableData[i].TextureIndex;
arg.WearableHashID = appear.WearableData[i].CacheID;
hashes.Add(arg);
}
handlerSetAppearance(sender, te, visualparams, hashes);
} }
catch (Exception e) catch (Exception e)
{ {
@ -11487,12 +11505,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
requestArgs.Add(arg); requestArgs.Add(arg);
} }
CachedTextureRequest handlerCachedTextureRequest = OnCachedTextureRequest; try
if (handlerCachedTextureRequest != null)
{ {
handlerCachedTextureRequest(simclient,cachedtex.AgentData.SerialNum,requestArgs); CachedTextureRequest handlerCachedTextureRequest = OnCachedTextureRequest;
if (handlerCachedTextureRequest != null)
{
handlerCachedTextureRequest(simclient,cachedtex.AgentData.SerialNum,requestArgs);
}
} }
catch (Exception e)
{
m_log.ErrorFormat("[CLIENT VIEW]: AgentTextureCached packet handler threw an exception, {0}", e);
return false;
}
return true; return true;
} }
@ -11916,17 +11942,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
m_udpServer.SendPacket(m_udpClient, packet, throttlePacketType, doAutomaticSplitting, method); m_udpServer.SendPacket(m_udpClient, packet, throttlePacketType, doAutomaticSplitting, method);
} }
public bool AddMoney(int debit)
{
if (m_moneyBalance + debit >= 0)
{
m_moneyBalance += debit;
SendMoneyBalance(UUID.Zero, true, Util.StringToBytes256("Poof Poof!"), m_moneyBalance);
return true;
}
return false;
}
protected void HandleAutopilot(Object sender, string method, List<String> args) protected void HandleAutopilot(Object sender, string method, List<String> args)
{ {
float locx = 0; float locx = 0;

View File

@ -147,7 +147,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
/// <param name="visualParam"></param> /// <param name="visualParam"></param>
public void SetAppearance(IScenePresence sp, AvatarAppearance appearance) public void SetAppearance(IScenePresence sp, AvatarAppearance appearance)
{ {
SetAppearance(sp, appearance.Texture, appearance.VisualParams); DoSetAppearance(sp, appearance.Texture, appearance.VisualParams, new List<CachedTextureRequestArg>());
} }
/// <summary> /// <summary>
@ -158,9 +158,20 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
/// <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)
{ {
// m_log.DebugFormat( DoSetAppearance(sp, textureEntry, visualParams, new List<CachedTextureRequestArg>());
// "[AVFACTORY]: start SetAppearance for {0}, te {1}, visualParams {2}", }
// sp.Name, textureEntry, visualParams);
/// <summary>
/// Set appearance data (texture asset IDs and slider settings)
/// </summary>
/// <param name="sp"></param>
/// <param name="texture"></param>
/// <param name="visualParam"></param>
protected void DoSetAppearance(IScenePresence sp, Primitive.TextureEntry textureEntry, byte[] visualParams, List<CachedTextureRequestArg> hashes)
{
// m_log.DebugFormat(
// "[AVFACTORY]: start SetAppearance for {0}, te {1}, visualParams {2}",
// sp.Name, textureEntry, visualParams);
// TODO: This is probably not necessary any longer, just assume the // TODO: This is probably not necessary any longer, just assume the
// textureEntry set implies that the appearance transaction is complete // textureEntry set implies that the appearance transaction is complete
@ -190,18 +201,25 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
// 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);
changed = sp.Appearance.SetTextureEntries(textureEntry) || changed; changed = sp.Appearance.SetTextureEntries(textureEntry) || changed;
// WriteBakedTexturesReport(sp, m_log.DebugFormat); // WriteBakedTexturesReport(sp, m_log.DebugFormat);
// If bake textures are missing and this is not an NPC, request a rebake from client // If bake textures are missing and this is not an NPC, request a rebake from client
if (!ValidateBakedTextureCache(sp) && (((ScenePresence)sp).PresenceType != PresenceType.Npc)) if (!ValidateBakedTextureCache(sp) && (((ScenePresence)sp).PresenceType != PresenceType.Npc))
RequestRebake(sp, true); RequestRebake(sp, true);
// Save the wearble hashes in the appearance
sp.Appearance.ResetTextureHashes();
if (m_reusetextures)
{
foreach (CachedTextureRequestArg arg in hashes)
sp.Appearance.SetTextureHash(arg.BakedTextureIndex,arg.WearableHashID);
}
// This appears to be set only in the final stage of the appearance // This appears to be set only in the final stage of the appearance
// update transaction. In theory, we should be able to do an immediate // update transaction. In theory, we should be able to do an immediate
// appearance send and save here. // appearance send and save here.
@ -235,13 +253,13 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
public bool SendAppearance(UUID agentId) public bool SendAppearance(UUID agentId)
{ {
// m_log.DebugFormat("[AVFACTORY]: Sending appearance for {0}", agentId); // m_log.DebugFormat("[AVFACTORY]: Sending appearance for {0}", agentId);
ScenePresence sp = m_scene.GetScenePresence(agentId); ScenePresence sp = m_scene.GetScenePresence(agentId);
if (sp == null) if (sp == null)
{ {
// This is expected if the user has gone away. // This is expected if the user has gone away.
// m_log.DebugFormat("[AVFACTORY]: Agent {0} no longer in the scene", agentId); // m_log.DebugFormat("[AVFACTORY]: Agent {0} no longer in the scene", agentId);
return false; return false;
} }
@ -318,7 +336,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
/// <param name="agentId"></param> /// <param name="agentId"></param>
public void QueueAppearanceSend(UUID agentid) public void QueueAppearanceSend(UUID agentid)
{ {
// m_log.DebugFormat("[AVFACTORY]: Queue appearance send for {0}", agentid); // m_log.DebugFormat("[AVFACTORY]: Queue appearance send for {0}", agentid);
// 10000 ticks per millisecond, 1000 milliseconds per second // 10000 ticks per millisecond, 1000 milliseconds per second
long timestamp = DateTime.Now.Ticks + Convert.ToInt64(m_sendtime * 1000 * 10000); long timestamp = DateTime.Now.Ticks + Convert.ToInt64(m_sendtime * 1000 * 10000);
@ -331,7 +349,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
public void QueueAppearanceSave(UUID agentid) public void QueueAppearanceSave(UUID agentid)
{ {
// m_log.DebugFormat("[AVFACTORY]: Queueing appearance save for {0}", agentid); // m_log.DebugFormat("[AVFACTORY]: Queueing appearance save for {0}", agentid);
// 10000 ticks per millisecond, 1000 milliseconds per second // 10000 ticks per millisecond, 1000 milliseconds per second
long timestamp = DateTime.Now.Ticks + Convert.ToInt64(m_savetime * 1000 * 10000); long timestamp = DateTime.Now.Ticks + Convert.ToInt64(m_savetime * 1000 * 10000);
@ -356,9 +374,9 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
if (face == null) if (face == null)
continue; continue;
// m_log.DebugFormat( // m_log.DebugFormat(
// "[AVFACTORY]: Looking for texture {0}, id {1} for {2} {3}", // "[AVFACTORY]: Looking for texture {0}, id {1} for {2} {3}",
// face.TextureID, idx, client.Name, client.AgentId); // face.TextureID, idx, client.Name, client.AgentId);
// if the texture is one of the "defaults" then skip it // if the texture is one of the "defaults" then skip it
// this should probably be more intelligent (skirt texture doesnt matter // this should probably be more intelligent (skirt texture doesnt matter
@ -373,7 +391,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
return false; return false;
} }
// m_log.DebugFormat("[AVFACTORY]: Completed texture check for {0} {1}", sp.Name, sp.UUID); // m_log.DebugFormat("[AVFACTORY]: Completed texture check for {0} {1}", sp.Name, sp.UUID);
// If we only found default textures, then the appearance is not cached // If we only found default textures, then the appearance is not cached
return (defonly ? false : true); return (defonly ? false : true);
@ -392,9 +410,9 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
if (face == null) if (face == null)
continue; continue;
// m_log.DebugFormat( // m_log.DebugFormat(
// "[AVFACTORY]: Looking for texture {0}, id {1} for {2} {3}", // "[AVFACTORY]: Looking for texture {0}, id {1} for {2} {3}",
// face.TextureID, idx, client.Name, client.AgentId); // face.TextureID, idx, client.Name, client.AgentId);
// if the texture is one of the "defaults" then skip it // if the texture is one of the "defaults" then skip it
// this should probably be more intelligent (skirt texture doesnt matter // this should probably be more intelligent (skirt texture doesnt matter
@ -458,9 +476,9 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
if (bakeType == BakeType.Unknown) if (bakeType == BakeType.Unknown)
continue; continue;
// m_log.DebugFormat( // m_log.DebugFormat(
// "[AVFACTORY]: NPC avatar {0} has texture id {1} : {2}", // "[AVFACTORY]: NPC avatar {0} has texture id {1} : {2}",
// acd.AgentID, i, acd.Appearance.Texture.FaceTextures[i]); // acd.AgentID, i, acd.Appearance.Texture.FaceTextures[i]);
int ftIndex = (int)AppearanceManager.BakeTypeToAgentTextureIndex(bakeType); int ftIndex = (int)AppearanceManager.BakeTypeToAgentTextureIndex(bakeType);
Primitive.TextureEntryFace texture = faceTextures[ftIndex]; // this will be null if there's no such baked texture Primitive.TextureEntryFace texture = faceTextures[ftIndex]; // this will be null if there's no such baked texture
@ -484,7 +502,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
UUID avatarID = kvp.Key; UUID avatarID = kvp.Key;
long sendTime = kvp.Value; long sendTime = kvp.Value;
// m_log.DebugFormat("[AVFACTORY]: Handling queued appearance updates for {0}, update delta to now is {1}", avatarID, sendTime - now); // m_log.DebugFormat("[AVFACTORY]: Handling queued appearance updates for {0}, update delta to now is {1}", avatarID, sendTime - now);
if (sendTime < now) if (sendTime < now)
{ {
@ -530,11 +548,11 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
if (sp == null) if (sp == null)
{ {
// This is expected if the user has gone away. // This is expected if the user has gone away.
// m_log.DebugFormat("[AVFACTORY]: Agent {0} no longer in the scene", agentid); // m_log.DebugFormat("[AVFACTORY]: Agent {0} no longer in the scene", agentid);
return; return;
} }
// m_log.DebugFormat("[AVFACTORY]: Saving appearance for avatar {0}", agentid); // m_log.DebugFormat("[AVFACTORY]: Saving appearance for avatar {0}", agentid);
// This could take awhile since it needs to pull inventory // This could take awhile since it needs to pull inventory
// We need to do it at the point of save so that there is a sufficient delay for any upload of new body part/shape // We need to do it at the point of save so that there is a sufficient delay for any upload of new body part/shape
@ -622,12 +640,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) private void Client_OnSetAppearance(IClientAPI client, Primitive.TextureEntry textureEntry, byte[] visualParams, List<CachedTextureRequestArg> hashes)
{ {
// 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); DoSetAppearance(sp, textureEntry, visualParams, hashes);
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);
} }
@ -684,7 +702,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
/// <param name="cachedTextureRequest"></param> /// <param name="cachedTextureRequest"></param>
private void Client_OnCachedTextureRequest(IClientAPI client, int serial, List<CachedTextureRequestArg> cachedTextureRequest) private void Client_OnCachedTextureRequest(IClientAPI client, int serial, List<CachedTextureRequestArg> cachedTextureRequest)
{ {
// m_log.WarnFormat("[AVFACTORY]: Client_OnCachedTextureRequest called for {0} ({1})", client.Name, client.AgentId); // m_log.DebugFormat("[AVFACTORY]: Client_OnCachedTextureRequest called for {0} ({1})", client.Name, client.AgentId);
ScenePresence sp = m_scene.GetScenePresence(client.AgentId); ScenePresence sp = m_scene.GetScenePresence(client.AgentId);
List<CachedTextureResponseArg> cachedTextureResponse = new List<CachedTextureResponseArg>(); List<CachedTextureResponseArg> cachedTextureResponse = new List<CachedTextureResponseArg>();
@ -695,23 +713,20 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
if (m_reusetextures) if (m_reusetextures)
{ {
// this is the most insanely dumb way to do this... however it seems to if (sp.Appearance.GetTextureHash(index) == request.WearableHashID)
// actually work. if the appearance has been reset because wearables have {
// changed then the texture entries are zero'd out until the bakes are Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[index];
// uploaded. on login, if the textures exist in the cache (eg if you logged if (face != null)
// into the simulator recently, then the appearance will pull those and send texture = face.TextureID;
// them back in the packet and you won't have to rebake. if the textures aren't }
// in the cache then the intial makeroot() call in scenepresence will zero else
// them out. {
// // We know that that hash is wrong, null it out
// a better solution (though how much better is an open question) is to // and wait for the setappearance call
// store the hashes in the appearance and compare them. Thats's coming. sp.Appearance.SetTextureHash(index,UUID.Zero);
}
Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[index]; // m_log.WarnFormat("[AVFACTORY]: use texture {0} for index {1}; hash={2}",texture,index,request.WearableHashID);
if (face != null)
texture = face.TextureID;
// m_log.WarnFormat("[AVFACTORY]: reuse texture {0} for index {1}",texture,index);
} }
CachedTextureResponseArg response = new CachedTextureResponseArg(); CachedTextureResponseArg response = new CachedTextureResponseArg();

View File

@ -371,7 +371,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
foreach (string fid in outstanding) foreach (string fid in outstanding)
{ {
UUID fromAgentID; UUID fromAgentID;
string firstname = "Unknown", lastname = "User"; string firstname = "Unknown", lastname = "UserFMSFOIN";
if (!GetAgentInfo(client.Scene.RegionInfo.ScopeID, fid, out fromAgentID, out firstname, out lastname)) if (!GetAgentInfo(client.Scene.RegionInfo.ScopeID, fid, out fromAgentID, out firstname, out lastname))
{ {
m_log.DebugFormat("[FRIENDS MODULE]: skipping malformed friend {0}", fid); m_log.DebugFormat("[FRIENDS MODULE]: skipping malformed friend {0}", fid);
@ -397,7 +397,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
protected virtual bool GetAgentInfo(UUID scopeID, string fid, out UUID agentID, out string first, out string last) protected virtual bool GetAgentInfo(UUID scopeID, string fid, out UUID agentID, out string first, out string last)
{ {
first = "Unknown"; last = "User"; first = "Unknown"; last = "UserFMGAI";
if (!UUID.TryParse(fid, out agentID)) if (!UUID.TryParse(fid, out agentID))
return false; return false;

View File

@ -293,7 +293,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
protected override bool GetAgentInfo(UUID scopeID, string fid, out UUID agentID, out string first, out string last) protected override bool GetAgentInfo(UUID scopeID, string fid, out UUID agentID, out string first, out string last)
{ {
first = "Unknown"; last = "User"; first = "Unknown"; last = "UserHGGAI";
if (base.GetAgentInfo(scopeID, fid, out agentID, out first, out last)) if (base.GetAgentInfo(scopeID, fid, out agentID, out first, out last))
return true; return true;

View File

@ -54,7 +54,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
public new void Initialise(IConfigSource config) public new void Initialise(IConfigSource config)
{ {
string umanmod = config.Configs["Modules"].GetString("UserManagementModule", Name); string umanmod = config.Configs["Modules"].GetString("UserManagementModule", null);
if (umanmod == Name) if (umanmod == Name)
{ {
m_Enabled = true; m_Enabled = true;

View File

@ -157,13 +157,16 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
} }
else else
{ {
string[] names = GetUserNames(uuid); string[] names;
bool foundRealName = TryGetUserNames(uuid, out names);
if (names.Length == 2) if (names.Length == 2)
{ {
//m_log.DebugFormat("[XXX] HandleUUIDNameRequest {0} is {1} {2}", uuid, names[0], names[1]); if (!foundRealName)
m_log.DebugFormat("[USER MANAGEMENT MODULE]: Sending {0} {1} for {2} to {3} since no bound name found", names[0], names[1], uuid, remote_client.Name);
remote_client.SendNameReply(uuid, names[0], names[1]); remote_client.SendNameReply(uuid, names[0], names[1]);
} }
} }
} }
@ -246,10 +249,15 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
} }
// search the local cache // search the local cache
foreach (UserData data in m_UserCache.Values) lock (m_UserCache)
if (users.Find(delegate(UserData d) { return d.Id == data.Id; }) == null && {
(data.FirstName.ToLower().StartsWith(query.ToLower()) || data.LastName.ToLower().StartsWith(query.ToLower()))) foreach (UserData data in m_UserCache.Values)
users.Add(data); {
if (users.Find(delegate(UserData d) { return d.Id == data.Id; }) == null &&
(data.FirstName.ToLower().StartsWith(query.ToLower()) || data.LastName.ToLower().StartsWith(query.ToLower())))
users.Add(data);
}
}
AddAdditionalUsers(query, users); AddAdditionalUsers(query, users);
@ -272,17 +280,24 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
} }
} }
private string[] GetUserNames(UUID uuid) /// <summary>
/// Try to get the names bound to the given uuid.
/// </summary>
/// <returns>True if the name was found, false if not.</returns>
/// <param name='uuid'></param>
/// <param name='names'>The array of names if found. If not found, then names[0] = "Unknown" and names[1] = "User"</param>
private bool TryGetUserNames(UUID uuid, out string[] names)
{ {
string[] returnstring = new string[2]; names = new string[2];
lock (m_UserCache) lock (m_UserCache)
{ {
if (m_UserCache.ContainsKey(uuid)) if (m_UserCache.ContainsKey(uuid))
{ {
returnstring[0] = m_UserCache[uuid].FirstName; names[0] = m_UserCache[uuid].FirstName;
returnstring[1] = m_UserCache[uuid].LastName; names[1] = m_UserCache[uuid].LastName;
return returnstring;
return true;
} }
} }
@ -290,8 +305,8 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
if (account != null) if (account != null)
{ {
returnstring[0] = account.FirstName; names[0] = account.FirstName;
returnstring[1] = account.LastName; names[1] = account.LastName;
UserData user = new UserData(); UserData user = new UserData();
user.FirstName = account.FirstName; user.FirstName = account.FirstName;
@ -299,14 +314,16 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
lock (m_UserCache) lock (m_UserCache)
m_UserCache[uuid] = user; m_UserCache[uuid] = user;
return true;
} }
else else
{ {
returnstring[0] = "Unknown"; names[0] = "Unknown";
returnstring[1] = "User"; names[1] = "UserUMMTGUN";
}
return returnstring; return false;
}
} }
#region IUserManagement #region IUserManagement
@ -342,15 +359,17 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
public string GetUserName(UUID uuid) public string GetUserName(UUID uuid)
{ {
string[] names = GetUserNames(uuid); string[] names;
TryGetUserNames(uuid, out names);
if (names.Length == 2) if (names.Length == 2)
{ {
string firstname = names[0]; string firstname = names[0];
string lastname = names[1]; string lastname = names[1];
return firstname + " " + lastname; return firstname + " " + lastname;
} }
return "(hippos)"; return "(hippos)";
} }
@ -466,12 +485,13 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
//ignore updates without creator data //ignore updates without creator data
return; return;
} }
//try update unknown users //try update unknown users
//and creator's home URL's //and creator's home URL's
if ((oldUser.FirstName == "Unknown" && !creatorData.Contains ("Unknown")) || (oldUser.HomeURL != null && !creatorData.StartsWith (oldUser.HomeURL))) if ((oldUser.FirstName == "Unknown" && !creatorData.Contains ("Unknown")) || (oldUser.HomeURL != null && !creatorData.StartsWith (oldUser.HomeURL)))
{ {
m_UserCache.Remove (id); m_UserCache.Remove (id);
// m_log.DebugFormat("[USER MANAGEMENT MODULE]: Re-adding user with id {0}, creatorData [{1}] and old HomeURL {2}", id, creatorData,oldUser.HomeURL); m_log.DebugFormat("[USER MANAGEMENT MODULE]: Re-adding user with id {0}, creatorData [{1}] and old HomeURL {2}", id, creatorData, oldUser.HomeURL);
} }
else else
{ {
@ -516,7 +536,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
else else
{ {
user.FirstName = "Unknown"; user.FirstName = "Unknown";
user.LastName = "User"; user.LastName = "UserUMMAU";
} }
AddUserInternal (user); AddUserInternal (user);
@ -547,6 +567,13 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
protected void RegisterConsoleCmds() protected void RegisterConsoleCmds()
{ {
MainConsole.Instance.Commands.AddCommand("Users", true,
"show name",
"show name <uuid>",
"Show the bindings between a single user UUID and a user name",
String.Empty,
HandleShowUser);
MainConsole.Instance.Commands.AddCommand("Users", true, MainConsole.Instance.Commands.AddCommand("Users", true,
"show names", "show names",
"show names", "show names",
@ -555,26 +582,54 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
HandleShowUsers); HandleShowUsers);
} }
private void HandleShowUsers(string module, string[] cmd) private void HandleShowUser(string module, string[] cmd)
{ {
lock (m_UserCache) if (cmd.Length < 3)
{ {
if (m_UserCache.Count == 0) MainConsole.Instance.OutputFormat("Usage: show name <uuid>");
{
MainConsole.Instance.Output("No users found");
return;
}
MainConsole.Instance.Output("UUID User Name");
MainConsole.Instance.Output("-----------------------------------------------------------------------------");
foreach (KeyValuePair<UUID, UserData> kvp in m_UserCache)
{
MainConsole.Instance.Output(String.Format("{0} {1} {2} ({3})",
kvp.Key, kvp.Value.FirstName, kvp.Value.LastName, kvp.Value.HomeURL));
}
return; return;
} }
UUID userId;
if (!ConsoleUtil.TryParseConsoleUuid(MainConsole.Instance, cmd[2], out userId))
return;
string[] names;
UserData ud;
lock (m_UserCache)
{
if (!m_UserCache.TryGetValue(userId, out ud))
{
MainConsole.Instance.OutputFormat("No name known for user with id {0}", userId);
return;
}
}
ConsoleDisplayTable cdt = new ConsoleDisplayTable();
cdt.AddColumn("UUID", 36);
cdt.AddColumn("Name", 30);
cdt.AddColumn("HomeURL", 40);
cdt.AddRow(userId, string.Format("{0} {1}", ud.FirstName, ud.LastName), ud.HomeURL);
MainConsole.Instance.Output(cdt.ToString());
}
private void HandleShowUsers(string module, string[] cmd)
{
ConsoleDisplayTable cdt = new ConsoleDisplayTable();
cdt.AddColumn("UUID", 36);
cdt.AddColumn("Name", 30);
cdt.AddColumn("HomeURL", 40);
lock (m_UserCache)
{
foreach (KeyValuePair<UUID, UserData> kvp in m_UserCache)
cdt.AddRow(kvp.Key, string.Format("{0} {1}", kvp.Value.FirstName, kvp.Value.LastName), kvp.Value.HomeURL);
}
MainConsole.Instance.Output(cdt.ToString());
} }
} }
} }

View File

@ -369,6 +369,15 @@ namespace OpenSim.Region.CoreModules.World.Sound
}); });
} }
public void SetSoundQueueing(UUID objectID, bool shouldQueue)
{
SceneObjectPart part;
if (!m_scene.TryGetSceneObjectPart(objectID, out part))
return;
part.SoundQueueing = shouldQueue;
}
#endregion #endregion
} }
} }

View File

@ -104,7 +104,6 @@ namespace OpenSim.Region.Framework.Interfaces
/// <param name="sound">Sound asset ID</param> /// <param name="sound">Sound asset ID</param>
/// <param name="volume">Sound volume</param> /// <param name="volume">Sound volume</param>
/// <param name="triggered">Triggered or not.</param> /// <param name="triggered">Triggered or not.</param>
/// <param name="flags"></param>
/// <param name="radius">Sound radius</param> /// <param name="radius">Sound radius</param>
/// <param name="useMaster">Play using sound master</param> /// <param name="useMaster">Play using sound master</param>
/// <param name="isMaster">Play as sound master</param> /// <param name="isMaster">Play as sound master</param>
@ -123,5 +122,12 @@ namespace OpenSim.Region.Framework.Interfaces
/// <param name="max">AABB top north-east corner</param> /// <param name="max">AABB top north-east corner</param>
void TriggerSoundLimited(UUID objectID, UUID sound, double volume, void TriggerSoundLimited(UUID objectID, UUID sound, double volume,
Vector3 min, Vector3 max); Vector3 min, Vector3 max);
/// <summary>
/// Set whether sounds on the given prim should be queued.
/// </summary>
/// <param name='objectID'></param>
/// <param name='shouldQueue'></param>
void SetSoundQueueing(UUID objectID, bool shouldQueue);
} }
} }

View File

@ -1499,7 +1499,7 @@ namespace OpenSim.Region.Framework.Scenes
if (!userExposed) if (!userExposed)
dupe.IsAttachment = true; dupe.IsAttachment = true;
dupe.AbsolutePosition = new Vector3(AbsolutePosition.X, AbsolutePosition.Y, AbsolutePosition.Z); dupe.m_sittingAvatars = new List<UUID>();
if (!userExposed) if (!userExposed)
{ {

View File

@ -219,6 +219,14 @@ namespace OpenSim.Region.Framework.Scenes
public double SoundRadius; public double SoundRadius;
/// <summary>
/// Should sounds played from this prim be queued?
/// </summary>
/// <remarks>
/// This should only be changed by sound modules. It is up to sound modules as to how they interpret this setting.
/// </remarks>
public bool SoundQueueing { get; set; }
public uint TimeStampFull; public uint TimeStampFull;
public uint TimeStampLastActivity; // Will be used for AutoReturn public uint TimeStampLastActivity; // Will be used for AutoReturn
@ -1791,6 +1799,8 @@ namespace OpenSim.Region.Framework.Scenes
Array.Copy(Shape.ExtraParams, extraP, extraP.Length); Array.Copy(Shape.ExtraParams, extraP, extraP.Length);
dupe.Shape.ExtraParams = extraP; dupe.Shape.ExtraParams = extraP;
dupe.PayPrice = (int[])PayPrice.Clone();
dupe.DynAttrs.CopyFrom(DynAttrs); dupe.DynAttrs.CopyFrom(DynAttrs);
if (userExposed) if (userExposed)
@ -2429,7 +2439,7 @@ namespace OpenSim.Region.Framework.Scenes
if (soundModule != null) if (soundModule != null)
{ {
soundModule.SendSound(UUID, CollisionSound, soundModule.SendSound(UUID, CollisionSound,
CollisionSoundVolume, true, (byte)0, 0, false, CollisionSoundVolume, true, 0, 0, false,
false); false);
} }
} }

View File

@ -2713,7 +2713,9 @@ namespace OpenSim.Region.Framework.Scenes
// again here... this comes after the cached appearance check because the avatars // again here... this comes after the cached appearance check because the avatars
// appearance goes into the avatar update packet // appearance goes into the avatar update packet
SendAvatarDataToAllAgents(); SendAvatarDataToAllAgents();
SendAppearanceToAgent(this);
// This invocation always shows up in the viewer logs as an error.
// SendAppearanceToAgent(this);
// If we are using the the cached appearance then send it out to everyone // If we are using the the cached appearance then send it out to everyone
if (cachedappearance) if (cachedappearance)

View File

@ -907,7 +907,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()); OnSetAppearance(this, appearance.Texture, (byte[])appearance.VisualParams.Clone(), new List<CachedTextureRequestArg>());
} }
public void SendRegionHandshake(RegionInfo regionInfo, RegionHandshakeArgs args) public void SendRegionHandshake(RegionInfo regionInfo, RegionHandshakeArgs args)
@ -1056,7 +1056,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
{ {
} }
public void SendMoneyBalance(UUID transaction, bool success, byte[] description, int balance) public void SendMoneyBalance(UUID transaction, bool success, byte[] description, int balance, int transactionType, UUID sourceID, bool sourceIsGroup, UUID destID, bool destIsGroup, int amount, string item)
{ {
} }
@ -1196,11 +1196,6 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
} }
public bool AddMoney(int debit)
{
return true;
}
public void SendSunPos(Vector3 sunPos, Vector3 sunVel, ulong CurrentTime, uint SecondsPerSunCycle, uint SecondsPerYear, float OrbitalPosition) public void SendSunPos(Vector3 sunPos, Vector3 sunVel, ulong CurrentTime, uint SecondsPerSunCycle, uint SecondsPerYear, float OrbitalPosition)
{ {

View File

@ -764,7 +764,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
remoteClient.SendCreateGroupReply(UUID.Zero, false, "You have got insufficient funds to create a group."); remoteClient.SendCreateGroupReply(UUID.Zero, false, "You have got insufficient funds to create a group.");
return UUID.Zero; return UUID.Zero;
} }
money.ApplyCharge(GetRequestingAgentID(remoteClient), money.GroupCreationCharge, "Group Creation"); money.ApplyCharge(GetRequestingAgentID(remoteClient), money.GroupCreationCharge, MoneyTransactionType.GroupCreate);
} }
UUID groupID = m_groupData.CreateGroup(GetRequestingAgentID(remoteClient), name, charter, showInList, insigniaID, membershipFee, openEnrollment, allowPublish, maturePublish, GetRequestingAgentID(remoteClient)); UUID groupID = m_groupData.CreateGroup(GetRequestingAgentID(remoteClient), name, charter, showInList, insigniaID, membershipFee, openEnrollment, allowPublish, maturePublish, GetRequestingAgentID(remoteClient));

View File

@ -191,9 +191,14 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule
// Please do not refactor these to be just one method // Please do not refactor these to be just one method
// Existing implementations need the distinction // Existing implementations need the distinction
// //
public void ApplyCharge(UUID agentID, int amount, string text) public void ApplyCharge(UUID agentID, int amount, MoneyTransactionType type, string extraData)
{ {
} }
public void ApplyCharge(UUID agentID, int amount, MoneyTransactionType type)
{
}
public void ApplyUploadCharge(UUID agentID, int amount, string text) public void ApplyUploadCharge(UUID agentID, int amount, string text)
{ {
} }
@ -322,7 +327,7 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule
client.SendAlertMessage(e.Message + " "); client.SendAlertMessage(e.Message + " ");
} }
client.SendMoneyBalance(TransactionID, true, new byte[0], returnfunds); client.SendMoneyBalance(TransactionID, true, new byte[0], returnfunds, 0, UUID.Zero, false, UUID.Zero, false, 0, String.Empty);
} }
else else
{ {
@ -385,12 +390,12 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule
{ {
if (sender != null) if (sender != null)
{ {
sender.SendMoneyBalance(UUID.Random(), transactionresult, Utils.StringToBytes(description), GetFundsForAgentID(senderID)); sender.SendMoneyBalance(UUID.Random(), transactionresult, Utils.StringToBytes(description), GetFundsForAgentID(senderID), 0, UUID.Zero, false, UUID.Zero, false, 0, String.Empty);
} }
if (receiver != null) if (receiver != null)
{ {
receiver.SendMoneyBalance(UUID.Random(), transactionresult, Utils.StringToBytes(description), GetFundsForAgentID(receiverID)); receiver.SendMoneyBalance(UUID.Random(), transactionresult, Utils.StringToBytes(description), GetFundsForAgentID(receiverID), 0, UUID.Zero, false, UUID.Zero, false, 0, String.Empty);
} }
} }
} }

View File

@ -694,7 +694,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
{ {
} }
public virtual void SendMoneyBalance(UUID transaction, bool success, byte[] description, int balance) public virtual void SendMoneyBalance(UUID transaction, bool success, byte[] description, int balance, int transactionType, UUID sourceID, bool sourceIsGroup, UUID destID, bool destIsGroup, int amount, string item)
{ {
} }
@ -866,11 +866,6 @@ namespace OpenSim.Region.OptionalModules.World.NPC
{ {
} }
public bool AddMoney(int debit)
{
return false;
}
public void SendSunPos(Vector3 sunPos, Vector3 sunVel, ulong time, uint dlen, uint ylen, float phase) public void SendSunPos(Vector3 sunPos, Vector3 sunVel, ulong time, uint dlen, uint ylen, float phase)
{ {
} }

View File

@ -251,6 +251,16 @@ public override BulletShape CreateMeshShape(BulletWorld world,
BSPhysicsShapeType.SHAPE_MESH); BSPhysicsShapeType.SHAPE_MESH);
} }
public override BulletShape CreateGImpactShape(BulletWorld world,
int indicesCount, int[] indices,
int verticesCount, float[] vertices)
{
BulletWorldUnman worldu = world as BulletWorldUnman;
return new BulletShapeUnman(
BSAPICPP.CreateGImpactShape2(worldu.ptr, indicesCount, indices, verticesCount, vertices),
BSPhysicsShapeType.SHAPE_GIMPACT);
}
public override BulletShape CreateHullShape(BulletWorld world, int hullCount, float[] hulls) public override BulletShape CreateHullShape(BulletWorld world, int hullCount, float[] hulls)
{ {
BulletWorldUnman worldu = world as BulletWorldUnman; BulletWorldUnman worldu = world as BulletWorldUnman;
@ -1425,6 +1435,11 @@ public static extern IntPtr CreateMeshShape2(IntPtr world,
int indicesCount, [MarshalAs(UnmanagedType.LPArray)] int[] indices, int indicesCount, [MarshalAs(UnmanagedType.LPArray)] int[] indices,
int verticesCount, [MarshalAs(UnmanagedType.LPArray)] float[] vertices ); int verticesCount, [MarshalAs(UnmanagedType.LPArray)] float[] vertices );
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern IntPtr CreateGImpactShape2(IntPtr world,
int indicesCount, [MarshalAs(UnmanagedType.LPArray)] int[] indices,
int verticesCount, [MarshalAs(UnmanagedType.LPArray)] float[] vertices );
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern IntPtr CreateHullShape2(IntPtr world, public static extern IntPtr CreateHullShape2(IntPtr world,
int hullCount, [MarshalAs(UnmanagedType.LPArray)] float[] hulls); int hullCount, [MarshalAs(UnmanagedType.LPArray)] float[] hulls);

View File

@ -1475,7 +1475,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
ret = BSPhysicsShapeType.SHAPE_UNKNOWN; ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
break; break;
case BroadphaseNativeTypes.CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE: case BroadphaseNativeTypes.CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE:
ret = BSPhysicsShapeType.SHAPE_MESH; ret = BSPhysicsShapeType.SHAPE_CONVEXHULL;
break; break;
case BroadphaseNativeTypes.CONVEX_HULL_SHAPE_PROXYTYPE: case BroadphaseNativeTypes.CONVEX_HULL_SHAPE_PROXYTYPE:
ret = BSPhysicsShapeType.SHAPE_HULL; ret = BSPhysicsShapeType.SHAPE_HULL;
@ -1503,7 +1503,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
ret = BSPhysicsShapeType.SHAPE_CONE; ret = BSPhysicsShapeType.SHAPE_CONE;
break; break;
case BroadphaseNativeTypes.CONVEX_SHAPE_PROXYTYPE: case BroadphaseNativeTypes.CONVEX_SHAPE_PROXYTYPE:
ret = BSPhysicsShapeType.SHAPE_UNKNOWN; ret = BSPhysicsShapeType.SHAPE_CONVEXHULL;
break; break;
case BroadphaseNativeTypes.CYLINDER_SHAPE_PROXYTYPE: case BroadphaseNativeTypes.CYLINDER_SHAPE_PROXYTYPE:
ret = BSPhysicsShapeType.SHAPE_CYLINDER; ret = BSPhysicsShapeType.SHAPE_CYLINDER;
@ -1547,7 +1547,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
break; break;
///Used for GIMPACT Trimesh integration ///Used for GIMPACT Trimesh integration
case BroadphaseNativeTypes.GIMPACT_SHAPE_PROXYTYPE: case BroadphaseNativeTypes.GIMPACT_SHAPE_PROXYTYPE:
ret = BSPhysicsShapeType.SHAPE_MESH; ret = BSPhysicsShapeType.SHAPE_GIMPACT;
break; break;
///Multimaterial mesh ///Multimaterial mesh
case BroadphaseNativeTypes.MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE: case BroadphaseNativeTypes.MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE:
@ -1820,6 +1820,11 @@ private sealed class BulletConstraintXNA : BulletConstraint
return new BulletShapeXNA(meshShape, BSPhysicsShapeType.SHAPE_MESH); return new BulletShapeXNA(meshShape, BSPhysicsShapeType.SHAPE_MESH);
} }
public override BulletShape CreateGImpactShape(BulletWorld pWorld, int pIndicesCount, int[] indices, int pVerticesCount, float[] verticesAsFloats)
{
// TODO:
return null;
}
public static void DumpRaw(ObjectArray<int>indices, ObjectArray<float> vertices, int pIndicesCount,int pVerticesCount ) public static void DumpRaw(ObjectArray<int>indices, ObjectArray<float> vertices, int pIndicesCount,int pVerticesCount )
{ {

View File

@ -71,6 +71,7 @@ public enum BSPhysicsShapeType
SHAPE_HEIGHTMAP = 23, SHAPE_HEIGHTMAP = 23,
SHAPE_AVATAR = 24, SHAPE_AVATAR = 24,
SHAPE_CONVEXHULL= 25, SHAPE_CONVEXHULL= 25,
SHAPE_GIMPACT = 26,
}; };
// The native shapes have predefined shape hash keys // The native shapes have predefined shape hash keys
@ -321,6 +322,10 @@ public abstract BulletShape CreateMeshShape(BulletWorld world,
int indicesCount, int[] indices, int indicesCount, int[] indices,
int verticesCount, float[] vertices ); int verticesCount, float[] vertices );
public abstract BulletShape CreateGImpactShape(BulletWorld world,
int indicesCount, int[] indices,
int verticesCount, float[] vertices );
public abstract BulletShape CreateHullShape(BulletWorld world, public abstract BulletShape CreateHullShape(BulletWorld world,
int hullCount, float[] hulls); int hullCount, float[] hulls);

View File

@ -483,8 +483,15 @@ public sealed class BSCharacter : BSPhysObject
{ {
// Bullet assumes we know what we are doing when forcing orientation // Bullet assumes we know what we are doing when forcing orientation
// so it lets us go against all the rules and just compensates for them later. // so it lets us go against all the rules and just compensates for them later.
// This keeps us from flipping the capsule over which the veiwer does not understand. // This forces rotation to be only around the Z axis and doesn't change any of the other axis.
ForceOrientation = new OMV.Quaternion(0, 0, _orientation.Z,0); // This keeps us from flipping the capsule over which the veiwer does not understand.
float oRoll, oPitch, oYaw;
_orientation.GetEulerAngles(out oRoll, out oPitch, out oYaw);
OMV.Quaternion trimmedOrientation = OMV.Quaternion.CreateFromEulers(0f, 0f, oYaw);
// DetailLog("{0},BSCharacter.setOrientation,taint,val={1},valDir={2},conv={3},convDir={4}",
// LocalID, _orientation, OMV.Vector3.UnitX * _orientation,
// trimmedOrientation, OMV.Vector3.UnitX * trimmedOrientation);
ForceOrientation = trimmedOrientation;
}); });
} }
} }

View File

@ -617,7 +617,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin
// Vehicles report collision events so we know when it's on the ground // Vehicles report collision events so we know when it's on the ground
m_physicsScene.PE.AddToCollisionFlags(ControllingPrim.PhysBody, CollisionFlags.BS_VEHICLE_COLLISIONS); m_physicsScene.PE.AddToCollisionFlags(ControllingPrim.PhysBody, CollisionFlags.BS_VEHICLE_COLLISIONS);
ControllingPrim.Inertia = m_physicsScene.PE.CalculateLocalInertia(ControllingPrim.PhysShape.physShapeInfo, m_vehicleMass); Vector3 inertia = m_physicsScene.PE.CalculateLocalInertia(ControllingPrim.PhysShape.physShapeInfo, m_vehicleMass);
ControllingPrim.Inertia = inertia * BSParam.VehicleInertiaFactor;
m_physicsScene.PE.SetMassProps(ControllingPrim.PhysBody, m_vehicleMass, ControllingPrim.Inertia); m_physicsScene.PE.SetMassProps(ControllingPrim.PhysBody, m_vehicleMass, ControllingPrim.Inertia);
m_physicsScene.PE.UpdateInertiaTensor(ControllingPrim.PhysBody); m_physicsScene.PE.UpdateInertiaTensor(ControllingPrim.PhysBody);

View File

@ -89,6 +89,8 @@ public static class BSParam
public static bool ShouldRemoveZeroWidthTriangles { get; private set; } public static bool ShouldRemoveZeroWidthTriangles { get; private set; }
public static bool ShouldUseBulletHACD { get; set; } public static bool ShouldUseBulletHACD { get; set; }
public static bool ShouldUseSingleConvexHullForPrims { get; set; } public static bool ShouldUseSingleConvexHullForPrims { get; set; }
public static bool ShouldUseGImpactShapeForPrims { get; set; }
public static bool ShouldUseAssetHulls { get; set; }
public static float TerrainImplementation { get; set; } public static float TerrainImplementation { get; set; }
public static int TerrainMeshMagnification { get; private set; } public static int TerrainMeshMagnification { get; private set; }
@ -146,6 +148,7 @@ public static class BSParam
public static float VehicleRestitution { get; private set; } public static float VehicleRestitution { get; private set; }
public static Vector3 VehicleLinearFactor { get; private set; } public static Vector3 VehicleLinearFactor { get; private set; }
public static Vector3 VehicleAngularFactor { get; private set; } public static Vector3 VehicleAngularFactor { get; private set; }
public static Vector3 VehicleInertiaFactor { get; private set; }
public static float VehicleGroundGravityFudge { get; private set; } public static float VehicleGroundGravityFudge { get; private set; }
public static float VehicleAngularBankingTimescaleFudge { get; private set; } public static float VehicleAngularBankingTimescaleFudge { get; private set; }
public static bool VehicleDebuggingEnable { get; private set; } public static bool VehicleDebuggingEnable { get; private set; }
@ -369,6 +372,10 @@ public static class BSParam
false ), false ),
new ParameterDefn<bool>("ShouldUseSingleConvexHullForPrims", "If true, use a single convex hull shape for physical prims", new ParameterDefn<bool>("ShouldUseSingleConvexHullForPrims", "If true, use a single convex hull shape for physical prims",
true ), true ),
new ParameterDefn<bool>("ShouldUseGImpactShapeForPrims", "If true, use a GImpact shape for prims with cuts and twists",
false ),
new ParameterDefn<bool>("ShouldUseAssetHulls", "If true, use hull if specified in the mesh asset info",
true ),
new ParameterDefn<int>("CrossingFailuresBeforeOutOfBounds", "How forgiving we are about getting into adjactent regions", new ParameterDefn<int>("CrossingFailuresBeforeOutOfBounds", "How forgiving we are about getting into adjactent regions",
5 ), 5 ),
@ -577,6 +584,8 @@ public static class BSParam
new Vector3(1f, 1f, 1f) ), new Vector3(1f, 1f, 1f) ),
new ParameterDefn<Vector3>("VehicleAngularFactor", "Fraction of physical angular changes applied to vehicle (<0,0,0> to <1,1,1>)", new ParameterDefn<Vector3>("VehicleAngularFactor", "Fraction of physical angular changes applied to vehicle (<0,0,0> to <1,1,1>)",
new Vector3(1f, 1f, 1f) ), new Vector3(1f, 1f, 1f) ),
new ParameterDefn<Vector3>("VehicleInertiaFactor", "Fraction of physical inertia applied (<0,0,0> to <1,1,1>)",
new Vector3(1f, 1f, 1f) ),
new ParameterDefn<float>("VehicleFriction", "Friction of vehicle on the ground (0.0 - 1.0)", new ParameterDefn<float>("VehicleFriction", "Friction of vehicle on the ground (0.0 - 1.0)",
0.0f ), 0.0f ),
new ParameterDefn<float>("VehicleRestitution", "Bouncyness factor for vehicles (0.0 - 1.0)", new ParameterDefn<float>("VehicleRestitution", "Bouncyness factor for vehicles (0.0 - 1.0)",

View File

@ -511,7 +511,10 @@ public class BSPrim : BSPhysObject
PhysScene.TaintedObject("setVehicleType", delegate() PhysScene.TaintedObject("setVehicleType", delegate()
{ {
ZeroMotion(true /* inTaintTime */); // Some vehicle scripts change vehicle type on the fly as an easy way to
// change all the parameters. Like a plane changing to CAR when on the
// ground. In this case, don't want to zero motion.
// ZeroMotion(true /* inTaintTime */);
VehicleActor.ProcessTypeChange(type); VehicleActor.ProcessTypeChange(type);
ActivateIfPhysical(false); ActivateIfPhysical(false);
}); });

View File

@ -268,6 +268,12 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
// Do any replacements in the parameters // Do any replacements in the parameters
m_physicsLoggingPrefix = m_physicsLoggingPrefix.Replace("%REGIONNAME%", RegionName); m_physicsLoggingPrefix = m_physicsLoggingPrefix.Replace("%REGIONNAME%", RegionName);
} }
else
{
BulletEngineName = "BulletUnmanaged";
m_physicsLoggingEnabled = false;
VehicleLoggingEnabled = false;
}
// The material characteristics. // The material characteristics.
BSMaterials.InitializeFromDefaults(Params); BSMaterials.InitializeFromDefaults(Params);
@ -322,6 +328,8 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
BSParam.ShouldUseBulletHACD = false; BSParam.ShouldUseBulletHACD = false;
m_log.InfoFormat("{0} Disabling ShouldUseSingleConvexHullForPrims", LogHeader); m_log.InfoFormat("{0} Disabling ShouldUseSingleConvexHullForPrims", LogHeader);
BSParam.ShouldUseSingleConvexHullForPrims = false; BSParam.ShouldUseSingleConvexHullForPrims = false;
m_log.InfoFormat("{0} Disabling ShouldUseGImpactShapeForPrims", LogHeader);
BSParam.ShouldUseGImpactShapeForPrims = false;
m_log.InfoFormat("{0} Setting terrain implimentation to Heightmap", LogHeader); m_log.InfoFormat("{0} Setting terrain implimentation to Heightmap", LogHeader);
BSParam.TerrainImplementation = (float)BSTerrainPhys.TerrainImplementation.Heightmap; BSParam.TerrainImplementation = (float)BSTerrainPhys.TerrainImplementation.Heightmap;
break; break;

View File

@ -230,6 +230,7 @@ public sealed class BSShapeCollection : IDisposable
BSShape potentialHull = null; BSShape potentialHull = null;
PrimitiveBaseShape pbs = prim.BaseShape; PrimitiveBaseShape pbs = prim.BaseShape;
// Use a simple, one section convex shape for prims that are probably convex (no cuts or twists)
if (BSParam.ShouldUseSingleConvexHullForPrims if (BSParam.ShouldUseSingleConvexHullForPrims
&& pbs != null && pbs != null
&& !pbs.SculptEntry && !pbs.SculptEntry
@ -238,7 +239,17 @@ public sealed class BSShapeCollection : IDisposable
{ {
potentialHull = BSShapeConvexHull.GetReference(m_physicsScene, false /* forceRebuild */, prim); potentialHull = BSShapeConvexHull.GetReference(m_physicsScene, false /* forceRebuild */, prim);
} }
else // Use the GImpact shape if it is a prim that has some concaveness
if (potentialHull == null
&& BSParam.ShouldUseGImpactShapeForPrims
&& pbs != null
&& !pbs.SculptEntry
)
{
potentialHull = BSShapeGImpact.GetReference(m_physicsScene, false /* forceRebuild */, prim);
}
// If not any of the simple cases, just make a hull
if (potentialHull == null)
{ {
potentialHull = BSShapeHull.GetReference(m_physicsScene, false /*forceRebuild*/, prim); potentialHull = BSShapeHull.GetReference(m_physicsScene, false /*forceRebuild*/, prim);
} }
@ -261,7 +272,7 @@ public sealed class BSShapeCollection : IDisposable
} }
else else
{ {
// Update prim.BSShape to reference a mesh of this shape. // Non-physical objects should be just meshes.
BSShape potentialMesh = BSShapeMesh.GetReference(m_physicsScene, false /*forceRebuild*/, prim); BSShape potentialMesh = BSShapeMesh.GetReference(m_physicsScene, false /*forceRebuild*/, prim);
// If the current shape is not what is on the prim at the moment, time to change. // If the current shape is not what is on the prim at the moment, time to change.
if (!prim.PhysShape.HasPhysicalShape if (!prim.PhysShape.HasPhysicalShape

View File

@ -31,6 +31,7 @@ using System.Text;
using OpenSim.Framework; using OpenSim.Framework;
using OpenSim.Region.Physics.Manager; using OpenSim.Region.Physics.Manager;
using OpenSim.Region.Physics.Meshing;
using OpenSim.Region.Physics.ConvexDecompositionDotNet; using OpenSim.Region.Physics.ConvexDecompositionDotNet;
using OMV = OpenMetaverse; using OMV = OpenMetaverse;
@ -422,15 +423,32 @@ public class BSShapeMesh : BSShape
outMesh = foundDesc; outMesh = foundDesc;
return ret; return ret;
} }
public delegate BulletShape CreateShapeCall(BulletWorld world, int indicesCount, int[] indices, int verticesCount, float[] vertices );
private BulletShape CreatePhysicalMesh(BSScene physicsScene, BSPhysObject prim, System.UInt64 newMeshKey, private BulletShape CreatePhysicalMesh(BSScene physicsScene, BSPhysObject prim, System.UInt64 newMeshKey,
PrimitiveBaseShape pbs, OMV.Vector3 size, float lod) PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
{
return BSShapeMesh.CreatePhysicalMeshShape(physicsScene, prim, newMeshKey, pbs, size, lod,
(w, iC, i, vC, v) => physicsScene.PE.CreateMeshShape(w, iC, i, vC, v) );
}
// Code that uses the mesher to create the index/vertices info for a trimesh shape.
// This is used by the passed 'makeShape' call to create the Bullet mesh shape.
// The actual build call is passed so this logic can be used by several of the shapes that use a
// simple mesh as their base shape.
public static BulletShape CreatePhysicalMeshShape(BSScene physicsScene, BSPhysObject prim, System.UInt64 newMeshKey,
PrimitiveBaseShape pbs, OMV.Vector3 size, float lod, CreateShapeCall makeShape)
{ {
BulletShape newShape = new BulletShape(); BulletShape newShape = new BulletShape();
IMesh meshData = physicsScene.mesher.CreateMesh(prim.PhysObjectName, pbs, size, lod, IMesh meshData = null;
false, // say it is not physical so a bounding box is not built lock (physicsScene.mesher)
false // do not cache the mesh and do not use previously built versions {
); meshData = physicsScene.mesher.CreateMesh(prim.PhysObjectName, pbs, size, lod,
false, // say it is not physical so a bounding box is not built
false // do not cache the mesh and do not use previously built versions
);
}
if (meshData != null) if (meshData != null)
{ {
@ -482,8 +500,7 @@ public class BSShapeMesh : BSShape
if (realIndicesIndex != 0) if (realIndicesIndex != 0)
{ {
newShape = physicsScene.PE.CreateMeshShape(physicsScene.World, newShape = makeShape(physicsScene.World, realIndicesIndex, indices, verticesAsFloats.Length / 3, verticesAsFloats);
realIndicesIndex, indices, verticesAsFloats.Length / 3, verticesAsFloats);
} }
else else
{ {
@ -561,13 +578,74 @@ public class BSShapeHull : BSShape
PrimitiveBaseShape pbs, OMV.Vector3 size, float lod) PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
{ {
BulletShape newShape = new BulletShape(); BulletShape newShape = new BulletShape();
IntPtr hullPtr = IntPtr.Zero;
if (BSParam.ShouldUseBulletHACD) IMesh meshData = null;
List<List<OMV.Vector3>> allHulls = null;
lock (physicsScene.mesher)
{
// Pass true for physicalness as this prevents the creation of bounding box which is not needed
meshData = physicsScene.mesher.CreateMesh(prim.PhysObjectName, pbs, size, lod, true /* isPhysical */, false /* shouldCache */);
// If we should use the asset's hull info, fetch it out of the locked mesher
if (meshData != null && BSParam.ShouldUseAssetHulls)
{
Meshmerizer realMesher = physicsScene.mesher as Meshmerizer;
if (realMesher != null)
{
allHulls = realMesher.GetConvexHulls(size);
}
if (allHulls == null)
{
physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,assetHulls,noAssetHull", prim.LocalID);
}
}
}
// If there is hull data in the mesh asset, build the hull from that
if (allHulls != null && BSParam.ShouldUseAssetHulls)
{
int hullCount = allHulls.Count;
int totalVertices = 1; // include one for the count of the hulls
// Using the structure described for HACD hulls, create the memory sturcture
// to pass the hull data to the creater.
foreach (List<OMV.Vector3> hullVerts in allHulls)
{
totalVertices += 4; // add four for the vertex count and centroid
totalVertices += hullVerts.Count * 3; // one vertex is three dimensions
}
float[] convHulls = new float[totalVertices];
convHulls[0] = (float)hullCount;
int jj = 1;
foreach (List<OMV.Vector3> hullVerts in allHulls)
{
convHulls[jj + 0] = hullVerts.Count;
convHulls[jj + 1] = 0f; // centroid x,y,z
convHulls[jj + 2] = 0f;
convHulls[jj + 3] = 0f;
jj += 4;
foreach (OMV.Vector3 oneVert in hullVerts)
{
convHulls[jj + 0] = oneVert.X;
convHulls[jj + 1] = oneVert.Y;
convHulls[jj + 2] = oneVert.Z;
jj += 3;
}
}
// create the hull data structure in Bullet
newShape = physicsScene.PE.CreateHullShape(physicsScene.World, hullCount, convHulls);
physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,assetHulls,hulls={1},totVert={2},shape={3}",
prim.LocalID, hullCount, totalVertices, newShape);
}
// If no hull specified in the asset and we should use Bullet's HACD approximation...
if (!newShape.HasPhysicalShape && BSParam.ShouldUseBulletHACD)
{ {
// Build the hull shape from an existing mesh shape. // Build the hull shape from an existing mesh shape.
// The mesh should have already been created in Bullet. // The mesh should have already been created in Bullet.
physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,shouldUseBulletHACD,entry", prim.LocalID); physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,bulletHACD,entry", prim.LocalID);
BSShape meshShape = BSShapeMesh.GetReference(physicsScene, true, prim); BSShape meshShape = BSShapeMesh.GetReference(physicsScene, true, prim);
if (meshShape.physShapeInfo.HasPhysicalShape) if (meshShape.physShapeInfo.HasPhysicalShape)
@ -585,129 +663,125 @@ public class BSShapeHull : BSShape
physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,hullFromMesh,beforeCall", prim.LocalID, newShape.HasPhysicalShape); physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,hullFromMesh,beforeCall", prim.LocalID, newShape.HasPhysicalShape);
newShape = physicsScene.PE.BuildHullShapeFromMesh(physicsScene.World, meshShape.physShapeInfo, parms); newShape = physicsScene.PE.BuildHullShapeFromMesh(physicsScene.World, meshShape.physShapeInfo, parms);
physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,hullFromMesh,hasBody={1}", prim.LocalID, newShape.HasPhysicalShape); physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,hullFromMesh,shape={1}", prim.LocalID, newShape);
// Now done with the mesh shape. // Now done with the mesh shape.
meshShape.Dereference(physicsScene); meshShape.Dereference(physicsScene);
} }
physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,shouldUseBulletHACD,exit,hasBody={1}", prim.LocalID, newShape.HasPhysicalShape); physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,bulletHACD,exit,hasBody={1}", prim.LocalID, newShape.HasPhysicalShape);
} }
if (!newShape.HasPhysicalShape)
// If no other hull specifications, use our HACD hull approximation.
if (!newShape.HasPhysicalShape && meshData != null)
{ {
// Build a new hull in the physical world using the C# HACD algorigthm. if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.Fetched)
// Pass true for physicalness as this prevents the creation of bounding box which is not needed
IMesh meshData = physicsScene.mesher.CreateMesh(prim.PhysObjectName, pbs, size, lod, true /* isPhysical */, false /* shouldCache */);
if (meshData != null)
{ {
if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.Fetched) // Release the fetched asset data once it has been used.
{ pbs.SculptData = new byte[0];
// Release the fetched asset data once it has been used. prim.PrimAssetState = BSPhysObject.PrimAssetCondition.Unknown;
pbs.SculptData = new byte[0];
prim.PrimAssetState = BSPhysObject.PrimAssetCondition.Unknown;
}
int[] indices = meshData.getIndexListAsInt();
List<OMV.Vector3> vertices = meshData.getVertexList();
//format conversion from IMesh format to DecompDesc format
List<int> convIndices = new List<int>();
List<float3> convVertices = new List<float3>();
for (int ii = 0; ii < indices.GetLength(0); ii++)
{
convIndices.Add(indices[ii]);
}
foreach (OMV.Vector3 vv in vertices)
{
convVertices.Add(new float3(vv.X, vv.Y, vv.Z));
}
uint maxDepthSplit = (uint)BSParam.CSHullMaxDepthSplit;
if (BSParam.CSHullMaxDepthSplit != BSParam.CSHullMaxDepthSplitForSimpleShapes)
{
// Simple primitive shapes we know are convex so they are better implemented with
// fewer hulls.
// Check for simple shape (prim without cuts) and reduce split parameter if so.
if (BSShapeCollection.PrimHasNoCuts(pbs))
{
maxDepthSplit = (uint)BSParam.CSHullMaxDepthSplitForSimpleShapes;
}
}
// setup and do convex hull conversion
m_hulls = new List<ConvexResult>();
DecompDesc dcomp = new DecompDesc();
dcomp.mIndices = convIndices;
dcomp.mVertices = convVertices;
dcomp.mDepth = maxDepthSplit;
dcomp.mCpercent = BSParam.CSHullConcavityThresholdPercent;
dcomp.mPpercent = BSParam.CSHullVolumeConservationThresholdPercent;
dcomp.mMaxVertices = (uint)BSParam.CSHullMaxVertices;
dcomp.mSkinWidth = BSParam.CSHullMaxSkinWidth;
ConvexBuilder convexBuilder = new ConvexBuilder(HullReturn);
// create the hull into the _hulls variable
convexBuilder.process(dcomp);
physicsScene.DetailLog("{0},BSShapeCollection.CreatePhysicalHull,key={1},inVert={2},inInd={3},split={4},hulls={5}",
BSScene.DetailLogZero, newHullKey, indices.GetLength(0), vertices.Count, maxDepthSplit, m_hulls.Count);
// Convert the vertices and indices for passing to unmanaged.
// The hull information is passed as a large floating point array.
// The format is:
// convHulls[0] = number of hulls
// convHulls[1] = number of vertices in first hull
// convHulls[2] = hull centroid X coordinate
// convHulls[3] = hull centroid Y coordinate
// convHulls[4] = hull centroid Z coordinate
// convHulls[5] = first hull vertex X
// convHulls[6] = first hull vertex Y
// convHulls[7] = first hull vertex Z
// convHulls[8] = second hull vertex X
// ...
// convHulls[n] = number of vertices in second hull
// convHulls[n+1] = second hull centroid X coordinate
// ...
//
// TODO: is is very inefficient. Someday change the convex hull generator to return
// data structures that do not need to be converted in order to pass to Bullet.
// And maybe put the values directly into pinned memory rather than marshaling.
int hullCount = m_hulls.Count;
int totalVertices = 1; // include one for the count of the hulls
foreach (ConvexResult cr in m_hulls)
{
totalVertices += 4; // add four for the vertex count and centroid
totalVertices += cr.HullIndices.Count * 3; // we pass just triangles
}
float[] convHulls = new float[totalVertices];
convHulls[0] = (float)hullCount;
int jj = 1;
foreach (ConvexResult cr in m_hulls)
{
// copy vertices for index access
float3[] verts = new float3[cr.HullVertices.Count];
int kk = 0;
foreach (float3 ff in cr.HullVertices)
{
verts[kk++] = ff;
}
// add to the array one hull's worth of data
convHulls[jj++] = cr.HullIndices.Count;
convHulls[jj++] = 0f; // centroid x,y,z
convHulls[jj++] = 0f;
convHulls[jj++] = 0f;
foreach (int ind in cr.HullIndices)
{
convHulls[jj++] = verts[ind].x;
convHulls[jj++] = verts[ind].y;
convHulls[jj++] = verts[ind].z;
}
}
// create the hull data structure in Bullet
newShape = physicsScene.PE.CreateHullShape(physicsScene.World, hullCount, convHulls);
} }
newShape.shapeKey = newHullKey;
int[] indices = meshData.getIndexListAsInt();
List<OMV.Vector3> vertices = meshData.getVertexList();
//format conversion from IMesh format to DecompDesc format
List<int> convIndices = new List<int>();
List<float3> convVertices = new List<float3>();
for (int ii = 0; ii < indices.GetLength(0); ii++)
{
convIndices.Add(indices[ii]);
}
foreach (OMV.Vector3 vv in vertices)
{
convVertices.Add(new float3(vv.X, vv.Y, vv.Z));
}
uint maxDepthSplit = (uint)BSParam.CSHullMaxDepthSplit;
if (BSParam.CSHullMaxDepthSplit != BSParam.CSHullMaxDepthSplitForSimpleShapes)
{
// Simple primitive shapes we know are convex so they are better implemented with
// fewer hulls.
// Check for simple shape (prim without cuts) and reduce split parameter if so.
if (BSShapeCollection.PrimHasNoCuts(pbs))
{
maxDepthSplit = (uint)BSParam.CSHullMaxDepthSplitForSimpleShapes;
}
}
// setup and do convex hull conversion
m_hulls = new List<ConvexResult>();
DecompDesc dcomp = new DecompDesc();
dcomp.mIndices = convIndices;
dcomp.mVertices = convVertices;
dcomp.mDepth = maxDepthSplit;
dcomp.mCpercent = BSParam.CSHullConcavityThresholdPercent;
dcomp.mPpercent = BSParam.CSHullVolumeConservationThresholdPercent;
dcomp.mMaxVertices = (uint)BSParam.CSHullMaxVertices;
dcomp.mSkinWidth = BSParam.CSHullMaxSkinWidth;
ConvexBuilder convexBuilder = new ConvexBuilder(HullReturn);
// create the hull into the _hulls variable
convexBuilder.process(dcomp);
physicsScene.DetailLog("{0},BSShapeCollection.CreatePhysicalHull,key={1},inVert={2},inInd={3},split={4},hulls={5}",
BSScene.DetailLogZero, newHullKey, indices.GetLength(0), vertices.Count, maxDepthSplit, m_hulls.Count);
// Convert the vertices and indices for passing to unmanaged.
// The hull information is passed as a large floating point array.
// The format is:
// convHulls[0] = number of hulls
// convHulls[1] = number of vertices in first hull
// convHulls[2] = hull centroid X coordinate
// convHulls[3] = hull centroid Y coordinate
// convHulls[4] = hull centroid Z coordinate
// convHulls[5] = first hull vertex X
// convHulls[6] = first hull vertex Y
// convHulls[7] = first hull vertex Z
// convHulls[8] = second hull vertex X
// ...
// convHulls[n] = number of vertices in second hull
// convHulls[n+1] = second hull centroid X coordinate
// ...
//
// TODO: is is very inefficient. Someday change the convex hull generator to return
// data structures that do not need to be converted in order to pass to Bullet.
// And maybe put the values directly into pinned memory rather than marshaling.
int hullCount = m_hulls.Count;
int totalVertices = 1; // include one for the count of the hulls
foreach (ConvexResult cr in m_hulls)
{
totalVertices += 4; // add four for the vertex count and centroid
totalVertices += cr.HullIndices.Count * 3; // we pass just triangles
}
float[] convHulls = new float[totalVertices];
convHulls[0] = (float)hullCount;
int jj = 1;
foreach (ConvexResult cr in m_hulls)
{
// copy vertices for index access
float3[] verts = new float3[cr.HullVertices.Count];
int kk = 0;
foreach (float3 ff in cr.HullVertices)
{
verts[kk++] = ff;
}
// add to the array one hull's worth of data
convHulls[jj++] = cr.HullIndices.Count;
convHulls[jj++] = 0f; // centroid x,y,z
convHulls[jj++] = 0f;
convHulls[jj++] = 0f;
foreach (int ind in cr.HullIndices)
{
convHulls[jj++] = verts[ind].x;
convHulls[jj++] = verts[ind].y;
convHulls[jj++] = verts[ind].z;
}
}
// create the hull data structure in Bullet
newShape = physicsScene.PE.CreateHullShape(physicsScene.World, hullCount, convHulls);
} }
newShape.shapeKey = newHullKey;
return newShape; return newShape;
} }
// Callback from convex hull creater with a newly created hull. // Callback from convex hull creater with a newly created hull.
@ -803,6 +877,7 @@ public class BSShapeCompound : BSShape
// Called at taint-time. // Called at taint-time.
private void DereferenceAnonCollisionShape(BSScene physicsScene, BulletShape pShape) private void DereferenceAnonCollisionShape(BSScene physicsScene, BulletShape pShape)
{ {
// TODO: figure a better way to go through all the shape types and find a possible instance.
BSShapeMesh meshDesc; BSShapeMesh meshDesc;
if (BSShapeMesh.TryGetMeshByPtr(pShape, out meshDesc)) if (BSShapeMesh.TryGetMeshByPtr(pShape, out meshDesc))
{ {
@ -824,17 +899,27 @@ public class BSShapeCompound : BSShape
} }
else else
{ {
if (physicsScene.PE.IsCompound(pShape)) BSShapeGImpact gImpactDesc;
if (BSShapeGImpact.TryGetGImpactByPtr(pShape, out gImpactDesc))
{ {
BSShapeCompound recursiveCompound = new BSShapeCompound(pShape); gImpactDesc.Dereference(physicsScene);
recursiveCompound.Dereference(physicsScene);
} }
else else
{ {
if (physicsScene.PE.IsNativeShape(pShape)) // Didn't find it in the lists of specific types. It could be compound.
if (physicsScene.PE.IsCompound(pShape))
{ {
BSShapeNative nativeShape = new BSShapeNative(pShape); BSShapeCompound recursiveCompound = new BSShapeCompound(pShape);
nativeShape.Dereference(physicsScene); recursiveCompound.Dereference(physicsScene);
}
else
{
// If none of the above, maybe it is a simple native shape.
if (physicsScene.PE.IsNativeShape(pShape))
{
BSShapeNative nativeShape = new BSShapeNative(pShape);
nativeShape.Dereference(physicsScene);
}
} }
} }
} }
@ -857,7 +942,7 @@ public class BSShapeConvexHull : BSShape
float lod; float lod;
System.UInt64 newMeshKey = BSShape.ComputeShapeKey(prim.Size, prim.BaseShape, out lod); System.UInt64 newMeshKey = BSShape.ComputeShapeKey(prim.Size, prim.BaseShape, out lod);
physicsScene.DetailLog("{0},BSShapeMesh,getReference,newKey={1},size={2},lod={3}", physicsScene.DetailLog("{0},BSShapeConvexHull,getReference,newKey={1},size={2},lod={3}",
prim.LocalID, newMeshKey.ToString("X"), prim.Size, lod); prim.LocalID, newMeshKey.ToString("X"), prim.Size, lod);
BSShapeConvexHull retConvexHull = null; BSShapeConvexHull retConvexHull = null;
@ -937,6 +1022,98 @@ public class BSShapeConvexHull : BSShape
return ret; return ret;
} }
} }
// ============================================================================================================
public class BSShapeGImpact : BSShape
{
private static string LogHeader = "[BULLETSIM SHAPE GIMPACT]";
public static Dictionary<System.UInt64, BSShapeGImpact> GImpacts = new Dictionary<System.UInt64, BSShapeGImpact>();
public BSShapeGImpact(BulletShape pShape) : base(pShape)
{
}
public static BSShape GetReference(BSScene physicsScene, bool forceRebuild, BSPhysObject prim)
{
float lod;
System.UInt64 newMeshKey = BSShape.ComputeShapeKey(prim.Size, prim.BaseShape, out lod);
physicsScene.DetailLog("{0},BSShapeGImpact,getReference,newKey={1},size={2},lod={3}",
prim.LocalID, newMeshKey.ToString("X"), prim.Size, lod);
BSShapeGImpact retGImpact = null;
lock (GImpacts)
{
if (GImpacts.TryGetValue(newMeshKey, out retGImpact))
{
// The mesh has already been created. Return a new reference to same.
retGImpact.IncrementReference();
}
else
{
retGImpact = new BSShapeGImpact(new BulletShape());
BulletShape newShape = retGImpact.CreatePhysicalGImpact(physicsScene, prim, newMeshKey, prim.BaseShape, prim.Size, lod);
// Check to see if mesh was created (might require an asset).
newShape = VerifyMeshCreated(physicsScene, newShape, prim);
newShape.shapeKey = newMeshKey;
if (!newShape.isNativeShape || prim.PrimAssetState == BSPhysObject.PrimAssetCondition.Failed)
{
// If a mesh was what was created, remember the built shape for later sharing.
// Also note that if meshing failed we put it in the mesh list as there is nothing else to do about the mesh.
GImpacts.Add(newMeshKey, retGImpact);
}
retGImpact.physShapeInfo = newShape;
}
}
return retGImpact;
}
private BulletShape CreatePhysicalGImpact(BSScene physicsScene, BSPhysObject prim, System.UInt64 newMeshKey,
PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
{
return BSShapeMesh.CreatePhysicalMeshShape(physicsScene, prim, newMeshKey, pbs, size, lod,
(w, iC, i, vC, v) => physicsScene.PE.CreateGImpactShape(w, iC, i, vC, v) );
}
public override BSShape GetReference(BSScene physicsScene, BSPhysObject prim)
{
// Calling this reference means we want another handle to an existing shape
// (usually linksets) so return this copy.
IncrementReference();
return this;
}
// Dereferencing a compound shape releases the hold on all the child shapes.
public override void Dereference(BSScene physicsScene)
{
lock (GImpacts)
{
this.DecrementReference();
physicsScene.DetailLog("{0},BSShapeGImpact.Dereference,shape={1}", BSScene.DetailLogZero, this);
// TODO: schedule aging and destruction of unused meshes.
}
}
// Loop through all the known hulls and return the description based on the physical address.
public static bool TryGetGImpactByPtr(BulletShape pShape, out BSShapeGImpact outHull)
{
bool ret = false;
BSShapeGImpact foundDesc = null;
lock (GImpacts)
{
foreach (BSShapeGImpact sh in GImpacts.Values)
{
if (sh.physShapeInfo.ReferenceSame(pShape))
{
foundDesc = sh;
ret = true;
break;
}
}
}
outHull = foundDesc;
return ret;
}
}
// ============================================================================================================ // ============================================================================================================
public class BSShapeAvatar : BSShape public class BSShapeAvatar : BSShape

View File

@ -1,16 +1,12 @@
PROBLEMS TO LOOK INTO CURRENT PROBLEMS TO FIX AND/OR LOOK AT
================================================= =================================================
Nebadon vehicle ride, get up, ride again. Second time vehicle does not act correctly. Script changing rotation of child prim while vehicle moving (eg turning wheel) causes
the wheel to appear to jump back. Looks like sending position from previous update.
Vehicle ride, get up, ride again. Second time vehicle does not act correctly.
Have to rez new vehicle and delete the old to fix situation. Have to rez new vehicle and delete the old to fix situation.
Hitting RESET on Nebadon's vehicle while riding causes vehicle to get into odd Hitting RESET on Nebadon's vehicle while riding causes vehicle to get into odd
position state where it will not settle onto ground properly, etc position state where it will not settle onto ground properly, etc
Two of Nebadon vehicles in a sim max the CPU. This is new. Two of Nebadon vehicles in a sim max the CPU. This is new.
A sitting, active vehicle bobs up and down a small amount.
CURRENT PRIORITIES
=================================================
Use the HACD convex hull routine in Bullet rather than the C# version.
Speed up hullifying large meshes.
Enable vehicle border crossings (at least as poorly as ODE) Enable vehicle border crossings (at least as poorly as ODE)
Terrain skirts Terrain skirts
Avatar created in previous region and not new region when crossing border Avatar created in previous region and not new region when crossing border
@ -361,4 +357,6 @@ Angular motion around Z moves the vehicle in world Z and not vehicle Z in ODE.
Nebadon vehicles turning funny in arena (DONE) Nebadon vehicles turning funny in arena (DONE)
Lock axis (DONE 20130401) Lock axis (DONE 20130401)
Terrain detail: double terrain mesh detail (DONE) Terrain detail: double terrain mesh detail (DONE)
Use the HACD convex hull routine in Bullet rather than the C# version.
Speed up hullifying large meshes. (DONE)

View File

@ -64,6 +64,7 @@ namespace OpenSim.Region.Physics.Meshing
public class Meshmerizer : IMesher public class Meshmerizer : IMesher
{ {
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private static string LogHeader = "[MESH]";
// Setting baseDir to a path will enable the dumping of raw files // Setting baseDir to a path will enable the dumping of raw files
// raw files can be imported by blender so a visual inspection of the results can be done // raw files can be imported by blender so a visual inspection of the results can be done
@ -72,6 +73,8 @@ namespace OpenSim.Region.Physics.Meshing
#else #else
private const string baseDir = null; //"rawFiles"; private const string baseDir = null; //"rawFiles";
#endif #endif
// If 'true', lots of DEBUG logging of asset parsing details
private bool debugDetail = false;
private bool cacheSculptMaps = true; private bool cacheSculptMaps = true;
private string decodedSculptMapPath = null; private string decodedSculptMapPath = null;
@ -80,6 +83,7 @@ namespace OpenSim.Region.Physics.Meshing
private float minSizeForComplexMesh = 0.2f; // prims with all dimensions smaller than this will have a bounding box mesh private float minSizeForComplexMesh = 0.2f; // prims with all dimensions smaller than this will have a bounding box mesh
private List<List<Vector3>> mConvexHulls = null; private List<List<Vector3>> mConvexHulls = null;
private List<Vector3> mBoundingHull = null;
private Dictionary<ulong, Mesh> m_uniqueMeshes = new Dictionary<ulong, Mesh>(); private Dictionary<ulong, Mesh> m_uniqueMeshes = new Dictionary<ulong, Mesh>();
@ -90,8 +94,11 @@ namespace OpenSim.Region.Physics.Meshing
decodedSculptMapPath = start_config.GetString("DecodedSculptMapPath","j2kDecodeCache"); decodedSculptMapPath = start_config.GetString("DecodedSculptMapPath","j2kDecodeCache");
cacheSculptMaps = start_config.GetBoolean("CacheSculptMaps", cacheSculptMaps); cacheSculptMaps = start_config.GetBoolean("CacheSculptMaps", cacheSculptMaps);
if(mesh_config != null) if (mesh_config != null)
{
useMeshiesPhysicsMesh = mesh_config.GetBoolean("UseMeshiesPhysicsMesh", useMeshiesPhysicsMesh); useMeshiesPhysicsMesh = mesh_config.GetBoolean("UseMeshiesPhysicsMesh", useMeshiesPhysicsMesh);
debugDetail = mesh_config.GetBoolean("LogMeshDetails", debugDetail);
}
try try
{ {
@ -321,6 +328,9 @@ namespace OpenSim.Region.Physics.Meshing
faces = new List<Face>(); faces = new List<Face>();
OSD meshOsd = null; OSD meshOsd = null;
mConvexHulls = null;
mBoundingHull = null;
if (primShape.SculptData.Length <= 0) if (primShape.SculptData.Length <= 0)
{ {
// XXX: At the moment we can not log here since ODEPrim, for instance, ends up triggering this // XXX: At the moment we can not log here since ODEPrim, for instance, ends up triggering this
@ -357,43 +367,79 @@ namespace OpenSim.Region.Physics.Meshing
OSDMap physicsParms = null; OSDMap physicsParms = null;
OSDMap map = (OSDMap)meshOsd; OSDMap map = (OSDMap)meshOsd;
if (map.ContainsKey("physics_shape")) if (map.ContainsKey("physics_shape"))
{
physicsParms = (OSDMap)map["physics_shape"]; // old asset format physicsParms = (OSDMap)map["physics_shape"]; // old asset format
if (debugDetail) m_log.DebugFormat("{0} prim='{1}': using 'physics_shape' mesh data", LogHeader, primName);
}
else if (map.ContainsKey("physics_mesh")) else if (map.ContainsKey("physics_mesh"))
{
physicsParms = (OSDMap)map["physics_mesh"]; // new asset format physicsParms = (OSDMap)map["physics_mesh"]; // new asset format
if (debugDetail) m_log.DebugFormat("{0} prim='{1}':using 'physics_mesh' mesh data", LogHeader, primName);
}
else if (map.ContainsKey("medium_lod")) else if (map.ContainsKey("medium_lod"))
{
physicsParms = (OSDMap)map["medium_lod"]; // if no physics mesh, try to fall back to medium LOD display mesh physicsParms = (OSDMap)map["medium_lod"]; // if no physics mesh, try to fall back to medium LOD display mesh
if (debugDetail) m_log.DebugFormat("{0} prim='{1}':using 'medium_lod' mesh data", LogHeader, primName);
}
else if (map.ContainsKey("high_lod")) else if (map.ContainsKey("high_lod"))
{
physicsParms = (OSDMap)map["high_lod"]; // if all else fails, use highest LOD display mesh and hope it works :) physicsParms = (OSDMap)map["high_lod"]; // if all else fails, use highest LOD display mesh and hope it works :)
if (debugDetail) m_log.DebugFormat("{0} prim='{1}':using 'high_lod' mesh data", LogHeader, primName);
}
if (map.ContainsKey("physics_convex")) if (map.ContainsKey("physics_convex"))
{ // pull this out also in case physics engine can use it { // pull this out also in case physics engine can use it
OSD convexBlockOsd = null;
try try
{ {
OSDMap convexBlock = (OSDMap)map["physics_convex"]; OSDMap convexBlock = (OSDMap)map["physics_convex"];
if (convexBlock.ContainsKey("HullList"))
{ {
byte[] hullList = convexBlock["HullList"].AsBinary(); int convexOffset = convexBlock["offset"].AsInteger() + (int)start;
int convexSize = convexBlock["size"].AsInteger();
byte[] convexBytes = new byte[convexSize];
System.Buffer.BlockCopy(primShape.SculptData, convexOffset, convexBytes, 0, convexSize);
try
{
convexBlockOsd = DecompressOsd(convexBytes);
}
catch (Exception e)
{
m_log.ErrorFormat("{0} prim='{1}': exception decoding convex block: {2}", LogHeader, primName, e);
//return false;
}
}
if (convexBlockOsd != null && convexBlockOsd is OSDMap)
{
convexBlock = convexBlockOsd as OSDMap;
if (debugDetail)
{
string keys = LogHeader + " keys found in convexBlock: ";
foreach (KeyValuePair<string, OSD> kvp in convexBlock)
keys += "'" + kvp.Key + "' ";
m_log.Debug(keys);
}
Vector3 min = new Vector3(-0.5f, -0.5f, -0.5f); Vector3 min = new Vector3(-0.5f, -0.5f, -0.5f);
if (convexBlock.ContainsKey("Min")) min = convexBlock["Min"].AsVector3(); if (convexBlock.ContainsKey("Min")) min = convexBlock["Min"].AsVector3();
Vector3 max = new Vector3(0.5f, 0.5f, 0.5f); Vector3 max = new Vector3(0.5f, 0.5f, 0.5f);
if (convexBlock.ContainsKey("Max")) max = convexBlock["Max"].AsVector3(); if (convexBlock.ContainsKey("Max")) max = convexBlock["Max"].AsVector3();
// decompress and decode hull points List<Vector3> boundingHull = null;
byte[] posBytes = DecompressOsd(convexBlock["Positions"].AsBinary()).AsBinary();
List<List<Vector3>> hulls = new List<List<Vector3>>();
int posNdx = 0;
foreach (byte cnt in hullList) if (convexBlock.ContainsKey("BoundingVerts"))
{ {
int count = cnt == 0 ? 256 : cnt; byte[] boundingVertsBytes = convexBlock["BoundingVerts"].AsBinary();
List<Vector3> hull = new List<Vector3>(); boundingHull = new List<Vector3>();
for (int i = 0; i < boundingVertsBytes.Length; )
for (int i = 0; i < count; i++)
{ {
ushort uX = Utils.BytesToUInt16(posBytes, posNdx); posNdx += 2; ushort uX = Utils.BytesToUInt16(boundingVertsBytes, i); i += 2;
ushort uY = Utils.BytesToUInt16(posBytes, posNdx); posNdx += 2; ushort uY = Utils.BytesToUInt16(boundingVertsBytes, i); i += 2;
ushort uZ = Utils.BytesToUInt16(posBytes, posNdx); posNdx += 2; ushort uZ = Utils.BytesToUInt16(boundingVertsBytes, i); i += 2;
Vector3 pos = new Vector3( Vector3 pos = new Vector3(
Utils.UInt16ToFloat(uX, min.X, max.X), Utils.UInt16ToFloat(uX, min.X, max.X),
@ -401,18 +447,57 @@ namespace OpenSim.Region.Physics.Meshing
Utils.UInt16ToFloat(uZ, min.Z, max.Z) Utils.UInt16ToFloat(uZ, min.Z, max.Z)
); );
hull.Add(pos); boundingHull.Add(pos);
} }
hulls.Add(hull); mBoundingHull = boundingHull;
if (debugDetail) m_log.DebugFormat("{0} prim='{1}': parsed bounding hull. nVerts={2}", LogHeader, primName, mBoundingHull.Count);
} }
mConvexHulls = hulls; if (convexBlock.ContainsKey("HullList"))
{
byte[] hullList = convexBlock["HullList"].AsBinary();
byte[] posBytes = convexBlock["Positions"].AsBinary();
List<List<Vector3>> hulls = new List<List<Vector3>>();
int posNdx = 0;
foreach (byte cnt in hullList)
{
int count = cnt == 0 ? 256 : cnt;
List<Vector3> hull = new List<Vector3>();
for (int i = 0; i < count; i++)
{
ushort uX = Utils.BytesToUInt16(posBytes, posNdx); posNdx += 2;
ushort uY = Utils.BytesToUInt16(posBytes, posNdx); posNdx += 2;
ushort uZ = Utils.BytesToUInt16(posBytes, posNdx); posNdx += 2;
Vector3 pos = new Vector3(
Utils.UInt16ToFloat(uX, min.X, max.X),
Utils.UInt16ToFloat(uY, min.Y, max.Y),
Utils.UInt16ToFloat(uZ, min.Z, max.Z)
);
hull.Add(pos);
}
hulls.Add(hull);
}
mConvexHulls = hulls;
if (debugDetail) m_log.DebugFormat("{0} prim='{1}': parsed hulls. nHulls={2}", LogHeader, primName, mConvexHulls.Count);
}
else
{
if (debugDetail) m_log.DebugFormat("{0} prim='{1}' has physics_convex but no HullList", LogHeader, primName);
}
} }
} }
catch (Exception e) catch (Exception e)
{ {
m_log.WarnFormat("[MESH]: exception decoding convex block: {0}", e.Message); m_log.WarnFormat("{0} exception decoding convex block: {1}", LogHeader, e);
} }
} }
@ -431,14 +516,14 @@ namespace OpenSim.Region.Physics.Meshing
OSD decodedMeshOsd = new OSD(); OSD decodedMeshOsd = new OSD();
byte[] meshBytes = new byte[physSize]; byte[] meshBytes = new byte[physSize];
System.Buffer.BlockCopy(primShape.SculptData, physOffset, meshBytes, 0, physSize); System.Buffer.BlockCopy(primShape.SculptData, physOffset, meshBytes, 0, physSize);
// byte[] decompressed = new byte[physSize * 5]; // byte[] decompressed = new byte[physSize * 5];
try try
{ {
decodedMeshOsd = DecompressOsd(meshBytes); decodedMeshOsd = DecompressOsd(meshBytes);
} }
catch (Exception e) catch (Exception e)
{ {
m_log.Error("[MESH]: exception decoding physical mesh: " + e.ToString()); m_log.ErrorFormat("{0} prim='{1}': exception decoding physical mesh: {2}", LogHeader, primName, e);
return false; return false;
} }
@ -447,7 +532,7 @@ namespace OpenSim.Region.Physics.Meshing
// physics_shape is an array of OSDMaps, one for each submesh // physics_shape is an array of OSDMaps, one for each submesh
if (decodedMeshOsd is OSDArray) if (decodedMeshOsd is OSDArray)
{ {
// Console.WriteLine("decodedMeshOsd for {0} - {1}", primName, Util.GetFormattedXml(decodedMeshOsd)); // Console.WriteLine("decodedMeshOsd for {0} - {1}", primName, Util.GetFormattedXml(decodedMeshOsd));
decodedMeshOsdArray = (OSDArray)decodedMeshOsd; decodedMeshOsdArray = (OSDArray)decodedMeshOsd;
foreach (OSD subMeshOsd in decodedMeshOsdArray) foreach (OSD subMeshOsd in decodedMeshOsdArray)
@ -455,6 +540,9 @@ namespace OpenSim.Region.Physics.Meshing
if (subMeshOsd is OSDMap) if (subMeshOsd is OSDMap)
AddSubMesh(subMeshOsd as OSDMap, size, coords, faces); AddSubMesh(subMeshOsd as OSDMap, size, coords, faces);
} }
if (debugDetail)
m_log.DebugFormat("{0} {1}: mesh decoded. offset={2}, size={3}, nCoords={4}, nFaces={5}",
LogHeader, primName, physOffset, physSize, coords.Count, faces.Count);
} }
} }
@ -772,6 +860,23 @@ namespace OpenSim.Region.Physics.Meshing
return true; return true;
} }
/// <summary>
/// temporary prototype code - please do not use until the interface has been finalized!
/// </summary>
/// <param name="size">value to scale the hull points by</param>
/// <returns>a list of vertices in the bounding hull if it exists and has been successfully decoded, otherwise null</returns>
public List<Vector3> GetBoundingHull(Vector3 size)
{
if (mBoundingHull == null)
return null;
List<Vector3> verts = new List<Vector3>();
foreach (var vert in mBoundingHull)
verts.Add(vert * size);
return verts;
}
/// <summary> /// <summary>
/// temporary prototype code - please do not use until the interface has been finalized! /// temporary prototype code - please do not use until the interface has been finalized!
/// </summary> /// </summary>
@ -788,6 +893,7 @@ namespace OpenSim.Region.Physics.Meshing
List<Vector3> verts = new List<Vector3>(); List<Vector3> verts = new List<Vector3>();
foreach (var vert in hull) foreach (var vert in hull)
verts.Add(vert * size); verts.Add(vert * size);
hulls.Add(verts);
} }
return hulls; return hulls;

View File

@ -2474,9 +2474,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
// send the sound, once, to all clients in range // send the sound, once, to all clients in range
if (m_SoundModule != null) if (m_SoundModule != null)
{ {
m_SoundModule.SendSound(m_host.UUID, m_SoundModule.SendSound(
ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound, AssetType.Sound), volume, false, 0, m_host.UUID,
0, false, false); ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound, AssetType.Sound),
volume, false, m_host.SoundQueueing ? (byte)SoundFlags.Queue : (byte)SoundFlags.None,
0, false, false);
} }
} }
@ -11822,7 +11824,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
public void llSetSoundQueueing(int queue) public void llSetSoundQueueing(int queue)
{ {
m_host.AddScriptLPS(1); m_host.AddScriptLPS(1);
NotImplemented("llSetSoundQueueing");
if (m_SoundModule != null)
m_SoundModule.SetSoundQueueing(m_host.UUID, queue == ScriptBaseClass.TRUE.value);
} }
public void llCollisionSprite(string impact_sprite) public void llCollisionSprite(string impact_sprite)

View File

@ -651,7 +651,7 @@ namespace OpenSim.Tests.Common.Mock
{ {
} }
public virtual void SendMoneyBalance(UUID transaction, bool success, byte[] description, int balance) public virtual void SendMoneyBalance(UUID transaction, bool success, byte[] description, int balance, int transactionType, UUID sourceID, bool sourceIsGroup, UUID destID, bool destIsGroup, int amount, string item)
{ {
} }
@ -875,11 +875,6 @@ namespace OpenSim.Tests.Common.Mock
} }
public bool AddMoney(int debit)
{
return false;
}
public void SendSunPos(Vector3 sunPos, Vector3 sunVel, ulong time, uint dlen, uint ylen, float phase) public void SendSunPos(Vector3 sunPos, Vector3 sunVel, ulong time, uint dlen, uint ylen, float phase)
{ {
} }

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1753,6 +1753,7 @@
<Reference name="OpenSim.Region.CoreModules"/> <Reference name="OpenSim.Region.CoreModules"/>
<Reference name="OpenSim.Framework.Console"/> <Reference name="OpenSim.Framework.Console"/>
<Reference name="OpenSim.Region.Physics.Manager"/> <Reference name="OpenSim.Region.Physics.Manager"/>
<Reference name="OpenSim.Region.Physics.Meshing" path="../../../../bin/Physics/"/>
<Reference name="OpenSim.Region.Physics.ConvexDecompositionDotNet"/> <Reference name="OpenSim.Region.Physics.ConvexDecompositionDotNet"/>
<Reference name="BulletXNA.dll" path="../../../../bin/"/> <Reference name="BulletXNA.dll" path="../../../../bin/"/>
<Reference name="log4net.dll" path="../../../../bin/"/> <Reference name="log4net.dll" path="../../../../bin/"/>