aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Addons/Groups/GroupsModule.cs2
-rw-r--r--OpenSim/Framework/AvatarAppearance.cs98
-rw-r--r--OpenSim/Framework/IClientAPI.cs7
-rw-r--r--OpenSim/Framework/IMoneyModule.cs3
-rw-r--r--OpenSim/Framework/Util.cs2
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs57
-rw-r--r--OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs105
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs4
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/Framework/UserManagement/HGUserManagementModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs123
-rw-r--r--OpenSim/Region/CoreModules/World/Sound/SoundModule.cs9
-rw-r--r--OpenSim/Region/Framework/Interfaces/ISoundModule.cs8
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs12
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs4
-rw-r--r--OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs9
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs2
-rw-r--r--OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs13
-rw-r--r--OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs7
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSAPIUnman.cs15
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs11
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs5
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs11
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs3
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSParam.cs9
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs5
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSScene.cs8
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs15
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSShapes.cs415
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt14
-rw-r--r--OpenSim/Region/Physics/Meshing/Meshmerizer.cs152
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs12
-rw-r--r--OpenSim/Tests/Common/Mock/TestClient.cs7
-rwxr-xr-xbin/lib32/BulletSim.dllbin1010176 -> 982528 bytes
-rwxr-xr-xbin/lib32/libBulletSim.sobin2096576 -> 2271724 bytes
-rwxr-xr-xbin/lib64/BulletSim.dllbin1142272 -> 1222656 bytes
-rwxr-xr-xbin/lib64/libBulletSim.sobin2265980 -> 2454796 bytes
-rw-r--r--prebuild.xml1
39 files changed, 820 insertions, 334 deletions
diff --git a/OpenSim/Addons/Groups/GroupsModule.cs b/OpenSim/Addons/Groups/GroupsModule.cs
index 10bfa8f..f805d69 100644
--- a/OpenSim/Addons/Groups/GroupsModule.cs
+++ b/OpenSim/Addons/Groups/GroupsModule.cs
@@ -766,7 +766,7 @@ namespace OpenSim.Groups
766 remoteClient.SendCreateGroupReply(UUID.Zero, false, "Insufficient funds to create a group."); 766 remoteClient.SendCreateGroupReply(UUID.Zero, false, "Insufficient funds to create a group.");
767 return UUID.Zero; 767 return UUID.Zero;
768 } 768 }
769 money.ApplyCharge(remoteClient.AgentId, money.GroupCreationCharge, "Group Creation"); 769 money.ApplyCharge(remoteClient.AgentId, money.GroupCreationCharge, MoneyTransactionType.GroupCreate);
770 } 770 }
771 string reason = string.Empty; 771 string reason = string.Empty;
772 UUID groupID = m_groupData.CreateGroup(remoteClient.AgentId, name, charter, showInList, insigniaID, membershipFee, openEnrollment, 772 UUID groupID = m_groupData.CreateGroup(remoteClient.AgentId, name, charter, showInList, insigniaID, membershipFee, openEnrollment,
diff --git a/OpenSim/Framework/AvatarAppearance.cs b/OpenSim/Framework/AvatarAppearance.cs
index 494ae5e..157feb5 100644
--- a/OpenSim/Framework/AvatarAppearance.cs
+++ b/OpenSim/Framework/AvatarAppearance.cs
@@ -53,6 +53,7 @@ namespace OpenSim.Framework
53 protected AvatarWearable[] m_wearables; 53 protected AvatarWearable[] m_wearables;
54 protected Dictionary<int, List<AvatarAttachment>> m_attachments; 54 protected Dictionary<int, List<AvatarAttachment>> m_attachments;
55 protected float m_avatarHeight = 0; 55 protected float m_avatarHeight = 0;
56 protected UUID[] m_texturehashes;
56 57
57 public virtual int Serial 58 public virtual int Serial
58 { 59 {
@@ -98,6 +99,8 @@ namespace OpenSim.Framework
98 SetDefaultParams(); 99 SetDefaultParams();
99 SetHeight(); 100 SetHeight();
100 m_attachments = new Dictionary<int, List<AvatarAttachment>>(); 101 m_attachments = new Dictionary<int, List<AvatarAttachment>>();
102
103 ResetTextureHashes();
101 } 104 }
102 105
103 public AvatarAppearance(OSDMap map) 106 public AvatarAppearance(OSDMap map)
@@ -108,32 +111,6 @@ namespace OpenSim.Framework
108 SetHeight(); 111 SetHeight();
109 } 112 }
110 113
111 public AvatarAppearance(AvatarWearable[] wearables, Primitive.TextureEntry textureEntry, byte[] visualParams)
112 {
113// m_log.WarnFormat("[AVATAR APPEARANCE] create initialized appearance");
114
115 m_serial = 0;
116
117 if (wearables != null)
118 m_wearables = wearables;
119 else
120 SetDefaultWearables();
121
122 if (textureEntry != null)
123 m_texture = textureEntry;
124 else
125 SetDefaultTexture();
126
127 if (visualParams != null)
128 m_visualparams = visualParams;
129 else
130 SetDefaultParams();
131
132 SetHeight();
133
134 m_attachments = new Dictionary<int, List<AvatarAttachment>>();
135 }
136
137 public AvatarAppearance(AvatarAppearance appearance) : this(appearance, true) 114 public AvatarAppearance(AvatarAppearance appearance) : this(appearance, true)
138 { 115 {
139 } 116 }
@@ -151,6 +128,8 @@ namespace OpenSim.Framework
151 SetHeight(); 128 SetHeight();
152 m_attachments = new Dictionary<int, List<AvatarAttachment>>(); 129 m_attachments = new Dictionary<int, List<AvatarAttachment>>();
153 130
131 ResetTextureHashes();
132
154 return; 133 return;
155 } 134 }
156 135
@@ -166,6 +145,10 @@ namespace OpenSim.Framework
166 SetWearable(i,appearance.Wearables[i]); 145 SetWearable(i,appearance.Wearables[i]);
167 } 146 }
168 147
148 m_texturehashes = new UUID[AvatarAppearance.TEXTURE_COUNT];
149 for (int i = 0; i < AvatarAppearance.TEXTURE_COUNT; i++)
150 m_texturehashes[i] = new UUID(appearance.m_texturehashes[i]);
151
169 m_texture = null; 152 m_texture = null;
170 if (appearance.Texture != null) 153 if (appearance.Texture != null)
171 { 154 {
@@ -200,6 +183,37 @@ namespace OpenSim.Framework
200 } 183 }
201 } 184 }
202 185
186 public void ResetTextureHashes()
187 {
188 m_texturehashes = new UUID[AvatarAppearance.TEXTURE_COUNT];
189 for (uint i = 0; i < AvatarAppearance.TEXTURE_COUNT; i++)
190 m_texturehashes[i] = UUID.Zero;
191 }
192
193 public UUID GetTextureHash(int textureIndex)
194 {
195 return m_texturehashes[NormalizeBakedTextureIndex(textureIndex)];
196 }
197
198 public void SetTextureHash(int textureIndex, UUID textureHash)
199 {
200 m_texturehashes[NormalizeBakedTextureIndex(textureIndex)] = new UUID(textureHash);
201 }
202
203 /// <summary>
204 /// Normalizes the texture index to the actual bake index, this is done to
205 /// accommodate older viewers that send the BAKE_INDICES index rather than
206 /// the actual texture index
207 /// </summary>
208 private int NormalizeBakedTextureIndex(int textureIndex)
209 {
210 // Earlier viewer send the index into the baked index array, just trying to be careful here
211 if (textureIndex < BAKE_INDICES.Length)
212 return BAKE_INDICES[textureIndex];
213
214 return textureIndex;
215 }
216
203 public void ClearWearables() 217 public void ClearWearables()
204 { 218 {
205 m_wearables = new AvatarWearable[AvatarWearable.MAX_WEARABLES]; 219 m_wearables = new AvatarWearable[AvatarWearable.MAX_WEARABLES];
@@ -223,12 +237,7 @@ namespace OpenSim.Framework
223 m_serial = 0; 237 m_serial = 0;
224 238
225 SetDefaultTexture(); 239 SetDefaultTexture();
226 240 ResetTextureHashes();
227 //for (int i = 0; i < BAKE_INDICES.Length; i++)
228 // {
229 // int idx = BAKE_INDICES[i];
230 // m_texture.FaceTextures[idx].TextureID = UUID.Zero;
231 // }
232 } 241 }
233 242
234 protected virtual void SetDefaultParams() 243 protected virtual void SetDefaultParams()
@@ -598,6 +607,12 @@ namespace OpenSim.Framework
598 data["serial"] = OSD.FromInteger(m_serial); 607 data["serial"] = OSD.FromInteger(m_serial);
599 data["height"] = OSD.FromReal(m_avatarHeight); 608 data["height"] = OSD.FromReal(m_avatarHeight);
600 609
610 // Hashes
611 OSDArray hashes = new OSDArray(AvatarAppearance.TEXTURE_COUNT);
612 for (uint i = 0; i < AvatarAppearance.TEXTURE_COUNT; i++)
613 hashes.Add(OSD.FromUUID(m_texturehashes[i]));
614 data["hashes"] = hashes;
615
601 // Wearables 616 // Wearables
602 OSDArray wears = new OSDArray(AvatarWearable.MAX_WEARABLES); 617 OSDArray wears = new OSDArray(AvatarWearable.MAX_WEARABLES);
603 for (int i = 0; i < AvatarWearable.MAX_WEARABLES; i++) 618 for (int i = 0; i < AvatarWearable.MAX_WEARABLES; i++)
@@ -642,6 +657,25 @@ namespace OpenSim.Framework
642 657
643 try 658 try
644 { 659 {
660 // Hashes
661 m_texturehashes = new UUID[AvatarAppearance.TEXTURE_COUNT];
662 if ((data != null) && (data["hashes"] != null) && (data["hashes"]).Type == OSDType.Array)
663 {
664 OSDArray hashes = (OSDArray)(data["hashes"]);
665 for (int i = 0; i < AvatarAppearance.TEXTURE_COUNT; i++)
666 {
667 UUID hashID = UUID.Zero;
668 if (i < hashes.Count && hashes[i] != null)
669 hashID = hashes[i].AsUUID();
670 m_texturehashes[i] = hashID;
671 }
672 }
673 else
674 {
675 for (uint i = 0; i < AvatarAppearance.TEXTURE_COUNT; i++)
676 m_texturehashes[i] = UUID.Zero;
677 }
678
645 // Wearables 679 // Wearables
646 SetDefaultWearables(); 680 SetDefaultWearables();
647 if ((data != null) && (data["wearables"] != null) && (data["wearables"]).Type == OSDType.Array) 681 if ((data != null) && (data["wearables"] != null) && (data["wearables"]).Type == OSDType.Array)
diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs
index 59ce2c4..65f8395 100644
--- a/OpenSim/Framework/IClientAPI.cs
+++ b/OpenSim/Framework/IClientAPI.cs
@@ -66,7 +66,7 @@ namespace OpenSim.Framework
66 66
67 public delegate void CachedTextureRequest(IClientAPI remoteClient, int serial, List<CachedTextureRequestArg> cachedTextureRequest); 67 public delegate void CachedTextureRequest(IClientAPI remoteClient, int serial, List<CachedTextureRequestArg> cachedTextureRequest);
68 68
69 public delegate void SetAppearance(IClientAPI remoteClient, Primitive.TextureEntry textureEntry, byte[] visualParams); 69 public delegate void SetAppearance(IClientAPI remoteClient, Primitive.TextureEntry textureEntry, byte[] visualParams, List<CachedTextureRequestArg> cachedTextureData);
70 70
71 public delegate void StartAnim(IClientAPI remoteClient, UUID animID); 71 public delegate void StartAnim(IClientAPI remoteClient, UUID animID);
72 72
@@ -1159,7 +1159,8 @@ namespace OpenSim.Framework
1159 void SendTeleportStart(uint flags); 1159 void SendTeleportStart(uint flags);
1160 void SendTeleportProgress(uint flags, string message); 1160 void SendTeleportProgress(uint flags, string message);
1161 1161
1162 void SendMoneyBalance(UUID transaction, bool success, byte[] description, int balance); 1162 void SendMoneyBalance(UUID transaction, bool success, byte[] description, int balance, int transactionType, UUID sourceID, bool sourceIsGroup, UUID destID, bool destIsGroup, int amount, string item);
1163
1163 void SendPayPrice(UUID objectID, int[] payPrice); 1164 void SendPayPrice(UUID objectID, int[] payPrice);
1164 1165
1165 void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations); 1166 void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations);
@@ -1254,8 +1255,6 @@ namespace OpenSim.Framework
1254 void SendDialog(string objectname, UUID objectID, UUID ownerID, string ownerFirstName, string ownerLastName, string msg, UUID textureID, int ch, 1255 void SendDialog(string objectname, UUID objectID, UUID ownerID, string ownerFirstName, string ownerLastName, string msg, UUID textureID, int ch,
1255 string[] buttonlabels); 1256 string[] buttonlabels);
1256 1257
1257 bool AddMoney(int debit);
1258
1259 /// <summary> 1258 /// <summary>
1260 /// Update the client as to where the sun is currently located. 1259 /// Update the client as to where the sun is currently located.
1261 /// </summary> 1260 /// </summary>
diff --git a/OpenSim/Framework/IMoneyModule.cs b/OpenSim/Framework/IMoneyModule.cs
index 1e09728..52f3e83 100644
--- a/OpenSim/Framework/IMoneyModule.cs
+++ b/OpenSim/Framework/IMoneyModule.cs
@@ -38,7 +38,8 @@ namespace OpenSim.Framework
38 int GetBalance(UUID agentID); 38 int GetBalance(UUID agentID);
39 bool UploadCovered(UUID agentID, int amount); 39 bool UploadCovered(UUID agentID, int amount);
40 bool AmountCovered(UUID agentID, int amount); 40 bool AmountCovered(UUID agentID, int amount);
41 void ApplyCharge(UUID agentID, int amount, string text); 41 void ApplyCharge(UUID agentID, int amount, MoneyTransactionType type);
42 void ApplyCharge(UUID agentID, int amount, MoneyTransactionType type, string extraData);
42 void ApplyUploadCharge(UUID agentID, int amount, string text); 43 void ApplyUploadCharge(UUID agentID, int amount, string text);
43 44
44 int UploadCharge { get; } 45 int UploadCharge { get; }
diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs
index a3602e9..ada4e89 100644
--- a/OpenSim/Framework/Util.cs
+++ b/OpenSim/Framework/Util.cs
@@ -2136,7 +2136,7 @@ namespace OpenSim.Framework
2136 /// <param name="secret">the secret part</param> 2136 /// <param name="secret">the secret part</param>
2137 public static bool ParseUniversalUserIdentifier(string value, out UUID uuid, out string url, out string firstname, out string lastname, out string secret) 2137 public static bool ParseUniversalUserIdentifier(string value, out UUID uuid, out string url, out string firstname, out string lastname, out string secret)
2138 { 2138 {
2139 uuid = UUID.Zero; url = string.Empty; firstname = "Unknown"; lastname = "User"; secret = string.Empty; 2139 uuid = UUID.Zero; url = string.Empty; firstname = "Unknown"; lastname = "UserUPUUI"; secret = string.Empty;
2140 2140
2141 string[] parts = value.Split(';'); 2141 string[] parts = value.Split(';');
2142 if (parts.Length >= 1) 2142 if (parts.Length >= 1)
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
index e014471..e47397d 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
@@ -345,7 +345,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
345 345
346// protected HashSet<uint> m_attachmentsSent; 346// protected HashSet<uint> m_attachmentsSent;
347 347
348 private int m_moneyBalance;
349 private int m_animationSequenceNumber = 1; 348 private int m_animationSequenceNumber = 1;
350 private bool m_SendLogoutPacketWhenClosing = true; 349 private bool m_SendLogoutPacketWhenClosing = true;
351 350
@@ -420,7 +419,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
420 public string Name { get { return FirstName + " " + LastName; } } 419 public string Name { get { return FirstName + " " + LastName; } }
421 420
422 public uint CircuitCode { get { return m_circuitCode; } } 421 public uint CircuitCode { get { return m_circuitCode; } }
423 public int MoneyBalance { get { return m_moneyBalance; } }
424 public int NextAnimationSequenceNumber { get { return m_animationSequenceNumber++; } } 422 public int NextAnimationSequenceNumber { get { return m_animationSequenceNumber++; } }
425 423
426 /// <summary> 424 /// <summary>
@@ -483,7 +481,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
483 m_firstName = sessionInfo.LoginInfo.First; 481 m_firstName = sessionInfo.LoginInfo.First;
484 m_lastName = sessionInfo.LoginInfo.Last; 482 m_lastName = sessionInfo.LoginInfo.Last;
485 m_startpos = sessionInfo.LoginInfo.StartPos; 483 m_startpos = sessionInfo.LoginInfo.StartPos;
486 m_moneyBalance = 1000;
487 484
488 m_udpServer = udpServer; 485 m_udpServer = udpServer;
489 m_udpClient = udpClient; 486 m_udpClient = udpClient;
@@ -1538,7 +1535,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1538 OutPacket(tpProgress, ThrottleOutPacketType.Unknown); 1535 OutPacket(tpProgress, ThrottleOutPacketType.Unknown);
1539 } 1536 }
1540 1537
1541 public void SendMoneyBalance(UUID transaction, bool success, byte[] description, int balance) 1538 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)
1542 { 1539 {
1543 MoneyBalanceReplyPacket money = (MoneyBalanceReplyPacket)PacketPool.Instance.GetPacket(PacketType.MoneyBalanceReply); 1540 MoneyBalanceReplyPacket money = (MoneyBalanceReplyPacket)PacketPool.Instance.GetPacket(PacketType.MoneyBalanceReply);
1544 money.MoneyData.AgentID = AgentId; 1541 money.MoneyData.AgentID = AgentId;
@@ -1546,7 +1543,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1546 money.MoneyData.TransactionSuccess = success; 1543 money.MoneyData.TransactionSuccess = success;
1547 money.MoneyData.Description = description; 1544 money.MoneyData.Description = description;
1548 money.MoneyData.MoneyBalance = balance; 1545 money.MoneyData.MoneyBalance = balance;
1549 money.TransactionInfo.ItemDescription = Util.StringToBytes256("NONE"); 1546 money.TransactionInfo.TransactionType = transactionType;
1547 money.TransactionInfo.SourceID = sourceID;
1548 money.TransactionInfo.IsSourceGroup = sourceIsGroup;
1549 money.TransactionInfo.DestID = destID;
1550 money.TransactionInfo.IsDestGroup = destIsGroup;
1551 money.TransactionInfo.Amount = amount;
1552 money.TransactionInfo.ItemDescription = Util.StringToBytes256(item);
1553
1550 OutPacket(money, ThrottleOutPacketType.Task); 1554 OutPacket(money, ThrottleOutPacketType.Task);
1551 } 1555 }
1552 1556
@@ -2279,6 +2283,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2279 /// <returns></returns> 2283 /// <returns></returns>
2280 public AgentAlertMessagePacket BuildAgentAlertPacket(string message, bool modal) 2284 public AgentAlertMessagePacket BuildAgentAlertPacket(string message, bool modal)
2281 { 2285 {
2286 // Prepend a slash to make the message come up in the top right
2287 // again.
2288 // Allow special formats to be sent from aware modules.
2289 if (!modal && !message.StartsWith("ALERT: ") && !message.StartsWith("NOTIFY: ") && message != "Home position set." && message != "You died and have been teleported to your home location")
2290 message = "/" + message;
2282 AgentAlertMessagePacket alertPack = (AgentAlertMessagePacket)PacketPool.Instance.GetPacket(PacketType.AgentAlertMessage); 2291 AgentAlertMessagePacket alertPack = (AgentAlertMessagePacket)PacketPool.Instance.GetPacket(PacketType.AgentAlertMessage);
2283 alertPack.AgentData.AgentID = AgentId; 2292 alertPack.AgentData.AgentID = AgentId;
2284 alertPack.AlertData.Message = Util.StringToBytes256(message); 2293 alertPack.AlertData.Message = Util.StringToBytes256(message);
@@ -6214,7 +6223,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6214 if (appear.ObjectData.TextureEntry.Length > 1) 6223 if (appear.ObjectData.TextureEntry.Length > 1)
6215 te = new Primitive.TextureEntry(appear.ObjectData.TextureEntry, 0, appear.ObjectData.TextureEntry.Length); 6224 te = new Primitive.TextureEntry(appear.ObjectData.TextureEntry, 0, appear.ObjectData.TextureEntry.Length);
6216 6225
6217 handlerSetAppearance(sender, te, visualparams); 6226 List<CachedTextureRequestArg> hashes = new List<CachedTextureRequestArg>();
6227 for (int i = 0; i < appear.WearableData.Length; i++)
6228 {
6229 CachedTextureRequestArg arg = new CachedTextureRequestArg();
6230 arg.BakedTextureIndex = appear.WearableData[i].TextureIndex;
6231 arg.WearableHashID = appear.WearableData[i].CacheID;
6232 hashes.Add(arg);
6233 }
6234
6235 handlerSetAppearance(sender, te, visualparams, hashes);
6218 } 6236 }
6219 catch (Exception e) 6237 catch (Exception e)
6220 { 6238 {
@@ -11487,12 +11505,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11487 requestArgs.Add(arg); 11505 requestArgs.Add(arg);
11488 } 11506 }
11489 11507
11490 CachedTextureRequest handlerCachedTextureRequest = OnCachedTextureRequest; 11508 try
11491 if (handlerCachedTextureRequest != null)
11492 { 11509 {
11493 handlerCachedTextureRequest(simclient,cachedtex.AgentData.SerialNum,requestArgs); 11510 CachedTextureRequest handlerCachedTextureRequest = OnCachedTextureRequest;
11511 if (handlerCachedTextureRequest != null)
11512 {
11513 handlerCachedTextureRequest(simclient,cachedtex.AgentData.SerialNum,requestArgs);
11514 }
11494 } 11515 }
11495 11516 catch (Exception e)
11517 {
11518 m_log.ErrorFormat("[CLIENT VIEW]: AgentTextureCached packet handler threw an exception, {0}", e);
11519 return false;
11520 }
11521
11496 return true; 11522 return true;
11497 } 11523 }
11498 11524
@@ -11916,17 +11942,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11916 m_udpServer.SendPacket(m_udpClient, packet, throttlePacketType, doAutomaticSplitting, method); 11942 m_udpServer.SendPacket(m_udpClient, packet, throttlePacketType, doAutomaticSplitting, method);
11917 } 11943 }
11918 11944
11919 public bool AddMoney(int debit)
11920 {
11921 if (m_moneyBalance + debit >= 0)
11922 {
11923 m_moneyBalance += debit;
11924 SendMoneyBalance(UUID.Zero, true, Util.StringToBytes256("Poof Poof!"), m_moneyBalance);
11925 return true;
11926 }
11927 return false;
11928 }
11929
11930 protected void HandleAutopilot(Object sender, string method, List<String> args) 11945 protected void HandleAutopilot(Object sender, string method, List<String> args)
11931 { 11946 {
11932 float locx = 0; 11947 float locx = 0;
diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
index b640b48..aea768e 100644
--- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
@@ -147,7 +147,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
147 /// <param name="visualParam"></param> 147 /// <param name="visualParam"></param>
148 public void SetAppearance(IScenePresence sp, AvatarAppearance appearance) 148 public void SetAppearance(IScenePresence sp, AvatarAppearance appearance)
149 { 149 {
150 SetAppearance(sp, appearance.Texture, appearance.VisualParams); 150 DoSetAppearance(sp, appearance.Texture, appearance.VisualParams, new List<CachedTextureRequestArg>());
151 } 151 }
152 152
153 /// <summary> 153 /// <summary>
@@ -158,9 +158,20 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
158 /// <param name="visualParam"></param> 158 /// <param name="visualParam"></param>
159 public void SetAppearance(IScenePresence sp, Primitive.TextureEntry textureEntry, byte[] visualParams) 159 public void SetAppearance(IScenePresence sp, Primitive.TextureEntry textureEntry, byte[] visualParams)
160 { 160 {
161// m_log.DebugFormat( 161 DoSetAppearance(sp, textureEntry, visualParams, new List<CachedTextureRequestArg>());
162// "[AVFACTORY]: start SetAppearance for {0}, te {1}, visualParams {2}", 162 }
163// sp.Name, textureEntry, visualParams); 163
164 /// <summary>
165 /// Set appearance data (texture asset IDs and slider settings)
166 /// </summary>
167 /// <param name="sp"></param>
168 /// <param name="texture"></param>
169 /// <param name="visualParam"></param>
170 protected void DoSetAppearance(IScenePresence sp, Primitive.TextureEntry textureEntry, byte[] visualParams, List<CachedTextureRequestArg> hashes)
171 {
172 // m_log.DebugFormat(
173 // "[AVFACTORY]: start SetAppearance for {0}, te {1}, visualParams {2}",
174 // sp.Name, textureEntry, visualParams);
164 175
165 // TODO: This is probably not necessary any longer, just assume the 176 // TODO: This is probably not necessary any longer, just assume the
166 // textureEntry set implies that the appearance transaction is complete 177 // textureEntry set implies that the appearance transaction is complete
@@ -190,18 +201,25 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
190 // Process the baked texture array 201 // Process the baked texture array
191 if (textureEntry != null) 202 if (textureEntry != null)
192 { 203 {
193// m_log.DebugFormat("[AVFACTORY]: Received texture update for {0} {1}", sp.Name, sp.UUID); 204 // m_log.DebugFormat("[AVFACTORY]: Received texture update for {0} {1}", sp.Name, sp.UUID);
194 205 // WriteBakedTexturesReport(sp, m_log.DebugFormat);
195// WriteBakedTexturesReport(sp, m_log.DebugFormat);
196 206
197 changed = sp.Appearance.SetTextureEntries(textureEntry) || changed; 207 changed = sp.Appearance.SetTextureEntries(textureEntry) || changed;
198 208
199// WriteBakedTexturesReport(sp, m_log.DebugFormat); 209 // WriteBakedTexturesReport(sp, m_log.DebugFormat);
200 210
201 // If bake textures are missing and this is not an NPC, request a rebake from client 211 // If bake textures are missing and this is not an NPC, request a rebake from client
202 if (!ValidateBakedTextureCache(sp) && (((ScenePresence)sp).PresenceType != PresenceType.Npc)) 212 if (!ValidateBakedTextureCache(sp) && (((ScenePresence)sp).PresenceType != PresenceType.Npc))
203 RequestRebake(sp, true); 213 RequestRebake(sp, true);
204 214
215 // Save the wearble hashes in the appearance
216 sp.Appearance.ResetTextureHashes();
217 if (m_reusetextures)
218 {
219 foreach (CachedTextureRequestArg arg in hashes)
220 sp.Appearance.SetTextureHash(arg.BakedTextureIndex,arg.WearableHashID);
221 }
222
205 // This appears to be set only in the final stage of the appearance 223 // This appears to be set only in the final stage of the appearance
206 // update transaction. In theory, we should be able to do an immediate 224 // update transaction. In theory, we should be able to do an immediate
207 // appearance send and save here. 225 // appearance send and save here.
@@ -235,13 +253,13 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
235 253
236 public bool SendAppearance(UUID agentId) 254 public bool SendAppearance(UUID agentId)
237 { 255 {
238// m_log.DebugFormat("[AVFACTORY]: Sending appearance for {0}", agentId); 256 // m_log.DebugFormat("[AVFACTORY]: Sending appearance for {0}", agentId);
239 257
240 ScenePresence sp = m_scene.GetScenePresence(agentId); 258 ScenePresence sp = m_scene.GetScenePresence(agentId);
241 if (sp == null) 259 if (sp == null)
242 { 260 {
243 // This is expected if the user has gone away. 261 // This is expected if the user has gone away.
244// m_log.DebugFormat("[AVFACTORY]: Agent {0} no longer in the scene", agentId); 262 // m_log.DebugFormat("[AVFACTORY]: Agent {0} no longer in the scene", agentId);
245 return false; 263 return false;
246 } 264 }
247 265
@@ -318,7 +336,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
318 /// <param name="agentId"></param> 336 /// <param name="agentId"></param>
319 public void QueueAppearanceSend(UUID agentid) 337 public void QueueAppearanceSend(UUID agentid)
320 { 338 {
321// m_log.DebugFormat("[AVFACTORY]: Queue appearance send for {0}", agentid); 339 // m_log.DebugFormat("[AVFACTORY]: Queue appearance send for {0}", agentid);
322 340
323 // 10000 ticks per millisecond, 1000 milliseconds per second 341 // 10000 ticks per millisecond, 1000 milliseconds per second
324 long timestamp = DateTime.Now.Ticks + Convert.ToInt64(m_sendtime * 1000 * 10000); 342 long timestamp = DateTime.Now.Ticks + Convert.ToInt64(m_sendtime * 1000 * 10000);
@@ -331,7 +349,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
331 349
332 public void QueueAppearanceSave(UUID agentid) 350 public void QueueAppearanceSave(UUID agentid)
333 { 351 {
334// m_log.DebugFormat("[AVFACTORY]: Queueing appearance save for {0}", agentid); 352 // m_log.DebugFormat("[AVFACTORY]: Queueing appearance save for {0}", agentid);
335 353
336 // 10000 ticks per millisecond, 1000 milliseconds per second 354 // 10000 ticks per millisecond, 1000 milliseconds per second
337 long timestamp = DateTime.Now.Ticks + Convert.ToInt64(m_savetime * 1000 * 10000); 355 long timestamp = DateTime.Now.Ticks + Convert.ToInt64(m_savetime * 1000 * 10000);
@@ -356,9 +374,9 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
356 if (face == null) 374 if (face == null)
357 continue; 375 continue;
358 376
359// m_log.DebugFormat( 377 // m_log.DebugFormat(
360// "[AVFACTORY]: Looking for texture {0}, id {1} for {2} {3}", 378 // "[AVFACTORY]: Looking for texture {0}, id {1} for {2} {3}",
361// face.TextureID, idx, client.Name, client.AgentId); 379 // face.TextureID, idx, client.Name, client.AgentId);
362 380
363 // if the texture is one of the "defaults" then skip it 381 // if the texture is one of the "defaults" then skip it
364 // this should probably be more intelligent (skirt texture doesnt matter 382 // this should probably be more intelligent (skirt texture doesnt matter
@@ -373,7 +391,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
373 return false; 391 return false;
374 } 392 }
375 393
376// m_log.DebugFormat("[AVFACTORY]: Completed texture check for {0} {1}", sp.Name, sp.UUID); 394 // m_log.DebugFormat("[AVFACTORY]: Completed texture check for {0} {1}", sp.Name, sp.UUID);
377 395
378 // If we only found default textures, then the appearance is not cached 396 // If we only found default textures, then the appearance is not cached
379 return (defonly ? false : true); 397 return (defonly ? false : true);
@@ -392,9 +410,9 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
392 if (face == null) 410 if (face == null)
393 continue; 411 continue;
394 412
395// m_log.DebugFormat( 413 // m_log.DebugFormat(
396// "[AVFACTORY]: Looking for texture {0}, id {1} for {2} {3}", 414 // "[AVFACTORY]: Looking for texture {0}, id {1} for {2} {3}",
397// face.TextureID, idx, client.Name, client.AgentId); 415 // face.TextureID, idx, client.Name, client.AgentId);
398 416
399 // if the texture is one of the "defaults" then skip it 417 // if the texture is one of the "defaults" then skip it
400 // this should probably be more intelligent (skirt texture doesnt matter 418 // this should probably be more intelligent (skirt texture doesnt matter
@@ -458,9 +476,9 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
458 if (bakeType == BakeType.Unknown) 476 if (bakeType == BakeType.Unknown)
459 continue; 477 continue;
460 478
461// m_log.DebugFormat( 479 // m_log.DebugFormat(
462// "[AVFACTORY]: NPC avatar {0} has texture id {1} : {2}", 480 // "[AVFACTORY]: NPC avatar {0} has texture id {1} : {2}",
463// acd.AgentID, i, acd.Appearance.Texture.FaceTextures[i]); 481 // acd.AgentID, i, acd.Appearance.Texture.FaceTextures[i]);
464 482
465 int ftIndex = (int)AppearanceManager.BakeTypeToAgentTextureIndex(bakeType); 483 int ftIndex = (int)AppearanceManager.BakeTypeToAgentTextureIndex(bakeType);
466 Primitive.TextureEntryFace texture = faceTextures[ftIndex]; // this will be null if there's no such baked texture 484 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
484 UUID avatarID = kvp.Key; 502 UUID avatarID = kvp.Key;
485 long sendTime = kvp.Value; 503 long sendTime = kvp.Value;
486 504
487// m_log.DebugFormat("[AVFACTORY]: Handling queued appearance updates for {0}, update delta to now is {1}", avatarID, sendTime - now); 505 // m_log.DebugFormat("[AVFACTORY]: Handling queued appearance updates for {0}, update delta to now is {1}", avatarID, sendTime - now);
488 506
489 if (sendTime < now) 507 if (sendTime < now)
490 { 508 {
@@ -530,11 +548,11 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
530 if (sp == null) 548 if (sp == null)
531 { 549 {
532 // This is expected if the user has gone away. 550 // This is expected if the user has gone away.
533// m_log.DebugFormat("[AVFACTORY]: Agent {0} no longer in the scene", agentid); 551 // m_log.DebugFormat("[AVFACTORY]: Agent {0} no longer in the scene", agentid);
534 return; 552 return;
535 } 553 }
536 554
537// m_log.DebugFormat("[AVFACTORY]: Saving appearance for avatar {0}", agentid); 555 // m_log.DebugFormat("[AVFACTORY]: Saving appearance for avatar {0}", agentid);
538 556
539 // This could take awhile since it needs to pull inventory 557 // This could take awhile since it needs to pull inventory
540 // 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 558 // 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
622 /// <param name="client"></param> 640 /// <param name="client"></param>
623 /// <param name="texture"></param> 641 /// <param name="texture"></param>
624 /// <param name="visualParam"></param> 642 /// <param name="visualParam"></param>
625 private void Client_OnSetAppearance(IClientAPI client, Primitive.TextureEntry textureEntry, byte[] visualParams) 643 private void Client_OnSetAppearance(IClientAPI client, Primitive.TextureEntry textureEntry, byte[] visualParams, List<CachedTextureRequestArg> hashes)
626 { 644 {
627 // m_log.WarnFormat("[AVFACTORY]: Client_OnSetAppearance called for {0} ({1})", client.Name, client.AgentId); 645 // m_log.WarnFormat("[AVFACTORY]: Client_OnSetAppearance called for {0} ({1})", client.Name, client.AgentId);
628 ScenePresence sp = m_scene.GetScenePresence(client.AgentId); 646 ScenePresence sp = m_scene.GetScenePresence(client.AgentId);
629 if (sp != null) 647 if (sp != null)
630 SetAppearance(sp, textureEntry, visualParams); 648 DoSetAppearance(sp, textureEntry, visualParams, hashes);
631 else 649 else
632 m_log.WarnFormat("[AVFACTORY]: Client_OnSetAppearance unable to find presence for {0}", client.AgentId); 650 m_log.WarnFormat("[AVFACTORY]: Client_OnSetAppearance unable to find presence for {0}", client.AgentId);
633 } 651 }
@@ -684,7 +702,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
684 /// <param name="cachedTextureRequest"></param> 702 /// <param name="cachedTextureRequest"></param>
685 private void Client_OnCachedTextureRequest(IClientAPI client, int serial, List<CachedTextureRequestArg> cachedTextureRequest) 703 private void Client_OnCachedTextureRequest(IClientAPI client, int serial, List<CachedTextureRequestArg> cachedTextureRequest)
686 { 704 {
687 // m_log.WarnFormat("[AVFACTORY]: Client_OnCachedTextureRequest called for {0} ({1})", client.Name, client.AgentId); 705 // m_log.DebugFormat("[AVFACTORY]: Client_OnCachedTextureRequest called for {0} ({1})", client.Name, client.AgentId);
688 ScenePresence sp = m_scene.GetScenePresence(client.AgentId); 706 ScenePresence sp = m_scene.GetScenePresence(client.AgentId);
689 707
690 List<CachedTextureResponseArg> cachedTextureResponse = new List<CachedTextureResponseArg>(); 708 List<CachedTextureResponseArg> cachedTextureResponse = new List<CachedTextureResponseArg>();
@@ -695,23 +713,20 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
695 713
696 if (m_reusetextures) 714 if (m_reusetextures)
697 { 715 {
698 // this is the most insanely dumb way to do this... however it seems to 716 if (sp.Appearance.GetTextureHash(index) == request.WearableHashID)
699 // actually work. if the appearance has been reset because wearables have 717 {
700 // changed then the texture entries are zero'd out until the bakes are 718 Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[index];
701 // uploaded. on login, if the textures exist in the cache (eg if you logged 719 if (face != null)
702 // into the simulator recently, then the appearance will pull those and send 720 texture = face.TextureID;
703 // them back in the packet and you won't have to rebake. if the textures aren't 721 }
704 // in the cache then the intial makeroot() call in scenepresence will zero 722 else
705 // them out. 723 {
706 // 724 // We know that that hash is wrong, null it out
707 // a better solution (though how much better is an open question) is to 725 // and wait for the setappearance call
708 // store the hashes in the appearance and compare them. Thats's coming. 726 sp.Appearance.SetTextureHash(index,UUID.Zero);
709 727 }
710 Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[index]; 728
711 if (face != null) 729 // m_log.WarnFormat("[AVFACTORY]: use texture {0} for index {1}; hash={2}",texture,index,request.WearableHashID);
712 texture = face.TextureID;
713
714 // m_log.WarnFormat("[AVFACTORY]: reuse texture {0} for index {1}",texture,index);
715 } 730 }
716 731
717 CachedTextureResponseArg response = new CachedTextureResponseArg(); 732 CachedTextureResponseArg response = new CachedTextureResponseArg();
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
index 8056030..4613344 100644
--- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
@@ -371,7 +371,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
371 foreach (string fid in outstanding) 371 foreach (string fid in outstanding)
372 { 372 {
373 UUID fromAgentID; 373 UUID fromAgentID;
374 string firstname = "Unknown", lastname = "User"; 374 string firstname = "Unknown", lastname = "UserFMSFOIN";
375 if (!GetAgentInfo(client.Scene.RegionInfo.ScopeID, fid, out fromAgentID, out firstname, out lastname)) 375 if (!GetAgentInfo(client.Scene.RegionInfo.ScopeID, fid, out fromAgentID, out firstname, out lastname))
376 { 376 {
377 m_log.DebugFormat("[FRIENDS MODULE]: skipping malformed friend {0}", fid); 377 m_log.DebugFormat("[FRIENDS MODULE]: skipping malformed friend {0}", fid);
@@ -397,7 +397,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
397 397
398 protected virtual bool GetAgentInfo(UUID scopeID, string fid, out UUID agentID, out string first, out string last) 398 protected virtual bool GetAgentInfo(UUID scopeID, string fid, out UUID agentID, out string first, out string last)
399 { 399 {
400 first = "Unknown"; last = "User"; 400 first = "Unknown"; last = "UserFMGAI";
401 if (!UUID.TryParse(fid, out agentID)) 401 if (!UUID.TryParse(fid, out agentID))
402 return false; 402 return false;
403 403
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs
index bf5c0bb..b3e3aa2 100644
--- a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs
@@ -293,7 +293,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
293 293
294 protected override bool GetAgentInfo(UUID scopeID, string fid, out UUID agentID, out string first, out string last) 294 protected override bool GetAgentInfo(UUID scopeID, string fid, out UUID agentID, out string first, out string last)
295 { 295 {
296 first = "Unknown"; last = "User"; 296 first = "Unknown"; last = "UserHGGAI";
297 if (base.GetAgentInfo(scopeID, fid, out agentID, out first, out last)) 297 if (base.GetAgentInfo(scopeID, fid, out agentID, out first, out last))
298 return true; 298 return true;
299 299
diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/HGUserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/HGUserManagementModule.cs
index fac93e6..ad3cf15 100644
--- a/OpenSim/Region/CoreModules/Framework/UserManagement/HGUserManagementModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/UserManagement/HGUserManagementModule.cs
@@ -54,7 +54,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
54 54
55 public new void Initialise(IConfigSource config) 55 public new void Initialise(IConfigSource config)
56 { 56 {
57 string umanmod = config.Configs["Modules"].GetString("UserManagementModule", Name); 57 string umanmod = config.Configs["Modules"].GetString("UserManagementModule", null);
58 if (umanmod == Name) 58 if (umanmod == Name)
59 { 59 {
60 m_Enabled = true; 60 m_Enabled = true;
diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
index 6847e57..a720d7b 100644
--- a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
@@ -157,13 +157,16 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
157 } 157 }
158 else 158 else
159 { 159 {
160 string[] names = GetUserNames(uuid); 160 string[] names;
161 bool foundRealName = TryGetUserNames(uuid, out names);
162
161 if (names.Length == 2) 163 if (names.Length == 2)
162 { 164 {
163 //m_log.DebugFormat("[XXX] HandleUUIDNameRequest {0} is {1} {2}", uuid, names[0], names[1]); 165 if (!foundRealName)
166 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);
167
164 remote_client.SendNameReply(uuid, names[0], names[1]); 168 remote_client.SendNameReply(uuid, names[0], names[1]);
165 } 169 }
166
167 } 170 }
168 } 171 }
169 172
@@ -246,10 +249,15 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
246 } 249 }
247 250
248 // search the local cache 251 // search the local cache
249 foreach (UserData data in m_UserCache.Values) 252 lock (m_UserCache)
250 if (users.Find(delegate(UserData d) { return d.Id == data.Id; }) == null && 253 {
251 (data.FirstName.ToLower().StartsWith(query.ToLower()) || data.LastName.ToLower().StartsWith(query.ToLower()))) 254 foreach (UserData data in m_UserCache.Values)
252 users.Add(data); 255 {
256 if (users.Find(delegate(UserData d) { return d.Id == data.Id; }) == null &&
257 (data.FirstName.ToLower().StartsWith(query.ToLower()) || data.LastName.ToLower().StartsWith(query.ToLower())))
258 users.Add(data);
259 }
260 }
253 261
254 AddAdditionalUsers(query, users); 262 AddAdditionalUsers(query, users);
255 263
@@ -272,17 +280,24 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
272 } 280 }
273 } 281 }
274 282
275 private string[] GetUserNames(UUID uuid) 283 /// <summary>
284 /// Try to get the names bound to the given uuid.
285 /// </summary>
286 /// <returns>True if the name was found, false if not.</returns>
287 /// <param name='uuid'></param>
288 /// <param name='names'>The array of names if found. If not found, then names[0] = "Unknown" and names[1] = "User"</param>
289 private bool TryGetUserNames(UUID uuid, out string[] names)
276 { 290 {
277 string[] returnstring = new string[2]; 291 names = new string[2];
278 292
279 lock (m_UserCache) 293 lock (m_UserCache)
280 { 294 {
281 if (m_UserCache.ContainsKey(uuid)) 295 if (m_UserCache.ContainsKey(uuid))
282 { 296 {
283 returnstring[0] = m_UserCache[uuid].FirstName; 297 names[0] = m_UserCache[uuid].FirstName;
284 returnstring[1] = m_UserCache[uuid].LastName; 298 names[1] = m_UserCache[uuid].LastName;
285 return returnstring; 299
300 return true;
286 } 301 }
287 } 302 }
288 303
@@ -290,8 +305,8 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
290 305
291 if (account != null) 306 if (account != null)
292 { 307 {
293 returnstring[0] = account.FirstName; 308 names[0] = account.FirstName;
294 returnstring[1] = account.LastName; 309 names[1] = account.LastName;
295 310
296 UserData user = new UserData(); 311 UserData user = new UserData();
297 user.FirstName = account.FirstName; 312 user.FirstName = account.FirstName;
@@ -299,14 +314,16 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
299 314
300 lock (m_UserCache) 315 lock (m_UserCache)
301 m_UserCache[uuid] = user; 316 m_UserCache[uuid] = user;
317
318 return true;
302 } 319 }
303 else 320 else
304 { 321 {
305 returnstring[0] = "Unknown"; 322 names[0] = "Unknown";
306 returnstring[1] = "User"; 323 names[1] = "UserUMMTGUN";
307 }
308 324
309 return returnstring; 325 return false;
326 }
310 } 327 }
311 328
312 #region IUserManagement 329 #region IUserManagement
@@ -342,15 +359,17 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
342 359
343 public string GetUserName(UUID uuid) 360 public string GetUserName(UUID uuid)
344 { 361 {
345 string[] names = GetUserNames(uuid); 362 string[] names;
363 TryGetUserNames(uuid, out names);
364
346 if (names.Length == 2) 365 if (names.Length == 2)
347 { 366 {
348 string firstname = names[0]; 367 string firstname = names[0];
349 string lastname = names[1]; 368 string lastname = names[1];
350 369
351 return firstname + " " + lastname; 370 return firstname + " " + lastname;
352
353 } 371 }
372
354 return "(hippos)"; 373 return "(hippos)";
355 } 374 }
356 375
@@ -466,12 +485,13 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
466 //ignore updates without creator data 485 //ignore updates without creator data
467 return; 486 return;
468 } 487 }
488
469 //try update unknown users 489 //try update unknown users
470 //and creator's home URL's 490 //and creator's home URL's
471 if ((oldUser.FirstName == "Unknown" && !creatorData.Contains ("Unknown")) || (oldUser.HomeURL != null && !creatorData.StartsWith (oldUser.HomeURL))) 491 if ((oldUser.FirstName == "Unknown" && !creatorData.Contains ("Unknown")) || (oldUser.HomeURL != null && !creatorData.StartsWith (oldUser.HomeURL)))
472 { 492 {
473 m_UserCache.Remove (id); 493 m_UserCache.Remove (id);
474// m_log.DebugFormat("[USER MANAGEMENT MODULE]: Re-adding user with id {0}, creatorData [{1}] and old HomeURL {2}", id, creatorData,oldUser.HomeURL); 494 m_log.DebugFormat("[USER MANAGEMENT MODULE]: Re-adding user with id {0}, creatorData [{1}] and old HomeURL {2}", id, creatorData, oldUser.HomeURL);
475 } 495 }
476 else 496 else
477 { 497 {
@@ -516,7 +536,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
516 else 536 else
517 { 537 {
518 user.FirstName = "Unknown"; 538 user.FirstName = "Unknown";
519 user.LastName = "User"; 539 user.LastName = "UserUMMAU";
520 } 540 }
521 541
522 AddUserInternal (user); 542 AddUserInternal (user);
@@ -548,6 +568,13 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
548 protected void RegisterConsoleCmds() 568 protected void RegisterConsoleCmds()
549 { 569 {
550 MainConsole.Instance.Commands.AddCommand("Users", true, 570 MainConsole.Instance.Commands.AddCommand("Users", true,
571 "show name",
572 "show name <uuid>",
573 "Show the bindings between a single user UUID and a user name",
574 String.Empty,
575 HandleShowUser);
576
577 MainConsole.Instance.Commands.AddCommand("Users", true,
551 "show names", 578 "show names",
552 "show names", 579 "show names",
553 "Show the bindings between user UUIDs and user names", 580 "Show the bindings between user UUIDs and user names",
@@ -555,26 +582,54 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
555 HandleShowUsers); 582 HandleShowUsers);
556 } 583 }
557 584
558 private void HandleShowUsers(string module, string[] cmd) 585 private void HandleShowUser(string module, string[] cmd)
559 { 586 {
587 if (cmd.Length < 3)
588 {
589 MainConsole.Instance.OutputFormat("Usage: show name <uuid>");
590 return;
591 }
592
593 UUID userId;
594 if (!ConsoleUtil.TryParseConsoleUuid(MainConsole.Instance, cmd[2], out userId))
595 return;
596
597 string[] names;
598
599 UserData ud;
600
560 lock (m_UserCache) 601 lock (m_UserCache)
561 { 602 {
562 if (m_UserCache.Count == 0) 603 if (!m_UserCache.TryGetValue(userId, out ud))
563 { 604 {
564 MainConsole.Instance.Output("No users found"); 605 MainConsole.Instance.OutputFormat("No name known for user with id {0}", userId);
565 return; 606 return;
566 } 607 }
567 608 }
568 MainConsole.Instance.Output("UUID User Name"); 609
569 MainConsole.Instance.Output("-----------------------------------------------------------------------------"); 610 ConsoleDisplayTable cdt = new ConsoleDisplayTable();
611 cdt.AddColumn("UUID", 36);
612 cdt.AddColumn("Name", 30);
613 cdt.AddColumn("HomeURL", 40);
614 cdt.AddRow(userId, string.Format("{0} {1}", ud.FirstName, ud.LastName), ud.HomeURL);
615
616 MainConsole.Instance.Output(cdt.ToString());
617 }
618
619 private void HandleShowUsers(string module, string[] cmd)
620 {
621 ConsoleDisplayTable cdt = new ConsoleDisplayTable();
622 cdt.AddColumn("UUID", 36);
623 cdt.AddColumn("Name", 30);
624 cdt.AddColumn("HomeURL", 40);
625
626 lock (m_UserCache)
627 {
570 foreach (KeyValuePair<UUID, UserData> kvp in m_UserCache) 628 foreach (KeyValuePair<UUID, UserData> kvp in m_UserCache)
571 { 629 cdt.AddRow(kvp.Key, string.Format("{0} {1}", kvp.Value.FirstName, kvp.Value.LastName), kvp.Value.HomeURL);
572 MainConsole.Instance.Output(String.Format("{0} {1} {2} ({3})",
573 kvp.Key, kvp.Value.FirstName, kvp.Value.LastName, kvp.Value.HomeURL));
574 }
575
576 return;
577 } 630 }
631
632 MainConsole.Instance.Output(cdt.ToString());
578 } 633 }
579 } 634 }
580} \ No newline at end of file 635} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs b/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs
index 883045a..d093224 100644
--- a/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs
+++ b/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs
@@ -369,6 +369,15 @@ namespace OpenSim.Region.CoreModules.World.Sound
369 }); 369 });
370 } 370 }
371 371
372 public void SetSoundQueueing(UUID objectID, bool shouldQueue)
373 {
374 SceneObjectPart part;
375 if (!m_scene.TryGetSceneObjectPart(objectID, out part))
376 return;
377
378 part.SoundQueueing = shouldQueue;
379 }
380
372 #endregion 381 #endregion
373 } 382 }
374} 383}
diff --git a/OpenSim/Region/Framework/Interfaces/ISoundModule.cs b/OpenSim/Region/Framework/Interfaces/ISoundModule.cs
index 68af492..8372ddd 100644
--- a/OpenSim/Region/Framework/Interfaces/ISoundModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/ISoundModule.cs
@@ -104,7 +104,6 @@ namespace OpenSim.Region.Framework.Interfaces
104 /// <param name="sound">Sound asset ID</param> 104 /// <param name="sound">Sound asset ID</param>
105 /// <param name="volume">Sound volume</param> 105 /// <param name="volume">Sound volume</param>
106 /// <param name="triggered">Triggered or not.</param> 106 /// <param name="triggered">Triggered or not.</param>
107 /// <param name="flags"></param>
108 /// <param name="radius">Sound radius</param> 107 /// <param name="radius">Sound radius</param>
109 /// <param name="useMaster">Play using sound master</param> 108 /// <param name="useMaster">Play using sound master</param>
110 /// <param name="isMaster">Play as sound master</param> 109 /// <param name="isMaster">Play as sound master</param>
@@ -123,5 +122,12 @@ namespace OpenSim.Region.Framework.Interfaces
123 /// <param name="max">AABB top north-east corner</param> 122 /// <param name="max">AABB top north-east corner</param>
124 void TriggerSoundLimited(UUID objectID, UUID sound, double volume, 123 void TriggerSoundLimited(UUID objectID, UUID sound, double volume,
125 Vector3 min, Vector3 max); 124 Vector3 min, Vector3 max);
125
126 /// <summary>
127 /// Set whether sounds on the given prim should be queued.
128 /// </summary>
129 /// <param name='objectID'></param>
130 /// <param name='shouldQueue'></param>
131 void SetSoundQueueing(UUID objectID, bool shouldQueue);
126 } 132 }
127} \ No newline at end of file 133} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index 38fa26a..df23cc5 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -1499,7 +1499,7 @@ namespace OpenSim.Region.Framework.Scenes
1499 if (!userExposed) 1499 if (!userExposed)
1500 dupe.IsAttachment = true; 1500 dupe.IsAttachment = true;
1501 1501
1502 dupe.AbsolutePosition = new Vector3(AbsolutePosition.X, AbsolutePosition.Y, AbsolutePosition.Z); 1502 dupe.m_sittingAvatars = new List<UUID>();
1503 1503
1504 if (!userExposed) 1504 if (!userExposed)
1505 { 1505 {
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 347a2b5..ea8c3c5 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -219,6 +219,14 @@ namespace OpenSim.Region.Framework.Scenes
219 219
220 public double SoundRadius; 220 public double SoundRadius;
221 221
222 /// <summary>
223 /// Should sounds played from this prim be queued?
224 /// </summary>
225 /// <remarks>
226 /// This should only be changed by sound modules. It is up to sound modules as to how they interpret this setting.
227 /// </remarks>
228 public bool SoundQueueing { get; set; }
229
222 public uint TimeStampFull; 230 public uint TimeStampFull;
223 231
224 public uint TimeStampLastActivity; // Will be used for AutoReturn 232 public uint TimeStampLastActivity; // Will be used for AutoReturn
@@ -1791,6 +1799,8 @@ namespace OpenSim.Region.Framework.Scenes
1791 Array.Copy(Shape.ExtraParams, extraP, extraP.Length); 1799 Array.Copy(Shape.ExtraParams, extraP, extraP.Length);
1792 dupe.Shape.ExtraParams = extraP; 1800 dupe.Shape.ExtraParams = extraP;
1793 1801
1802 dupe.PayPrice = (int[])PayPrice.Clone();
1803
1794 dupe.DynAttrs.CopyFrom(DynAttrs); 1804 dupe.DynAttrs.CopyFrom(DynAttrs);
1795 1805
1796 if (userExposed) 1806 if (userExposed)
@@ -2429,7 +2439,7 @@ namespace OpenSim.Region.Framework.Scenes
2429 if (soundModule != null) 2439 if (soundModule != null)
2430 { 2440 {
2431 soundModule.SendSound(UUID, CollisionSound, 2441 soundModule.SendSound(UUID, CollisionSound,
2432 CollisionSoundVolume, true, (byte)0, 0, false, 2442 CollisionSoundVolume, true, 0, 0, false,
2433 false); 2443 false);
2434 } 2444 }
2435 } 2445 }
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 0c91e13..ab7fd5b 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -2713,7 +2713,9 @@ namespace OpenSim.Region.Framework.Scenes
2713 // again here... this comes after the cached appearance check because the avatars 2713 // again here... this comes after the cached appearance check because the avatars
2714 // appearance goes into the avatar update packet 2714 // appearance goes into the avatar update packet
2715 SendAvatarDataToAllAgents(); 2715 SendAvatarDataToAllAgents();
2716 SendAppearanceToAgent(this); 2716
2717 // This invocation always shows up in the viewer logs as an error.
2718 // SendAppearanceToAgent(this);
2717 2719
2718 // If we are using the the cached appearance then send it out to everyone 2720 // If we are using the the cached appearance then send it out to everyone
2719 if (cachedappearance) 2721 if (cachedappearance)
diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
index 384eb1f..3726191 100644
--- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
+++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
@@ -907,7 +907,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
907 // Mimicking LLClientView which gets always set appearance from client. 907 // Mimicking LLClientView which gets always set appearance from client.
908 AvatarAppearance appearance; 908 AvatarAppearance appearance;
909 m_scene.GetAvatarAppearance(this, out appearance); 909 m_scene.GetAvatarAppearance(this, out appearance);
910 OnSetAppearance(this, appearance.Texture, (byte[])appearance.VisualParams.Clone()); 910 OnSetAppearance(this, appearance.Texture, (byte[])appearance.VisualParams.Clone(), new List<CachedTextureRequestArg>());
911 } 911 }
912 912
913 public void SendRegionHandshake(RegionInfo regionInfo, RegionHandshakeArgs args) 913 public void SendRegionHandshake(RegionInfo regionInfo, RegionHandshakeArgs args)
@@ -1056,7 +1056,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
1056 { 1056 {
1057 } 1057 }
1058 1058
1059 public void SendMoneyBalance(UUID transaction, bool success, byte[] description, int balance) 1059 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)
1060 { 1060 {
1061 1061
1062 } 1062 }
@@ -1196,11 +1196,6 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
1196 1196
1197 } 1197 }
1198 1198
1199 public bool AddMoney(int debit)
1200 {
1201 return true;
1202 }
1203
1204 public void SendSunPos(Vector3 sunPos, Vector3 sunVel, ulong CurrentTime, uint SecondsPerSunCycle, uint SecondsPerYear, float OrbitalPosition) 1199 public void SendSunPos(Vector3 sunPos, Vector3 sunVel, ulong CurrentTime, uint SecondsPerSunCycle, uint SecondsPerYear, float OrbitalPosition)
1205 { 1200 {
1206 1201
diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs
index 29f9591..32fb54b 100644
--- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs
@@ -764,7 +764,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
764 remoteClient.SendCreateGroupReply(UUID.Zero, false, "You have got insufficient funds to create a group."); 764 remoteClient.SendCreateGroupReply(UUID.Zero, false, "You have got insufficient funds to create a group.");
765 return UUID.Zero; 765 return UUID.Zero;
766 } 766 }
767 money.ApplyCharge(GetRequestingAgentID(remoteClient), money.GroupCreationCharge, "Group Creation"); 767 money.ApplyCharge(GetRequestingAgentID(remoteClient), money.GroupCreationCharge, MoneyTransactionType.GroupCreate);
768 } 768 }
769 UUID groupID = m_groupData.CreateGroup(GetRequestingAgentID(remoteClient), name, charter, showInList, insigniaID, membershipFee, openEnrollment, allowPublish, maturePublish, GetRequestingAgentID(remoteClient)); 769 UUID groupID = m_groupData.CreateGroup(GetRequestingAgentID(remoteClient), name, charter, showInList, insigniaID, membershipFee, openEnrollment, allowPublish, maturePublish, GetRequestingAgentID(remoteClient));
770 770
diff --git a/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs b/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs
index 35f44d0..1345db9 100644
--- a/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs
+++ b/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs
@@ -191,9 +191,14 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule
191 // Please do not refactor these to be just one method 191 // Please do not refactor these to be just one method
192 // Existing implementations need the distinction 192 // Existing implementations need the distinction
193 // 193 //
194 public void ApplyCharge(UUID agentID, int amount, string text) 194 public void ApplyCharge(UUID agentID, int amount, MoneyTransactionType type, string extraData)
195 { 195 {
196 } 196 }
197
198 public void ApplyCharge(UUID agentID, int amount, MoneyTransactionType type)
199 {
200 }
201
197 public void ApplyUploadCharge(UUID agentID, int amount, string text) 202 public void ApplyUploadCharge(UUID agentID, int amount, string text)
198 { 203 {
199 } 204 }
@@ -322,7 +327,7 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule
322 client.SendAlertMessage(e.Message + " "); 327 client.SendAlertMessage(e.Message + " ");
323 } 328 }
324 329
325 client.SendMoneyBalance(TransactionID, true, new byte[0], returnfunds); 330 client.SendMoneyBalance(TransactionID, true, new byte[0], returnfunds, 0, UUID.Zero, false, UUID.Zero, false, 0, String.Empty);
326 } 331 }
327 else 332 else
328 { 333 {
@@ -385,12 +390,12 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule
385 { 390 {
386 if (sender != null) 391 if (sender != null)
387 { 392 {
388 sender.SendMoneyBalance(UUID.Random(), transactionresult, Utils.StringToBytes(description), GetFundsForAgentID(senderID)); 393 sender.SendMoneyBalance(UUID.Random(), transactionresult, Utils.StringToBytes(description), GetFundsForAgentID(senderID), 0, UUID.Zero, false, UUID.Zero, false, 0, String.Empty);
389 } 394 }
390 395
391 if (receiver != null) 396 if (receiver != null)
392 { 397 {
393 receiver.SendMoneyBalance(UUID.Random(), transactionresult, Utils.StringToBytes(description), GetFundsForAgentID(receiverID)); 398 receiver.SendMoneyBalance(UUID.Random(), transactionresult, Utils.StringToBytes(description), GetFundsForAgentID(receiverID), 0, UUID.Zero, false, UUID.Zero, false, 0, String.Empty);
394 } 399 }
395 } 400 }
396 } 401 }
diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
index 553443f..592e4e1 100644
--- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
+++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
@@ -694,7 +694,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
694 { 694 {
695 } 695 }
696 696
697 public virtual void SendMoneyBalance(UUID transaction, bool success, byte[] description, int balance) 697 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)
698 { 698 {
699 } 699 }
700 700
@@ -866,11 +866,6 @@ namespace OpenSim.Region.OptionalModules.World.NPC
866 { 866 {
867 } 867 }
868 868
869 public bool AddMoney(int debit)
870 {
871 return false;
872 }
873
874 public void SendSunPos(Vector3 sunPos, Vector3 sunVel, ulong time, uint dlen, uint ylen, float phase) 869 public void SendSunPos(Vector3 sunPos, Vector3 sunVel, ulong time, uint dlen, uint ylen, float phase)
875 { 870 {
876 } 871 }
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSAPIUnman.cs b/OpenSim/Region/Physics/BulletSPlugin/BSAPIUnman.cs
index 231f0f8..12a0c17 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSAPIUnman.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSAPIUnman.cs
@@ -251,6 +251,16 @@ public override BulletShape CreateMeshShape(BulletWorld world,
251 BSPhysicsShapeType.SHAPE_MESH); 251 BSPhysicsShapeType.SHAPE_MESH);
252} 252}
253 253
254public override BulletShape CreateGImpactShape(BulletWorld world,
255 int indicesCount, int[] indices,
256 int verticesCount, float[] vertices)
257{
258 BulletWorldUnman worldu = world as BulletWorldUnman;
259 return new BulletShapeUnman(
260 BSAPICPP.CreateGImpactShape2(worldu.ptr, indicesCount, indices, verticesCount, vertices),
261 BSPhysicsShapeType.SHAPE_GIMPACT);
262}
263
254public override BulletShape CreateHullShape(BulletWorld world, int hullCount, float[] hulls) 264public override BulletShape CreateHullShape(BulletWorld world, int hullCount, float[] hulls)
255{ 265{
256 BulletWorldUnman worldu = world as BulletWorldUnman; 266 BulletWorldUnman worldu = world as BulletWorldUnman;
@@ -1426,6 +1436,11 @@ public static extern IntPtr CreateMeshShape2(IntPtr world,
1426 int verticesCount, [MarshalAs(UnmanagedType.LPArray)] float[] vertices ); 1436 int verticesCount, [MarshalAs(UnmanagedType.LPArray)] float[] vertices );
1427 1437
1428[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1438[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1439public static extern IntPtr CreateGImpactShape2(IntPtr world,
1440 int indicesCount, [MarshalAs(UnmanagedType.LPArray)] int[] indices,
1441 int verticesCount, [MarshalAs(UnmanagedType.LPArray)] float[] vertices );
1442
1443[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1429public static extern IntPtr CreateHullShape2(IntPtr world, 1444public static extern IntPtr CreateHullShape2(IntPtr world,
1430 int hullCount, [MarshalAs(UnmanagedType.LPArray)] float[] hulls); 1445 int hullCount, [MarshalAs(UnmanagedType.LPArray)] float[] hulls);
1431 1446
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs b/OpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs
index 59780ae..6db5f5e 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs
@@ -1475,7 +1475,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
1475 ret = BSPhysicsShapeType.SHAPE_UNKNOWN; 1475 ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
1476 break; 1476 break;
1477 case BroadphaseNativeTypes.CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE: 1477 case BroadphaseNativeTypes.CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE:
1478 ret = BSPhysicsShapeType.SHAPE_MESH; 1478 ret = BSPhysicsShapeType.SHAPE_CONVEXHULL;
1479 break; 1479 break;
1480 case BroadphaseNativeTypes.CONVEX_HULL_SHAPE_PROXYTYPE: 1480 case BroadphaseNativeTypes.CONVEX_HULL_SHAPE_PROXYTYPE:
1481 ret = BSPhysicsShapeType.SHAPE_HULL; 1481 ret = BSPhysicsShapeType.SHAPE_HULL;
@@ -1503,7 +1503,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
1503 ret = BSPhysicsShapeType.SHAPE_CONE; 1503 ret = BSPhysicsShapeType.SHAPE_CONE;
1504 break; 1504 break;
1505 case BroadphaseNativeTypes.CONVEX_SHAPE_PROXYTYPE: 1505 case BroadphaseNativeTypes.CONVEX_SHAPE_PROXYTYPE:
1506 ret = BSPhysicsShapeType.SHAPE_UNKNOWN; 1506 ret = BSPhysicsShapeType.SHAPE_CONVEXHULL;
1507 break; 1507 break;
1508 case BroadphaseNativeTypes.CYLINDER_SHAPE_PROXYTYPE: 1508 case BroadphaseNativeTypes.CYLINDER_SHAPE_PROXYTYPE:
1509 ret = BSPhysicsShapeType.SHAPE_CYLINDER; 1509 ret = BSPhysicsShapeType.SHAPE_CYLINDER;
@@ -1547,7 +1547,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
1547 break; 1547 break;
1548 ///Used for GIMPACT Trimesh integration 1548 ///Used for GIMPACT Trimesh integration
1549 case BroadphaseNativeTypes.GIMPACT_SHAPE_PROXYTYPE: 1549 case BroadphaseNativeTypes.GIMPACT_SHAPE_PROXYTYPE:
1550 ret = BSPhysicsShapeType.SHAPE_MESH; 1550 ret = BSPhysicsShapeType.SHAPE_GIMPACT;
1551 break; 1551 break;
1552 ///Multimaterial mesh 1552 ///Multimaterial mesh
1553 case BroadphaseNativeTypes.MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE: 1553 case BroadphaseNativeTypes.MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE:
@@ -1820,6 +1820,11 @@ private sealed class BulletConstraintXNA : BulletConstraint
1820 return new BulletShapeXNA(meshShape, BSPhysicsShapeType.SHAPE_MESH); 1820 return new BulletShapeXNA(meshShape, BSPhysicsShapeType.SHAPE_MESH);
1821 1821
1822 } 1822 }
1823 public override BulletShape CreateGImpactShape(BulletWorld pWorld, int pIndicesCount, int[] indices, int pVerticesCount, float[] verticesAsFloats)
1824 {
1825 // TODO:
1826 return null;
1827 }
1823 public static void DumpRaw(ObjectArray<int>indices, ObjectArray<float> vertices, int pIndicesCount,int pVerticesCount ) 1828 public static void DumpRaw(ObjectArray<int>indices, ObjectArray<float> vertices, int pIndicesCount,int pVerticesCount )
1824 { 1829 {
1825 1830
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs b/OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs
index 3378c93..6cdc112 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs
@@ -71,6 +71,7 @@ public enum BSPhysicsShapeType
71 SHAPE_HEIGHTMAP = 23, 71 SHAPE_HEIGHTMAP = 23,
72 SHAPE_AVATAR = 24, 72 SHAPE_AVATAR = 24,
73 SHAPE_CONVEXHULL= 25, 73 SHAPE_CONVEXHULL= 25,
74 SHAPE_GIMPACT = 26,
74}; 75};
75 76
76// The native shapes have predefined shape hash keys 77// The native shapes have predefined shape hash keys
@@ -321,6 +322,10 @@ public abstract BulletShape CreateMeshShape(BulletWorld world,
321 int indicesCount, int[] indices, 322 int indicesCount, int[] indices,
322 int verticesCount, float[] vertices ); 323 int verticesCount, float[] vertices );
323 324
325public abstract BulletShape CreateGImpactShape(BulletWorld world,
326 int indicesCount, int[] indices,
327 int verticesCount, float[] vertices );
328
324public abstract BulletShape CreateHullShape(BulletWorld world, 329public abstract BulletShape CreateHullShape(BulletWorld world,
325 int hullCount, float[] hulls); 330 int hullCount, float[] hulls);
326 331
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
index ff5b6ab..48f842e 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
@@ -483,8 +483,15 @@ public sealed class BSCharacter : BSPhysObject
483 { 483 {
484 // Bullet assumes we know what we are doing when forcing orientation 484 // Bullet assumes we know what we are doing when forcing orientation
485 // so it lets us go against all the rules and just compensates for them later. 485 // so it lets us go against all the rules and just compensates for them later.
486 // This keeps us from flipping the capsule over which the veiwer does not understand. 486 // This forces rotation to be only around the Z axis and doesn't change any of the other axis.
487 ForceOrientation = new OMV.Quaternion(0, 0, _orientation.Z,0); 487 // This keeps us from flipping the capsule over which the veiwer does not understand.
488 float oRoll, oPitch, oYaw;
489 _orientation.GetEulerAngles(out oRoll, out oPitch, out oYaw);
490 OMV.Quaternion trimmedOrientation = OMV.Quaternion.CreateFromEulers(0f, 0f, oYaw);
491 // DetailLog("{0},BSCharacter.setOrientation,taint,val={1},valDir={2},conv={3},convDir={4}",
492 // LocalID, _orientation, OMV.Vector3.UnitX * _orientation,
493 // trimmedOrientation, OMV.Vector3.UnitX * trimmedOrientation);
494 ForceOrientation = trimmedOrientation;
488 }); 495 });
489 } 496 }
490 } 497 }
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
index c16b7d3..311cf4f 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
@@ -617,7 +617,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin
617 // Vehicles report collision events so we know when it's on the ground 617 // Vehicles report collision events so we know when it's on the ground
618 m_physicsScene.PE.AddToCollisionFlags(ControllingPrim.PhysBody, CollisionFlags.BS_VEHICLE_COLLISIONS); 618 m_physicsScene.PE.AddToCollisionFlags(ControllingPrim.PhysBody, CollisionFlags.BS_VEHICLE_COLLISIONS);
619 619
620 ControllingPrim.Inertia = m_physicsScene.PE.CalculateLocalInertia(ControllingPrim.PhysShape.physShapeInfo, m_vehicleMass); 620 Vector3 inertia = m_physicsScene.PE.CalculateLocalInertia(ControllingPrim.PhysShape.physShapeInfo, m_vehicleMass);
621 ControllingPrim.Inertia = inertia * BSParam.VehicleInertiaFactor;
621 m_physicsScene.PE.SetMassProps(ControllingPrim.PhysBody, m_vehicleMass, ControllingPrim.Inertia); 622 m_physicsScene.PE.SetMassProps(ControllingPrim.PhysBody, m_vehicleMass, ControllingPrim.Inertia);
622 m_physicsScene.PE.UpdateInertiaTensor(ControllingPrim.PhysBody); 623 m_physicsScene.PE.UpdateInertiaTensor(ControllingPrim.PhysBody);
623 624
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs b/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs
index d33292f..2651e3b 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs
@@ -89,6 +89,8 @@ public static class BSParam
89 public static bool ShouldRemoveZeroWidthTriangles { get; private set; } 89 public static bool ShouldRemoveZeroWidthTriangles { get; private set; }
90 public static bool ShouldUseBulletHACD { get; set; } 90 public static bool ShouldUseBulletHACD { get; set; }
91 public static bool ShouldUseSingleConvexHullForPrims { get; set; } 91 public static bool ShouldUseSingleConvexHullForPrims { get; set; }
92 public static bool ShouldUseGImpactShapeForPrims { get; set; }
93 public static bool ShouldUseAssetHulls { get; set; }
92 94
93 public static float TerrainImplementation { get; set; } 95 public static float TerrainImplementation { get; set; }
94 public static int TerrainMeshMagnification { get; private set; } 96 public static int TerrainMeshMagnification { get; private set; }
@@ -146,6 +148,7 @@ public static class BSParam
146 public static float VehicleRestitution { get; private set; } 148 public static float VehicleRestitution { get; private set; }
147 public static Vector3 VehicleLinearFactor { get; private set; } 149 public static Vector3 VehicleLinearFactor { get; private set; }
148 public static Vector3 VehicleAngularFactor { get; private set; } 150 public static Vector3 VehicleAngularFactor { get; private set; }
151 public static Vector3 VehicleInertiaFactor { get; private set; }
149 public static float VehicleGroundGravityFudge { get; private set; } 152 public static float VehicleGroundGravityFudge { get; private set; }
150 public static float VehicleAngularBankingTimescaleFudge { get; private set; } 153 public static float VehicleAngularBankingTimescaleFudge { get; private set; }
151 public static bool VehicleDebuggingEnable { get; private set; } 154 public static bool VehicleDebuggingEnable { get; private set; }
@@ -369,6 +372,10 @@ public static class BSParam
369 false ), 372 false ),
370 new ParameterDefn<bool>("ShouldUseSingleConvexHullForPrims", "If true, use a single convex hull shape for physical prims", 373 new ParameterDefn<bool>("ShouldUseSingleConvexHullForPrims", "If true, use a single convex hull shape for physical prims",
371 true ), 374 true ),
375 new ParameterDefn<bool>("ShouldUseGImpactShapeForPrims", "If true, use a GImpact shape for prims with cuts and twists",
376 false ),
377 new ParameterDefn<bool>("ShouldUseAssetHulls", "If true, use hull if specified in the mesh asset info",
378 true ),
372 379
373 new ParameterDefn<int>("CrossingFailuresBeforeOutOfBounds", "How forgiving we are about getting into adjactent regions", 380 new ParameterDefn<int>("CrossingFailuresBeforeOutOfBounds", "How forgiving we are about getting into adjactent regions",
374 5 ), 381 5 ),
@@ -577,6 +584,8 @@ public static class BSParam
577 new Vector3(1f, 1f, 1f) ), 584 new Vector3(1f, 1f, 1f) ),
578 new ParameterDefn<Vector3>("VehicleAngularFactor", "Fraction of physical angular changes applied to vehicle (<0,0,0> to <1,1,1>)", 585 new ParameterDefn<Vector3>("VehicleAngularFactor", "Fraction of physical angular changes applied to vehicle (<0,0,0> to <1,1,1>)",
579 new Vector3(1f, 1f, 1f) ), 586 new Vector3(1f, 1f, 1f) ),
587 new ParameterDefn<Vector3>("VehicleInertiaFactor", "Fraction of physical inertia applied (<0,0,0> to <1,1,1>)",
588 new Vector3(1f, 1f, 1f) ),
580 new ParameterDefn<float>("VehicleFriction", "Friction of vehicle on the ground (0.0 - 1.0)", 589 new ParameterDefn<float>("VehicleFriction", "Friction of vehicle on the ground (0.0 - 1.0)",
581 0.0f ), 590 0.0f ),
582 new ParameterDefn<float>("VehicleRestitution", "Bouncyness factor for vehicles (0.0 - 1.0)", 591 new ParameterDefn<float>("VehicleRestitution", "Bouncyness factor for vehicles (0.0 - 1.0)",
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
index f5b0361..e11e365 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
@@ -511,7 +511,10 @@ public class BSPrim : BSPhysObject
511 511
512 PhysScene.TaintedObject("setVehicleType", delegate() 512 PhysScene.TaintedObject("setVehicleType", delegate()
513 { 513 {
514 ZeroMotion(true /* inTaintTime */); 514 // Some vehicle scripts change vehicle type on the fly as an easy way to
515 // change all the parameters. Like a plane changing to CAR when on the
516 // ground. In this case, don't want to zero motion.
517 // ZeroMotion(true /* inTaintTime */);
515 VehicleActor.ProcessTypeChange(type); 518 VehicleActor.ProcessTypeChange(type);
516 ActivateIfPhysical(false); 519 ActivateIfPhysical(false);
517 }); 520 });
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
index 3f407ce..39f5b0a 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
@@ -268,6 +268,12 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
268 // Do any replacements in the parameters 268 // Do any replacements in the parameters
269 m_physicsLoggingPrefix = m_physicsLoggingPrefix.Replace("%REGIONNAME%", RegionName); 269 m_physicsLoggingPrefix = m_physicsLoggingPrefix.Replace("%REGIONNAME%", RegionName);
270 } 270 }
271 else
272 {
273 BulletEngineName = "BulletUnmanaged";
274 m_physicsLoggingEnabled = false;
275 VehicleLoggingEnabled = false;
276 }
271 277
272 // The material characteristics. 278 // The material characteristics.
273 BSMaterials.InitializeFromDefaults(Params); 279 BSMaterials.InitializeFromDefaults(Params);
@@ -322,6 +328,8 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
322 BSParam.ShouldUseBulletHACD = false; 328 BSParam.ShouldUseBulletHACD = false;
323 m_log.InfoFormat("{0} Disabling ShouldUseSingleConvexHullForPrims", LogHeader); 329 m_log.InfoFormat("{0} Disabling ShouldUseSingleConvexHullForPrims", LogHeader);
324 BSParam.ShouldUseSingleConvexHullForPrims = false; 330 BSParam.ShouldUseSingleConvexHullForPrims = false;
331 m_log.InfoFormat("{0} Disabling ShouldUseGImpactShapeForPrims", LogHeader);
332 BSParam.ShouldUseGImpactShapeForPrims = false;
325 m_log.InfoFormat("{0} Setting terrain implimentation to Heightmap", LogHeader); 333 m_log.InfoFormat("{0} Setting terrain implimentation to Heightmap", LogHeader);
326 BSParam.TerrainImplementation = (float)BSTerrainPhys.TerrainImplementation.Heightmap; 334 BSParam.TerrainImplementation = (float)BSTerrainPhys.TerrainImplementation.Heightmap;
327 break; 335 break;
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
index 64aaa15..32bbc8f 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
@@ -230,6 +230,7 @@ public sealed class BSShapeCollection : IDisposable
230 BSShape potentialHull = null; 230 BSShape potentialHull = null;
231 231
232 PrimitiveBaseShape pbs = prim.BaseShape; 232 PrimitiveBaseShape pbs = prim.BaseShape;
233 // Use a simple, one section convex shape for prims that are probably convex (no cuts or twists)
233 if (BSParam.ShouldUseSingleConvexHullForPrims 234 if (BSParam.ShouldUseSingleConvexHullForPrims
234 && pbs != null 235 && pbs != null
235 && !pbs.SculptEntry 236 && !pbs.SculptEntry
@@ -238,7 +239,17 @@ public sealed class BSShapeCollection : IDisposable
238 { 239 {
239 potentialHull = BSShapeConvexHull.GetReference(m_physicsScene, false /* forceRebuild */, prim); 240 potentialHull = BSShapeConvexHull.GetReference(m_physicsScene, false /* forceRebuild */, prim);
240 } 241 }
241 else 242 // Use the GImpact shape if it is a prim that has some concaveness
243 if (potentialHull == null
244 && BSParam.ShouldUseGImpactShapeForPrims
245 && pbs != null
246 && !pbs.SculptEntry
247 )
248 {
249 potentialHull = BSShapeGImpact.GetReference(m_physicsScene, false /* forceRebuild */, prim);
250 }
251 // If not any of the simple cases, just make a hull
252 if (potentialHull == null)
242 { 253 {
243 potentialHull = BSShapeHull.GetReference(m_physicsScene, false /*forceRebuild*/, prim); 254 potentialHull = BSShapeHull.GetReference(m_physicsScene, false /*forceRebuild*/, prim);
244 } 255 }
@@ -261,7 +272,7 @@ public sealed class BSShapeCollection : IDisposable
261 } 272 }
262 else 273 else
263 { 274 {
264 // Update prim.BSShape to reference a mesh of this shape. 275 // Non-physical objects should be just meshes.
265 BSShape potentialMesh = BSShapeMesh.GetReference(m_physicsScene, false /*forceRebuild*/, prim); 276 BSShape potentialMesh = BSShapeMesh.GetReference(m_physicsScene, false /*forceRebuild*/, prim);
266 // If the current shape is not what is on the prim at the moment, time to change. 277 // If the current shape is not what is on the prim at the moment, time to change.
267 if (!prim.PhysShape.HasPhysicalShape 278 if (!prim.PhysShape.HasPhysicalShape
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs
index 72d039b..81edc12 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs
@@ -31,6 +31,7 @@ using System.Text;
31 31
32using OpenSim.Framework; 32using OpenSim.Framework;
33using OpenSim.Region.Physics.Manager; 33using OpenSim.Region.Physics.Manager;
34using OpenSim.Region.Physics.Meshing;
34using OpenSim.Region.Physics.ConvexDecompositionDotNet; 35using OpenSim.Region.Physics.ConvexDecompositionDotNet;
35 36
36using OMV = OpenMetaverse; 37using OMV = OpenMetaverse;
@@ -422,15 +423,32 @@ public class BSShapeMesh : BSShape
422 outMesh = foundDesc; 423 outMesh = foundDesc;
423 return ret; 424 return ret;
424 } 425 }
426
427 public delegate BulletShape CreateShapeCall(BulletWorld world, int indicesCount, int[] indices, int verticesCount, float[] vertices );
425 private BulletShape CreatePhysicalMesh(BSScene physicsScene, BSPhysObject prim, System.UInt64 newMeshKey, 428 private BulletShape CreatePhysicalMesh(BSScene physicsScene, BSPhysObject prim, System.UInt64 newMeshKey,
426 PrimitiveBaseShape pbs, OMV.Vector3 size, float lod) 429 PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
427 { 430 {
431 return BSShapeMesh.CreatePhysicalMeshShape(physicsScene, prim, newMeshKey, pbs, size, lod,
432 (w, iC, i, vC, v) => physicsScene.PE.CreateMeshShape(w, iC, i, vC, v) );
433 }
434
435 // Code that uses the mesher to create the index/vertices info for a trimesh shape.
436 // This is used by the passed 'makeShape' call to create the Bullet mesh shape.
437 // The actual build call is passed so this logic can be used by several of the shapes that use a
438 // simple mesh as their base shape.
439 public static BulletShape CreatePhysicalMeshShape(BSScene physicsScene, BSPhysObject prim, System.UInt64 newMeshKey,
440 PrimitiveBaseShape pbs, OMV.Vector3 size, float lod, CreateShapeCall makeShape)
441 {
428 BulletShape newShape = new BulletShape(); 442 BulletShape newShape = new BulletShape();
429 443
430 IMesh meshData = physicsScene.mesher.CreateMesh(prim.PhysObjectName, pbs, size, lod, 444 IMesh meshData = null;
431 false, // say it is not physical so a bounding box is not built 445 lock (physicsScene.mesher)
432 false // do not cache the mesh and do not use previously built versions 446 {
433 ); 447 meshData = physicsScene.mesher.CreateMesh(prim.PhysObjectName, pbs, size, lod,
448 false, // say it is not physical so a bounding box is not built
449 false // do not cache the mesh and do not use previously built versions
450 );
451 }
434 452
435 if (meshData != null) 453 if (meshData != null)
436 { 454 {
@@ -482,8 +500,7 @@ public class BSShapeMesh : BSShape
482 500
483 if (realIndicesIndex != 0) 501 if (realIndicesIndex != 0)
484 { 502 {
485 newShape = physicsScene.PE.CreateMeshShape(physicsScene.World, 503 newShape = makeShape(physicsScene.World, realIndicesIndex, indices, verticesAsFloats.Length / 3, verticesAsFloats);
486 realIndicesIndex, indices, verticesAsFloats.Length / 3, verticesAsFloats);
487 } 504 }
488 else 505 else
489 { 506 {
@@ -561,13 +578,74 @@ public class BSShapeHull : BSShape
561 PrimitiveBaseShape pbs, OMV.Vector3 size, float lod) 578 PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
562 { 579 {
563 BulletShape newShape = new BulletShape(); 580 BulletShape newShape = new BulletShape();
564 IntPtr hullPtr = IntPtr.Zero;
565 581
566 if (BSParam.ShouldUseBulletHACD) 582 IMesh meshData = null;
583 List<List<OMV.Vector3>> allHulls = null;
584 lock (physicsScene.mesher)
585 {
586 // Pass true for physicalness as this prevents the creation of bounding box which is not needed
587 meshData = physicsScene.mesher.CreateMesh(prim.PhysObjectName, pbs, size, lod, true /* isPhysical */, false /* shouldCache */);
588
589 // If we should use the asset's hull info, fetch it out of the locked mesher
590 if (meshData != null && BSParam.ShouldUseAssetHulls)
591 {
592 Meshmerizer realMesher = physicsScene.mesher as Meshmerizer;
593 if (realMesher != null)
594 {
595 allHulls = realMesher.GetConvexHulls(size);
596 }
597 if (allHulls == null)
598 {
599 physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,assetHulls,noAssetHull", prim.LocalID);
600 }
601 }
602 }
603
604 // If there is hull data in the mesh asset, build the hull from that
605 if (allHulls != null && BSParam.ShouldUseAssetHulls)
606 {
607 int hullCount = allHulls.Count;
608 int totalVertices = 1; // include one for the count of the hulls
609 // Using the structure described for HACD hulls, create the memory sturcture
610 // to pass the hull data to the creater.
611 foreach (List<OMV.Vector3> hullVerts in allHulls)
612 {
613 totalVertices += 4; // add four for the vertex count and centroid
614 totalVertices += hullVerts.Count * 3; // one vertex is three dimensions
615 }
616 float[] convHulls = new float[totalVertices];
617
618 convHulls[0] = (float)hullCount;
619 int jj = 1;
620 foreach (List<OMV.Vector3> hullVerts in allHulls)
621 {
622 convHulls[jj + 0] = hullVerts.Count;
623 convHulls[jj + 1] = 0f; // centroid x,y,z
624 convHulls[jj + 2] = 0f;
625 convHulls[jj + 3] = 0f;
626 jj += 4;
627 foreach (OMV.Vector3 oneVert in hullVerts)
628 {
629 convHulls[jj + 0] = oneVert.X;
630 convHulls[jj + 1] = oneVert.Y;
631 convHulls[jj + 2] = oneVert.Z;
632 jj += 3;
633 }
634 }
635
636 // create the hull data structure in Bullet
637 newShape = physicsScene.PE.CreateHullShape(physicsScene.World, hullCount, convHulls);
638
639 physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,assetHulls,hulls={1},totVert={2},shape={3}",
640 prim.LocalID, hullCount, totalVertices, newShape);
641 }
642
643 // If no hull specified in the asset and we should use Bullet's HACD approximation...
644 if (!newShape.HasPhysicalShape && BSParam.ShouldUseBulletHACD)
567 { 645 {
568 // Build the hull shape from an existing mesh shape. 646 // Build the hull shape from an existing mesh shape.
569 // The mesh should have already been created in Bullet. 647 // The mesh should have already been created in Bullet.
570 physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,shouldUseBulletHACD,entry", prim.LocalID); 648 physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,bulletHACD,entry", prim.LocalID);
571 BSShape meshShape = BSShapeMesh.GetReference(physicsScene, true, prim); 649 BSShape meshShape = BSShapeMesh.GetReference(physicsScene, true, prim);
572 650
573 if (meshShape.physShapeInfo.HasPhysicalShape) 651 if (meshShape.physShapeInfo.HasPhysicalShape)
@@ -585,129 +663,125 @@ public class BSShapeHull : BSShape
585 663
586 physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,hullFromMesh,beforeCall", prim.LocalID, newShape.HasPhysicalShape); 664 physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,hullFromMesh,beforeCall", prim.LocalID, newShape.HasPhysicalShape);
587 newShape = physicsScene.PE.BuildHullShapeFromMesh(physicsScene.World, meshShape.physShapeInfo, parms); 665 newShape = physicsScene.PE.BuildHullShapeFromMesh(physicsScene.World, meshShape.physShapeInfo, parms);
588 physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,hullFromMesh,hasBody={1}", prim.LocalID, newShape.HasPhysicalShape); 666 physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,hullFromMesh,shape={1}", prim.LocalID, newShape);
589 667
590 // Now done with the mesh shape. 668 // Now done with the mesh shape.
591 meshShape.Dereference(physicsScene); 669 meshShape.Dereference(physicsScene);
592 } 670 }
593 physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,shouldUseBulletHACD,exit,hasBody={1}", prim.LocalID, newShape.HasPhysicalShape); 671 physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,bulletHACD,exit,hasBody={1}", prim.LocalID, newShape.HasPhysicalShape);
594 } 672 }
595 if (!newShape.HasPhysicalShape) 673
674 // If no other hull specifications, use our HACD hull approximation.
675 if (!newShape.HasPhysicalShape && meshData != null)
596 { 676 {
597 // Build a new hull in the physical world using the C# HACD algorigthm. 677 if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.Fetched)
598 // Pass true for physicalness as this prevents the creation of bounding box which is not needed
599 IMesh meshData = physicsScene.mesher.CreateMesh(prim.PhysObjectName, pbs, size, lod, true /* isPhysical */, false /* shouldCache */);
600 if (meshData != null)
601 { 678 {
602 if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.Fetched) 679 // Release the fetched asset data once it has been used.
603 { 680 pbs.SculptData = new byte[0];
604 // Release the fetched asset data once it has been used. 681 prim.PrimAssetState = BSPhysObject.PrimAssetCondition.Unknown;
605 pbs.SculptData = new byte[0]; 682 }
606 prim.PrimAssetState = BSPhysObject.PrimAssetCondition.Unknown;
607 }
608 683
609 int[] indices = meshData.getIndexListAsInt(); 684 int[] indices = meshData.getIndexListAsInt();
610 List<OMV.Vector3> vertices = meshData.getVertexList(); 685 List<OMV.Vector3> vertices = meshData.getVertexList();
611 686
612 //format conversion from IMesh format to DecompDesc format 687 //format conversion from IMesh format to DecompDesc format
613 List<int> convIndices = new List<int>(); 688 List<int> convIndices = new List<int>();
614 List<float3> convVertices = new List<float3>(); 689 List<float3> convVertices = new List<float3>();
615 for (int ii = 0; ii < indices.GetLength(0); ii++) 690 for (int ii = 0; ii < indices.GetLength(0); ii++)
616 { 691 {
617 convIndices.Add(indices[ii]); 692 convIndices.Add(indices[ii]);
618 } 693 }
619 foreach (OMV.Vector3 vv in vertices) 694 foreach (OMV.Vector3 vv in vertices)
620 { 695 {
621 convVertices.Add(new float3(vv.X, vv.Y, vv.Z)); 696 convVertices.Add(new float3(vv.X, vv.Y, vv.Z));
622 } 697 }
623 698
624 uint maxDepthSplit = (uint)BSParam.CSHullMaxDepthSplit; 699 uint maxDepthSplit = (uint)BSParam.CSHullMaxDepthSplit;
625 if (BSParam.CSHullMaxDepthSplit != BSParam.CSHullMaxDepthSplitForSimpleShapes) 700 if (BSParam.CSHullMaxDepthSplit != BSParam.CSHullMaxDepthSplitForSimpleShapes)
701 {
702 // Simple primitive shapes we know are convex so they are better implemented with
703 // fewer hulls.
704 // Check for simple shape (prim without cuts) and reduce split parameter if so.
705 if (BSShapeCollection.PrimHasNoCuts(pbs))
626 { 706 {
627 // Simple primitive shapes we know are convex so they are better implemented with 707 maxDepthSplit = (uint)BSParam.CSHullMaxDepthSplitForSimpleShapes;
628 // fewer hulls.
629 // Check for simple shape (prim without cuts) and reduce split parameter if so.
630 if (BSShapeCollection.PrimHasNoCuts(pbs))
631 {
632 maxDepthSplit = (uint)BSParam.CSHullMaxDepthSplitForSimpleShapes;
633 }
634 } 708 }
709 }
710
711 // setup and do convex hull conversion
712 m_hulls = new List<ConvexResult>();
713 DecompDesc dcomp = new DecompDesc();
714 dcomp.mIndices = convIndices;
715 dcomp.mVertices = convVertices;
716 dcomp.mDepth = maxDepthSplit;
717 dcomp.mCpercent = BSParam.CSHullConcavityThresholdPercent;
718 dcomp.mPpercent = BSParam.CSHullVolumeConservationThresholdPercent;
719 dcomp.mMaxVertices = (uint)BSParam.CSHullMaxVertices;
720 dcomp.mSkinWidth = BSParam.CSHullMaxSkinWidth;
721 ConvexBuilder convexBuilder = new ConvexBuilder(HullReturn);
722 // create the hull into the _hulls variable
723 convexBuilder.process(dcomp);
724
725 physicsScene.DetailLog("{0},BSShapeCollection.CreatePhysicalHull,key={1},inVert={2},inInd={3},split={4},hulls={5}",
726 BSScene.DetailLogZero, newHullKey, indices.GetLength(0), vertices.Count, maxDepthSplit, m_hulls.Count);
727
728 // Convert the vertices and indices for passing to unmanaged.
729 // The hull information is passed as a large floating point array.
730 // The format is:
731 // convHulls[0] = number of hulls
732 // convHulls[1] = number of vertices in first hull
733 // convHulls[2] = hull centroid X coordinate
734 // convHulls[3] = hull centroid Y coordinate
735 // convHulls[4] = hull centroid Z coordinate
736 // convHulls[5] = first hull vertex X
737 // convHulls[6] = first hull vertex Y
738 // convHulls[7] = first hull vertex Z
739 // convHulls[8] = second hull vertex X
740 // ...
741 // convHulls[n] = number of vertices in second hull
742 // convHulls[n+1] = second hull centroid X coordinate
743 // ...
744 //
745 // TODO: is is very inefficient. Someday change the convex hull generator to return
746 // data structures that do not need to be converted in order to pass to Bullet.
747 // And maybe put the values directly into pinned memory rather than marshaling.
748 int hullCount = m_hulls.Count;
749 int totalVertices = 1; // include one for the count of the hulls
750 foreach (ConvexResult cr in m_hulls)
751 {
752 totalVertices += 4; // add four for the vertex count and centroid
753 totalVertices += cr.HullIndices.Count * 3; // we pass just triangles
754 }
755 float[] convHulls = new float[totalVertices];
635 756
636 // setup and do convex hull conversion 757 convHulls[0] = (float)hullCount;
637 m_hulls = new List<ConvexResult>(); 758 int jj = 1;
638 DecompDesc dcomp = new DecompDesc(); 759 foreach (ConvexResult cr in m_hulls)
639 dcomp.mIndices = convIndices; 760 {
640 dcomp.mVertices = convVertices; 761 // copy vertices for index access
641 dcomp.mDepth = maxDepthSplit; 762 float3[] verts = new float3[cr.HullVertices.Count];
642 dcomp.mCpercent = BSParam.CSHullConcavityThresholdPercent; 763 int kk = 0;
643 dcomp.mPpercent = BSParam.CSHullVolumeConservationThresholdPercent; 764 foreach (float3 ff in cr.HullVertices)
644 dcomp.mMaxVertices = (uint)BSParam.CSHullMaxVertices;
645 dcomp.mSkinWidth = BSParam.CSHullMaxSkinWidth;
646 ConvexBuilder convexBuilder = new ConvexBuilder(HullReturn);
647 // create the hull into the _hulls variable
648 convexBuilder.process(dcomp);
649
650 physicsScene.DetailLog("{0},BSShapeCollection.CreatePhysicalHull,key={1},inVert={2},inInd={3},split={4},hulls={5}",
651 BSScene.DetailLogZero, newHullKey, indices.GetLength(0), vertices.Count, maxDepthSplit, m_hulls.Count);
652
653 // Convert the vertices and indices for passing to unmanaged.
654 // The hull information is passed as a large floating point array.
655 // The format is:
656 // convHulls[0] = number of hulls
657 // convHulls[1] = number of vertices in first hull
658 // convHulls[2] = hull centroid X coordinate
659 // convHulls[3] = hull centroid Y coordinate
660 // convHulls[4] = hull centroid Z coordinate
661 // convHulls[5] = first hull vertex X
662 // convHulls[6] = first hull vertex Y
663 // convHulls[7] = first hull vertex Z
664 // convHulls[8] = second hull vertex X
665 // ...
666 // convHulls[n] = number of vertices in second hull
667 // convHulls[n+1] = second hull centroid X coordinate
668 // ...
669 //
670 // TODO: is is very inefficient. Someday change the convex hull generator to return
671 // data structures that do not need to be converted in order to pass to Bullet.
672 // And maybe put the values directly into pinned memory rather than marshaling.
673 int hullCount = m_hulls.Count;
674 int totalVertices = 1; // include one for the count of the hulls
675 foreach (ConvexResult cr in m_hulls)
676 { 765 {
677 totalVertices += 4; // add four for the vertex count and centroid 766 verts[kk++] = ff;
678 totalVertices += cr.HullIndices.Count * 3; // we pass just triangles
679 } 767 }
680 float[] convHulls = new float[totalVertices];
681 768
682 convHulls[0] = (float)hullCount; 769 // add to the array one hull's worth of data
683 int jj = 1; 770 convHulls[jj++] = cr.HullIndices.Count;
684 foreach (ConvexResult cr in m_hulls) 771 convHulls[jj++] = 0f; // centroid x,y,z
772 convHulls[jj++] = 0f;
773 convHulls[jj++] = 0f;
774 foreach (int ind in cr.HullIndices)
685 { 775 {
686 // copy vertices for index access 776 convHulls[jj++] = verts[ind].x;
687 float3[] verts = new float3[cr.HullVertices.Count]; 777 convHulls[jj++] = verts[ind].y;
688 int kk = 0; 778 convHulls[jj++] = verts[ind].z;
689 foreach (float3 ff in cr.HullVertices)
690 {
691 verts[kk++] = ff;
692 }
693
694 // add to the array one hull's worth of data
695 convHulls[jj++] = cr.HullIndices.Count;
696 convHulls[jj++] = 0f; // centroid x,y,z
697 convHulls[jj++] = 0f;
698 convHulls[jj++] = 0f;
699 foreach (int ind in cr.HullIndices)
700 {
701 convHulls[jj++] = verts[ind].x;
702 convHulls[jj++] = verts[ind].y;
703 convHulls[jj++] = verts[ind].z;
704 }
705 } 779 }
706 // create the hull data structure in Bullet
707 newShape = physicsScene.PE.CreateHullShape(physicsScene.World, hullCount, convHulls);
708 } 780 }
709 newShape.shapeKey = newHullKey; 781 // create the hull data structure in Bullet
782 newShape = physicsScene.PE.CreateHullShape(physicsScene.World, hullCount, convHulls);
710 } 783 }
784 newShape.shapeKey = newHullKey;
711 return newShape; 785 return newShape;
712 } 786 }
713 // Callback from convex hull creater with a newly created hull. 787 // Callback from convex hull creater with a newly created hull.
@@ -803,6 +877,7 @@ public class BSShapeCompound : BSShape
803 // Called at taint-time. 877 // Called at taint-time.
804 private void DereferenceAnonCollisionShape(BSScene physicsScene, BulletShape pShape) 878 private void DereferenceAnonCollisionShape(BSScene physicsScene, BulletShape pShape)
805 { 879 {
880 // TODO: figure a better way to go through all the shape types and find a possible instance.
806 BSShapeMesh meshDesc; 881 BSShapeMesh meshDesc;
807 if (BSShapeMesh.TryGetMeshByPtr(pShape, out meshDesc)) 882 if (BSShapeMesh.TryGetMeshByPtr(pShape, out meshDesc))
808 { 883 {
@@ -824,17 +899,27 @@ public class BSShapeCompound : BSShape
824 } 899 }
825 else 900 else
826 { 901 {
827 if (physicsScene.PE.IsCompound(pShape)) 902 BSShapeGImpact gImpactDesc;
903 if (BSShapeGImpact.TryGetGImpactByPtr(pShape, out gImpactDesc))
828 { 904 {
829 BSShapeCompound recursiveCompound = new BSShapeCompound(pShape); 905 gImpactDesc.Dereference(physicsScene);
830 recursiveCompound.Dereference(physicsScene);
831 } 906 }
832 else 907 else
833 { 908 {
834 if (physicsScene.PE.IsNativeShape(pShape)) 909 // Didn't find it in the lists of specific types. It could be compound.
910 if (physicsScene.PE.IsCompound(pShape))
911 {
912 BSShapeCompound recursiveCompound = new BSShapeCompound(pShape);
913 recursiveCompound.Dereference(physicsScene);
914 }
915 else
835 { 916 {
836 BSShapeNative nativeShape = new BSShapeNative(pShape); 917 // If none of the above, maybe it is a simple native shape.
837 nativeShape.Dereference(physicsScene); 918 if (physicsScene.PE.IsNativeShape(pShape))
919 {
920 BSShapeNative nativeShape = new BSShapeNative(pShape);
921 nativeShape.Dereference(physicsScene);
922 }
838 } 923 }
839 } 924 }
840 } 925 }
@@ -857,7 +942,7 @@ public class BSShapeConvexHull : BSShape
857 float lod; 942 float lod;
858 System.UInt64 newMeshKey = BSShape.ComputeShapeKey(prim.Size, prim.BaseShape, out lod); 943 System.UInt64 newMeshKey = BSShape.ComputeShapeKey(prim.Size, prim.BaseShape, out lod);
859 944
860 physicsScene.DetailLog("{0},BSShapeMesh,getReference,newKey={1},size={2},lod={3}", 945 physicsScene.DetailLog("{0},BSShapeConvexHull,getReference,newKey={1},size={2},lod={3}",
861 prim.LocalID, newMeshKey.ToString("X"), prim.Size, lod); 946 prim.LocalID, newMeshKey.ToString("X"), prim.Size, lod);
862 947
863 BSShapeConvexHull retConvexHull = null; 948 BSShapeConvexHull retConvexHull = null;
@@ -937,6 +1022,98 @@ public class BSShapeConvexHull : BSShape
937 return ret; 1022 return ret;
938 } 1023 }
939} 1024}
1025// ============================================================================================================
1026public class BSShapeGImpact : BSShape
1027{
1028 private static string LogHeader = "[BULLETSIM SHAPE GIMPACT]";
1029 public static Dictionary<System.UInt64, BSShapeGImpact> GImpacts = new Dictionary<System.UInt64, BSShapeGImpact>();
1030
1031 public BSShapeGImpact(BulletShape pShape) : base(pShape)
1032 {
1033 }
1034 public static BSShape GetReference(BSScene physicsScene, bool forceRebuild, BSPhysObject prim)
1035 {
1036 float lod;
1037 System.UInt64 newMeshKey = BSShape.ComputeShapeKey(prim.Size, prim.BaseShape, out lod);
1038
1039 physicsScene.DetailLog("{0},BSShapeGImpact,getReference,newKey={1},size={2},lod={3}",
1040 prim.LocalID, newMeshKey.ToString("X"), prim.Size, lod);
1041
1042 BSShapeGImpact retGImpact = null;
1043 lock (GImpacts)
1044 {
1045 if (GImpacts.TryGetValue(newMeshKey, out retGImpact))
1046 {
1047 // The mesh has already been created. Return a new reference to same.
1048 retGImpact.IncrementReference();
1049 }
1050 else
1051 {
1052 retGImpact = new BSShapeGImpact(new BulletShape());
1053 BulletShape newShape = retGImpact.CreatePhysicalGImpact(physicsScene, prim, newMeshKey, prim.BaseShape, prim.Size, lod);
1054
1055 // Check to see if mesh was created (might require an asset).
1056 newShape = VerifyMeshCreated(physicsScene, newShape, prim);
1057 newShape.shapeKey = newMeshKey;
1058 if (!newShape.isNativeShape || prim.PrimAssetState == BSPhysObject.PrimAssetCondition.Failed)
1059 {
1060 // If a mesh was what was created, remember the built shape for later sharing.
1061 // Also note that if meshing failed we put it in the mesh list as there is nothing else to do about the mesh.
1062 GImpacts.Add(newMeshKey, retGImpact);
1063 }
1064
1065 retGImpact.physShapeInfo = newShape;
1066 }
1067 }
1068 return retGImpact;
1069 }
1070
1071 private BulletShape CreatePhysicalGImpact(BSScene physicsScene, BSPhysObject prim, System.UInt64 newMeshKey,
1072 PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
1073 {
1074 return BSShapeMesh.CreatePhysicalMeshShape(physicsScene, prim, newMeshKey, pbs, size, lod,
1075 (w, iC, i, vC, v) => physicsScene.PE.CreateGImpactShape(w, iC, i, vC, v) );
1076 }
1077
1078 public override BSShape GetReference(BSScene physicsScene, BSPhysObject prim)
1079 {
1080 // Calling this reference means we want another handle to an existing shape
1081 // (usually linksets) so return this copy.
1082 IncrementReference();
1083 return this;
1084 }
1085 // Dereferencing a compound shape releases the hold on all the child shapes.
1086 public override void Dereference(BSScene physicsScene)
1087 {
1088 lock (GImpacts)
1089 {
1090 this.DecrementReference();
1091 physicsScene.DetailLog("{0},BSShapeGImpact.Dereference,shape={1}", BSScene.DetailLogZero, this);
1092 // TODO: schedule aging and destruction of unused meshes.
1093 }
1094 }
1095 // Loop through all the known hulls and return the description based on the physical address.
1096 public static bool TryGetGImpactByPtr(BulletShape pShape, out BSShapeGImpact outHull)
1097 {
1098 bool ret = false;
1099 BSShapeGImpact foundDesc = null;
1100 lock (GImpacts)
1101 {
1102 foreach (BSShapeGImpact sh in GImpacts.Values)
1103 {
1104 if (sh.physShapeInfo.ReferenceSame(pShape))
1105 {
1106 foundDesc = sh;
1107 ret = true;
1108 break;
1109 }
1110
1111 }
1112 }
1113 outHull = foundDesc;
1114 return ret;
1115 }
1116}
940 1117
941// ============================================================================================================ 1118// ============================================================================================================
942public class BSShapeAvatar : BSShape 1119public class BSShapeAvatar : BSShape
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt b/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt
index 5792ae6..df1da63 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt
+++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt
@@ -1,16 +1,12 @@
1PROBLEMS TO LOOK INTO 1CURRENT PROBLEMS TO FIX AND/OR LOOK AT
2================================================= 2=================================================
3Nebadon vehicle ride, get up, ride again. Second time vehicle does not act correctly. 3Script changing rotation of child prim while vehicle moving (eg turning wheel) causes
4 the wheel to appear to jump back. Looks like sending position from previous update.
5Vehicle ride, get up, ride again. Second time vehicle does not act correctly.
4 Have to rez new vehicle and delete the old to fix situation. 6 Have to rez new vehicle and delete the old to fix situation.
5Hitting RESET on Nebadon's vehicle while riding causes vehicle to get into odd 7Hitting RESET on Nebadon's vehicle while riding causes vehicle to get into odd
6 position state where it will not settle onto ground properly, etc 8 position state where it will not settle onto ground properly, etc
7Two of Nebadon vehicles in a sim max the CPU. This is new. 9Two of Nebadon vehicles in a sim max the CPU. This is new.
8A sitting, active vehicle bobs up and down a small amount.
9
10CURRENT PRIORITIES
11=================================================
12Use the HACD convex hull routine in Bullet rather than the C# version.
13 Speed up hullifying large meshes.
14Enable vehicle border crossings (at least as poorly as ODE) 10Enable vehicle border crossings (at least as poorly as ODE)
15 Terrain skirts 11 Terrain skirts
16 Avatar created in previous region and not new region when crossing border 12 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.
361Nebadon vehicles turning funny in arena (DONE) 357Nebadon vehicles turning funny in arena (DONE)
362Lock axis (DONE 20130401) 358Lock axis (DONE 20130401)
363Terrain detail: double terrain mesh detail (DONE) 359Terrain detail: double terrain mesh detail (DONE)
360Use the HACD convex hull routine in Bullet rather than the C# version.
361 Speed up hullifying large meshes. (DONE)
364 362
diff --git a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs
index 79edc12..fc679e7 100644
--- a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs
+++ b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs
@@ -64,6 +64,7 @@ namespace OpenSim.Region.Physics.Meshing
64 public class Meshmerizer : IMesher 64 public class Meshmerizer : IMesher
65 { 65 {
66 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 66 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
67 private static string LogHeader = "[MESH]";
67 68
68 // Setting baseDir to a path will enable the dumping of raw files 69 // Setting baseDir to a path will enable the dumping of raw files
69 // raw files can be imported by blender so a visual inspection of the results can be done 70 // 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
72#else 73#else
73 private const string baseDir = null; //"rawFiles"; 74 private const string baseDir = null; //"rawFiles";
74#endif 75#endif
76 // If 'true', lots of DEBUG logging of asset parsing details
77 private bool debugDetail = false;
75 78
76 private bool cacheSculptMaps = true; 79 private bool cacheSculptMaps = true;
77 private string decodedSculptMapPath = null; 80 private string decodedSculptMapPath = null;
@@ -80,6 +83,7 @@ namespace OpenSim.Region.Physics.Meshing
80 private float minSizeForComplexMesh = 0.2f; // prims with all dimensions smaller than this will have a bounding box mesh 83 private float minSizeForComplexMesh = 0.2f; // prims with all dimensions smaller than this will have a bounding box mesh
81 84
82 private List<List<Vector3>> mConvexHulls = null; 85 private List<List<Vector3>> mConvexHulls = null;
86 private List<Vector3> mBoundingHull = null;
83 87
84 private Dictionary<ulong, Mesh> m_uniqueMeshes = new Dictionary<ulong, Mesh>(); 88 private Dictionary<ulong, Mesh> m_uniqueMeshes = new Dictionary<ulong, Mesh>();
85 89
@@ -90,8 +94,11 @@ namespace OpenSim.Region.Physics.Meshing
90 94
91 decodedSculptMapPath = start_config.GetString("DecodedSculptMapPath","j2kDecodeCache"); 95 decodedSculptMapPath = start_config.GetString("DecodedSculptMapPath","j2kDecodeCache");
92 cacheSculptMaps = start_config.GetBoolean("CacheSculptMaps", cacheSculptMaps); 96 cacheSculptMaps = start_config.GetBoolean("CacheSculptMaps", cacheSculptMaps);
93 if(mesh_config != null) 97 if (mesh_config != null)
98 {
94 useMeshiesPhysicsMesh = mesh_config.GetBoolean("UseMeshiesPhysicsMesh", useMeshiesPhysicsMesh); 99 useMeshiesPhysicsMesh = mesh_config.GetBoolean("UseMeshiesPhysicsMesh", useMeshiesPhysicsMesh);
100 debugDetail = mesh_config.GetBoolean("LogMeshDetails", debugDetail);
101 }
95 102
96 try 103 try
97 { 104 {
@@ -321,6 +328,9 @@ namespace OpenSim.Region.Physics.Meshing
321 faces = new List<Face>(); 328 faces = new List<Face>();
322 OSD meshOsd = null; 329 OSD meshOsd = null;
323 330
331 mConvexHulls = null;
332 mBoundingHull = null;
333
324 if (primShape.SculptData.Length <= 0) 334 if (primShape.SculptData.Length <= 0)
325 { 335 {
326 // XXX: At the moment we can not log here since ODEPrim, for instance, ends up triggering this 336 // 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
357 OSDMap physicsParms = null; 367 OSDMap physicsParms = null;
358 OSDMap map = (OSDMap)meshOsd; 368 OSDMap map = (OSDMap)meshOsd;
359 if (map.ContainsKey("physics_shape")) 369 if (map.ContainsKey("physics_shape"))
370 {
360 physicsParms = (OSDMap)map["physics_shape"]; // old asset format 371 physicsParms = (OSDMap)map["physics_shape"]; // old asset format
372 if (debugDetail) m_log.DebugFormat("{0} prim='{1}': using 'physics_shape' mesh data", LogHeader, primName);
373 }
361 else if (map.ContainsKey("physics_mesh")) 374 else if (map.ContainsKey("physics_mesh"))
375 {
362 physicsParms = (OSDMap)map["physics_mesh"]; // new asset format 376 physicsParms = (OSDMap)map["physics_mesh"]; // new asset format
377 if (debugDetail) m_log.DebugFormat("{0} prim='{1}':using 'physics_mesh' mesh data", LogHeader, primName);
378 }
363 else if (map.ContainsKey("medium_lod")) 379 else if (map.ContainsKey("medium_lod"))
380 {
364 physicsParms = (OSDMap)map["medium_lod"]; // if no physics mesh, try to fall back to medium LOD display mesh 381 physicsParms = (OSDMap)map["medium_lod"]; // if no physics mesh, try to fall back to medium LOD display mesh
382 if (debugDetail) m_log.DebugFormat("{0} prim='{1}':using 'medium_lod' mesh data", LogHeader, primName);
383 }
365 else if (map.ContainsKey("high_lod")) 384 else if (map.ContainsKey("high_lod"))
385 {
366 physicsParms = (OSDMap)map["high_lod"]; // if all else fails, use highest LOD display mesh and hope it works :) 386 physicsParms = (OSDMap)map["high_lod"]; // if all else fails, use highest LOD display mesh and hope it works :)
387 if (debugDetail) m_log.DebugFormat("{0} prim='{1}':using 'high_lod' mesh data", LogHeader, primName);
388 }
367 389
368 if (map.ContainsKey("physics_convex")) 390 if (map.ContainsKey("physics_convex"))
369 { // pull this out also in case physics engine can use it 391 { // pull this out also in case physics engine can use it
392 OSD convexBlockOsd = null;
370 try 393 try
371 { 394 {
372 OSDMap convexBlock = (OSDMap)map["physics_convex"]; 395 OSDMap convexBlock = (OSDMap)map["physics_convex"];
373 if (convexBlock.ContainsKey("HullList"))
374 { 396 {
375 byte[] hullList = convexBlock["HullList"].AsBinary(); 397 int convexOffset = convexBlock["offset"].AsInteger() + (int)start;
398 int convexSize = convexBlock["size"].AsInteger();
399
400 byte[] convexBytes = new byte[convexSize];
401
402 System.Buffer.BlockCopy(primShape.SculptData, convexOffset, convexBytes, 0, convexSize);
403
404 try
405 {
406 convexBlockOsd = DecompressOsd(convexBytes);
407 }
408 catch (Exception e)
409 {
410 m_log.ErrorFormat("{0} prim='{1}': exception decoding convex block: {2}", LogHeader, primName, e);
411 //return false;
412 }
413 }
414
415 if (convexBlockOsd != null && convexBlockOsd is OSDMap)
416 {
417 convexBlock = convexBlockOsd as OSDMap;
418
419 if (debugDetail)
420 {
421 string keys = LogHeader + " keys found in convexBlock: ";
422 foreach (KeyValuePair<string, OSD> kvp in convexBlock)
423 keys += "'" + kvp.Key + "' ";
424 m_log.Debug(keys);
425 }
426
376 Vector3 min = new Vector3(-0.5f, -0.5f, -0.5f); 427 Vector3 min = new Vector3(-0.5f, -0.5f, -0.5f);
377 if (convexBlock.ContainsKey("Min")) min = convexBlock["Min"].AsVector3(); 428 if (convexBlock.ContainsKey("Min")) min = convexBlock["Min"].AsVector3();
378 Vector3 max = new Vector3(0.5f, 0.5f, 0.5f); 429 Vector3 max = new Vector3(0.5f, 0.5f, 0.5f);
379 if (convexBlock.ContainsKey("Max")) max = convexBlock["Max"].AsVector3(); 430 if (convexBlock.ContainsKey("Max")) max = convexBlock["Max"].AsVector3();
380 431
381 // decompress and decode hull points 432 List<Vector3> boundingHull = null;
382 byte[] posBytes = DecompressOsd(convexBlock["Positions"].AsBinary()).AsBinary();
383
384 List<List<Vector3>> hulls = new List<List<Vector3>>();
385 int posNdx = 0;
386 433
387 foreach (byte cnt in hullList) 434 if (convexBlock.ContainsKey("BoundingVerts"))
388 { 435 {
389 int count = cnt == 0 ? 256 : cnt; 436 byte[] boundingVertsBytes = convexBlock["BoundingVerts"].AsBinary();
390 List<Vector3> hull = new List<Vector3>(); 437 boundingHull = new List<Vector3>();
391 438 for (int i = 0; i < boundingVertsBytes.Length; )
392 for (int i = 0; i < count; i++)
393 { 439 {
394 ushort uX = Utils.BytesToUInt16(posBytes, posNdx); posNdx += 2; 440 ushort uX = Utils.BytesToUInt16(boundingVertsBytes, i); i += 2;
395 ushort uY = Utils.BytesToUInt16(posBytes, posNdx); posNdx += 2; 441 ushort uY = Utils.BytesToUInt16(boundingVertsBytes, i); i += 2;
396 ushort uZ = Utils.BytesToUInt16(posBytes, posNdx); posNdx += 2; 442 ushort uZ = Utils.BytesToUInt16(boundingVertsBytes, i); i += 2;
397 443
398 Vector3 pos = new Vector3( 444 Vector3 pos = new Vector3(
399 Utils.UInt16ToFloat(uX, min.X, max.X), 445 Utils.UInt16ToFloat(uX, min.X, max.X),
@@ -401,18 +447,57 @@ namespace OpenSim.Region.Physics.Meshing
401 Utils.UInt16ToFloat(uZ, min.Z, max.Z) 447 Utils.UInt16ToFloat(uZ, min.Z, max.Z)
402 ); 448 );
403 449
404 hull.Add(pos); 450 boundingHull.Add(pos);
405 } 451 }
406 452
407 hulls.Add(hull); 453 mBoundingHull = boundingHull;
454 if (debugDetail) m_log.DebugFormat("{0} prim='{1}': parsed bounding hull. nVerts={2}", LogHeader, primName, mBoundingHull.Count);
408 } 455 }
409 456
410 mConvexHulls = hulls; 457 if (convexBlock.ContainsKey("HullList"))
458 {
459 byte[] hullList = convexBlock["HullList"].AsBinary();
460
461 byte[] posBytes = convexBlock["Positions"].AsBinary();
462
463 List<List<Vector3>> hulls = new List<List<Vector3>>();
464 int posNdx = 0;
465
466 foreach (byte cnt in hullList)
467 {
468 int count = cnt == 0 ? 256 : cnt;
469 List<Vector3> hull = new List<Vector3>();
470
471 for (int i = 0; i < count; i++)
472 {
473 ushort uX = Utils.BytesToUInt16(posBytes, posNdx); posNdx += 2;
474 ushort uY = Utils.BytesToUInt16(posBytes, posNdx); posNdx += 2;
475 ushort uZ = Utils.BytesToUInt16(posBytes, posNdx); posNdx += 2;
476
477 Vector3 pos = new Vector3(
478 Utils.UInt16ToFloat(uX, min.X, max.X),
479 Utils.UInt16ToFloat(uY, min.Y, max.Y),
480 Utils.UInt16ToFloat(uZ, min.Z, max.Z)
481 );
482
483 hull.Add(pos);
484 }
485
486 hulls.Add(hull);
487 }
488
489 mConvexHulls = hulls;
490 if (debugDetail) m_log.DebugFormat("{0} prim='{1}': parsed hulls. nHulls={2}", LogHeader, primName, mConvexHulls.Count);
491 }
492 else
493 {
494 if (debugDetail) m_log.DebugFormat("{0} prim='{1}' has physics_convex but no HullList", LogHeader, primName);
495 }
411 } 496 }
412 } 497 }
413 catch (Exception e) 498 catch (Exception e)
414 { 499 {
415 m_log.WarnFormat("[MESH]: exception decoding convex block: {0}", e.Message); 500 m_log.WarnFormat("{0} exception decoding convex block: {1}", LogHeader, e);
416 } 501 }
417 } 502 }
418 503
@@ -431,14 +516,14 @@ namespace OpenSim.Region.Physics.Meshing
431 OSD decodedMeshOsd = new OSD(); 516 OSD decodedMeshOsd = new OSD();
432 byte[] meshBytes = new byte[physSize]; 517 byte[] meshBytes = new byte[physSize];
433 System.Buffer.BlockCopy(primShape.SculptData, physOffset, meshBytes, 0, physSize); 518 System.Buffer.BlockCopy(primShape.SculptData, physOffset, meshBytes, 0, physSize);
434// byte[] decompressed = new byte[physSize * 5]; 519 // byte[] decompressed = new byte[physSize * 5];
435 try 520 try
436 { 521 {
437 decodedMeshOsd = DecompressOsd(meshBytes); 522 decodedMeshOsd = DecompressOsd(meshBytes);
438 } 523 }
439 catch (Exception e) 524 catch (Exception e)
440 { 525 {
441 m_log.Error("[MESH]: exception decoding physical mesh: " + e.ToString()); 526 m_log.ErrorFormat("{0} prim='{1}': exception decoding physical mesh: {2}", LogHeader, primName, e);
442 return false; 527 return false;
443 } 528 }
444 529
@@ -447,7 +532,7 @@ namespace OpenSim.Region.Physics.Meshing
447 // physics_shape is an array of OSDMaps, one for each submesh 532 // physics_shape is an array of OSDMaps, one for each submesh
448 if (decodedMeshOsd is OSDArray) 533 if (decodedMeshOsd is OSDArray)
449 { 534 {
450// Console.WriteLine("decodedMeshOsd for {0} - {1}", primName, Util.GetFormattedXml(decodedMeshOsd)); 535 // Console.WriteLine("decodedMeshOsd for {0} - {1}", primName, Util.GetFormattedXml(decodedMeshOsd));
451 536
452 decodedMeshOsdArray = (OSDArray)decodedMeshOsd; 537 decodedMeshOsdArray = (OSDArray)decodedMeshOsd;
453 foreach (OSD subMeshOsd in decodedMeshOsdArray) 538 foreach (OSD subMeshOsd in decodedMeshOsdArray)
@@ -455,6 +540,9 @@ namespace OpenSim.Region.Physics.Meshing
455 if (subMeshOsd is OSDMap) 540 if (subMeshOsd is OSDMap)
456 AddSubMesh(subMeshOsd as OSDMap, size, coords, faces); 541 AddSubMesh(subMeshOsd as OSDMap, size, coords, faces);
457 } 542 }
543 if (debugDetail)
544 m_log.DebugFormat("{0} {1}: mesh decoded. offset={2}, size={3}, nCoords={4}, nFaces={5}",
545 LogHeader, primName, physOffset, physSize, coords.Count, faces.Count);
458 } 546 }
459 } 547 }
460 548
@@ -776,6 +864,23 @@ namespace OpenSim.Region.Physics.Meshing
776 /// temporary prototype code - please do not use until the interface has been finalized! 864 /// temporary prototype code - please do not use until the interface has been finalized!
777 /// </summary> 865 /// </summary>
778 /// <param name="size">value to scale the hull points by</param> 866 /// <param name="size">value to scale the hull points by</param>
867 /// <returns>a list of vertices in the bounding hull if it exists and has been successfully decoded, otherwise null</returns>
868 public List<Vector3> GetBoundingHull(Vector3 size)
869 {
870 if (mBoundingHull == null)
871 return null;
872
873 List<Vector3> verts = new List<Vector3>();
874 foreach (var vert in mBoundingHull)
875 verts.Add(vert * size);
876
877 return verts;
878 }
879
880 /// <summary>
881 /// temporary prototype code - please do not use until the interface has been finalized!
882 /// </summary>
883 /// <param name="size">value to scale the hull points by</param>
779 /// <returns>a list of hulls if they exist and have been successfully decoded, otherwise null</returns> 884 /// <returns>a list of hulls if they exist and have been successfully decoded, otherwise null</returns>
780 public List<List<Vector3>> GetConvexHulls(Vector3 size) 885 public List<List<Vector3>> GetConvexHulls(Vector3 size)
781 { 886 {
@@ -788,6 +893,7 @@ namespace OpenSim.Region.Physics.Meshing
788 List<Vector3> verts = new List<Vector3>(); 893 List<Vector3> verts = new List<Vector3>();
789 foreach (var vert in hull) 894 foreach (var vert in hull)
790 verts.Add(vert * size); 895 verts.Add(vert * size);
896 hulls.Add(verts);
791 } 897 }
792 898
793 return hulls; 899 return hulls;
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index 969243c..0b4b043 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -2474,9 +2474,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2474 // send the sound, once, to all clients in range 2474 // send the sound, once, to all clients in range
2475 if (m_SoundModule != null) 2475 if (m_SoundModule != null)
2476 { 2476 {
2477 m_SoundModule.SendSound(m_host.UUID, 2477 m_SoundModule.SendSound(
2478 ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound, AssetType.Sound), volume, false, 0, 2478 m_host.UUID,
2479 0, false, false); 2479 ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound, AssetType.Sound),
2480 volume, false, m_host.SoundQueueing ? (byte)SoundFlags.Queue : (byte)SoundFlags.None,
2481 0, false, false);
2480 } 2482 }
2481 } 2483 }
2482 2484
@@ -11822,7 +11824,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11822 public void llSetSoundQueueing(int queue) 11824 public void llSetSoundQueueing(int queue)
11823 { 11825 {
11824 m_host.AddScriptLPS(1); 11826 m_host.AddScriptLPS(1);
11825 NotImplemented("llSetSoundQueueing"); 11827
11828 if (m_SoundModule != null)
11829 m_SoundModule.SetSoundQueueing(m_host.UUID, queue == ScriptBaseClass.TRUE.value);
11826 } 11830 }
11827 11831
11828 public void llCollisionSprite(string impact_sprite) 11832 public void llCollisionSprite(string impact_sprite)
diff --git a/OpenSim/Tests/Common/Mock/TestClient.cs b/OpenSim/Tests/Common/Mock/TestClient.cs
index 09e751a..c660501 100644
--- a/OpenSim/Tests/Common/Mock/TestClient.cs
+++ b/OpenSim/Tests/Common/Mock/TestClient.cs
@@ -651,7 +651,7 @@ namespace OpenSim.Tests.Common.Mock
651 { 651 {
652 } 652 }
653 653
654 public virtual void SendMoneyBalance(UUID transaction, bool success, byte[] description, int balance) 654 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)
655 { 655 {
656 } 656 }
657 657
@@ -875,11 +875,6 @@ namespace OpenSim.Tests.Common.Mock
875 875
876 } 876 }
877 877
878 public bool AddMoney(int debit)
879 {
880 return false;
881 }
882
883 public void SendSunPos(Vector3 sunPos, Vector3 sunVel, ulong time, uint dlen, uint ylen, float phase) 878 public void SendSunPos(Vector3 sunPos, Vector3 sunVel, ulong time, uint dlen, uint ylen, float phase)
884 { 879 {
885 } 880 }
diff --git a/bin/lib32/BulletSim.dll b/bin/lib32/BulletSim.dll
index 1e94d05..bc0e222 100755
--- a/bin/lib32/BulletSim.dll
+++ b/bin/lib32/BulletSim.dll
Binary files differ
diff --git a/bin/lib32/libBulletSim.so b/bin/lib32/libBulletSim.so
index 6216a65..e09dd27 100755
--- a/bin/lib32/libBulletSim.so
+++ b/bin/lib32/libBulletSim.so
Binary files differ
diff --git a/bin/lib64/BulletSim.dll b/bin/lib64/BulletSim.dll
index 68cfcc4..5fc09f6 100755
--- a/bin/lib64/BulletSim.dll
+++ b/bin/lib64/BulletSim.dll
Binary files differ
diff --git a/bin/lib64/libBulletSim.so b/bin/lib64/libBulletSim.so
index 08c00af..925269d 100755
--- a/bin/lib64/libBulletSim.so
+++ b/bin/lib64/libBulletSim.so
Binary files differ
diff --git a/prebuild.xml b/prebuild.xml
index 9fbe08b..25c287e 100644
--- a/prebuild.xml
+++ b/prebuild.xml
@@ -1753,6 +1753,7 @@
1753 <Reference name="OpenSim.Region.CoreModules"/> 1753 <Reference name="OpenSim.Region.CoreModules"/>
1754 <Reference name="OpenSim.Framework.Console"/> 1754 <Reference name="OpenSim.Framework.Console"/>
1755 <Reference name="OpenSim.Region.Physics.Manager"/> 1755 <Reference name="OpenSim.Region.Physics.Manager"/>
1756 <Reference name="OpenSim.Region.Physics.Meshing" path="../../../../bin/Physics/"/>
1756 <Reference name="OpenSim.Region.Physics.ConvexDecompositionDotNet"/> 1757 <Reference name="OpenSim.Region.Physics.ConvexDecompositionDotNet"/>
1757 <Reference name="BulletXNA.dll" path="../../../../bin/"/> 1758 <Reference name="BulletXNA.dll" path="../../../../bin/"/>
1758 <Reference name="log4net.dll" path="../../../../bin/"/> 1759 <Reference name="log4net.dll" path="../../../../bin/"/>