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.");
return UUID.Zero;
}
money.ApplyCharge(remoteClient.AgentId, money.GroupCreationCharge, "Group Creation");
money.ApplyCharge(remoteClient.AgentId, money.GroupCreationCharge, MoneyTransactionType.GroupCreate);
}
string reason = string.Empty;
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 Dictionary<int, List<AvatarAttachment>> m_attachments;
protected float m_avatarHeight = 0;
protected UUID[] m_texturehashes;
public virtual int Serial
{
@ -98,6 +99,8 @@ namespace OpenSim.Framework
SetDefaultParams();
SetHeight();
m_attachments = new Dictionary<int, List<AvatarAttachment>>();
ResetTextureHashes();
}
public AvatarAppearance(OSDMap map)
@ -108,32 +111,6 @@ namespace OpenSim.Framework
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)
{
}
@ -151,6 +128,8 @@ namespace OpenSim.Framework
SetHeight();
m_attachments = new Dictionary<int, List<AvatarAttachment>>();
ResetTextureHashes();
return;
}
@ -166,6 +145,10 @@ namespace OpenSim.Framework
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;
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()
{
m_wearables = new AvatarWearable[AvatarWearable.MAX_WEARABLES];
@ -223,12 +237,7 @@ namespace OpenSim.Framework
m_serial = 0;
SetDefaultTexture();
//for (int i = 0; i < BAKE_INDICES.Length; i++)
// {
// int idx = BAKE_INDICES[i];
// m_texture.FaceTextures[idx].TextureID = UUID.Zero;
// }
ResetTextureHashes();
}
protected virtual void SetDefaultParams()
@ -598,6 +607,12 @@ namespace OpenSim.Framework
data["serial"] = OSD.FromInteger(m_serial);
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
OSDArray wears = new OSDArray(AvatarWearable.MAX_WEARABLES);
for (int i = 0; i < AvatarWearable.MAX_WEARABLES; i++)
@ -642,6 +657,25 @@ namespace OpenSim.Framework
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
SetDefaultWearables();
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 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);
@ -1159,7 +1159,8 @@ namespace OpenSim.Framework
void SendTeleportStart(uint flags);
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 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,
string[] buttonlabels);
bool AddMoney(int debit);
/// <summary>
/// Update the client as to where the sun is currently located.
/// </summary>

View File

@ -38,7 +38,8 @@ namespace OpenSim.Framework
int GetBalance(UUID agentID);
bool UploadCovered(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);
int UploadCharge { get; }

View File

