Merge branch 'master' into connector_plugin
commit
0b455d2882
|
@ -246,6 +246,11 @@ namespace OpenSim.Capabilities.Handlers
|
|||
}
|
||||
else
|
||||
{
|
||||
// Handle the case where no second range value was given. This is equivalent to requesting
|
||||
// the rest of the entity.
|
||||
if (end == -1)
|
||||
end = int.MaxValue;
|
||||
|
||||
end = Utils.Clamp(end, 0, texture.Data.Length - 1);
|
||||
start = Utils.Clamp(start, 0, end);
|
||||
int len = end - start + 1;
|
||||
|
@ -299,16 +304,44 @@ namespace OpenSim.Capabilities.Handlers
|
|||
// texture.FullID, range, response.StatusCode, response.ContentLength, texture.Data.Length);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a range header.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// As per http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html,
|
||||
/// this obeys range headers with two values (e.g. 533-4165) and no second value (e.g. 533-).
|
||||
/// Where there is no value, -1 is returned.
|
||||
/// FIXME: Need to cover the case where only a second value is specified (e.g. -4165), probably by returning -1
|
||||
/// for start.</remarks>
|
||||
/// <returns></returns>
|
||||
/// <param name='header'></param>
|
||||
/// <param name='start'>Start of the range. Undefined if this was not a number.</param>
|
||||
/// <param name='end'>End of the range. Will be -1 if no end specified. Undefined if there was a raw string but this was not a number.</param>
|
||||
private bool TryParseRange(string header, out int start, out int end)
|
||||
{
|
||||
start = end = 0;
|
||||
|
||||
if (header.StartsWith("bytes="))
|
||||
{
|
||||
string[] rangeValues = header.Substring(6).Split('-');
|
||||
|
||||
if (rangeValues.Length == 2)
|
||||
{
|
||||
if (Int32.TryParse(rangeValues[0], out start) && Int32.TryParse(rangeValues[1], out end))
|
||||
if (!Int32.TryParse(rangeValues[0], out start))
|
||||
return false;
|
||||
|
||||
string rawEnd = rangeValues[1];
|
||||
|
||||
if (rawEnd == "")
|
||||
{
|
||||
end = -1;
|
||||
return true;
|
||||
}
|
||||
else if (Int32.TryParse(rawEnd, out end))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
start = end = 0;
|
||||
|
|
|
@ -44,9 +44,15 @@ namespace OpenSim.Data.Tests
|
|||
/// <summary>This is a base class for testing any Data service for any DBMS.
|
||||
/// Requires NUnit 2.5 or better (to support the generics).
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// FIXME: Should extend OpenSimTestCase but compile on mono 2.4.3 currently fails with
|
||||
/// AssetTests`2 : System.MemberAccessException : Cannot create an instance of OpenSim.Data.Tests.AssetTests`2[TConn,TAssetData] because Type.ContainsGenericParameters is true.
|
||||
/// and similar on EstateTests, InventoryTests and RegionTests.
|
||||
/// Runs fine with mono 2.10.8.1, so easiest thing is to wait until min Mono version uplifts.
|
||||
/// </remarks>
|
||||
/// <typeparam name="TConn"></typeparam>
|
||||
/// <typeparam name="TService"></typeparam>
|
||||
public class BasicDataServiceTest<TConn, TService> : OpenSimTestCase
|
||||
public class BasicDataServiceTest<TConn, TService>
|
||||
where TConn : DbConnection, new()
|
||||
where TService : class, new()
|
||||
{
|
||||
|
|
|
@ -0,0 +1,508 @@
|
|||
/*
|
||||
* Copyright (c) 2008, openmetaverse.org, http://opensimulator.org/
|
||||
* All rights reserved.
|
||||
*
|
||||
* - Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* - Neither the name of the openmetaverse.org nor the names
|
||||
* of its contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace OpenSim.Framework
|
||||
{
|
||||
/// <summary>
|
||||
/// A double dictionary that is thread abort safe.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This adapts OpenMetaverse.DoubleDictionary to be thread-abort safe by acquiring ReaderWriterLockSlim within
|
||||
/// a finally section (which can't be interrupted by Thread.Abort()).
|
||||
/// </remarks>
|
||||
public class DoubleDictionaryThreadAbortSafe<TKey1, TKey2, TValue>
|
||||
{
|
||||
Dictionary<TKey1, TValue> Dictionary1;
|
||||
Dictionary<TKey2, TValue> Dictionary2;
|
||||
ReaderWriterLockSlim rwLock = new ReaderWriterLockSlim();
|
||||
|
||||
public DoubleDictionaryThreadAbortSafe()
|
||||
{
|
||||
Dictionary1 = new Dictionary<TKey1,TValue>();
|
||||
Dictionary2 = new Dictionary<TKey2,TValue>();
|
||||
}
|
||||
|
||||
public DoubleDictionaryThreadAbortSafe(int capacity)
|
||||
{
|
||||
Dictionary1 = new Dictionary<TKey1, TValue>(capacity);
|
||||
Dictionary2 = new Dictionary<TKey2, TValue>(capacity);
|
||||
}
|
||||
|
||||
public void Add(TKey1 key1, TKey2 key2, TValue value)
|
||||
{
|
||||
bool gotLock = false;
|
||||
|
||||
try
|
||||
{
|
||||
// Avoid an asynchronous Thread.Abort() from possibly never existing an acquired lock by placing
|
||||
// the acquision inside the main try. The inner finally block is needed because thread aborts cannot
|
||||
// interrupt code in these blocks (hence gotLock is guaranteed to be set correctly).
|
||||
try {}
|
||||
finally
|
||||
{
|
||||
rwLock.EnterWriteLock();
|
||||
gotLock = true;
|
||||
}
|
||||
|
||||
if (Dictionary1.ContainsKey(key1))
|
||||
{
|
||||
if (!Dictionary2.ContainsKey(key2))
|
||||
throw new ArgumentException("key1 exists in the dictionary but not key2");
|
||||
}
|
||||
else if (Dictionary2.ContainsKey(key2))
|
||||
{
|
||||
if (!Dictionary1.ContainsKey(key1))
|
||||
throw new ArgumentException("key2 exists in the dictionary but not key1");
|
||||
}
|
||||
|
||||
Dictionary1[key1] = value;
|
||||
Dictionary2[key2] = value;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (gotLock)
|
||||
rwLock.ExitWriteLock();
|
||||
}
|
||||
}
|
||||
|
||||
public bool Remove(TKey1 key1, TKey2 key2)
|
||||
{
|
||||
bool success;
|
||||
bool gotLock = false;
|
||||
|
||||
try
|
||||
{
|
||||
// Avoid an asynchronous Thread.Abort() from possibly never existing an acquired lock by placing
|
||||
// the acquision inside the main try. The inner finally block is needed because thread aborts cannot
|
||||
// interrupt code in these blocks (hence gotLock is guaranteed to be set correctly).
|
||||
try {}
|
||||
finally
|
||||
{
|
||||
rwLock.EnterWriteLock();
|
||||
gotLock = true;
|
||||
}
|
||||
|
||||
Dictionary1.Remove(key1);
|
||||
success = Dictionary2.Remove(key2);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (gotLock)
|
||||
rwLock.ExitWriteLock();
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
public bool Remove(TKey1 key1)
|
||||
{
|
||||
bool found = false;
|
||||
bool gotLock = false;
|
||||
|
||||
try
|
||||
{
|
||||
// Avoid an asynchronous Thread.Abort() from possibly never existing an acquired lock by placing
|
||||
// the acquision inside the main try. The inner finally block is needed because thread aborts cannot
|
||||
// interrupt code in these blocks (hence gotLock is guaranteed to be set correctly).
|
||||
try {}
|
||||
finally
|
||||
{
|
||||
rwLock.EnterWriteLock();
|
||||
gotLock = true;
|
||||
}
|
||||
|
||||
// This is an O(n) operation!
|
||||
TValue value;
|
||||
if (Dictionary1.TryGetValue(key1, out value))
|
||||
{
|
||||
foreach (KeyValuePair<TKey2, TValue> kvp in Dictionary2)
|
||||
{
|
||||
if (kvp.Value.Equals(value))
|
||||
{
|
||||
Dictionary1.Remove(key1);
|
||||
Dictionary2.Remove(kvp.Key);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (gotLock)
|
||||
rwLock.ExitWriteLock();
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
public bool Remove(TKey2 key2)
|
||||
{
|
||||
bool found = false;
|
||||
bool gotLock = false;
|
||||
|
||||
try
|
||||
{
|
||||
// Avoid an asynchronous Thread.Abort() from possibly never existing an acquired lock by placing
|
||||
// the acquision inside the main try. The inner finally block is needed because thread aborts cannot
|
||||
// interrupt code in these blocks (hence gotLock is guaranteed to be set correctly).
|
||||
try {}
|
||||
finally
|
||||
{
|
||||
rwLock.EnterWriteLock();
|
||||
gotLock = true;
|
||||
}
|
||||
|
||||
// This is an O(n) operation!
|
||||
TValue value;
|
||||
if (Dictionary2.TryGetValue(key2, out value))
|
||||
{
|
||||
foreach (KeyValuePair<TKey1, TValue> kvp in Dictionary1)
|
||||
{
|
||||
if (kvp.Value.Equals(value))
|
||||
{
|
||||
Dictionary2.Remove(key2);
|
||||
Dictionary1.Remove(kvp.Key);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (gotLock)
|
||||
rwLock.ExitWriteLock();
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
bool gotLock = false;
|
||||
|
||||
try
|
||||
{
|
||||
// Avoid an asynchronous Thread.Abort() from possibly never existing an acquired lock by placing
|
||||
// the acquision inside the main try. The inner finally block is needed because thread aborts cannot
|
||||
// interrupt code in these blocks (hence gotLock is guaranteed to be set correctly).
|
||||
try {}
|
||||
finally
|
||||
{
|
||||
rwLock.EnterWriteLock();
|
||||
gotLock = true;
|
||||
}
|
||||
|
||||
Dictionary1.Clear();
|
||||
Dictionary2.Clear();
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (gotLock)
|
||||
rwLock.ExitWriteLock();
|
||||
}
|
||||
}
|
||||
|
||||
public int Count
|
||||
{
|
||||
get { return Dictionary1.Count; }
|
||||
}
|
||||
|
||||
public bool ContainsKey(TKey1 key)
|
||||
{
|
||||
return Dictionary1.ContainsKey(key);
|
||||
}
|
||||
|
||||
public bool ContainsKey(TKey2 key)
|
||||
{
|
||||
return Dictionary2.ContainsKey(key);
|
||||
}
|
||||
|
||||
public bool TryGetValue(TKey1 key, out TValue value)
|
||||
{
|
||||
bool success;
|
||||
bool gotLock = false;
|
||||
|
||||
try
|
||||
{
|
||||
// Avoid an asynchronous Thread.Abort() from possibly never existing an acquired lock by placing
|
||||
// the acquision inside the main try. The inner finally block is needed because thread aborts cannot
|
||||
// interrupt code in these blocks (hence gotLock is guaranteed to be set correctly).
|
||||
try {}
|
||||
finally
|
||||
{
|
||||
rwLock.EnterReadLock();
|
||||
gotLock = true;
|
||||
}
|
||||
|
||||
success = Dictionary1.TryGetValue(key, out value);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (gotLock)
|
||||
rwLock.ExitReadLock();
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
public bool TryGetValue(TKey2 key, out TValue value)
|
||||
{
|
||||
bool success;
|
||||
bool gotLock = false;
|
||||
|
||||
try
|
||||
{
|
||||
// Avoid an asynchronous Thread.Abort() from possibly never existing an acquired lock by placing
|
||||
// the acquision inside the main try. The inner finally block is needed because thread aborts cannot
|
||||
// interrupt code in these blocks (hence gotLock is guaranteed to be set correctly).
|
||||
try {}
|
||||
finally
|
||||
{
|
||||
rwLock.EnterReadLock();
|
||||
gotLock = true;
|
||||
}
|
||||
|
||||
success = Dictionary2.TryGetValue(key, out value);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (gotLock)
|
||||
rwLock.ExitReadLock();
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
public void ForEach(Action<TValue> action)
|
||||
{
|
||||
bool gotLock = false;
|
||||
|
||||
try
|
||||
{
|
||||
// Avoid an asynchronous Thread.Abort() from possibly never existing an acquired lock by placing
|
||||
// the acquision inside the main try. The inner finally block is needed because thread aborts cannot
|
||||
// interrupt code in these blocks (hence gotLock is guaranteed to be set correctly).
|
||||
try {}
|
||||
finally
|
||||
{
|
||||
rwLock.EnterReadLock();
|
||||
gotLock = true;
|
||||
}
|
||||
|
||||
foreach (TValue value in Dictionary1.Values)
|
||||
action(value);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (gotLock)
|
||||
rwLock.ExitReadLock();
|
||||
}
|
||||
}
|
||||
|
||||
public void ForEach(Action<KeyValuePair<TKey1, TValue>> action)
|
||||
{
|
||||
bool gotLock = false;
|
||||
|
||||
try
|
||||
{
|
||||
// Avoid an asynchronous Thread.Abort() from possibly never existing an acquired lock by placing
|
||||
// the acquision inside the main try. The inner finally block is needed because thread aborts cannot
|
||||
// interrupt code in these blocks (hence gotLock is guaranteed to be set correctly).
|
||||
try {}
|
||||
finally
|
||||
{
|
||||
rwLock.EnterReadLock();
|
||||
gotLock = true;
|
||||
}
|
||||
|
||||
foreach (KeyValuePair<TKey1, TValue> entry in Dictionary1)
|
||||
action(entry);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (gotLock)
|
||||
rwLock.ExitReadLock();
|
||||
}
|
||||
}
|
||||
|
||||
public void ForEach(Action<KeyValuePair<TKey2, TValue>> action)
|
||||
{
|
||||
bool gotLock = false;
|
||||
|
||||
try
|
||||
{
|
||||
// Avoid an asynchronous Thread.Abort() from possibly never existing an acquired lock by placing
|
||||
// the acquision inside the main try. The inner finally block is needed because thread aborts cannot
|
||||
// interrupt code in these blocks (hence gotLock is guaranteed to be set correctly).
|
||||
try {}
|
||||
finally
|
||||
{
|
||||
rwLock.EnterReadLock();
|
||||
gotLock = true;
|
||||
}
|
||||
|
||||
foreach (KeyValuePair<TKey2, TValue> entry in Dictionary2)
|
||||
action(entry);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (gotLock)
|
||||
rwLock.ExitReadLock();
|
||||
}
|
||||
}
|
||||
|
||||
public TValue FindValue(Predicate<TValue> predicate)
|
||||
{
|
||||
bool gotLock = false;
|
||||
|
||||
try
|
||||
{
|
||||
// Avoid an asynchronous Thread.Abort() from possibly never existing an acquired lock by placing
|
||||
// the acquision inside the main try. The inner finally block is needed because thread aborts cannot
|
||||
// interrupt code in these blocks (hence gotLock is guaranteed to be set correctly).
|
||||
try {}
|
||||
finally
|
||||
{
|
||||
rwLock.EnterReadLock();
|
||||
gotLock = true;
|
||||
}
|
||||
|
||||
foreach (TValue value in Dictionary1.Values)
|
||||
{
|
||||
if (predicate(value))
|
||||
return value;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (gotLock)
|
||||
rwLock.ExitReadLock();
|
||||
}
|
||||
|
||||
return default(TValue);
|
||||
}
|
||||
|
||||
public IList<TValue> FindAll(Predicate<TValue> predicate)
|
||||
{
|
||||
IList<TValue> list = new List<TValue>();
|
||||
bool gotLock = false;
|
||||
|
||||
try
|
||||
{
|
||||
// Avoid an asynchronous Thread.Abort() from possibly never existing an acquired lock by placing
|
||||
// the acquision inside the main try. The inner finally block is needed because thread aborts cannot
|
||||
// interrupt code in these blocks (hence gotLock is guaranteed to be set correctly).
|
||||
try {}
|
||||
finally
|
||||
{
|
||||
rwLock.EnterReadLock();
|
||||
gotLock = true;
|
||||
}
|
||||
|
||||
foreach (TValue value in Dictionary1.Values)
|
||||
{
|
||||
if (predicate(value))
|
||||
list.Add(value);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (gotLock)
|
||||
rwLock.ExitReadLock();
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
public int RemoveAll(Predicate<TValue> predicate)
|
||||
{
|
||||
IList<TKey1> list = new List<TKey1>();
|
||||
bool gotUpgradeableLock = false;
|
||||
|
||||
try
|
||||
{
|
||||
// Avoid an asynchronous Thread.Abort() from possibly never existing an acquired lock by placing
|
||||
// the acquision inside the main try. The inner finally block is needed because thread aborts cannot
|
||||
// interrupt code in these blocks (hence gotLock is guaranteed to be set correctly).
|
||||
try {}
|
||||
finally
|
||||
{
|
||||
rwLock.EnterUpgradeableReadLock();
|
||||
gotUpgradeableLock = true;
|
||||
}
|
||||
|
||||
foreach (KeyValuePair<TKey1, TValue> kvp in Dictionary1)
|
||||
{
|
||||
if (predicate(kvp.Value))
|
||||
list.Add(kvp.Key);
|
||||
}
|
||||
|
||||
IList<TKey2> list2 = new List<TKey2>(list.Count);
|
||||
foreach (KeyValuePair<TKey2, TValue> kvp in Dictionary2)
|
||||
{
|
||||
if (predicate(kvp.Value))
|
||||
list2.Add(kvp.Key);
|
||||
}
|
||||
|
||||
bool gotWriteLock = false;
|
||||
|
||||
try
|
||||
{
|
||||
try {}
|
||||
finally
|
||||
{
|
||||
rwLock.EnterUpgradeableReadLock();
|
||||
gotWriteLock = true;
|
||||
}
|
||||
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
Dictionary1.Remove(list[i]);
|
||||
|
||||
for (int i = 0; i < list2.Count; i++)
|
||||
Dictionary2.Remove(list2[i]);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (gotWriteLock)
|
||||
rwLock.ExitWriteLock();
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (gotUpgradeableLock)
|
||||
rwLock.ExitUpgradeableReadLock();
|
||||
}
|
||||
|
||||
return list.Count;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -193,17 +193,6 @@ namespace OpenSim.Framework
|
|||
public PrimitiveBaseShape()
|
||||
{
|
||||
PCode = (byte)PCodeEnum.Primitive;
|
||||
ExtraParams = new byte[1];
|
||||
m_textureEntry = DEFAULT_TEXTURE;
|
||||
}
|
||||
|
||||
public PrimitiveBaseShape(bool noShape)
|
||||
{
|
||||
if (noShape)
|
||||
return;
|
||||
|
||||
PCode = (byte)PCodeEnum.Primitive;
|
||||
ExtraParams = new byte[1];
|
||||
m_textureEntry = DEFAULT_TEXTURE;
|
||||
}
|
||||
|
||||
|
@ -216,7 +205,6 @@ namespace OpenSim.Framework
|
|||
// m_log.DebugFormat("[PRIMITIVE BASE SHAPE]: Creating from {0}", prim.ID);
|
||||
|
||||
PCode = (byte)prim.PrimData.PCode;
|
||||
ExtraParams = new byte[1];
|
||||
|
||||
State = prim.PrimData.State;
|
||||
PathBegin = Primitive.PackBeginCut(prim.PrimData.PathBegin);
|
||||
|
@ -248,7 +236,10 @@ namespace OpenSim.Framework
|
|||
SculptTexture = prim.Sculpt.SculptTexture;
|
||||
SculptType = (byte)prim.Sculpt.Type;
|
||||
}
|
||||
else SculptType = (byte)OpenMetaverse.SculptType.None;
|
||||
else
|
||||
{
|
||||
SculptType = (byte)OpenMetaverse.SculptType.None;
|
||||
}
|
||||
}
|
||||
|
||||
[XmlIgnore]
|
||||
|
@ -340,9 +331,9 @@ namespace OpenSim.Framework
|
|||
_scale = new Vector3(side, side, side);
|
||||
}
|
||||
|
||||
public void SetHeigth(float heigth)
|
||||
public void SetHeigth(float height)
|
||||
{
|
||||
_scale.Z = heigth;
|
||||
_scale.Z = height;
|
||||
}
|
||||
|
||||
public void SetRadius(float radius)
|
||||
|
|
|
@ -436,7 +436,7 @@ namespace OpenSim.Framework.Servers.HttpServer
|
|||
// reqnum = String.Format("{0}:{1}",request.RemoteIPEndPoint,request.Headers["opensim-request-id"]);
|
||||
//m_log.DebugFormat("[BASE HTTP SERVER]: <{0}> handle request for {1}",reqnum,request.RawUrl);
|
||||
|
||||
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US", true);
|
||||
Culture.SetCurrentCulture();
|
||||
|
||||
// // This is the REST agent interface. We require an agent to properly identify
|
||||
// // itself. If the REST handler recognizes the prefix it will attempt to
|
||||
|
|
|
@ -304,9 +304,5 @@ namespace OpenSim.Framework.Tests
|
|||
Assert.That(Thread.CurrentThread.CurrentCulture.Name == ci.Name, "SetCurrentCulture failed to set thread culture to en-US");
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -53,8 +53,10 @@ namespace OpenSim.Region.CoreModules.Asset.Tests
|
|||
protected FlotsamAssetCache m_cache;
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
public override void SetUp()
|
||||
{
|
||||
base.SetUp();
|
||||
|
||||
IConfigSource config = new IniConfigSource();
|
||||
|
||||
config.AddConfig("Modules");
|
||||
|
|
|
@ -81,8 +81,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Groups
|
|||
}
|
||||
|
||||
if (groupsConfig.GetString("Module", "Default") != "Default")
|
||||
{
|
||||
m_Enabled = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -146,7 +146,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
|
|||
if (sp != null && !sp.IsChildAgent)
|
||||
{
|
||||
// Local message
|
||||
m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to root agent {0} {1}", sp.Name, toAgentID);
|
||||
// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to root agent {0} {1}", sp.Name, toAgentID);
|
||||
|
||||
sp.ControllingClient.SendInstantMessage(im);
|
||||
|
||||
|
@ -159,14 +159,14 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
|
|||
// try child avatar second
|
||||
foreach (Scene scene in m_Scenes)
|
||||
{
|
||||
m_log.DebugFormat(
|
||||
"[INSTANT MESSAGE]: Looking for child of {0} in {1}", toAgentID, scene.RegionInfo.RegionName);
|
||||
// m_log.DebugFormat(
|
||||
// "[INSTANT MESSAGE]: Looking for child of {0} in {1}", toAgentID, scene.RegionInfo.RegionName);
|
||||
|
||||
ScenePresence sp = scene.GetScenePresence(toAgentID);
|
||||
if (sp != null)
|
||||
{
|
||||
// Local message
|
||||
m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to child agent {0} {1}", sp.Name, toAgentID);
|
||||
// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to child agent {0} {1}", sp.Name, toAgentID);
|
||||
|
||||
sp.ControllingClient.SendInstantMessage(im);
|
||||
|
||||
|
@ -176,7 +176,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
|
|||
}
|
||||
}
|
||||
|
||||
m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to {0} via XMLRPC", im.toAgentID);
|
||||
// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to {0} via XMLRPC", im.toAgentID);
|
||||
|
||||
SendGridInstantMessageViaXMLRPC(im, result);
|
||||
}
|
||||
|
|
|
@ -186,8 +186,11 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
|
|||
|
||||
foreach (GridInstantMessage im in msglist)
|
||||
{
|
||||
// client.SendInstantMessage(im);
|
||||
|
||||
if (im.dialog == (byte)InstantMessageDialog.InventoryOffered)
|
||||
// send it directly or else the item will be given twice
|
||||
client.SendInstantMessage(im);
|
||||
else
|
||||
{
|
||||
// Send through scene event manager so all modules get a chance
|
||||
// to look at this message before it gets delivered.
|
||||
//
|
||||
|
@ -200,6 +203,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void UndeliveredMessage(GridInstantMessage im)
|
||||
{
|
||||
|
@ -215,7 +219,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
|
|||
if (!m_ForwardOfflineGroupMessages)
|
||||
{
|
||||
if (im.dialog == (byte)InstantMessageDialog.GroupNotice ||
|
||||
im.dialog != (byte)InstantMessageDialog.GroupInvitation)
|
||||
im.dialog == (byte)InstantMessageDialog.GroupInvitation)
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -57,8 +57,10 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess.Tests
|
|||
protected TestClient m_tc;
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
public override void SetUp()
|
||||
{
|
||||
base.SetUp();
|
||||
|
||||
m_iam = new BasicInventoryAccessModule();
|
||||
|
||||
IConfigSource config = new IniConfigSource();
|
||||
|
|
|
@ -46,8 +46,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence.Tests
|
|||
public class PresenceConnectorsTests : OpenSimTestCase
|
||||
{
|
||||
LocalPresenceServicesConnector m_LocalConnector;
|
||||
private void SetUp()
|
||||
|
||||
public override void SetUp()
|
||||
{
|
||||
base.SetUp();
|
||||
|
||||
IConfigSource config = new IniConfigSource();
|
||||
config.AddConfig("Modules");
|
||||
config.AddConfig("PresenceService");
|
||||
|
|
|
@ -60,8 +60,10 @@ namespace OpenSim.Region.CoreModules.World.Land.Tests
|
|||
protected ILandObject m_lo2;
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
public override void SetUp()
|
||||
{
|
||||
base.SetUp();
|
||||
|
||||
m_pcm = new PrimCountModule();
|
||||
LandManagementModule lmm = new LandManagementModule();
|
||||
m_scene = new SceneHelpers().SetupScene();
|
||||
|
|
|
@ -50,8 +50,10 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap.Tests
|
|||
protected MoapModule m_module;
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
public override void SetUp()
|
||||
{
|
||||
base.SetUp();
|
||||
|
||||
m_module = new MoapModule();
|
||||
m_scene = new SceneHelpers().SetupScene();
|
||||
SceneHelpers.SetupSceneModules(m_scene, m_module);
|
||||
|
|
|
@ -365,7 +365,8 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
|
|||
|
||||
if (mainParams.Count < 4)
|
||||
{
|
||||
m_console.OutputFormat("Usage: show part id [--full] <UUID-or-localID>");
|
||||
//m_console.OutputFormat("Usage: show part id [--full] <UUID-or-localID>");
|
||||
m_console.OutputFormat("Usage: show part id <UUID-or-localID>");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -405,6 +406,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
|
|||
|
||||
if (mainParams.Count < 5)
|
||||
{
|
||||
//m_console.OutputFormat("Usage: show part pos <start-coord> to <end-coord>");
|
||||
m_console.OutputFormat("Usage: show part pos [--full] <start-coord> to <end-coord>");
|
||||
return;
|
||||
}
|
||||
|
@ -445,7 +447,8 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
|
|||
|
||||
if (mainParams.Count < 4)
|
||||
{
|
||||
m_console.OutputFormat("Usage: show part name [--full] [--regex] <name>");
|
||||
m_console.OutputFormat("Usage: show part name [--regex] <name>");
|
||||
//m_console.OutputFormat("Usage: show part name [--full] [--regex] <name>");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -577,6 +580,58 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
|
|||
cdl.AddRow("Link number", sop.LinkNum);
|
||||
cdl.AddRow("Flags", sop.Flags);
|
||||
|
||||
if (showFull)
|
||||
{
|
||||
PrimitiveBaseShape s = sop.Shape;
|
||||
cdl.AddRow("FlexiDrag", s.FlexiDrag);
|
||||
cdl.AddRow("FlexiEntry", s.FlexiEntry);
|
||||
cdl.AddRow("FlexiForce", string.Format("<{0},{1},{2}>", s.FlexiForceX, s.FlexiForceY, s.FlexiForceZ));
|
||||
cdl.AddRow("FlexiGravity", s.FlexiGravity);
|
||||
cdl.AddRow("FlexiSoftness", s.FlexiSoftness);
|
||||
cdl.AddRow("HollowShape", s.HollowShape);
|
||||
cdl.AddRow(
|
||||
"LightColor",
|
||||
string.Format("<{0},{1},{2},{3}>", s.LightColorR, s.LightColorB, s.LightColorG, s.LightColorA));
|
||||
cdl.AddRow("FlexiDrag", s.LightCutoff);
|
||||
cdl.AddRow("FlexiDrag", s.LightEntry);
|
||||
cdl.AddRow("FlexiDrag", s.LightFalloff);
|
||||
cdl.AddRow("FlexiDrag", s.LightIntensity);
|
||||
cdl.AddRow("FlexiDrag", s.LightRadius);
|
||||
cdl.AddRow("Media", string.Format("{0} entries", s.Media != null ? s.Media.Count.ToString() : "n/a"));
|
||||
cdl.AddRow("PathBegin", s.PathBegin);
|
||||
cdl.AddRow("PathEnd", s.PathEnd);
|
||||
cdl.AddRow("PathCurve", s.PathCurve);
|
||||
cdl.AddRow("PathRadiusOffset", s.PathRadiusOffset);
|
||||
cdl.AddRow("PathRevolutions", s.PathRevolutions);
|
||||
cdl.AddRow("PathScale", string.Format("<{0},{1}>", s.PathScaleX, s.PathScaleY));
|
||||
cdl.AddRow("PathSkew", string.Format("<{0},{1}>", s.PathShearX, s.PathShearY));
|
||||
cdl.AddRow("FlexiDrag", s.PathSkew);
|
||||
cdl.AddRow("PathTaper", string.Format("<{0},{1}>", s.PathTaperX, s.PathTaperY));
|
||||
cdl.AddRow("PathTwist", s.PathTwist);
|
||||
cdl.AddRow("PathTwistBegin", s.PathTwistBegin);
|
||||
cdl.AddRow("PCode", s.PCode);
|
||||
cdl.AddRow("ProfileBegin", s.ProfileBegin);
|
||||
cdl.AddRow("ProfileEnd", s.ProfileEnd);
|
||||
cdl.AddRow("ProfileHollow", s.ProfileHollow);
|
||||
cdl.AddRow("ProfileShape", s.ProfileShape);
|
||||
cdl.AddRow("ProjectionAmbiance", s.ProjectionAmbiance);
|
||||
cdl.AddRow("ProjectionEntry", s.ProjectionEntry);
|
||||
cdl.AddRow("ProjectionFocus", s.ProjectionFocus);
|
||||
cdl.AddRow("ProjectionFOV", s.ProjectionFOV);
|
||||
cdl.AddRow("ProjectionTextureUUID", s.ProjectionTextureUUID);
|
||||
cdl.AddRow("Scale", s.Scale);
|
||||
cdl.AddRow(
|
||||
"SculptData",
|
||||
string.Format("{0} bytes", s.SculptData != null ? s.SculptData.Length.ToString() : "n/a"));
|
||||
cdl.AddRow("SculptEntry", s.SculptEntry);
|
||||
cdl.AddRow("SculptTexture", s.SculptTexture);
|
||||
cdl.AddRow("SculptType", s.SculptType);
|
||||
cdl.AddRow("State", s.State);
|
||||
|
||||
// TODO, unpack and display texture entries
|
||||
//cdl.AddRow("Textures", string.Format("{0} entries", s.Textures.
|
||||
}
|
||||
|
||||
object itemsOutput;
|
||||
if (showFull)
|
||||
{
|
||||
|
@ -588,7 +643,6 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
|
|||
itemsOutput = sop.Inventory.Count;
|
||||
}
|
||||
|
||||
|
||||
cdl.AddRow("Items", itemsOutput);
|
||||
|
||||
return sb.Append(cdl.ToString());
|
||||
|
|
|
@ -34,5 +34,6 @@ namespace OpenSim.Region.Framework.Interfaces
|
|||
void RegisterNewReceiver(IScriptModule scriptEngine, UUID channelID, UUID objectID, UUID itemID, string url);
|
||||
void ScriptRemoved(UUID itemID);
|
||||
void ObjectRemoved(UUID objectID);
|
||||
void UnRegisterReceiver(string channelID, UUID itemID);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ using System.Collections.Generic;
|
|||
using System.Reflection;
|
||||
using log4net;
|
||||
using OpenMetaverse;
|
||||
using OpenSim.Framework;
|
||||
|
||||
namespace OpenSim.Region.Framework.Scenes
|
||||
{
|
||||
|
@ -38,7 +39,8 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
{
|
||||
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
private readonly DoubleDictionary<UUID, uint, EntityBase> m_entities = new DoubleDictionary<UUID, uint, EntityBase>();
|
||||
private readonly DoubleDictionaryThreadAbortSafe<UUID, uint, EntityBase> m_entities
|
||||
= new DoubleDictionaryThreadAbortSafe<UUID, uint, EntityBase>();
|
||||
|
||||
public int Count
|
||||
{
|
||||
|
|
|
@ -5638,10 +5638,17 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
return m_SpawnPoint - 1;
|
||||
}
|
||||
|
||||
// Wrappers to get physics modules retrieve assets. Has to be done this way
|
||||
// because we can't assign the asset service to physics directly - at the
|
||||
// time physics are instantiated it's not registered but it will be by
|
||||
// the time the first prim exists.
|
||||
/// <summary>
|
||||
/// Wrappers to get physics modules retrieve assets.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Has to be done this way
|
||||
/// because we can't assign the asset service to physics directly - at the
|
||||
/// time physics are instantiated it's not registered but it will be by
|
||||
/// the time the first prim exists.
|
||||
/// </remarks>
|
||||
/// <param name="assetID"></param>
|
||||
/// <param name="callback"></param>
|
||||
public void PhysicsRequestAsset(UUID assetID, AssetReceivedDelegate callback)
|
||||
{
|
||||
AssetService.Get(assetID.ToString(), callback, PhysicsAssetReceived);
|
||||
|
|
|
@ -46,6 +46,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.XmlRpcGridRouterModule
|
|||
{
|
||||
public class XmlRpcInfo
|
||||
{
|
||||
public UUID item;
|
||||
public UUID channel;
|
||||
public string uri;
|
||||
}
|
||||
|
@ -88,6 +89,14 @@ namespace OpenSim.Region.OptionalModules.Scripting.XmlRpcGridRouterModule
|
|||
return;
|
||||
|
||||
scene.RegisterModuleInterface<IXmlRpcRouter>(this);
|
||||
|
||||
IScriptModule scriptEngine = scene.RequestModuleInterface<IScriptModule>();
|
||||
if ( scriptEngine != null )
|
||||
{
|
||||
scriptEngine.OnScriptRemoved += this.ScriptRemoved;
|
||||
scriptEngine.OnObjectRemoved += this.ObjectRemoved;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void RegionLoaded(Scene scene)
|
||||
|
@ -120,11 +129,16 @@ namespace OpenSim.Region.OptionalModules.Scripting.XmlRpcGridRouterModule
|
|||
|
||||
public void RegisterNewReceiver(IScriptModule scriptEngine, UUID channel, UUID objectID, UUID itemID, string uri)
|
||||
{
|
||||
if (!m_Channels.ContainsKey(itemID))
|
||||
{
|
||||
if (!m_Enabled)
|
||||
return;
|
||||
|
||||
m_log.InfoFormat("[XMLRPC GRID ROUTER]: New receiver Obj: {0} Ch: {1} ID: {2} URI: {3}",
|
||||
objectID.ToString(), channel.ToString(), itemID.ToString(), uri);
|
||||
|
||||
XmlRpcInfo info = new XmlRpcInfo();
|
||||
info.channel = channel;
|
||||
info.uri = uri;
|
||||
info.item = itemID;
|
||||
|
||||
bool success = SynchronousRestObjectRequester.MakeRequest<XmlRpcInfo, bool>(
|
||||
"POST", m_ServerURI+"/RegisterChannel/", info);
|
||||
|
@ -135,7 +149,16 @@ namespace OpenSim.Region.OptionalModules.Scripting.XmlRpcGridRouterModule
|
|||
}
|
||||
|
||||
m_Channels[itemID] = channel;
|
||||
|
||||
}
|
||||
|
||||
public void UnRegisterReceiver(string channelID, UUID itemID)
|
||||
{
|
||||
if (!m_Enabled)
|
||||
return;
|
||||
|
||||
RemoveChannel(itemID);
|
||||
|
||||
}
|
||||
|
||||
public void ScriptRemoved(UUID itemID)
|
||||
|
@ -143,10 +166,33 @@ namespace OpenSim.Region.OptionalModules.Scripting.XmlRpcGridRouterModule
|
|||
if (!m_Enabled)
|
||||
return;
|
||||
|
||||
if (m_Channels.ContainsKey(itemID))
|
||||
RemoveChannel(itemID);
|
||||
|
||||
}
|
||||
|
||||
public void ObjectRemoved(UUID objectID)
|
||||
{
|
||||
bool success = SynchronousRestObjectRequester.MakeRequest<UUID, bool>(
|
||||
"POST", m_ServerURI+"/RemoveChannel/", m_Channels[itemID]);
|
||||
// m_log.InfoFormat("[XMLRPC GRID ROUTER]: Object Removed {0}",objectID.ToString());
|
||||
}
|
||||
|
||||
private bool RemoveChannel(UUID itemID)
|
||||
{
|
||||
if(!m_Channels.ContainsKey(itemID))
|
||||
{
|
||||
m_log.InfoFormat("[XMLRPC GRID ROUTER]: Attempted to unregister non-existing Item: {0}", itemID.ToString());
|
||||
return false;
|
||||
}
|
||||
|
||||
XmlRpcInfo info = new XmlRpcInfo();
|
||||
|
||||
info.channel = m_Channels[itemID];
|
||||
info.item = itemID;
|
||||
info.uri = "http://0.0.0.0:00";
|
||||
|
||||
if (info != null)
|
||||
{
|
||||
bool success = SynchronousRestObjectRequester.MakeRequest<XmlRpcInfo, bool>(
|
||||
"POST", m_ServerURI+"/RemoveChannel/", info);
|
||||
|
||||
if (!success)
|
||||
{
|
||||
|
@ -154,11 +200,9 @@ namespace OpenSim.Region.OptionalModules.Scripting.XmlRpcGridRouterModule
|
|||
}
|
||||
|
||||
m_Channels.Remove(itemID);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public void ObjectRemoved(UUID objectID)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -101,12 +101,18 @@ namespace OpenSim.Region.OptionalModules.Scripting.XmlRpcRouterModule
|
|||
scriptEngine.PostScriptEvent(itemID, "xmlrpc_uri", new Object[] {uri});
|
||||
}
|
||||
|
||||
public void UnRegisterReceiver(string channelID, UUID itemID)
|
||||
{
|
||||
}
|
||||
|
||||
public void ScriptRemoved(UUID itemID)
|
||||
{
|
||||
System.Console.WriteLine("TEST Script Removed!");
|
||||
}
|
||||
|
||||
public void ObjectRemoved(UUID objectID)
|
||||
{
|
||||
System.Console.WriteLine("TEST Obj Removed!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -165,8 +165,8 @@ public sealed class BSCharacter : BSPhysObject
|
|||
BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, PhysBody.ptr);
|
||||
|
||||
// Do this after the object has been added to the world
|
||||
BulletSimAPI.SetCollisionFilterMask2(PhysBody.ptr,
|
||||
(uint)CollisionFilterGroups.AvatarFilter,
|
||||
BulletSimAPI.SetCollisionGroupMask2(PhysBody.ptr,
|
||||
(uint)CollisionFilterGroups.AvatarGroup,
|
||||
(uint)CollisionFilterGroups.AvatarMask);
|
||||
}
|
||||
|
||||
|
@ -307,7 +307,7 @@ public sealed class BSCharacter : BSPhysObject
|
|||
}
|
||||
if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0)
|
||||
{
|
||||
float waterHeight = PhysicsScene.GetWaterLevelAtXYZ(_position);
|
||||
float waterHeight = PhysicsScene.TerrainManager.GetWaterLevelAtXYZ(_position);
|
||||
if (Position.Z < waterHeight)
|
||||
{
|
||||
_position.Z = waterHeight;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,4 +1,4 @@
|
|||
/*
|
||||
/*
|
||||
* Copyright (c) Contributors, http://opensimulator.org/
|
||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||
*
|
||||
|
@ -53,24 +53,19 @@ public struct MaterialAttributes
|
|||
// Names must be in the order of the above enum.
|
||||
public static string[] MaterialNames = { "Stone", "Metal", "Glass", "Wood",
|
||||
"Flesh", "Plastic", "Rubber", "Light", "Avatar" };
|
||||
public static string[] MaterialAttribs = { "Density", "Friction", "Restitution",
|
||||
"ccdMotionThreshold", "ccdSweptSphereRadius" };
|
||||
public static string[] MaterialAttribs = { "Density", "Friction", "Restitution"};
|
||||
|
||||
public MaterialAttributes(string t, float d, float f, float r, float ccdM, float ccdS)
|
||||
public MaterialAttributes(string t, float d, float f, float r)
|
||||
{
|
||||
type = t;
|
||||
density = d;
|
||||
friction = f;
|
||||
restitution = r;
|
||||
ccdMotionThreshold = ccdM;
|
||||
ccdSweptSphereRadius = ccdS;
|
||||
}
|
||||
public string type;
|
||||
public float density;
|
||||
public float friction;
|
||||
public float restitution;
|
||||
public float ccdMotionThreshold;
|
||||
public float ccdSweptSphereRadius;
|
||||
}
|
||||
|
||||
public static class BSMaterials
|
||||
|
@ -86,50 +81,49 @@ public static class BSMaterials
|
|||
// This is where all the default material attributes are defined.
|
||||
public static void InitializeFromDefaults(ConfigurationParameters parms)
|
||||
{
|
||||
// Values from http://wiki.secondlife.com/wiki/PRIM_MATERIAL
|
||||
// public static string[] MaterialNames = { "Stone", "Metal", "Glass", "Wood",
|
||||
// "Flesh", "Plastic", "Rubber", "Light", "Avatar" };
|
||||
float dFriction = parms.defaultFriction;
|
||||
float dRestitution = parms.defaultRestitution;
|
||||
float dDensity = parms.defaultDensity;
|
||||
float dCcdM = parms.ccdMotionThreshold;
|
||||
float dCcdS = parms.ccdSweptSphereRadius;
|
||||
Attributes[(int)MaterialAttributes.Material.Stone] =
|
||||
new MaterialAttributes("stone",dDensity,dFriction,dRestitution, dCcdM, dCcdS);
|
||||
new MaterialAttributes("stone",dDensity, 0.8f, 0.4f);
|
||||
Attributes[(int)MaterialAttributes.Material.Metal] =
|
||||
new MaterialAttributes("metal",dDensity,dFriction,dRestitution, dCcdM, dCcdS);
|
||||
new MaterialAttributes("metal",dDensity, 0.3f, 0.4f);
|
||||
Attributes[(int)MaterialAttributes.Material.Glass] =
|
||||
new MaterialAttributes("glass",dDensity,dFriction,dRestitution, dCcdM, dCcdS);
|
||||
new MaterialAttributes("glass",dDensity, 0.2f, 0.7f);
|
||||
Attributes[(int)MaterialAttributes.Material.Wood] =
|
||||
new MaterialAttributes("wood",dDensity,dFriction,dRestitution, dCcdM, dCcdS);
|
||||
new MaterialAttributes("wood",dDensity, 0.6f, 0.5f);
|
||||
Attributes[(int)MaterialAttributes.Material.Flesh] =
|
||||
new MaterialAttributes("flesh",dDensity,dFriction,dRestitution, dCcdM, dCcdS);
|
||||
new MaterialAttributes("flesh",dDensity, 0.9f, 0.3f);
|
||||
Attributes[(int)MaterialAttributes.Material.Plastic] =
|
||||
new MaterialAttributes("plastic",dDensity,dFriction,dRestitution, dCcdM, dCcdS);
|
||||
new MaterialAttributes("plastic",dDensity, 0.4f, 0.7f);
|
||||
Attributes[(int)MaterialAttributes.Material.Rubber] =
|
||||
new MaterialAttributes("rubber",dDensity,dFriction,dRestitution, dCcdM, dCcdS);
|
||||
new MaterialAttributes("rubber",dDensity, 0.9f, 0.9f);
|
||||
Attributes[(int)MaterialAttributes.Material.Light] =
|
||||
new MaterialAttributes("light",dDensity,dFriction,dRestitution, dCcdM, dCcdS);
|
||||
new MaterialAttributes("light",dDensity, dFriction, dRestitution);
|
||||
Attributes[(int)MaterialAttributes.Material.Avatar] =
|
||||
new MaterialAttributes("avatar",dDensity,dFriction,dRestitution, dCcdM, dCcdS);
|
||||
new MaterialAttributes("avatar",60f, 0.2f, 0f);
|
||||
|
||||
Attributes[(int)MaterialAttributes.Material.Stone + (int)MaterialAttributes.Material.NumberOfTypes] =
|
||||
new MaterialAttributes("stonePhysical",dDensity,dFriction,dRestitution, dCcdM, dCcdS);
|
||||
new MaterialAttributes("stonePhysical",dDensity, 0.8f, 0.4f);
|
||||
Attributes[(int)MaterialAttributes.Material.Metal + (int)MaterialAttributes.Material.NumberOfTypes] =
|
||||
new MaterialAttributes("metalPhysical",dDensity,dFriction,dRestitution, dCcdM, dCcdS);
|
||||
new MaterialAttributes("metalPhysical",dDensity, 0.8f, 0.4f);
|
||||
Attributes[(int)MaterialAttributes.Material.Glass + (int)MaterialAttributes.Material.NumberOfTypes] =
|
||||
new MaterialAttributes("glassPhysical",dDensity,dFriction,dRestitution, dCcdM, dCcdS);
|
||||
new MaterialAttributes("glassPhysical",dDensity, 0.8f, 0.7f);
|
||||
Attributes[(int)MaterialAttributes.Material.Wood + (int)MaterialAttributes.Material.NumberOfTypes] =
|
||||
new MaterialAttributes("woodPhysical",dDensity,dFriction,dRestitution, dCcdM, dCcdS);
|
||||
new MaterialAttributes("woodPhysical",dDensity, 0.8f, 0.5f);
|
||||
Attributes[(int)MaterialAttributes.Material.Flesh + (int)MaterialAttributes.Material.NumberOfTypes] =
|
||||
new MaterialAttributes("fleshPhysical",dDensity,dFriction,dRestitution, dCcdM, dCcdS);
|
||||
new MaterialAttributes("fleshPhysical",dDensity, 0.8f, 0.3f);
|
||||
Attributes[(int)MaterialAttributes.Material.Plastic + (int)MaterialAttributes.Material.NumberOfTypes] =
|
||||
new MaterialAttributes("plasticPhysical",dDensity,dFriction,dRestitution, dCcdM, dCcdS);
|
||||
new MaterialAttributes("plasticPhysical",dDensity, 0.8f, 0.7f);
|
||||
Attributes[(int)MaterialAttributes.Material.Rubber + (int)MaterialAttributes.Material.NumberOfTypes] =
|
||||
new MaterialAttributes("rubberPhysical",dDensity,dFriction,dRestitution, dCcdM, dCcdS);
|
||||
new MaterialAttributes("rubberPhysical",dDensity, 0.8f, 0.9f);
|
||||
Attributes[(int)MaterialAttributes.Material.Light + (int)MaterialAttributes.Material.NumberOfTypes] =
|
||||
new MaterialAttributes("lightPhysical",dDensity,dFriction,dRestitution, dCcdM, dCcdS);
|
||||
new MaterialAttributes("lightPhysical",dDensity, dFriction, dRestitution);
|
||||
Attributes[(int)MaterialAttributes.Material.Avatar + (int)MaterialAttributes.Material.NumberOfTypes] =
|
||||
new MaterialAttributes("avatarPhysical",dDensity,dFriction,dRestitution, dCcdM, dCcdS);
|
||||
new MaterialAttributes("avatarPhysical",60f, 0.2f, 0f);
|
||||
}
|
||||
|
||||
// Under the [BulletSim] section, one can change the individual material
|
||||
|
|
|
@ -1,3 +1,30 @@
|
|||
/*
|
||||
* Copyright (c) Contributors, http://opensimulator.org/
|
||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the OpenSimulator Project nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
@ -7,6 +34,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
|||
{
|
||||
public abstract class BSMotor
|
||||
{
|
||||
// Timescales and other things can be turned off by setting them to 'infinite'.
|
||||
public const float Infinite = 12345f;
|
||||
public readonly static Vector3 InfiniteVector = new Vector3(BSMotor.Infinite, BSMotor.Infinite, BSMotor.Infinite);
|
||||
|
||||
public BSMotor(string useName)
|
||||
{
|
||||
UseName = useName;
|
||||
|
@ -15,7 +46,9 @@ public abstract class BSMotor
|
|||
public virtual void Reset() { }
|
||||
public virtual void Zero() { }
|
||||
|
||||
// A name passed at motor creation for easily identifyable debugging messages.
|
||||
public string UseName { get; private set; }
|
||||
|
||||
// Used only for outputting debug information. Might not be set so check for null.
|
||||
public BSScene PhysicsScene { get; set; }
|
||||
protected void MDetailLog(string msg, params Object[] parms)
|
||||
|
@ -30,10 +63,23 @@ public abstract class BSMotor
|
|||
}
|
||||
}
|
||||
// Can all the incremental stepping be replaced with motor classes?
|
||||
|
||||
// Motor which moves CurrentValue to TargetValue over TimeScale seconds.
|
||||
// The TargetValue is decays in TargetValueDecayTimeScale and
|
||||
// the CurrentValue will be held back by FrictionTimeScale.
|
||||
// TimeScale and TargetDelayTimeScale may be 'infinite' which means go decay.
|
||||
|
||||
// For instance, if something is moving at speed X and the desired speed is Y,
|
||||
// CurrentValue is X and TargetValue is Y. As the motor is stepped, new
|
||||
// values of CurrentValue are returned that approach the TargetValue.
|
||||
// The feature of decaying TargetValue is so vehicles will eventually
|
||||
// come to a stop rather than run forever. This can be disabled by
|
||||
// setting TargetValueDecayTimescale to 'infinite'.
|
||||
// The change from CurrentValue to TargetValue is linear over TimeScale seconds.
|
||||
public class BSVMotor : BSMotor
|
||||
{
|
||||
public Vector3 FrameOfReference { get; set; }
|
||||
public Vector3 Offset { get; set; }
|
||||
// public Vector3 FrameOfReference { get; set; }
|
||||
// public Vector3 Offset { get; set; }
|
||||
|
||||
public float TimeScale { get; set; }
|
||||
public float TargetValueDecayTimeScale { get; set; }
|
||||
|
@ -46,8 +92,9 @@ public class BSVMotor : BSMotor
|
|||
public BSVMotor(string useName)
|
||||
: base(useName)
|
||||
{
|
||||
TimeScale = TargetValueDecayTimeScale = Efficiency = 1f;
|
||||
FrictionTimescale = Vector3.Zero;
|
||||
TimeScale = TargetValueDecayTimeScale = BSMotor.Infinite;
|
||||
Efficiency = 1f;
|
||||
FrictionTimescale = BSMotor.InfiniteVector;
|
||||
CurrentValue = TargetValue = Vector3.Zero;
|
||||
}
|
||||
public BSVMotor(string useName, float timeScale, float decayTimeScale, Vector3 frictionTimeScale, float efficiency)
|
||||
|
@ -67,6 +114,14 @@ public class BSVMotor : BSMotor
|
|||
{
|
||||
TargetValue = target;
|
||||
}
|
||||
|
||||
// A form of stepping that does not take the time quantum into account.
|
||||
// The caller must do the right thing later.
|
||||
public Vector3 Step()
|
||||
{
|
||||
return Step(1f);
|
||||
}
|
||||
|
||||
public Vector3 Step(float timeStep)
|
||||
{
|
||||
Vector3 returnCurrent = Vector3.Zero;
|
||||
|
@ -78,23 +133,36 @@ public class BSVMotor : BSMotor
|
|||
// Addition = (desiredVector - currentAppliedVector) / secondsItShouldTakeToComplete
|
||||
Vector3 addAmount = (TargetValue - CurrentValue)/TimeScale * timeStep;
|
||||
CurrentValue += addAmount;
|
||||
|
||||
returnCurrent = CurrentValue;
|
||||
|
||||
// The desired value reduces to zero when also reduces the difference with current.
|
||||
float decayFactor = (1.0f / TargetValueDecayTimeScale) * timeStep;
|
||||
// The desired value reduces to zero which also reduces the difference with current.
|
||||
// If the decay time is infinite, don't decay at all.
|
||||
float decayFactor = 0f;
|
||||
if (TargetValueDecayTimeScale != BSMotor.Infinite)
|
||||
{
|
||||
decayFactor = (1.0f / TargetValueDecayTimeScale) * timeStep;
|
||||
TargetValue *= (1f - decayFactor);
|
||||
}
|
||||
|
||||
Vector3 frictionFactor = Vector3.Zero;
|
||||
frictionFactor = (Vector3.One / FrictionTimescale) * timeStep;
|
||||
if (FrictionTimescale != BSMotor.InfiniteVector)
|
||||
{
|
||||
// frictionFactor = (Vector3.One / FrictionTimescale) * timeStep;
|
||||
// Individual friction components can be 'infinite' so compute each separately.
|
||||
frictionFactor.X = FrictionTimescale.X == BSMotor.Infinite ? 0f : (1f / FrictionTimescale.X) * timeStep;
|
||||
frictionFactor.Y = FrictionTimescale.Y == BSMotor.Infinite ? 0f : (1f / FrictionTimescale.Y) * timeStep;
|
||||
frictionFactor.Z = FrictionTimescale.Z == BSMotor.Infinite ? 0f : (1f / FrictionTimescale.Z) * timeStep;
|
||||
CurrentValue *= (Vector3.One - frictionFactor);
|
||||
}
|
||||
|
||||
MDetailLog("{0},BSVMotor.Step,nonZero,{1},origTarget={2},origCurr={3},timeStep={4},timeScale={5},addAmnt={6},targetDecay={7},decayFact={8},fricTS={9},frictFact={10}",
|
||||
BSScene.DetailLogZero, UseName, origTarget, origCurrVal,
|
||||
MDetailLog("{0}, BSVMotor.Step,nonZero,{1},origCurr={2},origTarget={3},timeStep={4},timeScale={5},addAmnt={6},targetDecay={7},decayFact={8},fricTS={9},frictFact={10}",
|
||||
BSScene.DetailLogZero, UseName, origCurrVal, origTarget,
|
||||
timeStep, TimeScale, addAmount,
|
||||
TargetValueDecayTimeScale, decayFactor,
|
||||
FrictionTimescale, frictionFactor);
|
||||
MDetailLog("{0}, BSVMotor.Step,nonZero,{1},curr={2},target={3},add={4},decay={5},frict={6},ret={7}",
|
||||
BSScene.DetailLogZero, UseName, TargetValue, CurrentValue,
|
||||
BSScene.DetailLogZero, UseName, CurrentValue, TargetValue,
|
||||
addAmount, decayFactor, frictionFactor, returnCurrent);
|
||||
}
|
||||
else
|
||||
|
|
|
@ -253,8 +253,9 @@ public sealed class BSPrim : BSPhysObject
|
|||
// Zero some other properties in the physics engine
|
||||
PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ZeroMotion", delegate()
|
||||
{
|
||||
BulletSimAPI.SetInterpolationAngularVelocity2(PhysBody.ptr, OMV.Vector3.Zero);
|
||||
BulletSimAPI.SetAngularVelocity2(PhysBody.ptr, OMV.Vector3.Zero);
|
||||
// DetailLog("{0},BSPrim.ZeroAngularMotion,call,rotVel={1}", LocalID, _rotationalVelocity);
|
||||
BulletSimAPI.SetInterpolationAngularVelocity2(PhysBody.ptr, _rotationalVelocity);
|
||||
BulletSimAPI.SetAngularVelocity2(PhysBody.ptr, _rotationalVelocity);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -329,7 +330,7 @@ public sealed class BSPrim : BSPhysObject
|
|||
|
||||
if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0)
|
||||
{
|
||||
float waterHeight = PhysicsScene.GetWaterLevelAtXYZ(_position);
|
||||
float waterHeight = PhysicsScene.TerrainManager.GetWaterLevelAtXYZ(_position);
|
||||
// TODO: a floating motor so object will bob in the water
|
||||
if (Math.Abs(Position.Z - waterHeight) > 0.1f)
|
||||
{
|
||||
|
@ -347,7 +348,9 @@ public sealed class BSPrim : BSPhysObject
|
|||
if (ret)
|
||||
{
|
||||
// Apply upforce and overcome gravity.
|
||||
AddForce(upForce - PhysicsScene.DefaultGravity, false, inTaintTime);
|
||||
OMV.Vector3 correctionForce = upForce - PhysicsScene.DefaultGravity;
|
||||
DetailLog("{0},BSPrim.PositionSanityCheck,applyForce,pos={1},upForce={2},correctionForce={3}", LocalID, _position, upForce, correctionForce);
|
||||
AddForce(correctionForce, false, inTaintTime);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -643,9 +646,13 @@ public sealed class BSPrim : BSPhysObject
|
|||
BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, PhysBody.ptr);
|
||||
|
||||
// Collision filter can be set only when the object is in the world
|
||||
if (PhysBody.collisionFilter != 0 || PhysBody.collisionMask != 0)
|
||||
if (PhysBody.collisionGroup != 0 || PhysBody.collisionMask != 0)
|
||||
{
|
||||
BulletSimAPI.SetCollisionFilterMask2(PhysBody.ptr, (uint)PhysBody.collisionFilter, (uint)PhysBody.collisionMask);
|
||||
if (!BulletSimAPI.SetCollisionGroupMask2(PhysBody.ptr, (uint)PhysBody.collisionGroup, (uint)PhysBody.collisionMask))
|
||||
{
|
||||
PhysicsScene.Logger.ErrorFormat("{0} Failure setting prim collision mask. localID={1}, grp={2:X}, mask={3:X}",
|
||||
LogHeader, LocalID, PhysBody.collisionGroup, PhysBody.collisionMask);
|
||||
}
|
||||
}
|
||||
|
||||
// Recompute any linkset parameters.
|
||||
|
@ -684,11 +691,11 @@ public sealed class BSPrim : BSPhysObject
|
|||
// There can be special things needed for implementing linksets
|
||||
Linkset.MakeStatic(this);
|
||||
// The activation state is 'disabled' so Bullet will not try to act on it.
|
||||
BulletSimAPI.ForceActivationState2(PhysBody.ptr, ActivationState.DISABLE_SIMULATION);
|
||||
// BulletSimAPI.ForceActivationState2(PhysBody.ptr, ActivationState.DISABLE_SIMULATION);
|
||||
// Start it out sleeping and physical actions could wake it up.
|
||||
// BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ISLAND_SLEEPING);
|
||||
BulletSimAPI.ForceActivationState2(PhysBody.ptr, ActivationState.ISLAND_SLEEPING);
|
||||
|
||||
PhysBody.collisionFilter = CollisionFilterGroups.StaticObjectFilter;
|
||||
PhysBody.collisionGroup = CollisionFilterGroups.StaticObjectGroup;
|
||||
PhysBody.collisionMask = CollisionFilterGroups.StaticObjectMask;
|
||||
}
|
||||
else
|
||||
|
@ -734,7 +741,7 @@ public sealed class BSPrim : BSPhysObject
|
|||
BulletSimAPI.ForceActivationState2(PhysBody.ptr, ActivationState.ACTIVE_TAG);
|
||||
// BulletSimAPI.Activate2(BSBody.ptr, true);
|
||||
|
||||
PhysBody.collisionFilter = CollisionFilterGroups.ObjectFilter;
|
||||
PhysBody.collisionGroup = CollisionFilterGroups.ObjectGroup;
|
||||
PhysBody.collisionMask = CollisionFilterGroups.ObjectMask;
|
||||
}
|
||||
}
|
||||
|
@ -762,7 +769,7 @@ public sealed class BSPrim : BSPhysObject
|
|||
m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for non-solidness. id={1}, type={2}", LogHeader, LocalID, bodyType);
|
||||
}
|
||||
CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE);
|
||||
PhysBody.collisionFilter = CollisionFilterGroups.VolumeDetectFilter;
|
||||
PhysBody.collisionGroup = CollisionFilterGroups.VolumeDetectGroup;
|
||||
PhysBody.collisionMask = CollisionFilterGroups.VolumeDetectMask;
|
||||
}
|
||||
}
|
||||
|
@ -838,15 +845,6 @@ public sealed class BSPrim : BSPhysObject
|
|||
}
|
||||
public override OMV.Vector3 RotationalVelocity {
|
||||
get {
|
||||
/*
|
||||
OMV.Vector3 pv = OMV.Vector3.Zero;
|
||||
// if close to zero, report zero
|
||||
// This is copied from ODE but I'm not sure why it returns zero but doesn't
|
||||
// zero the property in the physics engine.
|
||||
if (_rotationalVelocity.ApproxEquals(pv, 0.2f))
|
||||
return pv;
|
||||
*/
|
||||
|
||||
return _rotationalVelocity;
|
||||
}
|
||||
set {
|
||||
|
@ -1012,6 +1010,9 @@ public sealed class BSPrim : BSPhysObject
|
|||
});
|
||||
}
|
||||
// A torque impulse.
|
||||
// ApplyTorqueImpulse adds torque directly to the angularVelocity.
|
||||
// AddAngularForce accumulates the force and applied it to the angular velocity all at once.
|
||||
// Computed as: angularVelocity += impulse * inertia;
|
||||
public void ApplyTorqueImpulse(OMV.Vector3 impulse, bool inTaintTime)
|
||||
{
|
||||
OMV.Vector3 applyImpulse = impulse;
|
||||
|
@ -1380,54 +1381,16 @@ public sealed class BSPrim : BSPhysObject
|
|||
|
||||
public override void UpdateProperties(EntityProperties entprop)
|
||||
{
|
||||
/*
|
||||
UpdatedProperties changed = 0;
|
||||
// assign to the local variables so the normal set action does not happen
|
||||
// if (_position != entprop.Position)
|
||||
if (!_position.ApproxEquals(entprop.Position, POSITION_TOLERANCE))
|
||||
{
|
||||
_position = entprop.Position;
|
||||
changed |= UpdatedProperties.Position;
|
||||
}
|
||||
// if (_orientation != entprop.Rotation)
|
||||
if (!_orientation.ApproxEquals(entprop.Rotation, ROTATION_TOLERANCE))
|
||||
{
|
||||
_orientation = entprop.Rotation;
|
||||
changed |= UpdatedProperties.Rotation;
|
||||
}
|
||||
// if (_velocity != entprop.Velocity)
|
||||
if (!_velocity.ApproxEquals(entprop.Velocity, VELOCITY_TOLERANCE))
|
||||
{
|
||||
_velocity = entprop.Velocity;
|
||||
changed |= UpdatedProperties.Velocity;
|
||||
}
|
||||
// if (_acceleration != entprop.Acceleration)
|
||||
if (!_acceleration.ApproxEquals(entprop.Acceleration, ACCELERATION_TOLERANCE))
|
||||
{
|
||||
_acceleration = entprop.Acceleration;
|
||||
changed |= UpdatedProperties.Acceleration;
|
||||
}
|
||||
// if (_rotationalVelocity != entprop.RotationalVelocity)
|
||||
if (!_rotationalVelocity.ApproxEquals(entprop.RotationalVelocity, ROTATIONAL_VELOCITY_TOLERANCE))
|
||||
{
|
||||
_rotationalVelocity = entprop.RotationalVelocity;
|
||||
changed |= UpdatedProperties.RotationalVel;
|
||||
}
|
||||
if (changed != 0)
|
||||
{
|
||||
// Only update the position of single objects and linkset roots
|
||||
if (Linkset.IsRoot(this))
|
||||
{
|
||||
base.RequestPhysicsterseUpdate();
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// Don't check for damping here -- it's done in BulletSim and SceneObjectPart.
|
||||
|
||||
// Updates only for individual prims and for the root object of a linkset.
|
||||
if (Linkset.IsRoot(this))
|
||||
{
|
||||
// A temporary kludge to suppress the rotational effects introduced on vehicles by Bullet
|
||||
// TODO: handle physics introduced by Bullet with computed vehicle physics.
|
||||
if (_vehicle.IsActive)
|
||||
{
|
||||
entprop.RotationalVelocity = OMV.Vector3.Zero;
|
||||
}
|
||||
|
||||
// Assign directly to the local variables so the normal set action does not happen
|
||||
_position = entprop.Position;
|
||||
_orientation = entprop.Rotation;
|
||||
|
@ -1436,7 +1399,7 @@ public sealed class BSPrim : BSPhysObject
|
|||
_rotationalVelocity = entprop.RotationalVelocity;
|
||||
|
||||
// The sanity check can change the velocity and/or position.
|
||||
if (PositionSanityCheck(true))
|
||||
if (IsPhysical && PositionSanityCheck(true))
|
||||
{
|
||||
entprop.Position = _position;
|
||||
entprop.Velocity = _velocity;
|
||||
|
@ -1446,12 +1409,10 @@ public sealed class BSPrim : BSPhysObject
|
|||
LastEntityProperties = CurrentEntityProperties;
|
||||
CurrentEntityProperties = entprop;
|
||||
|
||||
OMV.Vector3 direction = OMV.Vector3.UnitX * _orientation;
|
||||
OMV.Vector3 direction = OMV.Vector3.UnitX * _orientation; // DEBUG DEBUG DEBUG
|
||||
DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},dir={3},vel={4},rotVel={5}",
|
||||
LocalID, _position, _orientation, direction, _velocity, _rotationalVelocity);
|
||||
|
||||
// BulletSimAPI.DumpRigidBody2(PhysicsScene.World.ptr, BSBody.ptr); // DEBUG DEBUG DEBUG
|
||||
|
||||
base.RequestPhysicsterseUpdate();
|
||||
}
|
||||
/*
|
||||
|
|
|
@ -96,6 +96,9 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
|
|||
public long SimulationStep { get { return m_simulationStep; } }
|
||||
private int m_taintsToProcessPerStep;
|
||||
|
||||
public delegate void PreStepAction(float timeStep);
|
||||
public event PreStepAction BeforeStep;
|
||||
|
||||
// A value of the time now so all the collision and update routines do not have to get their own
|
||||
// Set to 'now' just before all the prims and actors are called for collisions and updates
|
||||
public int SimulationNowTime { get; private set; }
|
||||
|
@ -127,7 +130,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
|
|||
public const uint GROUNDPLANE_ID = 1;
|
||||
public const uint CHILDTERRAIN_ID = 2; // Terrain allocated based on our mega-prim childre start here
|
||||
|
||||
private float m_waterLevel;
|
||||
public float SimpleWaterLevel { get; set; }
|
||||
public BSTerrainManager TerrainManager { get; private set; }
|
||||
|
||||
public ConfigurationParameters Params
|
||||
|
@ -182,6 +185,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
|
|||
private string m_physicsLoggingDir;
|
||||
private string m_physicsLoggingPrefix;
|
||||
private int m_physicsLoggingFileMinutes;
|
||||
private bool m_physicsLoggingDoFlush;
|
||||
// 'true' of the vehicle code is to log lots of details
|
||||
public bool VehicleLoggingEnabled { get; private set; }
|
||||
|
||||
|
@ -290,6 +294,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
|
|||
m_physicsLoggingDir = pConfig.GetString("PhysicsLoggingDir", ".");
|
||||
m_physicsLoggingPrefix = pConfig.GetString("PhysicsLoggingPrefix", "physics-%REGIONNAME%-");
|
||||
m_physicsLoggingFileMinutes = pConfig.GetInt("PhysicsLoggingFileMinutes", 5);
|
||||
m_physicsLoggingDoFlush = pConfig.GetBoolean("PhysicsLoggingDoFlush", false);
|
||||
// Very detailed logging for vehicle debugging
|
||||
VehicleLoggingEnabled = pConfig.GetBoolean("VehicleLoggingEnabled", false);
|
||||
|
||||
|
@ -485,8 +490,10 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
|
|||
ProcessTaints();
|
||||
|
||||
// Some of the prims operate with special vehicle properties
|
||||
ProcessVehicles(timeStep);
|
||||
ProcessTaints(); // the vehicles might have added taints
|
||||
DoPreStepActions(timeStep);
|
||||
|
||||
// the prestep actions might have added taints
|
||||
ProcessTaints();
|
||||
|
||||
// step the physical world one interval
|
||||
m_simulationStep++;
|
||||
|
@ -515,9 +522,9 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
|
|||
collidersCount = 0;
|
||||
}
|
||||
|
||||
// Don't have to use the pointers passed back since we know it is the same pinned memory we passed in
|
||||
// Don't have to use the pointers passed back since we know it is the same pinned memory we passed in.
|
||||
|
||||
// Get a value for 'now' so all the collision and update routines don't have to get their own
|
||||
// Get a value for 'now' so all the collision and update routines don't have to get their own.
|
||||
SimulationNowTime = Util.EnvironmentTickCount();
|
||||
|
||||
// If there were collisions, process them by sending the event to the prim.
|
||||
|
@ -563,6 +570,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
|
|||
ObjectsWithCollisions.Remove(po);
|
||||
ObjectsWithNoMoreCollisions.Clear();
|
||||
}
|
||||
// Done with collisions.
|
||||
|
||||
// If any of the objects had updated properties, tell the object it has been changed by the physics engine
|
||||
if (updatedEntityCount > 0)
|
||||
|
@ -586,9 +594,8 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
|
|||
|
||||
// The physics engine returns the number of milliseconds it simulated this call.
|
||||
// These are summed and normalized to one second and divided by 1000 to give the reported physics FPS.
|
||||
// We multiply by 55 to give a recognizable running rate (55 or less).
|
||||
return numSubSteps * m_fixedTimeStep * 1000 * 55;
|
||||
// return timeStep * 1000 * 55;
|
||||
// Multiply by 55 to give a nominal frame rate of 55.
|
||||
return (float)numSubSteps * m_fixedTimeStep * 1000f * 55f;
|
||||
}
|
||||
|
||||
// Something has collided
|
||||
|
@ -634,12 +641,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
|
|||
|
||||
public override void SetWaterLevel(float baseheight)
|
||||
{
|
||||
m_waterLevel = baseheight;
|
||||
}
|
||||
// Someday....
|
||||
public float GetWaterLevelAtXYZ(Vector3 loc)
|
||||
{
|
||||
return m_waterLevel;
|
||||
SimpleWaterLevel = baseheight;
|
||||
}
|
||||
|
||||
public override void DeleteTerrain()
|
||||
|
@ -910,6 +912,16 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
|
|||
}
|
||||
}
|
||||
|
||||
private void DoPreStepActions(float timeStep)
|
||||
{
|
||||
ProcessVehicles(timeStep);
|
||||
|
||||
PreStepAction actions = BeforeStep;
|
||||
if (actions != null)
|
||||
actions(timeStep);
|
||||
|
||||
}
|
||||
|
||||
// Some prims have extra vehicle actions
|
||||
// Called at taint time!
|
||||
private void ProcessVehicles(float timeStep)
|
||||
|
@ -974,6 +986,8 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
|
|||
// Should handle fetching the right type from the ini file and converting it.
|
||||
// -- a delegate for getting the value as a float
|
||||
// -- a delegate for setting the value from a float
|
||||
// -- an optional delegate to update the value in the world. Most often used to
|
||||
// push the new value to an in-world object.
|
||||
//
|
||||
// The single letter parameters for the delegates are:
|
||||
// s = BSScene
|
||||
|
@ -1172,7 +1186,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
|
|||
(s) => { return s.m_params[0].avatarFriction; },
|
||||
(s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarFriction, p, l, v); } ),
|
||||
new ParameterDefn("AvatarStandingFriction", "Avatar friction when standing. Changed on avatar recreation.",
|
||||
0.99f,
|
||||
10.0f,
|
||||
(s,cf,p,v) => { s.m_params[0].avatarStandingFriction = cf.GetFloat(p, v); },
|
||||
(s) => { return s.m_params[0].avatarStandingFriction; },
|
||||
(s,p,l,v) => { s.m_params[0].avatarStandingFriction = v; } ),
|
||||
|
@ -1493,7 +1507,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
|
|||
{
|
||||
PhysicsLogging.Write(msg, args);
|
||||
// Add the Flush() if debugging crashes. Gets all the messages written out.
|
||||
// PhysicsLogging.Flush();
|
||||
if (m_physicsLoggingDoFlush) PhysicsLogging.Flush();
|
||||
}
|
||||
// Used to fill in the LocalID when there isn't one. It's the correct number of characters.
|
||||
public const string DetailLogZero = "0000000000";
|
||||
|
|
|
@ -65,9 +65,16 @@ public sealed class BSShapeCollection : IDisposable
|
|||
private Dictionary<System.UInt64, MeshDesc> Meshes = new Dictionary<System.UInt64, MeshDesc>();
|
||||
private Dictionary<System.UInt64, HullDesc> Hulls = new Dictionary<System.UInt64, HullDesc>();
|
||||
|
||||
private bool DDetail = false;
|
||||
|
||||
public BSShapeCollection(BSScene physScene)
|
||||
{
|
||||
PhysicsScene = physScene;
|
||||
// Set the next to 'true' for very detailed shape update detailed logging (detailed details?)
|
||||
// While detailed debugging is still active, this is better than commenting out all the
|
||||
// DetailLog statements. When debugging slows down, this and the protected logging
|
||||
// statements can be commented/removed.
|
||||
DDetail = true;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
|
@ -126,13 +133,13 @@ public sealed class BSShapeCollection : IDisposable
|
|||
{
|
||||
lock (m_collectionActivityLock)
|
||||
{
|
||||
DetailLog("{0},BSShapeCollection.ReferenceBody,newBody,body={1}", body.ID, body);
|
||||
if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceBody,newBody,body={1}", body.ID, body);
|
||||
PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.ReferenceBody", delegate()
|
||||
{
|
||||
if (!BulletSimAPI.IsInWorld2(body.ptr))
|
||||
{
|
||||
BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, body.ptr);
|
||||
DetailLog("{0},BSShapeCollection.ReferenceBody,addedToWorld,ref={1}", body.ID, body);
|
||||
if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceBody,addedToWorld,ref={1}", body.ID, body);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -149,7 +156,7 @@ public sealed class BSShapeCollection : IDisposable
|
|||
{
|
||||
PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.DereferenceBody", delegate()
|
||||
{
|
||||
DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody,body={1},inTaintTime={2}",
|
||||
if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody,body={1},inTaintTime={2}",
|
||||
body.ID, body, inTaintTime);
|
||||
// If the caller needs to know the old body is going away, pass the event up.
|
||||
if (bodyCallback != null) bodyCallback(body);
|
||||
|
@ -157,7 +164,7 @@ public sealed class BSShapeCollection : IDisposable
|
|||
if (BulletSimAPI.IsInWorld2(body.ptr))
|
||||
{
|
||||
BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, body.ptr);
|
||||
DetailLog("{0},BSShapeCollection.DereferenceBody,removingFromWorld. Body={1}", body.ID, body);
|
||||
if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceBody,removingFromWorld. Body={1}", body.ID, body);
|
||||
}
|
||||
|
||||
// Zero any reference to the shape so it is not freed when the body is deleted.
|
||||
|
@ -184,7 +191,7 @@ public sealed class BSShapeCollection : IDisposable
|
|||
{
|
||||
// There is an existing instance of this mesh.
|
||||
meshDesc.referenceCount++;
|
||||
DetailLog("{0},BSShapeCollection.ReferenceShape,existingMesh,key={1},cnt={2}",
|
||||
if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceShape,existingMesh,key={1},cnt={2}",
|
||||
BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount);
|
||||
}
|
||||
else
|
||||
|
@ -194,7 +201,7 @@ public sealed class BSShapeCollection : IDisposable
|
|||
meshDesc.shapeKey = shape.shapeKey;
|
||||
// We keep a reference to the underlying IMesh data so a hull can be built
|
||||
meshDesc.referenceCount = 1;
|
||||
DetailLog("{0},BSShapeCollection.ReferenceShape,newMesh,key={1},cnt={2}",
|
||||
if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceShape,newMesh,key={1},cnt={2}",
|
||||
BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount);
|
||||
ret = true;
|
||||
}
|
||||
|
@ -207,7 +214,7 @@ public sealed class BSShapeCollection : IDisposable
|
|||
{
|
||||
// There is an existing instance of this hull.
|
||||
hullDesc.referenceCount++;
|
||||
DetailLog("{0},BSShapeCollection.ReferenceShape,existingHull,key={1},cnt={2}",
|
||||
if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceShape,existingHull,key={1},cnt={2}",
|
||||
BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount);
|
||||
}
|
||||
else
|
||||
|
@ -216,7 +223,7 @@ public sealed class BSShapeCollection : IDisposable
|
|||
hullDesc.ptr = shape.ptr;
|
||||
hullDesc.shapeKey = shape.shapeKey;
|
||||
hullDesc.referenceCount = 1;
|
||||
DetailLog("{0},BSShapeCollection.ReferenceShape,newHull,key={1},cnt={2}",
|
||||
if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceShape,newHull,key={1},cnt={2}",
|
||||
BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount);
|
||||
ret = true;
|
||||
|
||||
|
@ -246,7 +253,7 @@ public sealed class BSShapeCollection : IDisposable
|
|||
if (shape.isNativeShape)
|
||||
{
|
||||
// Native shapes are not tracked and are released immediately
|
||||
DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,ptr={1},taintTime={2}",
|
||||
if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,ptr={1},taintTime={2}",
|
||||
BSScene.DetailLogZero, shape.ptr.ToString("X"), inTaintTime);
|
||||
if (shapeCallback != null) shapeCallback(shape);
|
||||
BulletSimAPI.DeleteCollisionShape2(PhysicsScene.World.ptr, shape.ptr);
|
||||
|
@ -286,7 +293,7 @@ public sealed class BSShapeCollection : IDisposable
|
|||
if (shapeCallback != null) shapeCallback(shape);
|
||||
meshDesc.lastReferenced = System.DateTime.Now;
|
||||
Meshes[shape.shapeKey] = meshDesc;
|
||||
DetailLog("{0},BSShapeCollection.DereferenceMesh,shape={1},refCnt={2}",
|
||||
if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceMesh,shape={1},refCnt={2}",
|
||||
BSScene.DetailLogZero, shape, meshDesc.referenceCount);
|
||||
|
||||
}
|
||||
|
@ -307,7 +314,7 @@ public sealed class BSShapeCollection : IDisposable
|
|||
|
||||
hullDesc.lastReferenced = System.DateTime.Now;
|
||||
Hulls[shape.shapeKey] = hullDesc;
|
||||
DetailLog("{0},BSShapeCollection.DereferenceHull,shape={1},refCnt={2}",
|
||||
if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceHull,shape={1},refCnt={2}",
|
||||
BSScene.DetailLogZero, shape, hullDesc.referenceCount);
|
||||
}
|
||||
}
|
||||
|
@ -325,13 +332,13 @@ public sealed class BSShapeCollection : IDisposable
|
|||
// Failed the sanity check!!
|
||||
PhysicsScene.Logger.ErrorFormat("{0} Attempt to free a compound shape that is not compound!! type={1}, ptr={2}",
|
||||
LogHeader, shape.type, shape.ptr.ToString("X"));
|
||||
DetailLog("{0},BSShapeCollection.DereferenceCompound,notACompoundShape,type={1},ptr={2}",
|
||||
if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceCompound,notACompoundShape,type={1},ptr={2}",
|
||||
BSScene.DetailLogZero, shape.type, shape.ptr.ToString("X"));
|
||||
return;
|
||||
}
|
||||
|
||||
int numChildren = BulletSimAPI.GetNumberOfCompoundChildren2(shape.ptr);
|
||||
DetailLog("{0},BSShapeCollection.DereferenceCompound,shape={1},children={2}", BSScene.DetailLogZero, shape, numChildren);
|
||||
if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceCompound,shape={1},children={2}", BSScene.DetailLogZero, shape, numChildren);
|
||||
|
||||
for (int ii = numChildren - 1; ii >= 0; ii--)
|
||||
{
|
||||
|
@ -379,7 +386,7 @@ public sealed class BSShapeCollection : IDisposable
|
|||
}
|
||||
}
|
||||
|
||||
DetailLog("{0},BSShapeCollection.DereferenceAnonCollisionShape,shape={1}", BSScene.DetailLogZero, shapeInfo);
|
||||
if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceAnonCollisionShape,shape={1}", BSScene.DetailLogZero, shapeInfo);
|
||||
|
||||
if (shapeInfo.type != BSPhysicsShapeType.SHAPE_UNKNOWN)
|
||||
{
|
||||
|
@ -410,7 +417,7 @@ public sealed class BSShapeCollection : IDisposable
|
|||
// an avatar capsule is close to a native shape (it is not shared)
|
||||
ret = GetReferenceToNativeShape(prim, BSPhysicsShapeType.SHAPE_CAPSULE,
|
||||
FixedShapeKey.KEY_CAPSULE, shapeCallback);
|
||||
DetailLog("{0},BSShapeCollection.CreateGeom,avatarCapsule,shape={1}", prim.LocalID, prim.PhysShape);
|
||||
if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,avatarCapsule,shape={1}", prim.LocalID, prim.PhysShape);
|
||||
ret = true;
|
||||
haveShape = true;
|
||||
}
|
||||
|
@ -420,7 +427,7 @@ public sealed class BSShapeCollection : IDisposable
|
|||
if (!haveShape && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_COMPOUND)
|
||||
{
|
||||
ret = GetReferenceToCompoundShape(prim, shapeCallback);
|
||||
DetailLog("{0},BSShapeCollection.CreateGeom,compoundShape,shape={1}", prim.LocalID, prim.PhysShape);
|
||||
if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,compoundShape,shape={1}", prim.LocalID, prim.PhysShape);
|
||||
haveShape = true;
|
||||
}
|
||||
|
||||
|
@ -465,7 +472,7 @@ public sealed class BSShapeCollection : IDisposable
|
|||
{
|
||||
ret = GetReferenceToNativeShape(prim, BSPhysicsShapeType.SHAPE_SPHERE,
|
||||
FixedShapeKey.KEY_SPHERE, shapeCallback);
|
||||
DetailLog("{0},BSShapeCollection.CreateGeom,sphere,force={1},shape={2}",
|
||||
if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,sphere,force={1},shape={2}",
|
||||
prim.LocalID, forceRebuild, prim.PhysShape);
|
||||
}
|
||||
}
|
||||
|
@ -479,7 +486,7 @@ public sealed class BSShapeCollection : IDisposable
|
|||
{
|
||||
ret = GetReferenceToNativeShape( prim, BSPhysicsShapeType.SHAPE_BOX,
|
||||
FixedShapeKey.KEY_BOX, shapeCallback);
|
||||
DetailLog("{0},BSShapeCollection.CreateGeom,box,force={1},shape={2}",
|
||||
if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,box,force={1},shape={2}",
|
||||
prim.LocalID, forceRebuild, prim.PhysShape);
|
||||
}
|
||||
}
|
||||
|
@ -504,13 +511,13 @@ public sealed class BSShapeCollection : IDisposable
|
|||
{
|
||||
// Update prim.BSShape to reference a hull of this shape.
|
||||
ret = GetReferenceToHull(prim,shapeCallback);
|
||||
DetailLog("{0},BSShapeCollection.CreateGeom,hull,shape={1},key={2}",
|
||||
if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,hull,shape={1},key={2}",
|
||||
prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X"));
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = GetReferenceToMesh(prim, shapeCallback);
|
||||
DetailLog("{0},BSShapeCollection.CreateGeom,mesh,shape={1},key={2}",
|
||||
if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,mesh,shape={1},key={2}",
|
||||
prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X"));
|
||||
}
|
||||
return ret;
|
||||
|
@ -528,7 +535,7 @@ public sealed class BSShapeCollection : IDisposable
|
|||
BulletShape newShape = BuildPhysicalNativeShape(prim, shapeType, shapeKey);
|
||||
|
||||
// Don't need to do a 'ReferenceShape()' here because native shapes are not shared.
|
||||
DetailLog("{0},BSShapeCollection.AddNativeShapeToPrim,create,newshape={1},scale={2}",
|
||||
if (DDetail) DetailLog("{0},BSShapeCollection.AddNativeShapeToPrim,create,newshape={1},scale={2}",
|
||||
prim.LocalID, newShape, prim.Scale);
|
||||
|
||||
prim.PhysShape = newShape;
|
||||
|
@ -554,7 +561,7 @@ public sealed class BSShapeCollection : IDisposable
|
|||
newShape = new BulletShape(
|
||||
BulletSimAPI.BuildCapsuleShape2(PhysicsScene.World.ptr, 1f, 1f, prim.Scale)
|
||||
, shapeType);
|
||||
DetailLog("{0},BSShapeCollection.BuiletPhysicalNativeShape,capsule,scale={1}", prim.LocalID, prim.Scale);
|
||||
if (DDetail) DetailLog("{0},BSShapeCollection.BuiletPhysicalNativeShape,capsule,scale={1}", prim.LocalID, prim.Scale);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -589,7 +596,7 @@ public sealed class BSShapeCollection : IDisposable
|
|||
if (newMeshKey == prim.PhysShape.shapeKey && prim.PhysShape.type == BSPhysicsShapeType.SHAPE_MESH)
|
||||
return false;
|
||||
|
||||
DetailLog("{0},BSShapeCollection.GetReferenceToMesh,create,oldKey={1},newKey={2}",
|
||||
if (DDetail) DetailLog("{0},BSShapeCollection.GetReferenceToMesh,create,oldKey={1},newKey={2}",
|
||||
prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newMeshKey.ToString("X"));
|
||||
|
||||
// Since we're recreating new, get rid of the reference to the previous shape
|
||||
|
@ -620,8 +627,7 @@ public sealed class BSShapeCollection : IDisposable
|
|||
}
|
||||
else
|
||||
{
|
||||
// Pass false for physicalness as this creates some sort of bounding box which we don't need
|
||||
meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, false);
|
||||
meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, true, false);
|
||||
|
||||
if (meshData != null)
|
||||
{
|
||||
|
@ -663,7 +669,7 @@ public sealed class BSShapeCollection : IDisposable
|
|||
if (newHullKey == prim.PhysShape.shapeKey && prim.PhysShape.type == BSPhysicsShapeType.SHAPE_HULL)
|
||||
return false;
|
||||
|
||||
DetailLog("{0},BSShapeCollection.GetReferenceToHull,create,oldKey={1},newKey={2}",
|
||||
if (DDetail) DetailLog("{0},BSShapeCollection.GetReferenceToHull,create,oldKey={1},newKey={2}",
|
||||
prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newHullKey.ToString("X"));
|
||||
|
||||
// Remove usage of the previous shape.
|
||||
|
@ -694,8 +700,8 @@ public sealed class BSShapeCollection : IDisposable
|
|||
else
|
||||
{
|
||||
// Build a new hull in the physical world
|
||||
// Pass false for physicalness as this creates some sort of bounding box which we don't need
|
||||
IMesh meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, false);
|
||||
// Pass true for physicalness as this creates some sort of bounding box which we don't need
|
||||
IMesh meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, true, false);
|
||||
if (meshData != null)
|
||||
{
|
||||
|
||||
|
@ -809,7 +815,7 @@ public sealed class BSShapeCollection : IDisposable
|
|||
// Create the shape for the root prim and add it to the compound shape. Cannot be a native shape.
|
||||
CreateGeomMeshOrHull(prim, shapeCallback);
|
||||
BulletSimAPI.AddChildShapeToCompoundShape2(cShape.ptr, prim.PhysShape.ptr, OMV.Vector3.Zero, OMV.Quaternion.Identity);
|
||||
DetailLog("{0},BSShapeCollection.GetReferenceToCompoundShape,addRootPrim,compShape={1},rootShape={2}",
|
||||
if (DDetail) DetailLog("{0},BSShapeCollection.GetReferenceToCompoundShape,addRootPrim,compShape={1},rootShape={2}",
|
||||
prim.LocalID, cShape, prim.PhysShape);
|
||||
|
||||
prim.PhysShape = cShape;
|
||||
|
@ -936,13 +942,13 @@ public sealed class BSShapeCollection : IDisposable
|
|||
{
|
||||
bodyPtr = BulletSimAPI.CreateBodyFromShape2(sim.ptr, shape.ptr,
|
||||
prim.LocalID, prim.RawPosition, prim.RawOrientation);
|
||||
DetailLog("{0},BSShapeCollection.CreateBody,mesh,ptr={1}", prim.LocalID, bodyPtr.ToString("X"));
|
||||
if (DDetail) DetailLog("{0},BSShapeCollection.CreateBody,mesh,ptr={1}", prim.LocalID, bodyPtr.ToString("X"));
|
||||
}
|
||||
else
|
||||
{
|
||||
bodyPtr = BulletSimAPI.CreateGhostFromShape2(sim.ptr, shape.ptr,
|
||||
prim.LocalID, prim.RawPosition, prim.RawOrientation);
|
||||
DetailLog("{0},BSShapeCollection.CreateBody,ghost,ptr={1}", prim.LocalID, bodyPtr.ToString("X"));
|
||||
if (DDetail) DetailLog("{0},BSShapeCollection.CreateBody,ghost,ptr={1}", prim.LocalID, bodyPtr.ToString("X"));
|
||||
}
|
||||
aBody = new BulletBody(prim.LocalID, bodyPtr);
|
||||
|
||||
|
|
|
@ -121,8 +121,8 @@ public sealed class BSTerrainHeightmap : BSTerrainPhys
|
|||
// redo its bounding box now that it is in the world
|
||||
BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, m_mapInfo.terrainBody.ptr);
|
||||
|
||||
BulletSimAPI.SetCollisionFilterMask2(m_mapInfo.terrainBody.ptr,
|
||||
(uint)CollisionFilterGroups.TerrainFilter,
|
||||
BulletSimAPI.SetCollisionGroupMask2(m_mapInfo.terrainBody.ptr,
|
||||
(uint)CollisionFilterGroups.TerrainGroup,
|
||||
(uint)CollisionFilterGroups.TerrainMask);
|
||||
|
||||
// Make it so the terrain will not move or be considered for movement.
|
||||
|
@ -148,7 +148,7 @@ public sealed class BSTerrainHeightmap : BSTerrainPhys
|
|||
}
|
||||
|
||||
// The passed position is relative to the base of the region.
|
||||
public override float GetHeightAtXYZ(Vector3 pos)
|
||||
public override float GetTerrainHeightAtXYZ(Vector3 pos)
|
||||
{
|
||||
float ret = BSTerrainManager.HEIGHT_GETHEIGHT_RET;
|
||||
|
||||
|
@ -166,5 +166,11 @@ public sealed class BSTerrainHeightmap : BSTerrainPhys
|
|||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// The passed position is relative to the base of the region.
|
||||
public override float GetWaterLevelAtXYZ(Vector3 pos)
|
||||
{
|
||||
return PhysicsScene.SimpleWaterLevel;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,7 +62,8 @@ public abstract class BSTerrainPhys : IDisposable
|
|||
ID = id;
|
||||
}
|
||||
public abstract void Dispose();
|
||||
public abstract float GetHeightAtXYZ(Vector3 pos);
|
||||
public abstract float GetTerrainHeightAtXYZ(Vector3 pos);
|
||||
public abstract float GetWaterLevelAtXYZ(Vector3 pos);
|
||||
}
|
||||
|
||||
// ==========================================================================================
|
||||
|
@ -75,6 +76,7 @@ public sealed class BSTerrainManager
|
|||
public const float HEIGHT_INITIALIZATION = 24.987f;
|
||||
public const float HEIGHT_INITIAL_LASTHEIGHT = 24.876f;
|
||||
public const float HEIGHT_GETHEIGHT_RET = 24.765f;
|
||||
public const float WATER_HEIGHT_GETHEIGHT_RET = 19.998f;
|
||||
|
||||
// If the min and max height are equal, we reduce the min by this
|
||||
// amount to make sure that a bounding box is built for the terrain.
|
||||
|
@ -138,8 +140,8 @@ public sealed class BSTerrainManager
|
|||
// Ground plane does not move
|
||||
BulletSimAPI.ForceActivationState2(m_groundPlane.ptr, ActivationState.DISABLE_SIMULATION);
|
||||
// Everything collides with the ground plane.
|
||||
BulletSimAPI.SetCollisionFilterMask2(m_groundPlane.ptr,
|
||||
(uint)CollisionFilterGroups.GroundPlaneFilter, (uint)CollisionFilterGroups.GroundPlaneMask);
|
||||
BulletSimAPI.SetCollisionGroupMask2(m_groundPlane.ptr,
|
||||
(uint)CollisionFilterGroups.GroundPlaneGroup, (uint)CollisionFilterGroups.GroundPlaneMask);
|
||||
|
||||
// Build an initial terrain and put it in the world. This quickly gets replaced by the real region terrain.
|
||||
BSTerrainPhys initialTerrain = new BSTerrainHeightmap(PhysicsScene, Vector3.Zero, BSScene.TERRAIN_ID, DefaultRegionSize);
|
||||
|
@ -358,7 +360,7 @@ public sealed class BSTerrainManager
|
|||
BSTerrainPhys physTerrain;
|
||||
if (m_terrains.TryGetValue(terrainBaseXYZ, out physTerrain))
|
||||
{
|
||||
ret = physTerrain.GetHeightAtXYZ(loc - terrainBaseXYZ);
|
||||
ret = physTerrain.GetTerrainHeightAtXYZ(loc - terrainBaseXYZ);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -370,6 +372,33 @@ public sealed class BSTerrainManager
|
|||
return ret;
|
||||
}
|
||||
|
||||
public float GetWaterLevelAtXYZ(Vector3 pos)
|
||||
{
|
||||
float ret = WATER_HEIGHT_GETHEIGHT_RET;
|
||||
|
||||
float tX = pos.X;
|
||||
float tY = pos.Y;
|
||||
|
||||
Vector3 terrainBaseXYZ = Vector3.Zero;
|
||||
terrainBaseXYZ.X = ((int)(tX / (int)DefaultRegionSize.X)) * (int)DefaultRegionSize.X;
|
||||
terrainBaseXYZ.Y = ((int)(tY / (int)DefaultRegionSize.Y)) * (int)DefaultRegionSize.Y;
|
||||
|
||||
lock (m_terrains)
|
||||
{
|
||||
BSTerrainPhys physTerrain;
|
||||
if (m_terrains.TryGetValue(terrainBaseXYZ, out physTerrain))
|
||||
{
|
||||
ret = physTerrain.GetWaterLevelAtXYZ(pos);
|
||||
}
|
||||
else
|
||||
{
|
||||
PhysicsScene.Logger.ErrorFormat("{0} GetWaterHeightAtXY: terrain not found: region={1}, x={2}, y={3}",
|
||||
LogHeader, PhysicsScene.RegionName, tX, tY);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Although no one seems to check this, I do support combining.
|
||||
public bool SupportsCombining()
|
||||
{
|
||||
|
|
|
@ -88,6 +88,8 @@ public sealed class BSTerrainMesh : BSTerrainPhys
|
|||
// Something is very messed up and a crash is in our future.
|
||||
return;
|
||||
}
|
||||
PhysicsScene.DetailLog("{0},BSTerrainMesh.create,meshed,indices={1},indSz={2},vertices={3},vertSz={4}",
|
||||
ID, indicesCount, indices.Length, verticesCount, vertices.Length);
|
||||
|
||||
m_terrainShape = new BulletShape(BulletSimAPI.CreateMeshShape2(PhysicsScene.World.ptr,
|
||||
indicesCount, indices, verticesCount, vertices),
|
||||
|
@ -122,14 +124,14 @@ public sealed class BSTerrainMesh : BSTerrainPhys
|
|||
// Static objects are not very massive.
|
||||
BulletSimAPI.SetMassProps2(m_terrainBody.ptr, 0f, Vector3.Zero);
|
||||
|
||||
// Return the new terrain to the world of physical objects
|
||||
// Put the new terrain to the world of physical objects
|
||||
BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, m_terrainBody.ptr);
|
||||
|
||||
// redo its bounding box now that it is in the world
|
||||
// Redo its bounding box now that it is in the world
|
||||
BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, m_terrainBody.ptr);
|
||||
|
||||
BulletSimAPI.SetCollisionFilterMask2(m_terrainBody.ptr,
|
||||
(uint)CollisionFilterGroups.TerrainFilter,
|
||||
BulletSimAPI.SetCollisionGroupMask2(m_terrainBody.ptr,
|
||||
(uint)CollisionFilterGroups.TerrainGroup,
|
||||
(uint)CollisionFilterGroups.TerrainMask);
|
||||
|
||||
// Make it so the terrain will not move or be considered for movement.
|
||||
|
@ -146,7 +148,7 @@ public sealed class BSTerrainMesh : BSTerrainPhys
|
|||
}
|
||||
}
|
||||
|
||||
public override float GetHeightAtXYZ(Vector3 pos)
|
||||
public override float GetTerrainHeightAtXYZ(Vector3 pos)
|
||||
{
|
||||
// For the moment use the saved heightmap to get the terrain height.
|
||||
// TODO: raycast downward to find the true terrain below the position.
|
||||
|
@ -167,6 +169,12 @@ public sealed class BSTerrainMesh : BSTerrainPhys
|
|||
return ret;
|
||||
}
|
||||
|
||||
// The passed position is relative to the base of the region.
|
||||
public override float GetWaterLevelAtXYZ(Vector3 pos)
|
||||
{
|
||||
return PhysicsScene.SimpleWaterLevel;
|
||||
}
|
||||
|
||||
// Convert the passed heightmap to mesh information suitable for CreateMeshShape2().
|
||||
// Return 'true' if successfully created.
|
||||
public static bool ConvertHeightmapToMesh(
|
||||
|
@ -188,6 +196,11 @@ public sealed class BSTerrainMesh : BSTerrainPhys
|
|||
// Simple mesh creation which assumes magnification == 1.
|
||||
// TODO: do a more general solution that scales, adds new vertices and smoothes the result.
|
||||
|
||||
// Create an array of vertices that is sizeX+1 by sizeY+1 (note the loop
|
||||
// from zero to <= sizeX). The triangle indices are then generated as two triangles
|
||||
// per heightmap point. There are sizeX by sizeY of these squares. The extra row and
|
||||
// column of vertices are used to complete the triangles of the last row and column
|
||||
// of the heightmap.
|
||||
try
|
||||
{
|
||||
// One vertice per heightmap value plus the vertices off the top and bottom edge.
|
||||
|
@ -200,16 +213,18 @@ public sealed class BSTerrainMesh : BSTerrainPhys
|
|||
float magY = (float)sizeY / extentY;
|
||||
physicsScene.DetailLog("{0},BSTerrainMesh.ConvertHeightMapToMesh,totVert={1},totInd={2},extentBase={3},magX={4},magY={5}",
|
||||
BSScene.DetailLogZero, totalVertices, totalIndices, extentBase, magX, magY);
|
||||
float minHeight = float.MaxValue;
|
||||
// Note that sizeX+1 vertices are created since there is land between this and the next region.
|
||||
for (int yy = 0; yy <= sizeY; yy++)
|
||||
{
|
||||
for (int xx = 0; xx <= sizeX; xx++) // Hint: the "<=" means we got through sizeX + 1 times
|
||||
for (int xx = 0; xx <= sizeX; xx++) // Hint: the "<=" means we go around sizeX + 1 times
|
||||
{
|
||||
int offset = yy * sizeX + xx;
|
||||
// Extend the height from the height from the last row or column
|
||||
// Extend the height with the height from the last row or column
|
||||
if (yy == sizeY) offset -= sizeX;
|
||||
if (xx == sizeX) offset -= 1;
|
||||
float height = heightMap[offset];
|
||||
minHeight = Math.Min(minHeight, height);
|
||||
vertices[verticesCount + 0] = (float)xx * magX + extentBase.X;
|
||||
vertices[verticesCount + 1] = (float)yy * magY + extentBase.Y;
|
||||
vertices[verticesCount + 2] = height + extentBase.Z;
|
||||
|
@ -222,7 +237,7 @@ public sealed class BSTerrainMesh : BSTerrainPhys
|
|||
{
|
||||
for (int xx = 0; xx < sizeX; xx++)
|
||||
{
|
||||
int offset = yy * sizeX + xx;
|
||||
int offset = yy * (sizeX + 1) + xx;
|
||||
// Each vertices is presumed to be the upper left corner of a box of two triangles
|
||||
indices[indicesCount + 0] = offset;
|
||||
indices[indicesCount + 1] = offset + 1;
|
||||
|
@ -233,6 +248,7 @@ public sealed class BSTerrainMesh : BSTerrainPhys
|
|||
indicesCount += 6;
|
||||
}
|
||||
}
|
||||
|
||||
ret = true;
|
||||
}
|
||||
catch (Exception e)
|
||||
|
|
|
@ -57,12 +57,12 @@ public struct BulletBody
|
|||
{
|
||||
ID = id;
|
||||
ptr = xx;
|
||||
collisionFilter = 0;
|
||||
collisionGroup = 0;
|
||||
collisionMask = 0;
|
||||
}
|
||||
public IntPtr ptr;
|
||||
public uint ID;
|
||||
public CollisionFilterGroups collisionFilter;
|
||||
public CollisionFilterGroups collisionGroup;
|
||||
public CollisionFilterGroups collisionMask;
|
||||
public override string ToString()
|
||||
{
|
||||
|
@ -71,10 +71,10 @@ public struct BulletBody
|
|||
buff.Append(ID.ToString());
|
||||
buff.Append(",p=");
|
||||
buff.Append(ptr.ToString("X"));
|
||||
if (collisionFilter != 0 || collisionMask != 0)
|
||||
if (collisionGroup != 0 || collisionMask != 0)
|
||||
{
|
||||
buff.Append(",f=");
|
||||
buff.Append(collisionFilter.ToString("X"));
|
||||
buff.Append(",g=");
|
||||
buff.Append(collisionGroup.ToString("X"));
|
||||
buff.Append(",m=");
|
||||
buff.Append(collisionMask.ToString("X"));
|
||||
}
|
||||
|
@ -357,9 +357,10 @@ public enum CollisionFlags : uint
|
|||
CF_CHARACTER_OBJECT = 1 << 4,
|
||||
CF_DISABLE_VISUALIZE_OBJECT = 1 << 5,
|
||||
CF_DISABLE_SPU_COLLISION_PROCESS = 1 << 6,
|
||||
// Following used by BulletSim to control collisions
|
||||
// Following used by BulletSim to control collisions and updates
|
||||
BS_SUBSCRIBE_COLLISION_EVENTS = 1 << 10,
|
||||
BS_FLOATS_ON_WATER = 1 << 11,
|
||||
BS_VEHICLE_COLLISIONS = 1 << 12,
|
||||
BS_NONE = 0,
|
||||
BS_ALL = 0xFFFFFFFF,
|
||||
|
||||
|
@ -376,36 +377,36 @@ public enum CollisionFilterGroups : uint
|
|||
// Don't use the bit definitions!! Define the use in a
|
||||
// filter/mask definition below. This way collision interactions
|
||||
// are more easily debugged.
|
||||
BNoneFilter = 0,
|
||||
BDefaultFilter = 1 << 0,
|
||||
BStaticFilter = 1 << 1,
|
||||
BKinematicFilter = 1 << 2,
|
||||
BDebrisFilter = 1 << 3,
|
||||
BNoneGroup = 0,
|
||||
BDefaultGroup = 1 << 0,
|
||||
BStaticGroup = 1 << 1,
|
||||
BKinematicGroup = 1 << 2,
|
||||
BDebrisGroup = 1 << 3,
|
||||
BSensorTrigger = 1 << 4,
|
||||
BCharacterFilter = 1 << 5,
|
||||
BAllFilter = 0xFFFFFFFF,
|
||||
BCharacterGroup = 1 << 5,
|
||||
BAllGroup = 0xFFFFFFFF,
|
||||
// Filter groups defined by BulletSim
|
||||
BGroundPlaneFilter = 1 << 10,
|
||||
BTerrainFilter = 1 << 11,
|
||||
BRaycastFilter = 1 << 12,
|
||||
BSolidFilter = 1 << 13,
|
||||
BLinksetFilter = 1 << 14,
|
||||
BGroundPlaneGroup = 1 << 10,
|
||||
BTerrainGroup = 1 << 11,
|
||||
BRaycastGroup = 1 << 12,
|
||||
BSolidGroup = 1 << 13,
|
||||
BLinksetGroup = 1 << 14,
|
||||
|
||||
// The collsion filters and masked are defined in one place -- don't want them scattered
|
||||
AvatarFilter = BCharacterFilter,
|
||||
AvatarMask = BAllFilter,
|
||||
ObjectFilter = BSolidFilter,
|
||||
ObjectMask = BAllFilter,
|
||||
StaticObjectFilter = BStaticFilter,
|
||||
StaticObjectMask = BAllFilter & ~BStaticFilter, // static objects don't collide with each other
|
||||
LinksetFilter = BLinksetFilter,
|
||||
LinksetMask = BAllFilter & ~BLinksetFilter, // linkset objects don't collide with each other
|
||||
VolumeDetectFilter = BSensorTrigger,
|
||||
AvatarGroup = BCharacterGroup,
|
||||
AvatarMask = BAllGroup,
|
||||
ObjectGroup = BSolidGroup,
|
||||
ObjectMask = BAllGroup,
|
||||
StaticObjectGroup = BStaticGroup,
|
||||
StaticObjectMask = AvatarGroup | ObjectGroup, // static things don't interact with much
|
||||
LinksetGroup = BLinksetGroup,
|
||||
LinksetMask = BAllGroup & ~BLinksetGroup, // linkset objects don't collide with each other
|
||||
VolumeDetectGroup = BSensorTrigger,
|
||||
VolumeDetectMask = ~BSensorTrigger,
|
||||
TerrainFilter = BTerrainFilter,
|
||||
TerrainMask = BAllFilter & ~BStaticFilter, // static objects on the ground don't collide
|
||||
GroundPlaneFilter = BGroundPlaneFilter,
|
||||
GroundPlaneMask = BAllFilter
|
||||
TerrainGroup = BTerrainGroup,
|
||||
TerrainMask = BAllGroup & ~BStaticGroup, // static objects on the ground don't collide
|
||||
GroundPlaneGroup = BGroundPlaneGroup,
|
||||
GroundPlaneMask = BAllGroup
|
||||
|
||||
};
|
||||
|
||||
|
@ -945,7 +946,7 @@ public static extern IntPtr GetConstraintRef2(IntPtr obj, int index);
|
|||
public static extern int GetNumConstraintRefs2(IntPtr obj);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void SetCollisionFilterMask2(IntPtr body, uint filter, uint mask);
|
||||
public static extern bool SetCollisionGroupMask2(IntPtr body, uint filter, uint mask);
|
||||
|
||||
// =====================================================================================
|
||||
// btCollisionShape entries
|
||||
|
@ -1006,14 +1007,17 @@ public static extern void DumpRigidBody2(IntPtr sim, IntPtr collisionObject);
|
|||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void DumpCollisionShape2(IntPtr sim, IntPtr collisionShape);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void DumpMapInfo2(IntPtr sim, IntPtr manInfo);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void DumpConstraint2(IntPtr sim, IntPtr constrain);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void DumpAllInfo2(IntPtr sim);
|
||||
public static extern void DumpActivationInfo2(IntPtr sim);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void DumpMapInfo2(IntPtr sim, IntPtr manInfo);
|
||||
public static extern void DumpAllInfo2(IntPtr sim);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void DumpPhysicsStatistics2(IntPtr sim);
|
||||
|
|
|
@ -0,0 +1,142 @@
|
|||
CRASHES
|
||||
=================================================
|
||||
20121129.1411: editting/moving phys object across region boundries causes crash
|
||||
getPos-> btRigidBody::upcast -> getBodyType -> BOOM
|
||||
20121128.1600: mesh object not rezzing (no physics mesh).
|
||||
Causes many errors. Doesn't stop after first error with box shape.
|
||||
Eventually crashes when deleting the object.
|
||||
|
||||
VEHICLES TODO LIST:
|
||||
=================================================
|
||||
Neb car jiggling left and right
|
||||
Happens on terrain and any other mesh object. Flat cubes are much smoother.
|
||||
Vehicles (Move smoothly)
|
||||
Add vehicle collisions so IsColliding is properly reported.
|
||||
Needed for banking, limitMotorUp, movementLimiting, ...
|
||||
Some vehicles should not be able to turn if no speed or off ground.
|
||||
For limitMotorUp, use raycast down to find if vehicle is in the air.
|
||||
Implement function efficiency for lineaar and angular motion.
|
||||
Should vehicle angular/linear movement friction happen after all the components
|
||||
or does it only apply to the basic movement?
|
||||
After getting off a vehicle, the root prim is phantom (can be walked through)
|
||||
Need to force a position update for the root prim after compound shape destruction
|
||||
Linkset explosion after three "rides" on Nebadon lite vehicle (LinksetConstraint)
|
||||
Implement referenceFrame for all the motion routines.
|
||||
Cannot edit/move a vehicle being ridden: it jumps back to the origional position.
|
||||
|
||||
BULLETSIM TODO LIST:
|
||||
=================================================
|
||||
Disable activity of passive linkset children.
|
||||
Since the linkset is a compound object, the old prims are left lying
|
||||
around and need to be phantomized so they don't collide, ...
|
||||
Scenes with hundred of thousands of static objects take a lot of physics CPU time.
|
||||
BSPrim.Force should set a continious force on the prim. The force should be
|
||||
applied each tick. Some limits?
|
||||
Single prim vehicles don't seem to properly vehiclize.
|
||||
Gun sending shooter flying.
|
||||
Collision margin (gap between physical objects lying on each other)
|
||||
Boundry checking (crashes related to crossing boundry)
|
||||
Add check for border edge position for avatars and objects.
|
||||
Verify the events are created for border crossings.
|
||||
Avatar rotation (check out changes to ScenePresence for physical rotation)
|
||||
Avatar running (what does phys engine need to do?)
|
||||
Small physical objects do not interact correctly
|
||||
Create chain of .5x.5x.1 torui and make all but top physical so to hang.
|
||||
The chain will fall apart and pairs will dance around on ground
|
||||
Chains of 1x1x.2 will stay connected but will dance.
|
||||
Chains above 2x2x.4 are move stable and get stablier as torui get larger.
|
||||
Add material type linkage and input all the material property definitions.
|
||||
Skeleton classes and table are in the sources but are not filled or used.
|
||||
Add PID motor for avatar movement (slow to stop, ...)
|
||||
setForce should set a constant force. Different than AddImpulse.
|
||||
Implement raycast.
|
||||
Implement ShapeCollection.Dispose()
|
||||
Implement water as a plain so raycasting and collisions can happen with same.
|
||||
|
||||
Find/remove avatar collision with ID=0.
|
||||
Test avatar walking up stairs. How does compare with SL.
|
||||
Radius of the capsule affects ability to climb edges.
|
||||
Tune terrain/object friction to be closer to SL.
|
||||
Debounce avatar contact so legs don't keep folding up when standing.
|
||||
Implement LSL physics controls. Like STATUS_ROTATE_X.
|
||||
Add border extensions to terrain to help region crossings and objects leaving region.
|
||||
|
||||
Speed up creation of large physical linksets
|
||||
For instance, sitting in Neb's car (130 prims) takes several seconds to become physical
|
||||
Performance test with lots of avatars. Can BulletSim support a thousand?
|
||||
Optimize collisions in C++: only send up to the object subscribed to collisions.
|
||||
Use collision subscription and remove the collsion(A,B) and collision(B,A)
|
||||
Check whether SimMotionState needs large if statement (see TODO).
|
||||
|
||||
Implement 'top colliders' info.
|
||||
Avatar jump
|
||||
Performance measurement and changes to make quicker.
|
||||
Implement detailed physics stats (GetStats()).
|
||||
|
||||
Eliminate collisions between objects in a linkset. (LinksetConstraint)
|
||||
Have UserPointer point to struct with localID and linksetID?
|
||||
Objects in original linkset still collide with each other?
|
||||
|
||||
Measure performance improvement from hulls
|
||||
Test not using ghost objects for volume detect implementation.
|
||||
Performance of closures and delegates for taint processing
|
||||
Are there faster ways?
|
||||
Is any slowdown introduced by the existing implementation significant?
|
||||
Is there are more efficient method of implementing pre and post step actions?
|
||||
See http://www.codeproject.com/Articles/29922/Weak-Events-in-C
|
||||
|
||||
Physics Arena central pyramid: why is one side permiable?
|
||||
|
||||
INTERNAL IMPROVEMENT/CLEANUP
|
||||
=================================================
|
||||
Remove unused fields from ShapeData (not used in API2)
|
||||
Breakout code for mesh/hull/compound/native into separate BSShape* classes
|
||||
Standardize access to building and reference code.
|
||||
The skeleton classes are in the sources but are not complete or linked in.
|
||||
Generalize Dynamics and PID with standardized motors.
|
||||
Generalize Linkset and vehicles into PropertyManagers
|
||||
Methods for Refresh, RemoveBodyDependencies, RestoreBodyDependencies
|
||||
Possibly generalized a 'pre step action' registration.
|
||||
Complete implemention of preStepActions
|
||||
Replace vehicle step call with prestep event.
|
||||
Is there a need for postStepActions? postStepTaints?
|
||||
Implement linkset by setting position of children when root updated. (LinksetManual)
|
||||
Linkset implementation using manual prim movement.
|
||||
LinkablePrim class? Would that simplify/centralize the linkset logic?
|
||||
BSScene.UpdateParameterSet() is broken. How to set params on objects?
|
||||
Remove HeightmapInfo from terrain specification.
|
||||
Since C++ code does not need terrain height, this structure et al are not needed.
|
||||
Add floating motor for BS_FLOATS_ON_WATER so prim and avatar will
|
||||
bob at the water level. BSPrim.PositionSanityCheck().
|
||||
|
||||
THREADING
|
||||
=================================================
|
||||
Do taint action immediately if not actually executing Bullet.
|
||||
Add lock around Bullet execution and just do taint actions if simulation is not happening.
|
||||
|
||||
DONE DONE DONE DONE
|
||||
=================================================
|
||||
Cleanup code in BSDynamics by using motors. (Resolution: started)
|
||||
Consider implementing terrain with a mesh rather than heightmap. (Resolution: done)
|
||||
Would have better and adjustable resolution.
|
||||
Build terrain mesh so heighmap is height of the center of the square meter.
|
||||
Resolution: NOT DONE: SL and ODE define meter square as being at one corner with one diagional.
|
||||
Terrain as mesh. (Resolution: done)
|
||||
How are static linksets seen by the physics engine?
|
||||
Resolution: they are not linked in physics. When moved, all the children are repositioned.
|
||||
Convert BSCharacter to use all API2 (Resolution: done)
|
||||
Avatar pushing difficult (too heavy?)
|
||||
Use asset service passed to BulletSim to get sculptie bodies, etc. (Resolution: done)
|
||||
Remove old code in DLL (all non-API2 stuff). (Resolution: done)
|
||||
Measurements of mega-physical prim performance (with graph) (Resolution: done, email)
|
||||
Debug Bullet internal stats output (why is timing all wrong?)
|
||||
Resolution: Bullet stats logging only works with a single instance of Bullet (one region).
|
||||
Implement meshes or just verify that they work. (Resolution: they do!)
|
||||
Do prim hash codes work for sculpties and meshes? (Resolution: yes)
|
||||
Linkset implementation using compound shapes. (Resolution: implemented LinksetCompound)
|
||||
Compound shapes will need the LocalID in the shapes and collision
|
||||
processing to get it from there.
|
||||
Light cycle falling over when driving (Resolution: implemented VerticalAttractor)
|
||||
Light cycle not banking (Resolution: It doesn't. Banking is roll adding yaw.)
|
||||
Package Bullet source mods for Bullet internal stats output
|
||||
(Resolution: move code into WorldData.h rather than relying on patches)
|
|
@ -36,6 +36,7 @@ namespace OpenSim.Region.Physics.Manager
|
|||
{
|
||||
IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod);
|
||||
IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical);
|
||||
IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool shouldCache);
|
||||
}
|
||||
|
||||
// Values for level of detail to be passed to the mesher.
|
||||
|
|
|
@ -64,10 +64,15 @@ namespace OpenSim.Region.Physics.Manager
|
|||
{
|
||||
public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod)
|
||||
{
|
||||
return CreateMesh(primName, primShape, size, lod, false);
|
||||
return CreateMesh(primName, primShape, size, lod, false, false);
|
||||
}
|
||||
|
||||
public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical)
|
||||
{
|
||||
return CreateMesh(primName, primShape, size, lod, false, false);
|
||||
}
|
||||
|
||||
public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool shouldCache)
|
||||
{
|
||||
// Remove the reference to the encoded JPEG2000 data so it can be GCed
|
||||
primShape.SculptData = OpenMetaverse.Utils.EmptyBytes;
|
||||
|
|
|
@ -321,7 +321,10 @@ namespace OpenSim.Region.Physics.Meshing
|
|||
|
||||
if (primShape.SculptData.Length <= 0)
|
||||
{
|
||||
m_log.ErrorFormat("[MESH]: asset data for {0} is zero length", primName);
|
||||
// XXX: At the moment we can not log here since ODEPrim, for instance, ends up triggering this
|
||||
// method twice - once before it has loaded sculpt data from the asset service and once afterwards.
|
||||
// The first time will always call with unloaded SculptData if this needs to be uploaded.
|
||||
// m_log.ErrorFormat("[MESH]: asset data for {0} is zero length", primName);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -699,11 +702,16 @@ namespace OpenSim.Region.Physics.Meshing
|
|||
|
||||
public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod)
|
||||
{
|
||||
return CreateMesh(primName, primShape, size, lod, false);
|
||||
return CreateMesh(primName, primShape, size, lod, false, true);
|
||||
}
|
||||
|
||||
public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical)
|
||||
{
|
||||
return CreateMesh(primName, primShape, size, lod, isPhysical, true);
|
||||
}
|
||||
|
||||
public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool shouldCache)
|
||||
{
|
||||
#if SPAM
|
||||
m_log.DebugFormat("[MESH]: Creating mesh for {0}", primName);
|
||||
#endif
|
||||
|
@ -713,9 +721,12 @@ namespace OpenSim.Region.Physics.Meshing
|
|||
|
||||
// If this mesh has been created already, return it instead of creating another copy
|
||||
// For large regions with 100k+ prims and hundreds of copies of each, this can save a GB or more of memory
|
||||
if (shouldCache)
|
||||
{
|
||||
key = primShape.GetMeshKey(size, lod);
|
||||
if (m_uniqueMeshes.TryGetValue(key, out mesh))
|
||||
return mesh;
|
||||
}
|
||||
|
||||
if (size.X < 0.01f) size.X = 0.01f;
|
||||
if (size.Y < 0.01f) size.Y = 0.01f;
|
||||
|
@ -738,8 +749,11 @@ namespace OpenSim.Region.Physics.Meshing
|
|||
// trim the vertex and triangle lists to free up memory
|
||||
mesh.TrimExcess();
|
||||
|
||||
if (shouldCache)
|
||||
{
|
||||
m_uniqueMeshes.Add(key, mesh);
|
||||
}
|
||||
}
|
||||
|
||||
return mesh;
|
||||
}
|
||||
|
|
|
@ -3361,6 +3361,11 @@ Console.WriteLine(" JointCreateFixed");
|
|||
_pbs.SculptData = new byte[asset.Data.Length];
|
||||
asset.Data.CopyTo(_pbs.SculptData, 0);
|
||||
// m_assetFailed = false;
|
||||
|
||||
// m_log.DebugFormat(
|
||||
// "[ODE PRIM]: Received mesh/sculpt data asset {0} with {1} bytes for {2} at {3} in {4}",
|
||||
// _pbs.SculptTexture, _pbs.SculptData.Length, Name, _position, _parent_scene.Name);
|
||||
|
||||
m_taintshape = true;
|
||||
_parent_scene.AddPhysicsActorTaint(this);
|
||||
}
|
||||
|
|
|
@ -114,6 +114,16 @@ namespace OpenSim.Region.ScriptEngine.Interfaces
|
|||
UUID AssetID { get; }
|
||||
Queue EventQueue { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Number of events queued for processing.
|
||||
/// </summary>
|
||||
long EventsQueued { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Number of events processed by this script instance.
|
||||
/// </summary>
|
||||
long EventsProcessed { get; }
|
||||
|
||||
void ClearQueue();
|
||||
int StartParam { get; set; }
|
||||
|
||||
|
|
|
@ -6856,6 +6856,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
|||
public void llCloseRemoteDataChannel(string channel)
|
||||
{
|
||||
m_host.AddScriptLPS(1);
|
||||
|
||||
IXmlRpcRouter xmlRpcRouter = m_ScriptEngine.World.RequestModuleInterface<IXmlRpcRouter>();
|
||||
if (xmlRpcRouter != null)
|
||||
{
|
||||
xmlRpcRouter.UnRegisterReceiver(channel, m_item.ItemID);
|
||||
}
|
||||
|
||||
IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>();
|
||||
xmlrpcMod.CloseXMLRPCChannel((UUID)channel);
|
||||
ScriptSleep(1000);
|
||||
|
|
|
@ -173,6 +173,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
|
|||
|
||||
public Queue EventQueue { get; private set; }
|
||||
|
||||
public long EventsQueued
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (EventQueue)
|
||||
return EventQueue.Count;
|
||||
}
|
||||
}
|
||||
|
||||
public long EventsProcessed { get; private set; }
|
||||
|
||||
public int StartParam { get; set; }
|
||||
|
||||
public TaskInventoryItem ScriptTask { get; private set; }
|
||||
|
@ -774,6 +785,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
|
|||
ChatTypeEnum.DebugChannel, 2147483647,
|
||||
part.AbsolutePosition,
|
||||
part.Name, part.UUID, false);
|
||||
|
||||
|
||||
m_log.DebugFormat(
|
||||
"[SCRIPT INSTANCE]: Runtime error in script {0}, part {1} {2} at {3} in {4}, displayed error {5}, actual exception {6}",
|
||||
ScriptName,
|
||||
PrimName,
|
||||
part.UUID,
|
||||
part.AbsolutePosition,
|
||||
part.ParentGroup.Scene.Name,
|
||||
text.Replace("\n", "\\n"),
|
||||
e.InnerException);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
|
@ -808,6 +830,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
|
|||
// script engine to run the next event.
|
||||
lock (EventQueue)
|
||||
{
|
||||
EventsProcessed++;
|
||||
|
||||
if (EventQueue.Count > 0 && Running && !ShuttingDown)
|
||||
{
|
||||
m_CurrentWorkItem = Engine.QueueEventHandler(this);
|
||||
|
@ -1013,7 +1037,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
|
|||
"({0}): {1}", scriptLine - 1,
|
||||
e.InnerException.Message);
|
||||
|
||||
System.Console.WriteLine(e.ToString()+"\n");
|
||||
return message;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,8 +57,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
|
|||
protected XEngine.XEngine m_engine;
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
public override void SetUp()
|
||||
{
|
||||
base.SetUp();
|
||||
|
||||
IConfigSource initConfigSource = new IniConfigSource();
|
||||
IConfig config = initConfigSource.AddConfig("XEngine");
|
||||
config.Set("Enabled", "true");
|
||||
|
|
|
@ -62,8 +62,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
|
|||
protected XEngine.XEngine m_engine;
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
public override void SetUp()
|
||||
{
|
||||
base.SetUp();
|
||||
|
||||
IConfigSource initConfigSource = new IniConfigSource();
|
||||
IConfig config = initConfigSource.AddConfig("XEngine");
|
||||
config.Set("Enabled", "true");
|
||||
|
|
|
@ -51,8 +51,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
|
|||
private LSL_Api m_lslApi;
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
public override void SetUp()
|
||||
{
|
||||
base.SetUp();
|
||||
|
||||
IConfigSource initConfigSource = new IniConfigSource();
|
||||
IConfig config = initConfigSource.AddConfig("XEngine");
|
||||
config.Set("Enabled", "true");
|
||||
|
|
|
@ -57,8 +57,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
|
|||
protected XEngine.XEngine m_engine;
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
public override void SetUp()
|
||||
{
|
||||
base.SetUp();
|
||||
|
||||
IConfigSource initConfigSource = new IniConfigSource();
|
||||
IConfig config = initConfigSource.AddConfig("XEngine");
|
||||
config.Set("Enabled", "true");
|
||||
|
|
|
@ -127,12 +127,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
|
|||
OSSL_Api osslApi = new OSSL_Api();
|
||||
osslApi.Initialize(m_engine, so.RootPart, null);
|
||||
|
||||
string npcRaw;
|
||||
bool gotExpectedException = false;
|
||||
try
|
||||
{
|
||||
npcRaw
|
||||
= osslApi.osNpcCreate("Jane", "Doe", new LSL_Types.Vector3(128, 128, 128), "not existing notecard name");
|
||||
osslApi.osNpcCreate("Jane", "Doe", new LSL_Types.Vector3(128, 128, 128), "not existing notecard name");
|
||||
}
|
||||
catch (ScriptException)
|
||||
{
|
||||
|
|
|
@ -30,6 +30,7 @@ using System.Collections;
|
|||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Security;
|
||||
using System.Security.Policy;
|
||||
|
@ -377,8 +378,20 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
|||
/// </summary>
|
||||
/// <param name="cmdparams"></param>
|
||||
/// <param name="instance"></param>
|
||||
/// <returns>true if we're okay to proceed, false if not.</returns>
|
||||
/// <param name="comparer">Basis on which to sort output. Can be null if no sort needs to take place</param>
|
||||
private void HandleScriptsAction(string[] cmdparams, Action<IScriptInstance> action)
|
||||
{
|
||||
HandleScriptsAction<object>(cmdparams, action, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse the raw item id into a script instance from the command params if it's present.
|
||||
/// </summary>
|
||||
/// <param name="cmdparams"></param>
|
||||
/// <param name="instance"></param>
|
||||
/// <param name="keySelector">Basis on which to sort output. Can be null if no sort needs to take place</param>
|
||||
private void HandleScriptsAction<TKey>(
|
||||
string[] cmdparams, Action<IScriptInstance> action, Func<IScriptInstance, TKey> keySelector)
|
||||
{
|
||||
if (!(MainConsole.Instance.ConsoleScene == null || MainConsole.Instance.ConsoleScene == m_Scene))
|
||||
return;
|
||||
|
@ -390,7 +403,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
|||
|
||||
if (cmdparams.Length == 2)
|
||||
{
|
||||
foreach (IScriptInstance instance in m_Scripts.Values)
|
||||
IEnumerable<IScriptInstance> scripts = m_Scripts.Values;
|
||||
|
||||
if (keySelector != null)
|
||||
scripts = scripts.OrderBy<IScriptInstance, TKey>(keySelector);
|
||||
|
||||
foreach (IScriptInstance instance in scripts)
|
||||
action(instance);
|
||||
|
||||
return;
|
||||
|
@ -437,9 +455,20 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
|||
StringBuilder sb = new StringBuilder();
|
||||
sb.AppendFormat("Status of XEngine instance for {0}\n", m_Scene.RegionInfo.RegionName);
|
||||
|
||||
lock (m_Scripts)
|
||||
sb.AppendFormat("Scripts loaded : {0}\n", m_Scripts.Count);
|
||||
long scriptsLoaded, eventsQueued = 0, eventsProcessed = 0;
|
||||
|
||||
lock (m_Scripts)
|
||||
{
|
||||
scriptsLoaded = m_Scripts.Count;
|
||||
|
||||
foreach (IScriptInstance si in m_Scripts.Values)
|
||||
{
|
||||
eventsQueued += si.EventsQueued;
|
||||
eventsProcessed += si.EventsProcessed;
|
||||
}
|
||||
}
|
||||
|
||||
sb.AppendFormat("Scripts loaded : {0}\n", scriptsLoaded);
|
||||
sb.AppendFormat("Unique scripts : {0}\n", m_uniqueScripts.Count);
|
||||
sb.AppendFormat("Scripts waiting for load : {0}\n", m_CompileQueue.Count);
|
||||
sb.AppendFormat("Max threads : {0}\n", m_ThreadPool.MaxThreads);
|
||||
|
@ -448,6 +477,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
|||
sb.AppendFormat("In use threads : {0}\n", m_ThreadPool.InUseThreads);
|
||||
sb.AppendFormat("Work items waiting : {0}\n", m_ThreadPool.WaitingCallbacks);
|
||||
// sb.AppendFormat("Assemblies loaded : {0}\n", m_Assemblies.Count);
|
||||
sb.AppendFormat("Events queued : {0}\n", eventsQueued);
|
||||
sb.AppendFormat("Events processed : {0}\n", eventsProcessed);
|
||||
|
||||
SensorRepeat sr = AsyncCommandManager.GetSensorRepeatPlugin(this);
|
||||
sb.AppendFormat("Sensors : {0}\n", sr != null ? sr.SensorsCount : 0);
|
||||
|
@ -478,7 +509,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
|||
}
|
||||
}
|
||||
|
||||
HandleScriptsAction(cmdparams, HandleShowScript);
|
||||
HandleScriptsAction<long>(cmdparams, HandleShowScript, si => si.EventsProcessed);
|
||||
}
|
||||
|
||||
private void HandleShowScript(IScriptInstance instance)
|
||||
|
@ -508,10 +539,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
|||
|
||||
sb.AppendFormat("Script name : {0}\n", instance.ScriptName);
|
||||
sb.AppendFormat("Status : {0}\n", status);
|
||||
|
||||
lock (eq)
|
||||
sb.AppendFormat("Queued events : {0}\n", eq.Count);
|
||||
|
||||
sb.AppendFormat("Queued events : {0}\n", instance.EventsQueued);
|
||||
sb.AppendFormat("Processed events : {0}\n", instance.EventsProcessed);
|
||||
sb.AppendFormat("Item UUID : {0}\n", instance.ItemID);
|
||||
sb.AppendFormat("Containing part name: {0}\n", instance.PrimName);
|
||||
sb.AppendFormat("Containing part UUID: {0}\n", instance.ObjectID);
|
||||
|
@ -1018,8 +1047,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
|||
|
||||
string assembly = "";
|
||||
|
||||
CultureInfo USCulture = new CultureInfo("en-US");
|
||||
Thread.CurrentThread.CurrentCulture = USCulture;
|
||||
Culture.SetCurrentCulture();
|
||||
|
||||
Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>> linemap;
|
||||
|
||||
|
@ -1415,8 +1443,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
|||
/// <returns></returns>
|
||||
private object ProcessEventHandler(object parms)
|
||||
{
|
||||
CultureInfo USCulture = new CultureInfo("en-US");
|
||||
Thread.CurrentThread.CurrentCulture = USCulture;
|
||||
Culture.SetCurrentCulture();
|
||||
|
||||
IScriptInstance instance = (ScriptInstance) parms;
|
||||
|
||||
|
|
|
@ -314,7 +314,7 @@ namespace OpenSim.Services.Connectors.Simulation
|
|||
|
||||
try
|
||||
{
|
||||
OSDMap result = WebUtil.ServiceOSDRequest(uri, request, "QUERYACCESS", 10000, false);
|
||||
OSDMap result = WebUtil.ServiceOSDRequest(uri, request, "QUERYACCESS", 30000, false);
|
||||
bool success = result["success"].AsBoolean();
|
||||
if (result.ContainsKey("_Result"))
|
||||
{
|
||||
|
|
|
@ -61,13 +61,13 @@ namespace OpenSim.Services.HypergridService
|
|||
protected static IGridService m_GridService;
|
||||
protected static IPresenceService m_PresenceService;
|
||||
protected static IUserAgentService m_UserAgentService;
|
||||
protected static IOfflineIMService m_OfflineIMService;
|
||||
|
||||
protected static IInstantMessageSimConnector m_IMSimConnector;
|
||||
|
||||
protected static Dictionary<UUID, object> m_UserLocationMap = new Dictionary<UUID, object>();
|
||||
private static ExpiringCache<UUID, GridRegion> m_RegionCache;
|
||||
|
||||
private static string m_RestURL;
|
||||
private static bool m_ForwardOfflineGroupMessages;
|
||||
private static bool m_InGatekeeper;
|
||||
|
||||
|
@ -111,9 +111,14 @@ namespace OpenSim.Services.HypergridService
|
|||
return;
|
||||
}
|
||||
|
||||
m_RestURL = cnf.GetString("OfflineMessageURL", string.Empty);
|
||||
m_ForwardOfflineGroupMessages = cnf.GetBoolean("ForwardOfflineGroupMessages", false);
|
||||
|
||||
if (m_InGatekeeper)
|
||||
{
|
||||
string offlineIMService = cnf.GetString("OfflineIMService", string.Empty);
|
||||
if (offlineIMService != string.Empty)
|
||||
m_OfflineIMService = ServerUtils.LoadPlugin<IOfflineIMService>(offlineIMService, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -329,18 +334,28 @@ namespace OpenSim.Services.HypergridService
|
|||
|
||||
private bool UndeliveredMessage(GridInstantMessage im)
|
||||
{
|
||||
if (m_RestURL != string.Empty && (im.offline != 0)
|
||||
&& (!im.fromGroup || (im.fromGroup && m_ForwardOfflineGroupMessages)))
|
||||
{
|
||||
// m_log.DebugFormat("[HG IM SERVICE]: Message saved");
|
||||
if (m_OfflineIMService == null)
|
||||
return false;
|
||||
|
||||
return SynchronousRestObjectRequester.MakeRequest<GridInstantMessage, bool>(
|
||||
"POST", m_RestURL + "/SaveMessage/", im);
|
||||
}
|
||||
else
|
||||
if (im.dialog != (byte)InstantMessageDialog.MessageFromObject &&
|
||||
im.dialog != (byte)InstantMessageDialog.MessageFromAgent &&
|
||||
im.dialog != (byte)InstantMessageDialog.GroupNotice &&
|
||||
im.dialog != (byte)InstantMessageDialog.GroupInvitation &&
|
||||
im.dialog != (byte)InstantMessageDialog.InventoryOffered)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_ForwardOfflineGroupMessages)
|
||||
{
|
||||
if (im.dialog == (byte)InstantMessageDialog.GroupNotice ||
|
||||
im.dialog == (byte)InstantMessageDialog.GroupInvitation)
|
||||
return false;
|
||||
}
|
||||
|
||||
// m_log.DebugFormat("[HG IM SERVICE]: Message saved");
|
||||
string reason = string.Empty;
|
||||
return m_OfflineIMService.StoreMessage(im, out reason);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
* Copyright (c) Contributors, http://opensimulator.org/
|
||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the OpenSimulator Project nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using OpenSim.Framework;
|
||||
using OpenMetaverse;
|
||||
|
||||
namespace OpenSim.Services.Interfaces
|
||||
{
|
||||
public interface IOfflineIMService
|
||||
{
|
||||
List<GridInstantMessage> GetMessages(UUID principalID);
|
||||
bool StoreMessage(GridInstantMessage im, out string reason);
|
||||
}
|
||||
|
||||
public class OfflineIMDataUtils
|
||||
{
|
||||
public static GridInstantMessage GridInstantMessage(Dictionary<string, object> dict)
|
||||
{
|
||||
GridInstantMessage im = new GridInstantMessage();
|
||||
|
||||
if (dict.ContainsKey("BinaryBucket") && dict["BinaryBucket"] != null)
|
||||
im.binaryBucket = OpenMetaverse.Utils.HexStringToBytes(dict["BinaryBucket"].ToString(), true);
|
||||
|
||||
if (dict.ContainsKey("Dialog") && dict["Dialog"] != null)
|
||||
im.dialog = byte.Parse(dict["Dialog"].ToString());
|
||||
|
||||
if (dict.ContainsKey("FromAgentID") && dict["FromAgentID"] != null)
|
||||
im.fromAgentID = new Guid(dict["FromAgentID"].ToString());
|
||||
|
||||
if (dict.ContainsKey("FromAgentName") && dict["FromAgentName"] != null)
|
||||
im.fromAgentName = dict["FromAgentName"].ToString();
|
||||
else
|
||||
im.fromAgentName = string.Empty;
|
||||
|
||||
if (dict.ContainsKey("FromGroup") && dict["FromGroup"] != null)
|
||||
im.fromGroup = bool.Parse(dict["FromGroup"].ToString());
|
||||
|
||||
if (dict.ContainsKey("SessionID") && dict["SessionID"] != null)
|
||||
im.imSessionID = new Guid(dict["SessionID"].ToString());
|
||||
|
||||
if (dict.ContainsKey("Message") && dict["Message"] != null)
|
||||
im.message = dict["Message"].ToString();
|
||||
else
|
||||
im.message = string.Empty;
|
||||
|
||||
if (dict.ContainsKey("Offline") && dict["Offline"] != null)
|
||||
im.offline = byte.Parse(dict["Offline"].ToString());
|
||||
|
||||
if (dict.ContainsKey("EstateID") && dict["EstateID"] != null)
|
||||
im.ParentEstateID = UInt32.Parse(dict["EstateID"].ToString());
|
||||
|
||||
if (dict.ContainsKey("Position") && dict["Position"] != null)
|
||||
im.Position = Vector3.Parse(dict["Position"].ToString());
|
||||
|
||||
if (dict.ContainsKey("RegionID") && dict["RegionID"] != null)
|
||||
im.RegionID = new Guid(dict["RegionID"].ToString());
|
||||
|
||||
if (dict.ContainsKey("Timestamp") && dict["Timestamp"] != null)
|
||||
im.timestamp = UInt32.Parse(dict["Timestamp"].ToString());
|
||||
|
||||
if (dict.ContainsKey("ToAgentID") && dict["ToAgentID"] != null)
|
||||
im.toAgentID = new Guid(dict["ToAgentID"].ToString());
|
||||
|
||||
return im;
|
||||
}
|
||||
|
||||
public static Dictionary<string, object> GridInstantMessage(GridInstantMessage im)
|
||||
{
|
||||
Dictionary<string, object> dict = new Dictionary<string, object>();
|
||||
|
||||
dict["BinaryBucket"] = OpenMetaverse.Utils.BytesToHexString(im.binaryBucket, im.binaryBucket.Length, null);
|
||||
dict["Dialog"] = im.dialog.ToString();
|
||||
dict["FromAgentID"] = im.fromAgentID.ToString();
|
||||
dict["FromAgentName"] = im.fromAgentName == null ? string.Empty : im.fromAgentName;
|
||||
dict["FromGroup"] = im.fromGroup.ToString();
|
||||
dict["SessionID"] = im.imSessionID.ToString();
|
||||
dict["Message"] = im.message == null ? string.Empty : im.message;
|
||||
dict["Offline"] = im.offline.ToString();
|
||||
dict["EstateID"] = im.ParentEstateID.ToString();
|
||||
dict["Position"] = im.Position.ToString();
|
||||
dict["RegionID"] = im.RegionID.ToString();
|
||||
dict["Timestamp"] = im.timestamp.ToString();
|
||||
dict["ToAgentID"] = im.toAgentID.ToString();
|
||||
|
||||
return dict;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
<configuration>
|
||||
<dllmap os="osx" dll="openjpeg-dotnet.dll" target="lib64/libopenjpeg-dotnet-2.1.5.0-dotnet-1.dylib" />
|
||||
<dllmap os="osx" dll="openjpeg-dotnet.dll" target="lib64/libopenjpeg-dotnet.dylib" />
|
||||
<dllmap os="!windows,osx" cpu="x86-64,ia64" dll="openjpeg-dotnet-x86_64.dll" target="lib64/libopenjpeg-dotnet-x86_64" />
|
||||
<dllmap os="!windows,osx" cpu="x86" dll="openjpeg-dotnet.dll" target="lib32/libopenjpeg-dotnet" />
|
||||
</configuration>
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -2052,7 +2052,7 @@
|
|||
<Reference name="OpenMetaverseTypes" path="../../../bin/"/>
|
||||
<Reference name="OpenMetaverse" path="../../../bin/"/>
|
||||
<Reference name="Nini" path="../../../bin/"/>
|
||||
<Reference name="Mono.Addins"/>
|
||||
<Reference name="Mono.Addins" path="../../../bin/"/>
|
||||
<Reference name="log4net" path="../../../bin/"/>
|
||||
<Files>
|
||||
<Match pattern="*.cs" recurse="true"/>
|
||||
|
@ -2460,7 +2460,7 @@
|
|||
<Reference name="OpenSim.Framework.Servers.HttpServer"/>
|
||||
<Reference name="OpenSim.Region.Physics.Manager"/>
|
||||
<Reference name="Mono.Data.SqliteClient" path="../../../bin/"/>
|
||||
<Reference name="Mono.Addins"/>
|
||||
<Reference name="Mono.Addins" path="../../../bin/"/>
|
||||
|
||||
<!-- For scripting in funny languages by default -->
|
||||
<Reference name="XMLRPC" path="../../../bin/"/>
|
||||
|
|
Loading…
Reference in New Issue