@ -2136,7 +2136,7 @@ namespace OpenSim.Framework
/// <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)
{
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(';');
if (parts.Length >= 1)

View File

@ -345,7 +345,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// protected HashSet<uint> m_attachmentsSent;
private int m_moneyBalance;
private int m_animationSequenceNumber = 1;
private bool m_SendLogoutPacketWhenClosing = true;
@ -420,7 +419,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
public string Name { get { return FirstName + " " + LastName; } }
public uint CircuitCode { get { return m_circuitCode; } }
public int MoneyBalance { get { return m_moneyBalance; } }
public int NextAnimationSequenceNumber { get { return m_animationSequenceNumber++; } }
/// <summary>
@ -483,7 +481,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
m_firstName = sessionInfo.LoginInfo.First;
m_lastName = sessionInfo.LoginInfo.Last;
m_startpos = sessionInfo.LoginInfo.StartPos;
m_moneyBalance = 1000;
m_udpServer = udpServer;
m_udpClient = udpClient;
@ -1538,7 +1535,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
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);
money.MoneyData.AgentID = AgentId;
@ -1546,7 +1543,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
money.MoneyData.TransactionSuccess = success;
money.MoneyData.Description = description;
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);
}
@ -2279,6 +2283,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// <returns></returns>
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);
alertPack.AgentData.AgentID = AgentId;
alertPack.AlertData.Message = Util.StringToBytes256(message);
@ -6214,7 +6223,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
if (appear.ObjectData.TextureEntry.Length > 1)
te = new Primitive.TextureEntry(appear.ObjectData.TextureEntry, 0, appear.ObjectData.TextureEntry.Length);
handlerSetAppearance(sender, te, visualparams);
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)
{
@ -11487,11 +11505,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP
requestArgs.Add(arg);
}
try
{
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;
}
@ -11916,17 +11942,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
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)
{
float locx = 0;

View File

@ -147,7 +147,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
/// <param name="visualParam"></param>
public void SetAppearance(IScenePresence sp, AvatarAppearance appearance)
{
SetAppearance(sp, appearance.Texture, appearance.VisualParams);
DoSetAppearance(sp, appearance.Texture, appearance.VisualParams, new List<CachedTextureRequestArg>());
}
/// <summary>
@ -157,6 +157,17 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
/// <param name="texture"></param>
/// <param name="visualParam"></param>
public void SetAppearance(IScenePresence sp, Primitive.TextureEntry textureEntry, byte[] visualParams)
{
DoSetAppearance(sp, textureEntry, visualParams, new List<CachedTextureRequestArg>());
}
/// <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}",
@ -191,7 +202,6 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
if (textureEntry != null)
{
// m_log.DebugFormat("[AVFACTORY]: Received texture update for {0} {1}", sp.Name, sp.UUID);
// WriteBakedTexturesReport(sp, m_log.DebugFormat);
changed = sp.Appearance.SetTextureEntries(textureEntry) || changed;
@ -202,6 +212,14 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
if (!ValidateBakedTextureCache(sp) && (((ScenePresence)sp).PresenceType != PresenceType.Npc))
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
// update transaction. In theory, we should be able to do an immediate
// appearance send and save here.
@ -622,12 +640,12 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
/// <param name="client"></param>
/// <param name="texture"></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);
ScenePresence sp = m_scene.GetScenePresence(client.AgentId);
if (sp != null)
SetAppearance(sp, textureEntry, visualParams);
DoSetAppearance(sp, textureEntry, visualParams, hashes);
else
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>
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);
List<CachedTextureResponseArg> cachedTextureResponse = new List<CachedTextureResponseArg>();
@ -695,23 +713,20 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
if (m_reusetextures)
{
// this is the most insanely dumb way to do this... however it seems to
// actually work. if the appearance has been reset because wearables have
// changed then the texture entries are zero'd out until the bakes are
// uploaded. on login, if the textures exist in the cache (eg if you logged
// into the simulator recently, then the appearance will pull those and send
// 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
// them out.
//
// a better solution (though how much better is an open question) is to
// store the hashes in the appearance and compare them. Thats's coming.
if (sp.Appearance.GetTextureHash(index) == request.WearableHashID)
{
Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[index];
if (face != null)
texture = face.TextureID;
}
else
{
// We know that that hash is wrong, null it out
// and wait for the setappearance call
sp.Appearance.SetTextureHash(index,UUID.Zero);
}
// m_log.WarnFormat("[AVFACTORY]: reuse texture {0} for index {1}",texture,index);
// m_log.WarnFormat("[AVFACTORY]: use texture {0} for index {1}; hash={2}",texture,index,request.WearableHashID);
}
CachedTextureResponseArg response = new CachedTextureResponseArg();

View File

@ -371,7 +371,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
foreach (string fid in outstanding)
{
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))
{
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)
{
first = "Unknown"; last = "User";
first = "Unknown"; last = "UserFMGAI";
if (!UUID.TryParse(fid, out agentID))
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)
{
first = "Unknown"; last = "User";
first = "Unknown"; last = "UserHGGAI";
if (base.GetAgentInfo(scopeID, fid, out agentID, out first, out last))
return true;

View File

@ -54,7 +54,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
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)
{
m_Enabled = true;

View File

@ -157,13 +157,16 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
}
else
{
string[] names = GetUserNames(uuid);
string[] names;
bool foundRealName = TryGetUserNames(uuid, out names);
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]);
}
}
}
@ -246,10 +249,15 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
}
// search the local cache
lock (m_UserCache)
{
foreach (UserData data in m_UserCache.Values)
{
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);
@ -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)
{
if (m_UserCache.ContainsKey(uuid))
{
returnstring[0] = m_UserCache[uuid].FirstName;
returnstring[1] = m_UserCache[uuid].LastName;
return returnstring;
names[0] = m_UserCache[uuid].FirstName;
names[1] = m_UserCache[uuid].LastName;
return true;
}
}
@ -290,8 +305,8 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
if (account != null)
{
returnstring[0] = account.FirstName;
returnstring[1] = account.LastName;
names[0] = account.FirstName;
names[1] = account.LastName;
UserData user = new UserData();
user.FirstName = account.FirstName;
@ -299,14 +314,16 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
lock (m_UserCache)
m_UserCache[uuid] = user;
return true;
}
else
{
returnstring[0] = "Unknown";
returnstring[1] = "User";
}
names[0] = "Unknown";
names[1] = "UserUMMTGUN";
return returnstring;
return false;
}
}
#region IUserManagement
@ -342,15 +359,17 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
public string GetUserName(UUID uuid)
{
string[] names = GetUserNames(uuid);
string[] names;
TryGetUserNames(uuid, out names);
if (names.Length == 2)
{
string firstname = names[0];
string lastname = names[1];
return firstname + " " + lastname;
}
return "(hippos)";
}
@ -466,12 +485,13 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
//ignore updates without creator data
return;
}
//try update unknown users
//and creator's home URL's
if ((oldUser.FirstName == "Unknown" && !creatorData.Contains ("Unknown")) || (oldUser.HomeURL != null && !creatorData.StartsWith (oldUser.HomeURL)))
{
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
{
@ -516,7 +536,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
else
{
user.FirstName = "Unknown";
user.LastName = "User";
user.LastName = "UserUMMAU";
}
AddUserInternal (user);
@ -547,6 +567,13 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
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,
"show names",
"show names",
@ -555,26 +582,54 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
HandleShowUsers);
}
private void HandleShowUsers(string module, string[] cmd)
private void HandleShowUser(string module, string[] cmd)
{
if (cmd.Length < 3)
{
MainConsole.Instance.OutputFormat("Usage: show name <uuid>");
return;
}
UUID userId;
if (!ConsoleUtil.TryParseConsoleUuid(MainConsole.Instance, cmd[2], out userId))
return;
string[] names;
UserData ud;
lock (m_UserCache)
{
if (m_UserCache.Count == 0)
if (!m_UserCache.TryGetValue(userId, out ud))
{
MainConsole.Instance.Output("No users found");
MainConsole.Instance.OutputFormat("No name known for user with id {0}", userId);
return;
}
}
MainConsole.Instance.Output("UUID User Name");
MainConsole.Instance.Output("-----------------------------------------------------------------------------");
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)
{
MainConsole.Instance.Output(String.Format("{0} {1} {2} ({3})",
kvp.Key, kvp.Value.FirstName, kvp.Value.LastName, kvp.Value.HomeURL));
cdt.AddRow(kvp.Key, string.Format("{0} {1}", kvp.Value.FirstName, kvp.Value.LastName), kvp.Value.HomeURL);
}
return;
}
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
}
}

View File

@ -104,7 +104,6 @@ namespace OpenSim.Region.Framework.Interfaces
/// <param name="sound">Sound asset ID</param>
/// <param name="volume">Sound volume</param>
/// <param name="triggered">Triggered or not.</param>
/// <param name="flags"></param>
/// <param name="radius">Sound radius</param>
/// <param name="useMaster">Play using 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>
void TriggerSoundLimited(UUID objectID, UUID sound, double volume,
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)
dupe.IsAttachment = true;
dupe.AbsolutePosition = new Vector3(AbsolutePosition.X, AbsolutePosition.Y, AbsolutePosition.Z);
dupe.m_sittingAvatars = new List<UUID>();
if (!userExposed)
{

View File

@ -219,6 +219,14 @@ namespace OpenSim.Region.Framework.Scenes
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 TimeStampLastActivity; // Will be used for AutoReturn
@ -1791,6 +1799,8 @@ namespace OpenSim.Region.Framework.Scenes
Array.Copy(Shape.ExtraParams, extraP, extraP.Length);
dupe.Shape.ExtraParams = extraP;
dupe.PayPrice = (int[])PayPrice.Clone();
dupe.DynAttrs.CopyFrom(DynAttrs);
if (userExposed)
@ -2429,7 +2439,7 @@ namespace OpenSim.Region.Framework.Scenes
if (soundModule != null)
{
soundModule.SendSound(UUID, CollisionSound,
CollisionSoundVolume, true, (byte)0, 0, false,
CollisionSoundVolume, true, 0, 0, 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
// appearance goes into the avatar update packet
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 (cachedappearance)

View File

@ -907,7 +907,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
// Mimicking LLClientView which gets always set appearance from client.
AvatarAppearance appearance;
m_scene.GetAvatarAppearance(this, out appearance);
OnSetAppearance(this, appearance.Texture, (byte[])appearance.VisualParams.Clone());
OnSetAppearance(this, appearance.Texture, (byte[])appearance.VisualParams.Clone(), new List<CachedTextureRequestArg>());
}
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)
{

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.");
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));

View File

@ -191,9 +191,14 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule
// Please do not refactor these to be just one method
// 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)
{
}
@ -322,7 +327,7 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule
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
{
@ -385,12 +390,12 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule
{
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)
{
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)
{
}

View File

@ -251,6 +251,16 @@ public override BulletShape CreateMeshShape(BulletWorld world,
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)
{
BulletWorldUnman worldu = world as BulletWorldUnman;
@ -1425,6 +1435,11 @@ public static extern IntPtr CreateMeshShape2(IntPtr world,
int indicesCount, [MarshalAs(UnmanagedType.LPArray)] int[] indices,
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]
public static extern IntPtr CreateHullShape2(IntPtr world,
int hullCount, [MarshalAs(UnmanagedType.LPArray)] float[] hulls);

View File

@ -1475,7 +1475,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
break;
case BroadphaseNativeTypes.CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE:
ret = BSPhysicsShapeType.SHAPE_MESH;
ret = BSPhysicsShapeType.SHAPE_CONVEXHULL;
break;
case BroadphaseNativeTypes.CONVEX_HULL_SHAPE_PROXYTYPE:
ret = BSPhysicsShapeType.SHAPE_HULL;
@ -1503,7 +1503,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
ret = BSPhysicsShapeType.SHAPE_CONE;
break;
case BroadphaseNativeTypes.CONVEX_SHAPE_PROXYTYPE:
ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
ret = BSPhysicsShapeType.SHAPE_CONVEXHULL;
break;
case BroadphaseNativeTypes.CYLINDER_SHAPE_PROXYTYPE:
ret = BSPhysicsShapeType.SHAPE_CYLINDER;
@ -1547,7 +1547,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
break;
///Used for GIMPACT Trimesh integration
case BroadphaseNativeTypes.GIMPACT_SHAPE_PROXYTYPE:
ret = BSPhysicsShapeType.SHAPE_MESH;
ret = BSPhysicsShapeType.SHAPE_GIMPACT;
break;
///Multimaterial mesh
case BroadphaseNativeTypes.MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE:
@ -1820,6 +1820,11 @@ private sealed class BulletConstraintXNA : BulletConstraint
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 )
{

View File

@ -71,6 +71,7 @@ public enum BSPhysicsShapeType
SHAPE_HEIGHTMAP = 23,
SHAPE_AVATAR = 24,
SHAPE_CONVEXHULL= 25,
SHAPE_GIMPACT = 26,
};
// The native shapes have predefined shape hash keys
@ -321,6 +322,10 @@ public abstract BulletShape CreateMeshShape(BulletWorld world,
int indicesCount, int[] indices,
int verticesCount, float[] vertices );
public abstract BulletShape CreateGImpactShape(BulletWorld world,
int indicesCount, int[] indices,
int verticesCount, float[] vertices );
public abstract BulletShape CreateHullShape(BulletWorld world,
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
// so it lets us go against all the rules and just compensates for them later.
// This forces rotation to be only around the Z axis and doesn't change any of the other axis.
// This keeps us from flipping the capsule over which the veiwer does not understand.
ForceOrientation = new OMV.Quaternion(0, 0, _orientation.Z,0);
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
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.UpdateInertiaTensor(ControllingPrim.PhysBody);

View File

@ -89,6 +89,8 @@ public static class BSParam
public static bool ShouldRemoveZeroWidthTriangles { get; private set; }
public static bool ShouldUseBulletHACD { 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 int TerrainMeshMagnification { get; private set; }
@ -146,6 +148,7 @@ public static class BSParam
public static float VehicleRestitution { get; private set; }
public static Vector3 VehicleLinearFactor { 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 VehicleAngularBankingTimescaleFudge { get; private set; }
public static bool VehicleDebuggingEnable { get; private set; }
@ -369,6 +372,10 @@ public static class BSParam
false ),
new ParameterDefn<bool>("ShouldUseSingleConvexHullForPrims", "If true, use a single convex hull shape for physical prims",
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",
5 ),
@ -577,6 +584,8 @@ public static class BSParam
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 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)",
0.0f ),
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()
{
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);
ActivateIfPhysical(false);
});

View File

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

View File

@ -230,6 +230,7 @@ public sealed class BSShapeCollection : IDisposable
BSShape potentialHull = null;
PrimitiveBaseShape pbs = prim.BaseShape;
// Use a simple, one section convex shape for prims that are probably convex (no cuts or twists)
if (BSParam.ShouldUseSingleConvexHullForPrims
&& pbs != null
&& !pbs.SculptEntry
@ -238,7 +239,17 @@ public sealed class BSShapeCollection : IDisposable
{
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);
}
@ -261,7 +272,7 @@ public sealed class BSShapeCollection : IDisposable
}
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);
// If the current shape is not what is on the prim at the moment, time to change.
if (!prim.PhysShape.HasPhysicalShape

View File

@ -31,6 +31,7 @@ using System.Text;
using OpenSim.Framework;
using OpenSim.Region.Physics.Manager;
using OpenSim.Region.Physics.Meshing;
using OpenSim.Region.Physics.ConvexDecompositionDotNet;
using OMV = OpenMetaverse;
@ -422,15 +423,32 @@ public class BSShapeMesh : BSShape
outMesh = foundDesc;
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,
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();
IMesh meshData = physicsScene.mesher.CreateMesh(prim.PhysObjectName, pbs, size, lod,
IMesh meshData = null;
lock (physicsScene.mesher)
{
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)
{
@ -482,8 +500,7 @@ public class BSShapeMesh : BSShape
if (realIndicesIndex != 0)
{
newShape = physicsScene.PE.CreateMeshShape(physicsScene.World,
realIndicesIndex, indices, verticesAsFloats.Length / 3, verticesAsFloats);
newShape = makeShape(physicsScene.World, realIndicesIndex, indices, verticesAsFloats.Length / 3, verticesAsFloats);
}
else
{
@ -561,13 +578,74 @@ public class BSShapeHull : BSShape
PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
{
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.
// 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);
if (meshShape.physShapeInfo.HasPhysicalShape)
@ -585,19 +663,16 @@ public class BSShapeHull : BSShape
physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,hullFromMesh,beforeCall", prim.LocalID, newShape.HasPhysicalShape);
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.
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)
{
// Build a new hull in the physical world using the C# HACD algorigthm.
// 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 no other hull specifications, use our HACD hull approximation.
if (!newShape.HasPhysicalShape && meshData != null)
{
if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.Fetched)
{
@ -707,7 +782,6 @@ public class BSShapeHull : BSShape
newShape = physicsScene.PE.CreateHullShape(physicsScene.World, hullCount, convHulls);
}
newShape.shapeKey = newHullKey;
}
return newShape;
}
// Callback from convex hull creater with a newly created hull.
@ -803,6 +877,7 @@ public class BSShapeCompound : BSShape
// Called at taint-time.
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;
if (BSShapeMesh.TryGetMeshByPtr(pShape, out meshDesc))
{
@ -824,6 +899,14 @@ public class BSShapeCompound : BSShape
}
else
{
BSShapeGImpact gImpactDesc;
if (BSShapeGImpact.TryGetGImpactByPtr(pShape, out gImpactDesc))
{
gImpactDesc.Dereference(physicsScene);
}
else
{
// Didn't find it in the lists of specific types. It could be compound.
if (physicsScene.PE.IsCompound(pShape))
{
BSShapeCompound recursiveCompound = new BSShapeCompound(pShape);
@ -831,6 +914,7 @@ public class BSShapeCompound : BSShape
}
else
{
// If none of the above, maybe it is a simple native shape.
if (physicsScene.PE.IsNativeShape(pShape))
{
BSShapeNative nativeShape = new BSShapeNative(pShape);
@ -842,6 +926,7 @@ public class BSShapeCompound : BSShape
}
}
}
}
// ============================================================================================================
public class BSShapeConvexHull : BSShape
@ -857,7 +942,7 @@ public class BSShapeConvexHull : BSShape
float 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);
BSShapeConvexHull retConvexHull = null;
@ -937,6 +1022,98 @@ public class BSShapeConvexHull : BSShape
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

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.
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
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)
Terrain skirts
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)
Lock axis (DONE 20130401)
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
{
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
// 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
private const string baseDir = null; //"rawFiles";
#endif
// If 'true', lots of DEBUG logging of asset parsing details
private bool debugDetail = false;
private bool cacheSculptMaps = true;
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 List<List<Vector3>> mConvexHulls = null;
private List<Vector3> mBoundingHull = null;
private Dictionary<ulong, Mesh> m_uniqueMeshes = new Dictionary<ulong, Mesh>();
@ -91,7 +95,10 @@ namespace OpenSim.Region.Physics.Meshing
decodedSculptMapPath = start_config.GetString("DecodedSculptMapPath","j2kDecodeCache");
cacheSculptMaps = start_config.GetBoolean("CacheSculptMaps", cacheSculptMaps);
if (mesh_config != null)
{
useMeshiesPhysicsMesh = mesh_config.GetBoolean("UseMeshiesPhysicsMesh", useMeshiesPhysicsMesh);
debugDetail = mesh_config.GetBoolean("LogMeshDetails", debugDetail);
}
try
{
@ -321,6 +328,9 @@ namespace OpenSim.Region.Physics.Meshing
faces = new List<Face>();
OSD meshOsd = null;
mConvexHulls = null;
mBoundingHull = null;
if (primShape.SculptData.Length <= 0)
{
// XXX: At the moment we can not log here since ODEPrim, for instance, ends up triggering this
@ -357,29 +367,98 @@ namespace OpenSim.Region.Physics.Meshing
OSDMap physicsParms = null;
OSDMap map = (OSDMap)meshOsd;
if (map.ContainsKey("physics_shape"))
{
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"))
{
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"))
{
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"))
{
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"))
{ // pull this out also in case physics engine can use it
OSD convexBlockOsd = null;
try
{
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);
if (convexBlock.ContainsKey("Min")) min = convexBlock["Min"].AsVector3();
Vector3 max = new Vector3(0.5f, 0.5f, 0.5f);
if (convexBlock.ContainsKey("Max")) max = convexBlock["Max"].AsVector3();
// decompress and decode hull points
byte[] posBytes = DecompressOsd(convexBlock["Positions"].AsBinary()).AsBinary();
List<Vector3> boundingHull = null;
if (convexBlock.ContainsKey("BoundingVerts"))
{
byte[] boundingVertsBytes = convexBlock["BoundingVerts"].AsBinary();
boundingHull = new List<Vector3>();
for (int i = 0; i < boundingVertsBytes.Length; )
{
ushort uX = Utils.BytesToUInt16(boundingVertsBytes, i); i += 2;
ushort uY = Utils.BytesToUInt16(boundingVertsBytes, i); i += 2;
ushort uZ = Utils.BytesToUInt16(boundingVertsBytes, i); i += 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)
);
boundingHull.Add(pos);
}
mBoundingHull = boundingHull;
if (debugDetail) m_log.DebugFormat("{0} prim='{1}': parsed bounding hull. nVerts={2}", LogHeader, primName, mBoundingHull.Count);
}
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;
@ -408,11 +487,17 @@ namespace OpenSim.Region.Physics.Meshing
}
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)
{
m_log.WarnFormat("[MESH]: exception decoding convex block: {0}", e.Message);
m_log.WarnFormat("{0} exception decoding convex block: {1}", LogHeader, e);
}
}
@ -438,7 +523,7 @@ namespace OpenSim.Region.Physics.Meshing
}
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;
}
@ -455,6 +540,9 @@ namespace OpenSim.Region.Physics.Meshing
if (subMeshOsd is OSDMap)
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;
}
/// <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>
/// temporary prototype code - please do not use until the interface has been finalized!
/// </summary>
@ -788,6 +893,7 @@ namespace OpenSim.Region.Physics.Meshing
List<Vector3> verts = new List<Vector3>();
foreach (var vert in hull)
verts.Add(vert * size);
hulls.Add(verts);
}
return hulls;

View File

@ -2474,8 +2474,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
// send the sound, once, to all clients in range
if (m_SoundModule != null)
{
m_SoundModule.SendSound(m_host.UUID,
ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound, AssetType.Sound), volume, false, 0,
m_SoundModule.SendSound(
m_host.UUID,
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)
{
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)

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)
{
}

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.Framework.Console"/>
<Reference name="OpenSim.Region.Physics.Manager"/>
<Reference name="OpenSim.Region.Physics.Meshing" path="../../../../bin/Physics/"/>
<Reference name="OpenSim.Region.Physics.ConvexDecompositionDotNet"/>
<Reference name="BulletXNA.dll" path="../../../../bin/"/>
<Reference name="log4net.dll" path="../../../../bin/"/>